<commit_before>/*globals window*/
(function (root, factory) {
  if (typeof module === 'object' && module.exports) {
    var Ractive = require("ractive");
    Ractive.events = require("ractive-events-keys");

    var axios = require("axios");
    var url = require("url");
    var _ = require("underscore");
    module.exports = factory(Ractive, axios, url, _);
  } else {
    root.Search = factory(root.Ractive, root.axios, root.url, root._);
  }
}(this, function (Ractive, axios, url, _) {
  "use strict";
  Ractive.DEBUG = false;

  var Search = {
    init: function() {

      if (window && !window.Promise) {
        window.Promise = Ractive.Promise; // axios needs a Promise polyfill, so we use the one provided by ractive.
      }

      var config;
      return axios.get("/config").then(function (response) {
        config = response.data;
      }).then(function () {
        return axios.get("/search_template.html").then(function (response) {
          return response.data;
        });
      }).then(function (data) {
        var searchRactive = new Ractive({
          el: "#search-app",
          template: data,
          data: {
            hits: {
              total: 0,
              hits: []
            },
            workUrl: function (work) {
                return '/work/' + url.parse(work.uri).path.split('/').pop();
            },
            personUrl: function (person) {
                return '/person/' + url.parse(person.uri).path.split('/').pop();
            },
            inPreferredLanguage: function(literals) {
              var noMatch = "";
              for (var lang in literals) {
                switch (lang) {
                  case "nb":
                    // fallthrough to "nn"
                  case "nn":
                    return literals[lang];
                  default:
                    noMatch = literals[lang];
                }
              }
              // no preferred language match, return arbritary (last in iteration)
              return noMatch;
            },
          }
        });

        searchRactive.on({
          search: function () {
            var term = searchRactive.get("search_term");
            axios.get("http://" + config.host + ":" + config.port + "/search/work/_search?q=" + term)
                .then(function (response) {
                  searchRactive.set("currentSearchTerm", term);
                  searchRactive.set("hits", response.data.hits);
                });
          }
        });
        return searchRactive;
      }).catch(function (error) {
        console.log(error);
      });
    }
  }
  return Search;
}));<commit_msg>patron-client: revert & fix inPreferredLanguage for search results<commit_after>/*globals window*/
(function (root, factory) {
  if (typeof module === 'object' && module.exports) {
    var Ractive = require("ractive");
    Ractive.events = require("ractive-events-keys");

    var axios = require("axios");
    var url = require("url");
    var _ = require("underscore");
    module.exports = factory(Ractive, axios, url, _);
  } else {
    root.Search = factory(root.Ractive, root.axios, root.url, root._);
  }
}(this, function (Ractive, axios, url, _) {
  "use strict";
  Ractive.DEBUG = false;

  var Search = {
    init: function() {

      if (window && !window.Promise) {
        window.Promise = Ractive.Promise; // axios needs a Promise polyfill, so we use the one provided by ractive.
      }

      var config;
      return axios.get("/config").then(function (response) {
        config = response.data;
      }).then(function () {
        return axios.get("/search_template.html").then(function (response) {
          return response.data;
        });
      }).then(function (data) {
        var searchRactive = new Ractive({
          el: "#search-app",
          template: data,
          data: {
            hits: {
              total: 0,
              hits: []
            },
            workUrl: function (work) {
                return '/work/' + url.parse(work.uri).path.split('/').pop();
            },
            personUrl: function (person) {
                return '/person/' + url.parse(person.uri).path.split('/').pop();
            },
            inPreferredLanguage: function(text) {
              var preferredTexts = _.compact([
                _.find(text, function (value, lang) {
                  return lang === "nb";
                }), _.find(text, function (value, lang) {
                  return lang === "nn";
                }), _.find(text, function (value, lang) {
                  return lang === "default";
                }), _.find(text, function (value) {
                  return true;
                })]);
              return _.first(preferredTexts);
            }
          }
        });

        searchRactive.on({
          search: function () {
            var term = searchRactive.get("search_term");
            axios.get("http://" + config.host + ":" + config.port + "/search/work/_search?q=" + term)
                .then(function (response) {
                  searchRactive.set("currentSearchTerm", term);
                  searchRactive.set("hits", response.data.hits);
                });
          }
        });
        return searchRactive;
      }).catch(function (error) {
        console.log(error);
      });
    }
  }
  return Search;
}));<|endoftext|>


<commit_before>// ***********************************************//
//                 models and stores
// ***********************************************//
require('akvo-flow/core');
require('akvo-flow/models/store_def');

FLOW.BaseModel = DS.Model.extend({
  keyId: DS.attr('number')
});

FLOW.SurveyGroup = FLOW.BaseModel.extend({
    didDelete: function() {FLOW.surveyGroupControl.populate();},
    didUpdate: function() {FLOW.surveyGroupControl.populate();},
    didCreate: function() {FLOW.surveyGroupControl.populate();},

	description: DS.attr('string',{defaultValue: ''}),
	name: DS.attr('string',{defaultValue: ''}),
	createdDateTime: DS.attr('string',{defaultValue: ''}),
	lastUpdateDateTime: DS.attr('string',{defaultValue: ''}),
	// the code field is used as name
	code: DS.attr('string',{defaultValue: ''})
});

FLOW.Survey = FLOW.BaseModel.extend({
	didDelete: function() {FLOW.surveyControl.populate();},
    didUpdate: function() {FLOW.surveyControl.populate();},
    didCreate: function() {FLOW.surveyControl.populate();},

	defaultLanguageCode: DS.attr('string'),
	status: DS.attr('string'),
	code: DS.attr('string'),
	requireApproval: DS.attr('string'),
	version: DS.attr('string'),
	description: DS.attr('string'),
	name: DS.attr('string'),
	pointType: DS.attr('string'),
	surveyGroupId: DS.attr('number'),
	createdDateTime:DS.attr('number'),
	lastUpdateDateTime:DS.attr('number')
});

FLOW.QuestionGroup = FLOW.BaseModel.extend({
	didDelete: function() {if (FLOW.questionGroupControl.get('allRecordsSaved')) FLOW.questionGroupControl.populate();},
    didUpdate: function() {if (FLOW.questionGroupControl.get('allRecordsSaved')) FLOW.questionGroupControl.populate();},
    didCreate: function() {if (FLOW.questionGroupControl.get('allRecordsSaved')) FLOW.questionGroupControl.populate();},

	order: DS.attr('number'),
	description: DS.attr('string'),
	name: DS.attr('string'),
	path: DS.attr('string'),
	code: DS.attr('string'),
	surveyId: DS.attr('number')
});

FLOW.Question = FLOW.BaseModel.extend({
	allowDecimal: DS.attr('boolean', {defaultValue: 0}),
	allowMultipleFlag: DS.attr('boolean', {defaultValue: 0}),
	allowOtherFlag: DS.attr('boolean', {defaultValue: 0}),
	allowSign: DS.attr('boolean', {defaultValue: 0}),
	collabseable: DS.attr('boolean', {defaultValue: 0}),
	displayName: DS.attr('string'),
	immutable: DS.attr('boolean', {defaultValue: 0}),
	isName: DS.attr('boolean', {defaultValue: 0}),
	mandatoryFlag: DS.attr('boolean', {defaultValue: 0}),
	maxVal: DS.attr('number'),
	minVal: DS.attr('number'),
	optionContainerDto: DS.attr('string'),
	order: DS.attr('number'),
	path: DS.attr('string'),
	questionDependency: DS.attr('string'),
	questionGroupId: DS.attr('number'),
	questionTypeString: DS.attr('string',{defaultValue:'freeText'}),
	surveyId: DS.attr('number'),
	text: DS.attr('string'),
	tip: DS.attr('string'),
	type: DS.attr('string')
});

FLOW.QuestionOption = FLOW.BaseModel.extend({
	questionId: DS.attr('number'),
	text: DS.attr('string')
});

FLOW.DeviceGroup = FLOW.BaseModel.extend({
	displayName: DS.attr('string',{defaultValue: ''}),
	code: DS.attr('string',{defaultValue: ''})
});

FLOW.Device = FLOW.BaseModel.extend({
	esn: DS.attr('string',{defaultValue: ''}),
	phoneNumber: DS.attr('string',{defaultValue: ''}),
	deviceIdentifier: DS.attr('string',{defaultValue: ''}),
	lastKnownLat: DS.attr('number', {defaultValue: 0}),
	lastKnownLon:DS.attr('number', {defaultValue: 0}),
	lastKnownAccuracy: DS.attr('number',{defaultValue:0}),
	lastPositionDate: DS.attr('number', {defaultValue: ''}),
	deviceGroup: DS.attr('string',{defaultValue: ''}),
	isSelected: false,
	deviceGroupName:null
});

FLOW.SurveyAssignment = FLOW.BaseModel.extend({
	name: DS.attr('string'),
	startDate: DS.attr('date'),
	endDate: DS.attr('date'),
	devices: DS.hasMany(FLOW.Device),
	surveys: DS.hasMany(FLOW.Survey)
});

FLOW.SurveyedLocale = DS.Model.extend({
  description:  DS.attr('string', {defaultValue: ''}),
  keyId:        DS.attr('number'),
  latitude:     DS.attr('number'),
  longitude:    DS.attr('number'),
  primaryKey:   'keyId',
  typeMark:     DS.attr('string', {defaultValue: 'WATER_POINT'})
});

// Explicitly avoid to use belongTo and hasMany as
// Ember-Data lacks of partial loading
// https://github.com/emberjs/data/issues/51
FLOW.PlacemarkDetail = FLOW.BaseModel.extend({
  questionText: DS.attr('string'),
  metricName: DS.attr('string'),
  stringValue: DS.attr('string')
});

FLOW.Placemark = FLOW.BaseModel.extend({
  latitude: DS.attr('number'),
  longitude: DS.attr('number'),
  collectionDate: DS.attr('date'),
  markType: DS.attr('string', {defaultValue: 'WATER_POINT'})
});<commit_msg>delete displayName field in DeviceGroup<commit_after>// ***********************************************//
//                 models and stores
// ***********************************************//
require('akvo-flow/core');
require('akvo-flow/models/store_def');

FLOW.BaseModel = DS.Model.extend({
  keyId: DS.attr('number')
});

FLOW.SurveyGroup = FLOW.BaseModel.extend({
    didDelete: function() {FLOW.surveyGroupControl.populate();},
    didUpdate: function() {FLOW.surveyGroupControl.populate();},
    didCreate: function() {FLOW.surveyGroupControl.populate();},

	description: DS.attr('string',{defaultValue: ''}),
	name: DS.attr('string',{defaultValue: ''}),
	createdDateTime: DS.attr('string',{defaultValue: ''}),
	lastUpdateDateTime: DS.attr('string',{defaultValue: ''}),
	// the code field is used as name
	code: DS.attr('string',{defaultValue: ''})
});

FLOW.Survey = FLOW.BaseModel.extend({
	didDelete: function() {FLOW.surveyControl.populate();},
    didUpdate: function() {FLOW.surveyControl.populate();},
    didCreate: function() {FLOW.surveyControl.populate();},

	defaultLanguageCode: DS.attr('string'),
	status: DS.attr('string'),
	code: DS.attr('string'),
	requireApproval: DS.attr('string'),
	version: DS.attr('string'),
	description: DS.attr('string'),
	name: DS.attr('string'),
	pointType: DS.attr('string'),
	surveyGroupId: DS.attr('number'),
	createdDateTime:DS.attr('number'),
	lastUpdateDateTime:DS.attr('number')
});

FLOW.QuestionGroup = FLOW.BaseModel.extend({
	didDelete: function() {if (FLOW.questionGroupControl.get('allRecordsSaved')) FLOW.questionGroupControl.populate();},
    didUpdate: function() {if (FLOW.questionGroupControl.get('allRecordsSaved')) FLOW.questionGroupControl.populate();},
    didCreate: function() {if (FLOW.questionGroupControl.get('allRecordsSaved')) FLOW.questionGroupControl.populate();},

	order: DS.attr('number'),
	description: DS.attr('string'),
	name: DS.attr('string'),
	path: DS.attr('string'),
	code: DS.attr('string'),
	surveyId: DS.attr('number')
});

FLOW.Question = FLOW.BaseModel.extend({
	allowDecimal: DS.attr('boolean', {defaultValue: 0}),
	allowMultipleFlag: DS.attr('boolean', {defaultValue: 0}),
	allowOtherFlag: DS.attr('boolean', {defaultValue: 0}),
	allowSign: DS.attr('boolean', {defaultValue: 0}),
	collabseable: DS.attr('boolean', {defaultValue: 0}),
	displayName: DS.attr('string'),
	immutable: DS.attr('boolean', {defaultValue: 0}),
	isName: DS.attr('boolean', {defaultValue: 0}),
	mandatoryFlag: DS.attr('boolean', {defaultValue: 0}),
	maxVal: DS.attr('number'),
	minVal: DS.attr('number'),
	optionContainerDto: DS.attr('string'),
	order: DS.attr('number'),
	path: DS.attr('string'),
	questionDependency: DS.attr('string'),
	questionGroupId: DS.attr('number'),
	questionTypeString: DS.attr('string',{defaultValue:'freeText'}),
	surveyId: DS.attr('number'),
	text: DS.attr('string'),
	tip: DS.attr('string'),
	type: DS.attr('string')
});

FLOW.QuestionOption = FLOW.BaseModel.extend({
	questionId: DS.attr('number'),
	text: DS.attr('string')
});

FLOW.DeviceGroup = FLOW.BaseModel.extend({
	code: DS.attr('string',{defaultValue: ''})
});

FLOW.Device = FLOW.BaseModel.extend({
	esn: DS.attr('string',{defaultValue: ''}),
	phoneNumber: DS.attr('string',{defaultValue: ''}),
	deviceIdentifier: DS.attr('string',{defaultValue: ''}),
	lastKnownLat: DS.attr('number', {defaultValue: 0}),
	lastKnownLon:DS.attr('number', {defaultValue: 0}),
	lastKnownAccuracy: DS.attr('number',{defaultValue:0}),
	lastPositionDate: DS.attr('number', {defaultValue: ''}),
	deviceGroup: DS.attr('string',{defaultValue: ''}),
	isSelected: false,
	deviceGroupName:null
});

FLOW.SurveyAssignment = FLOW.BaseModel.extend({
	name: DS.attr('string'),
	startDate: DS.attr('date'),
	endDate: DS.attr('date'),
	devices: DS.hasMany(FLOW.Device),
	surveys: DS.hasMany(FLOW.Survey)
});

FLOW.SurveyedLocale = DS.Model.extend({
  description:  DS.attr('string', {defaultValue: ''}),
  keyId:        DS.attr('number'),
  latitude:     DS.attr('number'),
  longitude:    DS.attr('number'),
  primaryKey:   'keyId',
  typeMark:     DS.attr('string', {defaultValue: 'WATER_POINT'})
});

// Explicitly avoid to use belongTo and hasMany as
// Ember-Data lacks of partial loading
// https://github.com/emberjs/data/issues/51
FLOW.PlacemarkDetail = FLOW.BaseModel.extend({
  questionText: DS.attr('string'),
  metricName: DS.attr('string'),
  stringValue: DS.attr('string')
});

FLOW.Placemark = FLOW.BaseModel.extend({
  latitude: DS.attr('number'),
  longitude: DS.attr('number'),
  collectionDate: DS.attr('date'),
  markType: DS.attr('string', {defaultValue: 'WATER_POINT'})
});<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016-2017 Jan Hoffmann
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

var reader = require('./reader');
var time = require('./time');

var DATA_FORMAT_VERSION = 6;

var cbError, cbMenu, cbFastSeller, cbReset;

var menuReady = false;
var fastSellersReady = false;

var data = [];

var location = 2;

function init(callbackError, callbackMenu, callbackFastSeller, callbackReset) {
    cbError = callbackError;
    cbMenu = callbackMenu;
    cbFastSeller = callbackFastSeller
    cbReset = callbackReset;

    load();

    var day = new time.Day();
    if ((data.length > 0 && day.getUTCTimestamp() == data[0].date) || !day.isWeekday()) {
        menuReady = true;
        cbMenu();
    }

    if (data.length > 0) {
        fastSellersReady = true;
        cbFastSeller();
    }

    reader.updateMenuData(data, location, readerCallback);
}

function readerCallback(day, success, data) {
    if (success) {
        setData(data);

        var today = new time.Day();
        if (today.getUTCTimestamp() == day.getUTCTimestamp()) {
            menuReady = true;
            cbMenu();
        }

        fastSellersReady = true;
        cbFastSeller();
    } else {
        if (!menuReady) {
            cbError();
        }
    }
}

function currentMenu() {
    if (!menuReady) {
        return null;
    }
    if (data.length > 0) {
        var day = new time.Day();
        var timestamp = day.getUTCTimestamp();
        if (timestamp == data[0].date) {
            return { 'menu': data[0].menu, 'message': data[0].message };
        }
    }
    return { 'menu': [], 'message': '' };
}

function fastSellers() {
    if (!fastSellersReady) {
        return null;
    }
    var list = [];
    for (var i = 0; i < data.length; i++) {
        var day = data[i];
        var menu = day.menu;
        loop_menu:
        for (var j = 0; j < menu.length; j++) {
            var category = menu[j];
            var meals = category.meals;
            for (var k = 0; k < meals.length; k++) {
                var meal = meals[k];
                if (meal.fastSeller == true) {
                    list.push({ 'date': day.date, 'title': meal.title });
                    break loop_menu;
                }
            }
        }
    }
    return list;
}

function getLocation() {
    return location;
}

function setLocation(newLocation) {
    if (newLocation != location) {
        location = newLocation

        data = [];
        menuReady = false;
        fastSellersReady = false;

        store();

        cbReset();

        var day = new time.Day();
        if (!day.isWeekday()) {
            menuReady = true;
            cbMenu();
        }

        reader.updateMenuData(data, location, readerCallback);
    }
}

function setData(newData) {
    data = newData;
    filterData();
    store();
}

function filterData() {
    var day = new time.Day();
    var cutoff = day.getUTCTimestamp();
    while (data.length > 0 && data[0].date < cutoff) {
        data.shift();
    }
}

function load() {
    var version = localStorage.getItem('version');
    version = parseInt(version);

    if (version >= 6 && version <= DATA_FORMAT_VERSION) {
        try {
            var storedLocation = localStorage.getItem('location');
            location = parseInt(storedLocation);
        } catch (err) {
            console.log('Failed to load location: ' + err);
        }
    }

    if (version === DATA_FORMAT_VERSION) {
        try {
            var timestamp = localStorage.getItem('timestamp');
            if (parseFloat(timestamp) <= time.now()) {
                var storedData = localStorage.getItem('data');
                data = JSON.parse(storedData);
                filterData();
            }
        } catch (err) {
            console.log('Failed to load data: ' + err);
        }
    }
}

function store() {
    localStorage.setItem('version', DATA_FORMAT_VERSION);
    localStorage.setItem('location', location);
    localStorage.setItem('timestamp', time.now());
    localStorage.setItem('data', JSON.stringify(data));
}

module.exports.init = init;
module.exports.currentMenu = currentMenu;
module.exports.fastSellers = fastSellers;
module.exports.getLocation = getLocation;
module.exports.setLocation = setLocation;
<commit_msg>Bump data format version<commit_after>/*
 * Copyright (c) 2016-2017 Jan Hoffmann
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

var reader = require('./reader');
var time = require('./time');

var DATA_FORMAT_VERSION = 7;

var cbError, cbMenu, cbFastSeller, cbReset;

var menuReady = false;
var fastSellersReady = false;

var data = [];

var location = 2;

function init(callbackError, callbackMenu, callbackFastSeller, callbackReset) {
    cbError = callbackError;
    cbMenu = callbackMenu;
    cbFastSeller = callbackFastSeller
    cbReset = callbackReset;

    load();

    var day = new time.Day();
    if ((data.length > 0 && day.getUTCTimestamp() == data[0].date) || !day.isWeekday()) {
        menuReady = true;
        cbMenu();
    }

    if (data.length > 0) {
        fastSellersReady = true;
        cbFastSeller();
    }

    reader.updateMenuData(data, location, readerCallback);
}

function readerCallback(day, success, data) {
    if (success) {
        setData(data);

        var today = new time.Day();
        if (today.getUTCTimestamp() == day.getUTCTimestamp()) {
            menuReady = true;
            cbMenu();
        }

        fastSellersReady = true;
        cbFastSeller();
    } else {
        if (!menuReady) {
            cbError();
        }
    }
}

function currentMenu() {
    if (!menuReady) {
        return null;
    }
    if (data.length > 0) {
        var day = new time.Day();
        var timestamp = day.getUTCTimestamp();
        if (timestamp == data[0].date) {
            return { 'menu': data[0].menu, 'message': data[0].message };
        }
    }
    return { 'menu': [], 'message': '' };
}

function fastSellers() {
    if (!fastSellersReady) {
        return null;
    }
    var list = [];
    for (var i = 0; i < data.length; i++) {
        var day = data[i];
        var menu = day.menu;
        loop_menu:
        for (var j = 0; j < menu.length; j++) {
            var category = menu[j];
            var meals = category.meals;
            for (var k = 0; k < meals.length; k++) {
                var meal = meals[k];
                if (meal.fastSeller == true) {
                    list.push({ 'date': day.date, 'title': meal.title });
                    break loop_menu;
                }
            }
        }
    }
    return list;
}

function getLocation() {
    return location;
}

function setLocation(newLocation) {
    if (newLocation != location) {
        location = newLocation

        data = [];
        menuReady = false;
        fastSellersReady = false;

        store();

        cbReset();

        var day = new time.Day();
        if (!day.isWeekday()) {
            menuReady = true;
            cbMenu();
        }

        reader.updateMenuData(data, location, readerCallback);
    }
}

function setData(newData) {
    data = newData;
    filterData();
    store();
}

function filterData() {
    var day = new time.Day();
    var cutoff = day.getUTCTimestamp();
    while (data.length > 0 && data[0].date < cutoff) {
        data.shift();
    }
}

function load() {
    var version = localStorage.getItem('version');
    version = parseInt(version);

    if (version >= 6 && version <= DATA_FORMAT_VERSION) {
        try {
            var storedLocation = localStorage.getItem('location');
            location = parseInt(storedLocation);
        } catch (err) {
            console.log('Failed to load location: ' + err);
        }
    }

    if (version === DATA_FORMAT_VERSION) {
        try {
            var timestamp = localStorage.getItem('timestamp');
            if (parseFloat(timestamp) <= time.now()) {
                var storedData = localStorage.getItem('data');
                data = JSON.parse(storedData);
                filterData();
            }
        } catch (err) {
            console.log('Failed to load data: ' + err);
        }
    }
}

function store() {
    localStorage.setItem('version', DATA_FORMAT_VERSION);
    localStorage.setItem('location', location);
    localStorage.setItem('timestamp', time.now());
    localStorage.setItem('data', JSON.stringify(data));
}

module.exports.init = init;
module.exports.currentMenu = currentMenu;
module.exports.fastSellers = fastSellers;
module.exports.getLocation = getLocation;
module.exports.setLocation = setLocation;
<|endoftext|>


<commit_before>/**
 * Copyright JS Foundation and other contributors, http://js.foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

var when = require('when');
var should = require('should');
var fs = require('fs-extra');

var helper = require('../../editor_helper');
var debugTab = require('../../pageobjects/editor/debugTab_page');
var workspace = require('../../pageobjects/editor/workspace_page');
var specUtil = require('../../pageobjects/util/spec_util_page');

var httpNodeRoot = '/api';

// https://cookbook.nodered.org/
describe('cookbook', function () {
    beforeEach(function () {
        workspace.init();
    });

    before(function () {
        helper.startServer();
    });

    after(function () {
        helper.stopServer();
    });

    describe('working with data formats', function () {
        it('convert to/from JSON', function () {
            var injectNode1 = workspace.addNode('inject');
            var jsonNode1 = workspace.addNode('json');
            var debugNode1 = workspace.addNode('debug');

            injectNode1.edit();
            injectNode1.setPayload('str', '{"a":1}');
            injectNode1.clickOk();

            jsonNode1.edit();
            jsonNode1.setProperty('payload');
            jsonNode1.clickOk();

            injectNode1.connect(jsonNode1);
            jsonNode1.connect(debugNode1);

            var injectNode2 = workspace.addNode('inject');
            var jsonNode2 = workspace.addNode('json');
            var debugNode2 = workspace.addNode('debug');

            injectNode2.edit();
            injectNode2.setPayload('json', '{"a":1}');
            injectNode2.clickOk();

            jsonNode2.edit();
            jsonNode2.setProperty('payload');
            jsonNode2.clickOk();

            injectNode2.connect(jsonNode2);
            jsonNode2.connect(debugNode2);

            workspace.deploy();

            debugTab.open();
            injectNode1.clickLeftButton();
            debugTab.getMessage().should.eql('1');
            debugTab.clearMessage();
            injectNode2.clickLeftButton();
            debugTab.getMessage().should.eql('"{"a":1}"');
        });

        it('convert to/from XML', function () {
            var injectNode1 = workspace.addNode('inject', 0);
            var templateNode1 = workspace.addNode('template', 200);
            var xmlNode1 = workspace.addNode('xml', 400);
            var debugNode1 = workspace.addNode('debug', 600);

            injectNode1.edit();
            injectNode1.setPayload('str', '{"a":1}');
            injectNode1.clickOk();

            templateNode1.edit();
            templateNode1.setFormat('text');
            templateNode1.setSyntax('plain');
            templateNode1.setTemplate('<note priority="high">'
                                    + '  <to>Nick</to>'
                                    + '  <from>Dave</from>'
                                    + '  <heading>Reminder</heading>'
                                    + '  Update the website'
                                    + '</note>');
            templateNode1.clickOk();

            xmlNode1.edit();
            xmlNode1.setProperty('payload');
            xmlNode1.clickOk();

            injectNode1.connect(templateNode1);
            templateNode1.connect(xmlNode1);
            xmlNode1.connect(debugNode1);

            var injectNode2 = workspace.addNode('inject');
            var xmlNode2 = workspace.addNode('xml');
            var debugNode2 = workspace.addNode('debug');

            injectNode2.edit();
            injectNode2.setPayload('json', '{'
                                         + '    "note": {'
                                         + '        "$": { "priority": "high" },'
                                         + '        "to": [ "Nick" ],'
                                         + '        "from": [ "Dave" ],'
                                         + '        "heading": [ "Reminder" ],'
                                         + '        "body": [ "Update the website" ]'
                                         + '    }'
                                         + '}');
            injectNode2.clickOk();

            xmlNode2.edit();
            xmlNode2.setProperty('payload');
            xmlNode2.clickOk();

            injectNode2.connect(xmlNode2);
            xmlNode2.connect(debugNode2);

            workspace.deploy();

            debugTab.open();
            injectNode1.clickLeftButton();
            debugTab.getMessage().should.eql('object');
            debugTab.clearMessage();
            injectNode2.clickLeftButton();
            debugTab.getMessage().should.eql('"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
                                            + '<note priority="high">'
                                            + '<to>Nick</to>'
                                            + '<from>Dave</from>'
                                            + '<heading>Reminder</heading>'
                                            + 'Update the website'
                                            + '</note>"');
        });

        it('convert to/from YAML', function () {
            var injectNode1 = workspace.addNode('inject', 0);
            var templateNode1 = workspace.addNode('template', 200);
            var yamlNode1 = workspace.addNode('yaml', 400);
            var debugNode1 = workspace.addNode('debug', 600);

            injectNode1.edit();
            injectNode1.setPayload('str', '{"a":1}');
            injectNode1.clickOk();

            templateNode1.edit();
            templateNode1.setFormat('yaml');
            templateNode1.setSyntax('plain');
            templateNode1.setTemplate('a: 1\n'
                                    + 'b:\n'
                                    + '  - 1\n'
                                    + '- 2\n'
                                    + '- 3');
            templateNode1.clickOk();

            yamlNode1.edit();
            yamlNode1.setProperty('payload');
            yamlNode1.clickOk();

            injectNode1.connect(templateNode1);
            templateNode1.connect(yamlNode1);
            yamlNode1.connect(debugNode1);

            var injectNode2 = workspace.addNode('inject');
            var yamlNode2 = workspace.addNode('yaml');
            var debugNode2 = workspace.addNode('debug');

            injectNode2.edit();
            injectNode2.setPayload('json', '{"a":1, "b":[1,2,3]}');
            injectNode2.clickOk();

            yamlNode2.edit();
            yamlNode2.setProperty('payload');
            yamlNode2.clickOk();

            injectNode2.connect(yamlNode2);
            yamlNode2.connect(debugNode2);

            workspace.deploy();

            debugTab.open();
            injectNode1.clickLeftButton();
            debugTab.getMessage().should.eql([ '1', 'array[3]' ]);
            debugTab.clearMessage();
            injectNode2.clickLeftButton();
            debugTab.getMessage().should.eql('"a: 1↵b:↵ - 1↵ - 2↵ - 3↵"');
        });

        it('generate CSV output', function () {
            var injectNode1 = workspace.addNode('inject', 0);
            var changeNode1 = workspace.addNode('change', 200);
            var csvNode1 = workspace.addNode('csv', 400);
            var debugNode1 = workspace.addNode('debug', 600);

            changeNode1.edit();
            changeNode1.ruleSet('payload', 'msg', '{'
                                                + '  "a": $floor(100*$random()),'
                                                + '  "b": $floor(100*$random()),'
                                                + '  "c": $floor(100*$random())'
                                                + '}', 'jsonata');
            changeNode1.clickOk();

            csvNode1.edit();
            csvNode1.setColumns('a,b,c');
            csvNode1.clickOk();

            injectNode1.connect(changeNode1);
            changeNode1.connect(csvNode1);
            csvNode1.connect(debugNode1);

            var injectNode2 = workspace.addNode('inject', 0, 80);
            var changeNode2 = workspace.addNode('change', 200, 80);
            var csvNode2 = workspace.addNode('csv', 400, 80);
            var debugNode2 = workspace.addNode('debug', 600, 80);

            changeNode2.edit();
            changeNode2.ruleSet('payload', 'msg', '['
                                                + '  {'
                                                + '    "a": $floor(100*$random()),'
                                                + '    "b": $floor(100*$random()),'
                                                + '    "c": $floor(100*$random())'
                                                + '  }, {'
                                                + '    "a": $floor(100*$random()),'
                                                + '    "b": $floor(100*$random()),'
                                                + '    "c": $floor(100*$random())'
                                                + '  }, {'
                                                + '    "a": $floor(100*$random()),'
                                                + '    "b": $floor(100*$random()),'
                                                + '    "c": $floor(100*$random())'
                                                + '  }, {'
                                                + '    "a": $floor(100*$random()),'
                                                + '    "b": $floor(100*$random()),'
                                                + '    "c": $floor(100*$random())'
                                                + '  }'
                                                + ']', 'jsonata');
            changeNode2.clickOk();

            csvNode2.edit();
            csvNode2.setColumns('a,b,c');
            csvNode2.setIncludeRow(true);
            csvNode2.clickOk();

            injectNode2.connect(changeNode2);
            changeNode2.connect(csvNode2);
            csvNode2.connect(debugNode2);

            workspace.deploy();

            debugTab.open();
            injectNode1.clickLeftButton();
            debugTab.getMessage().should.match(/^"([1-9]?[0-9],){2}[1-9]?[0-9]↵"$/);
            debugTab.clearMessage();
            injectNode2.clickLeftButton();
            debugTab.getMessage().should.match(/^"a,b,c↵(([1-9]?[0-9],){2}[1-9]?[0-9]↵){4}"$/);
        });

        it('parse CSV input', function () {
            var injectNode = workspace.addNode('inject');
            var templateNode = workspace.addNode('template');
            var csvNode = workspace.addNode('csv');
            var debugNode = workspace.addNode('debug');

            templateNode.edit();
            templateNode.setFormat('handlebars');
            templateNode.setSyntax('mustache');
            templateNode.setTemplate('# This is some random data\n'
                                   + 'a,b,c\n'
                                   + '80,18,2\n'
                                   + '52,36,10\n'
                                   + '91,18,61\n'
                                   + '32,47,65');
            templateNode.clickOk();

            csvNode.edit();
            csvNode.setSkipLines(1);
            csvNode.setFirstRow4Names(true);
            csvNode.setOutput('mult');
            csvNode.clickOk();

            injectNode.connect(templateNode);
            templateNode.connect(csvNode);
            csvNode.connect(debugNode);

            workspace.deploy();

            debugTab.open();
            injectNode.clickLeftButton();
            debugTab.getMessage().should.eql([ 'object', 'object', 'object', 'object' ]);
        });

        it('simple GET request', function () {
            var injectNode = workspace.addNode('inject');
            var httpRequestNode = workspace.addNode('httpRequest');
            var htmlNode = workspace.addNode('html');
            var debugNode = workspace.addNode('debug');

            httpRequestNode.edit();
            httpRequestNode.setMethod('GET');
            httpRequestNode.setUrl('https://nodered.org');
            httpRequestNode.clickOk();

            htmlNode.edit();
            htmlNode.setSelector('.node-red-latest-version');
            htmlNode.clickOk();

            injectNode.connect(httpRequestNode);
            httpRequestNode.connect(htmlNode);
            htmlNode.connect(debugNode);

            workspace.deploy();

            debugTab.open();
            injectNode.clickLeftButton();
            debugTab.getMessage().should.match(/^"v[0-9]+\.[0-9]+\.[0-9]"$/);
        });

        it('split text into one message per line', function () {
            var injectNode = workspace.addNode('inject');
            var templateNode = workspace.addNode('template');
            var splitNode = workspace.addNode('split');
            var changeNode = workspace.addNode('change');
            var joinNode = workspace.addNode('join');
            var debugNode = workspace.addNode('debug');

            templateNode.edit();
            templateNode.setFormat('handlebars');
            templateNode.setSyntax('mustache');
            templateNode.setTemplate('one\ntwo\nthree\nfour\nfive');
            templateNode.clickOk();

            changeNode.edit();
            changeNode.ruleSet('payload', 'msg', '(parts.index+1) & ": " & payload', 'jsonata');
            changeNode.clickOk();

            injectNode.connect(templateNode);
            templateNode.connect(splitNode);
            splitNode.connect(changeNode);
            changeNode.connect(joinNode);
            joinNode.connect(debugNode);

            workspace.deploy();

            debugTab.open();
            injectNode.clickLeftButton();
            debugTab.getMessage().should.eql('"1: one↵2: two↵3: three↵4: four↵5: five"');
        });
    });
});
<commit_msg>Fix test cases for UI testing<commit_after>/**
 * Copyright JS Foundation and other contributors, http://js.foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

var when = require('when');
var should = require('should');
var fs = require('fs-extra');

var helper = require('../../editor_helper');
var debugTab = require('../../pageobjects/editor/debugTab_page');
var workspace = require('../../pageobjects/editor/workspace_page');
var specUtil = require('../../pageobjects/util/spec_util_page');

var httpNodeRoot = '/api';

// https://cookbook.nodered.org/
describe('cookbook', function () {
    beforeEach(function () {
        workspace.init();
    });

    before(function () {
        helper.startServer();
    });

    after(function () {
        helper.stopServer();
    });

    describe('working with data formats', function () {
        it('convert to/from JSON', function () {
            var injectNode1 = workspace.addNode('inject');
            var jsonNode1 = workspace.addNode('json');
            var debugNode1 = workspace.addNode('debug');

            injectNode1.edit();
            injectNode1.setPayload('str', '{"a":1}');
            injectNode1.clickOk();

            jsonNode1.edit();
            jsonNode1.setProperty('payload');
            jsonNode1.clickOk();

            injectNode1.connect(jsonNode1);
            jsonNode1.connect(debugNode1);

            var injectNode2 = workspace.addNode('inject');
            var jsonNode2 = workspace.addNode('json');
            var debugNode2 = workspace.addNode('debug');

            injectNode2.edit();
            injectNode2.setPayload('json', '{"a":1}');
            injectNode2.clickOk();

            jsonNode2.edit();
            jsonNode2.setProperty('payload');
            jsonNode2.clickOk();

            injectNode2.connect(jsonNode2);
            jsonNode2.connect(debugNode2);

            workspace.deploy();

            debugTab.open();
            injectNode1.clickLeftButton();
            debugTab.getMessage().should.eql('1');
            debugTab.clearMessage();
            injectNode2.clickLeftButton();
            debugTab.getMessage().should.eql('"{"a":1}"');
        });

        it('convert to/from XML', function () {
            var injectNode1 = workspace.addNode('inject', 0);
            var templateNode1 = workspace.addNode('template', 200);
            var xmlNode1 = workspace.addNode('xml', 400);
            var debugNode1 = workspace.addNode('debug', 600);

            injectNode1.edit();
            injectNode1.setPayload('str', '{"a":1}');
            injectNode1.clickOk();

            templateNode1.edit();
            templateNode1.setFormat('text');
            templateNode1.setSyntax('plain');
            templateNode1.setTemplate('<note priority="high">'
                                    + '  <to>Nick</to>'
                                    + '  <from>Dave</from>'
                                    + '  <heading>Reminder</heading>'
                                    + '  Update the website'
                                    + '</note>');
            templateNode1.clickOk();

            xmlNode1.edit();
            xmlNode1.setProperty('payload');
            xmlNode1.clickOk();

            injectNode1.connect(templateNode1);
            templateNode1.connect(xmlNode1);
            xmlNode1.connect(debugNode1);

            var injectNode2 = workspace.addNode('inject');
            var xmlNode2 = workspace.addNode('xml');
            var debugNode2 = workspace.addNode('debug');

            injectNode2.edit();
            injectNode2.setPayload('json', '{'
                                         + '    "note": {'
                                         + '        "$": { "priority": "high" },'
                                         + '        "to": [ "Nick" ],'
                                         + '        "from": [ "Dave" ],'
                                         + '        "heading": [ "Reminder" ],'
                                         + '        "body": [ "Update the website" ]'
                                         + '    }'
                                         + '}');
            injectNode2.clickOk();

            xmlNode2.edit();
            xmlNode2.setProperty('payload');
            xmlNode2.clickOk();

            injectNode2.connect(xmlNode2);
            xmlNode2.connect(debugNode2);

            workspace.deploy();

            debugTab.open();
            injectNode1.clickLeftButton();
            debugTab.getMessage().should.eql('object');
            debugTab.clearMessage();
            injectNode2.clickLeftButton();
            debugTab.getMessage().should.eql('"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
                                            + '<note priority="high">'
                                            + '<to>Nick</to>'
                                            + '<from>Dave</from>'
                                            + '<heading>Reminder</heading>'
                                            + 'Update the website'
                                            + '</note>"');
        });

        it('convert to/from YAML', function () {
            var injectNode1 = workspace.addNode('inject', 0);
            var templateNode1 = workspace.addNode('template', 200);
            var yamlNode1 = workspace.addNode('yaml', 400);
            var debugNode1 = workspace.addNode('debug', 600);

            injectNode1.edit();
            injectNode1.setPayload('str', '{"a":1}');
            injectNode1.clickOk();

            templateNode1.edit();
            templateNode1.setFormat('yaml');
            templateNode1.setSyntax('plain');
            templateNode1.setTemplate('a: 1\n'
                                    + 'b:\n'
                                    + '  - 1\n'
                                    + '- 2\n'
                                    + '- 3');
            templateNode1.clickOk();

            yamlNode1.edit();
            yamlNode1.setProperty('payload');
            yamlNode1.clickOk();

            injectNode1.connect(templateNode1);
            templateNode1.connect(yamlNode1);
            yamlNode1.connect(debugNode1);

            var injectNode2 = workspace.addNode('inject');
            var yamlNode2 = workspace.addNode('yaml');
            var debugNode2 = workspace.addNode('debug');

            injectNode2.edit();
            injectNode2.setPayload('json', '{"a":1, "b":[1,2,3]}');
            injectNode2.clickOk();

            yamlNode2.edit();
            yamlNode2.setProperty('payload');
            yamlNode2.clickOk();

            injectNode2.connect(yamlNode2);
            yamlNode2.connect(debugNode2);

            workspace.deploy();

            debugTab.open();
            injectNode1.clickLeftButton();
            debugTab.getMessage().should.eql([ '1', 'array[3]' ]);
            debugTab.clearMessage();
            injectNode2.clickLeftButton();
            debugTab.getMessage().should.eql('"a: 1↵b:↵  - 1↵  - 2↵  - 3↵"');
        });

        it('generate CSV output', function () {
            var injectNode1 = workspace.addNode('inject', 0);
            var changeNode1 = workspace.addNode('change', 200);
            var csvNode1 = workspace.addNode('csv', 400);
            var debugNode1 = workspace.addNode('debug', 600);

            changeNode1.edit();
            changeNode1.ruleSet('payload', 'msg', '{'
                                                + '  "a": $floor(100*$random()),'
                                                + '  "b": $floor(100*$random()),'
                                                + '  "c": $floor(100*$random())'
                                                + '}', 'jsonata');
            changeNode1.clickOk();

            csvNode1.edit();
            csvNode1.setColumns('a,b,c');
            csvNode1.clickOk();

            injectNode1.connect(changeNode1);
            changeNode1.connect(csvNode1);
            csvNode1.connect(debugNode1);

            var injectNode2 = workspace.addNode('inject', 0, 80);
            var changeNode2 = workspace.addNode('change', 200, 80);
            var csvNode2 = workspace.addNode('csv', 400, 80);
            var debugNode2 = workspace.addNode('debug', 600, 80);

            changeNode2.edit();
            changeNode2.ruleSet('payload', 'msg', '['
                                                + '  {'
                                                + '    "a": $floor(100*$random()),'
                                                + '    "b": $floor(100*$random()),'
                                                + '    "c": $floor(100*$random())'
                                                + '  }, {'
                                                + '    "a": $floor(100*$random()),'
                                                + '    "b": $floor(100*$random()),'
                                                + '    "c": $floor(100*$random())'
                                                + '  }, {'
                                                + '    "a": $floor(100*$random()),'
                                                + '    "b": $floor(100*$random()),'
                                                + '    "c": $floor(100*$random())'
                                                + '  }, {'
                                                + '    "a": $floor(100*$random()),'
                                                + '    "b": $floor(100*$random()),'
                                                + '    "c": $floor(100*$random())'
                                                + '  }'
                                                + ']', 'jsonata');
            changeNode2.clickOk();

            csvNode2.edit();
            csvNode2.setColumns('a,b,c');
            csvNode2.setIncludeRow(true);
            csvNode2.clickOk();

            injectNode2.connect(changeNode2);
            changeNode2.connect(csvNode2);
            csvNode2.connect(debugNode2);

            workspace.deploy();

            debugTab.open();
            injectNode1.clickLeftButton();
            debugTab.getMessage().should.match(/^"([1-9]?[0-9],){2}[1-9]?[0-9]↵"$/);
            debugTab.clearMessage();
            injectNode2.clickLeftButton();
            debugTab.getMessage().should.match(/^"a,b,c↵(([1-9]?[0-9],){2}[1-9]?[0-9]↵){4}"$/);
        });

        it('parse CSV input', function () {
            var injectNode = workspace.addNode('inject');
            var templateNode = workspace.addNode('template');
            var csvNode = workspace.addNode('csv');
            var debugNode = workspace.addNode('debug');

            templateNode.edit();
            templateNode.setFormat('handlebars');
            templateNode.setSyntax('mustache');
            templateNode.setTemplate('# This is some random data\n'
                                   + 'a,b,c\n'
                                   + '80,18,2\n'
                                   + '52,36,10\n'
                                   + '91,18,61\n'
                                   + '32,47,65');
            templateNode.clickOk();

            csvNode.edit();
            csvNode.setSkipLines(1);
            csvNode.setFirstRow4Names(true);
            csvNode.setOutput('mult');
            csvNode.clickOk();

            injectNode.connect(templateNode);
            templateNode.connect(csvNode);
            csvNode.connect(debugNode);

            workspace.deploy();

            debugTab.open();
            injectNode.clickLeftButton();
            debugTab.getMessage().should.eql([ 'object', 'object', 'object', 'object' ]);
        });

        it('simple GET request', function () {
            var injectNode = workspace.addNode('inject');
            var httpRequestNode = workspace.addNode('httpRequest');
            var htmlNode = workspace.addNode('html');
            var debugNode = workspace.addNode('debug');

            httpRequestNode.edit();
            httpRequestNode.setMethod('GET');
            httpRequestNode.setUrl('https://nodered.org');
            httpRequestNode.clickOk();

            htmlNode.edit();
            htmlNode.setSelector('.node-red-latest-version');
            htmlNode.clickOk();

            injectNode.connect(httpRequestNode);
            httpRequestNode.connect(htmlNode);
            htmlNode.connect(debugNode);

            workspace.deploy();

            debugTab.open();
            injectNode.clickLeftButton();
            debugTab.getMessage().should.match(/^"v[0-9]+\.[0-9]+\.[0-9]"$/);
        });

        it('split text into one message per line', function () {
            var injectNode = workspace.addNode('inject');
            var templateNode = workspace.addNode('template');
            var splitNode = workspace.addNode('split');
            var changeNode = workspace.addNode('change');
            var joinNode = workspace.addNode('join');
            var debugNode = workspace.addNode('debug');

            templateNode.edit();
            templateNode.setFormat('handlebars');
            templateNode.setSyntax('mustache');
            templateNode.setTemplate('one\ntwo\nthree\nfour\nfive');
            templateNode.clickOk();

            changeNode.edit();
            changeNode.ruleSet('payload', 'msg', '(parts.index+1) & ": " & payload', 'jsonata');
            changeNode.clickOk();

            injectNode.connect(templateNode);
            templateNode.connect(splitNode);
            splitNode.connect(changeNode);
            changeNode.connect(joinNode);
            joinNode.connect(debugNode);

            workspace.deploy();

            debugTab.open();
            injectNode.clickLeftButton();
            debugTab.getMessage().should.eql('"1: one↵2: two↵3: three↵4: four↵5: five"');
        });
    });
});
<|endoftext|>


<commit_before>var app = angular.module('coconuts', ['ngAnimate', 'ngResource', 'ngRoute', 'ngTouch']).
config(['$httpProvider', '$routeProvider', function($httpProvider, $routeProvider) {
    // handle django's CSRF
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]).
controller('FolderCtrl', ['$http', '$location', '$scope', 'FormData', 'settings', function($http, $location, $scope, FormData, settings) {
    $scope.settings = settings;
    $scope.contents = {photos: []};

    function updatePhoto() {
        var path = $location.path();
        var photo, i;
        for (i = 0; i < $scope.contents.photos.length; i++) {
            photo = $scope.contents.photos[i];
            if (photo.path === path) {
                $scope.previousPhoto = $scope.contents.photos[i-1];
                $scope.currentPhoto = photo;
                $scope.nextPhoto = $scope.contents.photos[i+1];
                return;
            }
            $scope.previousPhoto = undefined;
            $scope.currentPhoto = undefined;
            $scope.nextPhoto = undefined;
        }
    }

    $scope.doAdd = function() {
        var formData = new FormData();
        formData.append('upload', $scope.addFile);
        $http.post(settings.coconuts_root + 'add_file' + $scope.contents.path, formData, {
            headers: { 'Content-Type': undefined },
            transformRequest: function(data) { return data; }
        }).success(function(contents) {
            $scope.addPrompt = false;
            $scope.contents = contents;
            updatePhoto();
        });
    };

    $scope.doCreate = function() {
        var formData = new FormData();
        formData.append('name', $scope.createName);
        $http.post(settings.coconuts_root + 'add_folder' + $scope.contents.path, formData, {
            headers: { 'Content-Type': undefined },
            transformRequest: function(data) { return data; }
        }).success(function(contents) {
            $scope.createPrompt = false;
            $scope.contents = contents;
            updatePhoto();
        });
    };

    $scope.promptDelete = function(obj) {
        $scope.deleteTarget = obj;
        $scope.deleteFolder = false;
    };
    $scope.doDelete = function() {
        $http.post(settings.coconuts_root + 'delete/' + $scope.deleteTarget.path).success(function(contents) {
            $scope.deleteTarget = undefined;
            $scope.contents = contents;
            $location.path($scope.contents.path);
        });
    };

    $scope.location = $location;
    $scope.$watch('location.path()', function(path) {
        if (path === '') path = '/';
        var crumbs = [];
        var crumbPath = '';
        var bits = path.split('/');
        for (var i = 1; i < bits.length - 1; i++) {
            crumbPath += '/' + bits[i] + '/';
            crumbs.push({name: bits[i], path: crumbPath});
        }
        $scope.crumbs = crumbs;
        $http.get(settings.coconuts_root + 'contents' + path).success(function(contents) {
            $scope.contents = contents;
            updatePhoto();
        });
    });
}]).
directive('coFile', ['$parse', function($parse) {
    return {
        restrict: 'A',
        link: function(scope, elm, attrs) {
            var model = $parse(attrs.coFile);
            elm.bind('change', function(evt) {
                scope.$apply(function() {
                    model.assign(scope, evt.target.files[0]);
                });
            });
        }
    };
}]).
factory('FormData', [function() {
    return FormData;
}]).
factory('settings', ['$http', function($http) {
    return {
        coconuts_root: '/images/',
        static_root: '/static/coconuts/'
    };
}]).
filter('fileIcon', ['settings', function(settings) {
    var mime_root = settings.static_root + 'img/mimetypes/';
    return function(name) {
        var idx = name.lastIndexOf('.');
        if (idx !== -1) {
            var extension = name.slice(idx + 1, name.length).toLowerCase();
            if (extension == 'gif' || extension == 'jpg' || extension == 'jpeg' || extension == 'png') {
                return mime_root + 'image-jpeg.png';
            } else if (extension == 'py') {
                return mime_root + 'text-x-python.png';
            }
        }
        return mime_root + 'unknown.png';
    };
}]).
filter('fileSize', [function() {
    var MB = 1024 * 1024;
    var KB = 1024;
    return function(val) {
        if (val > MB) {
            return (val / MB).toFixed(1) + ' MB';
        } else if (val > KB) {
            return (val / KB).toFixed(1) + ' kB';
        } else {
            return val + ' B';
        }
    };
}]).
filter('urlencode', [function() {
    return function(val) {
        return val;
    };
}]);
<commit_msg>rebuild crumbs<commit_after>var app = angular.module('coconuts', ['ngAnimate', 'ngResource', 'ngRoute', 'ngTouch']).
config(['$httpProvider', '$routeProvider', function($httpProvider, $routeProvider) {
    // handle django's CSRF
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]).
controller('FolderCtrl', ['$http', '$location', '$scope', 'FormData', 'settings', function($http, $location, $scope, FormData, settings) {
    $scope.settings = settings;
    $scope.contents = {photos: []};

    function updatePhoto() {
        var path = $location.path();
        var photo, i;
        for (i = 0; i < $scope.contents.photos.length; i++) {
            photo = $scope.contents.photos[i];
            if (photo.path === path) {
                $scope.previousPhoto = $scope.contents.photos[i-1];
                $scope.currentPhoto = photo;
                $scope.nextPhoto = $scope.contents.photos[i+1];
                return;
            }
            $scope.previousPhoto = undefined;
            $scope.currentPhoto = undefined;
            $scope.nextPhoto = undefined;
        }
    }

    $scope.doAdd = function() {
        var formData = new FormData();
        formData.append('upload', $scope.addFile);
        $http.post(settings.coconuts_root + 'add_file' + $scope.contents.path, formData, {
            headers: { 'Content-Type': undefined },
            transformRequest: function(data) { return data; }
        }).success(function(contents) {
            $scope.addPrompt = false;
            $scope.contents = contents;
            updatePhoto();
        });
    };

    $scope.doCreate = function() {
        var formData = new FormData();
        formData.append('name', $scope.createName);
        $http.post(settings.coconuts_root + 'add_folder' + $scope.contents.path, formData, {
            headers: { 'Content-Type': undefined },
            transformRequest: function(data) { return data; }
        }).success(function(contents) {
            $scope.createPrompt = false;
            $scope.contents = contents;
            updatePhoto();
        });
    };

    $scope.promptDelete = function(obj) {
        $scope.deleteTarget = obj;
        $scope.deleteFolder = false;
    };
    $scope.doDelete = function() {
        $http.post(settings.coconuts_root + 'delete/' + $scope.deleteTarget.path).success(function(contents) {
            $scope.deleteTarget = undefined;
            $scope.contents = contents;
            $location.path($scope.contents.path);
        });
    };

    $scope.location = $location;
    $scope.$watch('location.path()', function(path) {
        if (path === '') path = '/';
        var crumbs = [];
        var crumbPath = '/';
        var bits = path.split('/');
        for (var i = 1; i < bits.length - 1; i++) {
            crumbPath += bits[i] + '/';
            crumbs.push({name: bits[i], path: crumbPath});
        }
        $scope.crumbs = crumbs;
        $http.get(settings.coconuts_root + 'contents' + path).success(function(contents) {
            $scope.contents = contents;
            updatePhoto();
        });
    });
}]).
directive('coFile', ['$parse', function($parse) {
    return {
        restrict: 'A',
        link: function(scope, elm, attrs) {
            var model = $parse(attrs.coFile);
            elm.bind('change', function(evt) {
                scope.$apply(function() {
                    model.assign(scope, evt.target.files[0]);
                });
            });
        }
    };
}]).
factory('FormData', [function() {
    return FormData;
}]).
factory('settings', ['$http', function($http) {
    return {
        coconuts_root: '/images/',
        static_root: '/static/coconuts/'
    };
}]).
filter('fileIcon', ['settings', function(settings) {
    var mime_root = settings.static_root + 'img/mimetypes/';
    return function(name) {
        var idx = name.lastIndexOf('.');
        if (idx !== -1) {
            var extension = name.slice(idx + 1, name.length).toLowerCase();
            if (extension == 'gif' || extension == 'jpg' || extension == 'jpeg' || extension == 'png') {
                return mime_root + 'image-jpeg.png';
            } else if (extension == 'py') {
                return mime_root + 'text-x-python.png';
            }
        }
        return mime_root + 'unknown.png';
    };
}]).
filter('fileSize', [function() {
    var MB = 1024 * 1024;
    var KB = 1024;
    return function(val) {
        if (val > MB) {
            return (val / MB).toFixed(1) + ' MB';
        } else if (val > KB) {
            return (val / KB).toFixed(1) + ' kB';
        } else {
            return val + ' B';
        }
    };
}]).
filter('urlencode', [function() {
    return function(val) {
        return val;
    };
}]);
<|endoftext|>


<commit_before>describe("BaseModel", function() {

	describe("modules", function() {

		describe("relations", function() {

			describe("getClassReference", function() {
				window.__classReferenceTest__ = {
					foo: {
						bar: {
							Test: function() {}
						}
					}
				};

				it("gets a class reference by a String class name", function() {
					expect(BaseModel.modules.relations.self.getClassReference("__classReferenceTest__.foo.bar.Test")).toBeFunction();
				});

				it("throws an error when an invalid String class name is provided", function() {
					expect(function() {BaseModel.modules.relations.self.getClassReference("__classReferenceTest__.foo.bar.InvalidClassName");}).toThrowError();
				});
			});

			describe("hasOne", function() {
				beforeEach(function() {
					this.attributes = {
						id: 1234,
						name: "Chainsaw",
						description: "Cuts wood",
						price: 135.99,
						quantity: 8,
						category_id: 98,
						category: {
							id: 98,
							name: "Outdoors"
						}
					};
				});

				it("returns null when no attributes exist for a relation", function() {
					var model = new TestRelations();
					expect(model.category).toBeNull();
				});

				it("instantiates a relation when attributes exist", function() {
					var model = new TestRelations(this.attributes);
					expect(model.category).toBeDefined();
					expect(model.category).toBeInstanceof(Category);
					expect(model.category.name).toEqual("Outdoors");
					expect(model.category.id).toEqual(98);
				});

				it("lazily instantiates a relation when attributes exist", function() {
					var model = new TestRelations();
					expect(model.category).toBeNull();
					expect(model._relations.category).toBeUndefined();
					model.attributes = this.attributes;
					expect(model.category).toBeDefined();
					expect(model.category).toBeInstanceof(Category);
					expect(model.category.name).toEqual("Outdoors");
					expect(model.category.id).toEqual(98);
					expect(model.category_id).toEqual(model.category.id);
				});

				it("sets relationship Id attribute to null when setting relationship to null", function() {
					var model = new TestRelations(this.attributes);
					expect(model.category).toBeInstanceof(Category);
					expect(model.category.id).toEqual(model.category_id);
					expect(model.category_id).toEqual(98);
					model.category = null;
					expect(model.category).toBeNull();
					expect(model.category_id).toBeNull();
					expect(model.changedAttributes.category_id).toEqual(98);
				});

				it("assigning a relationship by object instance changes relationship Id", function() {
					var model = new TestRelations();
					var category = new Category({id: 98, name: "Outdoors"});
					expect(model.category_id).toBeNull();
					model.category = category;
					expect(model.relationsAttributes.category).toBeNull();
					expect(model.category).toEqual(category);
					expect(model.category.id).toEqual(98);
					expect(model.category_id).toEqual(category.id);
				});
			});

			describe("hasMany", function() {
				beforeEach(function() {
					this.attributes = {
						id: 1234,
						name: "Chainsaw",
						description: "Cuts wood",
						price: 135.99,
						quantity: 8,
						deals: [{
							id: 1,
							store_id: 1234,
							name: "New Year's Blowout",
							description: "Take 50% off everything in store!",
							start_date: "January 1, 2012",
							end_date: "February 1, 2012"
						},{
							id: 2,
							store_id: 1234,
							name: "Valentine's Day Sale",
							description: "45% off all chocolates",
							start_date: "February 15, 2012",
							end_date: "February 16, 2012"
						}]
					};
				});

				it("returns null when no attributes exist for a relation", function() {
					var model = new Store();
					expect(model.deals).toBeNull();
					expect(model._relations.deals).toBeUndefined();
				});

				it("instantiates a relation when attributes exist", function() {
					var model = new Store(this.attributes);
					expect(model.deals).toBeArray();
					expect(model.deals.length).toEqual(2);
					expect(model._relations.deals).toBeArray();
					expect(model.deals[0]).toBeInstanceof(Deal);
					expect(model.deals[1]).toBeInstanceof(Deal);
				});

				it("lazily instantiates a relation when attributes exist", function() {
					var model = new Store();
					expect(model.deals).toBeNull();
					expect(model._relations.deals).toBeUndefined();
					model.attributes = this.attributes;
					expect(model.deals).toBeArray();
					expect(model.deals.length).toEqual(2);
					expect(model._relations.deals).toBeArray();
					expect(model.deals[0]).toBeInstanceof(Deal);
					expect(model.deals[1]).toBeInstanceof(Deal);
				});

				it("assigns a relationship by object instance", function() {
					var model = new Store(this.attributes);
					var oldDeals = model.deals;
					var newDeals = [new Deal({id: 3, store_id: 1234})];
					model.deals = newDeals;
					expect(model.relationsAttributes.deals).toBeNull();
					expect(model.changedAttributes.deals).toBeUndefined();
					expect(model.deals).toEqual(newDeals);
					expect(model.deals.length).toEqual(1);
				});
			});

			describe("validation", function() {
				it("sets valid to false when a relationship is invalid", function() {
					var model = new Store({
						id: 1234,
						name: "Expo World",
						deals: [{
							name: "I am not valid"
						},{
							id: 5,
							store_id: 1234,
							name: "I am valid"
						}]
					});

					expect(model.validate()).toBeFalse();
					expect(model.deals[0].valid).toBeFalse();
					expect(model.deals[1].valid).toBeTrue();
					expect(model.errors.deals[0]).toEqual("has errors");
				});

				it("sets valid to true when all relations are valid", function() {
					var model = new Store({
						id: 1234,
						name: "Expo World",
						deals: [{
							id: 6,
							store_id: 1234,
							name: "I am valid"
						},{
							id: 5,
							store_id: 1234,
							name: "I am valid too"
						}]
					});

					expect(model.validate()).toBeTrue();
				});

				it("sets valid to true when there are no relations", function() {
					var model = new Store({
						id: 1234,
						name: "Expo World"
					});

					expect(model.validate()).toBeTrue();
				});

				it("sets valid to false when relations are valid, but main attributes are not", function() {
					var model = new Store({
						id: 1234,
						deals: [{
							id: 6,
							store_id: 1234,
							name: "I am valid"
						},{
							id: 5,
							store_id: 1234,
							name: "I am valid too"
						}]
					});

					expect(model.validate()).toBeFalse();
					expect(model.errors.name).toBeArray();
				});
			});

			describe("serialization", function() {
				it("serializes relations into a query string", function() {
					var model = new Store({
						id: 1234,
						deals: [{
							id: 4,
							store_id: 1234,
							name: "Testing1"
						},{
							id: 78,
							store_id: 1234,
							name: "Testing2"
						}],
						distribution_center: {
							id: 9876,
							address: "123 South St",
							postal_code: "12345-1234",
							region: "NE",
							country: "United States of America"
						}
					});
					var queryString = [
						'store[id]=1234',
						'store[deals][0][id]=4',
						'store[deals][0][store_id]=1234',
						'store[deals][0][name]=Testing1',
						'store[deals][1][id]=78',
						'store[deals][1][store_id]=1234',
						'store[deals][1][name]=Testing2',
						'store[distribution_center][id]=9876',
						'store[distribution_center][address]=123%20South%20St',
						'store[distribution_center][postal_code]=12345-1234',
						'store[distribution_center][region]=NE',
						'store[distribution_center][country]=United%20States%20of%20America'
					].sort().join("&");
					var actual = model.toQueryString({rootElement: "store"}).split(/&/g).sort().join("&");
					expect(actual).toEqual(queryString);
				});

				it("skips relations that do not exist", function() {
					var model = new Store({
						id: 1234,
						deals: [{
							id: 4,
							store_id: 1234,
							name: "Testing1"
						}]
					});
					var queryString = [
						'store[id]=1234',
						'store[deals][0][id]=4',
						'store[deals][0][store_id]=1234',
						'store[deals][0][name]=Testing1'
					].sort().join("&");
					var actual = model.toQueryString({rootElement: "store"}).split(/&/g).sort().join("&");
					expect(actual).toEqual(queryString);
				});

				describe("toXml", function() {
					beforeEach(function() {
						this.store = new Store();
					});

					it("serializes hasOne relationships", function() {
						this.store.attributes = {
							id: 1234,
							distribution_center: {
								id: 9876,
								address: "123 South St",
								postal_code: "12345-1234",
								region: "NE",
								country: "United States of America"
							}
						};

						var xml = [
							'<store>',
								'<id>1234</id>',
								'<distribution_center>',
									'<id>9876</id>',
									'<address>123 South St</address>',
									'<postal_code>12345-1234</postal_code>',
									'<region>NE</region>',
									'<country>United States of America</country>',
								'</distribution_center>',
							'</store>'
						].join("");
						var action = this.store.toXml({rootElement: "store"});
						expect(action).toEqual(xml);
					});

					it("serializes hasMany relationships", function() {
						this.store.attributes = {
							deals: [{
								id: 4,
								store_id: 1234,
								name: "Testing1"
							},{
								id: 78,
								store_id: 1234,
								name: "Testing2"
							}]
						};

						var xml = [
							'<store>',
								'<deals>',
									'<deal>',
										'<id>4</id>',
										'<store_id>1234</store_id>',
										'<name>Testing1</name>',
									'</deal>',
									'<deal>',
										'<id>78</id>',
										'<store_id>1234</store_id>',
										'<name>Testing2</name>',
									'</deal>',
								'</deals>',
							'</store>'
						].join("");

						var action = this.store.toXml({rootElement: "store"});
						expect(action).toEqual(xml);
					});
				});

				describe("toJson", function() {

				});
			});

		});

	});

});<commit_msg>Moving relations attributes into beforeEach()'s<commit_after>describe("BaseModel", function() {

	describe("modules", function() {

		describe("relations", function() {

			describe("getClassReference", function() {
				window.__classReferenceTest__ = {
					foo: {
						bar: {
							Test: function() {}
						}
					}
				};

				it("gets a class reference by a String class name", function() {
					expect(BaseModel.modules.relations.self.getClassReference("__classReferenceTest__.foo.bar.Test")).toBeFunction();
				});

				it("throws an error when an invalid String class name is provided", function() {
					expect(function() {BaseModel.modules.relations.self.getClassReference("__classReferenceTest__.foo.bar.InvalidClassName");}).toThrowError();
				});
			});

			describe("hasOne", function() {
				beforeEach(function() {
					this.attributes = {
						id: 1234,
						name: "Chainsaw",
						description: "Cuts wood",
						price: 135.99,
						quantity: 8,
						category_id: 98,
						category: {
							id: 98,
							name: "Outdoors"
						}
					};
				});

				it("returns null when no attributes exist for a relation", function() {
					var model = new TestRelations();
					expect(model.category).toBeNull();
				});

				it("instantiates a relation when attributes exist", function() {
					var model = new TestRelations(this.attributes);
					expect(model.category).toBeDefined();
					expect(model.category).toBeInstanceof(Category);
					expect(model.category.name).toEqual("Outdoors");
					expect(model.category.id).toEqual(98);
				});

				it("lazily instantiates a relation when attributes exist", function() {
					var model = new TestRelations();
					expect(model.category).toBeNull();
					expect(model._relations.category).toBeUndefined();
					model.attributes = this.attributes;
					expect(model.category).toBeDefined();
					expect(model.category).toBeInstanceof(Category);
					expect(model.category.name).toEqual("Outdoors");
					expect(model.category.id).toEqual(98);
					expect(model.category_id).toEqual(model.category.id);
				});

				it("sets relationship Id attribute to null when setting relationship to null", function() {
					var model = new TestRelations(this.attributes);
					expect(model.category).toBeInstanceof(Category);
					expect(model.category.id).toEqual(model.category_id);
					expect(model.category_id).toEqual(98);
					model.category = null;
					expect(model.category).toBeNull();
					expect(model.category_id).toBeNull();
					expect(model.changedAttributes.category_id).toEqual(98);
				});

				it("assigning a relationship by object instance changes relationship Id", function() {
					var model = new TestRelations();
					var category = new Category({id: 98, name: "Outdoors"});
					expect(model.category_id).toBeNull();
					model.category = category;
					expect(model.relationsAttributes.category).toBeNull();
					expect(model.category).toEqual(category);
					expect(model.category.id).toEqual(98);
					expect(model.category_id).toEqual(category.id);
				});
			});

			describe("hasMany", function() {
				beforeEach(function() {
					this.attributes = {
						id: 1234,
						name: "Chainsaw",
						description: "Cuts wood",
						price: 135.99,
						quantity: 8,
						deals: [{
							id: 1,
							store_id: 1234,
							name: "New Year's Blowout",
							description: "Take 50% off everything in store!",
							start_date: "January 1, 2012",
							end_date: "February 1, 2012"
						},{
							id: 2,
							store_id: 1234,
							name: "Valentine's Day Sale",
							description: "45% off all chocolates",
							start_date: "February 15, 2012",
							end_date: "February 16, 2012"
						}]
					};
				});

				it("returns null when no attributes exist for a relation", function() {
					var model = new Store();
					expect(model.deals).toBeNull();
					expect(model._relations.deals).toBeUndefined();
				});

				it("instantiates a relation when attributes exist", function() {
					var model = new Store(this.attributes);
					expect(model.deals).toBeArray();
					expect(model.deals.length).toEqual(2);
					expect(model._relations.deals).toBeArray();
					expect(model.deals[0]).toBeInstanceof(Deal);
					expect(model.deals[1]).toBeInstanceof(Deal);
				});

				it("lazily instantiates a relation when attributes exist", function() {
					var model = new Store();
					expect(model.deals).toBeNull();
					expect(model._relations.deals).toBeUndefined();
					model.attributes = this.attributes;
					expect(model.deals).toBeArray();
					expect(model.deals.length).toEqual(2);
					expect(model._relations.deals).toBeArray();
					expect(model.deals[0]).toBeInstanceof(Deal);
					expect(model.deals[1]).toBeInstanceof(Deal);
				});

				it("assigns a relationship by object instance", function() {
					var model = new Store(this.attributes);
					var oldDeals = model.deals;
					var newDeals = [new Deal({id: 3, store_id: 1234})];
					model.deals = newDeals;
					expect(model.relationsAttributes.deals).toBeNull();
					expect(model.changedAttributes.deals).toBeUndefined();
					expect(model.deals).toEqual(newDeals);
					expect(model.deals.length).toEqual(1);
				});
			});

			describe("validation", function() {
				it("sets valid to false when a relationship is invalid", function() {
					var model = new Store({
						id: 1234,
						name: "Expo World",
						deals: [{
							name: "I am not valid"
						},{
							id: 5,
							store_id: 1234,
							name: "I am valid"
						}]
					});

					expect(model.validate()).toBeFalse();
					expect(model.deals[0].valid).toBeFalse();
					expect(model.deals[1].valid).toBeTrue();
					expect(model.errors.deals[0]).toEqual("has errors");
				});

				it("sets valid to true when all relations are valid", function() {
					var model = new Store({
						id: 1234,
						name: "Expo World",
						deals: [{
							id: 6,
							store_id: 1234,
							name: "I am valid"
						},{
							id: 5,
							store_id: 1234,
							name: "I am valid too"
						}]
					});

					expect(model.validate()).toBeTrue();
				});

				it("sets valid to true when there are no relations", function() {
					var model = new Store({
						id: 1234,
						name: "Expo World"
					});

					expect(model.validate()).toBeTrue();
				});

				it("sets valid to false when relations are valid, but main attributes are not", function() {
					var model = new Store({
						id: 1234,
						deals: [{
							id: 6,
							store_id: 1234,
							name: "I am valid"
						},{
							id: 5,
							store_id: 1234,
							name: "I am valid too"
						}]
					});

					expect(model.validate()).toBeFalse();
					expect(model.errors.name).toBeArray();
				});
			});

			describe("serialization", function() {
				beforeEach(function() {
					this.storeWithDealsAndDistributionCenterAttrs = {
						id: 1234,
						deals: [{
							id: 4,
							store_id: 1234,
							name: "Testing1"
						},{
							id: 78,
							store_id: 1234,
							name: "Testing2"
						}],
						distribution_center: {
							id: 9876,
							address: "123 South St",
							postal_code: "12345-1234",
							region: "NE",
							country: "United States of America"
						}
					};

					this.storeWithDealsAttrs = {
						id: 1234,
						deals: [{
							id: 4,
							store_id: 1234,
							name: "Testing1"
						}]
					};

					this.storeWithDistributionCenterAttrs = {
						id: 1234,
						distribution_center: {
							id: 9876,
							address: "123 South St",
							postal_code: "12345-1234",
							region: "NE",
							country: "United States of America"
						}
					};

					this.storeWithOnlyDealsAttrs = {
						deals: [{
							id: 4,
							store_id: 1234,
							name: "Testing1"
						},{
							id: 78,
							store_id: 1234,
							name: "Testing2"
						}]
					};
				});

				describe("queryString", function() {
					it("serializes relations into a namespaced query string", function() {
						var model = new Store(this.storeWithDealsAndDistributionCenterAttrs);
						var queryString = [
							'store[id]=1234',
							'store[deals][0][id]=4',
							'store[deals][0][store_id]=1234',
							'store[deals][0][name]=Testing1',
							'store[deals][1][id]=78',
							'store[deals][1][store_id]=1234',
							'store[deals][1][name]=Testing2',
							'store[distribution_center][id]=9876',
							'store[distribution_center][address]=123%20South%20St',
							'store[distribution_center][postal_code]=12345-1234',
							'store[distribution_center][region]=NE',
							'store[distribution_center][country]=United%20States%20of%20America'
						].sort().join("&");
						var actual = model.toQueryString({rootElement: "store"}).split(/&/g).sort().join("&");
						expect(actual).toEqual(queryString);
					});

					it("skips relations that do not exist", function() {
						var model = new Store(this.storeWithDealsAttrs);
						var queryString = [
							'store[id]=1234',
							'store[deals][0][id]=4',
							'store[deals][0][store_id]=1234',
							'store[deals][0][name]=Testing1'
						].sort().join("&");
						var actual = model.toQueryString({rootElement: "store"}).split(/&/g).sort().join("&");
						expect(actual).toEqual(queryString);
					});
				});

				describe("toXml", function() {
					beforeEach(function() {
						this.store = new Store();
					});

					it("serializes hasOne relationships", function() {
						this.store.attributes = this.storeWithDistributionCenterAttrs;

						var xml = [
							'<store>',
								'<id>1234</id>',
								'<distribution_center>',
									'<id>9876</id>',
									'<address>123 South St</address>',
									'<postal_code>12345-1234</postal_code>',
									'<region>NE</region>',
									'<country>United States of America</country>',
								'</distribution_center>',
							'</store>'
						].join("");
						var action = this.store.toXml({rootElement: "store"});
						expect(action).toEqual(xml);
					});

					it("serializes hasMany relationships", function() {
						this.store.attributes = this.storeWithOnlyDealsAttrs;

						var xml = [
							'<store>',
								'<deals>',
									'<deal>',
										'<id>4</id>',
										'<store_id>1234</store_id>',
										'<name>Testing1</name>',
									'</deal>',
									'<deal>',
										'<id>78</id>',
										'<store_id>1234</store_id>',
										'<name>Testing2</name>',
									'</deal>',
								'</deals>',
							'</store>'
						].join("");

						var action = this.store.toXml({rootElement: "store"});
						expect(action).toEqual(xml);
					});
				});

				describe("toJson", function() {

				});
			});

		});

	});

});<|endoftext|>