mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-01-29 06:27:49 +00:00
Update Backbone tests to 1.1.1.
This commit is contained in:
2
vendor/backbone/LICENSE
vendored
2
vendor/backbone/LICENSE
vendored
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2010-2013 Jeremy Ashkenas, DocumentCloud
|
||||
Copyright (c) 2010-2014 Jeremy Ashkenas, DocumentCloud
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
||||
162
vendor/backbone/backbone.js
vendored
162
vendor/backbone/backbone.js
vendored
@@ -1,20 +1,36 @@
|
||||
// Backbone.js 1.1.0
|
||||
// Backbone.js 1.1.1
|
||||
|
||||
// (c) 2010-2011 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
// (c) 2011-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||
// (c) 2010-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||
// Backbone may be freely distributed under the MIT license.
|
||||
// For all details and documentation:
|
||||
// http://backbonejs.org
|
||||
|
||||
(function(){
|
||||
(function(root, factory) {
|
||||
|
||||
// Set up Backbone appropriately for the environment. Start with AMD.
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
|
||||
// Export global even in AMD case in case this script is loaded with
|
||||
// others that may still expect a global Backbone.
|
||||
root.Backbone = factory(root, exports, _, $);
|
||||
});
|
||||
|
||||
// Next for Node.js or CommonJS. jQuery may not be needed as a module.
|
||||
} else if (typeof exports !== 'undefined') {
|
||||
var _ = require('underscore'), $;
|
||||
try { $ = require('jquery'); } catch(e) {}
|
||||
factory(root, exports, _, $);
|
||||
|
||||
// Finally, as a browser global.
|
||||
} else {
|
||||
root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
|
||||
}
|
||||
|
||||
}(this, function(root, Backbone, _, $) {
|
||||
|
||||
// Initial Setup
|
||||
// -------------
|
||||
|
||||
// Save a reference to the global object (`window` in the browser, `exports`
|
||||
// on the server).
|
||||
var root = this;
|
||||
|
||||
// Save the previous value of the `Backbone` variable, so that it can be
|
||||
// restored later on, if `noConflict` is used.
|
||||
var previousBackbone = root.Backbone;
|
||||
@@ -25,25 +41,12 @@
|
||||
var slice = array.slice;
|
||||
var splice = array.splice;
|
||||
|
||||
// The top-level namespace. All public Backbone classes and modules will
|
||||
// be attached to this. Exported for both the browser and the server.
|
||||
var Backbone;
|
||||
if (typeof exports !== 'undefined') {
|
||||
Backbone = exports;
|
||||
} else {
|
||||
Backbone = root.Backbone = {};
|
||||
}
|
||||
|
||||
// Current version of the library. Keep in sync with `package.json`.
|
||||
Backbone.VERSION = '1.1.0';
|
||||
|
||||
// Require Underscore, if we're on the server, and it's not already present.
|
||||
var _ = root._;
|
||||
if (!_ && (typeof require !== 'undefined')) _ = require('underscore');
|
||||
Backbone.VERSION = '1.1.1';
|
||||
|
||||
// For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
|
||||
// the `$` variable.
|
||||
Backbone.$ = root.jQuery || root.Zepto || root.ender || root.$;
|
||||
Backbone.$ = $;
|
||||
|
||||
// Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
|
||||
// to its previous owner. Returns a reference to this Backbone object.
|
||||
@@ -109,7 +112,7 @@
|
||||
var retain, ev, events, names, i, l, j, k;
|
||||
if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;
|
||||
if (!name && !callback && !context) {
|
||||
this._events = {};
|
||||
this._events = void 0;
|
||||
return this;
|
||||
}
|
||||
names = name ? [name] : _.keys(this._events);
|
||||
@@ -205,7 +208,7 @@
|
||||
case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
|
||||
case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
|
||||
case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
|
||||
default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
|
||||
default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -350,7 +353,7 @@
|
||||
|
||||
// Trigger all relevant attribute changes.
|
||||
if (!silent) {
|
||||
if (changes.length) this._pending = true;
|
||||
if (changes.length) this._pending = options;
|
||||
for (var i = 0, l = changes.length; i < l; i++) {
|
||||
this.trigger('change:' + changes[i], this, current[changes[i]], options);
|
||||
}
|
||||
@@ -361,6 +364,7 @@
|
||||
if (changing) return this;
|
||||
if (!silent) {
|
||||
while (this._pending) {
|
||||
options = this._pending;
|
||||
this._pending = false;
|
||||
this.trigger('change', this, options);
|
||||
}
|
||||
@@ -528,9 +532,12 @@
|
||||
// using Backbone's restful methods, override this to change the endpoint
|
||||
// that will be called.
|
||||
url: function() {
|
||||
var base = _.result(this, 'urlRoot') || _.result(this.collection, 'url') || urlError();
|
||||
var base =
|
||||
_.result(this, 'urlRoot') ||
|
||||
_.result(this.collection, 'url') ||
|
||||
urlError();
|
||||
if (this.isNew()) return base;
|
||||
return base + (base.charAt(base.length - 1) === '/' ? '' : '/') + encodeURIComponent(this.id);
|
||||
return base.replace(/([^\/])$/, '$1/') + encodeURIComponent(this.id);
|
||||
},
|
||||
|
||||
// **parse** converts a response into the hash of attributes to be `set` on
|
||||
@@ -546,7 +553,7 @@
|
||||
|
||||
// A model is new if it has never been saved to the server, and lacks an id.
|
||||
isNew: function() {
|
||||
return this.id == null;
|
||||
return !this.has(this.idAttribute);
|
||||
},
|
||||
|
||||
// Check if the model is currently in a valid state.
|
||||
@@ -650,7 +657,7 @@
|
||||
options.index = index;
|
||||
model.trigger('remove', model, this, options);
|
||||
}
|
||||
this._removeReference(model);
|
||||
this._removeReference(model, options);
|
||||
}
|
||||
return singular ? models[0] : models;
|
||||
},
|
||||
@@ -676,11 +683,11 @@
|
||||
// Turn bare objects into model references, and prevent invalid models
|
||||
// from being added.
|
||||
for (i = 0, l = models.length; i < l; i++) {
|
||||
attrs = models[i];
|
||||
attrs = models[i] || {};
|
||||
if (attrs instanceof Model) {
|
||||
id = model = attrs;
|
||||
} else {
|
||||
id = attrs[targetModel.prototype.idAttribute];
|
||||
id = attrs[targetModel.prototype.idAttribute || 'id'];
|
||||
}
|
||||
|
||||
// If a duplicate is found, prevent it from being added and
|
||||
@@ -700,14 +707,13 @@
|
||||
model = models[i] = this._prepareModel(attrs, options);
|
||||
if (!model) continue;
|
||||
toAdd.push(model);
|
||||
|
||||
// Listen to added models' events, and index models for lookup by
|
||||
// `id` and by `cid`.
|
||||
model.on('all', this._onModelEvent, this);
|
||||
this._byId[model.cid] = model;
|
||||
if (model.id != null) this._byId[model.id] = model;
|
||||
this._addReference(model, options);
|
||||
}
|
||||
if (order) order.push(existing || model);
|
||||
|
||||
// Do not add multiple models with the same `id`.
|
||||
model = existing || model;
|
||||
if (order && (model.isNew() || !modelMap[model.id])) order.push(model);
|
||||
modelMap[model.id] = true;
|
||||
}
|
||||
|
||||
// Remove nonexistent models if appropriate.
|
||||
@@ -745,7 +751,7 @@
|
||||
}
|
||||
if (sort || (order && order.length)) this.trigger('sort', this, options);
|
||||
}
|
||||
|
||||
|
||||
// Return the added (or merged) model (or models).
|
||||
return singular ? models[0] : models;
|
||||
},
|
||||
@@ -757,7 +763,7 @@
|
||||
reset: function(models, options) {
|
||||
options || (options = {});
|
||||
for (var i = 0, l = this.models.length; i < l; i++) {
|
||||
this._removeReference(this.models[i]);
|
||||
this._removeReference(this.models[i], options);
|
||||
}
|
||||
options.previousModels = this.models;
|
||||
this._reset();
|
||||
@@ -798,7 +804,7 @@
|
||||
// Get a model from the set by id.
|
||||
get: function(obj) {
|
||||
if (obj == null) return void 0;
|
||||
return this._byId[obj.id] || this._byId[obj.cid] || this._byId[obj];
|
||||
return this._byId[obj] || this._byId[obj.id] || this._byId[obj.cid];
|
||||
},
|
||||
|
||||
// Get the model at the given index.
|
||||
@@ -874,7 +880,7 @@
|
||||
if (!options.wait) this.add(model, options);
|
||||
var collection = this;
|
||||
var success = options.success;
|
||||
options.success = function(model, resp, options) {
|
||||
options.success = function(model, resp) {
|
||||
if (options.wait) collection.add(model, options);
|
||||
if (success) success(model, resp, options);
|
||||
};
|
||||
@@ -904,10 +910,7 @@
|
||||
// Prepare a hash of attributes (or other model) to be added to this
|
||||
// collection.
|
||||
_prepareModel: function(attrs, options) {
|
||||
if (attrs instanceof Model) {
|
||||
if (!attrs.collection) attrs.collection = this;
|
||||
return attrs;
|
||||
}
|
||||
if (attrs instanceof Model) return attrs;
|
||||
options = options ? _.clone(options) : {};
|
||||
options.collection = this;
|
||||
var model = new this.model(attrs, options);
|
||||
@@ -916,8 +919,16 @@
|
||||
return false;
|
||||
},
|
||||
|
||||
// Internal method to create a model's ties to a collection.
|
||||
_addReference: function(model, options) {
|
||||
this._byId[model.cid] = model;
|
||||
if (model.id != null) this._byId[model.id] = model;
|
||||
if (!model.collection) model.collection = this;
|
||||
model.on('all', this._onModelEvent, this);
|
||||
},
|
||||
|
||||
// Internal method to sever a model's ties to a collection.
|
||||
_removeReference: function(model) {
|
||||
_removeReference: function(model, options) {
|
||||
if (this === model.collection) delete model.collection;
|
||||
model.off('all', this._onModelEvent, this);
|
||||
},
|
||||
@@ -946,7 +957,7 @@
|
||||
'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
|
||||
'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
|
||||
'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle',
|
||||
'lastIndexOf', 'isEmpty', 'chain'];
|
||||
'lastIndexOf', 'isEmpty', 'chain', 'sample'];
|
||||
|
||||
// Mix in each Underscore method as a proxy to `Collection#models`.
|
||||
_.each(methods, function(method) {
|
||||
@@ -958,7 +969,7 @@
|
||||
});
|
||||
|
||||
// Underscore methods that take a property name as an argument.
|
||||
var attributeMethods = ['groupBy', 'countBy', 'sortBy'];
|
||||
var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy'];
|
||||
|
||||
// Use attributes instead of properties.
|
||||
_.each(attributeMethods, function(method) {
|
||||
@@ -1180,7 +1191,9 @@
|
||||
return xhr;
|
||||
};
|
||||
|
||||
var noXhrPatch = typeof window !== 'undefined' && !!window.ActiveXObject && !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent);
|
||||
var noXhrPatch =
|
||||
typeof window !== 'undefined' && !!window.ActiveXObject &&
|
||||
!(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent);
|
||||
|
||||
// Map from CRUD to HTTP for our default `Backbone.sync` implementation.
|
||||
var methodMap = {
|
||||
@@ -1239,7 +1252,7 @@
|
||||
var router = this;
|
||||
Backbone.history.route(route, function(fragment) {
|
||||
var args = router._extractParameters(route, fragment);
|
||||
callback && callback.apply(router, args);
|
||||
router.execute(callback, args);
|
||||
router.trigger.apply(router, ['route:' + name].concat(args));
|
||||
router.trigger('route', name, args);
|
||||
Backbone.history.trigger('route', router, name, args);
|
||||
@@ -1247,6 +1260,12 @@
|
||||
return this;
|
||||
},
|
||||
|
||||
// Execute a route handler with the provided parameters. This is an
|
||||
// excellent place to do pre-route setup or post-route cleanup.
|
||||
execute: function(callback, args) {
|
||||
if (callback) callback.apply(this, args);
|
||||
},
|
||||
|
||||
// Simple proxy to `Backbone.history` to save a fragment into the history.
|
||||
navigate: function(fragment, options) {
|
||||
Backbone.history.navigate(fragment, options);
|
||||
@@ -1271,10 +1290,10 @@
|
||||
route = route.replace(escapeRegExp, '\\$&')
|
||||
.replace(optionalParam, '(?:$1)?')
|
||||
.replace(namedParam, function(match, optional) {
|
||||
return optional ? match : '([^\/]+)';
|
||||
return optional ? match : '([^/?]+)';
|
||||
})
|
||||
.replace(splatParam, '(.*?)');
|
||||
return new RegExp('^' + route + '$');
|
||||
.replace(splatParam, '([^?]*?)');
|
||||
return new RegExp('^' + route + '(?:\\?(.*))?$');
|
||||
},
|
||||
|
||||
// Given a route, and a URL fragment that it matches, return the array of
|
||||
@@ -1282,7 +1301,9 @@
|
||||
// treated as `null` to normalize cross-browser behavior.
|
||||
_extractParameters: function(route, fragment) {
|
||||
var params = route.exec(fragment).slice(1);
|
||||
return _.map(params, function(param) {
|
||||
return _.map(params, function(param, i) {
|
||||
// Don't decode the search params.
|
||||
if (i === params.length - 1) return param || null;
|
||||
return param ? decodeURIComponent(param) : null;
|
||||
});
|
||||
}
|
||||
@@ -1320,8 +1341,8 @@
|
||||
// Cached regex for removing a trailing slash.
|
||||
var trailingSlash = /\/$/;
|
||||
|
||||
// Cached regex for stripping urls of hash and query.
|
||||
var pathStripper = /[?#].*$/;
|
||||
// Cached regex for stripping urls of hash.
|
||||
var pathStripper = /#.*$/;
|
||||
|
||||
// Has the history handling already been started?
|
||||
History.started = false;
|
||||
@@ -1333,6 +1354,11 @@
|
||||
// twenty times a second.
|
||||
interval: 50,
|
||||
|
||||
// Are we at the app root?
|
||||
atRoot: function() {
|
||||
return this.location.pathname.replace(/[^\/]$/, '$&/') === this.root;
|
||||
},
|
||||
|
||||
// Gets the true hash value. Cannot use location.hash directly due to bug
|
||||
// in Firefox where location.hash will always be decoded.
|
||||
getHash: function(window) {
|
||||
@@ -1345,7 +1371,7 @@
|
||||
getFragment: function(fragment, forcePushState) {
|
||||
if (fragment == null) {
|
||||
if (this._hasPushState || !this._wantsHashChange || forcePushState) {
|
||||
fragment = this.location.pathname;
|
||||
fragment = decodeURI(this.location.pathname + this.location.search);
|
||||
var root = this.root.replace(trailingSlash, '');
|
||||
if (!fragment.indexOf(root)) fragment = fragment.slice(root.length);
|
||||
} else {
|
||||
@@ -1376,7 +1402,8 @@
|
||||
this.root = ('/' + this.root + '/').replace(rootStripper, '/');
|
||||
|
||||
if (oldIE && this._wantsHashChange) {
|
||||
this.iframe = Backbone.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow;
|
||||
var frame = Backbone.$('<iframe src="javascript:0" tabindex="-1">');
|
||||
this.iframe = frame.hide().appendTo('body')[0].contentWindow;
|
||||
this.navigate(fragment);
|
||||
}
|
||||
|
||||
@@ -1394,7 +1421,6 @@
|
||||
// opened by a non-pushState browser.
|
||||
this.fragment = fragment;
|
||||
var loc = this.location;
|
||||
var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root;
|
||||
|
||||
// Transition from hashChange to pushState or vice versa if both are
|
||||
// requested.
|
||||
@@ -1402,17 +1428,17 @@
|
||||
|
||||
// If we've started off with a route from a `pushState`-enabled
|
||||
// browser, but we're currently in a browser that doesn't support it...
|
||||
if (!this._hasPushState && !atRoot) {
|
||||
if (!this._hasPushState && !this.atRoot()) {
|
||||
this.fragment = this.getFragment(null, true);
|
||||
this.location.replace(this.root + this.location.search + '#' + this.fragment);
|
||||
this.location.replace(this.root + '#' + this.fragment);
|
||||
// Return immediately as browser will do redirect to new url
|
||||
return true;
|
||||
|
||||
// Or if we've started out with a hash-based route, but we're currently
|
||||
// in a browser where it could be `pushState`-based instead...
|
||||
} else if (this._hasPushState && atRoot && loc.hash) {
|
||||
} else if (this._hasPushState && this.atRoot() && loc.hash) {
|
||||
this.fragment = this.getHash().replace(routeStripper, '');
|
||||
this.history.replaceState({}, document.title, this.root + this.fragment + loc.search);
|
||||
this.history.replaceState({}, document.title, this.root + this.fragment);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1472,7 +1498,7 @@
|
||||
|
||||
var url = this.root + (fragment = this.getFragment(fragment || ''));
|
||||
|
||||
// Strip the fragment of the query and hash for matching.
|
||||
// Strip the hash for matching.
|
||||
fragment = fragment.replace(pathStripper, '');
|
||||
|
||||
if (this.fragment === fragment) return;
|
||||
@@ -1578,4 +1604,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
return Backbone;
|
||||
|
||||
}));
|
||||
|
||||
95
vendor/backbone/test/collection.js
vendored
95
vendor/backbone/test/collection.js
vendored
@@ -85,6 +85,11 @@
|
||||
equal(col2.get(model.clone()), col2.first());
|
||||
});
|
||||
|
||||
test('get with "undefined" id', function() {
|
||||
var collection = new Backbone.Collection([{id: 1}, {id: 'undefined'}]);
|
||||
equal(collection.get(1).id, 1);
|
||||
}),
|
||||
|
||||
test("update index when id changes", 4, function() {
|
||||
var col = new Backbone.Collection();
|
||||
col.add([
|
||||
@@ -107,7 +112,7 @@
|
||||
equal(col.pluck('label').join(' '), 'a b c d');
|
||||
});
|
||||
|
||||
test("add", 10, function() {
|
||||
test("add", 14, function() {
|
||||
var added, opts, secondAdded;
|
||||
added = opts = secondAdded = null;
|
||||
e = new Backbone.Model({id: 10, label : 'e'});
|
||||
@@ -136,6 +141,18 @@
|
||||
equal(atCol.length, 4);
|
||||
equal(atCol.at(1), e);
|
||||
equal(atCol.last(), h);
|
||||
|
||||
var coll = new Backbone.Collection(new Array(2));
|
||||
var addCount = 0;
|
||||
coll.on('add', function(){
|
||||
addCount += 1;
|
||||
});
|
||||
coll.add([undefined, f, g]);
|
||||
equal(coll.length, 5);
|
||||
equal(addCount, 3);
|
||||
coll.add(new Array(4));
|
||||
equal(coll.length, 9);
|
||||
equal(addCount, 7);
|
||||
});
|
||||
|
||||
test("add multiple models", 6, function() {
|
||||
@@ -535,7 +552,7 @@
|
||||
equal(coll.findWhere({a: 4}), void 0);
|
||||
});
|
||||
|
||||
test("Underscore methods", 14, function() {
|
||||
test("Underscore methods", 16, function() {
|
||||
equal(col.map(function(model){ return model.get('label'); }).join(' '), 'a b c d');
|
||||
equal(col.any(function(model){ return model.id === 100; }), false);
|
||||
equal(col.any(function(model){ return model.id === 0; }), true);
|
||||
@@ -554,9 +571,12 @@
|
||||
.value(),
|
||||
[4, 0]);
|
||||
deepEqual(col.difference([c, d]), [a, b]);
|
||||
ok(col.include(col.sample()));
|
||||
var first = col.first();
|
||||
ok(col.indexBy('id')[first.id] === first);
|
||||
});
|
||||
|
||||
test("reset", 12, function() {
|
||||
test("reset", 16, function() {
|
||||
var resetCount = 0;
|
||||
var models = col.models;
|
||||
col.on('reset', function() { resetCount += 1; });
|
||||
@@ -576,6 +596,15 @@
|
||||
col.reset();
|
||||
equal(col.length, 0);
|
||||
equal(resetCount, 4);
|
||||
|
||||
var f = new Backbone.Model({id: 20, label : 'f'});
|
||||
col.reset([undefined, f]);
|
||||
equal(col.length, 2);
|
||||
equal(resetCount, 5);
|
||||
|
||||
col.reset(new Array(4));
|
||||
equal(col.length, 4);
|
||||
equal(resetCount, 6);
|
||||
});
|
||||
|
||||
test ("reset with different values", function(){
|
||||
@@ -942,20 +971,6 @@
|
||||
strictEqual(c.length, 0);
|
||||
});
|
||||
|
||||
test("set with many models does not overflow the stack", function() {
|
||||
var n = 150000;
|
||||
var collection = new Backbone.Collection();
|
||||
var models = [];
|
||||
for (var i = 0; i < n; i++) {
|
||||
models.push({id: i});
|
||||
}
|
||||
collection.set(models);
|
||||
equal(collection.length, n);
|
||||
collection.reset();
|
||||
collection.set(models, {at: 0});
|
||||
equal(collection.length, n);
|
||||
});
|
||||
|
||||
test("set with only cids", 3, function() {
|
||||
var m1 = new Backbone.Model;
|
||||
var m2 = new Backbone.Model;
|
||||
@@ -1274,4 +1289,50 @@
|
||||
equal(job.items.get(2).subItems.get(3).get('subName'), 'NewThree');
|
||||
});
|
||||
|
||||
test('_addReference binds all collection events & adds to the lookup hashes', 9, function() {
|
||||
|
||||
var calls = {add: 0, remove: 0};
|
||||
|
||||
var Collection = Backbone.Collection.extend({
|
||||
|
||||
_addReference: function(model) {
|
||||
Backbone.Collection.prototype._addReference.apply(this, arguments);
|
||||
calls.add++;
|
||||
equal(model, this._byId[model.id]);
|
||||
equal(model, this._byId[model.cid]);
|
||||
equal(model._events.all.length, 1);
|
||||
},
|
||||
|
||||
_removeReference: function(model) {
|
||||
Backbone.Collection.prototype._removeReference.apply(this, arguments);
|
||||
calls.remove++;
|
||||
equal(this._byId[model.id], void 0);
|
||||
equal(this._byId[model.cid], void 0);
|
||||
equal(model.collection, void 0);
|
||||
equal(model._events.all, void 0);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var collection = new Collection();
|
||||
var model = collection.add({id: 1});
|
||||
collection.remove(model);
|
||||
|
||||
equal(calls.add, 1);
|
||||
equal(calls.remove, 1);
|
||||
|
||||
});
|
||||
|
||||
test('Do not allow duplicate models to be `add`ed or `set`', function() {
|
||||
var c = new Backbone.Collection();
|
||||
|
||||
c.add([{id: 1}, {id: 1}]);
|
||||
equal(c.length, 1);
|
||||
equal(c.models.length, 1);
|
||||
|
||||
c.set([{id: 1}, {id: 1}]);
|
||||
equal(c.length, 1);
|
||||
equal(c.models.length, 1);
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
8
vendor/backbone/test/environment.js
vendored
8
vendor/backbone/test/environment.js
vendored
@@ -4,10 +4,16 @@
|
||||
var ajax = Backbone.ajax;
|
||||
var emulateHTTP = Backbone.emulateHTTP;
|
||||
var emulateJSON = Backbone.emulateJSON;
|
||||
var history = window.history;
|
||||
var pushState = history.pushState;
|
||||
var replaceState = history.replaceState;
|
||||
|
||||
QUnit.testStart(function() {
|
||||
var env = this.config.current.testEnvironment;
|
||||
|
||||
// We never want to actually call these during tests.
|
||||
history.pushState = history.replaceState = function(){};
|
||||
|
||||
// Capture ajax settings for comparison.
|
||||
Backbone.ajax = function(settings) {
|
||||
env.ajaxSettings = settings;
|
||||
@@ -30,6 +36,8 @@
|
||||
Backbone.ajax = ajax;
|
||||
Backbone.emulateHTTP = emulateHTTP;
|
||||
Backbone.emulateJSON = emulateJSON;
|
||||
history.pushState = pushState;
|
||||
history.replaceState = replaceState;
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
2
vendor/backbone/test/events.js
vendored
2
vendor/backbone/test/events.js
vendored
@@ -305,7 +305,7 @@
|
||||
|
||||
test("if callback is truthy but not a function, `on` should throw an error just like jQuery", 1, function() {
|
||||
var view = _.extend({}, Backbone.Events).on('test', 'noop');
|
||||
throws(function() {
|
||||
raises(function() {
|
||||
view.trigger('test');
|
||||
});
|
||||
});
|
||||
|
||||
20
vendor/backbone/test/model.js
vendored
20
vendor/backbone/test/model.js
vendored
@@ -262,6 +262,26 @@
|
||||
model.set({result: void 0});
|
||||
});
|
||||
|
||||
test("nested set triggers with the correct options", function() {
|
||||
var model = new Backbone.Model();
|
||||
var o1 = {};
|
||||
var o2 = {};
|
||||
var o3 = {};
|
||||
model.on('change', function(__, options) {
|
||||
switch (model.get('a')) {
|
||||
case 1:
|
||||
equal(options, o1);
|
||||
return model.set('a', 2, o2);
|
||||
case 2:
|
||||
equal(options, o2);
|
||||
return model.set('a', 3, o3);
|
||||
case 3:
|
||||
equal(options, o3);
|
||||
}
|
||||
});
|
||||
model.set('a', 1, o1);
|
||||
});
|
||||
|
||||
test("multiple unsets", 1, function() {
|
||||
var i = 0;
|
||||
var counter = function(){ i++; };
|
||||
|
||||
90
vendor/backbone/test/router.js
vendored
90
vendor/backbone/test/router.js
vendored
@@ -5,10 +5,10 @@
|
||||
var lastRoute = null;
|
||||
var lastArgs = [];
|
||||
|
||||
function onRoute(router, route, args) {
|
||||
var onRoute = function(router, route, args) {
|
||||
lastRoute = route;
|
||||
lastArgs = args;
|
||||
}
|
||||
};
|
||||
|
||||
var Location = function(href) {
|
||||
this.replace(href);
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
_.extend(Location.prototype, {
|
||||
|
||||
parser: document.createElement('a'),
|
||||
|
||||
replace: function(href) {
|
||||
_.extend(this, _.pick($('<a></a>', {href: href})[0],
|
||||
this.parser.href = href;
|
||||
_.extend(this, _.pick(this.parser,
|
||||
'href',
|
||||
'hash',
|
||||
'host',
|
||||
@@ -64,7 +67,7 @@
|
||||
this.value = value;
|
||||
}
|
||||
};
|
||||
_.bindAll(ExternalObject);
|
||||
_.bindAll(ExternalObject, 'routingFunction');
|
||||
|
||||
var Router = Backbone.Router.extend({
|
||||
|
||||
@@ -87,7 +90,7 @@
|
||||
":repo/compare/*from...*to": "github",
|
||||
"decode/:named/*splat": "decode",
|
||||
"*first/complex-*part/*rest": "complex",
|
||||
":entity?*args": "query",
|
||||
"query/:entity": "query",
|
||||
"function/:value": ExternalObject.routingFunction,
|
||||
"*anything": "anything"
|
||||
},
|
||||
@@ -208,6 +211,11 @@
|
||||
equal(router.page, '20');
|
||||
});
|
||||
|
||||
test("routes via navigate with params", 1, function() {
|
||||
Backbone.history.navigate('query/test?a=b', {trigger: true});
|
||||
equal(router.queryArgs, 'a=b');
|
||||
});
|
||||
|
||||
test("routes via navigate for backwards-compatibility", 2, function() {
|
||||
Backbone.history.navigate('search/manhattan/p20', true);
|
||||
equal(router.query, 'manhattan');
|
||||
@@ -285,7 +293,7 @@
|
||||
});
|
||||
|
||||
test("routes (query)", 5, function() {
|
||||
location.replace('http://example.com#mandel?a=b&c=d');
|
||||
location.replace('http://example.com#query/mandel?a=b&c=d');
|
||||
Backbone.history.checkUrl();
|
||||
equal(router.entity, 'mandel');
|
||||
equal(router.queryArgs, 'a=b&c=d');
|
||||
@@ -535,7 +543,7 @@
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root/x/y?a=b');
|
||||
location.replace = function(url) {
|
||||
strictEqual(url, '/root/?a=b#x/y');
|
||||
strictEqual(url, '/root/#x/y?a=b');
|
||||
};
|
||||
Backbone.history = _.extend(new Backbone.History, {
|
||||
location: location,
|
||||
@@ -552,7 +560,7 @@
|
||||
|
||||
test("#1695 - hashChange to pushState with search.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root?a=b#x/y');
|
||||
location.replace('http://example.com/root#x/y?a=b');
|
||||
Backbone.history = _.extend(new Backbone.History, {
|
||||
location: location,
|
||||
history: {
|
||||
@@ -601,7 +609,7 @@
|
||||
test("#2062 - Trigger 'route' event on router instance.", 2, function() {
|
||||
router.on('route', function(name, args) {
|
||||
strictEqual(name, 'routeEvent');
|
||||
deepEqual(args, ['x']);
|
||||
deepEqual(args, ['x', null]);
|
||||
});
|
||||
location.replace('http://example.com#route-event/x');
|
||||
Backbone.history.checkUrl();
|
||||
@@ -684,7 +692,7 @@
|
||||
}
|
||||
});
|
||||
location.replace('http://example.com/root/path');
|
||||
Backbone.history.start({pushState: true, root: 'root'});
|
||||
Backbone.history.start({pushState: true, hashChange: false, root: 'root'});
|
||||
Backbone.history.navigate('');
|
||||
});
|
||||
|
||||
@@ -699,7 +707,7 @@
|
||||
}
|
||||
});
|
||||
location.replace('http://example.com/path');
|
||||
Backbone.history.start({pushState: true});
|
||||
Backbone.history.start({pushState: true, hashChange: false});
|
||||
Backbone.history.navigate('');
|
||||
});
|
||||
|
||||
@@ -722,8 +730,66 @@
|
||||
var router = new Router;
|
||||
|
||||
location.replace('http://example.com/');
|
||||
Backbone.history.start({pushState: true});
|
||||
Backbone.history.start({pushState: true, hashChange: false});
|
||||
Backbone.history.navigate('path?query#hash', true);
|
||||
});
|
||||
|
||||
test('Do not decode the search params.', function() {
|
||||
var Router = Backbone.Router.extend({
|
||||
routes: {
|
||||
path: function(params){
|
||||
strictEqual(params, 'x=y%20z');
|
||||
}
|
||||
}
|
||||
});
|
||||
var router = new Router;
|
||||
Backbone.history.navigate('path?x=y%20z', true);
|
||||
});
|
||||
|
||||
test('Navigate to a hash url.', function() {
|
||||
Backbone.history.stop();
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.start({pushState: true});
|
||||
var Router = Backbone.Router.extend({
|
||||
routes: {
|
||||
path: function(params) {
|
||||
strictEqual(params, 'x=y');
|
||||
}
|
||||
}
|
||||
});
|
||||
var router = new Router;
|
||||
location.replace('http://example.com/path?x=y#hash');
|
||||
Backbone.history.checkUrl();
|
||||
});
|
||||
|
||||
test('#navigate to a hash url.', function() {
|
||||
Backbone.history.stop();
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.start({pushState: true});
|
||||
var Router = Backbone.Router.extend({
|
||||
routes: {
|
||||
path: function(params) {
|
||||
strictEqual(params, 'x=y');
|
||||
}
|
||||
}
|
||||
});
|
||||
var router = new Router;
|
||||
Backbone.history.navigate('path?x=y#hash', true);
|
||||
});
|
||||
|
||||
test('unicode pathname', 1, function() {
|
||||
location.replace('http://example.com/myyjä');
|
||||
Backbone.history.stop();
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
var Router = Backbone.Router.extend({
|
||||
routes: {
|
||||
myyjä: function() {
|
||||
ok(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
var router = new Router;
|
||||
Backbone.history.start({pushState: true});
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
42
vendor/backbone/test/view.js
vendored
42
vendor/backbone/test/view.js
vendored
@@ -39,23 +39,23 @@
|
||||
test("delegateEvents", 6, function() {
|
||||
var counter1 = 0, counter2 = 0;
|
||||
|
||||
var view = new Backbone.View({el: '<p><a id="test"></a></p>'});
|
||||
var view = new Backbone.View({el: '#testElement'});
|
||||
view.increment = function(){ counter1++; };
|
||||
view.$el.on('click', function(){ counter2++; });
|
||||
|
||||
var events = {'click #test': 'increment'};
|
||||
var events = {'click h1': 'increment'};
|
||||
|
||||
view.delegateEvents(events);
|
||||
view.$('#test').trigger('click');
|
||||
view.$('h1').trigger('click');
|
||||
equal(counter1, 1);
|
||||
equal(counter2, 1);
|
||||
|
||||
view.$('#test').trigger('click');
|
||||
view.$('h1').trigger('click');
|
||||
equal(counter1, 2);
|
||||
equal(counter2, 2);
|
||||
|
||||
view.delegateEvents(events);
|
||||
view.$('#test').trigger('click');
|
||||
view.$('h1').trigger('click');
|
||||
equal(counter1, 3);
|
||||
equal(counter2, 3);
|
||||
});
|
||||
@@ -92,24 +92,24 @@
|
||||
test("undelegateEvents", 6, function() {
|
||||
var counter1 = 0, counter2 = 0;
|
||||
|
||||
var view = new Backbone.View({el: '<p><a id="test"></a></p>'});
|
||||
var view = new Backbone.View({el: '#testElement'});
|
||||
view.increment = function(){ counter1++; };
|
||||
view.$el.on('click', function(){ counter2++; });
|
||||
|
||||
var events = {'click #test': 'increment'};
|
||||
var events = {'click h1': 'increment'};
|
||||
|
||||
view.delegateEvents(events);
|
||||
view.$('#test').trigger('click');
|
||||
view.$('h1').trigger('click');
|
||||
equal(counter1, 1);
|
||||
equal(counter2, 1);
|
||||
|
||||
view.undelegateEvents();
|
||||
view.$('#test').trigger('click');
|
||||
view.$('h1').trigger('click');
|
||||
equal(counter1, 1);
|
||||
equal(counter2, 2);
|
||||
|
||||
view.delegateEvents(events);
|
||||
view.$('#test').trigger('click');
|
||||
view.$('h1').trigger('click');
|
||||
equal(counter1, 2);
|
||||
equal(counter2, 3);
|
||||
});
|
||||
@@ -218,7 +218,7 @@
|
||||
$('body').trigger('fake$event').trigger('fake$event');
|
||||
equal(count, 2);
|
||||
|
||||
$('body').unbind('.namespaced');
|
||||
$('body').off('.namespaced');
|
||||
$('body').trigger('fake$event');
|
||||
equal(count, 2);
|
||||
});
|
||||
@@ -304,28 +304,24 @@
|
||||
ok(view.$el.has('a'));
|
||||
});
|
||||
|
||||
test("events passed in options", 2, function() {
|
||||
test("events passed in options", 1, function() {
|
||||
var counter = 0;
|
||||
|
||||
var View = Backbone.View.extend({
|
||||
el: '<p><a id="test"></a></p>',
|
||||
el: '#testElement',
|
||||
increment: function() {
|
||||
counter++;
|
||||
}
|
||||
});
|
||||
|
||||
var view = new View({events:{'click #test':'increment'}});
|
||||
var view2 = new View({events:function(){
|
||||
return {'click #test':'increment'};
|
||||
}});
|
||||
var view = new View({
|
||||
events: {
|
||||
'click h1': 'increment'
|
||||
}
|
||||
});
|
||||
|
||||
view.$('#test').trigger('click');
|
||||
view2.$('#test').trigger('click');
|
||||
view.$('h1').trigger('click').trigger('click');
|
||||
equal(counter, 2);
|
||||
|
||||
view.$('#test').trigger('click');
|
||||
view2.$('#test').trigger('click');
|
||||
equal(counter, 4);
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user