diff --git a/test/underscore.html b/test/underscore.html index 3e276360c..468fef3ec 100644 --- a/test/underscore.html +++ b/test/underscore.html @@ -30,12 +30,13 @@ QUnit.config.excused = { 'Arrays': { 'drop': [ - 'alias for rest' + 'is an alias for rest' ], 'first': [ - 'can pass an index to first', - '[1,2]', - '0' + 'returns an empty array when n <= 0 (0 case)', + 'returns an empty array when n <= 0 (negative case)', + 'can fetch the first n elements', + 'returns the whole array if n > length' ], 'findIndex': [ 'called with context' @@ -44,29 +45,31 @@ 'called with context' ], 'flatten': [ - 'Flattens empty arrays', + 'supports empty arrays', 'can flatten nested arrays', 'works on an arguments object', - 'Flatten can handle very deep arrays' + 'can handle very deep arrays' ], 'head': [ - 'alias for first' + 'is an alias for first' ], 'indexOf': [ "sorted indexOf doesn't uses binary search", '0' ], 'initial': [ - 'initial can take an index', - 'initial can take a large index', - 'initial works on arguments object' + 'returns all but the last n elements', + 'returns an empty array when n > length', + 'works on an arguments object' ], 'intersection': [ 'can perform an OO-style intersection' ], 'last': [ - 'can pass an index to last', - '0' + 'returns an empty array when n <= 0 (0 case)', + 'returns an empty array when n <= 0 (negative case)', + 'can fetch the last n elements', + 'returns the whole array if n > length' ], 'lastIndexOf': [ 'should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`', @@ -81,19 +84,19 @@ 'range with two arguments a & b, b<a generates an empty array' ], 'rest': [ - 'working rest(0)', - 'rest can take an index', - 'works on arguments object' + 'returns the whole array when index is 0', + 'returns elements starting at the given index', + 'works on an arguments object' ], 'sortedIndex': [ '2', '3' ], 'tail': [ - 'alias for rest' + 'is an alias for rest' ], 'take': [ - 'alias for first' + 'is an alias for first' ], 'uniq': [ 'can find the unique values of an array using a custom iterator', @@ -101,9 +104,6 @@ 'string iterator works with sorted array', 'can use pluck like iterator', 'can use falsey pluck like iterator' - ], - 'unique': [ - 'alias for uniq' ] }, 'Chaining': { @@ -118,21 +118,9 @@ 'lookupIterator with contexts': true, 'Iterating objects with sketchy length properties': true, 'Resistant to collection length and properties changing while iterating': true, - 'all': [ - 'alias for all' - ], - 'any': [ - 'alias for any' - ], - 'collect': [ - 'alias for map' - ], 'countBy': [ 'true' ], - 'detect': [ - 'alias for detect' - ], 'each': [ 'context object property accessed' ], @@ -159,12 +147,6 @@ 'findWhere': [ 'checks properties given function' ], - 'foldl': [ - 'alias for reduce' - ], - 'foldr': [ - 'alias for reduceRight' - ], 'groupBy': [ 'true' ], @@ -237,6 +219,7 @@ }, 'Functions': { 'debounce asap': true, + 'debounce asap cancel': true, 'debounce after system time is set backwards': true, 'debounce asap recursively': true, 'throttle repeatedly with results': true, @@ -281,8 +264,8 @@ 'extending undefined results in undefined' ], 'extendOwn': [ - 'assigning non-objects results in returning the non-object value', - 'assigning undefined results in undefined' + 'extending non-objects results in returning the non-object value', + 'extending undefined results in undefined' ], 'functions': [ 'also looks up functions on the prototype' @@ -339,11 +322,17 @@ var mixinPrereqs = (function() { var aliasToReal = { + 'all': 'every', 'allKeys': 'keysIn', + 'any': 'some', + 'collect': 'map', 'compose': 'flowRight', 'contains': 'includes', + 'detect': 'find', 'extendOwn': 'assign', 'findWhere': 'find', + 'foldl': 'reduce', + 'foldr': 'reduceRight', 'include': 'includes', 'indexBy': 'keyBy', 'inject': 'reduce', @@ -356,6 +345,7 @@ 'pluck': 'map', 'restParam': 'restArgs', 'select': 'filter', + 'unique': 'uniq', 'where': 'filter' }; diff --git a/vendor/backbone/backbone.js b/vendor/backbone/backbone.js index 6b566e943..1909c4635 100644 --- a/vendor/backbone/backbone.js +++ b/vendor/backbone/backbone.js @@ -1,4 +1,4 @@ -// Backbone.js 1.2.1 +// Backbone.js 1.2.3 // (c) 2010-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors // Backbone may be freely distributed under the MIT license. @@ -41,10 +41,10 @@ var previousBackbone = root.Backbone; // Create a local reference to a common array method we'll want to use later. - var slice = [].slice; + var slice = Array.prototype.slice; // Current version of the library. Keep in sync with `package.json`. - Backbone.VERSION = '1.2.1'; + Backbone.VERSION = '1.2.3'; // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns // the `$` variable. @@ -506,7 +506,7 @@ } // Update the `id`. - this.id = this.get(this.idAttribute); + if (this.idAttribute in attrs) this.id = this.get(this.idAttribute); // Trigger all relevant attribute changes. if (!silent) { @@ -764,6 +764,16 @@ var setOptions = {add: true, remove: true, merge: true}; var addOptions = {add: true, remove: false}; + // Splices `insert` into `array` at index `at`. + var splice = function(array, insert, at) { + at = Math.min(Math.max(at, 0), array.length); + var tail = Array(array.length - at); + var length = insert.length; + for (var i = 0; i < tail.length; i++) tail[i] = array[i + at]; + for (i = 0; i < length; i++) array[i + at] = insert[i]; + for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i]; + }; + // Define the Collection's inheritable methods. _.extend(Collection.prototype, Events, { @@ -797,9 +807,9 @@ remove: function(models, options) { options = _.extend({}, options); var singular = !_.isArray(models); - models = singular ? [models] : _.clone(models); + models = singular ? [models] : models.slice(); var removed = this._removeModels(models, options); - if (!options.silent && removed) this.trigger('update', this, options); + if (!options.silent && removed.length) this.trigger('update', this, options); return singular ? removed[0] : removed; }, @@ -808,83 +818,88 @@ // already exist in the collection, as necessary. Similar to **Model#set**, // the core operation for updating the data contained by the collection. set: function(models, options) { + if (models == null) return; + options = _.defaults({}, options, setOptions); if (options.parse && !this._isModel(models)) models = this.parse(models, options); + var singular = !_.isArray(models); models = singular ? (models ? [models] : []) : models.slice(); - var id, model, attrs, existing, sort; + var at = options.at; if (at != null) at = +at; if (at < 0) at += this.length + 1; + + var set = []; + var toAdd = []; + var toRemove = []; + var modelMap = {}; + + var add = options.add; + var merge = options.merge; + var remove = options.remove; + + var sort = false; var sortable = this.comparator && (at == null) && options.sort !== false; var sortAttr = _.isString(this.comparator) ? this.comparator : null; - var toAdd = [], toRemove = [], modelMap = {}; - var add = options.add, merge = options.merge, remove = options.remove; - var order = !sortable && add && remove ? [] : false; - var orderChanged = false; // Turn bare objects into model references, and prevent invalid models // from being added. + var model; for (var i = 0; i < models.length; i++) { - attrs = models[i]; + model = models[i]; // If a duplicate is found, prevent it from being added and // optionally merge it into the existing model. - if (existing = this.get(attrs)) { - if (remove) modelMap[existing.cid] = true; - if (merge && attrs !== existing) { - attrs = this._isModel(attrs) ? attrs.attributes : attrs; + var existing = this.get(model); + if (existing) { + if (merge && model !== existing) { + var attrs = this._isModel(model) ? model.attributes : model; if (options.parse) attrs = existing.parse(attrs, options); existing.set(attrs, options); - if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true; + if (sortable && !sort) sort = existing.hasChanged(sortAttr); + } + if (!modelMap[existing.cid]) { + modelMap[existing.cid] = true; + set.push(existing); } models[i] = existing; // If this is a new, valid model, push it to the `toAdd` list. } else if (add) { - model = models[i] = this._prepareModel(attrs, options); - if (!model) continue; - toAdd.push(model); - this._addReference(model, options); + model = models[i] = this._prepareModel(model, options); + if (model) { + toAdd.push(model); + this._addReference(model, options); + modelMap[model.cid] = true; + set.push(model); + } } - - // Do not add multiple models with the same `id`. - model = existing || model; - if (!model) continue; - id = this.modelId(model.attributes); - if (order && (model.isNew() || !modelMap[id])) { - order.push(model); - - // Check to see if this is actually a new model at this index. - orderChanged = orderChanged || !this.models[i] || model.cid !== this.models[i].cid; - } - - modelMap[id] = true; } // Remove stale models. if (remove) { - for (var i = 0; i < this.length; i++) { - if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model); + for (i = 0; i < this.length; i++) { + model = this.models[i]; + if (!modelMap[model.cid]) toRemove.push(model); } if (toRemove.length) this._removeModels(toRemove, options); } // See if sorting is needed, update `length` and splice in new models. - if (toAdd.length || orderChanged) { + var orderChanged = false; + var replace = !sortable && add && remove; + if (set.length && replace) { + orderChanged = this.length != set.length || _.some(this.models, function(model, index) { + return model !== set[index]; + }); + this.models.length = 0; + splice(this.models, set, 0); + this.length = this.models.length; + } else if (toAdd.length) { if (sortable) sort = true; - this.length += toAdd.length; - if (at != null) { - for (var i = 0; i < toAdd.length; i++) { - this.models.splice(at + i, 0, toAdd[i]); - } - } else { - if (order) this.models.length = 0; - var orderedModels = order || toAdd; - for (var i = 0; i < orderedModels.length; i++) { - this.models.push(orderedModels[i]); - } - } + splice(this.models, toAdd, at == null ? this.length : at); + this.length = this.models.length; } // Silently sort the collection if appropriate. @@ -892,10 +907,10 @@ // Unless silenced, it's time to fire all appropriate add/sort events. if (!options.silent) { - var addOpts = at != null ? _.clone(options) : options; - for (var i = 0; i < toAdd.length; i++) { - if (at != null) addOpts.index = at + i; - (model = toAdd[i]).trigger('add', model, this, addOpts); + for (i = 0; i < toAdd.length; i++) { + if (at != null) options.index = at + i; + model = toAdd[i]; + model.trigger('add', model, this, options); } if (sort || orderChanged) this.trigger('sort', this, options); if (toAdd.length || toRemove.length) this.trigger('update', this, options); @@ -996,7 +1011,7 @@ // Pluck an attribute from each model in the collection. pluck: function(attr) { - return _.invoke(this.models, 'get', attr); + return this.map(attr + ''); }, // Fetch the default set of models for this collection, resetting the @@ -1088,6 +1103,12 @@ this.models.splice(index, 1); this.length--; + // Remove references before triggering 'remove' event to prevent an + // infinite loop. #3693 + delete this._byId[model.cid]; + var id = this.modelId(model.attributes); + if (id != null) delete this._byId[id]; + if (!options.silent) { options.index = index; model.trigger('remove', model, this, options); @@ -1096,7 +1117,7 @@ removed.push(model); this._removeReference(model, options); } - return removed.length ? removed : false; + return removed; }, // Method for checking whether an object should be considered a model for @@ -1127,14 +1148,16 @@ // events simply proxy through. "add" and "remove" events that originate // in other collections are ignored. _onModelEvent: function(event, model, collection, options) { - if ((event === 'add' || event === 'remove') && collection !== this) return; - if (event === 'destroy') this.remove(model, options); - if (event === 'change') { - var prevId = this.modelId(model.previousAttributes()); - var id = this.modelId(model.attributes); - if (prevId !== id) { - if (prevId != null) delete this._byId[prevId]; - if (id != null) this._byId[id] = model; + if (model) { + if ((event === 'add' || event === 'remove') && collection !== this) return; + if (event === 'destroy') this.remove(model, options); + if (event === 'change') { + var prevId = this.modelId(model.previousAttributes()); + var id = this.modelId(model.attributes); + if (prevId !== id) { + if (prevId != null) delete this._byId[prevId]; + if (id != null) this._byId[id] = model; + } } } this.trigger.apply(this, arguments); @@ -1145,14 +1168,14 @@ // Underscore methods that we want to implement on the Collection. // 90% of the core usefulness of Backbone Collections is actually implemented // right here: - var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 4, - foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3, + var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 0, + foldl: 0, inject: 0, reduceRight: 0, foldr: 0, find: 3, detect: 3, filter: 3, select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3, contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3, head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3, without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3, isEmpty: 1, chain: 1, sample: 3, partition: 3, groupBy: 3, countBy: 3, - sortBy: 3, indexBy: 3}; + sortBy: 3, indexBy: 3, findIndex: 3, findLastIndex: 3}; // Mix in each Underscore method as a proxy to `Collection#models`. addUnderscoreMethods(Collection, collectionMethods, 'models'); @@ -1617,7 +1640,7 @@ this.options = _.extend({root: '/'}, this.options, options); this.root = this.options.root; this._wantsHashChange = this.options.hashChange !== false; - this._hasHashChange = 'onhashchange' in window; + this._hasHashChange = 'onhashchange' in window && (document.documentMode === void 0 || document.documentMode > 7); this._useHashChange = this._wantsHashChange && this._hasHashChange; this._wantsPushState = !!this.options.pushState; this._hasPushState = !!(this.history && this.history.pushState); @@ -1841,14 +1864,9 @@ _.extend(child, parent, staticProps); // Set the prototype chain to inherit from `parent`, without calling - // `parent` constructor function. - var Surrogate = function(){ this.constructor = child; }; - Surrogate.prototype = parent.prototype; - child.prototype = new Surrogate; - - // Add prototype properties (instance properties) to the subclass, - // if supplied. - if (protoProps) _.extend(child.prototype, protoProps); + // `parent`'s constructor function and add the prototype properties. + child.prototype = _.create(parent.prototype, protoProps); + child.prototype.constructor = child; // Set a convenience property in case the parent's prototype is needed // later. diff --git a/vendor/backbone/test/collection.js b/vendor/backbone/test/collection.js index c691bc70e..c154566cc 100644 --- a/vendor/backbone/test/collection.js +++ b/vendor/backbone/test/collection.js @@ -2,9 +2,9 @@ var a, b, c, d, e, col, otherCol; - module("Backbone.Collection", { + QUnit.module("Backbone.Collection", { - setup: function() { + beforeEach: function(assert) { a = new Backbone.Model({id: 3, label: 'a'}); b = new Backbone.Model({id: 2, label: 'b'}); c = new Backbone.Model({id: 1, label: 'c'}); @@ -16,33 +16,36 @@ }); - test("new and sort", 6, function() { + QUnit.test("new and sort", function(assert) { + assert.expect(6); var counter = 0; col.on('sort', function(){ counter++; }); - deepEqual(col.pluck('label'), ['a', 'b', 'c', 'd']); + assert.deepEqual(col.pluck('label'), ['a', 'b', 'c', 'd']); col.comparator = function(a, b) { return a.id > b.id ? -1 : 1; }; col.sort(); - equal(counter, 1); - deepEqual(col.pluck('label'), ['a', 'b', 'c', 'd']); + assert.equal(counter, 1); + assert.deepEqual(col.pluck('label'), ['a', 'b', 'c', 'd']); col.comparator = function(model) { return model.id; }; col.sort(); - equal(counter, 2); - deepEqual(col.pluck('label'), ['d', 'c', 'b', 'a']); - equal(col.length, 4); + assert.equal(counter, 2); + assert.deepEqual(col.pluck('label'), ['d', 'c', 'b', 'a']); + assert.equal(col.length, 4); }); - test("String comparator.", 1, function() { + QUnit.test("String comparator.", function(assert) { + assert.expect(1); var collection = new Backbone.Collection([ {id: 3}, {id: 1}, {id: 2} ], {comparator: 'id'}); - deepEqual(collection.pluck('id'), [1, 2, 3]); + assert.deepEqual(collection.pluck('id'), [1, 2, 3]); }); - test("new and parse", 3, function() { + QUnit.test("new and parse", function(assert) { + assert.expect(3); var Collection = Backbone.Collection.extend({ parse : function(data) { return _.filter(data, function(datum) { @@ -52,12 +55,13 @@ }); var models = [{a: 1}, {a: 2}, {a: 3}, {a: 4}]; var collection = new Collection(models, {parse: true}); - strictEqual(collection.length, 2); - strictEqual(collection.first().get('a'), 2); - strictEqual(collection.last().get('a'), 4); + assert.strictEqual(collection.length, 2); + assert.strictEqual(collection.first().get('a'), 2); + assert.strictEqual(collection.last().get('a'), 4); }); - test("clone preserves model and comparator", 3, function() { + QUnit.test("clone preserves model and comparator", function(assert) { + assert.expect(3); var Model = Backbone.Model.extend(); var comparator = function(model){ return model.id; }; @@ -66,64 +70,70 @@ comparator: comparator }).clone(); collection.add({id: 2}); - ok(collection.at(0) instanceof Model); - ok(collection.at(1) instanceof Model); - strictEqual(collection.comparator, comparator); + assert.ok(collection.at(0) instanceof Model); + assert.ok(collection.at(1) instanceof Model); + assert.strictEqual(collection.comparator, comparator); }); - test("get", 6, function() { - equal(col.get(0), d); - equal(col.get(d.clone()), d); - equal(col.get(2), b); - equal(col.get({id: 1}), c); - equal(col.get(c.clone()), c); - equal(col.get(col.first().cid), col.first()); + QUnit.test("get", function(assert) { + assert.expect(6); + assert.equal(col.get(0), d); + assert.equal(col.get(d.clone()), d); + assert.equal(col.get(2), b); + assert.equal(col.get({id: 1}), c); + assert.equal(col.get(c.clone()), c); + assert.equal(col.get(col.first().cid), col.first()); }); - test("get with non-default ids", 5, function() { + QUnit.test("get with non-default ids", function(assert) { + assert.expect(5); var MongoModel = Backbone.Model.extend({idAttribute: '_id'}); var model = new MongoModel({_id: 100}); var col = new Backbone.Collection([model], {model: MongoModel}); - equal(col.get(100), model); - equal(col.get(model.cid), model); - equal(col.get(model), model); - equal(col.get(101), void 0); + assert.equal(col.get(100), model); + assert.equal(col.get(model.cid), model); + assert.equal(col.get(model), model); + assert.equal(col.get(101), void 0); var col2 = new Backbone.Collection(); col2.model = MongoModel; col2.add(model.attributes); - equal(col2.get(model.clone()), col2.first()); + assert.equal(col2.get(model.clone()), col2.first()); }); - test('get with "undefined" id', function() { + QUnit.test('get with "undefined" id', function(assert) { var collection = new Backbone.Collection([{id: 1}, {id: 'undefined'}]); - equal(collection.get(1).id, 1); + assert.equal(collection.get(1).id, 1); }); - test("update index when id changes", 4, function() { + QUnit.test("update index when id changes", function(assert) { + assert.expect(4); var col = new Backbone.Collection(); col.add([ {id : 0, name : 'one'}, {id : 1, name : 'two'} ]); var one = col.get(0); - equal(one.get('name'), 'one'); - col.on('change:name', function (model) { ok(this.get(model)); }); + assert.equal(one.get('name'), 'one'); + col.on('change:name', function (model) { assert.ok(this.get(model)); }); one.set({name: 'dalmatians', id : 101}); - equal(col.get(0), null); - equal(col.get(101).get('name'), 'dalmatians'); + assert.equal(col.get(0), null); + assert.equal(col.get(101).get('name'), 'dalmatians'); }); - test("at", 2, function() { - equal(col.at(2), c); - equal(col.at(-2), c); + QUnit.test("at", function(assert) { + assert.expect(2); + assert.equal(col.at(2), c); + assert.equal(col.at(-2), c); }); - test("pluck", 1, function() { - equal(col.pluck('label').join(' '), 'a b c d'); + QUnit.test("pluck", function(assert) { + assert.expect(1); + assert.equal(col.pluck('label').join(' '), 'a b c d'); }); - test("add", 14, function() { + QUnit.test("add", function(assert) { + assert.expect(14); var added, opts, secondAdded; added = opts = secondAdded = null; e = new Backbone.Model({id: 10, label : 'e'}); @@ -136,45 +146,47 @@ opts = options; }); col.add(e, {amazing: true}); - equal(added, 'e'); - equal(col.length, 5); - equal(col.last(), e); - equal(otherCol.length, 1); - equal(secondAdded, null); - ok(opts.amazing); + assert.equal(added, 'e'); + assert.equal(col.length, 5); + assert.equal(col.last(), e); + assert.equal(otherCol.length, 1); + assert.equal(secondAdded, null); + assert.ok(opts.amazing); var f = new Backbone.Model({id: 20, label : 'f'}); var g = new Backbone.Model({id: 21, label : 'g'}); var h = new Backbone.Model({id: 22, label : 'h'}); var atCol = new Backbone.Collection([f, g, h]); - equal(atCol.length, 3); + assert.equal(atCol.length, 3); atCol.add(e, {at: 1}); - equal(atCol.length, 4); - equal(atCol.at(1), e); - equal(atCol.last(), h); + assert.equal(atCol.length, 4); + assert.equal(atCol.at(1), e); + assert.equal(atCol.last(), h); var coll = new Backbone.Collection(new Array(2)); var addCount = 0; coll.on('add', function(){ - addCount += 1; + addCount += 1; }); coll.add([undefined, f, g]); - equal(coll.length, 5); - equal(addCount, 3); + assert.equal(coll.length, 5); + assert.equal(addCount, 3); coll.add(new Array(4)); - equal(coll.length, 9); - equal(addCount, 7); + assert.equal(coll.length, 9); + assert.equal(addCount, 7); }); - test("add multiple models", 6, function() { + QUnit.test("add multiple models", function(assert) { + assert.expect(6); var col = new Backbone.Collection([{at: 0}, {at: 1}, {at: 9}]); col.add([{at: 2}, {at: 3}, {at: 4}, {at: 5}, {at: 6}, {at: 7}, {at: 8}], {at: 2}); for (var i = 0; i <= 5; i++) { - equal(col.at(i).get('at'), i); + assert.equal(col.at(i).get('at'), i); } }); - test("add; at should have preference over comparator", 1, function() { + QUnit.test("add; at should have preference over comparator", function(assert) { + assert.expect(1); var Col = Backbone.Collection.extend({ comparator: function(a,b) { return a.id > b.id ? -1 : 1; @@ -184,61 +196,73 @@ var col = new Col([{id: 2}, {id: 3}]); col.add(new Backbone.Model({id: 1}), {at: 1}); - equal(col.pluck('id').join(' '), '3 1 2'); + assert.equal(col.pluck('id').join(' '), '3 1 2'); }); - test("can't add model to collection twice", function() { + QUnit.test("add; at should add to the end if the index is out of bounds", function(assert) { + assert.expect(1); + var col = new Backbone.Collection([{id: 2}, {id: 3}]); + col.add(new Backbone.Model({id: 1}), {at: 5}); + + assert.equal(col.pluck('id').join(' '), '2 3 1'); + }); + + QUnit.test("can't add model to collection twice", function(assert) { var col = new Backbone.Collection([{id: 1}, {id: 2}, {id: 1}, {id: 2}, {id: 3}]); - equal(col.pluck('id').join(' '), '1 2 3'); + assert.equal(col.pluck('id').join(' '), '1 2 3'); }); - test("can't add different model with same id to collection twice", 1, function() { + QUnit.test("can't add different model with same id to collection twice", function(assert) { + assert.expect(1); var col = new Backbone.Collection; col.unshift({id: 101}); col.add({id: 101}); - equal(col.length, 1); + assert.equal(col.length, 1); }); - test("merge in duplicate models with {merge: true}", 3, function() { + QUnit.test("merge in duplicate models with {merge: true}", function(assert) { + assert.expect(3); var col = new Backbone.Collection; col.add([{id: 1, name: 'Moe'}, {id: 2, name: 'Curly'}, {id: 3, name: 'Larry'}]); col.add({id: 1, name: 'Moses'}); - equal(col.first().get('name'), 'Moe'); + assert.equal(col.first().get('name'), 'Moe'); col.add({id: 1, name: 'Moses'}, {merge: true}); - equal(col.first().get('name'), 'Moses'); + assert.equal(col.first().get('name'), 'Moses'); col.add({id: 1, name: 'Tim'}, {merge: true, silent: true}); - equal(col.first().get('name'), 'Tim'); + assert.equal(col.first().get('name'), 'Tim'); }); - test("add model to multiple collections", 10, function() { + QUnit.test("add model to multiple collections", function(assert) { + assert.expect(10); var counter = 0; var e = new Backbone.Model({id: 10, label : 'e'}); e.on('add', function(model, collection) { counter++; - equal(e, model); + assert.equal(e, model); if (counter > 1) { - equal(collection, colF); + assert.equal(collection, colF); } else { - equal(collection, colE); + assert.equal(collection, colE); } }); var colE = new Backbone.Collection([]); colE.on('add', function(model, collection) { - equal(e, model); - equal(colE, collection); + assert.equal(e, model); + assert.equal(colE, collection); }); var colF = new Backbone.Collection([]); colF.on('add', function(model, collection) { - equal(e, model); - equal(colF, collection); + assert.equal(e, model); + assert.equal(colF, collection); }); colE.add(e); - equal(e.collection, colE); + assert.equal(e.collection, colE); colF.add(e); - equal(e.collection, colE); + assert.equal(e.collection, colE); }); - test("add model with parse", 1, function() { + QUnit.test("add model with parse", function(assert) { + assert.expect(1); var Model = Backbone.Model.extend({ parse: function(obj) { obj.value += 1; @@ -249,10 +273,10 @@ var Col = Backbone.Collection.extend({model: Model}); var col = new Col; col.add({value: 1}, {parse: true}); - equal(col.at(0).get('value'), 2); + assert.equal(col.at(0).get('value'), 2); }); - test("add with parse and merge", function() { + QUnit.test("add with parse and merge", function(assert) { var collection = new Backbone.Collection(); collection.parse = function(attrs) { return _.map(attrs, function(model) { @@ -262,10 +286,11 @@ }; collection.add({id: 1}); collection.add({model: {id: 1, name: 'Alf'}}, {parse: true, merge: true}); - equal(collection.first().get('name'), 'Alf'); + assert.equal(collection.first().get('name'), 'Alf'); }); - test("add model to collection with sort()-style comparator", 3, function() { + QUnit.test("add model to collection with sort()-style comparator", function(assert) { + assert.expect(3); var col = new Backbone.Collection; col.comparator = function(a, b) { return a.get('name') < b.get('name') ? -1 : 1; @@ -276,12 +301,13 @@ col.add(tom); col.add(rob); col.add(tim); - equal(col.indexOf(rob), 0); - equal(col.indexOf(tim), 1); - equal(col.indexOf(tom), 2); + assert.equal(col.indexOf(rob), 0); + assert.equal(col.indexOf(tim), 1); + assert.equal(col.indexOf(tom), 2); }); - test("comparator that depends on `this`", 2, function() { + QUnit.test("comparator that depends on `this`", function(assert) { + assert.expect(2); var col = new Backbone.Collection; col.negative = function(num) { return -num; @@ -290,39 +316,44 @@ return this.negative(a.id); }; col.add([{id: 1}, {id: 2}, {id: 3}]); - deepEqual(col.pluck('id'), [3, 2, 1]); + assert.deepEqual(col.pluck('id'), [3, 2, 1]); col.comparator = function(a, b) { return this.negative(b.id) - this.negative(a.id); }; col.sort(); - deepEqual(col.pluck('id'), [1, 2, 3]); + assert.deepEqual(col.pluck('id'), [1, 2, 3]); }); - test("remove", 10, function() { + QUnit.test("remove", function(assert) { + assert.expect(12); var removed = null; var result = null; col.on('remove', function(model, col, options) { removed = model.get('label'); - equal(options.index, 3); + assert.equal(options.index, 3); + assert.equal(col.get(model), undefined, '#3693: model cannot be fetched from collection'); }); result = col.remove(d); - equal(removed, 'd'); - strictEqual(result, d); + assert.equal(removed, 'd'); + assert.strictEqual(result, d); //if we try to remove d again, it's not going to actually get removed result = col.remove(d); - strictEqual(result, undefined); - equal(col.length, 3); - equal(col.first(), a); + assert.strictEqual(result, undefined); + assert.equal(col.length, 3); + assert.equal(col.first(), a); col.off(); result = col.remove([c, d]); - equal(result.length, 1, 'only returns removed models'); - equal(result[0], c, 'only returns removed models'); + assert.equal(result.length, 1, 'only returns removed models'); + assert.equal(result[0], c, 'only returns removed models'); result = col.remove([c, b]); - equal(result.length, 1, 'only returns removed models'); - equal(result[0], b, 'only returns removed models'); + assert.equal(result.length, 1, 'only returns removed models'); + assert.equal(result[0], b, 'only returns removed models'); + result = col.remove([]); + assert.deepEqual(result, [], 'returns empty array when nothing removed'); }); - test("add and remove return values", 13, function() { + QUnit.test("add and remove return values", function(assert) { + assert.expect(13); var Even = Backbone.Model.extend({ validate: function(attrs) { if (attrs.id % 2 !== 0) return "odd"; @@ -332,56 +363,60 @@ col.model = Even; var list = col.add([{id: 2}, {id: 4}], {validate: true}); - equal(list.length, 2); - ok(list[0] instanceof Backbone.Model); - equal(list[1], col.last()); - equal(list[1].get('id'), 4); + assert.equal(list.length, 2); + assert.ok(list[0] instanceof Backbone.Model); + assert.equal(list[1], col.last()); + assert.equal(list[1].get('id'), 4); list = col.add([{id: 3}, {id: 6}], {validate: true}); - equal(col.length, 3); - equal(list[0], false); - equal(list[1].get('id'), 6); + assert.equal(col.length, 3); + assert.equal(list[0], false); + assert.equal(list[1].get('id'), 6); var result = col.add({id: 6}); - equal(result.cid, list[1].cid); + assert.equal(result.cid, list[1].cid); result = col.remove({id: 6}); - equal(col.length, 2); - equal(result.id, 6); + assert.equal(col.length, 2); + assert.equal(result.id, 6); list = col.remove([{id: 2}, {id: 8}]); - equal(col.length, 1); - equal(list[0].get('id'), 2); - equal(list[1], null); + assert.equal(col.length, 1); + assert.equal(list[0].get('id'), 2); + assert.equal(list[1], null); }); - test("shift and pop", 2, function() { + QUnit.test("shift and pop", function(assert) { + assert.expect(2); var col = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]); - equal(col.shift().get('a'), 'a'); - equal(col.pop().get('c'), 'c'); + assert.equal(col.shift().get('a'), 'a'); + assert.equal(col.pop().get('c'), 'c'); }); - test("slice", 2, function() { + QUnit.test("slice", function(assert) { + assert.expect(2); var col = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]); var array = col.slice(1, 3); - equal(array.length, 2); - equal(array[0].get('b'), 'b'); + assert.equal(array.length, 2); + assert.equal(array[0].get('b'), 'b'); }); - test("events are unbound on remove", 3, function() { + QUnit.test("events are unbound on remove", function(assert) { + assert.expect(3); var counter = 0; var dj = new Backbone.Model(); var emcees = new Backbone.Collection([dj]); emcees.on('change', function(){ counter++; }); dj.set({name : 'Kool'}); - equal(counter, 1); + assert.equal(counter, 1); emcees.reset([]); - equal(dj.collection, undefined); + assert.equal(dj.collection, undefined); dj.set({name : 'Shadow'}); - equal(counter, 1); + assert.equal(counter, 1); }); - test("remove in multiple collections", 7, function() { + QUnit.test("remove in multiple collections", function(assert) { + assert.expect(7); var modelData = { id : 5, title : 'Othello' @@ -394,101 +429,107 @@ }); var colE = new Backbone.Collection([e]); var colF = new Backbone.Collection([f]); - ok(e != f); - ok(colE.length === 1); - ok(colF.length === 1); + assert.ok(e != f); + assert.ok(colE.length === 1); + assert.ok(colF.length === 1); colE.remove(e); - equal(passed, false); - ok(colE.length === 0); + assert.equal(passed, false); + assert.ok(colE.length === 0); colF.remove(e); - ok(colF.length === 0); - equal(passed, true); + assert.ok(colF.length === 0); + assert.equal(passed, true); }); - test("remove same model in multiple collection", 16, function() { + QUnit.test("remove same model in multiple collection", function(assert) { + assert.expect(16); var counter = 0; var e = new Backbone.Model({id: 5, title: 'Othello'}); e.on('remove', function(model, collection) { counter++; - equal(e, model); + assert.equal(e, model); if (counter > 1) { - equal(collection, colE); + assert.equal(collection, colE); } else { - equal(collection, colF); + assert.equal(collection, colF); } }); var colE = new Backbone.Collection([e]); colE.on('remove', function(model, collection) { - equal(e, model); - equal(colE, collection); + assert.equal(e, model); + assert.equal(colE, collection); }); var colF = new Backbone.Collection([e]); colF.on('remove', function(model, collection) { - equal(e, model); - equal(colF, collection); + assert.equal(e, model); + assert.equal(colF, collection); }); - equal(colE, e.collection); + assert.equal(colE, e.collection); colF.remove(e); - ok(colF.length === 0); - ok(colE.length === 1); - equal(counter, 1); - equal(colE, e.collection); + assert.ok(colF.length === 0); + assert.ok(colE.length === 1); + assert.equal(counter, 1); + assert.equal(colE, e.collection); colE.remove(e); - equal(null, e.collection); - ok(colE.length === 0); - equal(counter, 2); + assert.equal(null, e.collection); + assert.ok(colE.length === 0); + assert.equal(counter, 2); }); - test("model destroy removes from all collections", 3, function() { + QUnit.test("model destroy removes from all collections", function(assert) { + assert.expect(3); var e = new Backbone.Model({id: 5, title: 'Othello'}); e.sync = function(method, model, options) { options.success(); }; var colE = new Backbone.Collection([e]); var colF = new Backbone.Collection([e]); e.destroy(); - ok(colE.length === 0); - ok(colF.length === 0); - equal(undefined, e.collection); + assert.ok(colE.length === 0); + assert.ok(colF.length === 0); + assert.equal(undefined, e.collection); }); - test("Colllection: non-persisted model destroy removes from all collections", 3, function() { + QUnit.test("Collection: non-persisted model destroy removes from all collections", function(assert) { + assert.expect(3); var e = new Backbone.Model({title: 'Othello'}); e.sync = function(method, model, options) { throw "should not be called"; }; var colE = new Backbone.Collection([e]); var colF = new Backbone.Collection([e]); e.destroy(); - ok(colE.length === 0); - ok(colF.length === 0); - equal(undefined, e.collection); + assert.ok(colE.length === 0); + assert.ok(colF.length === 0); + assert.equal(undefined, e.collection); }); - test("fetch", 4, function() { + QUnit.test("fetch", function(assert) { + assert.expect(4); var collection = new Backbone.Collection; collection.url = '/test'; collection.fetch(); - equal(this.syncArgs.method, 'read'); - equal(this.syncArgs.model, collection); - equal(this.syncArgs.options.parse, true); + assert.equal(this.syncArgs.method, 'read'); + assert.equal(this.syncArgs.model, collection); + assert.equal(this.syncArgs.options.parse, true); collection.fetch({parse: false}); - equal(this.syncArgs.options.parse, false); + assert.equal(this.syncArgs.options.parse, false); }); - test("fetch with an error response triggers an error event", 1, function () { + QUnit.test("fetch with an error response triggers an error event", function(assert) { + assert.expect(1); var collection = new Backbone.Collection(); collection.on('error', function () { - ok(true); + assert.ok(true); }); collection.sync = function (method, model, options) { options.error(); }; collection.fetch(); }); - test("#3283 - fetch with an error response calls error with context", 1, function () { + QUnit.test("#3283 - fetch with an error response calls error with context", function(assert) { + assert.expect(1); var collection = new Backbone.Collection(); var obj = {}; var options = { context: obj, error: function() { - equal(this, obj); + assert.equal(this, obj); } }; collection.sync = function (method, model, options) { @@ -497,7 +538,8 @@ collection.fetch(options); }); - test("ensure fetch only parses once", 1, function() { + QUnit.test("ensure fetch only parses once", function(assert) { + assert.expect(1); var collection = new Backbone.Collection; var counter = 0; collection.parse = function(models) { @@ -506,21 +548,23 @@ }; collection.url = '/test'; collection.fetch(); - this.syncArgs.options.success(); - equal(counter, 1); + this.syncArgs.options.success([]); + assert.equal(counter, 1); }); - test("create", 4, function() { + QUnit.test("create", function(assert) { + assert.expect(4); var collection = new Backbone.Collection; collection.url = '/test'; var model = collection.create({label: 'f'}, {wait: true}); - equal(this.syncArgs.method, 'create'); - equal(this.syncArgs.model, model); - equal(model.get('label'), 'f'); - equal(model.collection, collection); + assert.equal(this.syncArgs.method, 'create'); + assert.equal(this.syncArgs.model, model); + assert.equal(model.get('label'), 'f'); + assert.equal(model.collection, collection); }); - test("create with validate:true enforces validation", 3, function() { + QUnit.test("create with validate:true enforces validation", function(assert) { + assert.expect(3); var ValidatingModel = Backbone.Model.extend({ validate: function(attrs) { return "fail"; @@ -531,13 +575,14 @@ }); var col = new ValidatingCollection(); col.on('invalid', function (collection, error, options) { - equal(error, "fail"); - equal(options.validationError, 'fail'); + assert.equal(error, "fail"); + assert.equal(options.validationError, 'fail'); }); - equal(col.create({"foo":"bar"}, {validate:true}), false); + assert.equal(col.create({"foo":"bar"}, {validate:true}), false); }); - test("create will pass extra options to success callback", 1, function () { + QUnit.test("create will pass extra options to success callback", function(assert) { + assert.expect(1); var Model = Backbone.Model.extend({ sync: function (method, model, options) { _.extend(options, {specialSync: true}); @@ -553,19 +598,19 @@ var collection = new Collection; var success = function (model, response, options) { - ok(options.specialSync, "Options were passed correctly to callback"); + assert.ok(options.specialSync, "Options were passed correctly to callback"); }; collection.create({}, {success: success}); this.ajaxSettings.success(); - }); - test("create with wait:true should not call collection.parse", 0, function() { + QUnit.test("create with wait:true should not call collection.parse", function(assert) { + assert.expect(0); var Collection = Backbone.Collection.extend({ url: '/test', parse: function () { - ok(false); + assert.ok(false); } }); @@ -575,7 +620,7 @@ this.ajaxSettings.success(); }); - test("a failing create returns model with errors", function() { + QUnit.test("a failing create returns model with errors", function(assert) { var ValidatingModel = Backbone.Model.extend({ validate: function(attrs) { return "fail"; @@ -586,25 +631,28 @@ }); var col = new ValidatingCollection(); var m = col.create({"foo":"bar"}); - equal(m.validationError, 'fail'); - equal(col.length, 1); + assert.equal(m.validationError, 'fail'); + assert.equal(col.length, 1); }); - test("initialize", 1, function() { + QUnit.test("initialize", function(assert) { + assert.expect(1); var Collection = Backbone.Collection.extend({ initialize: function() { this.one = 1; } }); var coll = new Collection; - equal(coll.one, 1); + assert.equal(coll.one, 1); }); - test("toJSON", 1, function() { - equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]'); + QUnit.test("toJSON", function(assert) { + assert.expect(1); + assert.equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]'); }); - test("where and findWhere", 8, function() { + QUnit.test("where and findWhere", function(assert) { + assert.expect(8); var model = new Backbone.Model({a: 1}); var coll = new Backbone.Collection([ model, @@ -613,46 +661,50 @@ {a: 2, b: 2}, {a: 3} ]); - equal(coll.where({a: 1}).length, 3); - equal(coll.where({a: 2}).length, 1); - equal(coll.where({a: 3}).length, 1); - equal(coll.where({b: 1}).length, 0); - equal(coll.where({b: 2}).length, 2); - equal(coll.where({a: 1, b: 2}).length, 1); - equal(coll.findWhere({a: 1}), model); - equal(coll.findWhere({a: 4}), void 0); + assert.equal(coll.where({a: 1}).length, 3); + assert.equal(coll.where({a: 2}).length, 1); + assert.equal(coll.where({a: 3}).length, 1); + assert.equal(coll.where({b: 1}).length, 0); + assert.equal(coll.where({b: 2}).length, 2); + assert.equal(coll.where({a: 1, b: 2}).length, 1); + assert.equal(coll.findWhere({a: 1}), model); + assert.equal(coll.findWhere({a: 4}), void 0); }); - test("Underscore methods", 19, function() { - equal(col.map(function(model){ return model.get('label'); }).join(' '), 'a b c d'); - equal(col.some(function(model){ return model.id === 100; }), false); - equal(col.some(function(model){ return model.id === 0; }), true); - equal(col.indexOf(b), 1); - equal(col.size(), 4); - equal(col.rest().length, 3); - ok(!_.includes(col.rest(), a)); - ok(_.includes(col.rest(), d)); - ok(!col.isEmpty()); - ok(!_.includes(col.without(d), d)); + QUnit.test("Underscore methods", function(assert) { + assert.expect(21); + assert.equal(col.map(function(model){ return model.get('label'); }).join(' '), 'a b c d'); + assert.equal(col.some(function(model){ return model.id === 100; }), false); + assert.equal(col.some(function(model){ return model.id === 0; }), true); + assert.equal(col.reduce(function(a, b) {return a.id > b.id ? a : b}).id, 3); + assert.equal(col.reduceRight(function(a, b) {return a.id > b.id ? a : b}).id, 3); + assert.equal(col.indexOf(b), 1); + assert.equal(col.size(), 4); + assert.equal(col.rest().length, 3); + assert.ok(!_.includes(col.rest(), a)); + assert.ok(_.includes(col.rest(), d)); + assert.ok(!col.isEmpty()); + assert.ok(!_.includes(col.without(d), d)); var wrapped = col.chain(); - equal(wrapped.map('id').max().value(), 3); - equal(wrapped.map('id').min().value(), 0); - deepEqual(wrapped - .filter(function(o){ return o.id % 2 === 0; }) - .map(function(o){ return o.id * 2; }) - .value(), - [4, 0]); - deepEqual(col.difference([c, d]), [a, b]); - ok(col.includes(col.sample())); + assert.equal(wrapped.map('id').max().value(), 3); + assert.equal(wrapped.map('id').min().value(), 0); + assert.deepEqual(wrapped + .filter(function(o){ return o.id % 2 === 0; }) + .map(function(o){ return o.id * 2; }) + .value(), + [4, 0]); + assert.deepEqual(col.difference([c, d]), [a, b]); + assert.ok(col.includes(col.sample())); var first = col.first(); - deepEqual(col.groupBy(function(model){ return model.id; })[first.id], [first]); - deepEqual(col.countBy(function(model){ return model.id; }), {0: 1, 1: 1, 2: 1, 3: 1}); - deepEqual(col.sortBy(function(model){ return model.id; })[0], col.at(3)); - ok(col.indexBy('id')[first.id] === first); + assert.deepEqual(col.groupBy(function(model){ return model.id; })[first.id], [first]); + assert.deepEqual(col.countBy(function(model){ return model.id; }), {0: 1, 1: 1, 2: 1, 3: 1}); + assert.deepEqual(col.sortBy(function(model){ return model.id; })[0], col.at(3)); + assert.ok(col.indexBy('id')[first.id] === first); }); - test("Underscore methods with object-style and property-style iteratee", 22, function () { + QUnit.test("Underscore methods with object-style and property-style iteratee", function(assert) { + assert.expect(26); var model = new Backbone.Model({a: 4, b: 1, e: 3}); var coll = new Backbone.Collection([ {a: 1, b: 1}, @@ -660,75 +712,81 @@ {a: 3, b: 1}, model ]); - equal(coll.find({a: 0}), undefined); - deepEqual(coll.find({a: 4}), model); - equal(coll.find('d'), undefined); - deepEqual(coll.find('e'), model); - equal(coll.filter({a: 0}), false); - deepEqual(coll.filter({a: 4}), [model]); - equal(coll.some({a: 0}), false); - equal(coll.some({a: 1}), true); - equal(coll.reject({a: 0}).length, 4); - deepEqual(coll.reject({a: 4}), _.without(coll.models, model)); - equal(coll.every({a: 0}), false); - equal(coll.every({b: 1}), true); - deepEqual(coll.partition({a: 0})[0], []); - deepEqual(coll.partition({a: 0})[1], coll.models); - deepEqual(coll.partition({a: 4})[0], [model]); - deepEqual(coll.partition({a: 4})[1], _.without(coll.models, model)); - deepEqual(coll.map({a: 2}), [false, true, false, false]); - deepEqual(coll.map('a'), [1, 2, 3, 4]); - deepEqual(coll.sortBy('a')[3], model); - deepEqual(coll.sortBy('e')[0], model); - deepEqual(coll.countBy({a: 4}), {'false': 3, 'true': 1}); - deepEqual(coll.countBy('d'), {'undefined': 4}); + assert.equal(coll.find({a: 0}), undefined); + assert.deepEqual(coll.find({a: 4}), model); + assert.equal(coll.find('d'), undefined); + assert.deepEqual(coll.find('e'), model); + assert.equal(coll.filter({a: 0}), false); + assert.deepEqual(coll.filter({a: 4}), [model]); + assert.equal(coll.some({a: 0}), false); + assert.equal(coll.some({a: 1}), true); + assert.equal(coll.reject({a: 0}).length, 4); + assert.deepEqual(coll.reject({a: 4}), _.without(coll.models, model)); + assert.equal(coll.every({a: 0}), false); + assert.equal(coll.every({b: 1}), true); + assert.deepEqual(coll.partition({a: 0})[0], []); + assert.deepEqual(coll.partition({a: 0})[1], coll.models); + assert.deepEqual(coll.partition({a: 4})[0], [model]); + assert.deepEqual(coll.partition({a: 4})[1], _.without(coll.models, model)); + assert.deepEqual(coll.map({a: 2}), [false, true, false, false]); + assert.deepEqual(coll.map('a'), [1, 2, 3, 4]); + assert.deepEqual(coll.sortBy('a')[3], model); + assert.deepEqual(coll.sortBy('e')[0], model); + assert.deepEqual(coll.countBy({a: 4}), {'false': 3, 'true': 1}); + assert.deepEqual(coll.countBy('d'), {'undefined': 4}); + assert.equal(coll.findIndex({b: 1}), 0); + assert.equal(coll.findIndex({b: 9}), -1); + assert.equal(coll.findLastIndex({b: 1}), 3); + assert.equal(coll.findLastIndex({b: 9}), -1); }); - test("reset", 16, function() { + QUnit.test("reset", function(assert) { + assert.expect(16); var resetCount = 0; var models = col.models; col.on('reset', function() { resetCount += 1; }); col.reset([]); - equal(resetCount, 1); - equal(col.length, 0); - equal(col.last(), null); + assert.equal(resetCount, 1); + assert.equal(col.length, 0); + assert.equal(col.last(), null); col.reset(models); - equal(resetCount, 2); - equal(col.length, 4); - equal(col.last(), d); + assert.equal(resetCount, 2); + assert.equal(col.length, 4); + assert.equal(col.last(), d); col.reset(_.map(models, function(m){ return m.attributes; })); - equal(resetCount, 3); - equal(col.length, 4); - ok(col.last() !== d); - ok(_.isEqual(col.last().attributes, d.attributes)); + assert.equal(resetCount, 3); + assert.equal(col.length, 4); + assert.ok(col.last() !== d); + assert.ok(_.isEqual(col.last().attributes, d.attributes)); col.reset(); - equal(col.length, 0); - equal(resetCount, 4); + assert.equal(col.length, 0); + assert.equal(resetCount, 4); var f = new Backbone.Model({id: 20, label : 'f'}); col.reset([undefined, f]); - equal(col.length, 2); - equal(resetCount, 5); + assert.equal(col.length, 2); + assert.equal(resetCount, 5); col.reset(new Array(4)); - equal(col.length, 4); - equal(resetCount, 6); + assert.equal(col.length, 4); + assert.equal(resetCount, 6); }); - test ("reset with different values", function(){ + QUnit.test ("reset with different values", function(assert) { var col = new Backbone.Collection({id: 1}); col.reset({id: 1, a: 1}); - equal(col.get(1).get('a'), 1); + assert.equal(col.get(1).get('a'), 1); }); - test("same references in reset", function() { + QUnit.test("same references in reset", function(assert) { var model = new Backbone.Model({id: 1}); var collection = new Backbone.Collection({id: 1}); collection.reset(model); - equal(collection.get(1), model); + assert.equal(collection.get(1), model); }); - test("reset passes caller options", 3, function() { + QUnit.test("reset passes caller options", function(assert) { + assert.expect(3); var Model = Backbone.Model.extend({ initialize: function(attrs, options) { this.model_parameter = options.model_parameter; @@ -736,44 +794,48 @@ }); var col = new (Backbone.Collection.extend({ model: Model }))(); col.reset([{ astring: "green", anumber: 1 }, { astring: "blue", anumber: 2 }], { model_parameter: 'model parameter' }); - equal(col.length, 2); + assert.equal(col.length, 2); col.each(function(model) { - equal(model.model_parameter, 'model parameter'); + assert.equal(model.model_parameter, 'model parameter'); }); }); - test("reset does not alter options by reference", 2, function() { + QUnit.test("reset does not alter options by reference", function(assert) { + assert.expect(2); var col = new Backbone.Collection([{id:1}]); var origOpts = {}; col.on("reset", function(col, opts){ - equal(origOpts.previousModels, undefined); - equal(opts.previousModels[0].id, 1); + assert.equal(origOpts.previousModels, undefined); + assert.equal(opts.previousModels[0].id, 1); }); col.reset([], origOpts); }); - test("trigger custom events on models", 1, function() { + QUnit.test("trigger custom events on models", function(assert) { + assert.expect(1); var fired = null; a.on("custom", function() { fired = true; }); a.trigger("custom"); - equal(fired, true); + assert.equal(fired, true); }); - test("add does not alter arguments", 2, function(){ + QUnit.test("add does not alter arguments", function(assert) { + assert.expect(2); var attrs = {}; var models = [attrs]; new Backbone.Collection().add(models); - equal(models.length, 1); - ok(attrs === models[0]); + assert.equal(models.length, 1); + assert.ok(attrs === models[0]); }); - test("#714: access `model.collection` in a brand new model.", 2, function() { + QUnit.test("#714: access `model.collection` in a brand new model.", function(assert) { + assert.expect(2); var collection = new Backbone.Collection; collection.url = '/test'; var Model = Backbone.Model.extend({ set: function(attrs) { - equal(attrs.prop, 'value'); - equal(this.collection, collection); + assert.equal(attrs.prop, 'value'); + assert.equal(this.collection, collection); return this; } }); @@ -781,16 +843,18 @@ collection.create({prop: 'value'}); }); - test("#574, remove its own reference to the .models array.", 2, function() { + QUnit.test("#574, remove its own reference to the .models array.", function(assert) { + assert.expect(2); var col = new Backbone.Collection([ {id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6} ]); - equal(col.length, 6); + assert.equal(col.length, 6); col.remove(col.models); - equal(col.length, 0); + assert.equal(col.length, 0); }); - test("#861, adding models to a collection which do not pass validation, with validate:true", 2, function() { + QUnit.test("#861, adding models to a collection which do not pass validation, with validate:true", function(assert) { + assert.expect(2); var Model = Backbone.Model.extend({ validate: function(attrs) { if (attrs.id == 3) return "id can't be 3"; @@ -802,61 +866,67 @@ }); var collection = new Collection; - collection.on("invalid", function() { ok(true); }); + collection.on("invalid", function() { assert.ok(true); }); collection.add([{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}], {validate:true}); - deepEqual(collection.pluck("id"), [1, 2, 4, 5, 6]); + assert.deepEqual(collection.pluck("id"), [1, 2, 4, 5, 6]); }); - test("Invalid models are discarded with validate:true.", 5, function() { + QUnit.test("Invalid models are discarded with validate:true.", function(assert) { + assert.expect(5); var collection = new Backbone.Collection; - collection.on('test', function() { ok(true); }); + collection.on('test', function() { assert.ok(true); }); collection.model = Backbone.Model.extend({ validate: function(attrs){ if (!attrs.valid) return 'invalid'; } }); var model = new collection.model({id: 1, valid: true}); collection.add([model, {id: 2}], {validate:true}); model.trigger('test'); - ok(collection.get(model.cid)); - ok(collection.get(1)); - ok(!collection.get(2)); - equal(collection.length, 1); + assert.ok(collection.get(model.cid)); + assert.ok(collection.get(1)); + assert.ok(!collection.get(2)); + assert.equal(collection.length, 1); }); - test("multiple copies of the same model", 3, function() { + QUnit.test("multiple copies of the same model", function(assert) { + assert.expect(3); var col = new Backbone.Collection(); var model = new Backbone.Model(); col.add([model, model]); - equal(col.length, 1); + assert.equal(col.length, 1); col.add([{id: 1}, {id: 1}]); - equal(col.length, 2); - equal(col.last().id, 1); + assert.equal(col.length, 2); + assert.equal(col.last().id, 1); }); - test("#964 - collection.get return inconsistent", 2, function() { + QUnit.test("#964 - collection.get return inconsistent", function(assert) { + assert.expect(2); var c = new Backbone.Collection(); - ok(c.get(null) === undefined); - ok(c.get() === undefined); + assert.ok(c.get(null) === undefined); + assert.ok(c.get() === undefined); }); - test("#1112 - passing options.model sets collection.model", 2, function() { + QUnit.test("#1112 - passing options.model sets collection.model", function(assert) { + assert.expect(2); var Model = Backbone.Model.extend({}); var c = new Backbone.Collection([{id: 1}], {model: Model}); - ok(c.model === Model); - ok(c.at(0) instanceof Model); + assert.ok(c.model === Model); + assert.ok(c.at(0) instanceof Model); }); - test("null and undefined are invalid ids.", 2, function() { + QUnit.test("null and undefined are invalid ids.", function(assert) { + assert.expect(2); var model = new Backbone.Model({id: 1}); var collection = new Backbone.Collection([model]); model.set({id: null}); - ok(!collection.get('null')); + assert.ok(!collection.get('null')); model.set({id: 1}); model.set({id: undefined}); - ok(!collection.get('undefined')); + assert.ok(!collection.get('undefined')); }); - test("falsy comparator", 4, function(){ + QUnit.test("falsy comparator", function(assert) { + assert.expect(4); var Col = Backbone.Collection.extend({ comparator: function(model){ return model.id; } }); @@ -864,19 +934,20 @@ var colFalse = new Col(null, {comparator: false}); var colNull = new Col(null, {comparator: null}); var colUndefined = new Col(null, {comparator: undefined}); - ok(col.comparator); - ok(!colFalse.comparator); - ok(!colNull.comparator); - ok(colUndefined.comparator); + assert.ok(col.comparator); + assert.ok(!colFalse.comparator); + assert.ok(!colNull.comparator); + assert.ok(colUndefined.comparator); }); - test("#1355 - `options` is passed to success callbacks", 2, function(){ + QUnit.test("#1355 - `options` is passed to success callbacks", function(assert) { + assert.expect(2); var m = new Backbone.Model({x:1}); var col = new Backbone.Collection(); var opts = { opts: true, success: function(collection, resp, options) { - ok(options.opts); + assert.ok(options.opts); } }; col.sync = m.sync = function( method, collection, options ){ @@ -886,31 +957,33 @@ col.create(m, opts); }); - test("#1412 - Trigger 'request' and 'sync' events.", 4, function() { + QUnit.test("#1412 - Trigger 'request' and 'sync' events.", function(assert) { + assert.expect(4); var collection = new Backbone.Collection; collection.url = '/test'; Backbone.ajax = function(settings){ settings.success(); }; collection.on('request', function(obj, xhr, options) { - ok(obj === collection, "collection has correct 'request' event after fetching"); + assert.ok(obj === collection, "collection has correct 'request' event after fetching"); }); collection.on('sync', function(obj, response, options) { - ok(obj === collection, "collection has correct 'sync' event after fetching"); + assert.ok(obj === collection, "collection has correct 'sync' event after fetching"); }); collection.fetch(); collection.off(); collection.on('request', function(obj, xhr, options) { - ok(obj === collection.get(1), "collection has correct 'request' event after one of its models save"); + assert.ok(obj === collection.get(1), "collection has correct 'request' event after one of its models save"); }); collection.on('sync', function(obj, response, options) { - ok(obj === collection.get(1), "collection has correct 'sync' event after one of its models save"); + assert.ok(obj === collection.get(1), "collection has correct 'sync' event after one of its models save"); }); collection.create({id: 1}); collection.off(); }); - test("#3283 - fetch, create calls success with context", 2, function() { + QUnit.test("#3283 - fetch, create calls success with context", function(assert) { + assert.expect(2); var collection = new Backbone.Collection; collection.url = '/test'; Backbone.ajax = function(settings) { @@ -920,7 +993,7 @@ var options = { context: obj, success: function() { - equal(this, obj); + assert.equal(this, obj); } }; @@ -928,41 +1001,46 @@ collection.create({id: 1}, options); }); - test("#1447 - create with wait adds model.", 1, function() { + QUnit.test("#1447 - create with wait adds model.", function(assert) { + assert.expect(1); var collection = new Backbone.Collection; var model = new Backbone.Model; model.sync = function(method, model, options){ options.success(); }; - collection.on('add', function(){ ok(true); }); + collection.on('add', function(){ assert.ok(true); }); collection.create(model, {wait: true}); }); - test("#1448 - add sorts collection after merge.", 1, function() { + QUnit.test("#1448 - add sorts collection after merge.", function(assert) { + assert.expect(1); var collection = new Backbone.Collection([ {id: 1, x: 1}, {id: 2, x: 2} ]); collection.comparator = function(model){ return model.get('x'); }; collection.add({id: 1, x: 3}, {merge: true}); - deepEqual(collection.pluck('id'), [2, 1]); + assert.deepEqual(collection.pluck('id'), [2, 1]); }); - test("#1655 - groupBy can be used with a string argument.", 3, function() { + QUnit.test("#1655 - groupBy can be used with a string argument.", function(assert) { + assert.expect(3); var collection = new Backbone.Collection([{x: 1}, {x: 2}]); var grouped = collection.groupBy('x'); - strictEqual(_.keys(grouped).length, 2); - strictEqual(grouped[1][0].get('x'), 1); - strictEqual(grouped[2][0].get('x'), 2); + assert.strictEqual(_.keys(grouped).length, 2); + assert.strictEqual(grouped[1][0].get('x'), 1); + assert.strictEqual(grouped[2][0].get('x'), 2); }); - test("#1655 - sortBy can be used with a string argument.", 1, function() { + QUnit.test("#1655 - sortBy can be used with a string argument.", function(assert) { + assert.expect(1); var collection = new Backbone.Collection([{x: 3}, {x: 1}, {x: 2}]); var values = _.map(collection.sortBy('x'), function(model) { return model.get('x'); }); - deepEqual(values, [1, 2, 3]); + assert.deepEqual(values, [1, 2, 3]); }); - test("#1604 - Removal during iteration.", 0, function() { + QUnit.test("#1604 - Removal during iteration.", function(assert) { + assert.expect(0); var collection = new Backbone.Collection([{}, {}]); collection.on('add', function() { collection.at(0).destroy(); @@ -970,7 +1048,7 @@ collection.add({}, {at: 0}); }); - test("#1638 - `sort` during `add` triggers correctly.", function() { + QUnit.test("#1638 - `sort` during `add` triggers correctly.", function(assert) { var collection = new Backbone.Collection; collection.comparator = function(model) { return model.get('x'); }; var added = []; @@ -980,16 +1058,17 @@ added.push(model.id); }); collection.add([{id: 1, x: 1}, {id: 2, x: 2}]); - deepEqual(added, [1, 2]); + assert.deepEqual(added, [1, 2]); }); - test("fetch parses models by default", 1, function() { + QUnit.test("fetch parses models by default", function(assert) { + assert.expect(1); var model = {}; var Collection = Backbone.Collection.extend({ url: 'test', model: Backbone.Model.extend({ parse: function(resp) { - strictEqual(resp, model); + assert.strictEqual(resp, model); } }) }); @@ -997,18 +1076,20 @@ this.ajaxSettings.success([model]); }); - test("`sort` shouldn't always fire on `add`", 1, function() { + QUnit.test("`sort` shouldn't always fire on `add`", function(assert) { + assert.expect(1); var c = new Backbone.Collection([{id: 1}, {id: 2}, {id: 3}], { comparator: 'id' }); - c.sort = function(){ ok(true); }; + c.sort = function(){ assert.ok(true); }; c.add([]); c.add({id: 1}); c.add([{id: 2}, {id: 3}]); c.add({id: 4}); }); - test("#1407 parse option on constructor parses collection and models", 2, function() { + QUnit.test("#1407 parse option on constructor parses collection and models", function(assert) { + assert.expect(2); var model = { namespace : [{id: 1}, {id:2}] }; @@ -1025,11 +1106,12 @@ }); var c = new Collection(model, {parse:true}); - equal(c.length, 2); - equal(c.at(0).get('name'), 'test'); + assert.equal(c.length, 2); + assert.equal(c.at(0).get('name'), 'test'); }); - test("#1407 parse option on reset parses collection and models", 2, function() { + QUnit.test("#1407 parse option on reset parses collection and models", function(assert) { + assert.expect(2); var model = { namespace : [{id: 1}, {id:2}] }; @@ -1045,14 +1127,15 @@ } }); var c = new Collection(); - c.reset(model, {parse:true}); + c.reset(model, {parse:true}); - equal(c.length, 2); - equal(c.at(0).get('name'), 'test'); + assert.equal(c.length, 2); + assert.equal(c.at(0).get('name'), 'test'); }); - test("Reset includes previous models in triggered event.", 1, function() { + QUnit.test("Reset includes previous models in triggered event.", function(assert) { + assert.expect(1); var model = new Backbone.Model(); var collection = new Backbone.Collection([model]) .on('reset', function(collection, options) { @@ -1061,7 +1144,7 @@ collection.reset([]); }); - test("set", function() { + QUnit.test("set", function(assert) { var m1 = new Backbone.Model(); var m2 = new Backbone.Model({id: 2}); var m3 = new Backbone.Model(); @@ -1069,58 +1152,66 @@ // Test add/change/remove events c.on('add', function(model) { - strictEqual(model, m3); + assert.strictEqual(model, m3); }); c.on('change', function(model) { - strictEqual(model, m2); + assert.strictEqual(model, m2); }); c.on('remove', function(model) { - strictEqual(model, m1); + assert.strictEqual(model, m1); }); // remove: false doesn't remove any models c.set([], {remove: false}); - strictEqual(c.length, 2); + assert.strictEqual(c.length, 2); // add: false doesn't add any models c.set([m1, m2, m3], {add: false}); - strictEqual(c.length, 2); + assert.strictEqual(c.length, 2); // merge: false doesn't change any models c.set([m1, {id: 2, a: 1}], {merge: false}); - strictEqual(m2.get('a'), void 0); + assert.strictEqual(m2.get('a'), void 0); // add: false, remove: false only merges existing models c.set([m1, {id: 2, a: 0}, m3, {id: 4}], {add: false, remove: false}); - strictEqual(c.length, 2); - strictEqual(m2.get('a'), 0); + assert.strictEqual(c.length, 2); + assert.strictEqual(m2.get('a'), 0); // default options add/remove/merge as appropriate c.set([{id: 2, a: 1}, m3]); - strictEqual(c.length, 2); - strictEqual(m2.get('a'), 1); + assert.strictEqual(c.length, 2); + assert.strictEqual(m2.get('a'), 1); // Test removing models not passing an argument c.off('remove').on('remove', function(model) { - ok(model === m2 || model === m3); + assert.ok(model === m2 || model === m3); }); c.set([]); - strictEqual(c.length, 0); + assert.strictEqual(c.length, 0); + + // Test null models on set doesn't clear collection + c.off(); + c.set([{id: 1}]); + c.set(); + assert.strictEqual(c.length, 1); }); - test("set with only cids", 3, function() { + QUnit.test("set with only cids", function(assert) { + assert.expect(3); var m1 = new Backbone.Model; var m2 = new Backbone.Model; var c = new Backbone.Collection; c.set([m1, m2]); - equal(c.length, 2); + assert.equal(c.length, 2); c.set([m1]); - equal(c.length, 1); + assert.equal(c.length, 1); c.set([m1, m1, m1, m2, m2], {remove: false}); - equal(c.length, 2); + assert.equal(c.length, 2); }); - test("set with only idAttribute", 3, function() { + QUnit.test("set with only idAttribute", function(assert) { + assert.expect(3); var m1 = { _id: 1 }; var m2 = { _id: 2 }; var col = Backbone.Collection.extend({ @@ -1130,14 +1221,14 @@ }); var c = new col; c.set([m1, m2]); - equal(c.length, 2); + assert.equal(c.length, 2); c.set([m1]); - equal(c.length, 1); + assert.equal(c.length, 1); c.set([m1, m1, m1, m2, m2], {remove: false}); - equal(c.length, 2); + assert.equal(c.length, 2); }); - test("set + merge with default values defined", function() { + QUnit.test("set + merge with default values defined", function(assert) { var Model = Backbone.Model.extend({ defaults: { key: 'value' @@ -1145,17 +1236,17 @@ }); var m = new Model({id: 1}); var col = new Backbone.Collection([m], {model: Model}); - equal(col.first().get('key'), 'value'); + assert.equal(col.first().get('key'), 'value'); col.set({id: 1, key: 'other'}); - equal(col.first().get('key'), 'other'); + assert.equal(col.first().get('key'), 'other'); col.set({id: 1, other: 'value'}); - equal(col.first().get('key'), 'other'); - equal(col.length, 1); + assert.equal(col.first().get('key'), 'other'); + assert.equal(col.length, 1); }); - test('merge without mutation', function () { + QUnit.test('merge without mutation', function(assert) { var Model = Backbone.Model.extend({ initialize: function (attrs, options) { if (attrs.child) { @@ -1166,14 +1257,14 @@ var Collection = Backbone.Collection.extend({model: Model}); var data = [{id: 1, child: {id: 2}}]; var collection = new Collection(data); - equal(collection.first().id, 1); + assert.equal(collection.first().id, 1); collection.set(data); - equal(collection.first().id, 1); + assert.equal(collection.first().id, 1); collection.set([{id: 2, child: {id: 2}}].concat(data)); - deepEqual(collection.pluck('id'), [2, 1]); + assert.deepEqual(collection.pluck('id'), [2, 1]); }); - test("`set` and model level `parse`", function() { + QUnit.test("`set` and model level `parse`", function(assert) { var Model = Backbone.Model.extend({}); var Collection = Backbone.Collection.extend({ model: Model, @@ -1185,14 +1276,14 @@ {model: {id: 1}}, {model: {id: 2}} ]}, {parse: true}); - equal(collection.first(), model); + assert.equal(collection.first(), model); }); - test("`set` data is only parsed once", function() { + QUnit.test("`set` data is only parsed once", function(assert) { var collection = new Backbone.Collection(); collection.model = Backbone.Model.extend({ parse: function (data) { - equal(data.parsed, void 0); + assert.equal(data.parsed, void 0); data.parsed = true; return data; } @@ -1200,61 +1291,64 @@ collection.set({}, {parse: true}); }); - test('`set` matches input order in the absence of a comparator', function () { + QUnit.test('`set` matches input order in the absence of a comparator', function(assert) { var one = new Backbone.Model({id: 1}); var two = new Backbone.Model({id: 2}); var three = new Backbone.Model({id: 3}); var collection = new Backbone.Collection([one, two, three]); collection.set([{id: 3}, {id: 2}, {id: 1}]); - deepEqual(collection.models, [three, two, one]); + assert.deepEqual(collection.models, [three, two, one]); collection.set([{id: 1}, {id: 2}]); - deepEqual(collection.models, [one, two]); + assert.deepEqual(collection.models, [one, two]); collection.set([two, three, one]); - deepEqual(collection.models, [two, three, one]); + assert.deepEqual(collection.models, [two, three, one]); collection.set([{id: 1}, {id: 2}], {remove: false}); - deepEqual(collection.models, [two, three, one]); + assert.deepEqual(collection.models, [two, three, one]); collection.set([{id: 1}, {id: 2}, {id: 3}], {merge: false}); - deepEqual(collection.models, [one, two, three]); + assert.deepEqual(collection.models, [one, two, three]); collection.set([three, two, one, {id: 4}], {add: false}); - deepEqual(collection.models, [one, two, three]); + assert.deepEqual(collection.models, [one, two, three]); }); - test("#1894 - Push should not trigger a sort", 0, function() { + QUnit.test("#1894 - Push should not trigger a sort", function(assert) { + assert.expect(0); var Collection = Backbone.Collection.extend({ comparator: 'id', - sort: function() { ok(false); } + sort: function() { assert.ok(false); } }); new Collection().push({id: 1}); }); - test("#2428 - push duplicate models, return the correct one", 1, function() { + QUnit.test("#2428 - push duplicate models, return the correct one", function(assert) { + assert.expect(1); var col = new Backbone.Collection; var model1 = col.push({id: 101}); - var model2 = col.push({id: 101}) - ok(model2.cid == model1.cid); + var model2 = col.push({id: 101}); + assert.ok(model2.cid == model1.cid); }); - test("`set` with non-normal id", function() { + QUnit.test("`set` with non-normal id", function(assert) { var Collection = Backbone.Collection.extend({ model: Backbone.Model.extend({idAttribute: '_id'}) }); var collection = new Collection({_id: 1}); collection.set([{_id: 1, a: 1}], {add: false}); - equal(collection.first().get('a'), 1); + assert.equal(collection.first().get('a'), 1); }); - test("#1894 - `sort` can optionally be turned off", 0, function() { + QUnit.test("#1894 - `sort` can optionally be turned off", function(assert) { + assert.expect(0); var Collection = Backbone.Collection.extend({ comparator: 'id', - sort: function() { ok(false); } + sort: function() { assert.ok(false); } }); new Collection().add({id: 1}, {sort: false}); }); - test("#1915 - `parse` data in the right order in `set`", function() { + QUnit.test("#1915 - `parse` data in the right order in `set`", function(assert) { var collection = new (Backbone.Collection.extend({ parse: function (data) { - strictEqual(data.status, 'ok'); + assert.strictEqual(data.status, 'ok'); return data.data; } })); @@ -1262,26 +1356,29 @@ collection.set(res, {parse: true}); }); - asyncTest("#1939 - `parse` is passed `options`", 1, function () { + QUnit.test("#1939 - `parse` is passed `options`", function(assert) { + var done = assert.async(); + assert.expect(1); var collection = new (Backbone.Collection.extend({ url: '/', parse: function (data, options) { - strictEqual(options.xhr.someHeader, 'headerValue'); + assert.strictEqual(options.xhr.someHeader, 'headerValue'); return data; } })); var ajax = Backbone.ajax; Backbone.ajax = function (params) { - _.defer(params.success); + _.defer(params.success, []); return {someHeader: 'headerValue'}; }; collection.fetch({ - success: function () { start(); } + success: function () { done(); } }); Backbone.ajax = ajax; }); - test("fetch will pass extra options to success callback", 1, function () { + QUnit.test("fetch will pass extra options to success callback", function(assert) { + assert.expect(1); var SpecialSyncCollection = Backbone.Collection.extend({ url: '/test', sync: function (method, collection, options) { @@ -1293,14 +1390,15 @@ var collection = new SpecialSyncCollection(); var onSuccess = function (collection, resp, options) { - ok(options.specialSync, "Options were passed correctly to callback"); + assert.ok(options.specialSync, "Options were passed correctly to callback"); }; collection.fetch({ success: onSuccess }); this.ajaxSettings.success(); }); - test("`add` only `sort`s when necessary", 2, function () { + QUnit.test("`add` only `sort`s when necessary", function(assert) { + assert.expect(2); var collection = new (Backbone.Collection.extend({ comparator: 'a' }))([{id: 1}, {id: 2}, {id: 3}]); @@ -1313,7 +1411,8 @@ collection.add(collection.models, {merge: true}); // don't sort }); - test("`add` only `sort`s when necessary with comparator function", 3, function () { + QUnit.test("`add` only `sort`s when necessary with comparator function", function(assert) { + assert.expect(3); var collection = new (Backbone.Collection.extend({ comparator: function(a, b) { return a.get('a') > b.get('a') ? 1 : (a.get('a') < b.get('a') ? -1 : 0); @@ -1328,7 +1427,8 @@ collection.add(collection.models, {merge: true}); // don't sort }); - test("Attach options to collection.", 2, function() { + QUnit.test("Attach options to collection.", function(assert) { + assert.expect(2); var Model = Backbone.Model; var comparator = function(){}; @@ -1337,31 +1437,48 @@ comparator: comparator }); - ok(collection.model === Model); - ok(collection.comparator === comparator); + assert.ok(collection.model === Model); + assert.ok(collection.comparator === comparator); }); - test("`add` overrides `set` flags", function () { + QUnit.test("Pass falsey for `models` for empty Col with `options`", function(assert) { + assert.expect(9); + var opts = {a: 1, b: 2}; + _.forEach([undefined, null, false], function(falsey) { + var Collection = Backbone.Collection.extend({ + initialize: function(models, options) { + assert.strictEqual(models, falsey); + assert.strictEqual(options, opts); + } + }); + + var col = new Collection(falsey, opts); + assert.strictEqual(col.length, 0); + }); + }); + + QUnit.test("`add` overrides `set` flags", function(assert) { var collection = new Backbone.Collection(); collection.once('add', function (model, collection, options) { collection.add({id: 2}, options); }); collection.set({id: 1}); - equal(collection.length, 2); + assert.equal(collection.length, 2); }); - test("#2606 - Collection#create, success arguments", 1, function() { + QUnit.test("#2606 - Collection#create, success arguments", function(assert) { + assert.expect(1); var collection = new Backbone.Collection; collection.url = 'test'; collection.create({}, { success: function(model, resp, options) { - strictEqual(resp, 'response'); + assert.strictEqual(resp, 'response'); } }); this.ajaxSettings.success('response'); }); - test("#2612 - nested `parse` works with `Collection#set`", function() { + QUnit.test("#2612 - nested `parse` works with `Collection#set`", function(assert) { var Job = Backbone.Model.extend({ constructor: function() { @@ -1430,20 +1547,21 @@ }; var job = new Job(data, {parse: true}); - equal(job.get('name'), 'JobName'); - equal(job.items.at(0).get('name'), 'Sub1'); - equal(job.items.length, 2); - equal(job.items.get(1).subItems.get(1).get('subName'), 'One'); - equal(job.items.get(2).subItems.get(3).get('subName'), 'Three'); + assert.equal(job.get('name'), 'JobName'); + assert.equal(job.items.at(0).get('name'), 'Sub1'); + assert.equal(job.items.length, 2); + assert.equal(job.items.get(1).subItems.get(1).get('subName'), 'One'); + assert.equal(job.items.get(2).subItems.get(3).get('subName'), 'Three'); job.set(job.parse(newData, {parse: true})); - equal(job.get('name'), 'NewJobName'); - equal(job.items.at(0).get('name'), 'NewSub1'); - equal(job.items.length, 2); - equal(job.items.get(1).subItems.get(1).get('subName'), 'NewOne'); - equal(job.items.get(2).subItems.get(3).get('subName'), 'NewThree'); + assert.equal(job.get('name'), 'NewJobName'); + assert.equal(job.items.at(0).get('name'), 'NewSub1'); + assert.equal(job.items.length, 2); + assert.equal(job.items.get(1).subItems.get(1).get('subName'), 'NewOne'); + assert.equal(job.items.get(2).subItems.get(3).get('subName'), 'NewThree'); }); - test('_addReference binds all collection events & adds to the lookup hashes', 9, function() { + QUnit.test('_addReference binds all collection events & adds to the lookup hashes', function(assert) { + assert.expect(9); var calls = {add: 0, remove: 0}; @@ -1452,18 +1570,18 @@ _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); + assert.equal(model, this._byId[model.id]); + assert.equal(model, this._byId[model.cid]); + assert.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, void 0); + assert.equal(this._byId[model.id], void 0); + assert.equal(this._byId[model.cid], void 0); + assert.equal(model.collection, void 0); + assert.equal(model._events, void 0); } }); @@ -1472,50 +1590,51 @@ var model = collection.add({id: 1}); collection.remove(model); - equal(calls.add, 1); - equal(calls.remove, 1); - + assert.equal(calls.add, 1); + assert.equal(calls.remove, 1); }); - test('Do not allow duplicate models to be `add`ed or `set`', function() { + QUnit.test('Do not allow duplicate models to be `add`ed or `set`', function(assert) { var c = new Backbone.Collection(); c.add([{id: 1}, {id: 1}]); - equal(c.length, 1); - equal(c.models.length, 1); + assert.equal(c.length, 1); + assert.equal(c.models.length, 1); c.set([{id: 1}, {id: 1}]); - equal(c.length, 1); - equal(c.models.length, 1); + assert.equal(c.length, 1); + assert.equal(c.models.length, 1); }); - test('#3020: #set with {add: false} should not throw.', 2, function() { + QUnit.test('#3020: #set with {add: false} should not throw.', function(assert) { + assert.expect(2); var collection = new Backbone.Collection; collection.set([{id: 1}], {add: false}); - strictEqual(collection.length, 0); - strictEqual(collection.models.length, 0); + assert.strictEqual(collection.length, 0); + assert.strictEqual(collection.models.length, 0); }); - test("create with wait, model instance, #3028", 1, function() { + QUnit.test("create with wait, model instance, #3028", function(assert) { + assert.expect(1); var collection = new Backbone.Collection(); var model = new Backbone.Model({id: 1}); model.sync = function(){ - equal(this.collection, collection); + assert.equal(this.collection, collection); }; collection.create(model, {wait: true}); }); - test("modelId", function() { + QUnit.test("modelId", function(assert) { var Stooge = Backbone.Model.extend(); var StoogeCollection = Backbone.Collection.extend({model: Stooge}); // Default to using `Collection::model::idAttribute`. - equal(StoogeCollection.prototype.modelId({id: 1}), 1); + assert.equal(StoogeCollection.prototype.modelId({id: 1}), 1); Stooge.prototype.idAttribute = '_id'; - equal(StoogeCollection.prototype.modelId({_id: 1}), 1); + assert.equal(StoogeCollection.prototype.modelId({_id: 1}), 1); }); - test('Polymorphic models work with "simple" constructors', function () { + QUnit.test('Polymorphic models work with "simple" constructors', function(assert) { var A = Backbone.Model.extend(); var B = Backbone.Model.extend(); var C = Backbone.Collection.extend({ @@ -1524,14 +1643,14 @@ } }); var collection = new C([{id: 1, type: 'a'}, {id: 2, type: 'b'}]); - equal(collection.length, 2); - ok(collection.at(0) instanceof A); - equal(collection.at(0).id, 1); - ok(collection.at(1) instanceof B); - equal(collection.at(1).id, 2); + assert.equal(collection.length, 2); + assert.ok(collection.at(0) instanceof A); + assert.equal(collection.at(0).id, 1); + assert.ok(collection.at(1) instanceof B); + assert.equal(collection.at(1).id, 2); }); - test('Polymorphic models work with "advanced" constructors', function () { + QUnit.test('Polymorphic models work with "advanced" constructors', function(assert) { var A = Backbone.Model.extend({idAttribute: '_id'}); var B = Backbone.Model.extend({idAttribute: '_id'}); var C = Backbone.Collection.extend({ @@ -1544,11 +1663,11 @@ }) }); var collection = new C([{_id: 1, type: 'a'}, {_id: 2, type: 'b'}]); - equal(collection.length, 2); - ok(collection.at(0) instanceof A); - equal(collection.at(0), collection.get(1)); - ok(collection.at(1) instanceof B); - equal(collection.at(1), collection.get(2)); + assert.equal(collection.length, 2); + assert.ok(collection.at(0) instanceof A); + assert.equal(collection.at(0), collection.get(1)); + assert.ok(collection.at(1) instanceof B); + assert.equal(collection.at(1), collection.get(2)); C = Backbone.Collection.extend({ model: function (attrs) { @@ -1560,117 +1679,150 @@ } }); collection = new C([{id: 1, type: 'a'}, {id: 1, type: 'b'}]); - equal(collection.length, 2); - ok(collection.at(0) instanceof A); - equal(collection.at(0), collection.get('a-1')); - ok(collection.at(1) instanceof B); - equal(collection.at(1), collection.get('b-1')); + assert.equal(collection.length, 2); + assert.ok(collection.at(0) instanceof A); + assert.equal(collection.at(0), collection.get('a-1')); + assert.ok(collection.at(1) instanceof B); + assert.equal(collection.at(1), collection.get('b-1')); }); - test("#3039: adding at index fires with correct at", 3, function() { + QUnit.test("#3039: adding at index fires with correct at", function(assert) { + assert.expect(3); var col = new Backbone.Collection([{at: 0}, {at: 4}]); col.on('add', function(model, col, options) { - equal(model.get('at'), options.index); + assert.equal(model.get('at'), options.index); }); col.add([{at: 1}, {at: 2}, {at: 3}], {at: 1}); }); - test("#3039: index is not sent when at is not specified", 2, function() { + QUnit.test("#3039: index is not sent when at is not specified", function(assert) { + assert.expect(2); var col = new Backbone.Collection([{at: 0}]); col.on('add', function(model, col, options) { - equal(undefined, options.index); + assert.equal(undefined, options.index); }); col.add([{at: 1}, {at: 2}]); }); - test('#3199 - Order changing should trigger a sort', 1, function() { - var one = new Backbone.Model({id: 1}); - var two = new Backbone.Model({id: 2}); - var three = new Backbone.Model({id: 3}); - var collection = new Backbone.Collection([one, two, three]); - collection.on('sort', function() { - ok(true); - }); - collection.set([{id: 3}, {id: 2}, {id: 1}]); + QUnit.test('#3199 - Order changing should trigger a sort', function(assert) { + assert.expect(1); + var one = new Backbone.Model({id: 1}); + var two = new Backbone.Model({id: 2}); + var three = new Backbone.Model({id: 3}); + var collection = new Backbone.Collection([one, two, three]); + collection.on('sort', function() { + assert.ok(true); + }); + collection.set([{id: 3}, {id: 2}, {id: 1}]); }); - test('#3199 - Adding a model should trigger a sort', 1, function() { + QUnit.test('#3199 - Adding a model should trigger a sort', function(assert) { + assert.expect(1); var one = new Backbone.Model({id: 1}); var two = new Backbone.Model({id: 2}); var three = new Backbone.Model({id: 3}); var collection = new Backbone.Collection([one, two, three]); collection.on('sort', function() { - ok(true); + assert.ok(true); }); - collection.set([{id: 3}, {id: 2}, {id: 1}, {id: 0}]); - }) + collection.set([{id: 1}, {id: 2}, {id: 3}, {id: 0}]); + }); - test('#3199 - Order not changing should not trigger a sort', 0, function() { + QUnit.test('#3199 - Order not changing should not trigger a sort', function(assert) { + assert.expect(0); var one = new Backbone.Model({id: 1}); var two = new Backbone.Model({id: 2}); var three = new Backbone.Model({id: 3}); var collection = new Backbone.Collection([one, two, three]); collection.on('sort', function() { - ok(false); + assert.ok(false); }); collection.set([{id: 1}, {id: 2}, {id: 3}]); }); - test("add supports negative indexes", 1, function() { + QUnit.test("add supports negative indexes", function(assert) { + assert.expect(1); var collection = new Backbone.Collection([{id: 1}]); collection.add([{id: 2}, {id: 3}], {at: -1}); collection.add([{id: 2.5}], {at: -2}); - equal(collection.pluck('id').join(','), "1,2,2.5,3"); + collection.add([{id: 0.5}], {at: -6}); + assert.equal(collection.pluck('id').join(','), "0.5,1,2,2.5,3"); }); - test("#set accepts options.at as a string", 1, function() { + QUnit.test("#set accepts options.at as a string", function(assert) { + assert.expect(1); var collection = new Backbone.Collection([{id: 1}, {id: 2}]); collection.add([{id: 3}], {at: '1'}); - deepEqual(collection.pluck('id'), [1, 3, 2]); + assert.deepEqual(collection.pluck('id'), [1, 3, 2]); }); - test("adding multiple models triggers `update` event once", 1, function() { + + QUnit.test("adding multiple models triggers `update` event once", function(assert) { + assert.expect(1); var collection = new Backbone.Collection; - collection.on('update', function() { ok(true); }); + collection.on('update', function() { assert.ok(true); }); collection.add([{id: 1}, {id: 2}, {id: 3}]); }); - test("removing models triggers `update` event once", 1, function() { + QUnit.test("removing models triggers `update` event once", function(assert) { + assert.expect(1); var collection = new Backbone.Collection([{id: 1}, {id: 2}, {id: 3}]); - collection.on('update', function() { ok(true); }); + collection.on('update', function() { assert.ok(true); }); collection.remove([{id: 1}, {id: 2}]); }); - test("remove does not trigger `set` when nothing removed", 0, function() { + QUnit.test("remove does not trigger `set` when nothing removed", function(assert) { + assert.expect(0); var collection = new Backbone.Collection([{id: 1}, {id: 2}]); - collection.on('update', function() { ok(false); }); + collection.on('update', function() { assert.ok(false); }); collection.remove([{id: 3}]); }); - test("set triggers `set` event once", 1, function() { + QUnit.test("set triggers `set` event once", function(assert) { + assert.expect(1); var collection = new Backbone.Collection([{id: 1}, {id: 2}]); - collection.on('update', function() { ok(true); }); + collection.on('update', function() { assert.ok(true); }); collection.set([{id: 1}, {id: 3}]); }); - test("set does not trigger `update` event when nothing added nor removed", 0, function() { + QUnit.test("set does not trigger `update` event when nothing added nor removed", function(assert) { + assert.expect(0); var collection = new Backbone.Collection([{id: 1}, {id: 2}]); - collection.on('update', function() { ok(false); }); + collection.on('update', function() { assert.ok(false); }); collection.set([{id: 1}, {id: 2}]); }); - test("#3610 - invoke collects arguments", 3, function() { + QUnit.test("#3610 - invoke collects arguments", function(assert) { + assert.expect(3); var Model = Backbone.Model.extend({ - method: function(a, b, c) { - equal(a, 1); - equal(b, 2); - equal(c, 3); - } + method: function(a, b, c) { + assert.equal(a, 1); + assert.equal(b, 2); + assert.equal(c, 3); + } }); var Collection = Backbone.Collection.extend({ - model: Model + model: Model }); var collection = new Collection([{id: 1}]); collection.invoke('method', 1, 2, 3); }); + QUnit.test('#3662 - triggering change without model will not error', function(assert) { + assert.expect(1); + var collection = new Backbone.Collection([{id: 1}]); + var model = collection.first(); + collection.on('change', function(model) { + assert.equal(model, undefined); + }); + model.trigger('change'); + }); + + QUnit.test('#3871 - falsy parse result creates empty collection', function(assert) { + var collection = new (Backbone.Collection.extend({ + parse: function (data, options) {} + })); + collection.set('', { parse: true }); + assert.equal(collection.length, 0); + }); + })(); diff --git a/vendor/backbone/test/events.js b/vendor/backbone/test/events.js index 609d1f810..07ee7ee47 100644 --- a/vendor/backbone/test/events.js +++ b/vendor/backbone/test/events.js @@ -1,41 +1,43 @@ (function() { - module("Backbone.Events"); + QUnit.module("Backbone.Events"); - test("on and trigger", 2, function() { + QUnit.test("on and trigger", function(assert) { + assert.expect(2); var obj = { counter: 0 }; _.extend(obj,Backbone.Events); obj.on('event', function() { obj.counter += 1; }); obj.trigger('event'); - equal(obj.counter,1,'counter should be incremented.'); + assert.equal(obj.counter, 1, 'counter should be incremented.'); obj.trigger('event'); obj.trigger('event'); obj.trigger('event'); obj.trigger('event'); - equal(obj.counter, 5, 'counter should be incremented five times.'); + assert.equal(obj.counter, 5, 'counter should be incremented five times.'); }); - test("binding and triggering multiple events", 4, function() { + QUnit.test("binding and triggering multiple events", function(assert) { + assert.expect(4); var obj = { counter: 0 }; _.extend(obj, Backbone.Events); obj.on('a b c', function() { obj.counter += 1; }); obj.trigger('a'); - equal(obj.counter, 1); + assert.equal(obj.counter, 1); obj.trigger('a b'); - equal(obj.counter, 3); + assert.equal(obj.counter, 3); obj.trigger('c'); - equal(obj.counter, 4); + assert.equal(obj.counter, 4); obj.off('a c'); obj.trigger('a b c'); - equal(obj.counter, 5); + assert.equal(obj.counter, 5); }); - test("binding and triggering with event maps", function() { + QUnit.test("binding and triggering with event maps", function(assert) { var obj = { counter: 0 }; _.extend(obj, Backbone.Events); @@ -50,23 +52,23 @@ }, obj); obj.trigger('a'); - equal(obj.counter, 1); + assert.equal(obj.counter, 1); obj.trigger('a b'); - equal(obj.counter, 3); + assert.equal(obj.counter, 3); obj.trigger('c'); - equal(obj.counter, 4); + assert.equal(obj.counter, 4); obj.off({ a: increment, c: increment }, obj); obj.trigger('a b c'); - equal(obj.counter, 5); + assert.equal(obj.counter, 5); }); - test("binding and triggering multiple event names with event maps", function() { + QUnit.test("binding and triggering multiple event names with event maps", function(assert) { var obj = { counter: 0 }; _.extend(obj, Backbone.Events); @@ -79,29 +81,30 @@ }); obj.trigger('a'); - equal(obj.counter, 1); + assert.equal(obj.counter, 1); obj.trigger('a b'); - equal(obj.counter, 3); + assert.equal(obj.counter, 3); obj.trigger('c'); - equal(obj.counter, 4); + assert.equal(obj.counter, 4); obj.off({ 'a c': increment }); obj.trigger('a b c'); - equal(obj.counter, 5); + assert.equal(obj.counter, 5); }); - test("binding and trigger with event maps context", 2, function() { + QUnit.test("binding and trigger with event maps context", function(assert) { + assert.expect(2); var obj = { counter: 0 }; var context = {}; _.extend(obj, Backbone.Events); obj.on({ a: function() { - strictEqual(this, context, 'defaults `context` to `callback` param'); + assert.strictEqual(this, context, 'defaults `context` to `callback` param'); } }, context).trigger('a'); @@ -112,20 +115,22 @@ }, this, context).trigger('a'); }); - test("listenTo and stopListening", 1, function() { + QUnit.test("listenTo and stopListening", function(assert) { + assert.expect(1); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); - a.listenTo(b, 'all', function(){ ok(true); }); + a.listenTo(b, 'all', function(){ assert.ok(true); }); b.trigger('anything'); - a.listenTo(b, 'all', function(){ ok(false); }); + a.listenTo(b, 'all', function(){ assert.ok(false); }); a.stopListening(); b.trigger('anything'); }); - test("listenTo and stopListening with event maps", 4, function() { + QUnit.test("listenTo and stopListening with event maps", function(assert) { + assert.expect(4); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); - var cb = function(){ ok(true); }; + var cb = function(){ assert.ok(true); }; a.listenTo(b, {event: cb}); b.trigger('event'); a.listenTo(b, {event2: cb}); @@ -136,10 +141,11 @@ b.trigger('event event2'); }); - test("stopListening with omitted args", 2, function () { + QUnit.test("stopListening with omitted args", function(assert) { + assert.expect(2); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); - var cb = function () { ok(true); }; + var cb = function () { assert.ok(true); }; a.listenTo(b, 'event', cb); b.on('event', cb); a.listenTo(b, 'event2', cb); @@ -152,7 +158,8 @@ b.trigger('event2'); }); - test("listenToOnce", 2, function() { + QUnit.test("listenToOnce", function(assert) { + assert.expect(2); // Same as the previous test, but we use once rather than having to explicitly unbind var obj = { counterA: 0, counterB: 0 }; _.extend(obj, Backbone.Events); @@ -161,172 +168,186 @@ obj.listenToOnce(obj, 'event', incrA); obj.listenToOnce(obj, 'event', incrB); obj.trigger('event'); - equal(obj.counterA, 1, 'counterA should have only been incremented once.'); - equal(obj.counterB, 1, 'counterB should have only been incremented once.'); + assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.'); + assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.'); }); - test("listenToOnce and stopListening", 1, function() { + QUnit.test("listenToOnce and stopListening", function(assert) { + assert.expect(1); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); - a.listenToOnce(b, 'all', function() { ok(true); }); + a.listenToOnce(b, 'all', function() { assert.ok(true); }); b.trigger('anything'); b.trigger('anything'); - a.listenToOnce(b, 'all', function() { ok(false); }); + a.listenToOnce(b, 'all', function() { assert.ok(false); }); a.stopListening(); b.trigger('anything'); }); - test("listenTo, listenToOnce and stopListening", 1, function() { + QUnit.test("listenTo, listenToOnce and stopListening", function(assert) { + assert.expect(1); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); - a.listenToOnce(b, 'all', function() { ok(true); }); + a.listenToOnce(b, 'all', function() { assert.ok(true); }); b.trigger('anything'); b.trigger('anything'); - a.listenTo(b, 'all', function() { ok(false); }); + a.listenTo(b, 'all', function() { assert.ok(false); }); a.stopListening(); b.trigger('anything'); }); - test("listenTo and stopListening with event maps", 1, function() { + QUnit.test("listenTo and stopListening with event maps", function(assert) { + assert.expect(1); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); - a.listenTo(b, {change: function(){ ok(true); }}); + a.listenTo(b, {change: function(){ assert.ok(true); }}); b.trigger('change'); - a.listenTo(b, {change: function(){ ok(false); }}); + a.listenTo(b, {change: function(){ assert.ok(false); }}); a.stopListening(); b.trigger('change'); }); - test("listenTo yourself", 1, function(){ + QUnit.test("listenTo yourself", function(assert) { + assert.expect(1); var e = _.extend({}, Backbone.Events); - e.listenTo(e, "foo", function(){ ok(true); }); + e.listenTo(e, "foo", function(){ assert.ok(true); }); e.trigger("foo"); }); - test("listenTo yourself cleans yourself up with stopListening", 1, function(){ + QUnit.test("listenTo yourself cleans yourself up with stopListening", function(assert) { + assert.expect(1); var e = _.extend({}, Backbone.Events); - e.listenTo(e, "foo", function(){ ok(true); }); + e.listenTo(e, "foo", function(){ assert.ok(true); }); e.trigger("foo"); e.stopListening(); e.trigger("foo"); }); - test("stopListening cleans up references", 12, function() { + QUnit.test("stopListening cleans up references", function(assert) { + assert.expect(12); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); var fn = function() {}; b.on('event', fn); a.listenTo(b, 'event', fn).stopListening(); - equal(_.size(a._listeningTo), 0); - equal(_.size(b._events.event), 1); - equal(_.size(b._listeners), 0); + assert.equal(_.size(a._listeningTo), 0); + assert.equal(_.size(b._events.event), 1); + assert.equal(_.size(b._listeners), 0); a.listenTo(b, 'event', fn).stopListening(b); - equal(_.size(a._listeningTo), 0); - equal(_.size(b._events.event), 1); - equal(_.size(b._listeners), 0); + assert.equal(_.size(a._listeningTo), 0); + assert.equal(_.size(b._events.event), 1); + assert.equal(_.size(b._listeners), 0); a.listenTo(b, 'event', fn).stopListening(b, 'event'); - equal(_.size(a._listeningTo), 0); - equal(_.size(b._events.event), 1); - equal(_.size(b._listeners), 0); + assert.equal(_.size(a._listeningTo), 0); + assert.equal(_.size(b._events.event), 1); + assert.equal(_.size(b._listeners), 0); a.listenTo(b, 'event', fn).stopListening(b, 'event', fn); - equal(_.size(a._listeningTo), 0); - equal(_.size(b._events.event), 1); - equal(_.size(b._listeners), 0); + assert.equal(_.size(a._listeningTo), 0); + assert.equal(_.size(b._events.event), 1); + assert.equal(_.size(b._listeners), 0); }); - test("stopListening cleans up references from listenToOnce", 12, function() { + QUnit.test("stopListening cleans up references from listenToOnce", function(assert) { + assert.expect(12); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); var fn = function() {}; b.on('event', fn); a.listenToOnce(b, 'event', fn).stopListening(); - equal(_.size(a._listeningTo), 0); - equal(_.size(b._events.event), 1); - equal(_.size(b._listeners), 0); + assert.equal(_.size(a._listeningTo), 0); + assert.equal(_.size(b._events.event), 1); + assert.equal(_.size(b._listeners), 0); a.listenToOnce(b, 'event', fn).stopListening(b); - equal(_.size(a._listeningTo), 0); - equal(_.size(b._events.event), 1); - equal(_.size(b._listeners), 0); + assert.equal(_.size(a._listeningTo), 0); + assert.equal(_.size(b._events.event), 1); + assert.equal(_.size(b._listeners), 0); a.listenToOnce(b, 'event', fn).stopListening(b, 'event'); - equal(_.size(a._listeningTo), 0); - equal(_.size(b._events.event), 1); - equal(_.size(b._listeners), 0); + assert.equal(_.size(a._listeningTo), 0); + assert.equal(_.size(b._events.event), 1); + assert.equal(_.size(b._listeners), 0); a.listenToOnce(b, 'event', fn).stopListening(b, 'event', fn); - equal(_.size(a._listeningTo), 0); - equal(_.size(b._events.event), 1); - equal(_.size(b._listeners), 0); + assert.equal(_.size(a._listeningTo), 0); + assert.equal(_.size(b._events.event), 1); + assert.equal(_.size(b._listeners), 0); }); - test("listenTo and off cleaning up references", 8, function() { + QUnit.test("listenTo and off cleaning up references", function(assert) { + assert.expect(8); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); var fn = function() {}; a.listenTo(b, 'event', fn); b.off(); - equal(_.size(a._listeningTo), 0); - equal(_.size(b._listeners), 0); + assert.equal(_.size(a._listeningTo), 0); + assert.equal(_.size(b._listeners), 0); a.listenTo(b, 'event', fn); b.off('event'); - equal(_.size(a._listeningTo), 0); - equal(_.size(b._listeners), 0); + assert.equal(_.size(a._listeningTo), 0); + assert.equal(_.size(b._listeners), 0); a.listenTo(b, 'event', fn); b.off(null, fn); - equal(_.size(a._listeningTo), 0); - equal(_.size(b._listeners), 0); + assert.equal(_.size(a._listeningTo), 0); + assert.equal(_.size(b._listeners), 0); a.listenTo(b, 'event', fn); b.off(null, null, a); - equal(_.size(a._listeningTo), 0); - equal(_.size(b._listeners), 0); + assert.equal(_.size(a._listeningTo), 0); + assert.equal(_.size(b._listeners), 0); }); - test("listenTo and stopListening cleaning up references", 2, function() { + QUnit.test("listenTo and stopListening cleaning up references", function(assert) { + assert.expect(2); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); - a.listenTo(b, 'all', function(){ ok(true); }); + a.listenTo(b, 'all', function(){ assert.ok(true); }); b.trigger('anything'); - a.listenTo(b, 'other', function(){ ok(false); }); + a.listenTo(b, 'other', function(){ assert.ok(false); }); a.stopListening(b, 'other'); a.stopListening(b, 'all'); - equal(_.size(a._listeningTo), 0); + assert.equal(_.size(a._listeningTo), 0); }); - test("listenToOnce without context cleans up references after the event has fired", 2, function() { + QUnit.test("listenToOnce without context cleans up references after the event has fired", function(assert) { + assert.expect(2); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); - a.listenToOnce(b, 'all', function(){ ok(true); }); + a.listenToOnce(b, 'all', function(){ assert.ok(true); }); b.trigger('anything'); - equal(_.size(a._listeningTo), 0); + assert.equal(_.size(a._listeningTo), 0); }); - test("listenToOnce with event maps cleans up references", 2, function() { + QUnit.test("listenToOnce with event maps cleans up references", function(assert) { + assert.expect(2); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); a.listenToOnce(b, { - one: function() { ok(true); }, - two: function() { ok(false); } + one: function() { assert.ok(true); }, + two: function() { assert.ok(false); } }); b.trigger('one'); - equal(_.size(a._listeningTo), 1); + assert.equal(_.size(a._listeningTo), 1); }); - test("listenToOnce with event maps binds the correct `this`", 1, function() { + QUnit.test("listenToOnce with event maps binds the correct `this`", function(assert) { + assert.expect(1); var a = _.extend({}, Backbone.Events); var b = _.extend({}, Backbone.Events); a.listenToOnce(b, { - one: function() { ok(this === a); }, - two: function() { ok(false); } + one: function() { assert.ok(this === a); }, + two: function() { assert.ok(false); } }); b.trigger('one'); }); - test("listenTo with empty callback doesn't throw an error", 1, function(){ + QUnit.test("listenTo with empty callback doesn't throw an error", function(assert) { + assert.expect(1); var e = _.extend({}, Backbone.Events); e.listenTo(e, "foo", null); e.trigger("foo"); - ok(true); + assert.ok(true); }); - test("trigger all for each event", 3, function() { + QUnit.test("trigger all for each event", function(assert) { + assert.expect(3); var a, b, obj = { counter: 0 }; _.extend(obj, Backbone.Events); obj.on('all', function(event) { @@ -335,12 +356,13 @@ if (event == 'b') b = true; }) .trigger('a b'); - ok(a); - ok(b); - equal(obj.counter, 2); + assert.ok(a); + assert.ok(b); + assert.equal(obj.counter, 2); }); - test("on, then unbind all functions", 1, function() { + QUnit.test("on, then unbind all functions", function(assert) { + assert.expect(1); var obj = { counter: 0 }; _.extend(obj,Backbone.Events); var callback = function() { obj.counter += 1; }; @@ -348,10 +370,11 @@ obj.trigger('event'); obj.off('event'); obj.trigger('event'); - equal(obj.counter, 1, 'counter should have only been incremented once.'); + assert.equal(obj.counter, 1, 'counter should have only been incremented once.'); }); - test("bind two callbacks, unbind only one", 2, function() { + QUnit.test("bind two callbacks, unbind only one", function(assert) { + assert.expect(2); var obj = { counterA: 0, counterB: 0 }; _.extend(obj,Backbone.Events); var callback = function() { obj.counterA += 1; }; @@ -360,11 +383,12 @@ obj.trigger('event'); obj.off('event', callback); obj.trigger('event'); - equal(obj.counterA, 1, 'counterA should have only been incremented once.'); - equal(obj.counterB, 2, 'counterB should have been incremented twice.'); + assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.'); + assert.equal(obj.counterB, 2, 'counterB should have been incremented twice.'); }); - test("unbind a callback in the midst of it firing", 1, function() { + QUnit.test("unbind a callback in the midst of it firing", function(assert) { + assert.expect(1); var obj = {counter: 0}; _.extend(obj, Backbone.Events); var callback = function() { @@ -375,10 +399,11 @@ obj.trigger('event'); obj.trigger('event'); obj.trigger('event'); - equal(obj.counter, 1, 'the callback should have been unbound.'); + assert.equal(obj.counter, 1, 'the callback should have been unbound.'); }); - test("two binds that unbind themeselves", 2, function() { + QUnit.test("two binds that unbind themeselves", function(assert) { + assert.expect(2); var obj = { counterA: 0, counterB: 0 }; _.extend(obj,Backbone.Events); var incrA = function(){ obj.counterA += 1; obj.off('event', incrA); }; @@ -388,16 +413,17 @@ obj.trigger('event'); obj.trigger('event'); obj.trigger('event'); - equal(obj.counterA, 1, 'counterA should have only been incremented once.'); - equal(obj.counterB, 1, 'counterB should have only been incremented once.'); + assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.'); + assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.'); }); - test("bind a callback with a supplied context", 1, function () { + QUnit.test("bind a callback with a supplied context", function(assert) { + assert.expect(1); var TestClass = function () { return this; }; TestClass.prototype.assertTrue = function () { - ok(true, '`this` was bound to the callback'); + assert.ok(true, '`this` was bound to the callback'); }; var obj = _.extend({},Backbone.Events); @@ -405,7 +431,8 @@ obj.trigger('event'); }); - test("nested trigger with unbind", 1, function () { + QUnit.test("nested trigger with unbind", function(assert) { + assert.expect(1); var obj = { counter: 0 }; _.extend(obj, Backbone.Events); var incr1 = function(){ obj.counter += 1; obj.off('event', incr1); obj.trigger('event'); }; @@ -413,23 +440,25 @@ obj.on('event', incr1); obj.on('event', incr2); obj.trigger('event'); - equal(obj.counter, 3, 'counter should have been incremented three times'); + assert.equal(obj.counter, 3, 'counter should have been incremented three times'); }); - test("callback list is not altered during trigger", 2, function () { + QUnit.test("callback list is not altered during trigger", function(assert) { + assert.expect(2); var counter = 0, obj = _.extend({}, Backbone.Events); var incr = function(){ counter++; }; var incrOn = function(){ obj.on('event all', incr); }; var incrOff = function(){ obj.off('event all', incr); }; obj.on('event all', incrOn).trigger('event'); - equal(counter, 0, 'on does not alter callback list'); + assert.equal(counter, 0, 'on does not alter callback list'); obj.off().on('event', incrOff).on('event all', incr).trigger('event'); - equal(counter, 2, 'off does not alter callback list'); + assert.equal(counter, 2, 'off does not alter callback list'); }); - test("#1282 - 'all' callback list is retrieved after each event.", 1, function() { + QUnit.test("#1282 - 'all' callback list is retrieved after each event.", function(assert) { + assert.expect(1); var counter = 0; var obj = _.extend({}, Backbone.Events); var incr = function(){ counter++; }; @@ -437,47 +466,53 @@ obj.on('y', incr).on('all', incr); }) .trigger('x y'); - strictEqual(counter, 2); + assert.strictEqual(counter, 2); }); - test("if no callback is provided, `on` is a noop", 0, function() { + QUnit.test("if no callback is provided, `on` is a noop", function(assert) { + assert.expect(0); _.extend({}, Backbone.Events).on('test').trigger('test'); }); - test("if callback is truthy but not a function, `on` should throw an error just like jQuery", 1, function() { + QUnit.test("if callback is truthy but not a function, `on` should throw an error just like jQuery", function(assert) { + assert.expect(1); var view = _.extend({}, Backbone.Events).on('test', 'noop'); - throws(function() { + assert.throws(function() { view.trigger('test'); }); }); - test("remove all events for a specific context", 4, function() { + QUnit.test("remove all events for a specific context", function(assert) { + assert.expect(4); var obj = _.extend({}, Backbone.Events); - obj.on('x y all', function() { ok(true); }); - obj.on('x y all', function() { ok(false); }, obj); + obj.on('x y all', function() { assert.ok(true); }); + obj.on('x y all', function() { assert.ok(false); }, obj); obj.off(null, null, obj); obj.trigger('x y'); }); - test("remove all events for a specific callback", 4, function() { + QUnit.test("remove all events for a specific callback", function(assert) { + assert.expect(4); var obj = _.extend({}, Backbone.Events); - var success = function() { ok(true); }; - var fail = function() { ok(false); }; + var success = function() { assert.ok(true); }; + var fail = function() { assert.ok(false); }; obj.on('x y all', success); obj.on('x y all', fail); obj.off(null, fail); obj.trigger('x y'); }); - test("#1310 - off does not skip consecutive events", 0, function() { + QUnit.test("#1310 - off does not skip consecutive events", function(assert) { + assert.expect(0); var obj = _.extend({}, Backbone.Events); - obj.on('event', function() { ok(false); }, obj); - obj.on('event', function() { ok(false); }, obj); + obj.on('event', function() { assert.ok(false); }, obj); + obj.on('event', function() { assert.ok(false); }, obj); obj.off(null, null, obj); obj.trigger('event'); }); - test("once", 2, function() { + QUnit.test("once", function(assert) { + assert.expect(2); // Same as the previous test, but we use once rather than having to explicitly unbind var obj = { counterA: 0, counterB: 0 }; _.extend(obj, Backbone.Events); @@ -486,12 +521,13 @@ obj.once('event', incrA); obj.once('event', incrB); obj.trigger('event'); - equal(obj.counterA, 1, 'counterA should have only been incremented once.'); - equal(obj.counterB, 1, 'counterB should have only been incremented once.'); + assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.'); + assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.'); }); - test("once variant one", 3, function() { - var f = function(){ ok(true); }; + QUnit.test("once variant one", function(assert) { + assert.expect(3); + var f = function(){ assert.ok(true); }; var a = _.extend({}, Backbone.Events).once('event', f); var b = _.extend({}, Backbone.Events).on('event', f); @@ -502,8 +538,9 @@ b.trigger('event'); }); - test("once variant two", 3, function() { - var f = function(){ ok(true); }; + QUnit.test("once variant two", function(assert) { + assert.expect(3); + var f = function(){ assert.ok(true); }; var obj = _.extend({}, Backbone.Events); obj @@ -513,8 +550,9 @@ .trigger('event'); }); - test("once with off", 0, function() { - var f = function(){ ok(true); }; + QUnit.test("once with off", function(assert) { + assert.expect(0); + var f = function(){ assert.ok(true); }; var obj = _.extend({}, Backbone.Events); obj.once('event', f); @@ -522,7 +560,7 @@ obj.trigger('event'); }); - test("once with event maps", function() { + QUnit.test("once with event maps", function(assert) { var obj = { counter: 0 }; _.extend(obj, Backbone.Events); @@ -537,94 +575,103 @@ }, obj); obj.trigger('a'); - equal(obj.counter, 1); + assert.equal(obj.counter, 1); obj.trigger('a b'); - equal(obj.counter, 2); + assert.equal(obj.counter, 2); obj.trigger('c'); - equal(obj.counter, 3); + assert.equal(obj.counter, 3); obj.trigger('a b c'); - equal(obj.counter, 3); + assert.equal(obj.counter, 3); }); - test("once with off only by context", 0, function() { + QUnit.test("once with off only by context", function(assert) { + assert.expect(0); var context = {}; var obj = _.extend({}, Backbone.Events); - obj.once('event', function(){ ok(false); }, context); + obj.once('event', function(){ assert.ok(false); }, context); obj.off(null, null, context); obj.trigger('event'); }); - test("Backbone object inherits Events", function() { - ok(Backbone.on === Backbone.Events.on); + QUnit.test("Backbone object inherits Events", function(assert) { + assert.ok(Backbone.on === Backbone.Events.on); }); - asyncTest("once with asynchronous events", 1, function() { - var func = _.debounce(function() { ok(true); start(); }, 50); + QUnit.test("once with asynchronous events", function(assert) { + var done = assert.async(); + assert.expect(1); + var func = _.debounce(function() { assert.ok(true); done(); }, 50); var obj = _.extend({}, Backbone.Events).once('async', func); obj.trigger('async'); obj.trigger('async'); }); - test("once with multiple events.", 2, function() { + QUnit.test("once with multiple events.", function(assert) { + assert.expect(2); var obj = _.extend({}, Backbone.Events); - obj.once('x y', function() { ok(true); }); + obj.once('x y', function() { assert.ok(true); }); obj.trigger('x y'); }); - test("Off during iteration with once.", 2, function() { + QUnit.test("Off during iteration with once.", function(assert) { + assert.expect(2); var obj = _.extend({}, Backbone.Events); var f = function(){ this.off('event', f); }; obj.on('event', f); obj.once('event', function(){}); - obj.on('event', function(){ ok(true); }); + obj.on('event', function(){ assert.ok(true); }); obj.trigger('event'); obj.trigger('event'); }); - test("`once` on `all` should work as expected", 1, function() { + QUnit.test("`once` on `all` should work as expected", function(assert) { + assert.expect(1); Backbone.once('all', function() { - ok(true); + assert.ok(true); Backbone.trigger('all'); }); Backbone.trigger('all'); }); - test("once without a callback is a noop", 0, function() { + QUnit.test("once without a callback is a noop", function(assert) { + assert.expect(0); _.extend({}, Backbone.Events).once('event').trigger('event'); }); - test("listenToOnce without a callback is a noop", 0, function() { + QUnit.test("listenToOnce without a callback is a noop", function(assert) { + assert.expect(0); var obj = _.extend({}, Backbone.Events); obj.listenToOnce(obj, 'event').trigger('event'); }); - test("event functions are chainable", function() { + QUnit.test("event functions are chainable", function(assert) { var obj = _.extend({}, Backbone.Events); var obj2 = _.extend({}, Backbone.Events); var fn = function() {}; - equal(obj, obj.trigger('noeventssetyet')); - equal(obj, obj.off('noeventssetyet')); - equal(obj, obj.stopListening('noeventssetyet')); - equal(obj, obj.on('a', fn)); - equal(obj, obj.once('c', fn)); - equal(obj, obj.trigger('a')); - equal(obj, obj.listenTo(obj2, 'a', fn)); - equal(obj, obj.listenToOnce(obj2, 'b', fn)); - equal(obj, obj.off('a c')); - equal(obj, obj.stopListening(obj2, 'a')); - equal(obj, obj.stopListening()); + assert.equal(obj, obj.trigger('noeventssetyet')); + assert.equal(obj, obj.off('noeventssetyet')); + assert.equal(obj, obj.stopListening('noeventssetyet')); + assert.equal(obj, obj.on('a', fn)); + assert.equal(obj, obj.once('c', fn)); + assert.equal(obj, obj.trigger('a')); + assert.equal(obj, obj.listenTo(obj2, 'a', fn)); + assert.equal(obj, obj.listenToOnce(obj2, 'b', fn)); + assert.equal(obj, obj.off('a c')); + assert.equal(obj, obj.stopListening(obj2, 'a')); + assert.equal(obj, obj.stopListening()); }); - test("#3448 - listenToOnce with space-separated events", 2, function() { + QUnit.test("#3448 - listenToOnce with space-separated events", function(assert) { + assert.expect(2); var one = _.extend({}, Backbone.Events); var two = _.extend({}, Backbone.Events); var count = 1; - one.listenToOnce(two, 'x y', function(n) { ok(n === count++); }); + one.listenToOnce(two, 'x y', function(n) { assert.ok(n === count++); }); two.trigger('x', 1); two.trigger('x', 1); two.trigger('y', 2); diff --git a/vendor/backbone/test/model.js b/vendor/backbone/test/model.js index faaf61dda..e095652cf 100644 --- a/vendor/backbone/test/model.js +++ b/vendor/backbone/test/model.js @@ -6,9 +6,9 @@ }); var doc, collection; - module("Backbone.Model", { + QUnit.module("Backbone.Model", { - setup: function() { + beforeEach: function(assert) { doc = new proxy({ id : '1-the-tempest', title : "The Tempest", @@ -21,29 +21,32 @@ }); - test("initialize", 3, function() { + QUnit.test("initialize", function(assert) { + assert.expect(3); var Model = Backbone.Model.extend({ initialize: function() { this.one = 1; - equal(this.collection, collection); + assert.equal(this.collection, collection); } }); var model = new Model({}, {collection: collection}); - equal(model.one, 1); - equal(model.collection, collection); + assert.equal(model.one, 1); + assert.equal(model.collection, collection); }); - test("initialize with attributes and options", 1, function() { + QUnit.test("initialize with attributes and options", function(assert) { + assert.expect(1); var Model = Backbone.Model.extend({ initialize: function(attributes, options) { this.one = options.one; } }); var model = new Model({}, {one: 1}); - equal(model.one, 1); + assert.equal(model.one, 1); }); - test("initialize with parsed attributes", 1, function() { + QUnit.test("initialize with parsed attributes", function(assert) { + assert.expect(1); var Model = Backbone.Model.extend({ parse: function(attrs) { attrs.value += 1; @@ -51,10 +54,11 @@ } }); var model = new Model({value: 1}, {parse: true}); - equal(model.get('value'), 2); + assert.equal(model.get('value'), 2); }); - test("initialize with defaults", 2, function() { + QUnit.test("initialize with defaults", function(assert) { + assert.expect(2); var Model = Backbone.Model.extend({ defaults: { first_name: 'Unknown', @@ -62,11 +66,12 @@ } }); var model = new Model({'first_name': 'John'}); - equal(model.get('first_name'), 'John'); - equal(model.get('last_name'), 'Unknown'); + assert.equal(model.get('first_name'), 'John'); + assert.equal(model.get('last_name'), 'Unknown'); }); - test("parse can return null", 1, function() { + QUnit.test("parse can return null", function(assert) { + assert.expect(1); var Model = Backbone.Model.extend({ parse: function(attrs) { attrs.value += 1; @@ -74,30 +79,33 @@ } }); var model = new Model({value: 1}, {parse: true}); - equal(JSON.stringify(model.toJSON()), "{}"); + assert.equal(JSON.stringify(model.toJSON()), "{}"); }); - test("url", 3, function() { + QUnit.test("url", function(assert) { + assert.expect(3); doc.urlRoot = null; - equal(doc.url(), '/collection/1-the-tempest'); + assert.equal(doc.url(), '/collection/1-the-tempest'); doc.collection.url = '/collection/'; - equal(doc.url(), '/collection/1-the-tempest'); + assert.equal(doc.url(), '/collection/1-the-tempest'); doc.collection = null; - throws(function() { doc.url(); }); + assert.throws(function() { doc.url(); }); doc.collection = collection; }); - test("url when using urlRoot, and uri encoding", 2, function() { + QUnit.test("url when using urlRoot, and uri encoding", function(assert) { + assert.expect(2); var Model = Backbone.Model.extend({ urlRoot: '/collection' }); var model = new Model(); - equal(model.url(), '/collection'); + assert.equal(model.url(), '/collection'); model.set({id: '+1+'}); - equal(model.url(), '/collection/%2B1%2B'); + assert.equal(model.url(), '/collection/%2B1%2B'); }); - test("url when using urlRoot as a function to determine urlRoot at runtime", 2, function() { + QUnit.test("url when using urlRoot as a function to determine urlRoot at runtime", function(assert) { + assert.expect(2); var Model = Backbone.Model.extend({ urlRoot: function() { return '/nested/' + this.get('parent_id') + '/collection'; @@ -105,79 +113,85 @@ }); var model = new Model({parent_id: 1}); - equal(model.url(), '/nested/1/collection'); + assert.equal(model.url(), '/nested/1/collection'); model.set({id: 2}); - equal(model.url(), '/nested/1/collection/2'); + assert.equal(model.url(), '/nested/1/collection/2'); }); - test("underscore methods", 5, function() { + QUnit.test("underscore methods", function(assert) { + assert.expect(5); var model = new Backbone.Model({ 'foo': 'a', 'bar': 'b', 'baz': 'c' }); var model2 = model.clone(); - deepEqual(model.keys(), ['foo', 'bar', 'baz']); - deepEqual(model.values(), ['a', 'b', 'c']); - deepEqual(model.invert(), { 'a': 'foo', 'b': 'bar', 'c': 'baz' }); - deepEqual(model.pick('foo', 'baz'), {'foo': 'a', 'baz': 'c'}); - deepEqual(model.omit('foo', 'bar'), {'baz': 'c'}); + assert.deepEqual(model.keys(), ['foo', 'bar', 'baz']); + assert.deepEqual(model.values(), ['a', 'b', 'c']); + assert.deepEqual(model.invert(), { 'a': 'foo', 'b': 'bar', 'c': 'baz' }); + assert.deepEqual(model.pick('foo', 'baz'), {'foo': 'a', 'baz': 'c'}); + assert.deepEqual(model.omit('foo', 'bar'), {'baz': 'c'}); }); - test("chain", function() { + QUnit.test("chain", function(assert) { var model = new Backbone.Model({ a: 0, b: 1, c: 2 }); - deepEqual(model.chain().pick("a", "b", "c").values().compact().value(), [1, 2]); + assert.deepEqual(model.chain().pick("a", "b", "c").values().compact().value(), [1, 2]); }); - test("clone", 10, function() { + QUnit.test("clone", function(assert) { + assert.expect(10); var a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3}); var b = a.clone(); - equal(a.get('foo'), 1); - equal(a.get('bar'), 2); - equal(a.get('baz'), 3); - equal(b.get('foo'), a.get('foo'), "Foo should be the same on the clone."); - equal(b.get('bar'), a.get('bar'), "Bar should be the same on the clone."); - equal(b.get('baz'), a.get('baz'), "Baz should be the same on the clone."); + assert.equal(a.get('foo'), 1); + assert.equal(a.get('bar'), 2); + assert.equal(a.get('baz'), 3); + assert.equal(b.get('foo'), a.get('foo'), "Foo should be the same on the clone."); + assert.equal(b.get('bar'), a.get('bar'), "Bar should be the same on the clone."); + assert.equal(b.get('baz'), a.get('baz'), "Baz should be the same on the clone."); a.set({foo : 100}); - equal(a.get('foo'), 100); - equal(b.get('foo'), 1, "Changing a parent attribute does not change the clone."); + assert.equal(a.get('foo'), 100); + assert.equal(b.get('foo'), 1, "Changing a parent attribute does not change the clone."); var foo = new Backbone.Model({p: 1}); var bar = new Backbone.Model({p: 2}); bar.set(foo.clone().attributes, {unset: true}); - equal(foo.get('p'), 1); - equal(bar.get('p'), undefined); + assert.equal(foo.get('p'), 1); + assert.equal(bar.get('p'), undefined); }); - test("isNew", 6, function() { + QUnit.test("isNew", function(assert) { + assert.expect(6); var a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3}); - ok(a.isNew(), "it should be new"); + assert.ok(a.isNew(), "it should be new"); a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3, 'id': -5 }); - ok(!a.isNew(), "any defined ID is legal, negative or positive"); + assert.ok(!a.isNew(), "any defined ID is legal, negative or positive"); a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3, 'id': 0 }); - ok(!a.isNew(), "any defined ID is legal, including zero"); - ok( new Backbone.Model({ }).isNew(), "is true when there is no id"); - ok(!new Backbone.Model({ 'id': 2 }).isNew(), "is false for a positive integer"); - ok(!new Backbone.Model({ 'id': -5 }).isNew(), "is false for a negative integer"); + assert.ok(!a.isNew(), "any defined ID is legal, including zero"); + assert.ok( new Backbone.Model({ }).isNew(), "is true when there is no id"); + assert.ok(!new Backbone.Model({ 'id': 2 }).isNew(), "is false for a positive integer"); + assert.ok(!new Backbone.Model({ 'id': -5 }).isNew(), "is false for a negative integer"); }); - test("get", 2, function() { - equal(doc.get('title'), 'The Tempest'); - equal(doc.get('author'), 'Bill Shakespeare'); + QUnit.test("get", function(assert) { + assert.expect(2); + assert.equal(doc.get('title'), 'The Tempest'); + assert.equal(doc.get('author'), 'Bill Shakespeare'); }); - test("escape", 5, function() { - equal(doc.escape('title'), 'The Tempest'); + QUnit.test("escape", function(assert) { + assert.expect(5); + assert.equal(doc.escape('title'), 'The Tempest'); doc.set({audience: 'Bill & Bob'}); - equal(doc.escape('audience'), 'Bill & Bob'); + assert.equal(doc.escape('audience'), 'Bill & Bob'); doc.set({audience: 'Tim > Joan'}); - equal(doc.escape('audience'), 'Tim > Joan'); + assert.equal(doc.escape('audience'), 'Tim > Joan'); doc.set({audience: 10101}); - equal(doc.escape('audience'), '10101'); + assert.equal(doc.escape('audience'), '10101'); doc.unset('audience'); - equal(doc.escape('audience'), ''); + assert.equal(doc.escape('audience'), ''); }); - test("has", 10, function() { + QUnit.test("has", function(assert) { + assert.expect(10); var model = new Backbone.Model(); - strictEqual(model.has('name'), false); + assert.strictEqual(model.has('name'), false); model.set({ '0': 0, @@ -190,70 +204,73 @@ 'undefined': undefined }); - strictEqual(model.has('0'), true); - strictEqual(model.has('1'), true); - strictEqual(model.has('true'), true); - strictEqual(model.has('false'), true); - strictEqual(model.has('empty'), true); - strictEqual(model.has('name'), true); + assert.strictEqual(model.has('0'), true); + assert.strictEqual(model.has('1'), true); + assert.strictEqual(model.has('true'), true); + assert.strictEqual(model.has('false'), true); + assert.strictEqual(model.has('empty'), true); + assert.strictEqual(model.has('name'), true); model.unset('name'); - strictEqual(model.has('name'), false); - strictEqual(model.has('null'), false); - strictEqual(model.has('undefined'), false); + assert.strictEqual(model.has('name'), false); + assert.strictEqual(model.has('null'), false); + assert.strictEqual(model.has('undefined'), false); }); - test("matches", 4, function() { + QUnit.test("matches", function(assert) { + assert.expect(4); var model = new Backbone.Model(); - strictEqual(model.matches({'name': 'Jonas', 'cool': true}), false); + assert.strictEqual(model.matches({'name': 'Jonas', 'cool': true}), false); model.set({name: 'Jonas', 'cool': true}); - strictEqual(model.matches({'name': 'Jonas'}), true); - strictEqual(model.matches({'name': 'Jonas', 'cool': true}), true); - strictEqual(model.matches({'name': 'Jonas', 'cool': false}), false); + assert.strictEqual(model.matches({'name': 'Jonas'}), true); + assert.strictEqual(model.matches({'name': 'Jonas', 'cool': true}), true); + assert.strictEqual(model.matches({'name': 'Jonas', 'cool': false}), false); }); - test("matches with predicate", function() { + QUnit.test("matches with predicate", function(assert) { var model = new Backbone.Model({a: 0}); - strictEqual(model.matches(function(attr) { + assert.strictEqual(model.matches(function(attr) { return attr.a > 1 && attr.b != null; }), false); model.set({a: 3, b: true}); - strictEqual(model.matches(function(attr) { + assert.strictEqual(model.matches(function(attr) { return attr.a > 1 && attr.b != null; }), true); - }) + }); - test("set and unset", 8, function() { + QUnit.test("set and unset", function(assert) { + assert.expect(8); var a = new Backbone.Model({id: 'id', foo: 1, bar: 2, baz: 3}); var changeCount = 0; a.on("change:foo", function() { changeCount += 1; }); a.set({'foo': 2}); - ok(a.get('foo') == 2, "Foo should have changed."); - ok(changeCount == 1, "Change count should have incremented."); - a.set({'foo': 2}); // set with value that is not new shouldn't fire change event - ok(a.get('foo') == 2, "Foo should NOT have changed, still 2"); - ok(changeCount == 1, "Change count should NOT have incremented."); + assert.ok(a.get('foo') == 2, "Foo should have changed."); + assert.ok(changeCount == 1, "Change count should have incremented."); + // set with value that is not new shouldn't fire change event + a.set({'foo': 2}); + assert.ok(a.get('foo') == 2, "Foo should NOT have changed, still 2"); + assert.ok(changeCount == 1, "Change count should NOT have incremented."); a.validate = function(attrs) { - equal(attrs.foo, void 0, "validate:true passed while unsetting"); + assert.equal(attrs.foo, void 0, "validate:true passed while unsetting"); }; a.unset('foo', {validate: true}); - equal(a.get('foo'), void 0, "Foo should have changed"); + assert.equal(a.get('foo'), void 0, "Foo should have changed"); delete a.validate; - ok(changeCount == 2, "Change count should have incremented for unset."); + assert.ok(changeCount == 2, "Change count should have incremented for unset."); a.unset('id'); - equal(a.id, undefined, "Unsetting the id should remove the id property."); + assert.equal(a.id, undefined, "Unsetting the id should remove the id property."); }); - test("#2030 - set with failed validate, followed by another set triggers change", function () { + QUnit.test("#2030 - set with failed validate, followed by another set triggers change", function(assert) { var attr = 0, main = 0, error = 0; var Model = Backbone.Model.extend({ validate: function (attr) { @@ -264,28 +281,29 @@ } }); var model = new Model({x:0}); - model.on('change:x', function () { attr++; }); - model.on('change', function () { main++; }); - model.set({x:2}, {validate:true}); - model.set({x:1}, {validate:true}); - deepEqual([attr, main, error], [1, 1, 1]); + model.on('change:x', function () { attr++; }); + model.on('change', function () { main++; }); + model.set({x:2}, {validate:true}); + model.set({x:1}, {validate:true}); + assert.deepEqual([attr, main, error], [1, 1, 1]); }); - test("set triggers changes in the correct order", function() { + QUnit.test("set triggers changes in the correct order", function(assert) { var value = null; var model = new Backbone.Model; model.on('last', function(){ value = 'last'; }); model.on('first', function(){ value = 'first'; }); model.trigger('first'); model.trigger('last'); - equal(value, 'last'); + assert.equal(value, 'last'); }); - test("set falsy values in the correct order", 2, function() { + QUnit.test("set falsy values in the correct order", function(assert) { + assert.expect(2); var model = new Backbone.Model({result: 'result'}); model.on('change', function() { - equal(model.changed.result, void 0); - equal(model.previous('result'), false); + assert.equal(model.changed.result, void 0); + assert.equal(model.previous('result'), false); }); model.set({result: void 0}, {silent: true}); model.set({result: null}, {silent: true}); @@ -293,7 +311,7 @@ model.set({result: void 0}); }); - test("nested set triggers with the correct options", function() { + QUnit.test("nested set triggers with the correct options", function(assert) { var model = new Backbone.Model(); var o1 = {}; var o2 = {}; @@ -301,19 +319,20 @@ model.on('change', function(__, options) { switch (model.get('a')) { case 1: - equal(options, o1); + assert.equal(options, o1); return model.set('a', 2, o2); case 2: - equal(options, o2); + assert.equal(options, o2); return model.set('a', 3, o3); case 3: - equal(options, o3); + assert.equal(options, o3); } }); model.set('a', 1, o1); }); - test("multiple unsets", 1, function() { + QUnit.test("multiple unsets", function(assert) { + assert.expect(1); var i = 0; var counter = function(){ i++; }; var model = new Backbone.Model({a: 1}); @@ -321,65 +340,70 @@ model.set({a: 2}); model.unset('a'); model.unset('a'); - equal(i, 2, 'Unset does not fire an event for missing attributes.'); + assert.equal(i, 2, 'Unset does not fire an event for missing attributes.'); }); - test("unset and changedAttributes", 1, function() { + QUnit.test("unset and changedAttributes", function(assert) { + assert.expect(1); var model = new Backbone.Model({a: 1}); model.on('change', function() { - ok('a' in model.changedAttributes(), 'changedAttributes should contain unset properties'); + assert.ok('a' in model.changedAttributes(), 'changedAttributes should contain unset properties'); }); model.unset('a'); }); - test("using a non-default id attribute.", 5, function() { + QUnit.test("using a non-default id attribute.", function(assert) { + assert.expect(5); var MongoModel = Backbone.Model.extend({idAttribute : '_id'}); var model = new MongoModel({id: 'eye-dee', _id: 25, title: 'Model'}); - equal(model.get('id'), 'eye-dee'); - equal(model.id, 25); - equal(model.isNew(), false); + assert.equal(model.get('id'), 'eye-dee'); + assert.equal(model.id, 25); + assert.equal(model.isNew(), false); model.unset('_id'); - equal(model.id, undefined); - equal(model.isNew(), true); + assert.equal(model.id, undefined); + assert.equal(model.isNew(), true); }); - test("setting an alternative cid prefix", 4, function() { + QUnit.test("setting an alternative cid prefix", function(assert) { + assert.expect(4); var Model = Backbone.Model.extend({ cidPrefix: 'm' }); var model = new Model(); - equal(model.cid.charAt(0), 'm'); + assert.equal(model.cid.charAt(0), 'm'); model = new Backbone.Model(); - equal(model.cid.charAt(0), 'c'); + assert.equal(model.cid.charAt(0), 'c'); var Collection = Backbone.Collection.extend({ model: Model }); var collection = new Collection([{id: 'c5'}, {id: 'c6'}, {id: 'c7'}]); - equal(collection.get('c6').cid.charAt(0), 'm'); + assert.equal(collection.get('c6').cid.charAt(0), 'm'); collection.set([{id: 'c6', value: 'test'}], { merge: true, add: true, remove: false }); - ok(collection.get('c6').has('value')); + assert.ok(collection.get('c6').has('value')); }); - test("set an empty string", 1, function() { + QUnit.test("set an empty string", function(assert) { + assert.expect(1); var model = new Backbone.Model({name : "Model"}); model.set({name : ''}); - equal(model.get('name'), ''); + assert.equal(model.get('name'), ''); }); - test("setting an object", 1, function() { + QUnit.test("setting an object", function(assert) { + assert.expect(1); var model = new Backbone.Model({ custom: { foo: 1 } }); model.on('change', function() { - ok(1); + assert.ok(1); }); model.set({ custom: { foo: 1 } // no change should be fired @@ -389,20 +413,22 @@ }); }); - test("clear", 3, function() { + QUnit.test("clear", function(assert) { + assert.expect(3); var changed; var model = new Backbone.Model({id: 1, name : "Model"}); model.on("change:name", function(){ changed = true; }); model.on("change", function() { var changedAttrs = model.changedAttributes(); - ok('name' in changedAttrs); + assert.ok('name' in changedAttrs); }); model.clear(); - equal(changed, true); - equal(model.get('name'), undefined); + assert.equal(changed, true); + assert.equal(model.get('name'), undefined); }); - test("defaults", 4, function() { + QUnit.test("defaults", function(assert) { + assert.expect(4); var Defaulted = Backbone.Model.extend({ defaults: { "one": 1, @@ -410,8 +436,8 @@ } }); var model = new Defaulted({two: undefined}); - equal(model.get('one'), 1); - equal(model.get('two'), 2); + assert.equal(model.get('one'), 1); + assert.equal(model.get('two'), 2); Defaulted = Backbone.Model.extend({ defaults: function() { return { @@ -421,66 +447,72 @@ } }); model = new Defaulted({two: undefined}); - equal(model.get('one'), 3); - equal(model.get('two'), 4); + assert.equal(model.get('one'), 3); + assert.equal(model.get('two'), 4); }); - test("change, hasChanged, changedAttributes, previous, previousAttributes", 9, function() { + QUnit.test("change, hasChanged, changedAttributes, previous, previousAttributes", function(assert) { + assert.expect(9); var model = new Backbone.Model({name: "Tim", age: 10}); - deepEqual(model.changedAttributes(), false); + assert.deepEqual(model.changedAttributes(), false); model.on('change', function() { - ok(model.hasChanged('name'), 'name changed'); - ok(!model.hasChanged('age'), 'age did not'); - ok(_.isEqual(model.changedAttributes(), {name : 'Rob'}), 'changedAttributes returns the changed attrs'); - equal(model.previous('name'), 'Tim'); - ok(_.isEqual(model.previousAttributes(), {name : "Tim", age : 10}), 'previousAttributes is correct'); + assert.ok(model.hasChanged('name'), 'name changed'); + assert.ok(!model.hasChanged('age'), 'age did not'); + assert.ok(_.isEqual(model.changedAttributes(), {name : 'Rob'}), 'changedAttributes returns the changed attrs'); + assert.equal(model.previous('name'), 'Tim'); + assert.ok(_.isEqual(model.previousAttributes(), {name : "Tim", age : 10}), 'previousAttributes is correct'); }); - equal(model.hasChanged(), false); - equal(model.hasChanged(undefined), false); + assert.equal(model.hasChanged(), false); + assert.equal(model.hasChanged(undefined), false); model.set({name : 'Rob'}); - equal(model.get('name'), 'Rob'); + assert.equal(model.get('name'), 'Rob'); }); - test("changedAttributes", 3, function() { + QUnit.test("changedAttributes", function(assert) { + assert.expect(3); var model = new Backbone.Model({a: 'a', b: 'b'}); - deepEqual(model.changedAttributes(), false); - equal(model.changedAttributes({a: 'a'}), false); - equal(model.changedAttributes({a: 'b'}).a, 'b'); + assert.deepEqual(model.changedAttributes(), false); + assert.equal(model.changedAttributes({a: 'a'}), false); + assert.equal(model.changedAttributes({a: 'b'}).a, 'b'); }); - test("change with options", 2, function() { + QUnit.test("change with options", function(assert) { + assert.expect(2); var value; var model = new Backbone.Model({name: 'Rob'}); model.on('change', function(model, options) { value = options.prefix + model.get('name'); }); model.set({name: 'Bob'}, {prefix: 'Mr. '}); - equal(value, 'Mr. Bob'); + assert.equal(value, 'Mr. Bob'); model.set({name: 'Sue'}, {prefix: 'Ms. '}); - equal(value, 'Ms. Sue'); + assert.equal(value, 'Ms. Sue'); }); - test("change after initialize", 1, function () { + QUnit.test("change after initialize", function(assert) { + assert.expect(1); var changed = 0; var attrs = {id: 1, label: 'c'}; var obj = new Backbone.Model(attrs); obj.on('change', function() { changed += 1; }); obj.set(attrs); - equal(changed, 0); + assert.equal(changed, 0); }); - test("save within change event", 1, function () { + QUnit.test("save within change event", function(assert) { + assert.expect(1); var env = this; var model = new Backbone.Model({firstName : "Taylor", lastName: "Swift"}); model.url = '/test'; model.on('change', function () { model.save(); - ok(_.isEqual(env.syncArgs.model, model)); + assert.ok(_.isEqual(env.syncArgs.model, model)); }); model.set({lastName: 'Hicks'}); }); - test("validate after save", 2, function() { + QUnit.test("validate after save", function(assert) { + assert.expect(2); var lastError, model = new Backbone.Model(); model.validate = function(attrs) { if (attrs.admin) return "Can't change admin status."; @@ -493,20 +525,22 @@ }); model.save(null); - equal(lastError, "Can't change admin status."); - equal(model.validationError, "Can't change admin status."); + assert.equal(lastError, "Can't change admin status."); + assert.equal(model.validationError, "Can't change admin status."); }); - test("save", 2, function() { + QUnit.test("save", function(assert) { + assert.expect(2); doc.save({title : "Henry V"}); - equal(this.syncArgs.method, 'update'); - ok(_.isEqual(this.syncArgs.model, doc)); + assert.equal(this.syncArgs.method, 'update'); + assert.ok(_.isEqual(this.syncArgs.model, doc)); }); - test("save, fetch, destroy triggers error event when an error occurs", 3, function () { + QUnit.test("save, fetch, destroy triggers error event when an error occurs", function(assert) { + assert.expect(3); var model = new Backbone.Model(); model.on('error', function () { - ok(true); + assert.ok(true); }); model.sync = function (method, model, options) { options.error(); @@ -516,13 +550,14 @@ model.destroy(); }); - test("#3283 - save, fetch, destroy calls success with context", 3, function () { + QUnit.test("#3283 - save, fetch, destroy calls success with context", function(assert) { + assert.expect(3); var model = new Backbone.Model(); var obj = {}; var options = { context: obj, success: function() { - equal(this, obj); + assert.equal(this, obj); } }; model.sync = function (method, model, options) { @@ -533,13 +568,14 @@ model.destroy(options); }); - test("#3283 - save, fetch, destroy calls error with context", 3, function () { + QUnit.test("#3283 - save, fetch, destroy calls error with context", function(assert) { + assert.expect(3); var model = new Backbone.Model(); var obj = {}; var options = { context: obj, error: function() { - equal(this, obj); + assert.equal(this, obj); } }; model.sync = function (method, model, options) { @@ -550,53 +586,56 @@ model.destroy(options); }); - test("#3470 - save and fetch with parse false", 2, function() { + QUnit.test("#3470 - save and fetch with parse false", function(assert) { + assert.expect(2); var i = 0; var model = new Backbone.Model(); model.parse = function() { - ok(false); + assert.ok(false); }; model.sync = function(method, model, options) { options.success({i: ++i}); }; model.fetch({parse: false}); - equal(model.get('i'), i); + assert.equal(model.get('i'), i); model.save(null, {parse: false}); - equal(model.get('i'), i); + assert.equal(model.get('i'), i); }); - test("save with PATCH", function() { + QUnit.test("save with PATCH", function(assert) { doc.clear().set({id: 1, a: 1, b: 2, c: 3, d: 4}); doc.save(); - equal(this.syncArgs.method, 'update'); - equal(this.syncArgs.options.attrs, undefined); + assert.equal(this.syncArgs.method, 'update'); + assert.equal(this.syncArgs.options.attrs, undefined); doc.save({b: 2, d: 4}, {patch: true}); - equal(this.syncArgs.method, 'patch'); - equal(_.size(this.syncArgs.options.attrs), 2); - equal(this.syncArgs.options.attrs.d, 4); - equal(this.syncArgs.options.attrs.a, undefined); - equal(this.ajaxSettings.data, "{\"b\":2,\"d\":4}"); + assert.equal(this.syncArgs.method, 'patch'); + assert.equal(_.size(this.syncArgs.options.attrs), 2); + assert.equal(this.syncArgs.options.attrs.d, 4); + assert.equal(this.syncArgs.options.attrs.a, undefined); + assert.equal(this.ajaxSettings.data, "{\"b\":2,\"d\":4}"); }); - test("save with PATCH and different attrs", function() { + QUnit.test("save with PATCH and different attrs", function(assert) { doc.clear().save({b: 2, d: 4}, {patch: true, attrs: {B: 1, D: 3}}); - equal(this.syncArgs.options.attrs.D, 3); - equal(this.syncArgs.options.attrs.d, undefined); - equal(this.ajaxSettings.data, "{\"B\":1,\"D\":3}"); - deepEqual(doc.attributes, {b: 2, d: 4}); + assert.equal(this.syncArgs.options.attrs.D, 3); + assert.equal(this.syncArgs.options.attrs.d, undefined); + assert.equal(this.ajaxSettings.data, "{\"B\":1,\"D\":3}"); + assert.deepEqual(doc.attributes, {b: 2, d: 4}); }); - test("save in positional style", 1, function() { + QUnit.test("save in positional style", function(assert) { + assert.expect(1); var model = new Backbone.Model(); model.sync = function(method, model, options) { options.success(); }; model.save('title', 'Twelfth Night'); - equal(model.get('title'), 'Twelfth Night'); + assert.equal(model.get('title'), 'Twelfth Night'); }); - test("save with non-object success response", 2, function () { + QUnit.test("save with non-object success response", function(assert) { + assert.expect(2); var model = new Backbone.Model(); model.sync = function(method, model, options) { options.success('', options); @@ -604,21 +643,22 @@ }; model.save({testing:'empty'}, { success: function (model) { - deepEqual(model.attributes, {testing:'empty'}); + assert.deepEqual(model.attributes, {testing:'empty'}); } }); }); - test("save with wait and supplied id", function() { + QUnit.test("save with wait and supplied id", function(assert) { var Model = Backbone.Model.extend({ urlRoot: '/collection' }); var model = new Model(); model.save({id: 42}, {wait: true}); - equal(this.ajaxSettings.url, '/collection/42'); + assert.equal(this.ajaxSettings.url, '/collection/42'); }); - test("save will pass extra options to success callback", 1, function () { + QUnit.test("save will pass extra options to success callback", function(assert) { + assert.expect(1); var SpecialSyncModel = Backbone.Model.extend({ sync: function (method, model, options) { _.extend(options, { specialSync: true }); @@ -630,20 +670,22 @@ var model = new SpecialSyncModel(); var onSuccess = function (model, response, options) { - ok(options.specialSync, "Options were passed correctly to callback"); + assert.ok(options.specialSync, "Options were passed correctly to callback"); }; model.save(null, { success: onSuccess }); this.ajaxSettings.success(); }); - test("fetch", 2, function() { + QUnit.test("fetch", function(assert) { + assert.expect(2); doc.fetch(); - equal(this.syncArgs.method, 'read'); - ok(_.isEqual(this.syncArgs.model, doc)); + assert.equal(this.syncArgs.method, 'read'); + assert.ok(_.isEqual(this.syncArgs.model, doc)); }); - test("fetch will pass extra options to success callback", 1, function () { + QUnit.test("fetch will pass extra options to success callback", function(assert) { + assert.expect(1); var SpecialSyncModel = Backbone.Model.extend({ sync: function (method, model, options) { _.extend(options, { specialSync: true }); @@ -655,23 +697,25 @@ var model = new SpecialSyncModel(); var onSuccess = function (model, response, options) { - ok(options.specialSync, "Options were passed correctly to callback"); + assert.ok(options.specialSync, "Options were passed correctly to callback"); }; model.fetch({ success: onSuccess }); this.ajaxSettings.success(); }); - test("destroy", 3, function() { + QUnit.test("destroy", function(assert) { + assert.expect(3); doc.destroy(); - equal(this.syncArgs.method, 'delete'); - ok(_.isEqual(this.syncArgs.model, doc)); + assert.equal(this.syncArgs.method, 'delete'); + assert.ok(_.isEqual(this.syncArgs.model, doc)); var newModel = new Backbone.Model; - equal(newModel.destroy(), false); + assert.equal(newModel.destroy(), false); }); - test("destroy will pass extra options to success callback", 1, function () { + QUnit.test("destroy will pass extra options to success callback", function(assert) { + assert.expect(1); var SpecialSyncModel = Backbone.Model.extend({ sync: function (method, model, options) { _.extend(options, { specialSync: true }); @@ -683,21 +727,22 @@ var model = new SpecialSyncModel({ id: 'id' }); var onSuccess = function (model, response, options) { - ok(options.specialSync, "Options were passed correctly to callback"); + assert.ok(options.specialSync, "Options were passed correctly to callback"); }; model.destroy({ success: onSuccess }); this.ajaxSettings.success(); }); - test("non-persisted destroy", 1, function() { + QUnit.test("non-persisted destroy", function(assert) { + assert.expect(1); var a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3}); a.sync = function() { throw "should not be called"; }; a.destroy(); - ok(true, "non-persisted model should not call sync"); + assert.ok(true, "non-persisted model should not call sync"); }); - test("validate", function() { + QUnit.test("validate", function(assert) { var lastError; var model = new Backbone.Model(); model.validate = function(attrs) { @@ -707,18 +752,19 @@ lastError = error; }); var result = model.set({a: 100}); - equal(result, model); - equal(model.get('a'), 100); - equal(lastError, undefined); + assert.equal(result, model); + assert.equal(model.get('a'), 100); + assert.equal(lastError, undefined); result = model.set({admin: true}); - equal(model.get('admin'), true); + assert.equal(model.get('admin'), true); result = model.set({a: 200, admin: false}, {validate:true}); - equal(lastError, "Can't change admin status."); - equal(result, false); - equal(model.get('a'), 100); + assert.equal(lastError, "Can't change admin status."); + assert.equal(result, false); + assert.equal(model.get('a'), 100); }); - test("validate on unset and clear", 6, function() { + QUnit.test("validate on unset and clear", function(assert) { + assert.expect(6); var error; var model = new Backbone.Model({name: "One"}); model.validate = function(attrs) { @@ -728,19 +774,20 @@ } }; model.set({name: "Two"}); - equal(model.get('name'), 'Two'); - equal(error, undefined); + assert.equal(model.get('name'), 'Two'); + assert.equal(error, undefined); model.unset('name', {validate: true}); - equal(error, true); - equal(model.get('name'), 'Two'); + assert.equal(error, true); + assert.equal(model.get('name'), 'Two'); model.clear({validate:true}); - equal(model.get('name'), 'Two'); + assert.equal(model.get('name'), 'Two'); delete model.validate; model.clear(); - equal(model.get('name'), undefined); + assert.equal(model.get('name'), undefined); }); - test("validate with error callback", 8, function() { + QUnit.test("validate with error callback", function(assert) { + assert.expect(8); var lastError, boundError; var model = new Backbone.Model(); model.validate = function(attrs) { @@ -750,29 +797,31 @@ boundError = true; }); var result = model.set({a: 100}, {validate:true}); - equal(result, model); - equal(model.get('a'), 100); - equal(model.validationError, null); - equal(boundError, undefined); + assert.equal(result, model); + assert.equal(model.get('a'), 100); + assert.equal(model.validationError, null); + assert.equal(boundError, undefined); result = model.set({a: 200, admin: true}, {validate:true}); - equal(result, false); - equal(model.get('a'), 100); - equal(model.validationError, "Can't change admin status."); - equal(boundError, true); + assert.equal(result, false); + assert.equal(model.get('a'), 100); + assert.equal(model.validationError, "Can't change admin status."); + assert.equal(boundError, true); }); - test("defaults always extend attrs (#459)", 2, function() { + QUnit.test("defaults always extend attrs (#459)", function(assert) { + assert.expect(2); var Defaulted = Backbone.Model.extend({ defaults: {one: 1}, initialize : function(attrs, opts) { - equal(this.attributes.one, 1); + assert.equal(this.attributes.one, 1); } }); var providedattrs = new Defaulted({}); var emptyattrs = new Defaulted(); }); - test("Inherit class properties", 6, function() { + QUnit.test("Inherit class properties", function(assert) { + assert.expect(6); var Parent = Backbone.Model.extend({ instancePropSame: function() {}, instancePropDiff: function() {} @@ -786,17 +835,18 @@ var adult = new Parent; var kid = new Child; - equal(Child.classProp, Parent.classProp); - notEqual(Child.classProp, undefined); + assert.equal(Child.classProp, Parent.classProp); + assert.notEqual(Child.classProp, undefined); - equal(kid.instancePropSame, adult.instancePropSame); - notEqual(kid.instancePropSame, undefined); + assert.equal(kid.instancePropSame, adult.instancePropSame); + assert.notEqual(kid.instancePropSame, undefined); - notEqual(Child.prototype.instancePropDiff, Parent.prototype.instancePropDiff); - notEqual(Child.prototype.instancePropDiff, undefined); + assert.notEqual(Child.prototype.instancePropDiff, Parent.prototype.instancePropDiff); + assert.notEqual(Child.prototype.instancePropDiff, undefined); }); - test("Nested change events don't clobber previous attributes", 4, function() { + QUnit.test("Nested change events don't clobber previous attributes", function(assert) { + assert.expect(4); new Backbone.Model() .on('change:state', function(model, newState) { equal(model.previous('state'), undefined); @@ -811,25 +861,27 @@ .set({state: 'hello'}); }); - test("hasChanged/set should use same comparison", 2, function() { + QUnit.test("hasChanged/set should use same comparison", function(assert) { + assert.expect(2); var changed = 0, model = new Backbone.Model({a: null}); model.on('change', function() { - ok(this.hasChanged('a')); + assert.ok(this.hasChanged('a')); }) .on('change:a', function() { changed++; }) .set({a: undefined}); - equal(changed, 1); + assert.equal(changed, 1); }); - test("#582, #425, change:attribute callbacks should fire after all changes have occurred", 9, function() { + QUnit.test("#582, #425, change:attribute callbacks should fire after all changes have occurred", function(assert) { + assert.expect(9); var model = new Backbone.Model; var assertion = function() { - equal(model.get('a'), 'a'); - equal(model.get('b'), 'b'); - equal(model.get('c'), 'c'); + assert.equal(model.get('a'), 'a'); + assert.equal(model.get('b'), 'b'); + assert.equal(model.get('c'), 'c'); }; model.on('change:a', assertion); @@ -839,146 +891,160 @@ model.set({a: 'a', b: 'b', c: 'c'}); }); - test("#871, set with attributes property", 1, function() { + QUnit.test("#871, set with attributes property", function(assert) { + assert.expect(1); var model = new Backbone.Model(); model.set({attributes: true}); - ok(model.has('attributes')); + assert.ok(model.has('attributes')); }); - test("set value regardless of equality/change", 1, function() { + QUnit.test("set value regardless of equality/change", function(assert) { + assert.expect(1); var model = new Backbone.Model({x: []}); var a = []; model.set({x: a}); - ok(model.get('x') === a); + assert.ok(model.get('x') === a); }); - test("set same value does not trigger change", 0, function() { + QUnit.test("set same value does not trigger change", function(assert) { + assert.expect(0); var model = new Backbone.Model({x: 1}); - model.on('change change:x', function() { ok(false); }); + model.on('change change:x', function() { assert.ok(false); }); model.set({x: 1}); model.set({x: 1}); }); - test("unset does not fire a change for undefined attributes", 0, function() { + QUnit.test("unset does not fire a change for undefined attributes", function(assert) { + assert.expect(0); var model = new Backbone.Model({x: undefined}); - model.on('change:x', function(){ ok(false); }); + model.on('change:x', function(){ assert.ok(false); }); model.unset('x'); }); - test("set: undefined values", 1, function() { + QUnit.test("set: undefined values", function(assert) { + assert.expect(1); var model = new Backbone.Model({x: undefined}); - ok('x' in model.attributes); + assert.ok('x' in model.attributes); }); - test("hasChanged works outside of change events, and true within", 6, function() { + QUnit.test("hasChanged works outside of change events, and true within", function(assert) { + assert.expect(6); var model = new Backbone.Model({x: 1}); model.on('change:x', function() { - ok(model.hasChanged('x')); - equal(model.get('x'), 1); + assert.ok(model.hasChanged('x')); + assert.equal(model.get('x'), 1); }); model.set({x: 2}, {silent: true}); - ok(model.hasChanged()); - equal(model.hasChanged('x'), true); + assert.ok(model.hasChanged()); + assert.equal(model.hasChanged('x'), true); model.set({x: 1}); - ok(model.hasChanged()); - equal(model.hasChanged('x'), true); + assert.ok(model.hasChanged()); + assert.equal(model.hasChanged('x'), true); }); - test("hasChanged gets cleared on the following set", 4, function() { + QUnit.test("hasChanged gets cleared on the following set", function(assert) { + assert.expect(4); var model = new Backbone.Model; model.set({x: 1}); - ok(model.hasChanged()); + assert.ok(model.hasChanged()); model.set({x: 1}); - ok(!model.hasChanged()); + assert.ok(!model.hasChanged()); model.set({x: 2}); - ok(model.hasChanged()); + assert.ok(model.hasChanged()); model.set({}); - ok(!model.hasChanged()); + assert.ok(!model.hasChanged()); }); - test("save with `wait` succeeds without `validate`", 1, function() { + QUnit.test("save with `wait` succeeds without `validate`", function(assert) { + assert.expect(1); var model = new Backbone.Model(); model.url = '/test'; model.save({x: 1}, {wait: true}); - ok(this.syncArgs.model === model); + assert.ok(this.syncArgs.model === model); }); - test("save without `wait` doesn't set invalid attributes", function () { + QUnit.test("save without `wait` doesn't set invalid attributes", function(assert) { var model = new Backbone.Model(); - model.validate = function () { return 1; } + model.validate = function () { return 1; }; model.save({a: 1}); - equal(model.get('a'), void 0); + assert.equal(model.get('a'), void 0); }); - test("save doesn't validate twice", function () { + QUnit.test("save doesn't validate twice", function(assert) { var model = new Backbone.Model(); var times = 0; model.sync = function () {}; - model.validate = function () { ++times; } + model.validate = function () { ++times; }; model.save({}); - equal(times, 1); + assert.equal(times, 1); }); - test("`hasChanged` for falsey keys", 2, function() { + QUnit.test("`hasChanged` for falsey keys", function(assert) { + assert.expect(2); var model = new Backbone.Model(); model.set({x: true}, {silent: true}); - ok(!model.hasChanged(0)); - ok(!model.hasChanged('')); + assert.ok(!model.hasChanged(0)); + assert.ok(!model.hasChanged('')); }); - test("`previous` for falsey keys", 2, function() { + QUnit.test("`previous` for falsey keys", function(assert) { + assert.expect(2); var model = new Backbone.Model({0: true, '': true}); model.set({0: false, '': false}, {silent: true}); - equal(model.previous(0), true); - equal(model.previous(''), true); + assert.equal(model.previous(0), true); + assert.equal(model.previous(''), true); }); - test("`save` with `wait` sends correct attributes", 5, function() { + QUnit.test("`save` with `wait` sends correct attributes", function(assert) { + assert.expect(5); var changed = 0; var model = new Backbone.Model({x: 1, y: 2}); model.url = '/test'; model.on('change:x', function() { changed++; }); model.save({x: 3}, {wait: true}); - deepEqual(JSON.parse(this.ajaxSettings.data), {x: 3, y: 2}); - equal(model.get('x'), 1); - equal(changed, 0); + assert.deepEqual(JSON.parse(this.ajaxSettings.data), {x: 3, y: 2}); + assert.equal(model.get('x'), 1); + assert.equal(changed, 0); this.syncArgs.options.success({}); - equal(model.get('x'), 3); - equal(changed, 1); + assert.equal(model.get('x'), 3); + assert.equal(changed, 1); }); - test("a failed `save` with `wait` doesn't leave attributes behind", 1, function() { + QUnit.test("a failed `save` with `wait` doesn't leave attributes behind", function(assert) { + assert.expect(1); var model = new Backbone.Model; model.url = '/test'; model.save({x: 1}, {wait: true}); - equal(model.get('x'), void 0); + assert.equal(model.get('x'), void 0); }); - test("#1030 - `save` with `wait` results in correct attributes if success is called during sync", 2, function() { + QUnit.test("#1030 - `save` with `wait` results in correct attributes if success is called during sync", function(assert) { + assert.expect(2); var model = new Backbone.Model({x: 1, y: 2}); model.sync = function(method, model, options) { options.success(); }; - model.on("change:x", function() { ok(true); }); + model.on("change:x", function() { assert.ok(true); }); model.save({x: 3}, {wait: true}); - equal(model.get('x'), 3); + assert.equal(model.get('x'), 3); }); - test("save with wait validates attributes", function() { + QUnit.test("save with wait validates attributes", function(assert) { var model = new Backbone.Model(); model.url = '/test'; - model.validate = function() { ok(true); }; + model.validate = function() { assert.ok(true); }; model.save({x: 1}, {wait: true}); }); - test("save turns on parse flag", function () { + QUnit.test("save turns on parse flag", function(assert) { var Model = Backbone.Model.extend({ - sync: function(method, model, options) { ok(options.parse); } + sync: function(method, model, options) { assert.ok(options.parse); } }); new Model().save(); }); - test("nested `set` during `'change:attr'`", 2, function() { + QUnit.test("nested `set` during `'change:attr'`", function(assert) { + assert.expect(2); var events = []; var model = new Backbone.Model(); model.on('all', function(event) { events.push(event); }); @@ -989,75 +1055,79 @@ model.set({y: true}); }); model.set({x: true}); - deepEqual(events, ['change:y', 'change:x', 'change']); + assert.deepEqual(events, ['change:y', 'change:x', 'change']); events = []; model.set({z: true}); - deepEqual(events, []); + assert.deepEqual(events, []); }); - test("nested `change` only fires once", 1, function() { + QUnit.test("nested `change` only fires once", function(assert) { + assert.expect(1); var model = new Backbone.Model(); model.on('change', function() { - ok(true); + assert.ok(true); model.set({x: true}); }); model.set({x: true}); }); - test("nested `set` during `'change'`", 6, function() { + QUnit.test("nested `set` during `'change'`", function(assert) { + assert.expect(6); var count = 0; var model = new Backbone.Model(); model.on('change', function() { switch(count++) { case 0: - deepEqual(this.changedAttributes(), {x: true}); - equal(model.previous('x'), undefined); + assert.deepEqual(this.changedAttributes(), {x: true}); + assert.equal(model.previous('x'), undefined); model.set({y: true}); break; case 1: - deepEqual(this.changedAttributes(), {x: true, y: true}); - equal(model.previous('x'), undefined); + assert.deepEqual(this.changedAttributes(), {x: true, y: true}); + assert.equal(model.previous('x'), undefined); model.set({z: true}); break; case 2: - deepEqual(this.changedAttributes(), {x: true, y: true, z: true}); - equal(model.previous('y'), undefined); + assert.deepEqual(this.changedAttributes(), {x: true, y: true, z: true}); + assert.equal(model.previous('y'), undefined); break; default: - ok(false); + assert.ok(false); } }); model.set({x: true}); }); - test("nested `change` with silent", 3, function() { + QUnit.test("nested `change` with silent", function(assert) { + assert.expect(3); var count = 0; var model = new Backbone.Model(); - model.on('change:y', function() { ok(false); }); + model.on('change:y', function() { assert.ok(false); }); model.on('change', function() { switch(count++) { case 0: - deepEqual(this.changedAttributes(), {x: true}); + assert.deepEqual(this.changedAttributes(), {x: true}); model.set({y: true}, {silent: true}); model.set({z: true}); break; case 1: - deepEqual(this.changedAttributes(), {x: true, y: true, z: true}); + assert.deepEqual(this.changedAttributes(), {x: true, y: true, z: true}); break; case 2: - deepEqual(this.changedAttributes(), {z: false}); + assert.deepEqual(this.changedAttributes(), {z: false}); break; default: - ok(false); + assert.ok(false); } }); model.set({x: true}); model.set({z: false}); }); - test("nested `change:attr` with silent", 0, function() { + QUnit.test("nested `change:attr` with silent", function(assert) { + assert.expect(0); var model = new Backbone.Model(); - model.on('change:y', function(){ ok(false); }); + model.on('change:y', function(){ assert.ok(false); }); model.on('change', function() { model.set({y: true}, {silent: true}); model.set({z: true}); @@ -1065,19 +1135,21 @@ model.set({x: true}); }); - test("multiple nested changes with silent", 1, function() { + QUnit.test("multiple nested changes with silent", function(assert) { + assert.expect(1); var model = new Backbone.Model(); model.on('change:x', function() { model.set({y: 1}, {silent: true}); model.set({y: 2}); }); model.on('change:y', function(model, val) { - equal(val, 2); + assert.equal(val, 2); }); model.set({x: true}); }); - test("multiple nested changes with silent", 1, function() { + QUnit.test("multiple nested changes with silent", function(assert) { + assert.expect(1); var changes = []; var model = new Backbone.Model(); model.on('change:b', function(model, val) { changes.push(val); }); @@ -1085,21 +1157,23 @@ model.set({b: 1}); }); model.set({b: 0}); - deepEqual(changes, [0, 1]); + assert.deepEqual(changes, [0, 1]); }); - test("basic silent change semantics", 1, function() { + QUnit.test("basic silent change semantics", function(assert) { + assert.expect(1); var model = new Backbone.Model; model.set({x: 1}); - model.on('change', function(){ ok(true); }); + model.on('change', function(){ assert.ok(true); }); model.set({x: 2}, {silent: true}); model.set({x: 1}); }); - test("nested set multiple times", 1, function() { + QUnit.test("nested set multiple times", function(assert) { + assert.expect(1); var model = new Backbone.Model(); model.on('change:b', function() { - ok(true); + assert.ok(true); }); model.on('change:a', function() { model.set({b: true}); @@ -1108,25 +1182,28 @@ model.set({a: true}); }); - test("#1122 - clear does not alter options.", 1, function() { + QUnit.test("#1122 - clear does not alter options.", function(assert) { + assert.expect(1); var model = new Backbone.Model(); var options = {}; model.clear(options); - ok(!options.unset); + assert.ok(!options.unset); }); - test("#1122 - unset does not alter options.", 1, function() { + QUnit.test("#1122 - unset does not alter options.", function(assert) { + assert.expect(1); var model = new Backbone.Model(); var options = {}; model.unset('x', options); - ok(!options.unset); + assert.ok(!options.unset); }); - test("#1355 - `options` is passed to success callbacks", 3, function() { + QUnit.test("#1355 - `options` is passed to success callbacks", function(assert) { + assert.expect(3); var model = new Backbone.Model(); var opts = { success: function( model, resp, options ) { - ok(options); + assert.ok(options); } }; model.sync = function(method, model, options) { @@ -1137,77 +1214,86 @@ model.destroy(opts); }); - test("#1412 - Trigger 'sync' event.", 3, function() { + QUnit.test("#1412 - Trigger 'sync' event.", function(assert) { + assert.expect(3); var model = new Backbone.Model({id: 1}); model.sync = function (method, model, options) { options.success(); }; - model.on('sync', function(){ ok(true); }); + model.on('sync', function(){ assert.ok(true); }); model.fetch(); model.save(); model.destroy(); }); - asyncTest("#1365 - Destroy: New models execute success callback.", 2, function() { + QUnit.test("#1365 - Destroy: New models execute success callback.", function(assert) { + var done = assert.async(); + assert.expect(2); new Backbone.Model() - .on('sync', function() { ok(false); }) - .on('destroy', function(){ ok(true); }) + .on('sync', function() { assert.ok(false); }) + .on('destroy', function(){ assert.ok(true); }) .destroy({ success: function(){ - ok(true); - start(); + assert.ok(true); + done(); }}); }); - test("#1433 - Save: An invalid model cannot be persisted.", 1, function() { + QUnit.test("#1433 - Save: An invalid model cannot be persisted.", function(assert) { + assert.expect(1); var model = new Backbone.Model; model.validate = function(){ return 'invalid'; }; - model.sync = function(){ ok(false); }; - strictEqual(model.save(), false); + model.sync = function(){ assert.ok(false); }; + assert.strictEqual(model.save(), false); }); - test("#1377 - Save without attrs triggers 'error'.", 1, function() { + QUnit.test("#1377 - Save without attrs triggers 'error'.", function(assert) { + assert.expect(1); var Model = Backbone.Model.extend({ url: '/test/', sync: function(method, model, options){ options.success(); }, validate: function(){ return 'invalid'; } }); var model = new Model({id: 1}); - model.on('invalid', function(){ ok(true); }); + model.on('invalid', function(){ assert.ok(true); }); model.save(); }); - test("#1545 - `undefined` can be passed to a model constructor without coersion", function() { + QUnit.test("#1545 - `undefined` can be passed to a model constructor without coersion", function(assert) { var Model = Backbone.Model.extend({ defaults: { one: 1 }, initialize : function(attrs, opts) { - equal(attrs, undefined); + assert.equal(attrs, undefined); } }); var emptyattrs = new Model(); var undefinedattrs = new Model(undefined); }); - asyncTest("#1478 - Model `save` does not trigger change on unchanged attributes", 0, function() { + QUnit.test("#1478 - Model `save` does not trigger change on unchanged attributes", function(assert) { + var done = assert.async(); + assert.expect(0); var Model = Backbone.Model.extend({ sync: function(method, model, options) { setTimeout(function(){ options.success(); - start(); + done(); }, 0); } }); new Model({x: true}) - .on('change:x', function(){ ok(false); }) + .on('change:x', function(){ assert.ok(false); }) .save(null, {wait: true}); }); - test("#1664 - Changing from one value, silently to another, back to original triggers a change.", 1, function() { + QUnit.test("#1664 - Changing from one value, silently to another, back to original triggers a change.", function(assert) { + assert.expect(1); var model = new Backbone.Model({x:1}); - model.on('change:x', function() { ok(true); }); + model.on('change:x', function() { assert.ok(true); }); model.set({x:2},{silent:true}); model.set({x:3},{silent:true}); model.set({x:1}); }); - test("#1664 - multiple silent changes nested inside a change event", 2, function() { + QUnit.test("#1664 - multiple silent changes nested inside a change event", function(assert) { + assert.expect(2); var changes = []; var model = new Backbone.Model(); model.on('change', function() { @@ -1217,19 +1303,20 @@ }); model.on('change:a change:b change:c', function(model, val) { changes.push(val); }); model.set({a:'a', b:1, c:'item'}); - deepEqual(changes, ['a',1,'item']); - deepEqual(model.attributes, {a: 'c', b: 2}); + assert.deepEqual(changes, ['a',1,'item']); + assert.deepEqual(model.attributes, {a: 'c', b: 2}); }); - test("#1791 - `attributes` is available for `parse`", function() { + QUnit.test("#1791 - `attributes` is available for `parse`", function(assert) { var Model = Backbone.Model.extend({ parse: function() { this.has('a'); } // shouldn't throw an error }); var model = new Model(null, {parse: true}); - expect(0); + assert.expect(0); }); - test("silent changes in last `change` event back to original triggers change", 2, function() { + QUnit.test("silent changes in last `change` event back to original triggers change", function(assert) { + assert.expect(2); var changes = []; var model = new Backbone.Model(); model.on('change:a change:b change:c', function(model, val) { changes.push(val); }); @@ -1237,62 +1324,65 @@ model.set({a:'c'}, {silent:true}); }); model.set({a:'a'}); - deepEqual(changes, ['a']); + assert.deepEqual(changes, ['a']); model.set({a:'a'}); - deepEqual(changes, ['a', 'a']); + assert.deepEqual(changes, ['a', 'a']); }); - test("#1943 change calculations should use _.isEqual", function() { + QUnit.test("#1943 change calculations should use _.isEqual", function(assert) { var model = new Backbone.Model({a: {key: 'value'}}); model.set('a', {key:'value'}, {silent:true}); - equal(model.changedAttributes(), false); + assert.equal(model.changedAttributes(), false); }); - test("#1964 - final `change` event is always fired, regardless of interim changes", 1, function () { + QUnit.test("#1964 - final `change` event is always fired, regardless of interim changes", function(assert) { + assert.expect(1); var model = new Backbone.Model(); model.on('change:property', function() { model.set('property', 'bar'); }); model.on('change', function() { - ok(true); + assert.ok(true); }); model.set('property', 'foo'); }); - test("isValid", function() { + QUnit.test("isValid", function(assert) { var model = new Backbone.Model({valid: true}); model.validate = function(attrs) { if (!attrs.valid) return "invalid"; }; - equal(model.isValid(), true); - equal(model.set({valid: false}, {validate:true}), false); - equal(model.isValid(), true); + assert.equal(model.isValid(), true); + assert.equal(model.set({valid: false}, {validate:true}), false); + assert.equal(model.isValid(), true); model.set({valid:false}); - equal(model.isValid(), false); - ok(!model.set('valid', false, {validate: true})); + assert.equal(model.isValid(), false); + assert.ok(!model.set('valid', false, {validate: true})); }); - test("#1179 - isValid returns true in the absence of validate.", 1, function() { + QUnit.test("#1179 - isValid returns true in the absence of validate.", function(assert) { + assert.expect(1); var model = new Backbone.Model(); model.validate = null; - ok(model.isValid()); + assert.ok(model.isValid()); }); - test("#1961 - Creating a model with {validate:true} will call validate and use the error callback", function () { + QUnit.test("#1961 - Creating a model with {validate:true} will call validate and use the error callback", function(assert) { var Model = Backbone.Model.extend({ validate: function (attrs) { if (attrs.id === 1) return "This shouldn't happen"; } }); var model = new Model({id: 1}, {validate: true}); - equal(model.validationError, "This shouldn't happen"); + assert.equal(model.validationError, "This shouldn't happen"); }); - test("toJSON receives attrs during save(..., {wait: true})", 1, function() { + QUnit.test("toJSON receives attrs during save(..., {wait: true})", function(assert) { + assert.expect(1); var Model = Backbone.Model.extend({ url: '/test', toJSON: function() { - strictEqual(this.attributes.x, 1); + assert.strictEqual(this.attributes.x, 1); return _.clone(this.attributes); } }); @@ -1300,13 +1390,24 @@ model.save({x: 1}, {wait: true}); }); - test("#2034 - nested set with silent only triggers one change", 1, function() { + QUnit.test("#2034 - nested set with silent only triggers one change", function(assert) { + assert.expect(1); var model = new Backbone.Model(); model.on('change', function() { model.set({b: true}, {silent: true}); - ok(true); + assert.ok(true); }); model.set({a: true}); }); + QUnit.test('#3778 - id will only be updated if it is set', function(assert) { + assert.expect(2); + var model = new Backbone.Model({id: 1}); + model.id = 2; + model.set({foo: 'bar'}); + assert.equal(model.id, 2); + model.set({id: 3}); + assert.equal(model.id, 3); + }); + })(); diff --git a/vendor/backbone/test/noconflict.js b/vendor/backbone/test/noconflict.js index ac4324d02..40d39ebc6 100644 --- a/vendor/backbone/test/noconflict.js +++ b/vendor/backbone/test/noconflict.js @@ -1,12 +1,13 @@ (function() { - module("Backbone.noConflict"); + QUnit.module("Backbone.noConflict"); - test('noConflict', 2, function() { + QUnit.test('noConflict', function(assert) { + assert.expect(2); var noconflictBackbone = Backbone.noConflict(); - equal(window.Backbone, undefined, 'Returned window.Backbone'); + assert.equal(window.Backbone, undefined, 'Returned window.Backbone'); window.Backbone = noconflictBackbone; - equal(window.Backbone, noconflictBackbone, 'Backbone is still pointing to the original Backbone'); + assert.equal(window.Backbone, noconflictBackbone, 'Backbone is still pointing to the original Backbone'); }); })(); diff --git a/vendor/backbone/test/router.js b/vendor/backbone/test/router.js index 324ed07f2..891d1e8e8 100644 --- a/vendor/backbone/test/router.js +++ b/vendor/backbone/test/router.js @@ -40,7 +40,7 @@ }); - module("Backbone.Router", { + QUnit.module("Backbone.Router", { setup: function() { location = new Location('http://example.com'); @@ -176,167 +176,189 @@ }); - test("initialize", 1, function() { - equal(router.testing, 101); + QUnit.test("initialize", function(assert) { + assert.expect(1); + assert.equal(router.testing, 101); }); - test("routes (simple)", 4, function() { + QUnit.test("routes (simple)", function(assert) { + assert.expect(4); location.replace('http://example.com#search/news'); Backbone.history.checkUrl(); - equal(router.query, 'news'); - equal(router.page, void 0); - equal(lastRoute, 'search'); - equal(lastArgs[0], 'news'); + assert.equal(router.query, 'news'); + assert.equal(router.page, void 0); + assert.equal(lastRoute, 'search'); + assert.equal(lastArgs[0], 'news'); }); - test("routes (simple, but unicode)", 4, function() { + QUnit.test("routes (simple, but unicode)", function(assert) { + assert.expect(4); location.replace('http://example.com#search/тест'); Backbone.history.checkUrl(); - equal(router.query, "тест"); - equal(router.page, void 0); - equal(lastRoute, 'search'); - equal(lastArgs[0], "тест"); + assert.equal(router.query, "тест"); + assert.equal(router.page, void 0); + assert.equal(lastRoute, 'search'); + assert.equal(lastArgs[0], "тест"); }); - test("routes (two part)", 2, function() { + QUnit.test("routes (two part)", function(assert) { + assert.expect(2); location.replace('http://example.com#search/nyc/p10'); Backbone.history.checkUrl(); - equal(router.query, 'nyc'); - equal(router.page, '10'); + assert.equal(router.query, 'nyc'); + assert.equal(router.page, '10'); }); - test("routes via navigate", 2, function() { + QUnit.test("routes via navigate", function(assert) { + assert.expect(2); Backbone.history.navigate('search/manhattan/p20', {trigger: true}); - equal(router.query, 'manhattan'); - equal(router.page, '20'); + assert.equal(router.query, 'manhattan'); + assert.equal(router.page, '20'); }); - test("routes via navigate with params", 1, function() { + QUnit.test("routes via navigate with params", function(assert) { + assert.expect(1); Backbone.history.navigate('query/test?a=b', {trigger: true}); - equal(router.queryArgs, 'a=b'); + assert.equal(router.queryArgs, 'a=b'); }); - test("routes via navigate for backwards-compatibility", 2, function() { + QUnit.test("routes via navigate for backwards-compatibility", function(assert) { + assert.expect(2); Backbone.history.navigate('search/manhattan/p20', true); - equal(router.query, 'manhattan'); - equal(router.page, '20'); + assert.equal(router.query, 'manhattan'); + assert.equal(router.page, '20'); }); - test("reports matched route via nagivate", 1, function() { - ok(Backbone.history.navigate('search/manhattan/p20', true)); + QUnit.test("reports matched route via nagivate", function(assert) { + assert.expect(1); + assert.ok(Backbone.history.navigate('search/manhattan/p20', true)); }); - test("route precedence via navigate", 6, function(){ + QUnit.test("route precedence via navigate", function(assert){ + assert.expect(6); // check both 0.9.x and backwards-compatibility options _.each([ { trigger: true }, true ], function( options ){ Backbone.history.navigate('contacts', options); - equal(router.contact, 'index'); + assert.equal(router.contact, 'index'); Backbone.history.navigate('contacts/new', options); - equal(router.contact, 'new'); + assert.equal(router.contact, 'new'); Backbone.history.navigate('contacts/foo', options); - equal(router.contact, 'load'); + assert.equal(router.contact, 'load'); }); }); - test("loadUrl is not called for identical routes.", 0, function() { - Backbone.history.loadUrl = function(){ ok(false); }; + QUnit.test("loadUrl is not called for identical routes.", function(assert) { + assert.expect(0); + Backbone.history.loadUrl = function(){ assert.ok(false); }; location.replace('http://example.com#route'); Backbone.history.navigate('route'); Backbone.history.navigate('/route'); Backbone.history.navigate('/route'); }); - test("use implicit callback if none provided", 1, function() { + QUnit.test("use implicit callback if none provided", function(assert) { + assert.expect(1); router.count = 0; router.navigate('implicit', {trigger: true}); - equal(router.count, 1); + assert.equal(router.count, 1); }); - test("routes via navigate with {replace: true}", 1, function() { + QUnit.test("routes via navigate with {replace: true}", function(assert) { + assert.expect(1); location.replace('http://example.com#start_here'); Backbone.history.checkUrl(); location.replace = function(href) { - strictEqual(href, new Location('http://example.com#end_here').href); + assert.strictEqual(href, new Location('http://example.com#end_here').href); }; Backbone.history.navigate('end_here', {replace: true}); }); - test("routes (splats)", 1, function() { + QUnit.test("routes (splats)", function(assert) { + assert.expect(1); location.replace('http://example.com#splat/long-list/of/splatted_99args/end'); Backbone.history.checkUrl(); - equal(router.args, 'long-list/of/splatted_99args'); + assert.equal(router.args, 'long-list/of/splatted_99args'); }); - test("routes (github)", 3, function() { + QUnit.test("routes (github)", function(assert) { + assert.expect(3); location.replace('http://example.com#backbone/compare/1.0...braddunbar:with/slash'); Backbone.history.checkUrl(); - equal(router.repo, 'backbone'); - equal(router.from, '1.0'); - equal(router.to, 'braddunbar:with/slash'); + assert.equal(router.repo, 'backbone'); + assert.equal(router.from, '1.0'); + assert.equal(router.to, 'braddunbar:with/slash'); }); - test("routes (optional)", 2, function() { + QUnit.test("routes (optional)", function(assert) { + assert.expect(2); location.replace('http://example.com#optional'); Backbone.history.checkUrl(); - ok(!router.arg); + assert.ok(!router.arg); location.replace('http://example.com#optional/thing'); Backbone.history.checkUrl(); - equal(router.arg, 'thing'); + assert.equal(router.arg, 'thing'); }); - test("routes (complex)", 3, function() { + QUnit.test("routes (complex)", function(assert) { + assert.expect(3); location.replace('http://example.com#one/two/three/complex-part/four/five/six/seven'); Backbone.history.checkUrl(); - equal(router.first, 'one/two/three'); - equal(router.part, 'part'); - equal(router.rest, 'four/five/six/seven'); + assert.equal(router.first, 'one/two/three'); + assert.equal(router.part, 'part'); + assert.equal(router.rest, 'four/five/six/seven'); }); - test("routes (query)", 5, function() { + QUnit.test("routes (query)", function(assert) { + assert.expect(5); 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'); - equal(lastRoute, 'query'); - equal(lastArgs[0], 'mandel'); - equal(lastArgs[1], 'a=b&c=d'); + assert.equal(router.entity, 'mandel'); + assert.equal(router.queryArgs, 'a=b&c=d'); + assert.equal(lastRoute, 'query'); + assert.equal(lastArgs[0], 'mandel'); + assert.equal(lastArgs[1], 'a=b&c=d'); }); - test("routes (anything)", 1, function() { + QUnit.test("routes (anything)", function(assert) { + assert.expect(1); location.replace('http://example.com#doesnt-match-a-route'); Backbone.history.checkUrl(); - equal(router.anything, 'doesnt-match-a-route'); + assert.equal(router.anything, 'doesnt-match-a-route'); }); - test("routes (function)", 3, function() { + QUnit.test("routes (function)", function(assert) { + assert.expect(3); router.on('route', function(name) { - ok(name === ''); + assert.ok(name === ''); }); - equal(ExternalObject.value, 'unset'); + assert.equal(ExternalObject.value, 'unset'); location.replace('http://example.com#function/set'); Backbone.history.checkUrl(); - equal(ExternalObject.value, 'set'); + assert.equal(ExternalObject.value, 'set'); }); - test("Decode named parameters, not splats.", 2, function() { + QUnit.test("Decode named parameters, not splats.", function(assert) { + assert.expect(2); location.replace('http://example.com#decode/a%2Fb/c%2Fd/e'); Backbone.history.checkUrl(); - strictEqual(router.named, 'a/b'); - strictEqual(router.path, 'c/d/e'); + assert.strictEqual(router.named, 'a/b'); + assert.strictEqual(router.path, 'c/d/e'); }); - test("fires event when router doesn't have callback on it", 1, function() { - router.on("route:noCallback", function(){ ok(true); }); + QUnit.test("fires event when router doesn't have callback on it", function(assert) { + assert.expect(1); + router.on("route:noCallback", function(){ assert.ok(true); }); location.replace('http://example.com#noCallback'); Backbone.history.checkUrl(); }); - test("No events are triggered if #execute returns false.", 1, function() { + QUnit.test("No events are triggered if #execute returns false.", function(assert) { + assert.expect(1); var Router = Backbone.Router.extend({ routes: { foo: function() { - ok(true); + assert.ok(true); } }, @@ -350,92 +372,100 @@ var router = new Router; router.on('route route:foo', function() { - ok(false); + assert.ok(false); }); Backbone.history.on('route', function() { - ok(false); + assert.ok(false); }); location.replace('http://example.com#foo'); Backbone.history.checkUrl(); }); - test("#933, #908 - leading slash", 2, function() { + QUnit.test("#933, #908 - leading slash", function(assert) { + assert.expect(2); location.replace('http://example.com/root/foo'); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history.start({root: '/root', hashChange: false, silent: true}); - strictEqual(Backbone.history.getFragment(), 'foo'); + assert.strictEqual(Backbone.history.getFragment(), 'foo'); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history.start({root: '/root/', hashChange: false, silent: true}); - strictEqual(Backbone.history.getFragment(), 'foo'); + assert.strictEqual(Backbone.history.getFragment(), 'foo'); }); - test("#967 - Route callback gets passed encoded values.", 3, function() { + QUnit.test("#967 - Route callback gets passed encoded values.", function(assert) { + assert.expect(3); var route = 'has%2Fslash/complex-has%23hash/has%20space'; Backbone.history.navigate(route, {trigger: true}); - strictEqual(router.first, 'has/slash'); - strictEqual(router.part, 'has#hash'); - strictEqual(router.rest, 'has space'); + assert.strictEqual(router.first, 'has/slash'); + assert.strictEqual(router.part, 'has#hash'); + assert.strictEqual(router.rest, 'has space'); }); - test("correctly handles URLs with % (#868)", 3, function() { + QUnit.test("correctly handles URLs with % (#868)", function(assert) { + assert.expect(3); location.replace('http://example.com#search/fat%3A1.5%25'); Backbone.history.checkUrl(); location.replace('http://example.com#search/fat'); Backbone.history.checkUrl(); - equal(router.query, 'fat'); - equal(router.page, void 0); - equal(lastRoute, 'search'); + assert.equal(router.query, 'fat'); + assert.equal(router.page, void 0); + assert.equal(lastRoute, 'search'); }); - test("#2666 - Hashes with UTF8 in them.", 2, function() { + QUnit.test("#2666 - Hashes with UTF8 in them.", function(assert) { + assert.expect(2); Backbone.history.navigate('charñ', {trigger: true}); - equal(router.charType, 'UTF'); + assert.equal(router.charType, 'UTF'); Backbone.history.navigate('char%C3%B1', {trigger: true}); - equal(router.charType, 'UTF'); + assert.equal(router.charType, 'UTF'); }); - test("#1185 - Use pathname when hashChange is not wanted.", 1, function() { + QUnit.test("#1185 - Use pathname when hashChange is not wanted.", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/path/name#hash'); Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history.start({hashChange: false}); var fragment = Backbone.history.getFragment(); - strictEqual(fragment, location.pathname.replace(/^\//, '')); + assert.strictEqual(fragment, location.pathname.replace(/^\//, '')); }); - test("#1206 - Strip leading slash before location.assign.", 1, function() { + QUnit.test("#1206 - Strip leading slash before location.assign.", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/root/'); Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history.start({hashChange: false, root: '/root/'}); location.assign = function(pathname) { - strictEqual(pathname, '/root/fragment'); + assert.strictEqual(pathname, '/root/fragment'); }; Backbone.history.navigate('/fragment'); }); - test("#1387 - Root fragment without trailing slash.", 1, function() { + QUnit.test("#1387 - Root fragment without trailing slash.", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/root'); Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history.start({hashChange: false, root: '/root/', silent: true}); - strictEqual(Backbone.history.getFragment(), ''); + assert.strictEqual(Backbone.history.getFragment(), ''); }); - test("#1366 - History does not prepend root to fragment.", 2, function() { + QUnit.test("#1366 - History does not prepend root to fragment.", function(assert) { + assert.expect(2); Backbone.history.stop(); location.replace('http://example.com/root/'); Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(state, title, url) { - strictEqual(url, '/root/x'); + assert.strictEqual(url, '/root/x'); } } }); @@ -445,17 +475,18 @@ hashChange: false }); Backbone.history.navigate('x'); - strictEqual(Backbone.history.fragment, 'x'); + assert.strictEqual(Backbone.history.fragment, 'x'); }); - test("Normalize root.", 1, function() { + QUnit.test("Normalize root.", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/root'); Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(state, title, url) { - strictEqual(url, '/root/fragment'); + assert.strictEqual(url, '/root/fragment'); } } }); @@ -467,7 +498,8 @@ Backbone.history.navigate('fragment'); }); - test("Normalize root.", 1, function() { + QUnit.test("Normalize root.", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/root#fragment'); Backbone.history = _.extend(new Backbone.History, { @@ -475,7 +507,7 @@ history: { pushState: function(state, title, url) {}, replaceState: function(state, title, url) { - strictEqual(url, '/root/fragment'); + assert.strictEqual(url, '/root/fragment'); } } }); @@ -485,18 +517,20 @@ }); }); - test("Normalize root.", 1, function() { + QUnit.test("Normalize root.", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/root'); Backbone.history = _.extend(new Backbone.History, {location: location}); - Backbone.history.loadUrl = function() { ok(true); }; + Backbone.history.loadUrl = function() { assert.ok(true); }; Backbone.history.start({ pushState: true, root: '/root' }); }); - test("Normalize root - leading slash.", 1, function() { + QUnit.test("Normalize root - leading slash.", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/root'); Backbone.history = _.extend(new Backbone.History, { @@ -507,10 +541,11 @@ } }); Backbone.history.start({root: 'root'}); - strictEqual(Backbone.history.root, '/root/'); + assert.strictEqual(Backbone.history.root, '/root/'); }); - test("Transition from hashChange to pushState.", 1, function() { + QUnit.test("Transition from hashChange to pushState.", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/root#x/y'); Backbone.history = _.extend(new Backbone.History, { @@ -518,7 +553,7 @@ history: { pushState: function(){}, replaceState: function(state, title, url){ - strictEqual(url, '/root/x/y'); + assert.strictEqual(url, '/root/x/y'); } } }); @@ -528,7 +563,8 @@ }); }); - test("#1619: Router: Normalize empty root", 1, function() { + QUnit.test("#1619: Router: Normalize empty root", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/'); Backbone.history = _.extend(new Backbone.History, { @@ -539,17 +575,18 @@ } }); Backbone.history.start({root: ''}); - strictEqual(Backbone.history.root, '/'); + assert.strictEqual(Backbone.history.root, '/'); }); - test("#1619: Router: nagivate with empty root", 1, function() { + QUnit.test("#1619: Router: nagivate with empty root", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/'); Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(state, title, url) { - strictEqual(url, '/fragment'); + assert.strictEqual(url, '/fragment'); } } }); @@ -561,11 +598,12 @@ Backbone.history.navigate('fragment'); }); - test("Transition from pushState to hashChange.", 1, function() { + QUnit.test("Transition from pushState to hashChange.", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/root/x/y?a=b'); location.replace = function(url) { - strictEqual(url, '/root#x/y?a=b'); + assert.strictEqual(url, '/root#x/y?a=b'); }; Backbone.history = _.extend(new Backbone.History, { location: location, @@ -580,7 +618,8 @@ }); }); - test("#1695 - hashChange to pushState with search.", 1, function() { + QUnit.test("#1695 - hashChange to pushState with search.", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/root#x/y?a=b'); Backbone.history = _.extend(new Backbone.History, { @@ -588,7 +627,7 @@ history: { pushState: function(){}, replaceState: function(state, title, url){ - strictEqual(url, '/root/x/y?a=b'); + assert.strictEqual(url, '/root/x/y?a=b'); } } }); @@ -598,46 +637,51 @@ }); }); - test("#1746 - Router allows empty route.", 1, function() { + QUnit.test("#1746 - Router allows empty route.", function(assert) { + assert.expect(1); var Router = Backbone.Router.extend({ routes: {'': 'empty'}, empty: function(){}, route: function(route){ - strictEqual(route, ''); + assert.strictEqual(route, ''); } }); new Router; }); - test("#1794 - Trailing space in fragments.", 1, function() { + QUnit.test("#1794 - Trailing space in fragments.", function(assert) { + assert.expect(1); var history = new Backbone.History; - strictEqual(history.getFragment('fragment '), 'fragment'); + assert.strictEqual(history.getFragment('fragment '), 'fragment'); }); - test("#1820 - Leading slash and trailing space.", 1, function() { + QUnit.test("#1820 - Leading slash and trailing space.", 1, function(assert) { var history = new Backbone.History; - strictEqual(history.getFragment('/fragment '), 'fragment'); + assert.strictEqual(history.getFragment('/fragment '), 'fragment'); }); - test("#1980 - Optional parameters.", 2, function() { + QUnit.test("#1980 - Optional parameters.", function(assert) { + assert.expect(2); location.replace('http://example.com#named/optional/y'); Backbone.history.checkUrl(); - strictEqual(router.z, undefined); + assert.strictEqual(router.z, undefined); location.replace('http://example.com#named/optional/y123'); Backbone.history.checkUrl(); - strictEqual(router.z, '123'); + assert.strictEqual(router.z, '123'); }); - test("#2062 - Trigger 'route' event on router instance.", 2, function() { + QUnit.test("#2062 - Trigger 'route' event on router instance.", function(assert) { + assert.expect(2); router.on('route', function(name, args) { - strictEqual(name, 'routeEvent'); - deepEqual(args, ['x', null]); + assert.strictEqual(name, 'routeEvent'); + assert.deepEqual(args, ['x', null]); }); location.replace('http://example.com#route-event/x'); Backbone.history.checkUrl(); }); - test("#2255 - Extend routes by making routes a function.", 1, function() { + QUnit.test("#2255 - Extend routes by making routes a function.", function(assert) { + assert.expect(1); var RouterBase = Backbone.Router.extend({ routes: function() { return { @@ -657,17 +701,18 @@ }); var router = new RouterExtended(); - deepEqual({home: "root", index: "index.html", show: "show", search: "search"}, router.routes); + assert.deepEqual({home: "root", index: "index.html", show: "show", search: "search"}, router.routes); }); - test("#2538 - hashChange to pushState only if both requested.", 0, function() { + QUnit.test("#2538 - hashChange to pushState only if both requested.", function(assert) { + assert.expect(0); Backbone.history.stop(); location.replace('http://example.com/root?a=b#x/y'); Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(){}, - replaceState: function(){ ok(false); } + replaceState: function(){ assert.ok(false); } } }); Backbone.history.start({ @@ -677,7 +722,8 @@ }); }); - test('No hash fallback.', 0, function() { + QUnit.test('No hash fallback.', function(assert) { + assert.expect(0); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, { location: location, @@ -689,7 +735,7 @@ var Router = Backbone.Router.extend({ routes: { - hash: function() { ok(false); } + hash: function() { assert.ok(false); } } }); var router = new Router; @@ -703,13 +749,14 @@ Backbone.history.checkUrl(); }); - test('#2656 - No trailing slash on root.', 1, function() { + QUnit.test('#2656 - No trailing slash on root.', function(assert) { + assert.expect(1); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(state, title, url){ - strictEqual(url, '/root'); + assert.strictEqual(url, '/root'); } } }); @@ -718,13 +765,14 @@ Backbone.history.navigate(''); }); - test('#2656 - No trailing slash on root.', 1, function() { + QUnit.test('#2656 - No trailing slash on root.', function(assert) { + assert.expect(1); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(state, title, url) { - strictEqual(url, '/'); + assert.strictEqual(url, '/'); } } }); @@ -733,13 +781,14 @@ Backbone.history.navigate(''); }); - test('#2656 - No trailing slash on root.', 1, function() { + QUnit.test('#2656 - No trailing slash on root.', function(assert) { + assert.expect(1); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(state, title, url){ - strictEqual(url, '/root?x=1'); + assert.strictEqual(url, '/root?x=1'); } } }); @@ -748,20 +797,21 @@ Backbone.history.navigate('?x=1'); }); - test('#2765 - Fragment matching sans query/hash.', 2, function() { + QUnit.test('#2765 - Fragment matching sans query/hash.', function(assert) { + assert.expect(2); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(state, title, url) { - strictEqual(url, '/path?query#hash'); + assert.strictEqual(url, '/path?query#hash'); } } }); var Router = Backbone.Router.extend({ routes: { - path: function() { ok(true); } + path: function() { assert.ok(true); } } }); var router = new Router; @@ -771,11 +821,12 @@ Backbone.history.navigate('path?query#hash', true); }); - test('Do not decode the search params.', function() { + QUnit.test('Do not decode the search params.', function(assert) { + assert.expect(1); var Router = Backbone.Router.extend({ routes: { path: function(params){ - strictEqual(params, 'x=y%3Fz'); + assert.strictEqual(params, 'x=y%3Fz'); } } }); @@ -783,14 +834,15 @@ Backbone.history.navigate('path?x=y%3Fz', true); }); - test('Navigate to a hash url.', function() { + QUnit.test('Navigate to a hash url.', function(assert) { + assert.expect(1); 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'); + assert.strictEqual(params, 'x=y'); } } }); @@ -799,14 +851,15 @@ Backbone.history.checkUrl(); }); - test('#navigate to a hash url.', function() { + QUnit.test('#navigate to a hash url.', function(assert) { + assert.expect(1); 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'); + assert.strictEqual(params, 'x=y'); } } }); @@ -814,14 +867,15 @@ Backbone.history.navigate('path?x=y#hash', true); }); - test('unicode pathname', 1, function() { + QUnit.test('unicode pathname', function(assert) { + assert.expect(1); 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); + assert.ok(true); } } }); @@ -829,7 +883,8 @@ Backbone.history.start({pushState: true}); }); - test('unicode pathname with % in a parameter', 1, function() { + QUnit.test('unicode pathname with % in a parameter', function(assert) { + assert.expect(1); location.replace('http://example.com/myyjä/foo%20%25%3F%2f%40%25%20bar'); location.pathname = '/myyj%C3%A4/foo%20%25%3F%2f%40%25%20bar'; Backbone.history.stop(); @@ -837,7 +892,7 @@ var Router = Backbone.Router.extend({ routes: { 'myyjä/:query': function(query) { - strictEqual(query, 'foo %?/@% bar'); + assert.strictEqual(query, 'foo %?/@% bar'); } } }); @@ -845,14 +900,15 @@ Backbone.history.start({pushState: true}); }); - test('newline in route', 1, function() { + QUnit.test('newline in route', function(assert) { + assert.expect(1); location.replace('http://example.com/stuff%0Anonsense?param=foo%0Abar'); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, {location: location}); var Router = Backbone.Router.extend({ routes: { 'stuff\nnonsense': function() { - ok(true); + assert.ok(true); } } }); @@ -860,7 +916,8 @@ Backbone.history.start({pushState: true}); }); - test('Router#execute receives callback, args, name.', 3, function() { + QUnit.test('Router#execute receives callback, args, name.', function(assert) { + assert.expect(3); location.replace('http://example.com#foo/123/bar?x=y'); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, {location: location}); @@ -868,20 +925,21 @@ routes: {'foo/:id/bar': 'foo'}, foo: function(){}, execute: function(callback, args, name) { - strictEqual(callback, this.foo); - deepEqual(args, ['123', 'x=y']); - strictEqual(name, 'foo'); + assert.strictEqual(callback, this.foo); + assert.deepEqual(args, ['123', 'x=y']); + assert.strictEqual(name, 'foo'); } }); var router = new Router; Backbone.history.start(); }); - test("pushState to hashChange with only search params.", 1, function() { + QUnit.test("pushState to hashChange with only search params.", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com?a=b'); location.replace = function(url) { - strictEqual(url, '/#?a=b'); + assert.strictEqual(url, '/#?a=b'); }; Backbone.history = _.extend(new Backbone.History, { location: location, @@ -890,37 +948,40 @@ Backbone.history.start({pushState: true}); }); - test("#3123 - History#navigate decodes before comparison.", 1, function() { + QUnit.test("#3123 - History#navigate decodes before comparison.", function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/shop/search?keyword=short%20dress'); Backbone.history = _.extend(new Backbone.History, { location: location, history: { - pushState: function(){ ok(false); }, - replaceState: function(){ ok(false); } + pushState: function(){ assert.ok(false); }, + replaceState: function(){ assert.ok(false); } } }); Backbone.history.start({pushState: true}); Backbone.history.navigate('shop/search?keyword=short%20dress', true); - strictEqual(Backbone.history.fragment, 'shop/search?keyword=short dress'); + assert.strictEqual(Backbone.history.fragment, 'shop/search?keyword=short dress'); }); - test('#3175 - Urls in the params', 1, function() { + QUnit.test('#3175 - Urls in the params', function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com#login?a=value&backUrl=https%3A%2F%2Fwww.msn.com%2Fidp%2Fidpdemo%3Fspid%3Dspdemo%26target%3Db'); Backbone.history = _.extend(new Backbone.History, {location: location}); var router = new Backbone.Router; router.route('login', function(params) { - strictEqual(params, 'a=value&backUrl=https%3A%2F%2Fwww.msn.com%2Fidp%2Fidpdemo%3Fspid%3Dspdemo%26target%3Db'); + assert.strictEqual(params, 'a=value&backUrl=https%3A%2F%2Fwww.msn.com%2Fidp%2Fidpdemo%3Fspid%3Dspdemo%26target%3Db'); }); Backbone.history.start(); }); - test('#3358 - pushState to hashChange transition with search params', 1, function() { + QUnit.test('#3358 - pushState to hashChange transition with search params', function(assert) { + assert.expect(1); Backbone.history.stop(); location.replace('http://example.com/root?foo=bar'); location.replace = function(url) { - strictEqual(url, '/root#?foo=bar'); + assert.strictEqual(url, '/root#?foo=bar'); }; Backbone.history = _.extend(new Backbone.History, { location: location, @@ -932,14 +993,15 @@ Backbone.history.start({root: '/root', pushState: true}); }); - test("Paths that don't match the root should not match no root", 0, function() { + QUnit.test("Paths that don't match the root should not match no root", function(assert) { + assert.expect(0); location.replace('http://example.com/foo'); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, {location: location}); var Router = Backbone.Router.extend({ routes: { foo: function(){ - ok(false, 'should not match unless root matches'); + assert.ok(false, 'should not match unless root matches'); } } }); @@ -947,14 +1009,15 @@ Backbone.history.start({root: 'root', pushState: true}); }); - test("Paths that don't match the root should not match roots of the same length", 0, function() { + QUnit.test("Paths that don't match the root should not match roots of the same length", function(assert) { + assert.expect(0); location.replace('http://example.com/xxxx/foo'); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, {location: location}); var Router = Backbone.Router.extend({ routes: { foo: function(){ - ok(false, 'should not match unless root matches'); + assert.ok(false, 'should not match unless root matches'); } } }); @@ -962,34 +1025,37 @@ Backbone.history.start({root: 'root', pushState: true}); }); - test("roots with regex characters", 1, function() { + QUnit.test("roots with regex characters", function(assert) { + assert.expect(1); location.replace('http://example.com/x+y.z/foo'); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, {location: location}); var Router = Backbone.Router.extend({ - routes: {foo: function(){ ok(true); }} + routes: {foo: function(){ assert.ok(true); }} }); var router = new Router; Backbone.history.start({root: 'x+y.z', pushState: true}); }); - test("roots with unicode characters", 1, function() { + QUnit.test("roots with unicode characters", function(assert) { + assert.expect(1); location.replace('http://example.com/®ooτ/foo'); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, {location: location}); var Router = Backbone.Router.extend({ - routes: {foo: function(){ ok(true); }} + routes: {foo: function(){ assert.ok(true); }} }); var router = new Router; Backbone.history.start({root: '®ooτ', pushState: true}); }); - test("roots without slash", 1, function() { + QUnit.test("roots without slash", function(assert) { + assert.expect(1); location.replace('http://example.com/®ooτ'); Backbone.history.stop(); Backbone.history = _.extend(new Backbone.History, {location: location}); var Router = Backbone.Router.extend({ - routes: {'': function(){ ok(true); }} + routes: {'': function(){ assert.ok(true); }} }); var router = new Router; Backbone.history.start({root: '®ooτ', pushState: true}); diff --git a/vendor/backbone/test/setup/environment.js b/vendor/backbone/test/setup/environment.js index 309f23c30..c2441ac77 100644 --- a/vendor/backbone/test/setup/environment.js +++ b/vendor/backbone/test/setup/environment.js @@ -8,6 +8,8 @@ var pushState = history.pushState; var replaceState = history.replaceState; + QUnit.config.noglobals = true; + QUnit.testStart(function() { var env = QUnit.config.current.testEnvironment; diff --git a/vendor/backbone/test/sync.js b/vendor/backbone/test/sync.js index a1f68ac9e..9907a89a5 100644 --- a/vendor/backbone/test/sync.js +++ b/vendor/backbone/test/sync.js @@ -11,208 +11,226 @@ length : 123 }; - module("Backbone.sync", { + QUnit.module("Backbone.sync", { - setup : function() { + beforeEach : function(assert) { library = new Library; library.create(attrs, {wait: false}); }, - teardown: function() { + afterEach: function(assert) { Backbone.emulateHTTP = false; } }); - test("read", 4, function() { + QUnit.test("read", function(assert) { + assert.expect(4); library.fetch(); - equal(this.ajaxSettings.url, '/library'); - equal(this.ajaxSettings.type, 'GET'); - equal(this.ajaxSettings.dataType, 'json'); - ok(_.isEmpty(this.ajaxSettings.data)); + assert.equal(this.ajaxSettings.url, '/library'); + assert.equal(this.ajaxSettings.type, 'GET'); + assert.equal(this.ajaxSettings.dataType, 'json'); + assert.ok(_.isEmpty(this.ajaxSettings.data)); }); - test("passing data", 3, function() { + QUnit.test("passing data", function(assert) { + assert.expect(3); library.fetch({data: {a: 'a', one: 1}}); - equal(this.ajaxSettings.url, '/library'); - equal(this.ajaxSettings.data.a, 'a'); - equal(this.ajaxSettings.data.one, 1); + assert.equal(this.ajaxSettings.url, '/library'); + assert.equal(this.ajaxSettings.data.a, 'a'); + assert.equal(this.ajaxSettings.data.one, 1); }); - test("create", 6, function() { - equal(this.ajaxSettings.url, '/library'); - equal(this.ajaxSettings.type, 'POST'); - equal(this.ajaxSettings.dataType, 'json'); + QUnit.test("create", function(assert) { + assert.expect(6); + assert.equal(this.ajaxSettings.url, '/library'); + assert.equal(this.ajaxSettings.type, 'POST'); + assert.equal(this.ajaxSettings.dataType, 'json'); var data = JSON.parse(this.ajaxSettings.data); - equal(data.title, 'The Tempest'); - equal(data.author, 'Bill Shakespeare'); - equal(data.length, 123); + assert.equal(data.title, 'The Tempest'); + assert.equal(data.author, 'Bill Shakespeare'); + assert.equal(data.length, 123); }); - test("update", 7, function() { + QUnit.test("update", function(assert) { + assert.expect(7); library.first().save({id: '1-the-tempest', author: 'William Shakespeare'}); - equal(this.ajaxSettings.url, '/library/1-the-tempest'); - equal(this.ajaxSettings.type, 'PUT'); - equal(this.ajaxSettings.dataType, 'json'); + assert.equal(this.ajaxSettings.url, '/library/1-the-tempest'); + assert.equal(this.ajaxSettings.type, 'PUT'); + assert.equal(this.ajaxSettings.dataType, 'json'); var data = JSON.parse(this.ajaxSettings.data); - equal(data.id, '1-the-tempest'); - equal(data.title, 'The Tempest'); - equal(data.author, 'William Shakespeare'); - equal(data.length, 123); + assert.equal(data.id, '1-the-tempest'); + assert.equal(data.title, 'The Tempest'); + assert.equal(data.author, 'William Shakespeare'); + assert.equal(data.length, 123); }); - test("update with emulateHTTP and emulateJSON", 7, function() { + QUnit.test("update with emulateHTTP and emulateJSON", function(assert) { + assert.expect(7); library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, { emulateHTTP: true, emulateJSON: true }); - equal(this.ajaxSettings.url, '/library/2-the-tempest'); - equal(this.ajaxSettings.type, 'POST'); - equal(this.ajaxSettings.dataType, 'json'); - equal(this.ajaxSettings.data._method, 'PUT'); + assert.equal(this.ajaxSettings.url, '/library/2-the-tempest'); + assert.equal(this.ajaxSettings.type, 'POST'); + assert.equal(this.ajaxSettings.dataType, 'json'); + assert.equal(this.ajaxSettings.data._method, 'PUT'); var data = JSON.parse(this.ajaxSettings.data.model); - equal(data.id, '2-the-tempest'); - equal(data.author, 'Tim Shakespeare'); - equal(data.length, 123); + assert.equal(data.id, '2-the-tempest'); + assert.equal(data.author, 'Tim Shakespeare'); + assert.equal(data.length, 123); }); - test("update with just emulateHTTP", 6, function() { + QUnit.test("update with just emulateHTTP", function(assert) { + assert.expect(6); library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, { emulateHTTP: true }); - equal(this.ajaxSettings.url, '/library/2-the-tempest'); - equal(this.ajaxSettings.type, 'POST'); - equal(this.ajaxSettings.contentType, 'application/json'); + assert.equal(this.ajaxSettings.url, '/library/2-the-tempest'); + assert.equal(this.ajaxSettings.type, 'POST'); + assert.equal(this.ajaxSettings.contentType, 'application/json'); var data = JSON.parse(this.ajaxSettings.data); - equal(data.id, '2-the-tempest'); - equal(data.author, 'Tim Shakespeare'); - equal(data.length, 123); + assert.equal(data.id, '2-the-tempest'); + assert.equal(data.author, 'Tim Shakespeare'); + assert.equal(data.length, 123); }); - test("update with just emulateJSON", 6, function() { + QUnit.test("update with just emulateJSON", function(assert) { + assert.expect(6); library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, { emulateJSON: true }); - equal(this.ajaxSettings.url, '/library/2-the-tempest'); - equal(this.ajaxSettings.type, 'PUT'); - equal(this.ajaxSettings.contentType, 'application/x-www-form-urlencoded'); + assert.equal(this.ajaxSettings.url, '/library/2-the-tempest'); + assert.equal(this.ajaxSettings.type, 'PUT'); + assert.equal(this.ajaxSettings.contentType, 'application/x-www-form-urlencoded'); var data = JSON.parse(this.ajaxSettings.data.model); - equal(data.id, '2-the-tempest'); - equal(data.author, 'Tim Shakespeare'); - equal(data.length, 123); + assert.equal(data.id, '2-the-tempest'); + assert.equal(data.author, 'Tim Shakespeare'); + assert.equal(data.length, 123); }); - test("read model", 3, function() { + QUnit.test("read model", function(assert) { + assert.expect(3); library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}); library.first().fetch(); - equal(this.ajaxSettings.url, '/library/2-the-tempest'); - equal(this.ajaxSettings.type, 'GET'); - ok(_.isEmpty(this.ajaxSettings.data)); + assert.equal(this.ajaxSettings.url, '/library/2-the-tempest'); + assert.equal(this.ajaxSettings.type, 'GET'); + assert.ok(_.isEmpty(this.ajaxSettings.data)); }); - test("destroy", 3, function() { + QUnit.test("destroy", function(assert) { + assert.expect(3); library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}); library.first().destroy({wait: true}); - equal(this.ajaxSettings.url, '/library/2-the-tempest'); - equal(this.ajaxSettings.type, 'DELETE'); - equal(this.ajaxSettings.data, null); + assert.equal(this.ajaxSettings.url, '/library/2-the-tempest'); + assert.equal(this.ajaxSettings.type, 'DELETE'); + assert.equal(this.ajaxSettings.data, null); }); - test("destroy with emulateHTTP", 3, function() { + QUnit.test("destroy with emulateHTTP", function(assert) { + assert.expect(3); library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}); library.first().destroy({ emulateHTTP: true, emulateJSON: true }); - equal(this.ajaxSettings.url, '/library/2-the-tempest'); - equal(this.ajaxSettings.type, 'POST'); - equal(JSON.stringify(this.ajaxSettings.data), '{"_method":"DELETE"}'); + assert.equal(this.ajaxSettings.url, '/library/2-the-tempest'); + assert.equal(this.ajaxSettings.type, 'POST'); + assert.equal(JSON.stringify(this.ajaxSettings.data), '{"_method":"DELETE"}'); }); - test("urlError", 2, function() { + QUnit.test("urlError", function(assert) { + assert.expect(2); var model = new Backbone.Model(); - throws(function() { + assert.throws(function() { model.fetch(); }); model.fetch({url: '/one/two'}); - equal(this.ajaxSettings.url, '/one/two'); + assert.equal(this.ajaxSettings.url, '/one/two'); }); - test("#1052 - `options` is optional.", 0, function() { + QUnit.test("#1052 - `options` is optional.", function(assert) { + assert.expect(0); var model = new Backbone.Model(); model.url = '/test'; Backbone.sync('create', model); }); - test("Backbone.ajax", 1, function() { + QUnit.test("Backbone.ajax", function(assert) { + assert.expect(1); Backbone.ajax = function(settings){ - strictEqual(settings.url, '/test'); + assert.strictEqual(settings.url, '/test'); }; var model = new Backbone.Model(); model.url = '/test'; Backbone.sync('create', model); }); - test("Call provided error callback on error.", 1, function() { + QUnit.test("Call provided error callback on error.", function(assert) { + assert.expect(1); var model = new Backbone.Model; model.url = '/test'; Backbone.sync('read', model, { - error: function() { ok(true); } + error: function() { assert.ok(true); } }); this.ajaxSettings.error(); }); - test('Use Backbone.emulateHTTP as default.', 2, function() { + QUnit.test('Use Backbone.emulateHTTP as default.', function(assert) { + assert.expect(2); var model = new Backbone.Model; model.url = '/test'; Backbone.emulateHTTP = true; model.sync('create', model); - strictEqual(this.ajaxSettings.emulateHTTP, true); + assert.strictEqual(this.ajaxSettings.emulateHTTP, true); Backbone.emulateHTTP = false; model.sync('create', model); - strictEqual(this.ajaxSettings.emulateHTTP, false); + assert.strictEqual(this.ajaxSettings.emulateHTTP, false); }); - test('Use Backbone.emulateJSON as default.', 2, function() { + QUnit.test('Use Backbone.emulateJSON as default.', function(assert) { + assert.expect(2); var model = new Backbone.Model; model.url = '/test'; Backbone.emulateJSON = true; model.sync('create', model); - strictEqual(this.ajaxSettings.emulateJSON, true); + assert.strictEqual(this.ajaxSettings.emulateJSON, true); Backbone.emulateJSON = false; model.sync('create', model); - strictEqual(this.ajaxSettings.emulateJSON, false); + assert.strictEqual(this.ajaxSettings.emulateJSON, false); }); - test("#1756 - Call user provided beforeSend function.", 4, function() { + QUnit.test("#1756 - Call user provided beforeSend function.", function(assert) { + assert.expect(4); Backbone.emulateHTTP = true; var model = new Backbone.Model; model.url = '/test'; var xhr = { setRequestHeader: function(header, value) { - strictEqual(header, 'X-HTTP-Method-Override'); - strictEqual(value, 'DELETE'); + assert.strictEqual(header, 'X-HTTP-Method-Override'); + assert.strictEqual(value, 'DELETE'); } }; model.sync('delete', model, { beforeSend: function(_xhr) { - ok(_xhr === xhr); + assert.ok(_xhr === xhr); return false; } }); - strictEqual(this.ajaxSettings.beforeSend(xhr), false); + assert.strictEqual(this.ajaxSettings.beforeSend(xhr), false); }); - test('#2928 - Pass along `textStatus` and `errorThrown`.', 2, function() { + QUnit.test('#2928 - Pass along `textStatus` and `errorThrown`.', function(assert) { + assert.expect(2); var model = new Backbone.Model; model.url = '/test'; model.on('error', function(model, xhr, options) { - strictEqual(options.textStatus, 'textStatus'); - strictEqual(options.errorThrown, 'errorThrown'); + assert.strictEqual(options.textStatus, 'textStatus'); + assert.strictEqual(options.errorThrown, 'errorThrown'); }); model.fetch(); this.ajaxSettings.error({}, 'textStatus', 'errorThrown'); diff --git a/vendor/backbone/test/view.js b/vendor/backbone/test/view.js index 51e6c6e44..0bfd84f07 100644 --- a/vendor/backbone/test/view.js +++ b/vendor/backbone/test/view.js @@ -2,9 +2,9 @@ var view; - module("Backbone.View", { + QUnit.module("Backbone.View", { - setup: function() { + beforeEach: function(assert) { $('#qunit-fixture').append( '

Test

' ); @@ -18,46 +18,52 @@ }); - test("constructor", 3, function() { - equal(view.el.id, 'test-view'); - equal(view.el.className, 'test-view'); - equal(view.el.other, void 0); + QUnit.test("constructor", function(assert) { + assert.expect(3); + assert.equal(view.el.id, 'test-view'); + assert.equal(view.el.className, 'test-view'); + assert.equal(view.el.other, void 0); }); - test("$", 2, function() { + QUnit.test("$", function(assert) { + assert.expect(2); var view = new Backbone.View; view.setElement('

test

'); var result = view.$('a b'); - strictEqual(result[0].innerHTML, 'test'); - ok(result.length === +result.length); + assert.strictEqual(result[0].innerHTML, 'test'); + assert.ok(result.length === +result.length); }); - test("$el", 3, function() { + QUnit.test("$el", function(assert) { + assert.expect(3); var view = new Backbone.View; view.setElement('

test

'); - strictEqual(view.el.nodeType, 1); + assert.strictEqual(view.el.nodeType, 1); - ok(view.$el instanceof Backbone.$); - strictEqual(view.$el[0], view.el); + assert.ok(view.$el instanceof Backbone.$); + assert.strictEqual(view.$el[0], view.el); }); - test("initialize", 1, function() { + QUnit.test("initialize", function(assert) { + assert.expect(1); var View = Backbone.View.extend({ initialize: function() { this.one = 1; } }); - strictEqual(new View().one, 1); + assert.strictEqual(new View().one, 1); }); - test("render", 1, function() { + QUnit.test("render", function(assert) { + assert.expect(1); var view = new Backbone.View; - equal(view.render(), view, '#render returns the view instance'); + assert.equal(view.render(), view, '#render returns the view instance'); }); - test("delegateEvents", 6, function() { + QUnit.test("delegateEvents", function(assert) { + assert.expect(6); var counter1 = 0, counter2 = 0; var view = new Backbone.View({el: '#testElement'}); @@ -68,33 +74,35 @@ view.delegateEvents(events); view.$('h1').trigger('click'); - equal(counter1, 1); - equal(counter2, 1); + assert.equal(counter1, 1); + assert.equal(counter2, 1); view.$('h1').trigger('click'); - equal(counter1, 2); - equal(counter2, 2); + assert.equal(counter1, 2); + assert.equal(counter2, 2); view.delegateEvents(events); view.$('h1').trigger('click'); - equal(counter1, 3); - equal(counter2, 3); + assert.equal(counter1, 3); + assert.equal(counter2, 3); }); - test("delegate", 3, function() { + QUnit.test("delegate", function(assert) { + assert.expect(3); var view = new Backbone.View({el: '#testElement'}); view.delegate('click', 'h1', function() { - ok(true); + assert.ok(true); }); view.delegate('click', function() { - ok(true); + assert.ok(true); }); view.$('h1').trigger('click'); - equal(view.delegate(), view, '#delegate returns the view instance'); + assert.equal(view.delegate(), view, '#delegate returns the view instance'); }); - test("delegateEvents allows functions for callbacks", 3, function() { + QUnit.test("delegateEvents allows functions for callbacks", function(assert) { + assert.expect(3); var view = new Backbone.View({el: '

'}); view.counter = 0; @@ -106,24 +114,26 @@ view.delegateEvents(events); view.$el.trigger('click'); - equal(view.counter, 1); + assert.equal(view.counter, 1); view.$el.trigger('click'); - equal(view.counter, 2); + assert.equal(view.counter, 2); view.delegateEvents(events); view.$el.trigger('click'); - equal(view.counter, 3); + assert.equal(view.counter, 3); }); - test("delegateEvents ignore undefined methods", 0, function() { + QUnit.test("delegateEvents ignore undefined methods", function(assert) { + assert.expect(0); var view = new Backbone.View({el: '

'}); view.delegateEvents({'click': 'undefinedMethod'}); view.$el.trigger('click'); }); - test("undelegateEvents", 7, function() { + QUnit.test("undelegateEvents", function(assert) { + assert.expect(7); var counter1 = 0, counter2 = 0; var view = new Backbone.View({el: '#testElement'}); @@ -134,107 +144,116 @@ view.delegateEvents(events); view.$('h1').trigger('click'); - equal(counter1, 1); - equal(counter2, 1); + assert.equal(counter1, 1); + assert.equal(counter2, 1); view.undelegateEvents(); view.$('h1').trigger('click'); - equal(counter1, 1); - equal(counter2, 2); + assert.equal(counter1, 1); + assert.equal(counter2, 2); view.delegateEvents(events); view.$('h1').trigger('click'); - equal(counter1, 2); - equal(counter2, 3); + assert.equal(counter1, 2); + assert.equal(counter2, 3); - equal(view.undelegateEvents(), view, '#undelegateEvents returns the view instance'); + assert.equal(view.undelegateEvents(), view, '#undelegateEvents returns the view instance'); }); - test("undelegate", 1, function() { + QUnit.test("undelegate", function(assert) { + assert.expect(1); view = new Backbone.View({el: '#testElement'}); - view.delegate('click', function() { ok(false); }); - view.delegate('click', 'h1', function() { ok(false); }); + view.delegate('click', function() { assert.ok(false); }); + view.delegate('click', 'h1', function() { assert.ok(false); }); view.undelegate('click'); view.$('h1').trigger('click'); view.$el.trigger('click'); - equal(view.undelegate(), view, '#undelegate returns the view instance'); + assert.equal(view.undelegate(), view, '#undelegate returns the view instance'); }); - test("undelegate with passed handler", 1, function() { + QUnit.test("undelegate with passed handler", function(assert) { + assert.expect(1); view = new Backbone.View({el: '#testElement'}); - var listener = function() { ok(false); }; + var listener = function() { assert.ok(false); }; view.delegate('click', listener); - view.delegate('click', function() { ok(true); }); + view.delegate('click', function() { assert.ok(true); }); view.undelegate('click', listener); view.$el.trigger('click'); }); - test("undelegate with selector", 2, function() { + QUnit.test("undelegate with selector", function(assert) { + assert.expect(2); view = new Backbone.View({el: '#testElement'}); - view.delegate('click', function() { ok(true); }); - view.delegate('click', 'h1', function() { ok(false); }); + view.delegate('click', function() { assert.ok(true); }); + view.delegate('click', 'h1', function() { assert.ok(false); }); view.undelegate('click', 'h1'); view.$('h1').trigger('click'); view.$el.trigger('click'); }); - test("undelegate with handler and selector", 2, function() { + QUnit.test("undelegate with handler and selector", function(assert) { + assert.expect(2); view = new Backbone.View({el: '#testElement'}); - view.delegate('click', function() { ok(true); }); - var handler = function(){ ok(false); }; + view.delegate('click', function() { assert.ok(true); }); + var handler = function(){ assert.ok(false); }; view.delegate('click', 'h1', handler); view.undelegate('click', 'h1', handler); view.$('h1').trigger('click'); view.$el.trigger('click'); }); - test("tagName can be provided as a string", 1, function() { + QUnit.test("tagName can be provided as a string", function(assert) { + assert.expect(1); var View = Backbone.View.extend({ tagName: 'span' }); - equal(new View().el.tagName, 'SPAN'); + assert.equal(new View().el.tagName, 'SPAN'); }); - test("tagName can be provided as a function", 1, function() { + QUnit.test("tagName can be provided as a function", function(assert) { + assert.expect(1); var View = Backbone.View.extend({ tagName: function() { return 'p'; } }); - ok(new View().$el.is('p')); + assert.ok(new View().$el.is('p')); }); - test("_ensureElement with DOM node el", 1, function() { + QUnit.test("_ensureElement with DOM node el", function(assert) { + assert.expect(1); var View = Backbone.View.extend({ el: document.body }); - equal(new View().el, document.body); + assert.equal(new View().el, document.body); }); - test("_ensureElement with string el", 3, function() { + QUnit.test("_ensureElement with string el", function(assert) { + assert.expect(3); var View = Backbone.View.extend({ el: "body" }); - strictEqual(new View().el, document.body); + assert.strictEqual(new View().el, document.body); View = Backbone.View.extend({ el: "#testElement > h1" }); - strictEqual(new View().el, $("#testElement > h1").get(0)); + assert.strictEqual(new View().el, $("#testElement > h1").get(0)); View = Backbone.View.extend({ el: "#nonexistent" }); - ok(!new View().el); + assert.ok(!new View().el); }); - test("with className and id functions", 2, function() { + QUnit.test("with className and id functions", function(assert) { + assert.expect(2); var View = Backbone.View.extend({ className: function() { return 'className'; @@ -244,11 +263,12 @@ } }); - strictEqual(new View().el.className, 'className'); - strictEqual(new View().el.id, 'id'); + assert.strictEqual(new View().el.className, 'className'); + assert.strictEqual(new View().el.id, 'id'); }); - test("with attributes", 2, function() { + QUnit.test("with attributes", function(assert) { + assert.expect(2); var View = Backbone.View.extend({ attributes: { id: 'id', @@ -256,21 +276,41 @@ } }); - strictEqual(new View().el.className, 'class'); - strictEqual(new View().el.id, 'id'); + assert.strictEqual(new View().el.className, 'class'); + assert.strictEqual(new View().el.id, 'id'); }); - test("with attributes as a function", 1, function() { + QUnit.test("with attributes as a function", function(assert) { + assert.expect(1); var View = Backbone.View.extend({ attributes: function() { return {'class': 'dynamic'}; } }); - strictEqual(new View().el.className, 'dynamic'); + assert.strictEqual(new View().el.className, 'dynamic'); }); - test("multiple views per element", 3, function() { + QUnit.test("should default to className/id properties", function(assert) { + assert.expect(4); + var View = Backbone.View.extend({ + className: 'backboneClass', + id: 'backboneId', + attributes: { + 'class': 'attributeClass', + 'id': 'attributeId' + } + }); + + var view = new View; + assert.strictEqual(view.el.className, 'backboneClass'); + assert.strictEqual(view.el.id, 'backboneId'); + assert.strictEqual(view.$el.attr('class'), 'backboneClass'); + assert.strictEqual(view.$el.attr('id'), 'backboneId'); + }); + + QUnit.test("multiple views per element", function(assert) { + assert.expect(3); var count = 0; var $el = $('

'); @@ -285,22 +325,23 @@ var view1 = new View; $el.trigger("click"); - equal(1, count); + assert.equal(1, count); var view2 = new View; $el.trigger("click"); - equal(3, count); + assert.equal(3, count); view1.delegateEvents(); $el.trigger("click"); - equal(5, count); + assert.equal(5, count); }); - test("custom events", 2, function() { + QUnit.test("custom events", function(assert) { + assert.expect(2); var View = Backbone.View.extend({ el: $('body'), events: { - "fake$event": function() { ok(true); } + "fake$event": function() { assert.ok(true); } } }); @@ -311,24 +352,26 @@ $('body').trigger('fake$event'); }); - test("#1048 - setElement uses provided object.", 2, function() { + QUnit.test("#1048 - setElement uses provided object.", function(assert) { + assert.expect(2); var $el = $('body'); var view = new Backbone.View({el: $el}); - ok(view.$el === $el); + assert.ok(view.$el === $el); view.setElement($el = $($el)); - ok(view.$el === $el); + assert.ok(view.$el === $el); }); - test("#986 - Undelegate before changing element.", 1, function() { + QUnit.test("#986 - Undelegate before changing element.", function(assert) { + assert.expect(1); var button1 = $(''); var button2 = $(''); var View = Backbone.View.extend({ events: { click: function(e) { - ok(view.el === e.target); + assert.ok(view.el === e.target); } } }); @@ -340,23 +383,25 @@ button2.trigger('click'); }); - test("#1172 - Clone attributes object", 2, function() { + QUnit.test("#1172 - Clone attributes object", function(assert) { + assert.expect(2); var View = Backbone.View.extend({ attributes: {foo: 'bar'} }); var view1 = new View({id: 'foo'}); - strictEqual(view1.el.id, 'foo'); + assert.strictEqual(view1.el.id, 'foo'); var view2 = new View(); - ok(!view2.el.id); + assert.ok(!view2.el.id); }); - test("views stopListening", 0, function() { + QUnit.test("views stopListening", function(assert) { + assert.expect(0); var View = Backbone.View.extend({ initialize: function() { - this.listenTo(this.model, 'all x', function(){ ok(false); }); - this.listenTo(this.collection, 'all x', function(){ ok(false); }); + this.listenTo(this.model, 'all x', function(){ assert.ok(false); }); + this.listenTo(this.collection, 'all x', function(){ assert.ok(false); }); } }); @@ -370,7 +415,8 @@ view.collection.trigger('x'); }); - test("Provide function for el.", 2, function() { + QUnit.test("Provide function for el.", function(assert) { + assert.expect(2); var View = Backbone.View.extend({ el: function() { return "

"; @@ -378,11 +424,12 @@ }); var view = new View; - ok(view.$el.is('p')); - ok(view.$el.has('a')); + assert.ok(view.$el.is('p')); + assert.ok(view.$el.has('a')); }); - test("events passed in options", 1, function() { + QUnit.test("events passed in options", function(assert) { + assert.expect(1); var counter = 0; var View = Backbone.View.extend({ @@ -399,32 +446,34 @@ }); view.$('h1').trigger('click').trigger('click'); - equal(counter, 2); + assert.equal(counter, 2); }); - test("remove", 2, function() { + QUnit.test("remove", function(assert) { + assert.expect(2); var view = new Backbone.View; document.body.appendChild(view.el); - view.delegate('click', function() { ok(false); }); - view.listenTo(view, 'all x', function() { ok(false); }); + view.delegate('click', function() { assert.ok(false); }); + view.listenTo(view, 'all x', function() { assert.ok(false); }); - equal(view.remove(), view, '#remove returns the view instance'); + assert.equal(view.remove(), view, '#remove returns the view instance'); view.$el.trigger('click'); view.trigger('x'); // In IE8 and below, parentNode still exists but is not document.body. - notEqual(view.el.parentNode, document.body); + assert.notEqual(view.el.parentNode, document.body); }); - test("setElement", 3, function() { + QUnit.test("setElement", function(assert) { + assert.expect(3); var view = new Backbone.View({ events: { - click: function() { ok(false); } + click: function() { assert.ok(false); } } }); view.events = { - click: function() { ok(true); } + click: function() { assert.ok(true); } }; var oldEl = view.el; var $oldEl = view.$el; @@ -434,8 +483,8 @@ $oldEl.click(); view.$el.click(); - notEqual(oldEl, view.el); - notEqual($oldEl, view.$el); + assert.notEqual(oldEl, view.el); + assert.notEqual($oldEl, view.$el); }); })(); diff --git a/vendor/underscore/test/arrays.js b/vendor/underscore/test/arrays.js index 5b52ad433..d159b37a8 100644 --- a/vendor/underscore/test/arrays.js +++ b/vendor/underscore/test/arrays.js @@ -3,161 +3,159 @@ QUnit.module('Arrays'); - test('first', function() { - equal(_.first([1, 2, 3]), 1, 'can pull out the first element of an array'); - equal(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"'); - deepEqual(_.first([1, 2, 3], 0), [], 'can pass an index to first'); - deepEqual(_.first([1, 2, 3], 2), [1, 2], 'can pass an index to first'); - deepEqual(_.first([1, 2, 3], 5), [1, 2, 3], 'can pass an index to first'); + test('first', function(assert) { + assert.equal(_.first([1, 2, 3]), 1, 'can pull out the first element of an array'); + assert.equal(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"'); + assert.deepEqual(_.first([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)'); + assert.deepEqual(_.first([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)'); + assert.deepEqual(_.first([1, 2, 3], 2), [1, 2], 'can fetch the first n elements'); + assert.deepEqual(_.first([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length'); var result = (function(){ return _.first(arguments); }(4, 3, 2, 1)); - equal(result, 4, 'works on an arguments object.'); + assert.equal(result, 4, 'works on an arguments object'); result = _.map([[1, 2, 3], [1, 2, 3]], _.first); - deepEqual(result, [1, 1], 'works well with _.map'); - result = (function() { return _.first([1, 2, 3], 2); }()); - deepEqual(result, [1, 2]); - - equal(_.first(null), void 0, 'handles nulls'); - strictEqual(_.first([1, 2, 3], -1).length, 0); + assert.deepEqual(result, [1, 1], 'works well with _.map'); + assert.equal(_.first(null), void 0, 'returns undefined when called on null'); }); - test('head', function() { - strictEqual(_.first, _.head, 'alias for first'); + test('head', function(assert) { + assert.strictEqual(_.head, _.first, 'is an alias for first'); }); - test('take', function() { - strictEqual(_.first, _.take, 'alias for first'); + test('take', function(assert) { + assert.strictEqual(_.take, _.first, 'is an alias for first'); }); - test('rest', function() { + test('rest', function(assert) { var numbers = [1, 2, 3, 4]; - deepEqual(_.rest(numbers), [2, 3, 4], 'working rest()'); - deepEqual(_.rest(numbers, 0), [1, 2, 3, 4], 'working rest(0)'); - deepEqual(_.rest(numbers, 2), [3, 4], 'rest can take an index'); + assert.deepEqual(_.rest(numbers), [2, 3, 4], 'fetches all but the first element'); + assert.deepEqual(_.rest(numbers, 0), [1, 2, 3, 4], 'returns the whole array when index is 0'); + assert.deepEqual(_.rest(numbers, 2), [3, 4], 'returns elements starting at the given index'); var result = (function(){ return _(arguments).rest(); }(1, 2, 3, 4)); - deepEqual(result, [2, 3, 4], 'works on arguments object'); + assert.deepEqual(result, [2, 3, 4], 'works on an arguments object'); result = _.map([[1, 2, 3], [1, 2, 3]], _.rest); - deepEqual(_.flatten(result), [2, 3, 2, 3], 'works well with _.map'); - result = (function(){ return _(arguments).rest(); }(1, 2, 3, 4)); - deepEqual(result, [2, 3, 4], 'works on arguments object'); + assert.deepEqual(_.flatten(result), [2, 3, 2, 3], 'works well with _.map'); }); - test('tail', function() { - strictEqual(_.rest, _.tail, 'alias for rest'); + test('tail', function(assert) { + assert.strictEqual(_.tail, _.rest, 'is an alias for rest'); }); - test('drop', function() { - strictEqual(_.rest, _.drop, 'alias for rest'); + test('drop', function(assert) { + assert.strictEqual(_.drop, _.rest, 'is an alias for rest'); }); - test('initial', function() { - deepEqual(_.initial([1, 2, 3, 4, 5]), [1, 2, 3, 4], 'working initial()'); - deepEqual(_.initial([1, 2, 3, 4], 2), [1, 2], 'initial can take an index'); - deepEqual(_.initial([1, 2, 3, 4], 6), [], 'initial can take a large index'); + test('initial', function(assert) { + assert.deepEqual(_.initial([1, 2, 3, 4, 5]), [1, 2, 3, 4], 'returns all but the last element'); + assert.deepEqual(_.initial([1, 2, 3, 4], 2), [1, 2], 'returns all but the last n elements'); + assert.deepEqual(_.initial([1, 2, 3, 4], 6), [], 'returns an empty array when n > length'); var result = (function(){ return _(arguments).initial(); }(1, 2, 3, 4)); - deepEqual(result, [1, 2, 3], 'initial works on arguments object'); + assert.deepEqual(result, [1, 2, 3], 'works on an arguments object'); result = _.map([[1, 2, 3], [1, 2, 3]], _.initial); - deepEqual(_.flatten(result), [1, 2, 1, 2], 'initial works with _.map'); + assert.deepEqual(_.flatten(result), [1, 2, 1, 2], 'works well with _.map'); }); - test('last', function() { - equal(_.last([1, 2, 3]), 3, 'can pull out the last element of an array'); - deepEqual(_.last([1, 2, 3], 0), [], 'can pass an index to last'); - deepEqual(_.last([1, 2, 3], 2), [2, 3], 'can pass an index to last'); - deepEqual(_.last([1, 2, 3], 5), [1, 2, 3], 'can pass an index to last'); + test('last', function(assert) { + assert.equal(_.last([1, 2, 3]), 3, 'can pull out the last element of an array'); + assert.equal(_([1, 2, 3]).last(), 3, 'can perform OO-style "last()"'); + assert.deepEqual(_.last([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)'); + assert.deepEqual(_.last([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)'); + assert.deepEqual(_.last([1, 2, 3], 2), [2, 3], 'can fetch the last n elements'); + assert.deepEqual(_.last([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length'); var result = (function(){ return _(arguments).last(); }(1, 2, 3, 4)); - equal(result, 4, 'works on an arguments object'); + assert.equal(result, 4, 'works on an arguments object'); result = _.map([[1, 2, 3], [1, 2, 3]], _.last); - deepEqual(result, [3, 3], 'works well with _.map'); - - equal(_.last(null), void 0, 'handles nulls'); - strictEqual(_.last([1, 2, 3], -1).length, 0); + assert.deepEqual(result, [3, 3], 'works well with _.map'); + assert.equal(_.last(null), void 0, 'returns undefined when called on null'); }); - test('compact', function() { - equal(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values'); - var result = (function(){ return _.compact(arguments).length; }(0, 1, false, 2, false, 3)); - equal(result, 3, 'works on an arguments object'); + test('compact', function(assert) { + assert.deepEqual(_.compact([1, false, null, 0, '', void 0, NaN, 2]), [1, 2], 'removes all falsy values'); + var result = (function(){ return _.compact(arguments); }(0, 1, false, 2, false, 3)); + assert.deepEqual(result, [1, 2, 3], 'works on an arguments object'); + result = _.map([[1, false, false], [false, false, 3]], _.compact); + assert.deepEqual(result, [[1], [3]], 'works well with _.map'); }); - test('flatten', function() { - deepEqual(_.flatten(null), [], 'Flattens supports null'); - deepEqual(_.flatten(void 0), [], 'Flattens supports undefined'); + test('flatten', function(assert) { + assert.deepEqual(_.flatten(null), [], 'supports null'); + assert.deepEqual(_.flatten(void 0), [], 'supports undefined'); - deepEqual(_.flatten([[], [[]], []]), [], 'Flattens empty arrays'); - deepEqual(_.flatten([[], [[]], []], true), [[]], 'Flattens empty arrays'); + assert.deepEqual(_.flatten([[], [[]], []]), [], 'supports empty arrays'); + assert.deepEqual(_.flatten([[], [[]], []], true), [[]], 'can shallowly flatten empty arrays'); var list = [1, [2], [3, [[[4]]]]]; - deepEqual(_.flatten(list), [1, 2, 3, 4], 'can flatten nested arrays'); - deepEqual(_.flatten(list, true), [1, 2, 3, [[[4]]]], 'can shallowly flatten nested arrays'); + assert.deepEqual(_.flatten(list), [1, 2, 3, 4], 'can flatten nested arrays'); + assert.deepEqual(_.flatten(list, true), [1, 2, 3, [[[4]]]], 'can shallowly flatten nested arrays'); var result = (function(){ return _.flatten(arguments); }(1, [2], [3, [[[4]]]])); - deepEqual(result, [1, 2, 3, 4], 'works on an arguments object'); + assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object'); list = [[1], [2], [3], [[4]]]; - deepEqual(_.flatten(list, true), [1, 2, 3, [4]], 'can shallowly flatten arrays containing only other arrays'); + assert.deepEqual(_.flatten(list, true), [1, 2, 3, [4]], 'can shallowly flatten arrays containing only other arrays'); - equal(_.flatten([_.range(10), _.range(10), 5, 1, 3], true).length, 23); - equal(_.flatten([_.range(10), _.range(10), 5, 1, 3]).length, 23); - equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3]).length, 1056003, 'Flatten can handle massive collections'); - equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3], true).length, 1056003, 'Flatten can handle massive collections'); + assert.equal(_.flatten([_.range(10), _.range(10), 5, 1, 3], true).length, 23, 'can flatten medium length arrays'); + assert.equal(_.flatten([_.range(10), _.range(10), 5, 1, 3]).length, 23, 'can shallowly flatten medium length arrays'); + assert.equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3]).length, 1056003, 'can handle massive arrays'); + assert.equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3], true).length, 1056003, 'can handle massive arrays in shallow mode'); var x = _.range(100000); for (var i = 0; i < 1000; i++) x = [x]; - deepEqual(_.flatten(x), _.range(100000), 'Flatten can handle very deep arrays'); - deepEqual(_.flatten(x, true), x[0], 'Flatten can handle very deep arrays with shallow'); + assert.deepEqual(_.flatten(x), _.range(100000), 'can handle very deep arrays'); + assert.deepEqual(_.flatten(x, true), x[0], 'can handle very deep arrays in shallow mode'); }); - test('without', function() { + test('without', function(assert) { var list = [1, 2, 1, 0, 3, 1, 4]; - deepEqual(_.without(list, 0, 1), [2, 3, 4], 'can remove all instances of an object'); + assert.deepEqual(_.without(list, 0, 1), [2, 3, 4], 'removes all instances of the given values'); var result = (function(){ return _.without(arguments, 0, 1); }(1, 2, 1, 0, 3, 1, 4)); - deepEqual(result, [2, 3, 4], 'works on an arguments object'); + assert.deepEqual(result, [2, 3, 4], 'works on an arguments object'); list = [{one: 1}, {two: 2}]; - equal(_.without(list, {one: 1}).length, 2, 'uses real object identity for comparisons.'); - equal(_.without(list, list[0]).length, 1, 'ditto.'); + assert.deepEqual(_.without(list, {one: 1}), list, 'compares objects by reference (value case)'); + assert.deepEqual(_.without(list, list[0]), [{two: 2}], 'compares objects by reference (reference case)'); }); - test('sortedIndex', function() { - var numbers = [10, 20, 30, 40, 50], num = 35; - var indexForNum = _.sortedIndex(numbers, num); - equal(indexForNum, 3, '35 should be inserted at index 3'); - + test('sortedIndex', function(assert) { + var numbers = [10, 20, 30, 40, 50]; + var indexFor35 = _.sortedIndex(numbers, 35); + assert.equal(indexFor35, 3, 'finds the index at which a value should be inserted to retain order'); var indexFor30 = _.sortedIndex(numbers, 30); - equal(indexFor30, 2, '30 should be inserted at index 2'); + assert.equal(indexFor30, 2, 'finds the smallest index at which a value could be inserted to retain order'); var objects = [{x: 10}, {x: 20}, {x: 30}, {x: 40}]; var iterator = function(obj){ return obj.x; }; - strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2); - strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3); + assert.strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2, 'uses the result of `iterator` for order comparisons'); + assert.strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3, 'when `iterator` is a string, uses that key for order comparisons'); var context = {1: 2, 2: 3, 3: 4}; iterator = function(obj){ return this[obj]; }; - strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1); + assert.strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1, 'can execute its iterator in the given context'); - var values = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647]; - var array = Array(Math.pow(2, 32) - 1); + var values = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, + 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647]; + var largeArray = Array(Math.pow(2, 32) - 1); var length = values.length; + // Sparsely populate `array` while (length--) { - array[values[length]] = values[length]; + largeArray[values[length]] = values[length]; } - equal(_.sortedIndex(array, 2147483648), 2147483648, 'should work with large indexes'); + assert.equal(_.sortedIndex(largeArray, 2147483648), 2147483648, 'works with large indexes'); }); - test('uniq', function() { + test('uniq', function(assert) { var list = [1, 2, 1, 3, 1, 4]; - deepEqual(_.uniq(list), [1, 2, 3, 4], 'can find the unique values of an unsorted array'); + assert.deepEqual(_.uniq(list), [1, 2, 3, 4], 'can find the unique values of an unsorted array'); list = [1, 1, 1, 2, 2, 3]; - deepEqual(_.uniq(list, true), [1, 2, 3], 'can find the unique values of a sorted array faster'); + assert.deepEqual(_.uniq(list, true), [1, 2, 3], 'can find the unique values of a sorted array faster'); list = [{name: 'moe'}, {name: 'curly'}, {name: 'larry'}, {name: 'curly'}]; var iterator = function(value) { return value.name; }; - deepEqual(_.map(_.uniq(list, false, iterator), iterator), ['moe', 'curly', 'larry'], 'can find the unique values of an array using a custom iterator'); + assert.deepEqual(_.map(_.uniq(list, false, iterator), iterator), ['moe', 'curly', 'larry'], 'can find the unique values of an array using a custom iterator'); - deepEqual(_.map(_.uniq(list, iterator), iterator), ['moe', 'curly', 'larry'], 'can find the unique values of an array using a custom iterator without specifying whether array is sorted'); + assert.deepEqual(_.map(_.uniq(list, iterator), iterator), ['moe', 'curly', 'larry'], 'can find the unique values of an array using a custom iterator without specifying whether array is sorted'); iterator = function(value) { return value + 1; }; list = [1, 2, 2, 3, 4, 4]; - deepEqual(_.uniq(list, true, iterator), [1, 2, 3, 4], 'iterator works with sorted array'); + assert.deepEqual(_.uniq(list, true, iterator), [1, 2, 3, 4], 'iterator works with sorted array'); var kittens = [ {kitten: 'Celery', cuteness: 8}, @@ -170,236 +168,236 @@ {kitten: 'Juniper', cuteness: 10} ]; - deepEqual(_.uniq(kittens, true, 'cuteness'), expected, 'string iterator works with sorted array'); + assert.deepEqual(_.uniq(kittens, true, 'cuteness'), expected, 'string iterator works with sorted array'); var result = (function(){ return _.uniq(arguments); }(1, 2, 1, 3, 1, 4)); - deepEqual(result, [1, 2, 3, 4], 'works on an arguments object'); + assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object'); var a = {}, b = {}, c = {}; - deepEqual(_.uniq([a, b, a, b, c]), [a, b, c], 'works on values that can be tested for equivalency but not ordered'); + assert.deepEqual(_.uniq([a, b, a, b, c]), [a, b, c], 'works on values that can be tested for equivalency but not ordered'); - deepEqual(_.uniq(null), []); + assert.deepEqual(_.uniq(null), []); var context = {}; list = [3]; _.uniq(list, function(value, index, array) { - strictEqual(this, context); - strictEqual(value, 3); - strictEqual(index, 0); - strictEqual(array, list); + assert.strictEqual(this, context); + assert.strictEqual(value, 3); + assert.strictEqual(index, 0); + assert.strictEqual(array, list); }, context); - deepEqual(_.uniq([{a: 1, b: 1}, {a: 1, b: 2}, {a: 1, b: 3}, {a: 2, b: 1}], 'a'), [{a: 1, b: 1}, {a: 2, b: 1}], 'can use pluck like iterator'); - deepEqual(_.uniq([{0: 1, b: 1}, {0: 1, b: 2}, {0: 1, b: 3}, {0: 2, b: 1}], 0), [{0: 1, b: 1}, {0: 2, b: 1}], 'can use falsey pluck like iterator'); + assert.deepEqual(_.uniq([{a: 1, b: 1}, {a: 1, b: 2}, {a: 1, b: 3}, {a: 2, b: 1}], 'a'), [{a: 1, b: 1}, {a: 2, b: 1}], 'can use pluck like iterator'); + assert.deepEqual(_.uniq([{0: 1, b: 1}, {0: 1, b: 2}, {0: 1, b: 3}, {0: 2, b: 1}], 0), [{0: 1, b: 1}, {0: 2, b: 1}], 'can use falsey pluck like iterator'); }); - test('unique', function() { - strictEqual(_.uniq, _.unique, 'alias for uniq'); + test('unique', function(assert) { + assert.strictEqual(_.unique, _.uniq, 'is an alias for uniq'); }); - test('intersection', function() { + test('intersection', function(assert) { var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho']; - deepEqual(_.intersection(stooges, leaders), ['moe'], 'can take the set intersection of two arrays'); - deepEqual(_(stooges).intersection(leaders), ['moe'], 'can perform an OO-style intersection'); + assert.deepEqual(_.intersection(stooges, leaders), ['moe'], 'can take the set intersection of two arrays'); + assert.deepEqual(_(stooges).intersection(leaders), ['moe'], 'can perform an OO-style intersection'); var result = (function(){ return _.intersection(arguments, leaders); }('moe', 'curly', 'larry')); - deepEqual(result, ['moe'], 'works on an arguments object'); + assert.deepEqual(result, ['moe'], 'works on an arguments object'); var theSixStooges = ['moe', 'moe', 'curly', 'curly', 'larry', 'larry']; - deepEqual(_.intersection(theSixStooges, leaders), ['moe'], 'returns a duplicate-free array'); + assert.deepEqual(_.intersection(theSixStooges, leaders), ['moe'], 'returns a duplicate-free array'); result = _.intersection([2, 4, 3, 1], [1, 2, 3]); - deepEqual(result, [2, 3, 1], 'preserves order of first array'); + assert.deepEqual(result, [2, 3, 1], 'preserves order of first array'); result = _.intersection(null, [1, 2, 3]); - equal(Object.prototype.toString.call(result), '[object Array]', 'returns an empty array when passed null as first argument'); - equal(result.length, 0, 'returns an empty array when passed null as first argument'); + assert.equal(Object.prototype.toString.call(result), '[object Array]', 'returns an empty array when passed null as first argument'); + assert.equal(result.length, 0, 'returns an empty array when passed null as first argument'); result = _.intersection([1, 2, 3], null); - equal(Object.prototype.toString.call(result), '[object Array]', 'returns an empty array when passed null as argument beyond the first'); - equal(result.length, 0, 'returns an empty array when passed null as argument beyond the first'); + assert.equal(Object.prototype.toString.call(result), '[object Array]', 'returns an empty array when passed null as argument beyond the first'); + assert.equal(result.length, 0, 'returns an empty array when passed null as argument beyond the first'); }); - test('union', function() { + test('union', function(assert) { var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]); - deepEqual(result, [1, 2, 3, 30, 40], 'takes the union of a list of arrays'); + assert.deepEqual(result, [1, 2, 3, 30, 40], 'takes the union of a list of arrays'); result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]); - deepEqual(result, [1, 2, 3, 30, 40, [1]], 'takes the union of a list of nested arrays'); + assert.deepEqual(result, [1, 2, 3, 30, 40, [1]], 'takes the union of a list of nested arrays'); var args = null; (function(){ args = arguments; }(1, 2, 3)); result = _.union(args, [2, 30, 1], [1, 40]); - deepEqual(result, [1, 2, 3, 30, 40], 'takes the union of a list of arrays'); + assert.deepEqual(result, [1, 2, 3, 30, 40], 'takes the union of a list of arrays'); result = _.union([1, 2, 3], 4); - deepEqual(result, [1, 2, 3], 'restrict the union to arrays only'); + assert.deepEqual(result, [1, 2, 3], 'restrict the union to arrays only'); }); - test('difference', function() { + test('difference', function(assert) { var result = _.difference([1, 2, 3], [2, 30, 40]); - deepEqual(result, [1, 3], 'takes the difference of two arrays'); + assert.deepEqual(result, [1, 3], 'takes the difference of two arrays'); result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]); - deepEqual(result, [3, 4], 'takes the difference of three arrays'); + assert.deepEqual(result, [3, 4], 'takes the difference of three arrays'); result = _.difference([1, 2, 3], 1); - deepEqual(result, [1, 2, 3], 'restrict the difference to arrays only'); + assert.deepEqual(result, [1, 2, 3], 'restrict the difference to arrays only'); }); - test('zip', function() { + test('zip', function(assert) { var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true]; - deepEqual(_.zip(names, ages, leaders), [ + assert.deepEqual(_.zip(names, ages, leaders), [ ['moe', 30, true], ['larry', 40, void 0], ['curly', 50, void 0] ], 'zipped together arrays of different lengths'); var stooges = _.zip(['moe', 30, 'stooge 1'], ['larry', 40, 'stooge 2'], ['curly', 50, 'stooge 3']); - deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], ['stooge 1', 'stooge 2', 'stooge 3']], 'zipped pairs'); + assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], ['stooge 1', 'stooge 2', 'stooge 3']], 'zipped pairs'); - // In the case of difference lengths of the tuples undefineds + // In the case of different lengths of the tuples, undefined values // should be used as placeholder stooges = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']); - deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], [void 0, void 0, 'extra data']], 'zipped pairs with empties'); + assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], [void 0, void 0, 'extra data']], 'zipped pairs with empties'); var empty = _.zip([]); - deepEqual(empty, [], 'unzipped empty'); + assert.deepEqual(empty, [], 'unzipped empty'); - deepEqual(_.zip(null), [], 'handles null'); - deepEqual(_.zip(), [], '_.zip() returns []'); + assert.deepEqual(_.zip(null), [], 'handles null'); + assert.deepEqual(_.zip(), [], '_.zip() returns []'); }); - test('unzip', function() { - deepEqual(_.unzip(null), [], 'handles null'); + test('unzip', function(assert) { + assert.deepEqual(_.unzip(null), [], 'handles null'); - deepEqual(_.unzip([['a', 'b'], [1, 2]]), [['a', 1], ['b', 2]]); + assert.deepEqual(_.unzip([['a', 'b'], [1, 2]]), [['a', 1], ['b', 2]]); // complements zip var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]); - deepEqual(_.unzip(zipped), [['fred', 'barney'], [30, 40], [true, false]]); + assert.deepEqual(_.unzip(zipped), [['fred', 'barney'], [30, 40], [true, false]]); zipped = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']); - deepEqual(_.unzip(zipped), [['moe', 30, void 0], ['larry', 40, void 0], ['curly', 50, 'extra data']], 'Uses length of largest array'); + assert.deepEqual(_.unzip(zipped), [['moe', 30, void 0], ['larry', 40, void 0], ['curly', 50, 'extra data']], 'Uses length of largest array'); }); - test('object', function() { + test('object', function(assert) { var result = _.object(['moe', 'larry', 'curly'], [30, 40, 50]); var shouldBe = {moe: 30, larry: 40, curly: 50}; - deepEqual(result, shouldBe, 'two arrays zipped together into an object'); + assert.deepEqual(result, shouldBe, 'two arrays zipped together into an object'); result = _.object([['one', 1], ['two', 2], ['three', 3]]); shouldBe = {one: 1, two: 2, three: 3}; - deepEqual(result, shouldBe, 'an array of pairs zipped together into an object'); + assert.deepEqual(result, shouldBe, 'an array of pairs zipped together into an object'); var stooges = {moe: 30, larry: 40, curly: 50}; - deepEqual(_.object(_.pairs(stooges)), stooges, 'an object converted to pairs and back to an object'); + assert.deepEqual(_.object(_.pairs(stooges)), stooges, 'an object converted to pairs and back to an object'); - deepEqual(_.object(null), {}, 'handles nulls'); + assert.deepEqual(_.object(null), {}, 'handles nulls'); }); - test('indexOf', function() { + test('indexOf', function(assert) { var numbers = [1, 2, 3]; - equal(_.indexOf(numbers, 2), 1, 'can compute indexOf'); + assert.equal(_.indexOf(numbers, 2), 1, 'can compute indexOf'); var result = (function(){ return _.indexOf(arguments, 2); }(1, 2, 3)); - equal(result, 1, 'works on an arguments object'); + assert.equal(result, 1, 'works on an arguments object'); _.each([null, void 0, [], false], function(val) { var msg = 'Handles: ' + (_.isArray(val) ? '[]' : val); - equal(_.indexOf(val, 2), -1, msg); - equal(_.indexOf(val, 2, -1), -1, msg); - equal(_.indexOf(val, 2, -20), -1, msg); - equal(_.indexOf(val, 2, 15), -1, msg); + assert.equal(_.indexOf(val, 2), -1, msg); + assert.equal(_.indexOf(val, 2, -1), -1, msg); + assert.equal(_.indexOf(val, 2, -20), -1, msg); + assert.equal(_.indexOf(val, 2, 15), -1, msg); }); var num = 35; numbers = [10, 20, 30, 40, 50]; var index = _.indexOf(numbers, num, true); - equal(index, -1, '35 is not in the list'); + assert.equal(index, -1, '35 is not in the list'); numbers = [10, 20, 30, 40, 50]; num = 40; index = _.indexOf(numbers, num, true); - equal(index, 3, '40 is in the list'); + assert.equal(index, 3, '40 is in the list'); numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40; - equal(_.indexOf(numbers, num, true), 1, '40 is in the list'); - equal(_.indexOf(numbers, 6, true), -1, '6 isnt in the list'); - equal(_.indexOf([1, 2, 5, 4, 6, 7], 5, true), -1, 'sorted indexOf doesn\'t uses binary search'); - ok(_.every(['1', [], {}, null], function() { + assert.equal(_.indexOf(numbers, num, true), 1, '40 is in the list'); + assert.equal(_.indexOf(numbers, 6, true), -1, '6 isnt in the list'); + assert.equal(_.indexOf([1, 2, 5, 4, 6, 7], 5, true), -1, 'sorted indexOf doesn\'t uses binary search'); + assert.ok(_.every(['1', [], {}, null], function() { return _.indexOf(numbers, num, {}) === 1; }), 'non-nums as fromIndex make indexOf assume sorted'); numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; index = _.indexOf(numbers, 2, 5); - equal(index, 7, 'supports the fromIndex argument'); + assert.equal(index, 7, 'supports the fromIndex argument'); index = _.indexOf([,,, 0], void 0); - equal(index, 0, 'treats sparse arrays as if they were dense'); + assert.equal(index, 0, 'treats sparse arrays as if they were dense'); var array = [1, 2, 3, 1, 2, 3]; - strictEqual(_.indexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index'); - strictEqual(_.indexOf(array, 1, -2), -1, 'neg `fromIndex` starts at the right index'); - strictEqual(_.indexOf(array, 2, -3), 4); + assert.strictEqual(_.indexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index'); + assert.strictEqual(_.indexOf(array, 1, -2), -1, 'neg `fromIndex` starts at the right index'); + assert.strictEqual(_.indexOf(array, 2, -3), 4); _.each([-6, -8, -Infinity], function(fromIndex) { - strictEqual(_.indexOf(array, 1, fromIndex), 0); + assert.strictEqual(_.indexOf(array, 1, fromIndex), 0); }); - strictEqual(_.indexOf([1, 2, 3], 1, true), 0); + assert.strictEqual(_.indexOf([1, 2, 3], 1, true), 0); index = _.indexOf([], void 0, true); - equal(index, -1, 'empty array with truthy `isSorted` returns -1'); + assert.equal(index, -1, 'empty array with truthy `isSorted` returns -1'); }); - test('indexOf with NaN', function() { - strictEqual(_.indexOf([1, 2, NaN, NaN], NaN), 2, 'Expected [1, 2, NaN] to contain NaN'); - strictEqual(_.indexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN'); + test('indexOf with NaN', function(assert) { + assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN), 2, 'Expected [1, 2, NaN] to contain NaN'); + assert.strictEqual(_.indexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN'); - strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, 1), 2, 'startIndex does not affect result'); - strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, -2), 2, 'startIndex does not affect result'); + assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, 1), 2, 'startIndex does not affect result'); + assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, -2), 2, 'startIndex does not affect result'); (function() { - strictEqual(_.indexOf(arguments, NaN), 2, 'Expected arguments [1, 2, NaN] to contain NaN'); + assert.strictEqual(_.indexOf(arguments, NaN), 2, 'Expected arguments [1, 2, NaN] to contain NaN'); }(1, 2, NaN, NaN)); }); - test('indexOf with +- 0', function() { + test('indexOf with +- 0', function(assert) { _.each([-0, +0], function(val) { - strictEqual(_.indexOf([1, 2, val, val], val), 2); - strictEqual(_.indexOf([1, 2, val, val], -val), 2); + assert.strictEqual(_.indexOf([1, 2, val, val], val), 2); + assert.strictEqual(_.indexOf([1, 2, val, val], -val), 2); }); }); - test('lastIndexOf', function() { + test('lastIndexOf', function(assert) { var numbers = [1, 0, 1]; var falsey = [void 0, '', 0, false, NaN, null, void 0]; - equal(_.lastIndexOf(numbers, 1), 2); + assert.equal(_.lastIndexOf(numbers, 1), 2); numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0]; numbers.lastIndexOf = null; - equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function'); - equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element'); + assert.equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function'); + assert.equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element'); var result = (function(){ return _.lastIndexOf(arguments, 1); }(1, 0, 1, 0, 0, 1, 0, 0, 0)); - equal(result, 5, 'works on an arguments object'); + assert.equal(result, 5, 'works on an arguments object'); _.each([null, void 0, [], false], function(val) { var msg = 'Handles: ' + (_.isArray(val) ? '[]' : val); - equal(_.lastIndexOf(val, 2), -1, msg); - equal(_.lastIndexOf(val, 2, -1), -1, msg); - equal(_.lastIndexOf(val, 2, -20), -1, msg); - equal(_.lastIndexOf(val, 2, 15), -1, msg); + assert.equal(_.lastIndexOf(val, 2), -1, msg); + assert.equal(_.lastIndexOf(val, 2, -1), -1, msg); + assert.equal(_.lastIndexOf(val, 2, -20), -1, msg); + assert.equal(_.lastIndexOf(val, 2, 15), -1, msg); }); numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; var index = _.lastIndexOf(numbers, 2, 2); - equal(index, 1, 'supports the fromIndex argument'); + assert.equal(index, 1, 'supports the fromIndex argument'); var array = [1, 2, 3, 1, 2, 3]; - strictEqual(_.lastIndexOf(array, 1, 0), 0, 'starts at the correct from idx'); - strictEqual(_.lastIndexOf(array, 3), 5, 'should return the index of the last matched value'); - strictEqual(_.lastIndexOf(array, 4), -1, 'should return `-1` for an unmatched value'); + assert.strictEqual(_.lastIndexOf(array, 1, 0), 0, 'starts at the correct from idx'); + assert.strictEqual(_.lastIndexOf(array, 3), 5, 'should return the index of the last matched value'); + assert.strictEqual(_.lastIndexOf(array, 4), -1, 'should return `-1` for an unmatched value'); - strictEqual(_.lastIndexOf(array, 1, 2), 0, 'should work with a positive `fromIndex`'); + assert.strictEqual(_.lastIndexOf(array, 1, 2), 0, 'should work with a positive `fromIndex`'); _.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) { - strictEqual(_.lastIndexOf(array, void 0, fromIndex), -1); - strictEqual(_.lastIndexOf(array, 1, fromIndex), 3); - strictEqual(_.lastIndexOf(array, '', fromIndex), -1); + assert.strictEqual(_.lastIndexOf(array, void 0, fromIndex), -1); + assert.strictEqual(_.lastIndexOf(array, 1, fromIndex), 3); + assert.strictEqual(_.lastIndexOf(array, '', fromIndex), -1); }); var expected = _.map(falsey, function(value) { @@ -410,39 +408,39 @@ return _.lastIndexOf(array, 3, fromIndex); }); - deepEqual(actual, expected, 'should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`'); - strictEqual(_.lastIndexOf(array, 3, '1'), 5, 'should treat non-number `fromIndex` values as `array.length`'); - strictEqual(_.lastIndexOf(array, 3, true), 5, 'should treat non-number `fromIndex` values as `array.length`'); + assert.deepEqual(actual, expected, 'should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`'); + assert.strictEqual(_.lastIndexOf(array, 3, '1'), 5, 'should treat non-number `fromIndex` values as `array.length`'); + assert.strictEqual(_.lastIndexOf(array, 3, true), 5, 'should treat non-number `fromIndex` values as `array.length`'); - strictEqual(_.lastIndexOf(array, 2, -3), 1, 'should work with a negative `fromIndex`'); - strictEqual(_.lastIndexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index'); + assert.strictEqual(_.lastIndexOf(array, 2, -3), 1, 'should work with a negative `fromIndex`'); + assert.strictEqual(_.lastIndexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index'); - deepEqual(_.map([-6, -8, -Infinity], function(fromIndex) { + assert.deepEqual(_.map([-6, -8, -Infinity], function(fromIndex) { return _.lastIndexOf(array, 1, fromIndex); }), [0, -1, -1]); }); - test('lastIndexOf with NaN', function() { - strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN), 3, 'Expected [1, 2, NaN] to contain NaN'); - strictEqual(_.lastIndexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN'); + test('lastIndexOf with NaN', function(assert) { + assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN), 3, 'Expected [1, 2, NaN] to contain NaN'); + assert.strictEqual(_.lastIndexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN'); - strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, 2), 2, 'fromIndex does not affect result'); - strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, -2), 2, 'fromIndex does not affect result'); + assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, 2), 2, 'fromIndex does not affect result'); + assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, -2), 2, 'fromIndex does not affect result'); (function() { - strictEqual(_.lastIndexOf(arguments, NaN), 3, 'Expected arguments [1, 2, NaN] to contain NaN'); + assert.strictEqual(_.lastIndexOf(arguments, NaN), 3, 'Expected arguments [1, 2, NaN] to contain NaN'); }(1, 2, NaN, NaN)); }); - test('lastIndexOf with +- 0', function() { + test('lastIndexOf with +- 0', function(assert) { _.each([-0, +0], function(val) { - strictEqual(_.lastIndexOf([1, 2, val, val], val), 3); - strictEqual(_.lastIndexOf([1, 2, val, val], -val), 3); - strictEqual(_.lastIndexOf([-1, 1, 2], -val), -1); + assert.strictEqual(_.lastIndexOf([1, 2, val, val], val), 3); + assert.strictEqual(_.lastIndexOf([1, 2, val, val], -val), 3); + assert.strictEqual(_.lastIndexOf([-1, 1, 2], -val), -1); }); }); - test('findIndex', function() { + test('findIndex', function(assert) { var objects = [ {a: 0, b: 0}, {a: 1, b: 1}, @@ -450,42 +448,42 @@ {a: 0, b: 0} ]; - equal(_.findIndex(objects, function(obj) { + assert.equal(_.findIndex(objects, function(obj) { return obj.a === 0; }), 0); - equal(_.findIndex(objects, function(obj) { + assert.equal(_.findIndex(objects, function(obj) { return obj.b * obj.a === 4; }), 2); - equal(_.findIndex(objects, 'a'), 1, 'Uses lookupIterator'); + assert.equal(_.findIndex(objects, 'a'), 1, 'Uses lookupIterator'); - equal(_.findIndex(objects, function(obj) { + assert.equal(_.findIndex(objects, function(obj) { return obj.b * obj.a === 5; }), -1); - equal(_.findIndex(null, _.noop), -1); - strictEqual(_.findIndex(objects, function(a) { + assert.equal(_.findIndex(null, _.noop), -1); + assert.strictEqual(_.findIndex(objects, function(a) { return a.foo === null; }), -1); _.findIndex([{a: 1}], function(a, key, obj) { - equal(key, 0); - deepEqual(obj, [{a: 1}]); - strictEqual(this, objects, 'called with context'); + assert.equal(key, 0); + assert.deepEqual(obj, [{a: 1}]); + assert.strictEqual(this, objects, 'called with context'); }, objects); var sparse = []; sparse[20] = {a: 2, b: 2}; - equal(_.findIndex(sparse, function(obj) { + assert.equal(_.findIndex(sparse, function(obj) { return obj && obj.b * obj.a === 4; }), 20, 'Works with sparse arrays'); var array = [1, 2, 3, 4]; array.match = 55; - strictEqual(_.findIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys'); + assert.strictEqual(_.findIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys'); }); - test('findLastIndex', function() { + test('findLastIndex', function(assert) { var objects = [ {a: 0, b: 0}, {a: 1, b: 1}, @@ -493,65 +491,67 @@ {a: 0, b: 0} ]; - equal(_.findLastIndex(objects, function(obj) { + assert.equal(_.findLastIndex(objects, function(obj) { return obj.a === 0; }), 3); - equal(_.findLastIndex(objects, function(obj) { + assert.equal(_.findLastIndex(objects, function(obj) { return obj.b * obj.a === 4; }), 2); - equal(_.findLastIndex(objects, 'a'), 2, 'Uses lookupIterator'); + assert.equal(_.findLastIndex(objects, 'a'), 2, 'Uses lookupIterator'); - equal(_.findLastIndex(objects, function(obj) { + assert.equal(_.findLastIndex(objects, function(obj) { return obj.b * obj.a === 5; }), -1); - equal(_.findLastIndex(null, _.noop), -1); - strictEqual(_.findLastIndex(objects, function(a) { + assert.equal(_.findLastIndex(null, _.noop), -1); + assert.strictEqual(_.findLastIndex(objects, function(a) { return a.foo === null; }), -1); _.findLastIndex([{a: 1}], function(a, key, obj) { - equal(key, 0); - deepEqual(obj, [{a: 1}]); - strictEqual(this, objects, 'called with context'); + assert.equal(key, 0); + assert.deepEqual(obj, [{a: 1}]); + assert.strictEqual(this, objects, 'called with context'); }, objects); var sparse = []; sparse[20] = {a: 2, b: 2}; - equal(_.findLastIndex(sparse, function(obj) { + assert.equal(_.findLastIndex(sparse, function(obj) { return obj && obj.b * obj.a === 4; }), 20, 'Works with sparse arrays'); var array = [1, 2, 3, 4]; array.match = 55; - strictEqual(_.findLastIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys'); + assert.strictEqual(_.findLastIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys'); }); - test('range', function() { - deepEqual(_.range(0), [], 'range with 0 as a first argument generates an empty array'); - deepEqual(_.range(4), [0, 1, 2, 3], 'range with a single positive argument generates an array of elements 0,1,2,...,n-1'); - deepEqual(_.range(5, 8), [5, 6, 7], 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1'); - deepEqual(_.range(8, 5), [], 'range with two arguments a & b, b<a generates an empty array'); - deepEqual(_.range(3, 10, 3), [3, 6, 9], 'range with three arguments a & b & c, c < b-a, a < b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) < c'); - deepEqual(_.range(3, 10, 15), [3], 'range with three arguments a & b & c, c > b-a, a < b generates an array with a single element, equal to a'); - deepEqual(_.range(12, 7, -2), [12, 10, 8], 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b'); - deepEqual(_.range(0, -10, -1), [0, -1, -2, -3, -4, -5, -6, -7, -8, -9], 'final example in the Python docs'); + test('range', function(assert) { + assert.deepEqual(_.range(0), [], 'range with 0 as a first argument generates an empty array'); + assert.deepEqual(_.range(4), [0, 1, 2, 3], 'range with a single positive argument generates an array of elements 0,1,2,...,n-1'); + assert.deepEqual(_.range(5, 8), [5, 6, 7], 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1'); + assert.deepEqual(_.range(3, 10, 3), [3, 6, 9], 'range with three arguments a & b & c, c < b-a, a < b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) < c'); + assert.deepEqual(_.range(3, 10, 15), [3], 'range with three arguments a & b & c, c > b-a, a < b generates an array with a single element, equal to a'); + assert.deepEqual(_.range(12, 7, -2), [12, 10, 8], 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b'); + assert.deepEqual(_.range(0, -10, -1), [0, -1, -2, -3, -4, -5, -6, -7, -8, -9], 'final example in the Python docs'); + assert.strictEqual(1 / _.range(-0, 1)[0], -Infinity, 'should preserve -0'); + assert.deepEqual(_.range(8, 5), [8, 7, 6], 'negative range generates descending array'); + assert.deepEqual(_.range(-3), [0, -1, -2], 'negative range generates descending array'); }); - test('chunk', function() { - deepEqual(_.chunk([], 2), [], 'chunk for empty array returns an empty array'); + test('chunk', function(assert) { + assert.deepEqual(_.chunk([], 2), [], 'chunk for empty array returns an empty array'); - deepEqual(_.chunk([1, 2, 3], 0), [], 'chunk into parts of 0 elements returns empty array'); - deepEqual(_.chunk([1, 2, 3], -1), [], 'chunk into parts of negative amount of elements returns an empty array'); - deepEqual(_.chunk([1, 2, 3]), [], 'defaults to empty array (chunk size 0)'); + assert.deepEqual(_.chunk([1, 2, 3], 0), [], 'chunk into parts of 0 elements returns empty array'); + assert.deepEqual(_.chunk([1, 2, 3], -1), [], 'chunk into parts of negative amount of elements returns an empty array'); + assert.deepEqual(_.chunk([1, 2, 3]), [], 'defaults to empty array (chunk size 0)'); - deepEqual(_.chunk([1, 2, 3], 1), [[1], [2], [3]], 'chunk into parts of 1 elements returns original array'); + assert.deepEqual(_.chunk([1, 2, 3], 1), [[1], [2], [3]], 'chunk into parts of 1 elements returns original array'); - deepEqual(_.chunk([1, 2, 3], 3), [[1, 2, 3]], 'chunk into parts of current array length elements returns the original array'); - deepEqual(_.chunk([1, 2, 3], 5), [[1, 2, 3]], 'chunk into parts of more then current array length elements returns the original array'); + assert.deepEqual(_.chunk([1, 2, 3], 3), [[1, 2, 3]], 'chunk into parts of current array length elements returns the original array'); + assert.deepEqual(_.chunk([1, 2, 3], 5), [[1, 2, 3]], 'chunk into parts of more then current array length elements returns the original array'); - deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 2), [[10, 20], [30, 40], [50, 60], [70]], 'chunk into parts of less then current array length elements'); - deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 3), [[10, 20, 30], [40, 50, 60], [70]], 'chunk into parts of less then current array length elements'); + assert.deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 2), [[10, 20], [30, 40], [50, 60], [70]], 'chunk into parts of less then current array length elements'); + assert.deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 3), [[10, 20, 30], [40, 50, 60], [70]], 'chunk into parts of less then current array length elements'); }); }()); diff --git a/vendor/underscore/test/chaining.js b/vendor/underscore/test/chaining.js index c5830f36f..1e708b90b 100644 --- a/vendor/underscore/test/chaining.js +++ b/vendor/underscore/test/chaining.js @@ -3,7 +3,7 @@ QUnit.module('Chaining'); - test('map/flatten/reduce', function() { + test('map/flatten/reduce', function(assert) { var lyrics = [ 'I\'m a lumberjack and I\'m okay', 'I sleep all night and I work all day', @@ -19,11 +19,11 @@ return hash; }, {}) .value(); - equal(counts.a, 16, 'counted all the letters in the song'); - equal(counts.e, 10, 'counted all the letters in the song'); + assert.equal(counts.a, 16, 'counted all the letters in the song'); + assert.equal(counts.e, 10, 'counted all the letters in the song'); }); - test('select/reject/sortBy', function() { + test('select/reject/sortBy', function(assert) { var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; numbers = _(numbers).chain().select(function(n) { return n % 2 === 0; @@ -32,10 +32,10 @@ }).sortBy(function(n) { return -n; }).value(); - deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers'); + assert.deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers'); }); - test('select/reject/sortBy in functional style', function() { + test('select/reject/sortBy in functional style', function(assert) { var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; numbers = _.chain(numbers).select(function(n) { return n % 2 === 0; @@ -44,10 +44,10 @@ }).sortBy(function(n) { return -n; }).value(); - deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers'); + assert.deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers'); }); - test('reverse/concat/unshift/pop/map', function() { + test('reverse/concat/unshift/pop/map', function(assert) { var numbers = [1, 2, 3, 4, 5]; numbers = _(numbers).chain() .reverse() @@ -56,44 +56,44 @@ .pop() .map(function(n){ return n * 2; }) .value(); - deepEqual(numbers, [34, 10, 8, 6, 4, 2, 10, 10], 'can chain together array functions.'); + assert.deepEqual(numbers, [34, 10, 8, 6, 4, 2, 10, 10], 'can chain together array functions.'); }); - test('splice', function() { + test('splice', function(assert) { var instance = _([1, 2, 3, 4, 5]).chain(); - deepEqual(instance.splice(1, 3).value(), [1, 5]); - deepEqual(instance.splice(1, 0).value(), [1, 5]); - deepEqual(instance.splice(1, 1).value(), [1]); - deepEqual(instance.splice(0, 1).value(), [], '#397 Can create empty array'); + assert.deepEqual(instance.splice(1, 3).value(), [1, 5]); + assert.deepEqual(instance.splice(1, 0).value(), [1, 5]); + assert.deepEqual(instance.splice(1, 1).value(), [1]); + assert.deepEqual(instance.splice(0, 1).value(), [], '#397 Can create empty array'); }); - test('shift', function() { + test('shift', function(assert) { var instance = _([1, 2, 3]).chain(); - deepEqual(instance.shift().value(), [2, 3]); - deepEqual(instance.shift().value(), [3]); - deepEqual(instance.shift().value(), [], '#397 Can create empty array'); + assert.deepEqual(instance.shift().value(), [2, 3]); + assert.deepEqual(instance.shift().value(), [3]); + assert.deepEqual(instance.shift().value(), [], '#397 Can create empty array'); }); - test('pop', function() { + test('pop', function(assert) { var instance = _([1, 2, 3]).chain(); - deepEqual(instance.pop().value(), [1, 2]); - deepEqual(instance.pop().value(), [1]); - deepEqual(instance.pop().value(), [], '#397 Can create empty array'); + assert.deepEqual(instance.pop().value(), [1, 2]); + assert.deepEqual(instance.pop().value(), [1]); + assert.deepEqual(instance.pop().value(), [], '#397 Can create empty array'); }); - test('chaining works in small stages', function() { + test('chaining works in small stages', function(assert) { var o = _([1, 2, 3, 4]).chain(); - deepEqual(o.filter(function(i) { return i < 3; }).value(), [1, 2]); - deepEqual(o.filter(function(i) { return i > 2; }).value(), [3, 4]); + assert.deepEqual(o.filter(function(i) { return i < 3; }).value(), [1, 2]); + assert.deepEqual(o.filter(function(i) { return i > 2; }).value(), [3, 4]); }); - test('#1562: Engine proxies for chained functions', function() { + test('#1562: Engine proxies for chained functions', function(assert) { var wrapped = _(512); - strictEqual(wrapped.toJSON(), 512); - strictEqual(wrapped.valueOf(), 512); - strictEqual(+wrapped, 512); - strictEqual(wrapped.toString(), '512'); - strictEqual('' + wrapped, '512'); + assert.strictEqual(wrapped.toJSON(), 512); + assert.strictEqual(wrapped.valueOf(), 512); + assert.strictEqual(+wrapped, 512); + assert.strictEqual(wrapped.toString(), '512'); + assert.strictEqual('' + wrapped, '512'); }); }()); diff --git a/vendor/underscore/test/collections.js b/vendor/underscore/test/collections.js index 485eb0ce8..721f4acb7 100644 --- a/vendor/underscore/test/collections.js +++ b/vendor/underscore/test/collections.js @@ -3,24 +3,24 @@ QUnit.module('Collections'); - test('each', function() { + test('each', function(assert) { _.each([1, 2, 3], function(num, i) { - equal(num, i + 1, 'each iterators provide value and iteration count'); + assert.equal(num, i + 1, 'each iterators provide value and iteration count'); }); var answers = []; _.each([1, 2, 3], function(num){ answers.push(num * this.multiplier); }, {multiplier: 5}); - deepEqual(answers, [5, 10, 15], 'context object property accessed'); + assert.deepEqual(answers, [5, 10, 15], 'context object property accessed'); answers = []; _.each([1, 2, 3], function(num){ answers.push(num); }); - deepEqual(answers, [1, 2, 3], 'aliased as "forEach"'); + assert.deepEqual(answers, [1, 2, 3], 'can iterate a simple array'); answers = []; var obj = {one: 1, two: 2, three: 3}; obj.constructor.prototype.four = 4; _.each(obj, function(value, key){ answers.push(key); }); - deepEqual(answers, ['one', 'two', 'three'], 'iterating over objects works, and ignores the object prototype.'); + assert.deepEqual(answers, ['one', 'two', 'three'], 'iterating over objects works, and ignores the object prototype.'); delete obj.constructor.prototype.four; // ensure the each function is JITed @@ -28,36 +28,36 @@ var count = 0; obj = {1: 'foo', 2: 'bar', 3: 'baz'}; _.each(obj, function(){ count++; }); - equal(count, 3, 'the fun should be called only 3 times'); + assert.equal(count, 3, 'the fun should be called only 3 times'); var answer = null; _.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; }); - ok(answer, 'can reference the original collection from inside the iterator'); + assert.ok(answer, 'can reference the original collection from inside the iterator'); answers = 0; _.each(null, function(){ ++answers; }); - equal(answers, 0, 'handles a null properly'); + assert.equal(answers, 0, 'handles a null properly'); _.each(false, function(){}); var a = [1, 2, 3]; - strictEqual(_.each(a, function(){}), a); - strictEqual(_.each(null, function(){}), null); + assert.strictEqual(_.each(a, function(){}), a); + assert.strictEqual(_.each(null, function(){}), null); }); - test('forEach', function() { - strictEqual(_.each, _.forEach, 'alias for each'); + test('forEach', function(assert) { + assert.strictEqual(_.forEach, _.each, 'is an alias for each'); }); - test('lookupIterator with contexts', function() { + test('lookupIterator with contexts', function(assert) { _.each([true, false, 'yes', '', 0, 1, {}], function(context) { _.each([1], function() { - equal(this, context); + assert.equal(this, context); }, context); }); }); - test('Iterating objects with sketchy length properties', function() { + test('Iterating objects with sketchy length properties', function(assert) { var functions = [ 'each', 'map', 'filter', 'find', 'some', 'every', 'max', 'min', @@ -79,29 +79,29 @@ {length: new Number(15)} ]; - expect(tricks.length * (functions.length + reducers.length + 4)); + assert.expect(tricks.length * (functions.length + reducers.length + 4)); _.each(tricks, function(trick) { var length = trick.length; - strictEqual(_.size(trick), 1, 'size on obj with length: ' + length); - deepEqual(_.toArray(trick), [length], 'toArray on obj with length: ' + length); - deepEqual(_.shuffle(trick), [length], 'shuffle on obj with length: ' + length); - deepEqual(_.sample(trick), length, 'sample on obj with length: ' + length); + assert.strictEqual(_.size(trick), 1, 'size on obj with length: ' + length); + assert.deepEqual(_.toArray(trick), [length], 'toArray on obj with length: ' + length); + assert.deepEqual(_.shuffle(trick), [length], 'shuffle on obj with length: ' + length); + assert.deepEqual(_.sample(trick), length, 'sample on obj with length: ' + length); _.each(functions, function(method) { _[method](trick, function(val, key) { - strictEqual(key, 'length', method + ': ran with length = ' + val); + assert.strictEqual(key, 'length', method + ': ran with length = ' + val); }); }); _.each(reducers, function(method) { - strictEqual(_[method](trick), trick.length, method); + assert.strictEqual(_[method](trick), trick.length, method); }); }); }); - test('Resistant to collection length and properties changing while iterating', function() { + test('Resistant to collection length and properties changing while iterating', function(assert) { var collection = [ 'each', 'map', 'filter', 'find', @@ -124,14 +124,14 @@ ++answers; return method === 'every' ? true : null; }, {}); - equal(answers, 100, method + ' enumerates [0, length)'); + assert.equal(answers, 100, method + ' enumerates [0, length)'); var growingCollection = [1, 2, 3], count = 0; _[method](growingCollection, function() { if (count < 10) growingCollection.push(count++); return method === 'every' ? true : null; }, {}); - equal(count, 3, method + ' is resistant to length changes'); + assert.equal(count, 3, method + ' is resistant to length changes'); }); _.each(collection.concat(object), function(method) { @@ -141,85 +141,86 @@ return method === 'every' ? true : null; }, {}); - equal(count, 2, method + ' is resistant to property changes'); + assert.equal(count, 2, method + ' is resistant to property changes'); }); }); - test('map', function() { + test('map', function(assert) { var doubled = _.map([1, 2, 3], function(num){ return num * 2; }); - deepEqual(doubled, [2, 4, 6], 'doubled numbers'); + assert.deepEqual(doubled, [2, 4, 6], 'doubled numbers'); var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; }, {multiplier: 3}); - deepEqual(tripled, [3, 6, 9], 'tripled numbers with context'); + assert.deepEqual(tripled, [3, 6, 9], 'tripled numbers with context'); doubled = _([1, 2, 3]).map(function(num){ return num * 2; }); - deepEqual(doubled, [2, 4, 6], 'OO-style doubled numbers'); + assert.deepEqual(doubled, [2, 4, 6], 'OO-style doubled numbers'); var ids = _.map({length: 2, 0: {id: '1'}, 1: {id: '2'}}, function(n){ return n.id; }); - deepEqual(ids, ['1', '2'], 'Can use collection methods on Array-likes.'); + assert.deepEqual(ids, ['1', '2'], 'Can use collection methods on Array-likes.'); - deepEqual(_.map(null, _.noop), [], 'handles a null properly'); + assert.deepEqual(_.map(null, _.noop), [], 'handles a null properly'); - deepEqual(_.map([1], function() { + assert.deepEqual(_.map([1], function() { return this.length; }, [5]), [1], 'called with context'); // Passing a property name like _.pluck. var people = [{name: 'moe', age: 30}, {name: 'curly', age: 50}]; - deepEqual(_.map(people, 'name'), ['moe', 'curly'], 'predicate string map to object properties'); + assert.deepEqual(_.map(people, 'name'), ['moe', 'curly'], 'predicate string map to object properties'); }); - test('collect', function() { - strictEqual(_.map, _.collect, 'alias for map'); + test('collect', function(assert) { + assert.strictEqual(_.collect, _.map, 'is an alias for map'); }); - test('reduce', function() { + test('reduce', function(assert) { var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0); - equal(sum, 6, 'can sum up an array'); + assert.equal(sum, 6, 'can sum up an array'); var context = {multiplier: 3}; sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num * this.multiplier; }, 0, context); - equal(sum, 18, 'can reduce with a context object'); - - sum = _.inject([1, 2, 3], function(memo, num){ return memo + num; }, 0); - equal(sum, 6, 'aliased as "inject"'); + assert.equal(sum, 18, 'can reduce with a context object'); sum = _([1, 2, 3]).reduce(function(memo, num){ return memo + num; }, 0); - equal(sum, 6, 'OO-style reduce'); + assert.equal(sum, 6, 'OO-style reduce'); sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }); - equal(sum, 6, 'default initial value'); + assert.equal(sum, 6, 'default initial value'); var prod = _.reduce([1, 2, 3, 4], function(memo, num){ return memo * num; }); - equal(prod, 24, 'can reduce via multiplication'); + assert.equal(prod, 24, 'can reduce via multiplication'); - ok(_.reduce(null, _.noop, 138) === 138, 'handles a null (with initial value) properly'); - equal(_.reduce([], _.noop, void 0), void 0, 'undefined can be passed as a special case'); - equal(_.reduce([_], _.noop), _, 'collection of length one with no initial value returns the first item'); - equal(_.reduce([], _.noop), void 0, 'returns undefined when collection is empty and no initial value'); + assert.ok(_.reduce(null, _.noop, 138) === 138, 'handles a null (with initial value) properly'); + assert.equal(_.reduce([], _.noop, void 0), void 0, 'undefined can be passed as a special case'); + assert.equal(_.reduce([_], _.noop), _, 'collection of length one with no initial value returns the first item'); + assert.equal(_.reduce([], _.noop), void 0, 'returns undefined when collection is empty and no initial value'); }); - test('foldl', function() { - strictEqual(_.reduce, _.foldl, 'alias for reduce'); + test('foldl', function(assert) { + assert.strictEqual(_.foldl, _.reduce, 'is an alias for reduce'); }); - test('reduceRight', function() { + test('inject', function(assert) { + assert.strictEqual(_.inject, _.reduce, 'is an alias for reduce'); + }); + + test('reduceRight', function(assert) { var list = _.reduceRight(['foo', 'bar', 'baz'], function(memo, str){ return memo + str; }, ''); - equal(list, 'bazbarfoo', 'can perform right folds'); + assert.equal(list, 'bazbarfoo', 'can perform right folds'); list = _.reduceRight(['foo', 'bar', 'baz'], function(memo, str){ return memo + str; }); - equal(list, 'bazbarfoo', 'default initial value'); + assert.equal(list, 'bazbarfoo', 'default initial value'); var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(memo, num){ return memo + num; }); - equal(sum, 6, 'default initial value on object'); + assert.equal(sum, 6, 'default initial value on object'); - ok(_.reduceRight(null, _.noop, 138) === 138, 'handles a null (with initial value) properly'); - equal(_.reduceRight([_], _.noop), _, 'collection of length one with no initial value returns the first item'); + assert.ok(_.reduceRight(null, _.noop, 138) === 138, 'handles a null (with initial value) properly'); + assert.equal(_.reduceRight([_], _.noop), _, 'collection of length one with no initial value returns the first item'); - equal(_.reduceRight([], _.noop, void 0), void 0, 'undefined can be passed as a special case'); - equal(_.reduceRight([], _.noop), void 0, 'returns undefined when collection is empty and no initial value'); + assert.equal(_.reduceRight([], _.noop, void 0), void 0, 'undefined can be passed as a special case'); + assert.equal(_.reduceRight([], _.noop), void 0, 'returns undefined when collection is empty and no initial value'); // Assert that the correct arguments are being passed. @@ -236,7 +237,7 @@ if (!args) args = _.toArray(arguments); }, init); - deepEqual(args, expected); + assert.deepEqual(args, expected); // And again, with numeric keys. @@ -252,30 +253,30 @@ if (!args) args = _.toArray(arguments); }, init); - deepEqual(args, expected); + assert.deepEqual(args, expected); }); - test('foldr', function() { - strictEqual(_.reduceRight, _.foldr, 'alias for reduceRight'); + test('foldr', function(assert) { + assert.strictEqual(_.foldr, _.reduceRight, 'is an alias for reduceRight'); }); - test('find', function() { + test('find', function(assert) { var array = [1, 2, 3, 4]; - strictEqual(_.find(array, function(n) { return n > 2; }), 3, 'should return first found `value`'); - strictEqual(_.find(array, function() { return false; }), void 0, 'should return `undefined` if `value` is not found'); + assert.strictEqual(_.find(array, function(n) { return n > 2; }), 3, 'should return first found `value`'); + assert.strictEqual(_.find(array, function() { return false; }), void 0, 'should return `undefined` if `value` is not found'); array.dontmatch = 55; - strictEqual(_.find(array, function(x) { return x === 55; }), void 0, 'iterates array-likes correctly'); + assert.strictEqual(_.find(array, function(x) { return x === 55; }), void 0, 'iterates array-likes correctly'); // Matching an object like _.findWhere. var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}]; - deepEqual(_.find(list, {a: 1}), {a: 1, b: 2}, 'can be used as findWhere'); - deepEqual(_.find(list, {b: 4}), {a: 1, b: 4}); - ok(!_.find(list, {c: 1}), 'undefined when not found'); - ok(!_.find([], {c: 1}), 'undefined when searching empty list'); + assert.deepEqual(_.find(list, {a: 1}), {a: 1, b: 2}, 'can be used as findWhere'); + assert.deepEqual(_.find(list, {b: 4}), {a: 1, b: 4}); + assert.ok(!_.find(list, {c: 1}), 'undefined when not found'); + assert.ok(!_.find([], {c: 1}), 'undefined when searching empty list'); var result = _.find([1, 2, 3], function(num){ return num * 2 === 4; }); - equal(result, 2, 'found the first "2" and broke the loop'); + assert.equal(result, 2, 'found the first "2" and broke the loop'); var obj = { a: {x: 1, z: 3}, @@ -284,348 +285,367 @@ d: {x: 4, z: 1} }; - deepEqual(_.find(obj, {x: 2}), {x: 2, z: 2}, 'works on objects'); - deepEqual(_.find(obj, {x: 2, z: 1}), void 0); - deepEqual(_.find(obj, function(x) { + assert.deepEqual(_.find(obj, {x: 2}), {x: 2, z: 2}, 'works on objects'); + assert.deepEqual(_.find(obj, {x: 2, z: 1}), void 0); + assert.deepEqual(_.find(obj, function(x) { return x.x === 4; }), {x: 4, z: 1}); _.findIndex([{a: 1}], function(a, key, o) { - equal(key, 0); - deepEqual(o, [{a: 1}]); - strictEqual(this, _, 'called with context'); + assert.equal(key, 0); + assert.deepEqual(o, [{a: 1}]); + assert.strictEqual(this, _, 'called with context'); }, _); }); - test('detect', function() { - strictEqual(_.detect, _.find, 'alias for detect'); + test('detect', function(assert) { + assert.strictEqual(_.detect, _.find, 'is an alias for find'); }); - test('filter', function() { + test('filter', function(assert) { var evenArray = [1, 2, 3, 4, 5, 6]; var evenObject = {one: 1, two: 2, three: 3}; var isEven = function(num){ return num % 2 === 0; }; - deepEqual(_.filter(evenArray, isEven), [2, 4, 6]); - deepEqual(_.filter(evenObject, isEven), [2], 'can filter objects'); - deepEqual(_.filter([{}, evenObject, []], 'two'), [evenObject], 'predicate string map to object properties'); + assert.deepEqual(_.filter(evenArray, isEven), [2, 4, 6]); + assert.deepEqual(_.filter(evenObject, isEven), [2], 'can filter objects'); + assert.deepEqual(_.filter([{}, evenObject, []], 'two'), [evenObject], 'predicate string map to object properties'); _.filter([1], function() { - equal(this, evenObject, 'given context'); + assert.equal(this, evenObject, 'given context'); }, evenObject); // Can be used like _.where. var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; - deepEqual(_.filter(list, {a: 1}), [{a: 1, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]); - deepEqual(_.filter(list, {b: 2}), [{a: 1, b: 2}, {a: 2, b: 2}]); - deepEqual(_.filter(list, {}), list, 'Empty object accepts all items'); - deepEqual(_(list).filter({}), list, 'OO-filter'); + assert.deepEqual(_.filter(list, {a: 1}), [{a: 1, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]); + assert.deepEqual(_.filter(list, {b: 2}), [{a: 1, b: 2}, {a: 2, b: 2}]); + assert.deepEqual(_.filter(list, {}), list, 'Empty object accepts all items'); + assert.deepEqual(_(list).filter({}), list, 'OO-filter'); }); - test('select', function() { - strictEqual(_.filter, _.select, 'alias for filter'); + test('select', function(assert) { + assert.strictEqual(_.select, _.filter, 'is an alias for filter'); }); - test('reject', function() { + test('reject', function(assert) { var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 === 0; }); - deepEqual(odds, [1, 3, 5], 'rejected each even number'); + assert.deepEqual(odds, [1, 3, 5], 'rejected each even number'); var context = 'obj'; var evens = _.reject([1, 2, 3, 4, 5, 6], function(num){ - equal(context, 'obj'); + assert.equal(context, 'obj'); return num % 2 !== 0; }, context); - deepEqual(evens, [2, 4, 6], 'rejected each odd number'); + assert.deepEqual(evens, [2, 4, 6], 'rejected each odd number'); - deepEqual(_.reject([odds, {one: 1, two: 2, three: 3}], 'two'), [odds], 'predicate string map to object properties'); + assert.deepEqual(_.reject([odds, {one: 1, two: 2, three: 3}], 'two'), [odds], 'predicate string map to object properties'); // Can be used like _.where. var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; - deepEqual(_.reject(list, {a: 1}), [{a: 2, b: 2}]); - deepEqual(_.reject(list, {b: 2}), [{a: 1, b: 3}, {a: 1, b: 4}]); - deepEqual(_.reject(list, {}), [], 'Returns empty list given empty object'); - deepEqual(_.reject(list, []), [], 'Returns empty list given empty array'); + assert.deepEqual(_.reject(list, {a: 1}), [{a: 2, b: 2}]); + assert.deepEqual(_.reject(list, {b: 2}), [{a: 1, b: 3}, {a: 1, b: 4}]); + assert.deepEqual(_.reject(list, {}), [], 'Returns empty list given empty object'); + assert.deepEqual(_.reject(list, []), [], 'Returns empty list given empty array'); }); - test('every', function() { - ok(_.every([], _.identity), 'the empty set'); - ok(_.every([true, true, true], _.identity), 'every true values'); - ok(!_.every([true, false, true], _.identity), 'one false value'); - ok(_.every([0, 10, 28], function(num){ return num % 2 === 0; }), 'even numbers'); - ok(!_.every([0, 11, 28], function(num){ return num % 2 === 0; }), 'an odd number'); - ok(_.every([1], _.identity) === true, 'cast to boolean - true'); - ok(_.every([0], _.identity) === false, 'cast to boolean - false'); - ok(!_.every([void 0, void 0, void 0], _.identity), 'works with arrays of undefined'); + test('every', function(assert) { + assert.ok(_.every([], _.identity), 'the empty set'); + assert.ok(_.every([true, true, true], _.identity), 'every true values'); + assert.ok(!_.every([true, false, true], _.identity), 'one false value'); + assert.ok(_.every([0, 10, 28], function(num){ return num % 2 === 0; }), 'even numbers'); + assert.ok(!_.every([0, 11, 28], function(num){ return num % 2 === 0; }), 'an odd number'); + assert.ok(_.every([1], _.identity) === true, 'cast to boolean - true'); + assert.ok(_.every([0], _.identity) === false, 'cast to boolean - false'); + assert.ok(!_.every([void 0, void 0, void 0], _.identity), 'works with arrays of undefined'); var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; - ok(!_.every(list, {a: 1, b: 2}), 'Can be called with object'); - ok(_.every(list, 'a'), 'String mapped to object property'); + assert.ok(!_.every(list, {a: 1, b: 2}), 'Can be called with object'); + assert.ok(_.every(list, 'a'), 'String mapped to object property'); list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}]; - ok(_.every(list, {b: 2}), 'Can be called with object'); - ok(!_.every(list, 'c'), 'String mapped to object property'); + assert.ok(_.every(list, {b: 2}), 'Can be called with object'); + assert.ok(!_.every(list, 'c'), 'String mapped to object property'); - ok(_.every({a: 1, b: 2, c: 3, d: 4}, _.isNumber), 'takes objects'); - ok(!_.every({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); - ok(_.every(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); - ok(!_.every(['a', 'b', 'c', 'd', 'f'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); + assert.ok(_.every({a: 1, b: 2, c: 3, d: 4}, _.isNumber), 'takes objects'); + assert.ok(!_.every({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); + assert.ok(_.every(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); + assert.ok(!_.every(['a', 'b', 'c', 'd', 'f'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); }); - test('all', function() { - strictEqual(_.all, _.every, 'alias for all'); + test('all', function(assert) { + assert.strictEqual(_.all, _.every, 'is an alias for every'); }); - test('some', function() { - ok(!_.some([]), 'the empty set'); - ok(!_.some([false, false, false]), 'all false values'); - ok(_.some([false, false, true]), 'one true value'); - ok(_.some([null, 0, 'yes', false]), 'a string'); - ok(!_.some([null, 0, '', false]), 'falsy values'); - ok(!_.some([1, 11, 29], function(num){ return num % 2 === 0; }), 'all odd numbers'); - ok(_.some([1, 10, 29], function(num){ return num % 2 === 0; }), 'an even number'); - ok(_.some([1], _.identity) === true, 'cast to boolean - true'); - ok(_.some([0], _.identity) === false, 'cast to boolean - false'); - ok(_.some([false, false, true])); + test('some', function(assert) { + assert.ok(!_.some([]), 'the empty set'); + assert.ok(!_.some([false, false, false]), 'all false values'); + assert.ok(_.some([false, false, true]), 'one true value'); + assert.ok(_.some([null, 0, 'yes', false]), 'a string'); + assert.ok(!_.some([null, 0, '', false]), 'falsy values'); + assert.ok(!_.some([1, 11, 29], function(num){ return num % 2 === 0; }), 'all odd numbers'); + assert.ok(_.some([1, 10, 29], function(num){ return num % 2 === 0; }), 'an even number'); + assert.ok(_.some([1], _.identity) === true, 'cast to boolean - true'); + assert.ok(_.some([0], _.identity) === false, 'cast to boolean - false'); + assert.ok(_.some([false, false, true])); var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; - ok(!_.some(list, {a: 5, b: 2}), 'Can be called with object'); - ok(_.some(list, 'a'), 'String mapped to object property'); + assert.ok(!_.some(list, {a: 5, b: 2}), 'Can be called with object'); + assert.ok(_.some(list, 'a'), 'String mapped to object property'); list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}]; - ok(_.some(list, {b: 2}), 'Can be called with object'); - ok(!_.some(list, 'd'), 'String mapped to object property'); + assert.ok(_.some(list, {b: 2}), 'Can be called with object'); + assert.ok(!_.some(list, 'd'), 'String mapped to object property'); - ok(_.some({a: '1', b: '2', c: '3', d: '4', e: 6}, _.isNumber), 'takes objects'); - ok(!_.some({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); - ok(_.some(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); - ok(!_.some(['x', 'y', 'z'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); + assert.ok(_.some({a: '1', b: '2', c: '3', d: '4', e: 6}, _.isNumber), 'takes objects'); + assert.ok(!_.some({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); + assert.ok(_.some(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); + assert.ok(!_.some(['x', 'y', 'z'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); }); - test('any', function() { - strictEqual(_.any, _.some, 'alias for any'); + test('any', function(assert) { + assert.strictEqual(_.any, _.some, 'is an alias for some'); }); - test('includes', function() { + test('includes', function(assert) { _.each([null, void 0, 0, 1, NaN, {}, []], function(val) { - strictEqual(_.includes(val, 'hasOwnProperty'), false); + assert.strictEqual(_.includes(val, 'hasOwnProperty'), false); }); - strictEqual(_.includes([1, 2, 3], 2), true, 'two is in the array'); - ok(!_.includes([1, 3, 9], 2), 'two is not in the array'); + assert.strictEqual(_.includes([1, 2, 3], 2), true, 'two is in the array'); + assert.ok(!_.includes([1, 3, 9], 2), 'two is not in the array'); - strictEqual(_.includes([5, 4, 3, 2, 1], 5, true), true, 'doesn\'t delegate to binary search'); + assert.strictEqual(_.includes([5, 4, 3, 2, 1], 5, true), true, 'doesn\'t delegate to binary search'); - ok(_.includes({moe: 1, larry: 3, curly: 9}, 3) === true, '_.includes on objects checks their values'); - ok(_([1, 2, 3]).includes(2), 'OO-style includes'); - }); - - test('include', function() { - strictEqual(_.includes, _.include, 'alias for includes'); - }); - - test('contains', function() { - strictEqual(_.includes, _.contains, 'alias for includes'); + assert.ok(_.includes({moe: 1, larry: 3, curly: 9}, 3) === true, '_.includes on objects checks their values'); + assert.ok(_([1, 2, 3]).includes(2), 'OO-style includes'); var numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; - strictEqual(_.includes(numbers, 1, 1), true, 'contains takes a fromIndex'); - strictEqual(_.includes(numbers, 1, -1), false, 'contains takes a fromIndex'); - strictEqual(_.includes(numbers, 1, -2), false, 'contains takes a fromIndex'); - strictEqual(_.includes(numbers, 1, -3), true, 'contains takes a fromIndex'); - strictEqual(_.includes(numbers, 1, 6), true, 'contains takes a fromIndex'); - strictEqual(_.includes(numbers, 1, 7), false, 'contains takes a fromIndex'); + assert.strictEqual(_.includes(numbers, 1, 1), true, 'takes a fromIndex'); + assert.strictEqual(_.includes(numbers, 1, -1), false, 'takes a fromIndex'); + assert.strictEqual(_.includes(numbers, 1, -2), false, 'takes a fromIndex'); + assert.strictEqual(_.includes(numbers, 1, -3), true, 'takes a fromIndex'); + assert.strictEqual(_.includes(numbers, 1, 6), true, 'takes a fromIndex'); + assert.strictEqual(_.includes(numbers, 1, 7), false, 'takes a fromIndex'); - ok(_.every([1, 2, 3], _.partial(_.contains, numbers)), 'fromIndex is guarded'); + assert.ok(_.every([1, 2, 3], _.partial(_.includes, numbers)), 'fromIndex is guarded'); }); - test('includes with NaN', function() { - strictEqual(_.includes([1, 2, NaN, NaN], NaN), true, 'Expected [1, 2, NaN] to contain NaN'); - strictEqual(_.includes([1, 2, Infinity], NaN), false, 'Expected [1, 2, NaN] to contain NaN'); + test('include', function(assert) { + assert.strictEqual(_.include, _.includes, 'is an alias for includes'); }); - test('includes with +- 0', function() { + test('contains', function(assert) { + assert.strictEqual(_.contains, _.includes, 'is an alias for includes'); + + }); + + test('includes with NaN', function(assert) { + assert.strictEqual(_.includes([1, 2, NaN, NaN], NaN), true, 'Expected [1, 2, NaN] to contain NaN'); + assert.strictEqual(_.includes([1, 2, Infinity], NaN), false, 'Expected [1, 2, NaN] to contain NaN'); + }); + + test('includes with +- 0', function(assert) { _.each([-0, +0], function(val) { - strictEqual(_.includes([1, 2, val, val], val), true); - strictEqual(_.includes([1, 2, val, val], -val), true); - strictEqual(_.includes([-1, 1, 2], -val), false); + assert.strictEqual(_.includes([1, 2, val, val], val), true); + assert.strictEqual(_.includes([1, 2, val, val], -val), true); + assert.strictEqual(_.includes([-1, 1, 2], -val), false); }); }); - test('invoke', 5, function() { + test('invoke', 5, function(assert) { var list = [[5, 1, 7], [3, 2, 1]]; var result = _.invoke(list, 'sort'); - deepEqual(result[0], [1, 5, 7], 'first array sorted'); - deepEqual(result[1], [1, 2, 3], 'second array sorted'); + assert.deepEqual(result[0], [1, 5, 7], 'first array sorted'); + assert.deepEqual(result[1], [1, 2, 3], 'second array sorted'); _.invoke([{ method: function() { - deepEqual(_.toArray(arguments), [1, 2, 3], 'called with arguments'); + assert.deepEqual(_.toArray(arguments), [1, 2, 3], 'called with arguments'); } }], 'method', 1, 2, 3); - deepEqual(_.invoke([{a: null}, {}, {a: _.constant(1)}], 'a'), [null, void 0, 1], 'handles null & undefined'); + assert.deepEqual(_.invoke([{a: null}, {}, {a: _.constant(1)}], 'a'), [null, void 0, 1], 'handles null & undefined'); - throws(function() { + assert.throws(function() { _.invoke([{a: 1}], 'a'); }, TypeError, 'throws for non-functions'); }); - test('invoke w/ function reference', function() { + test('invoke w/ function reference', function(assert) { var list = [[5, 1, 7], [3, 2, 1]]; var result = _.invoke(list, Array.prototype.sort); - deepEqual(result[0], [1, 5, 7], 'first array sorted'); - deepEqual(result[1], [1, 2, 3], 'second array sorted'); + assert.deepEqual(result[0], [1, 5, 7], 'first array sorted'); + assert.deepEqual(result[1], [1, 2, 3], 'second array sorted'); - deepEqual(_.invoke([1, 2, 3], function(a) { + assert.deepEqual(_.invoke([1, 2, 3], function(a) { return a + this; }, 5), [6, 7, 8], 'receives params from invoke'); }); // Relevant when using ClojureScript - test('invoke when strings have a call method', function() { + test('invoke when strings have a call method', function(assert) { String.prototype.call = function() { return 42; }; var list = [[5, 1, 7], [3, 2, 1]]; var s = 'foo'; - equal(s.call(), 42, 'call function exists'); + assert.equal(s.call(), 42, 'call function exists'); var result = _.invoke(list, 'sort'); - deepEqual(result[0], [1, 5, 7], 'first array sorted'); - deepEqual(result[1], [1, 2, 3], 'second array sorted'); + assert.deepEqual(result[0], [1, 5, 7], 'first array sorted'); + assert.deepEqual(result[1], [1, 2, 3], 'second array sorted'); delete String.prototype.call; - equal(s.call, void 0, 'call function removed'); + assert.equal(s.call, void 0, 'call function removed'); }); - test('pluck', function() { + test('pluck', function(assert) { var people = [{name: 'moe', age: 30}, {name: 'curly', age: 50}]; - deepEqual(_.pluck(people, 'name'), ['moe', 'curly'], 'pulls names out of objects'); - deepEqual(_.pluck(people, 'address'), [void 0, void 0], 'missing properties are returned as undefined'); + assert.deepEqual(_.pluck(people, 'name'), ['moe', 'curly'], 'pulls names out of objects'); + assert.deepEqual(_.pluck(people, 'address'), [void 0, void 0], 'missing properties are returned as undefined'); //compat: most flexible handling of edge cases - deepEqual(_.pluck([{'[object Object]': 1}], {}), [1]); + assert.deepEqual(_.pluck([{'[object Object]': 1}], {}), [1]); }); - test('where', function() { + test('where', function(assert) { var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; var result = _.where(list, {a: 1}); - equal(result.length, 3); - equal(result[result.length - 1].b, 4); + assert.equal(result.length, 3); + assert.equal(result[result.length - 1].b, 4); result = _.where(list, {b: 2}); - equal(result.length, 2); - equal(result[0].a, 1); + assert.equal(result.length, 2); + assert.equal(result[0].a, 1); result = _.where(list, {}); - equal(result.length, list.length); + assert.equal(result.length, list.length); function test() {} test.map = _.map; - deepEqual(_.where([_, {a: 1, b: 2}, _], test), [_, _], 'checks properties given function'); + assert.deepEqual(_.where([_, {a: 1, b: 2}, _], test), [_, _], 'checks properties given function'); }); - test('findWhere', function() { + test('findWhere', function(assert) { var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}]; var result = _.findWhere(list, {a: 1}); - deepEqual(result, {a: 1, b: 2}); + assert.deepEqual(result, {a: 1, b: 2}); result = _.findWhere(list, {b: 4}); - deepEqual(result, {a: 1, b: 4}); + assert.deepEqual(result, {a: 1, b: 4}); result = _.findWhere(list, {c: 1}); - ok(_.isUndefined(result), 'undefined when not found'); + assert.ok(_.isUndefined(result), 'undefined when not found'); result = _.findWhere([], {c: 1}); - ok(_.isUndefined(result), 'undefined when searching empty list'); + assert.ok(_.isUndefined(result), 'undefined when searching empty list'); function test() {} test.map = _.map; - equal(_.findWhere([_, {a: 1, b: 2}, _], test), _, 'checks properties given function'); + assert.equal(_.findWhere([_, {a: 1, b: 2}, _], test), _, 'checks properties given function'); function TestClass() { this.y = 5; this.x = 'foo'; } var expect = {c: 1, x: 'foo', y: 5}; - deepEqual(_.findWhere([{y: 5, b: 6}, expect], new TestClass()), expect, 'uses class instance properties'); + assert.deepEqual(_.findWhere([{y: 5, b: 6}, expect], new TestClass()), expect, 'uses class instance properties'); }); - test('max', function() { - equal(-Infinity, _.max(null), 'can handle null/undefined'); - equal(-Infinity, _.max(void 0), 'can handle null/undefined'); - equal(-Infinity, _.max(null, _.identity), 'can handle null/undefined'); + test('max', function(assert) { + assert.equal(-Infinity, _.max(null), 'can handle null/undefined'); + assert.equal(-Infinity, _.max(void 0), 'can handle null/undefined'); + assert.equal(-Infinity, _.max(null, _.identity), 'can handle null/undefined'); - equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); + assert.equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); var neg = _.max([1, 2, 3], function(num){ return -num; }); - equal(neg, 1, 'can perform a computation-based max'); + assert.equal(neg, 1, 'can perform a computation-based max'); - equal(-Infinity, _.max({}), 'Maximum value of an empty object'); - equal(-Infinity, _.max([]), 'Maximum value of an empty array'); - equal(_.max({a: 'a'}), -Infinity, 'Maximum value of a non-numeric collection'); + assert.equal(-Infinity, _.max({}), 'Maximum value of an empty object'); + assert.equal(-Infinity, _.max([]), 'Maximum value of an empty array'); + assert.equal(_.max({a: 'a'}), -Infinity, 'Maximum value of a non-numeric collection'); - equal(299999, _.max(_.range(1, 300000)), 'Maximum value of a too-big array'); + assert.equal(299999, _.max(_.range(1, 300000)), 'Maximum value of a too-big array'); - equal(3, _.max([1, 2, 3, 'test']), 'Finds correct max in array starting with num and containing a NaN'); - equal(3, _.max(['test', 1, 2, 3]), 'Finds correct max in array starting with NaN'); + assert.equal(3, _.max([1, 2, 3, 'test']), 'Finds correct max in array starting with num and containing a NaN'); + assert.equal(3, _.max(['test', 1, 2, 3]), 'Finds correct max in array starting with NaN'); - deepEqual([3, 6], _.map([[1, 2, 3], [4, 5, 6]], _.max), 'Finds correct max in array when mapping through multiple arrays'); + assert.equal(3, _.max([1, 2, 3, null]), 'Finds correct max in array starting with num and containing a `null`'); + assert.equal(3, _.max([null, 1, 2, 3]), 'Finds correct max in array starting with a `null`'); + + assert.equal(3, _.max([1, 2, 3, '']), 'Finds correct max in array starting with num and containing an empty string'); + assert.equal(3, _.max(['', 1, 2, 3]), 'Finds correct max in array starting with an empty string'); + + assert.equal(3, _.max([1, 2, 3, false]), 'Finds correct max in array starting with num and containing a false'); + assert.equal(3, _.max([false, 1, 2, 3]), 'Finds correct max in array starting with a false'); + + assert.equal(4, _.max([0, 1, 2, 3, 4]), 'Finds correct max in array containing a zero'); + assert.equal(0, _.max([-3, -2, -1, 0]), 'Finds correct max in array containing negative numbers'); + + assert.deepEqual([3, 6], _.map([[1, 2, 3], [4, 5, 6]], _.max), 'Finds correct max in array when mapping through multiple arrays'); var a = {x: -Infinity}; var b = {x: -Infinity}; var iterator = function(o){ return o.x; }; - equal(_.max([a, b], iterator), a, 'Respects iterator return value of -Infinity'); + assert.equal(_.max([a, b], iterator), a, 'Respects iterator return value of -Infinity'); - deepEqual(_.max([{a: 1}, {a: 0, b: 3}, {a: 4}, {a: 2}], 'a'), {a: 4}, 'String keys use property iterator'); + assert.deepEqual(_.max([{a: 1}, {a: 0, b: 3}, {a: 4}, {a: 2}], 'a'), {a: 4}, 'String keys use property iterator'); - deepEqual(_.max([0, 2], function(c){ return c * this.x; }, {x: 1}), 2, 'Iterator context'); - deepEqual(_.max([[1], [2, 3], [-1, 4], [5]], 0), [5], 'Lookup falsy iterator'); - deepEqual(_.max([{0: 1}, {0: 2}, {0: -1}, {a: 1}], 0), {0: 2}, 'Lookup falsy iterator'); + assert.deepEqual(_.max([0, 2], function(c){ return c * this.x; }, {x: 1}), 2, 'Iterator context'); + assert.deepEqual(_.max([[1], [2, 3], [-1, 4], [5]], 0), [5], 'Lookup falsy iterator'); + assert.deepEqual(_.max([{0: 1}, {0: 2}, {0: -1}, {a: 1}], 0), {0: 2}, 'Lookup falsy iterator'); }); - test('min', function() { - equal(Infinity, _.min(null), 'can handle null/undefined'); - equal(Infinity, _.min(void 0), 'can handle null/undefined'); - equal(Infinity, _.min(null, _.identity), 'can handle null/undefined'); + test('min', function(assert) { + assert.equal(Infinity, _.min(null), 'can handle null/undefined'); + assert.equal(Infinity, _.min(void 0), 'can handle null/undefined'); + assert.equal(Infinity, _.min(null, _.identity), 'can handle null/undefined'); - equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min'); + assert.equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min'); var neg = _.min([1, 2, 3], function(num){ return -num; }); - equal(neg, 3, 'can perform a computation-based min'); + assert.equal(neg, 3, 'can perform a computation-based min'); - equal(Infinity, _.min({}), 'Minimum value of an empty object'); - equal(Infinity, _.min([]), 'Minimum value of an empty array'); - equal(_.min({a: 'a'}), Infinity, 'Minimum value of a non-numeric collection'); + assert.equal(Infinity, _.min({}), 'Minimum value of an empty object'); + assert.equal(Infinity, _.min([]), 'Minimum value of an empty array'); + assert.equal(_.min({a: 'a'}), Infinity, 'Minimum value of a non-numeric collection'); - deepEqual([1, 4], _.map([[1, 2, 3], [4, 5, 6]], _.min), 'Finds correct min in array when mapping through multiple arrays'); + assert.deepEqual([1, 4], _.map([[1, 2, 3], [4, 5, 6]], _.min), 'Finds correct min in array when mapping through multiple arrays'); var now = new Date(9999999999); var then = new Date(0); - equal(_.min([now, then]), then); + assert.equal(_.min([now, then]), then); - equal(1, _.min(_.range(1, 300000)), 'Minimum value of a too-big array'); + assert.equal(1, _.min(_.range(1, 300000)), 'Minimum value of a too-big array'); - equal(1, _.min([1, 2, 3, 'test']), 'Finds correct min in array starting with num and containing a NaN'); - equal(1, _.min(['test', 1, 2, 3]), 'Finds correct min in array starting with NaN'); + assert.equal(1, _.min([1, 2, 3, 'test']), 'Finds correct min in array starting with num and containing a NaN'); + assert.equal(1, _.min(['test', 1, 2, 3]), 'Finds correct min in array starting with NaN'); + + assert.equal(1, _.min([1, 2, 3, null]), 'Finds correct min in array starting with num and containing a `null`'); + assert.equal(1, _.min([null, 1, 2, 3]), 'Finds correct min in array starting with a `null`'); + + assert.equal(0, _.min([0, 1, 2, 3, 4]), 'Finds correct min in array containing a zero'); + assert.equal(-3, _.min([-3, -2, -1, 0]), 'Finds correct min in array containing negative numbers'); var a = {x: Infinity}; var b = {x: Infinity}; var iterator = function(o){ return o.x; }; - equal(_.min([a, b], iterator), a, 'Respects iterator return value of Infinity'); + assert.equal(_.min([a, b], iterator), a, 'Respects iterator return value of Infinity'); - deepEqual(_.min([{a: 1}, {a: 0, b: 3}, {a: 4}, {a: 2}], 'a'), {a: 0, b: 3}, 'String keys use property iterator'); + assert.deepEqual(_.min([{a: 1}, {a: 0, b: 3}, {a: 4}, {a: 2}], 'a'), {a: 0, b: 3}, 'String keys use property iterator'); - deepEqual(_.min([0, 2], function(c){ return c * this.x; }, {x: -1}), 2, 'Iterator context'); - deepEqual(_.min([[1], [2, 3], [-1, 4], [5]], 0), [-1, 4], 'Lookup falsy iterator'); - deepEqual(_.min([{0: 1}, {0: 2}, {0: -1}, {a: 1}], 0), {0: -1}, 'Lookup falsy iterator'); + assert.deepEqual(_.min([0, 2], function(c){ return c * this.x; }, {x: -1}), 2, 'Iterator context'); + assert.deepEqual(_.min([[1], [2, 3], [-1, 4], [5]], 0), [-1, 4], 'Lookup falsy iterator'); + assert.deepEqual(_.min([{0: 1}, {0: 2}, {0: -1}, {a: 1}], 0), {0: -1}, 'Lookup falsy iterator'); }); - test('sortBy', function() { + test('sortBy', function(assert) { var people = [{name: 'curly', age: 50}, {name: 'moe', age: 30}]; people = _.sortBy(people, function(person){ return person.age; }); - deepEqual(_.pluck(people, 'name'), ['moe', 'curly'], 'stooges sorted by age'); + assert.deepEqual(_.pluck(people, 'name'), ['moe', 'curly'], 'stooges sorted by age'); var list = [void 0, 4, 1, void 0, 3, 2]; - deepEqual(_.sortBy(list, _.identity), [1, 2, 3, 4, void 0, void 0], 'sortBy with undefined values'); + assert.deepEqual(_.sortBy(list, _.identity), [1, 2, 3, 4, void 0, void 0], 'sortBy with undefined values'); list = ['one', 'two', 'three', 'four', 'five']; var sorted = _.sortBy(list, 'length'); - deepEqual(sorted, ['one', 'two', 'four', 'five', 'three'], 'sorted by length'); + assert.deepEqual(sorted, ['one', 'two', 'four', 'five', 'three'], 'sorted by length'); function Pair(x, y) { this.x = x; @@ -650,144 +670,150 @@ return pair.x; }); - deepEqual(actual, stableArray, 'sortBy should be stable for arrays'); - deepEqual(_.sortBy(stableArray, 'x'), stableArray, 'sortBy accepts property string'); + assert.deepEqual(actual, stableArray, 'sortBy should be stable for arrays'); + assert.deepEqual(_.sortBy(stableArray, 'x'), stableArray, 'sortBy accepts property string'); actual = _.sortBy(stableObject, function(pair) { return pair.x; }); - deepEqual(actual, stableArray, 'sortBy should be stable for objects'); + assert.deepEqual(actual, stableArray, 'sortBy should be stable for objects'); list = ['q', 'w', 'e', 'r', 't', 'y']; - deepEqual(_.sortBy(list), ['e', 'q', 'r', 't', 'w', 'y'], 'uses _.identity if iterator is not specified'); + assert.deepEqual(_.sortBy(list), ['e', 'q', 'r', 't', 'w', 'y'], 'uses _.identity if iterator is not specified'); }); - test('groupBy', function() { + test('groupBy', function(assert) { var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; }); - ok('0' in parity && '1' in parity, 'created a group for each value'); - deepEqual(parity[0], [2, 4, 6], 'put each even number in the right group'); + assert.ok('0' in parity && '1' in parity, 'created a group for each value'); + assert.deepEqual(parity[0], [2, 4, 6], 'put each even number in the right group'); var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; var grouped = _.groupBy(list, 'length'); - deepEqual(grouped['3'], ['one', 'two', 'six', 'ten']); - deepEqual(grouped['4'], ['four', 'five', 'nine']); - deepEqual(grouped['5'], ['three', 'seven', 'eight']); + assert.deepEqual(grouped['3'], ['one', 'two', 'six', 'ten']); + assert.deepEqual(grouped['4'], ['four', 'five', 'nine']); + assert.deepEqual(grouped['5'], ['three', 'seven', 'eight']); var context = {}; - _.groupBy([{}], function(){ ok(this === context); }, context); + _.groupBy([{}], function(){ assert.ok(this === context); }, context); grouped = _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; }); - equal(grouped.constructor.length, 1); - equal(grouped.hasOwnProperty.length, 2); + assert.equal(grouped.constructor.length, 1); + assert.equal(grouped.hasOwnProperty.length, 2); var array = [{}]; - _.groupBy(array, function(value, index, obj){ ok(obj === array); }); + _.groupBy(array, function(value, index, obj){ assert.ok(obj === array); }); array = [1, 2, 1, 2, 3]; grouped = _.groupBy(array); - equal(grouped['1'].length, 2); - equal(grouped['3'].length, 1); + assert.equal(grouped['1'].length, 2); + assert.equal(grouped['3'].length, 1); var matrix = [ [1, 2], [1, 3], [2, 3] ]; - deepEqual(_.groupBy(matrix, 0), {1: [[1, 2], [1, 3]], 2: [[2, 3]]}); - deepEqual(_.groupBy(matrix, 1), {2: [[1, 2]], 3: [[1, 3], [2, 3]]}); + assert.deepEqual(_.groupBy(matrix, 0), {1: [[1, 2], [1, 3]], 2: [[2, 3]]}); + assert.deepEqual(_.groupBy(matrix, 1), {2: [[1, 2]], 3: [[1, 3], [2, 3]]}); }); - test('indexBy', function() { + test('indexBy', function(assert) { var parity = _.indexBy([1, 2, 3, 4, 5], function(num){ return num % 2 === 0; }); - equal(parity['true'], 4); - equal(parity['false'], 5); + assert.equal(parity['true'], 4); + assert.equal(parity['false'], 5); var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; var grouped = _.indexBy(list, 'length'); - equal(grouped['3'], 'ten'); - equal(grouped['4'], 'nine'); - equal(grouped['5'], 'eight'); + assert.equal(grouped['3'], 'ten'); + assert.equal(grouped['4'], 'nine'); + assert.equal(grouped['5'], 'eight'); var array = [1, 2, 1, 2, 3]; grouped = _.indexBy(array); - equal(grouped['1'], 1); - equal(grouped['2'], 2); - equal(grouped['3'], 3); + assert.equal(grouped['1'], 1); + assert.equal(grouped['2'], 2); + assert.equal(grouped['3'], 3); }); - test('countBy', function() { + test('countBy', function(assert) { var parity = _.countBy([1, 2, 3, 4, 5], function(num){ return num % 2 === 0; }); - equal(parity['true'], 2); - equal(parity['false'], 3); + assert.equal(parity['true'], 2); + assert.equal(parity['false'], 3); var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; var grouped = _.countBy(list, 'length'); - equal(grouped['3'], 4); - equal(grouped['4'], 3); - equal(grouped['5'], 3); + assert.equal(grouped['3'], 4); + assert.equal(grouped['4'], 3); + assert.equal(grouped['5'], 3); var context = {}; - _.countBy([{}], function(){ ok(this === context); }, context); + _.countBy([{}], function(){ assert.ok(this === context); }, context); grouped = _.countBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; }); - equal(grouped.constructor, 1); - equal(grouped.hasOwnProperty, 2); + assert.equal(grouped.constructor, 1); + assert.equal(grouped.hasOwnProperty, 2); var array = [{}]; - _.countBy(array, function(value, index, obj){ ok(obj === array); }); + _.countBy(array, function(value, index, obj){ assert.ok(obj === array); }); array = [1, 2, 1, 2, 3]; grouped = _.countBy(array); - equal(grouped['1'], 2); - equal(grouped['3'], 1); + assert.equal(grouped['1'], 2); + assert.equal(grouped['3'], 1); }); - test('shuffle', function() { - deepEqual(_.shuffle([1]), [1], 'behaves correctly on size 1 arrays'); + test('shuffle', function(assert) { + assert.deepEqual(_.shuffle([1]), [1], 'behaves correctly on size 1 arrays'); var numbers = _.range(20); var shuffled = _.shuffle(numbers); - notDeepEqual(numbers, shuffled, 'does change the order'); // Chance of false negative: 1 in ~2.4*10^18 - notStrictEqual(numbers, shuffled, 'original object is unmodified'); - deepEqual(numbers, _.sortBy(shuffled), 'contains the same members before and after shuffle'); + assert.notDeepEqual(numbers, shuffled, 'does change the order'); // Chance of false negative: 1 in ~2.4*10^18 + assert.notStrictEqual(numbers, shuffled, 'original object is unmodified'); + assert.deepEqual(numbers, _.sortBy(shuffled), 'contains the same members before and after shuffle'); shuffled = _.shuffle({a: 1, b: 2, c: 3, d: 4}); - equal(shuffled.length, 4); - deepEqual(shuffled.sort(), [1, 2, 3, 4], 'works on objects'); + assert.equal(shuffled.length, 4); + assert.deepEqual(shuffled.sort(), [1, 2, 3, 4], 'works on objects'); }); - test('sample', function() { - strictEqual(_.sample([1]), 1, 'behaves correctly when no second parameter is given'); - deepEqual(_.sample([1, 2, 3], -2), [], 'behaves correctly on negative n'); + test('sample', function(assert) { + assert.strictEqual(_.sample([1]), 1, 'behaves correctly when no second parameter is given'); + assert.deepEqual(_.sample([1, 2, 3], -2), [], 'behaves correctly on negative n'); var numbers = _.range(10); var allSampled = _.sample(numbers, 10).sort(); - deepEqual(allSampled, numbers, 'contains the same members before and after sample'); + assert.deepEqual(allSampled, numbers, 'contains the same members before and after sample'); allSampled = _.sample(numbers, 20).sort(); - deepEqual(allSampled, numbers, 'also works when sampling more objects than are present'); - ok(_.contains(numbers, _.sample(numbers)), 'sampling a single element returns something from the array'); - strictEqual(_.sample([]), void 0, 'sampling empty array with no number returns undefined'); - notStrictEqual(_.sample([], 5), [], 'sampling empty array with a number returns an empty array'); - notStrictEqual(_.sample([1, 2, 3], 0), [], 'sampling an array with 0 picks returns an empty array'); - deepEqual(_.sample([1, 2], -1), [], 'sampling a negative number of picks returns an empty array'); - ok(_.contains([1, 2, 3], _.sample({a: 1, b: 2, c: 3})), 'sample one value from an object'); + assert.deepEqual(allSampled, numbers, 'also works when sampling more objects than are present'); + assert.ok(_.contains(numbers, _.sample(numbers)), 'sampling a single element returns something from the array'); + assert.strictEqual(_.sample([]), void 0, 'sampling empty array with no number returns undefined'); + assert.notStrictEqual(_.sample([], 5), [], 'sampling empty array with a number returns an empty array'); + assert.notStrictEqual(_.sample([1, 2, 3], 0), [], 'sampling an array with 0 picks returns an empty array'); + assert.deepEqual(_.sample([1, 2], -1), [], 'sampling a negative number of picks returns an empty array'); + assert.ok(_.contains([1, 2, 3], _.sample({a: 1, b: 2, c: 3})), 'sample one value from an object'); var partialSample = _.sample(_.range(1000), 10); var partialSampleSorted = partialSample.sort(); - notDeepEqual(partialSampleSorted, _.range(10), 'samples from the whole array, not just the beginning'); + assert.notDeepEqual(partialSampleSorted, _.range(10), 'samples from the whole array, not just the beginning'); }); - test('toArray', function() { - ok(!_.isArray(arguments), 'arguments object is not an array'); - ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); + test('toArray', function(assert) { + assert.ok(!_.isArray(arguments), 'arguments object is not an array'); + assert.ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); var a = [1, 2, 3]; - ok(_.toArray(a) !== a, 'array is cloned'); - deepEqual(_.toArray(a), [1, 2, 3], 'cloned array contains same elements'); + assert.ok(_.toArray(a) !== a, 'array is cloned'); + assert.deepEqual(_.toArray(a), [1, 2, 3], 'cloned array contains same elements'); var numbers = _.toArray({one: 1, two: 2, three: 3}); - deepEqual(numbers, [1, 2, 3], 'object flattened into array'); + assert.deepEqual(numbers, [1, 2, 3], 'object flattened into array'); + + var hearts = '\uD83D\uDC95'; + var pair = hearts.split(''); + var expected = [pair[0], hearts, '&', hearts, pair[1]]; + assert.deepEqual(_.toArray(expected.join('')), expected, 'maintains astral characters'); + assert.deepEqual(_.toArray(''), [], 'empty string into empty array'); if (typeof document != 'undefined') { // test in IE < 9 @@ -795,78 +821,78 @@ try { actual = _.toArray(document.childNodes); } catch(e) { /* ignored */ } - deepEqual(actual, _.map(document.childNodes, _.identity), 'works on NodeList'); + assert.deepEqual(actual, _.map(document.childNodes, _.identity), 'works on NodeList'); } }); - test('size', function() { - equal(_.size({one: 1, two: 2, three: 3}), 3, 'can compute the size of an object'); - equal(_.size([1, 2, 3]), 3, 'can compute the size of an array'); - equal(_.size({length: 3, 0: 0, 1: 0, 2: 0}), 3, 'can compute the size of Array-likes'); + test('size', function(assert) { + assert.equal(_.size({one: 1, two: 2, three: 3}), 3, 'can compute the size of an object'); + assert.equal(_.size([1, 2, 3]), 3, 'can compute the size of an array'); + assert.equal(_.size({length: 3, 0: 0, 1: 0, 2: 0}), 3, 'can compute the size of Array-likes'); var func = function() { return _.size(arguments); }; - equal(func(1, 2, 3, 4), 4, 'can test the size of the arguments object'); + assert.equal(func(1, 2, 3, 4), 4, 'can test the size of the arguments object'); - equal(_.size('hello'), 5, 'can compute the size of a string literal'); - equal(_.size(new String('hello')), 5, 'can compute the size of string object'); + assert.equal(_.size('hello'), 5, 'can compute the size of a string literal'); + assert.equal(_.size(new String('hello')), 5, 'can compute the size of string object'); - equal(_.size(null), 0, 'handles nulls'); - equal(_.size(0), 0, 'handles numbers'); + assert.equal(_.size(null), 0, 'handles nulls'); + assert.equal(_.size(0), 0, 'handles numbers'); }); - test('partition', function() { + test('partition', function(assert) { var list = [0, 1, 2, 3, 4, 5]; - deepEqual(_.partition(list, function(x) { return x < 4; }), [[0, 1, 2, 3], [4, 5]], 'handles bool return values'); - deepEqual(_.partition(list, function(x) { return x & 1; }), [[1, 3, 5], [0, 2, 4]], 'handles 0 and 1 return values'); - deepEqual(_.partition(list, function(x) { return x - 3; }), [[0, 1, 2, 4, 5], [3]], 'handles other numeric return values'); - deepEqual(_.partition(list, function(x) { return x > 1 ? null : true; }), [[0, 1], [2, 3, 4, 5]], 'handles null return values'); - deepEqual(_.partition(list, function(x) { if (x < 2) return true; }), [[0, 1], [2, 3, 4, 5]], 'handles undefined return values'); - deepEqual(_.partition({a: 1, b: 2, c: 3}, function(x) { return x > 1; }), [[2, 3], [1]], 'handles objects'); + assert.deepEqual(_.partition(list, function(x) { return x < 4; }), [[0, 1, 2, 3], [4, 5]], 'handles bool return values'); + assert.deepEqual(_.partition(list, function(x) { return x & 1; }), [[1, 3, 5], [0, 2, 4]], 'handles 0 and 1 return values'); + assert.deepEqual(_.partition(list, function(x) { return x - 3; }), [[0, 1, 2, 4, 5], [3]], 'handles other numeric return values'); + assert.deepEqual(_.partition(list, function(x) { return x > 1 ? null : true; }), [[0, 1], [2, 3, 4, 5]], 'handles null return values'); + assert.deepEqual(_.partition(list, function(x) { if (x < 2) return true; }), [[0, 1], [2, 3, 4, 5]], 'handles undefined return values'); + assert.deepEqual(_.partition({a: 1, b: 2, c: 3}, function(x) { return x > 1; }), [[2, 3], [1]], 'handles objects'); - deepEqual(_.partition(list, function(x, index) { return index % 2; }), [[1, 3, 5], [0, 2, 4]], 'can reference the array index'); - deepEqual(_.partition(list, function(x, index, arr) { return x === arr.length - 1; }), [[5], [0, 1, 2, 3, 4]], 'can reference the collection'); + assert.deepEqual(_.partition(list, function(x, index) { return index % 2; }), [[1, 3, 5], [0, 2, 4]], 'can reference the array index'); + assert.deepEqual(_.partition(list, function(x, index, arr) { return x === arr.length - 1; }), [[5], [0, 1, 2, 3, 4]], 'can reference the collection'); // Default iterator - deepEqual(_.partition([1, false, true, '']), [[1, true], [false, '']], 'Default iterator'); - deepEqual(_.partition([{x: 1}, {x: 0}, {x: 1}], 'x'), [[{x: 1}, {x: 1}], [{x: 0}]], 'Takes a string'); + assert.deepEqual(_.partition([1, false, true, '']), [[1, true], [false, '']], 'Default iterator'); + assert.deepEqual(_.partition([{x: 1}, {x: 0}, {x: 1}], 'x'), [[{x: 1}, {x: 1}], [{x: 0}]], 'Takes a string'); // Context var predicate = function(x){ return x === this.x; }; - deepEqual(_.partition([1, 2, 3], predicate, {x: 2}), [[2], [1, 3]], 'partition takes a context argument'); + assert.deepEqual(_.partition([1, 2, 3], predicate, {x: 2}), [[2], [1, 3]], 'partition takes a context argument'); - deepEqual(_.partition([{a: 1}, {b: 2}, {a: 1, b: 2}], {a: 1}), [[{a: 1}, {a: 1, b: 2}], [{b: 2}]], 'predicate can be object'); + assert.deepEqual(_.partition([{a: 1}, {b: 2}, {a: 1, b: 2}], {a: 1}), [[{a: 1}, {a: 1, b: 2}], [{b: 2}]], 'predicate can be object'); var object = {a: 1}; _.partition(object, function(val, key, obj) { - equal(val, 1); - equal(key, 'a'); - equal(obj, object); - equal(this, predicate); + assert.equal(val, 1); + assert.equal(key, 'a'); + assert.equal(obj, object); + assert.equal(this, predicate); }, predicate); }); if (typeof document != 'undefined') { - test('Can use various collection methods on NodeLists', function() { + test('Can use various collection methods on NodeLists', function(assert) { var parent = document.createElement('div'); parent.innerHTML = 'textnode'; var elementChildren = _.filter(parent.childNodes, _.isElement); - equal(elementChildren.length, 2); + assert.equal(elementChildren.length, 2); - deepEqual(_.map(elementChildren, 'id'), ['id1', 'id2']); - deepEqual(_.map(parent.childNodes, 'nodeType'), [1, 3, 1]); + assert.deepEqual(_.map(elementChildren, 'id'), ['id1', 'id2']); + assert.deepEqual(_.map(parent.childNodes, 'nodeType'), [1, 3, 1]); - ok(!_.every(parent.childNodes, _.isElement)); - ok(_.some(parent.childNodes, _.isElement)); + assert.ok(!_.every(parent.childNodes, _.isElement)); + assert.ok(_.some(parent.childNodes, _.isElement)); function compareNode(node) { return _.isElement(node) ? node.id.charAt(2) : void 0; } - equal(_.max(parent.childNodes, compareNode), _.last(parent.childNodes)); - equal(_.min(parent.childNodes, compareNode), _.first(parent.childNodes)); + assert.equal(_.max(parent.childNodes, compareNode), _.last(parent.childNodes)); + assert.equal(_.min(parent.childNodes, compareNode), _.first(parent.childNodes)); }); } diff --git a/vendor/underscore/test/cross-document.js b/vendor/underscore/test/cross-document.js index 215d78e85..fff3a07d4 100644 --- a/vendor/underscore/test/cross-document.js +++ b/vendor/underscore/test/cross-document.js @@ -33,95 +33,95 @@ ); iDoc.close(); - test('isEqual', function() { + test('isEqual', function(assert) { - ok(!_.isEqual(iNumber, 101)); - ok(_.isEqual(iNumber, 100)); + assert.ok(!_.isEqual(iNumber, 101)); + assert.ok(_.isEqual(iNumber, 100)); // Objects from another frame. - ok(_.isEqual({}, iObject), 'Objects with equivalent members created in different documents are equal'); + assert.ok(_.isEqual({}, iObject), 'Objects with equivalent members created in different documents are equal'); // Array from another frame. - ok(_.isEqual([1, 2, 3], iArray), 'Arrays with equivalent elements created in different documents are equal'); + assert.ok(_.isEqual([1, 2, 3], iArray), 'Arrays with equivalent elements created in different documents are equal'); }); - test('isEmpty', function() { - ok(!_([iNumber]).isEmpty(), '[1] is not empty'); - ok(!_.isEmpty(iArray), '[] is empty'); - ok(_.isEmpty(iObject), '{} is empty'); + test('isEmpty', function(assert) { + assert.ok(!_([iNumber]).isEmpty(), '[1] is not empty'); + assert.ok(!_.isEmpty(iArray), '[] is empty'); + assert.ok(_.isEmpty(iObject), '{} is empty'); }); - test('isElement', function() { - ok(!_.isElement('div'), 'strings are not dom elements'); - ok(_.isElement(document.body), 'the body tag is a DOM element'); - ok(_.isElement(iElement), 'even from another frame'); + test('isElement', function(assert) { + assert.ok(!_.isElement('div'), 'strings are not dom elements'); + assert.ok(_.isElement(document.body), 'the body tag is a DOM element'); + assert.ok(_.isElement(iElement), 'even from another frame'); }); - test('isArguments', function() { - ok(_.isArguments(iArguments), 'even from another frame'); + test('isArguments', function(assert) { + assert.ok(_.isArguments(iArguments), 'even from another frame'); }); - test('isObject', function() { - ok(_.isObject(iElement), 'even from another frame'); - ok(_.isObject(iFunction), 'even from another frame'); + test('isObject', function(assert) { + assert.ok(_.isObject(iElement), 'even from another frame'); + assert.ok(_.isObject(iFunction), 'even from another frame'); }); - test('isArray', function() { - ok(_.isArray(iArray), 'even from another frame'); + test('isArray', function(assert) { + assert.ok(_.isArray(iArray), 'even from another frame'); }); - test('isString', function() { - ok(_.isString(iString), 'even from another frame'); + test('isString', function(assert) { + assert.ok(_.isString(iString), 'even from another frame'); }); - test('isNumber', function() { - ok(_.isNumber(iNumber), 'even from another frame'); + test('isNumber', function(assert) { + assert.ok(_.isNumber(iNumber), 'even from another frame'); }); - test('isBoolean', function() { - ok(_.isBoolean(iBoolean), 'even from another frame'); + test('isBoolean', function(assert) { + assert.ok(_.isBoolean(iBoolean), 'even from another frame'); }); - test('isFunction', function() { - ok(_.isFunction(iFunction), 'even from another frame'); + test('isFunction', function(assert) { + assert.ok(_.isFunction(iFunction), 'even from another frame'); }); - test('isDate', function() { - ok(_.isDate(iDate), 'even from another frame'); + test('isDate', function(assert) { + assert.ok(_.isDate(iDate), 'even from another frame'); }); - test('isRegExp', function() { - ok(_.isRegExp(iRegExp), 'even from another frame'); + test('isRegExp', function(assert) { + assert.ok(_.isRegExp(iRegExp), 'even from another frame'); }); - test('isNaN', function() { - ok(_.isNaN(iNaN), 'even from another frame'); + test('isNaN', function(assert) { + assert.ok(_.isNaN(iNaN), 'even from another frame'); }); - test('isNull', function() { - ok(_.isNull(iNull), 'even from another frame'); + test('isNull', function(assert) { + assert.ok(_.isNull(iNull), 'even from another frame'); }); - test('isUndefined', function() { - ok(_.isUndefined(iUndefined), 'even from another frame'); + test('isUndefined', function(assert) { + assert.ok(_.isUndefined(iUndefined), 'even from another frame'); }); - test('isError', function() { - ok(_.isError(iError), 'even from another frame'); + test('isError', function(assert) { + assert.ok(_.isError(iError), 'even from another frame'); }); if (typeof ActiveXObject != 'undefined') { - test('IE host objects', function() { + test('IE host objects', function(assert) { var xml = new ActiveXObject('Msxml2.DOMDocument.3.0'); - ok(!_.isNumber(xml)); - ok(!_.isBoolean(xml)); - ok(!_.isNaN(xml)); - ok(!_.isFunction(xml)); - ok(!_.isNull(xml)); - ok(!_.isUndefined(xml)); + assert.ok(!_.isNumber(xml)); + assert.ok(!_.isBoolean(xml)); + assert.ok(!_.isNaN(xml)); + assert.ok(!_.isFunction(xml)); + assert.ok(!_.isNull(xml)); + assert.ok(!_.isUndefined(xml)); }); - test('#1621 IE 11 compat mode DOM elements are not functions', function() { + test('#1621 IE 11 compat mode DOM elements are not functions', function(assert) { var fn = function() {}; var xml = new ActiveXObject('Msxml2.DOMDocument.3.0'); var div = document.createElement('div'); @@ -132,9 +132,9 @@ _.isFunction(fn); } - equal(_.isFunction(xml), false); - equal(_.isFunction(div), false); - equal(_.isFunction(fn), true); + assert.equal(_.isFunction(xml), false); + assert.equal(_.isFunction(div), false); + assert.equal(_.isFunction(fn), true); }); } diff --git a/vendor/underscore/test/functions.js b/vendor/underscore/test/functions.js index 7ceb49dfe..09512feb7 100644 --- a/vendor/underscore/test/functions.js +++ b/vendor/underscore/test/functions.js @@ -4,32 +4,32 @@ QUnit.module('Functions'); QUnit.config.asyncRetries = 3; - test('bind', function() { + test('bind', function(assert) { var context = {name: 'moe'}; var func = function(arg) { return 'name: ' + (this.name || arg); }; var bound = _.bind(func, context); - equal(bound(), 'name: moe', 'can bind a function to a context'); + assert.equal(bound(), 'name: moe', 'can bind a function to a context'); bound = _(func).bind(context); - equal(bound(), 'name: moe', 'can do OO-style binding'); + assert.equal(bound(), 'name: moe', 'can do OO-style binding'); bound = _.bind(func, null, 'curly'); var result = bound(); // Work around a PhantomJS bug when applying a function with null|undefined. - ok(result === 'name: curly' || result === 'name: ' + window.name, 'can bind without specifying a context'); + assert.ok(result === 'name: curly' || result === 'name: ' + window.name, 'can bind without specifying a context'); func = function(salutation, name) { return salutation + ': ' + name; }; func = _.bind(func, this, 'hello'); - equal(func('moe'), 'hello: moe', 'the function was partially applied in advance'); + assert.equal(func('moe'), 'hello: moe', 'the function was partially applied in advance'); func = _.bind(func, this, 'curly'); - equal(func(), 'hello: curly', 'the function was completely applied in advance'); + assert.equal(func(), 'hello: curly', 'the function was completely applied in advance'); func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; }; func = _.bind(func, this, 'hello', 'moe', 'curly'); - equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments'); + assert.equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments'); - func = function(ctx, message) { equal(this, ctx, message); }; + func = function(ctx, message) { assert.equal(this, ctx, message); }; _.bind(func, 0, 0, 'can bind a function to `0`')(); _.bind(func, '', '', 'can bind a function to an empty string')(); _.bind(func, false, false, 'can bind a function to `false`')(); @@ -40,29 +40,29 @@ var boundf = _.bind(F, {hello: 'moe curly'}); var Boundf = boundf; // make eslint happy. var newBoundf = new Boundf(); - equal(newBoundf.hello, void 0, 'function should not be bound to the context, to comply with ECMAScript 5'); - equal(boundf().hello, 'moe curly', "When called without the new operator, it's OK to be bound to the context"); - ok(newBoundf instanceof F, 'a bound instance is an instance of the original function'); + assert.equal(newBoundf.hello, void 0, 'function should not be bound to the context, to comply with ECMAScript 5'); + assert.equal(boundf().hello, 'moe curly', "When called without the new operator, it's OK to be bound to the context"); + assert.ok(newBoundf instanceof F, 'a bound instance is an instance of the original function'); - throws(function() { _.bind('notafunction'); }, TypeError, 'throws an error when binding to a non-function'); + assert.throws(function() { _.bind('notafunction'); }, TypeError, 'throws an error when binding to a non-function'); }); - test('partial', function() { + test('partial', function(assert) { var obj = {name: 'moe'}; var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); }; obj.func = _.partial(func, 'a', 'b'); - equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply'); + assert.equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply'); obj.func = _.partial(func, _, 'b', _, 'd'); - equal(obj.func('a', 'c'), 'moe a b c d', 'can partially apply with placeholders'); + assert.equal(obj.func('a', 'c'), 'moe a b c d', 'can partially apply with placeholders'); func = _.partial(function() { return arguments.length; }, _, 'b', _, 'd'); - equal(func('a', 'c', 'e'), 5, 'accepts more arguments than the number of placeholders'); - equal(func('a'), 4, 'accepts fewer arguments than the number of placeholders'); + assert.equal(func('a', 'c', 'e'), 5, 'accepts more arguments than the number of placeholders'); + assert.equal(func('a'), 4, 'accepts fewer arguments than the number of placeholders'); func = _.partial(function() { return typeof arguments[2]; }, _, 'b', _, 'd'); - equal(func('a'), 'undefined', 'unfilled placeholders are undefined'); + assert.equal(func('a'), 'undefined', 'unfilled placeholders are undefined'); // passes context function MyWidget(name, options) { @@ -74,22 +74,22 @@ }; var MyWidgetWithCoolOpts = _.partial(MyWidget, _, {a: 1}); var widget = new MyWidgetWithCoolOpts('foo'); - ok(widget instanceof MyWidget, 'Can partially bind a constructor'); - equal(widget.get(), 'foo', 'keeps prototype'); - deepEqual(widget.options, {a: 1}); + assert.ok(widget instanceof MyWidget, 'Can partially bind a constructor'); + assert.equal(widget.get(), 'foo', 'keeps prototype'); + assert.deepEqual(widget.options, {a: 1}); _.partial.placeholder = obj; func = _.partial(function() { return arguments.length; }, obj, 'b', obj, 'd'); - equal(func('a'), 4, 'allows the placeholder to be swapped out'); + assert.equal(func('a'), 4, 'allows the placeholder to be swapped out'); _.partial.placeholder = {}; func = _.partial(function() { return arguments.length; }, obj, 'b', obj, 'd'); - equal(func('a'), 5, 'swapping the placeholder preserves previously bound arguments'); + assert.equal(func('a'), 5, 'swapping the placeholder preserves previously bound arguments'); _.partial.placeholder = _; }); - test('bindAll', function() { + test('bindAll', function(assert) { var curly = {name: 'curly'}, moe = { name: 'moe', getName: function() { return 'name: ' + this.name; }, @@ -98,8 +98,8 @@ curly.getName = moe.getName; _.bindAll(moe, 'getName', 'sayHi'); curly.sayHi = moe.sayHi; - equal(curly.getName(), 'name: curly', 'unbound function is bound to current object'); - equal(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object'); + assert.equal(curly.getName(), 'name: curly', 'unbound function is bound to current object'); + assert.equal(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object'); curly = {name: 'curly'}; moe = { @@ -109,57 +109,57 @@ sayLast: function() { return this.sayHi(_.last(arguments)); } }; - throws(function() { _.bindAll(moe); }, Error, 'throws an error for bindAll with no functions named'); - throws(function() { _.bindAll(moe, 'sayBye'); }, TypeError, 'throws an error for bindAll if the given key is undefined'); - throws(function() { _.bindAll(moe, 'name'); }, TypeError, 'throws an error for bindAll if the given key is not a function'); + assert.throws(function() { _.bindAll(moe); }, Error, 'throws an error for bindAll with no functions named'); + assert.throws(function() { _.bindAll(moe, 'sayBye'); }, TypeError, 'throws an error for bindAll if the given key is undefined'); + assert.throws(function() { _.bindAll(moe, 'name'); }, TypeError, 'throws an error for bindAll if the given key is not a function'); _.bindAll(moe, 'sayHi', 'sayLast'); curly.sayHi = moe.sayHi; - equal(curly.sayHi(), 'hi: moe'); + assert.equal(curly.sayHi(), 'hi: moe'); var sayLast = moe.sayLast; - equal(sayLast(1, 2, 3, 4, 5, 6, 7, 'Tom'), 'hi: moe', 'createCallback works with any number of arguments'); + assert.equal(sayLast(1, 2, 3, 4, 5, 6, 7, 'Tom'), 'hi: moe', 'createCallback works with any number of arguments'); _.bindAll(moe, ['getName']); var getName = moe.getName; - equal(getName(), 'name: moe', 'flattens arguments into a single list'); + assert.equal(getName(), 'name: moe', 'flattens arguments into a single list'); }); - test('memoize', function() { + test('memoize', function(assert) { var fib = function(n) { return n < 2 ? n : fib(n - 1) + fib(n - 2); }; - equal(fib(10), 55, 'a memoized version of fibonacci produces identical results'); + assert.equal(fib(10), 55, 'a memoized version of fibonacci produces identical results'); fib = _.memoize(fib); // Redefine `fib` for memoization - equal(fib(10), 55, 'a memoized version of fibonacci produces identical results'); + assert.equal(fib(10), 55, 'a memoized version of fibonacci produces identical results'); var o = function(str) { return str; }; var fastO = _.memoize(o); - equal(o('toString'), 'toString', 'checks hasOwnProperty'); - equal(fastO('toString'), 'toString', 'checks hasOwnProperty'); + assert.equal(o('toString'), 'toString', 'checks hasOwnProperty'); + assert.equal(fastO('toString'), 'toString', 'checks hasOwnProperty'); // Expose the cache. var upper = _.memoize(function(s) { return s.toUpperCase(); }); - equal(upper('foo'), 'FOO'); - equal(upper('bar'), 'BAR'); - deepEqual(upper.cache, {foo: 'FOO', bar: 'BAR'}); + assert.equal(upper('foo'), 'FOO'); + assert.equal(upper('bar'), 'BAR'); + assert.deepEqual(upper.cache, {foo: 'FOO', bar: 'BAR'}); upper.cache = {foo: 'BAR', bar: 'FOO'}; - equal(upper('foo'), 'BAR'); - equal(upper('bar'), 'FOO'); + assert.equal(upper('foo'), 'BAR'); + assert.equal(upper('bar'), 'FOO'); var hashed = _.memoize(function(key) { //https://github.com/jashkenas/underscore/pull/1679#discussion_r13736209 - ok(/[a-z]+/.test(key), 'hasher doesn\'t change keys'); + assert.ok(/[a-z]+/.test(key), 'hasher doesn\'t change keys'); return key; }, function(key) { return key.toUpperCase(); }); hashed('yep'); - deepEqual(hashed.cache, {YEP: 'yep'}, 'takes a hasher'); + assert.deepEqual(hashed.cache, {YEP: 'yep'}, 'takes a hasher'); // Test that the hash function can be used to swizzle the key. var objCacher = _.memoize(function(value, key) { @@ -169,78 +169,78 @@ }); var myObj = objCacher('a', 'alpha'); var myObjAlias = objCacher('b', 'alpha'); - notStrictEqual(myObj, void 0, 'object is created if second argument used as key'); - strictEqual(myObj, myObjAlias, 'object is cached if second argument used as key'); - strictEqual(myObj.value, 'a', 'object is not modified if second argument used as key'); + assert.notStrictEqual(myObj, void 0, 'object is created if second argument used as key'); + assert.strictEqual(myObj, myObjAlias, 'object is cached if second argument used as key'); + assert.strictEqual(myObj.value, 'a', 'object is not modified if second argument used as key'); }); - asyncTest('delay', 2, function() { + asyncTest('delay', 2, function(assert) { var delayed = false; _.delay(function(){ delayed = true; }, 100); - setTimeout(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50); - setTimeout(function(){ ok(delayed, 'delayed the function'); start(); }, 150); + setTimeout(function(){ assert.ok(!delayed, "didn't delay the function quite yet"); }, 50); + setTimeout(function(){ assert.ok(delayed, 'delayed the function'); start(); }, 150); }); - asyncTest('defer', 1, function() { + asyncTest('defer', 1, function(assert) { var deferred = false; _.defer(function(bool){ deferred = bool; }, true); - _.delay(function(){ ok(deferred, 'deferred the function'); start(); }, 50); + _.delay(function(){ assert.ok(deferred, 'deferred the function'); start(); }, 50); }); - asyncTest('throttle', 2, function() { + asyncTest('throttle', 2, function(assert) { var counter = 0; var incr = function(){ counter++; }; var throttledIncr = _.throttle(incr, 32); throttledIncr(); throttledIncr(); - equal(counter, 1, 'incr was called immediately'); - _.delay(function(){ equal(counter, 2, 'incr was throttled'); start(); }, 64); + assert.equal(counter, 1, 'incr was called immediately'); + _.delay(function(){ assert.equal(counter, 2, 'incr was throttled'); start(); }, 64); }); - asyncTest('throttle arguments', 2, function() { + asyncTest('throttle arguments', 2, function(assert) { var value = 0; var update = function(val){ value = val; }; var throttledUpdate = _.throttle(update, 32); throttledUpdate(1); throttledUpdate(2); _.delay(function(){ throttledUpdate(3); }, 64); - equal(value, 1, 'updated to latest value'); - _.delay(function(){ equal(value, 3, 'updated to latest value'); start(); }, 96); + assert.equal(value, 1, 'updated to latest value'); + _.delay(function(){ assert.equal(value, 3, 'updated to latest value'); start(); }, 96); }); - asyncTest('throttle once', 2, function() { + asyncTest('throttle once', 2, function(assert) { var counter = 0; var incr = function(){ return ++counter; }; var throttledIncr = _.throttle(incr, 32); var result = throttledIncr(); _.delay(function(){ - equal(result, 1, 'throttled functions return their value'); - equal(counter, 1, 'incr was called once'); start(); + assert.equal(result, 1, 'throttled functions return their value'); + assert.equal(counter, 1, 'incr was called once'); start(); }, 64); }); - asyncTest('throttle twice', 1, function() { + asyncTest('throttle twice', 1, function(assert) { var counter = 0; var incr = function(){ counter++; }; var throttledIncr = _.throttle(incr, 32); throttledIncr(); throttledIncr(); - _.delay(function(){ equal(counter, 2, 'incr was called twice'); start(); }, 64); + _.delay(function(){ assert.equal(counter, 2, 'incr was called twice'); start(); }, 64); }); - asyncTest('more throttling', 3, function() { + asyncTest('more throttling', 3, function(assert) { var counter = 0; var incr = function(){ counter++; }; var throttledIncr = _.throttle(incr, 30); throttledIncr(); throttledIncr(); - equal(counter, 1); + assert.equal(counter, 1); _.delay(function(){ - equal(counter, 2); + assert.equal(counter, 2); throttledIncr(); - equal(counter, 3); + assert.equal(counter, 3); start(); }, 85); }); - asyncTest('throttle repeatedly with results', 6, function() { + asyncTest('throttle repeatedly with results', 6, function(assert) { var counter = 0; var incr = function(){ return ++counter; }; var throttledIncr = _.throttle(incr, 100); @@ -252,17 +252,17 @@ _.delay(saveResult, 160); _.delay(saveResult, 230); _.delay(function() { - equal(results[0], 1, 'incr was called once'); - equal(results[1], 1, 'incr was throttled'); - equal(results[2], 1, 'incr was throttled'); - equal(results[3], 2, 'incr was called twice'); - equal(results[4], 2, 'incr was throttled'); - equal(results[5], 3, 'incr was called trailing'); + assert.equal(results[0], 1, 'incr was called once'); + assert.equal(results[1], 1, 'incr was throttled'); + assert.equal(results[2], 1, 'incr was throttled'); + assert.equal(results[3], 2, 'incr was called twice'); + assert.equal(results[4], 2, 'incr was throttled'); + assert.equal(results[5], 3, 'incr was called trailing'); start(); }, 300); }); - asyncTest('throttle triggers trailing call when invoked repeatedly', 2, function() { + asyncTest('throttle triggers trailing call when invoked repeatedly', 2, function(assert) { var counter = 0; var limit = 48; var incr = function(){ counter++; }; @@ -273,29 +273,29 @@ throttledIncr(); } var lastCount = counter; - ok(counter > 1); + assert.ok(counter > 1); _.delay(function() { - ok(counter > lastCount); + assert.ok(counter > lastCount); start(); }, 96); }); - asyncTest('throttle does not trigger leading call when leading is set to false', 2, function() { + asyncTest('throttle does not trigger leading call when leading is set to false', 2, function(assert) { var counter = 0; var incr = function(){ counter++; }; var throttledIncr = _.throttle(incr, 60, {leading: false}); throttledIncr(); throttledIncr(); - equal(counter, 0); + assert.equal(counter, 0); _.delay(function() { - equal(counter, 1); + assert.equal(counter, 1); start(); }, 96); }); - asyncTest('more throttle does not trigger leading call when leading is set to false', 3, function() { + asyncTest('more throttle does not trigger leading call when leading is set to false', 3, function(assert) { var counter = 0; var incr = function(){ counter++; }; var throttledIncr = _.throttle(incr, 100, {leading: false}); @@ -304,75 +304,75 @@ _.delay(throttledIncr, 50); _.delay(throttledIncr, 60); _.delay(throttledIncr, 200); - equal(counter, 0); + assert.equal(counter, 0); _.delay(function() { - equal(counter, 1); + assert.equal(counter, 1); }, 250); _.delay(function() { - equal(counter, 2); + assert.equal(counter, 2); start(); }, 350); }); - asyncTest('one more throttle with leading: false test', 2, function() { + asyncTest('one more throttle with leading: false test', 2, function(assert) { var counter = 0; var incr = function(){ counter++; }; var throttledIncr = _.throttle(incr, 100, {leading: false}); var time = new Date; while (new Date - time < 350) throttledIncr(); - ok(counter <= 3); + assert.ok(counter <= 3); _.delay(function() { - ok(counter <= 4); + assert.ok(counter <= 4); start(); }, 200); }); - asyncTest('throttle does not trigger trailing call when trailing is set to false', 4, function() { + asyncTest('throttle does not trigger trailing call when trailing is set to false', 4, function(assert) { var counter = 0; var incr = function(){ counter++; }; var throttledIncr = _.throttle(incr, 60, {trailing: false}); throttledIncr(); throttledIncr(); throttledIncr(); - equal(counter, 1); + assert.equal(counter, 1); _.delay(function() { - equal(counter, 1); + assert.equal(counter, 1); throttledIncr(); throttledIncr(); - equal(counter, 2); + assert.equal(counter, 2); _.delay(function() { - equal(counter, 2); + assert.equal(counter, 2); start(); }, 96); }, 96); }); - asyncTest('throttle continues to function after system time is set backwards', 2, function() { + asyncTest('throttle continues to function after system time is set backwards', 2, function(assert) { var counter = 0; var incr = function(){ counter++; }; var throttledIncr = _.throttle(incr, 100); var origNowFunc = _.now; throttledIncr(); - equal(counter, 1); + assert.equal(counter, 1); _.now = function() { return new Date(2013, 0, 1, 1, 1, 1); }; _.delay(function() { throttledIncr(); - equal(counter, 2); + assert.equal(counter, 2); start(); _.now = origNowFunc; }, 200); }); - asyncTest('throttle re-entrant', 2, function() { + asyncTest('throttle re-entrant', 2, function(assert) { var sequence = [ ['b1', 'b2'], ['c1', 'c2'] @@ -388,50 +388,100 @@ }; throttledAppend = _.throttle(append, 32); throttledAppend.call('a1', 'a2'); - equal(value, 'a1a2'); + assert.equal(value, 'a1a2'); _.delay(function(){ - equal(value, 'a1a2c1c2b1b2', 'append was throttled successfully'); + assert.equal(value, 'a1a2c1c2b1b2', 'append was throttled successfully'); start(); }, 100); }); - asyncTest('debounce', 1, function() { + asyncTest('throttle cancel', function(assert) { + var counter = 0; + var incr = function(){ counter++; }; + var throttledIncr = _.throttle(incr, 32); + throttledIncr(); + throttledIncr.cancel(); + throttledIncr(); + throttledIncr(); + + assert.equal(counter, 2, 'incr was called immediately'); + _.delay(function(){ assert.equal(counter, 3, 'incr was throttled'); start(); }, 64); + }); + + asyncTest('throttle cancel with leading: false', function(assert) { + var counter = 0; + var incr = function(){ counter++; }; + var throttledIncr = _.throttle(incr, 32, {leading: false}); + throttledIncr(); + throttledIncr.cancel(); + + assert.equal(counter, 0, 'incr was throttled'); + _.delay(function(){ assert.equal(counter, 0, 'incr was throttled'); start(); }, 64); + }); + + asyncTest('debounce', 1, function(assert) { var counter = 0; var incr = function(){ counter++; }; var debouncedIncr = _.debounce(incr, 32); debouncedIncr(); debouncedIncr(); _.delay(debouncedIncr, 16); - _.delay(function(){ equal(counter, 1, 'incr was debounced'); start(); }, 96); + _.delay(function(){ assert.equal(counter, 1, 'incr was debounced'); start(); }, 96); }); - asyncTest('debounce asap', 4, function() { + asyncTest('debounce cancel', 1, function(assert) { + var counter = 0; + var incr = function(){ counter++; }; + var debouncedIncr = _.debounce(incr, 32); + debouncedIncr(); + debouncedIncr.cancel(); + _.delay(function(){ assert.equal(counter, 0, 'incr was not called'); start(); }, 96); + }); + + asyncTest('debounce asap', 4, function(assert) { var a, b; var counter = 0; var incr = function(){ return ++counter; }; var debouncedIncr = _.debounce(incr, 64, true); a = debouncedIncr(); b = debouncedIncr(); - equal(a, 1); - equal(b, 1); - equal(counter, 1, 'incr was called immediately'); + assert.equal(a, 1); + assert.equal(b, 1); + assert.equal(counter, 1, 'incr was called immediately'); _.delay(debouncedIncr, 16); _.delay(debouncedIncr, 32); _.delay(debouncedIncr, 48); - _.delay(function(){ equal(counter, 1, 'incr was debounced'); start(); }, 128); + _.delay(function(){ assert.equal(counter, 1, 'incr was debounced'); start(); }, 128); }); - asyncTest('debounce asap recursively', 2, function() { + asyncTest('debounce asap cancel', 4, function(assert) { + var a, b; + var counter = 0; + var incr = function(){ return ++counter; }; + var debouncedIncr = _.debounce(incr, 64, true); + a = debouncedIncr(); + debouncedIncr.cancel(); + b = debouncedIncr(); + assert.equal(a, 1); + assert.equal(b, 2); + assert.equal(counter, 2, 'incr was called immediately'); + _.delay(debouncedIncr, 16); + _.delay(debouncedIncr, 32); + _.delay(debouncedIncr, 48); + _.delay(function(){ assert.equal(counter, 2, 'incr was debounced'); start(); }, 128); + }); + + asyncTest('debounce asap recursively', 2, function(assert) { var counter = 0; var debouncedIncr = _.debounce(function(){ counter++; if (counter < 10) debouncedIncr(); }, 32, true); debouncedIncr(); - equal(counter, 1, 'incr was called immediately'); - _.delay(function(){ equal(counter, 1, 'incr was debounced'); start(); }, 96); + assert.equal(counter, 1, 'incr was called immediately'); + _.delay(function(){ assert.equal(counter, 1, 'incr was debounced'); start(); }, 96); }); - asyncTest('debounce after system time is set backwards', 2, function() { + asyncTest('debounce after system time is set backwards', 2, function(assert) { var counter = 0; var origNowFunc = _.now; var debouncedIncr = _.debounce(function(){ @@ -439,7 +489,7 @@ }, 100, true); debouncedIncr(); - equal(counter, 1, 'incr was called immediately'); + assert.equal(counter, 1, 'incr was called immediately'); _.now = function() { return new Date(2013, 0, 1, 1, 1, 1); @@ -447,13 +497,13 @@ _.delay(function() { debouncedIncr(); - equal(counter, 2, 'incr was debounced successfully'); + assert.equal(counter, 2, 'incr was debounced successfully'); start(); _.now = origNowFunc; }, 200); }); - asyncTest('debounce re-entrant', 2, function() { + asyncTest('debounce re-entrant', 2, function(assert) { var sequence = [ ['b1', 'b2'] ]; @@ -468,80 +518,80 @@ }; debouncedAppend = _.debounce(append, 32); debouncedAppend.call('a1', 'a2'); - equal(value, ''); + assert.equal(value, ''); _.delay(function(){ - equal(value, 'a1a2b1b2', 'append was debounced successfully'); + assert.equal(value, 'a1a2b1b2', 'append was debounced successfully'); start(); }, 100); }); - test('once', function() { + test('once', function(assert) { var num = 0; var increment = _.once(function(){ return ++num; }); increment(); increment(); - equal(num, 1); + assert.equal(num, 1); - equal(increment(), 1, 'stores a memo to the last value'); + assert.equal(increment(), 1, 'stores a memo to the last value'); }); - test('Recursive onced function.', 1, function() { + test('Recursive onced function.', 1, function(assert) { var f = _.once(function(){ - ok(true); + assert.ok(true); f(); }); f(); }); - test('wrap', function() { + test('wrap', function(assert) { var greet = function(name){ return 'hi: ' + name; }; var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); }); - equal(backwards('moe'), 'hi: moe eom', 'wrapped the salutation function'); + assert.equal(backwards('moe'), 'hi: moe eom', 'wrapped the salutation function'); var inner = function(){ return 'Hello '; }; var obj = {name: 'Moe'}; obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; }); - equal(obj.hi(), 'Hello Moe'); + assert.equal(obj.hi(), 'Hello Moe'); var noop = function(){}; var wrapped = _.wrap(noop, function(){ return Array.prototype.slice.call(arguments, 0); }); var ret = wrapped(['whats', 'your'], 'vector', 'victor'); - deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']); + assert.deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']); }); - test('negate', function() { + test('negate', function(assert) { var isOdd = function(n){ return n & 1; }; - equal(_.negate(isOdd)(2), true, 'should return the complement of the given function'); - equal(_.negate(isOdd)(3), false, 'should return the complement of the given function'); + assert.equal(_.negate(isOdd)(2), true, 'should return the complement of the given function'); + assert.equal(_.negate(isOdd)(3), false, 'should return the complement of the given function'); }); - test('compose', function() { + test('compose', function(assert) { var greet = function(name){ return 'hi: ' + name; }; var exclaim = function(sentence){ return sentence + '!'; }; var composed = _.compose(exclaim, greet); - equal(composed('moe'), 'hi: moe!', 'can compose a function that takes another'); + assert.equal(composed('moe'), 'hi: moe!', 'can compose a function that takes another'); composed = _.compose(greet, exclaim); - equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative'); + assert.equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative'); // f(g(h(x, y, z))) function h(x, y, z) { - equal(arguments.length, 3, 'First function called with multiple args'); + assert.equal(arguments.length, 3, 'First function called with multiple args'); return z * y; } function g(x) { - equal(arguments.length, 1, 'Composed function is called with 1 argument'); + assert.equal(arguments.length, 1, 'Composed function is called with 1 argument'); return x; } function f(x) { - equal(arguments.length, 1, 'Composed function is called with 1 argument'); + assert.equal(arguments.length, 1, 'Composed function is called with 1 argument'); return x * 2; } composed = _.compose(f, g, h); - equal(composed(1, 2, 3), 12); + assert.equal(composed(1, 2, 3), 12); }); - test('after', function() { + test('after', function(assert) { var testAfter = function(afterAmount, timesCalled) { var afterCalled = 0; var after = _.after(afterAmount, function() { @@ -551,13 +601,13 @@ return afterCalled; }; - equal(testAfter(5, 5), 1, 'after(N) should fire after being called N times'); - equal(testAfter(5, 4), 0, 'after(N) should not fire unless called N times'); - equal(testAfter(0, 0), 0, 'after(0) should not fire immediately'); - equal(testAfter(0, 1), 1, 'after(0) should fire when first invoked'); + assert.equal(testAfter(5, 5), 1, 'after(N) should fire after being called N times'); + assert.equal(testAfter(5, 4), 0, 'after(N) should not fire unless called N times'); + assert.equal(testAfter(0, 0), 0, 'after(0) should not fire immediately'); + assert.equal(testAfter(0, 1), 1, 'after(0) should fire when first invoked'); }); - test('before', function() { + test('before', function(assert) { var testBefore = function(beforeAmount, timesCalled) { var beforeCalled = 0; var before = _.before(beforeAmount, function() { beforeCalled++; }); @@ -565,58 +615,58 @@ return beforeCalled; }; - equal(testBefore(5, 5), 4, 'before(N) should not fire after being called N times'); - equal(testBefore(5, 4), 4, 'before(N) should fire before being called N times'); - equal(testBefore(0, 0), 0, 'before(0) should not fire immediately'); - equal(testBefore(0, 1), 0, 'before(0) should not fire when first invoked'); + assert.equal(testBefore(5, 5), 4, 'before(N) should not fire after being called N times'); + assert.equal(testBefore(5, 4), 4, 'before(N) should fire before being called N times'); + assert.equal(testBefore(0, 0), 0, 'before(0) should not fire immediately'); + assert.equal(testBefore(0, 1), 0, 'before(0) should not fire when first invoked'); var context = {num: 0}; var increment = _.before(3, function(){ return ++this.num; }); _.times(10, increment, context); - equal(increment(), 2, 'stores a memo to the last value'); - equal(context.num, 2, 'provides context'); + assert.equal(increment(), 2, 'stores a memo to the last value'); + assert.equal(context.num, 2, 'provides context'); }); - test('iteratee', function() { + test('iteratee', function(assert) { var identity = _.iteratee(); - equal(identity, _.identity, '_.iteratee is exposed as an external function.'); + assert.equal(identity, _.identity, '_.iteratee is exposed as an external function.'); function fn() { return arguments; } _.each([_.iteratee(fn), _.iteratee(fn, {})], function(cb) { - equal(cb().length, 0); - deepEqual(_.toArray(cb(1, 2, 3)), _.range(1, 4)); - deepEqual(_.toArray(cb(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), _.range(1, 11)); + assert.equal(cb().length, 0); + assert.deepEqual(_.toArray(cb(1, 2, 3)), _.range(1, 4)); + assert.deepEqual(_.toArray(cb(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), _.range(1, 11)); }); }); - test('restArgs', 10, function() { + test('restArgs', 10, function(assert) { _.restArgs(function(a, args) { - strictEqual(a, 1); - deepEqual(args, [2, 3], 'collects rest arguments into an array'); + assert.strictEqual(a, 1); + assert.deepEqual(args, [2, 3], 'collects rest arguments into an array'); })(1, 2, 3); _.restArgs(function(a, args) { - strictEqual(a, void 0); - deepEqual(args, [], 'passes empty array if there are not enough arguments'); + assert.strictEqual(a, void 0); + assert.deepEqual(args, [], 'passes empty array if there are not enough arguments'); })(); _.restArgs(function(a, b, c, args) { - strictEqual(arguments.length, 4); - deepEqual(args, [4, 5], 'works on functions with many named parameters'); + assert.strictEqual(arguments.length, 4); + assert.deepEqual(args, [4, 5], 'works on functions with many named parameters'); })(1, 2, 3, 4, 5); var obj = {}; _.restArgs(function() { - strictEqual(this, obj, 'invokes function with this context'); + assert.strictEqual(this, obj, 'invokes function with this context'); }).call(obj); _.restArgs(function(array, iteratee, context) { - deepEqual(array, [1, 2, 3, 4], 'startIndex can be used manually specify index of rest parameter'); - strictEqual(iteratee, void 0); - strictEqual(context, void 0); + assert.deepEqual(array, [1, 2, 3, 4], 'startIndex can be used manually specify index of rest parameter'); + assert.strictEqual(iteratee, void 0); + assert.strictEqual(context, void 0); }, 0)(1, 2, 3, 4); }); diff --git a/vendor/underscore/test/objects.js b/vendor/underscore/test/objects.js index 066264c2b..bc3075839 100644 --- a/vendor/underscore/test/objects.js +++ b/vendor/underscore/test/objects.js @@ -5,16 +5,16 @@ var testElement = typeof document === 'object' ? document.createElement('div') : void 0; - test('keys', function() { - deepEqual(_.keys({one: 1, two: 2}), ['one', 'two'], 'can extract the keys from an object'); + test('keys', function(assert) { + assert.deepEqual(_.keys({one: 1, two: 2}), ['one', 'two'], 'can extract the keys from an object'); // the test above is not safe because it relies on for-in enumeration order var a = []; a[1] = 0; - deepEqual(_.keys(a), ['1'], 'is not fooled by sparse arrays; see issue #95'); - deepEqual(_.keys(null), []); - deepEqual(_.keys(void 0), []); - deepEqual(_.keys(1), []); - deepEqual(_.keys('a'), []); - deepEqual(_.keys(true), []); + assert.deepEqual(_.keys(a), ['1'], 'is not fooled by sparse arrays; see issue #95'); + assert.deepEqual(_.keys(null), []); + assert.deepEqual(_.keys(void 0), []); + assert.deepEqual(_.keys(1), []); + assert.deepEqual(_.keys('a'), []); + assert.deepEqual(_.keys(true), []); // keys that may be missed if the implementation isn't careful var trouble = { @@ -32,20 +32,20 @@ }; var troubleKeys = ['constructor', 'valueOf', 'hasOwnProperty', 'toString', 'toLocaleString', 'propertyIsEnumerable', 'isPrototypeOf', '__defineGetter__', '__defineSetter__', '__lookupSetter__', '__lookupGetter__'].sort(); - deepEqual(_.keys(trouble).sort(), troubleKeys, 'matches non-enumerable properties'); + assert.deepEqual(_.keys(trouble).sort(), troubleKeys, 'matches non-enumerable properties'); }); - test('allKeys', function() { - deepEqual(_.allKeys({one: 1, two: 2}), ['one', 'two'], 'can extract the allKeys from an object'); + test('allKeys', function(assert) { + assert.deepEqual(_.allKeys({one: 1, two: 2}), ['one', 'two'], 'can extract the allKeys from an object'); // the test above is not safe because it relies on for-in enumeration order var a = []; a[1] = 0; - deepEqual(_.allKeys(a), ['1'], 'is not fooled by sparse arrays; see issue #95'); + assert.deepEqual(_.allKeys(a), ['1'], 'is not fooled by sparse arrays; see issue #95'); a.a = a; - deepEqual(_.allKeys(a), ['1', 'a'], 'is not fooled by sparse arrays with additional properties'); + assert.deepEqual(_.allKeys(a), ['1', 'a'], 'is not fooled by sparse arrays with additional properties'); _.each([null, void 0, 1, 'a', true, NaN, {}, [], new Number(5), new Date(0)], function(val) { - deepEqual(_.allKeys(val), []); + assert.deepEqual(_.allKeys(val), []); }); // allKeys that may be missed if the implementation isn't careful @@ -60,255 +60,259 @@ }; var troubleKeys = ['constructor', 'valueOf', 'hasOwnProperty', 'toString', 'toLocaleString', 'propertyIsEnumerable', 'isPrototypeOf'].sort(); - deepEqual(_.allKeys(trouble).sort(), troubleKeys, 'matches non-enumerable properties'); + assert.deepEqual(_.allKeys(trouble).sort(), troubleKeys, 'matches non-enumerable properties'); function A() {} A.prototype.foo = 'foo'; var b = new A(); b.bar = 'bar'; - deepEqual(_.allKeys(b).sort(), ['bar', 'foo'], 'should include inherited keys'); + assert.deepEqual(_.allKeys(b).sort(), ['bar', 'foo'], 'should include inherited keys'); function y() {} y.x = 'z'; - deepEqual(_.allKeys(y), ['x'], 'should get keys from constructor'); + assert.deepEqual(_.allKeys(y), ['x'], 'should get keys from constructor'); }); - test('values', function() { - deepEqual(_.values({one: 1, two: 2}), [1, 2], 'can extract the values from an object'); - deepEqual(_.values({one: 1, two: 2, length: 3}), [1, 2, 3], '... even when one of them is "length"'); + test('values', function(assert) { + assert.deepEqual(_.values({one: 1, two: 2}), [1, 2], 'can extract the values from an object'); + assert.deepEqual(_.values({one: 1, two: 2, length: 3}), [1, 2, 3], '... even when one of them is "length"'); }); - test('pairs', function() { - deepEqual(_.pairs({one: 1, two: 2}), [['one', 1], ['two', 2]], 'can convert an object into pairs'); - deepEqual(_.pairs({one: 1, two: 2, length: 3}), [['one', 1], ['two', 2], ['length', 3]], '... even when one of them is "length"'); + test('pairs', function(assert) { + assert.deepEqual(_.pairs({one: 1, two: 2}), [['one', 1], ['two', 2]], 'can convert an object into pairs'); + assert.deepEqual(_.pairs({one: 1, two: 2, length: 3}), [['one', 1], ['two', 2], ['length', 3]], '... even when one of them is "length"'); }); - test('invert', function() { + test('invert', function(assert) { var obj = {first: 'Moe', second: 'Larry', third: 'Curly'}; - deepEqual(_.keys(_.invert(obj)), ['Moe', 'Larry', 'Curly'], 'can invert an object'); - deepEqual(_.invert(_.invert(obj)), obj, 'two inverts gets you back where you started'); + assert.deepEqual(_.keys(_.invert(obj)), ['Moe', 'Larry', 'Curly'], 'can invert an object'); + assert.deepEqual(_.invert(_.invert(obj)), obj, 'two inverts gets you back where you started'); obj = {length: 3}; - equal(_.invert(obj)['3'], 'length', 'can invert an object with "length"'); + assert.equal(_.invert(obj)['3'], 'length', 'can invert an object with "length"'); }); - test('functions', function() { + test('functions', function(assert) { var obj = {a: 'dash', b: _.map, c: /yo/, d: _.reduce}; - deepEqual(['b', 'd'], _.functions(obj), 'can grab the function names of any passed-in object'); + assert.deepEqual(['b', 'd'], _.functions(obj), 'can grab the function names of any passed-in object'); var Animal = function(){}; Animal.prototype.run = function(){}; - deepEqual(_.functions(new Animal), ['run'], 'also looks up functions on the prototype'); + assert.deepEqual(_.functions(new Animal), ['run'], 'also looks up functions on the prototype'); }); - test('methods', function() { - strictEqual(_.functions, _.methods, 'alias for functions'); + test('methods', function(assert) { + assert.strictEqual(_.methods, _.functions, 'is an alias for functions'); }); - test('extend', function() { + test('extend', function(assert) { var result; - equal(_.extend({}, {a: 'b'}).a, 'b', 'can extend an object with the attributes of another'); - equal(_.extend({a: 'x'}, {a: 'b'}).a, 'b', 'properties in source override destination'); - equal(_.extend({x: 'x'}, {a: 'b'}).x, 'x', "properties not in source don't get overriden"); + assert.equal(_.extend({}, {a: 'b'}).a, 'b', 'can extend an object with the attributes of another'); + assert.equal(_.extend({a: 'x'}, {a: 'b'}).a, 'b', 'properties in source override destination'); + assert.equal(_.extend({x: 'x'}, {a: 'b'}).x, 'x', "properties not in source don't get overriden"); result = _.extend({x: 'x'}, {a: 'a'}, {b: 'b'}); - deepEqual(result, {x: 'x', a: 'a', b: 'b'}, 'can extend from multiple source objects'); + assert.deepEqual(result, {x: 'x', a: 'a', b: 'b'}, 'can extend from multiple source objects'); result = _.extend({x: 'x'}, {a: 'a', x: 2}, {a: 'b'}); - deepEqual(result, {x: 2, a: 'b'}, 'extending from multiple source objects last property trumps'); + assert.deepEqual(result, {x: 2, a: 'b'}, 'extending from multiple source objects last property trumps'); result = _.extend({}, {a: void 0, b: null}); - deepEqual(_.keys(result), ['a', 'b'], 'extend copies undefined values'); + assert.deepEqual(_.keys(result), ['a', 'b'], 'extend copies undefined values'); var F = function() {}; F.prototype = {a: 'b'}; var subObj = new F(); subObj.c = 'd'; - deepEqual(_.extend({}, subObj), {a: 'b', c: 'd'}, 'extend copies all properties from source'); + assert.deepEqual(_.extend({}, subObj), {a: 'b', c: 'd'}, 'extend copies all properties from source'); _.extend(subObj, {}); - ok(!subObj.hasOwnProperty('a'), "extend does not convert destination object's 'in' properties to 'own' properties"); + assert.ok(!subObj.hasOwnProperty('a'), "extend does not convert destination object's 'in' properties to 'own' properties"); try { result = {}; _.extend(result, null, void 0, {a: 1}); } catch(e) { /* ignored */ } - equal(result.a, 1, 'should not error on `null` or `undefined` sources'); + assert.equal(result.a, 1, 'should not error on `null` or `undefined` sources'); - strictEqual(_.extend(null, {a: 1}), null, 'extending null results in null'); - strictEqual(_.extend(void 0, {a: 1}), void 0, 'extending undefined results in undefined'); + assert.strictEqual(_.extend(null, {a: 1}), null, 'extending null results in null'); + assert.strictEqual(_.extend(void 0, {a: 1}), void 0, 'extending undefined results in undefined'); }); - test('extendOwn', function() { + test('extendOwn', function(assert) { var result; - equal(_.extendOwn({}, {a: 'b'}).a, 'b', 'can assign an object with the attributes of another'); - equal(_.extendOwn({a: 'x'}, {a: 'b'}).a, 'b', 'properties in source override destination'); - equal(_.extendOwn({x: 'x'}, {a: 'b'}).x, 'x', "properties not in source don't get overriden"); + assert.equal(_.extendOwn({}, {a: 'b'}).a, 'b', 'can extend an object with the attributes of another'); + assert.equal(_.extendOwn({a: 'x'}, {a: 'b'}).a, 'b', 'properties in source override destination'); + assert.equal(_.extendOwn({x: 'x'}, {a: 'b'}).x, 'x', "properties not in source don't get overriden"); result = _.extendOwn({x: 'x'}, {a: 'a'}, {b: 'b'}); - deepEqual(result, {x: 'x', a: 'a', b: 'b'}, 'can assign from multiple source objects'); - result = _.assign({x: 'x'}, {a: 'a', x: 2}, {a: 'b'}); - deepEqual(result, {x: 2, a: 'b'}, 'assigning from multiple source objects last property trumps'); - deepEqual(_.extendOwn({}, {a: void 0, b: null}), {a: void 0, b: null}, 'assign copies undefined values'); + assert.deepEqual(result, {x: 'x', a: 'a', b: 'b'}, 'can extend from multiple source objects'); + result = _.extendOwn({x: 'x'}, {a: 'a', x: 2}, {a: 'b'}); + assert.deepEqual(result, {x: 2, a: 'b'}, 'extending from multiple source objects last property trumps'); + assert.deepEqual(_.extendOwn({}, {a: void 0, b: null}), {a: void 0, b: null}, 'copies undefined values'); var F = function() {}; F.prototype = {a: 'b'}; var subObj = new F(); subObj.c = 'd'; - deepEqual(_.extendOwn({}, subObj), {c: 'd'}, 'assign copies own properties from source'); + assert.deepEqual(_.extendOwn({}, subObj), {c: 'd'}, 'copies own properties from source'); result = {}; - deepEqual(_.assign(result, null, void 0, {a: 1}), {a: 1}, 'should not error on `null` or `undefined` sources'); + assert.deepEqual(_.extendOwn(result, null, void 0, {a: 1}), {a: 1}, 'should not error on `null` or `undefined` sources'); _.each(['a', 5, null, false], function(val) { - strictEqual(_.assign(val, {a: 1}), val, 'assigning non-objects results in returning the non-object value'); + assert.strictEqual(_.extendOwn(val, {a: 1}), val, 'extending non-objects results in returning the non-object value'); }); - strictEqual(_.extendOwn(void 0, {a: 1}), void 0, 'assigning undefined results in undefined'); + assert.strictEqual(_.extendOwn(void 0, {a: 1}), void 0, 'extending undefined results in undefined'); result = _.extendOwn({a: 1, 0: 2, 1: '5', length: 6}, {0: 1, 1: 2, length: 2}); - deepEqual(result, {a: 1, 0: 1, 1: 2, length: 2}, 'assign should treat array-like objects like normal objects'); + assert.deepEqual(result, {a: 1, 0: 1, 1: 2, length: 2}, 'should treat array-like objects like normal objects'); }); - test('pick', function() { + test('assign', function(assert) { + assert.strictEqual(_.assign, _.extendOwn, 'is an alias for extendOwn'); + }); + + test('pick', function(assert) { var result; result = _.pick({a: 1, b: 2, c: 3}, 'a', 'c'); - deepEqual(result, {a: 1, c: 3}, 'can restrict properties to those named'); + assert.deepEqual(result, {a: 1, c: 3}, 'can restrict properties to those named'); result = _.pick({a: 1, b: 2, c: 3}, ['b', 'c']); - deepEqual(result, {b: 2, c: 3}, 'can restrict properties to those named in an array'); + assert.deepEqual(result, {b: 2, c: 3}, 'can restrict properties to those named in an array'); result = _.pick({a: 1, b: 2, c: 3}, ['a'], 'b'); - deepEqual(result, {a: 1, b: 2}, 'can restrict properties to those named in mixed args'); + assert.deepEqual(result, {a: 1, b: 2}, 'can restrict properties to those named in mixed args'); result = _.pick(['a', 'b'], 1); - deepEqual(result, {1: 'b'}, 'can pick numeric properties'); + assert.deepEqual(result, {1: 'b'}, 'can pick numeric properties'); _.each([null, void 0], function(val) { - deepEqual(_.pick(val, 'hasOwnProperty'), {}, 'Called with null/undefined'); - deepEqual(_.pick(val, _.constant(true)), {}); + assert.deepEqual(_.pick(val, 'hasOwnProperty'), {}, 'Called with null/undefined'); + assert.deepEqual(_.pick(val, _.constant(true)), {}); }); - deepEqual(_.pick(5, 'toString', 'b'), {toString: Number.prototype.toString}, 'can iterate primitives'); + assert.deepEqual(_.pick(5, 'toString', 'b'), {toString: Number.prototype.toString}, 'can iterate primitives'); var data = {a: 1, b: 2, c: 3}; var callback = function(value, key, object) { - strictEqual(key, {1: 'a', 2: 'b', 3: 'c'}[value]); - strictEqual(object, data); + assert.strictEqual(key, {1: 'a', 2: 'b', 3: 'c'}[value]); + assert.strictEqual(object, data); return value !== this.value; }; result = _.pick(data, callback, {value: 2}); - deepEqual(result, {a: 1, c: 3}, 'can accept a predicate and context'); + assert.deepEqual(result, {a: 1, c: 3}, 'can accept a predicate and context'); var Obj = function(){}; Obj.prototype = {a: 1, b: 2, c: 3}; var instance = new Obj(); - deepEqual(_.pick(instance, 'a', 'c'), {a: 1, c: 3}, 'include prototype props'); + assert.deepEqual(_.pick(instance, 'a', 'c'), {a: 1, c: 3}, 'include prototype props'); - deepEqual(_.pick(data, function(val, key) { + assert.deepEqual(_.pick(data, function(val, key) { return this[key] === 3 && this === instance; }, instance), {c: 3}, 'function is given context'); - ok(!_.has(_.pick({}, 'foo'), 'foo'), 'does not set own property if property not in object'); + assert.ok(!_.has(_.pick({}, 'foo'), 'foo'), 'does not set own property if property not in object'); _.pick(data, function(value, key, obj) { - equal(obj, data, 'passes same object as third parameter of iteratee'); + assert.equal(obj, data, 'passes same object as third parameter of iteratee'); }); }); - test('omit', function() { + test('omit', function(assert) { var result; result = _.omit({a: 1, b: 2, c: 3}, 'b'); - deepEqual(result, {a: 1, c: 3}, 'can omit a single named property'); + assert.deepEqual(result, {a: 1, c: 3}, 'can omit a single named property'); result = _.omit({a: 1, b: 2, c: 3}, 'a', 'c'); - deepEqual(result, {b: 2}, 'can omit several named properties'); + assert.deepEqual(result, {b: 2}, 'can omit several named properties'); result = _.omit({a: 1, b: 2, c: 3}, ['b', 'c']); - deepEqual(result, {a: 1}, 'can omit properties named in an array'); + assert.deepEqual(result, {a: 1}, 'can omit properties named in an array'); result = _.omit(['a', 'b'], 0); - deepEqual(result, {1: 'b'}, 'can omit numeric properties'); + assert.deepEqual(result, {1: 'b'}, 'can omit numeric properties'); - deepEqual(_.omit(null, 'a', 'b'), {}, 'non objects return empty object'); - deepEqual(_.omit(void 0, 'toString'), {}, 'null/undefined return empty object'); - deepEqual(_.omit(5, 'toString', 'b'), {}, 'returns empty object for primitives'); + assert.deepEqual(_.omit(null, 'a', 'b'), {}, 'non objects return empty object'); + assert.deepEqual(_.omit(void 0, 'toString'), {}, 'null/undefined return empty object'); + assert.deepEqual(_.omit(5, 'toString', 'b'), {}, 'returns empty object for primitives'); var data = {a: 1, b: 2, c: 3}; var callback = function(value, key, object) { - strictEqual(key, {1: 'a', 2: 'b', 3: 'c'}[value]); - strictEqual(object, data); + assert.strictEqual(key, {1: 'a', 2: 'b', 3: 'c'}[value]); + assert.strictEqual(object, data); return value !== this.value; }; result = _.omit(data, callback, {value: 2}); - deepEqual(result, {b: 2}, 'can accept a predicate'); + assert.deepEqual(result, {b: 2}, 'can accept a predicate'); var Obj = function(){}; Obj.prototype = {a: 1, b: 2, c: 3}; var instance = new Obj(); - deepEqual(_.omit(instance, 'b'), {a: 1, c: 3}, 'include prototype props'); + assert.deepEqual(_.omit(instance, 'b'), {a: 1, c: 3}, 'include prototype props'); - deepEqual(_.omit(data, function(val, key) { + assert.deepEqual(_.omit(data, function(val, key) { return this[key] === 3 && this === instance; }, instance), {a: 1, b: 2}, 'function is given context'); }); - test('defaults', function() { + test('defaults', function(assert) { var options = {zero: 0, one: 1, empty: '', nan: NaN, nothing: null}; _.defaults(options, {zero: 1, one: 10, twenty: 20, nothing: 'str'}); - equal(options.zero, 0, 'value exists'); - equal(options.one, 1, 'value exists'); - equal(options.twenty, 20, 'default applied'); - equal(options.nothing, null, "null isn't overridden"); + assert.equal(options.zero, 0, 'value exists'); + assert.equal(options.one, 1, 'value exists'); + assert.equal(options.twenty, 20, 'default applied'); + assert.equal(options.nothing, null, "null isn't overridden"); _.defaults(options, {empty: 'full'}, {nan: 'nan'}, {word: 'word'}, {word: 'dog'}); - equal(options.empty, '', 'value exists'); - ok(_.isNaN(options.nan), "NaN isn't overridden"); - equal(options.word, 'word', 'new value is added, first one wins'); + assert.equal(options.empty, '', 'value exists'); + assert.ok(_.isNaN(options.nan), "NaN isn't overridden"); + assert.equal(options.word, 'word', 'new value is added, first one wins'); try { options = {}; _.defaults(options, null, void 0, {a: 1}); } catch(e) { /* ignored */ } - equal(options.a, 1, 'should not error on `null` or `undefined` sources'); + assert.equal(options.a, 1, 'should not error on `null` or `undefined` sources'); - deepEqual(_.defaults(null, {a: 1}), {a: 1}, 'defaults skips nulls'); - deepEqual(_.defaults(void 0, {a: 1}), {a: 1}, 'defaults skips undefined'); + assert.deepEqual(_.defaults(null, {a: 1}), {a: 1}, 'defaults skips nulls'); + assert.deepEqual(_.defaults(void 0, {a: 1}), {a: 1}, 'defaults skips undefined'); }); - test('clone', function() { + test('clone', function(assert) { var moe = {name: 'moe', lucky: [13, 27, 34]}; var clone = _.clone(moe); - equal(clone.name, 'moe', 'the clone as the attributes of the original'); + assert.equal(clone.name, 'moe', 'the clone as the attributes of the original'); clone.name = 'curly'; - ok(clone.name === 'curly' && moe.name === 'moe', 'clones can change shallow attributes without affecting the original'); + assert.ok(clone.name === 'curly' && moe.name === 'moe', 'clones can change shallow attributes without affecting the original'); clone.lucky.push(101); - equal(_.last(moe.lucky), 101, 'changes to deep attributes are shared with the original'); + assert.equal(_.last(moe.lucky), 101, 'changes to deep attributes are shared with the original'); - equal(_.clone(void 0), void 0, 'non objects should not be changed by clone'); - equal(_.clone(1), 1, 'non objects should not be changed by clone'); - equal(_.clone(null), null, 'non objects should not be changed by clone'); + assert.equal(_.clone(void 0), void 0, 'non objects should not be changed by clone'); + assert.equal(_.clone(1), 1, 'non objects should not be changed by clone'); + assert.equal(_.clone(null), null, 'non objects should not be changed by clone'); }); - test('create', function() { + test('create', function(assert) { var Parent = function() {}; Parent.prototype = {foo: function() {}, bar: 2}; _.each(['foo', null, void 0, 1], function(val) { - deepEqual(_.create(val), {}, 'should return empty object when a non-object is provided'); + assert.deepEqual(_.create(val), {}, 'should return empty object when a non-object is provided'); }); - ok(_.create([]) instanceof Array, 'should return new instance of array when array is provided'); + assert.ok(_.create([]) instanceof Array, 'should return new instance of array when array is provided'); var Child = function() {}; Child.prototype = _.create(Parent.prototype); - ok(new Child instanceof Parent, 'object should inherit prototype'); + assert.ok(new Child instanceof Parent, 'object should inherit prototype'); var func = function() {}; Child.prototype = _.create(Parent.prototype, {func: func}); - strictEqual(Child.prototype.func, func, 'properties should be added to object'); + assert.strictEqual(Child.prototype.func, func, 'properties should be added to object'); Child.prototype = _.create(Parent.prototype, {constructor: Child}); - strictEqual(Child.prototype.constructor, Child); + assert.strictEqual(Child.prototype.constructor, Child); Child.prototype.foo = 'foo'; var created = _.create(Child.prototype, new Child); - ok(!created.hasOwnProperty('foo'), 'should only add own properties'); + assert.ok(!created.hasOwnProperty('foo'), 'should only add own properties'); }); - test('isEqual', function() { + test('isEqual', function(assert) { function First() { this.value = 1; } @@ -319,128 +323,128 @@ Second.prototype.value = 2; // Basic equality and identity comparisons. - ok(_.isEqual(null, null), '`null` is equal to `null`'); - ok(_.isEqual(), '`undefined` is equal to `undefined`'); + assert.ok(_.isEqual(null, null), '`null` is equal to `null`'); + assert.ok(_.isEqual(), '`undefined` is equal to `undefined`'); - ok(!_.isEqual(0, -0), '`0` is not equal to `-0`'); - ok(!_.isEqual(-0, 0), 'Commutative equality is implemented for `0` and `-0`'); - ok(!_.isEqual(null, void 0), '`null` is not equal to `undefined`'); - ok(!_.isEqual(void 0, null), 'Commutative equality is implemented for `null` and `undefined`'); + assert.ok(!_.isEqual(0, -0), '`0` is not equal to `-0`'); + assert.ok(!_.isEqual(-0, 0), 'Commutative equality is implemented for `0` and `-0`'); + assert.ok(!_.isEqual(null, void 0), '`null` is not equal to `undefined`'); + assert.ok(!_.isEqual(void 0, null), 'Commutative equality is implemented for `null` and `undefined`'); // String object and primitive comparisons. - ok(_.isEqual('Curly', 'Curly'), 'Identical string primitives are equal'); - ok(_.isEqual(new String('Curly'), new String('Curly')), 'String objects with identical primitive values are equal'); - ok(_.isEqual(new String('Curly'), 'Curly'), 'String primitives and their corresponding object wrappers are equal'); - ok(_.isEqual('Curly', new String('Curly')), 'Commutative equality is implemented for string objects and primitives'); + assert.ok(_.isEqual('Curly', 'Curly'), 'Identical string primitives are equal'); + assert.ok(_.isEqual(new String('Curly'), new String('Curly')), 'String objects with identical primitive values are equal'); + assert.ok(_.isEqual(new String('Curly'), 'Curly'), 'String primitives and their corresponding object wrappers are equal'); + assert.ok(_.isEqual('Curly', new String('Curly')), 'Commutative equality is implemented for string objects and primitives'); - ok(!_.isEqual('Curly', 'Larry'), 'String primitives with different values are not equal'); - ok(!_.isEqual(new String('Curly'), new String('Larry')), 'String objects with different primitive values are not equal'); - ok(!_.isEqual(new String('Curly'), {toString: function(){ return 'Curly'; }}), 'String objects and objects with a custom `toString` method are not equal'); + assert.ok(!_.isEqual('Curly', 'Larry'), 'String primitives with different values are not equal'); + assert.ok(!_.isEqual(new String('Curly'), new String('Larry')), 'String objects with different primitive values are not equal'); + assert.ok(!_.isEqual(new String('Curly'), {toString: function(){ return 'Curly'; }}), 'String objects and objects with a custom `toString` method are not equal'); // Number object and primitive comparisons. - ok(_.isEqual(75, 75), 'Identical number primitives are equal'); - ok(_.isEqual(new Number(75), new Number(75)), 'Number objects with identical primitive values are equal'); - ok(_.isEqual(75, new Number(75)), 'Number primitives and their corresponding object wrappers are equal'); - ok(_.isEqual(new Number(75), 75), 'Commutative equality is implemented for number objects and primitives'); - ok(!_.isEqual(new Number(0), -0), '`new Number(0)` and `-0` are not equal'); - ok(!_.isEqual(0, new Number(-0)), 'Commutative equality is implemented for `new Number(0)` and `-0`'); + assert.ok(_.isEqual(75, 75), 'Identical number primitives are equal'); + assert.ok(_.isEqual(new Number(75), new Number(75)), 'Number objects with identical primitive values are equal'); + assert.ok(_.isEqual(75, new Number(75)), 'Number primitives and their corresponding object wrappers are equal'); + assert.ok(_.isEqual(new Number(75), 75), 'Commutative equality is implemented for number objects and primitives'); + assert.ok(!_.isEqual(new Number(0), -0), '`new Number(0)` and `-0` are not equal'); + assert.ok(!_.isEqual(0, new Number(-0)), 'Commutative equality is implemented for `new Number(0)` and `-0`'); - ok(!_.isEqual(new Number(75), new Number(63)), 'Number objects with different primitive values are not equal'); - ok(!_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), 'Number objects and objects with a `valueOf` method are not equal'); + assert.ok(!_.isEqual(new Number(75), new Number(63)), 'Number objects with different primitive values are not equal'); + assert.ok(!_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), 'Number objects and objects with a `valueOf` method are not equal'); // Comparisons involving `NaN`. - ok(_.isEqual(NaN, NaN), '`NaN` is equal to `NaN`'); - ok(_.isEqual(new Number(NaN), NaN), 'Object(`NaN`) is equal to `NaN`'); - ok(!_.isEqual(61, NaN), 'A number primitive is not equal to `NaN`'); - ok(!_.isEqual(new Number(79), NaN), 'A number object is not equal to `NaN`'); - ok(!_.isEqual(Infinity, NaN), '`Infinity` is not equal to `NaN`'); + assert.ok(_.isEqual(NaN, NaN), '`NaN` is equal to `NaN`'); + assert.ok(_.isEqual(new Number(NaN), NaN), 'Object(`NaN`) is equal to `NaN`'); + assert.ok(!_.isEqual(61, NaN), 'A number primitive is not equal to `NaN`'); + assert.ok(!_.isEqual(new Number(79), NaN), 'A number object is not equal to `NaN`'); + assert.ok(!_.isEqual(Infinity, NaN), '`Infinity` is not equal to `NaN`'); // Boolean object and primitive comparisons. - ok(_.isEqual(true, true), 'Identical boolean primitives are equal'); - ok(_.isEqual(new Boolean, new Boolean), 'Boolean objects with identical primitive values are equal'); - ok(_.isEqual(true, new Boolean(true)), 'Boolean primitives and their corresponding object wrappers are equal'); - ok(_.isEqual(new Boolean(true), true), 'Commutative equality is implemented for booleans'); - ok(!_.isEqual(new Boolean(true), new Boolean), 'Boolean objects with different primitive values are not equal'); + assert.ok(_.isEqual(true, true), 'Identical boolean primitives are equal'); + assert.ok(_.isEqual(new Boolean, new Boolean), 'Boolean objects with identical primitive values are equal'); + assert.ok(_.isEqual(true, new Boolean(true)), 'Boolean primitives and their corresponding object wrappers are equal'); + assert.ok(_.isEqual(new Boolean(true), true), 'Commutative equality is implemented for booleans'); + assert.ok(!_.isEqual(new Boolean(true), new Boolean), 'Boolean objects with different primitive values are not equal'); // Common type coercions. - ok(!_.isEqual(new Boolean(false), true), '`new Boolean(false)` is not equal to `true`'); - ok(!_.isEqual('75', 75), 'String and number primitives with like values are not equal'); - ok(!_.isEqual(new Number(63), new String(63)), 'String and number objects with like values are not equal'); - ok(!_.isEqual(75, '75'), 'Commutative equality is implemented for like string and number values'); - ok(!_.isEqual(0, ''), 'Number and string primitives with like values are not equal'); - ok(!_.isEqual(1, true), 'Number and boolean primitives with like values are not equal'); - ok(!_.isEqual(new Boolean(false), new Number(0)), 'Boolean and number objects with like values are not equal'); - ok(!_.isEqual(false, new String('')), 'Boolean primitives and string objects with like values are not equal'); - ok(!_.isEqual(12564504e5, new Date(2009, 9, 25)), 'Dates and their corresponding numeric primitive values are not equal'); + assert.ok(!_.isEqual(new Boolean(false), true), '`new Boolean(false)` is not equal to `true`'); + assert.ok(!_.isEqual('75', 75), 'String and number primitives with like values are not equal'); + assert.ok(!_.isEqual(new Number(63), new String(63)), 'String and number objects with like values are not equal'); + assert.ok(!_.isEqual(75, '75'), 'Commutative equality is implemented for like string and number values'); + assert.ok(!_.isEqual(0, ''), 'Number and string primitives with like values are not equal'); + assert.ok(!_.isEqual(1, true), 'Number and boolean primitives with like values are not equal'); + assert.ok(!_.isEqual(new Boolean(false), new Number(0)), 'Boolean and number objects with like values are not equal'); + assert.ok(!_.isEqual(false, new String('')), 'Boolean primitives and string objects with like values are not equal'); + assert.ok(!_.isEqual(12564504e5, new Date(2009, 9, 25)), 'Dates and their corresponding numeric primitive values are not equal'); // Dates. - ok(_.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), 'Date objects referencing identical times are equal'); - ok(!_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), 'Date objects referencing different times are not equal'); - ok(!_.isEqual(new Date(2009, 11, 13), { + assert.ok(_.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), 'Date objects referencing identical times are equal'); + assert.ok(!_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), 'Date objects referencing different times are not equal'); + assert.ok(!_.isEqual(new Date(2009, 11, 13), { getTime: function(){ return 12606876e5; } }), 'Date objects and objects with a `getTime` method are not equal'); - ok(!_.isEqual(new Date('Curly'), new Date('Curly')), 'Invalid dates are not equal'); + assert.ok(!_.isEqual(new Date('Curly'), new Date('Curly')), 'Invalid dates are not equal'); // Functions. - ok(!_.isEqual(First, Second), 'Different functions with identical bodies and source code representations are not equal'); + assert.ok(!_.isEqual(First, Second), 'Different functions with identical bodies and source code representations are not equal'); // RegExps. - ok(_.isEqual(/(?:)/gim, /(?:)/gim), 'RegExps with equivalent patterns and flags are equal'); - ok(_.isEqual(/(?:)/gi, /(?:)/ig), 'Flag order is not significant'); - ok(!_.isEqual(/(?:)/g, /(?:)/gi), 'RegExps with equivalent patterns and different flags are not equal'); - ok(!_.isEqual(/Moe/gim, /Curly/gim), 'RegExps with different patterns and equivalent flags are not equal'); - ok(!_.isEqual(/(?:)/gi, /(?:)/g), 'Commutative equality is implemented for RegExps'); - ok(!_.isEqual(/Curly/g, {source: 'Larry', global: true, ignoreCase: false, multiline: false}), 'RegExps and RegExp-like objects are not equal'); + assert.ok(_.isEqual(/(?:)/gim, /(?:)/gim), 'RegExps with equivalent patterns and flags are equal'); + assert.ok(_.isEqual(/(?:)/gi, /(?:)/ig), 'Flag order is not significant'); + assert.ok(!_.isEqual(/(?:)/g, /(?:)/gi), 'RegExps with equivalent patterns and different flags are not equal'); + assert.ok(!_.isEqual(/Moe/gim, /Curly/gim), 'RegExps with different patterns and equivalent flags are not equal'); + assert.ok(!_.isEqual(/(?:)/gi, /(?:)/g), 'Commutative equality is implemented for RegExps'); + assert.ok(!_.isEqual(/Curly/g, {source: 'Larry', global: true, ignoreCase: false, multiline: false}), 'RegExps and RegExp-like objects are not equal'); // Empty arrays, array-like objects, and object literals. - ok(_.isEqual({}, {}), 'Empty object literals are equal'); - ok(_.isEqual([], []), 'Empty array literals are equal'); - ok(_.isEqual([{}], [{}]), 'Empty nested arrays and objects are equal'); - ok(!_.isEqual({length: 0}, []), 'Array-like objects and arrays are not equal.'); - ok(!_.isEqual([], {length: 0}), 'Commutative equality is implemented for array-like objects'); + assert.ok(_.isEqual({}, {}), 'Empty object literals are equal'); + assert.ok(_.isEqual([], []), 'Empty array literals are equal'); + assert.ok(_.isEqual([{}], [{}]), 'Empty nested arrays and objects are equal'); + assert.ok(!_.isEqual({length: 0}, []), 'Array-like objects and arrays are not equal.'); + assert.ok(!_.isEqual([], {length: 0}), 'Commutative equality is implemented for array-like objects'); - ok(!_.isEqual({}, []), 'Object literals and array literals are not equal'); - ok(!_.isEqual([], {}), 'Commutative equality is implemented for objects and arrays'); + assert.ok(!_.isEqual({}, []), 'Object literals and array literals are not equal'); + assert.ok(!_.isEqual([], {}), 'Commutative equality is implemented for objects and arrays'); // Arrays with primitive and object values. - ok(_.isEqual([1, 'Larry', true], [1, 'Larry', true]), 'Arrays containing identical primitives are equal'); - ok(_.isEqual([/Moe/g, new Date(2009, 9, 25)], [/Moe/g, new Date(2009, 9, 25)]), 'Arrays containing equivalent elements are equal'); + assert.ok(_.isEqual([1, 'Larry', true], [1, 'Larry', true]), 'Arrays containing identical primitives are equal'); + assert.ok(_.isEqual([/Moe/g, new Date(2009, 9, 25)], [/Moe/g, new Date(2009, 9, 25)]), 'Arrays containing equivalent elements are equal'); // Multi-dimensional arrays. var a = [new Number(47), false, 'Larry', /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}]; var b = [new Number(47), false, 'Larry', /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}]; - ok(_.isEqual(a, b), 'Arrays containing nested arrays and objects are recursively compared'); + assert.ok(_.isEqual(a, b), 'Arrays containing nested arrays and objects are recursively compared'); // Overwrite the methods defined in ES 5.1 section 15.4.4. a.forEach = a.map = a.filter = a.every = a.indexOf = a.lastIndexOf = a.some = a.reduce = a.reduceRight = null; b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null; // Array elements and properties. - ok(_.isEqual(a, b), 'Arrays containing equivalent elements and different non-numeric properties are equal'); + assert.ok(_.isEqual(a, b), 'Arrays containing equivalent elements and different non-numeric properties are equal'); a.push('White Rocks'); - ok(!_.isEqual(a, b), 'Arrays of different lengths are not equal'); + assert.ok(!_.isEqual(a, b), 'Arrays of different lengths are not equal'); a.push('East Boulder'); b.push('Gunbarrel Ranch', 'Teller Farm'); - ok(!_.isEqual(a, b), 'Arrays of identical lengths containing different elements are not equal'); + assert.ok(!_.isEqual(a, b), 'Arrays of identical lengths containing different elements are not equal'); // Sparse arrays. - ok(_.isEqual(Array(3), Array(3)), 'Sparse arrays of identical lengths are equal'); - ok(!_.isEqual(Array(3), Array(6)), 'Sparse arrays of different lengths are not equal when both are empty'); + assert.ok(_.isEqual(Array(3), Array(3)), 'Sparse arrays of identical lengths are equal'); + assert.ok(!_.isEqual(Array(3), Array(6)), 'Sparse arrays of different lengths are not equal when both are empty'); var sparse = []; sparse[1] = 5; - ok(_.isEqual(sparse, [void 0, 5]), 'Handles sparse arrays as dense'); + assert.ok(_.isEqual(sparse, [void 0, 5]), 'Handles sparse arrays as dense'); // Simple objects. - ok(_.isEqual({a: 'Curly', b: 1, c: true}, {a: 'Curly', b: 1, c: true}), 'Objects containing identical primitives are equal'); - ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), 'Objects containing equivalent members are equal'); - ok(!_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), 'Objects of identical sizes with different values are not equal'); - ok(!_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), 'Objects of identical sizes with different property names are not equal'); - ok(!_.isEqual({a: 1, b: 2}, {a: 1}), 'Objects of different sizes are not equal'); - ok(!_.isEqual({a: 1}, {a: 1, b: 2}), 'Commutative equality is implemented for objects'); - ok(!_.isEqual({x: 1, y: void 0}, {x: 1, z: 2}), 'Objects with identical keys and different values are not equivalent'); + assert.ok(_.isEqual({a: 'Curly', b: 1, c: true}, {a: 'Curly', b: 1, c: true}), 'Objects containing identical primitives are equal'); + assert.ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), 'Objects containing equivalent members are equal'); + assert.ok(!_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), 'Objects of identical sizes with different values are not equal'); + assert.ok(!_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), 'Objects of identical sizes with different property names are not equal'); + assert.ok(!_.isEqual({a: 1, b: 2}, {a: 1}), 'Objects of different sizes are not equal'); + assert.ok(!_.isEqual({a: 1}, {a: 1, b: 2}), 'Commutative equality is implemented for objects'); + assert.ok(!_.isEqual({x: 1, y: void 0}, {x: 1, z: 2}), 'Objects with identical keys and different values are not equivalent'); // `A` contains nested objects and arrays. a = { @@ -471,456 +475,460 @@ seconds: 54 } }; - ok(_.isEqual(a, b), 'Objects with nested equivalent members are recursively compared'); + assert.ok(_.isEqual(a, b), 'Objects with nested equivalent members are recursively compared'); // Instances. - ok(_.isEqual(new First, new First), 'Object instances are equal'); - ok(!_.isEqual(new First, new Second), 'Objects with different constructors and identical own properties are not equal'); - ok(!_.isEqual({value: 1}, new First), 'Object instances and objects sharing equivalent properties are not equal'); - ok(!_.isEqual({value: 2}, new Second), 'The prototype chain of objects should not be examined'); + assert.ok(_.isEqual(new First, new First), 'Object instances are equal'); + assert.ok(!_.isEqual(new First, new Second), 'Objects with different constructors and identical own properties are not equal'); + assert.ok(!_.isEqual({value: 1}, new First), 'Object instances and objects sharing equivalent properties are not equal'); + assert.ok(!_.isEqual({value: 2}, new Second), 'The prototype chain of objects should not be examined'); // Circular Arrays. (a = []).push(a); (b = []).push(b); - ok(_.isEqual(a, b), 'Arrays containing circular references are equal'); + assert.ok(_.isEqual(a, b), 'Arrays containing circular references are equal'); a.push(new String('Larry')); b.push(new String('Larry')); - ok(_.isEqual(a, b), 'Arrays containing circular references and equivalent properties are equal'); + assert.ok(_.isEqual(a, b), 'Arrays containing circular references and equivalent properties are equal'); a.push('Shemp'); b.push('Curly'); - ok(!_.isEqual(a, b), 'Arrays containing circular references and different properties are not equal'); + assert.ok(!_.isEqual(a, b), 'Arrays containing circular references and different properties are not equal'); // More circular arrays #767. a = ['everything is checked but', 'this', 'is not']; a[1] = a; b = ['everything is checked but', ['this', 'array'], 'is not']; - ok(!_.isEqual(a, b), 'Comparison of circular references with non-circular references are not equal'); + assert.ok(!_.isEqual(a, b), 'Comparison of circular references with non-circular references are not equal'); // Circular Objects. a = {abc: null}; b = {abc: null}; a.abc = a; b.abc = b; - ok(_.isEqual(a, b), 'Objects containing circular references are equal'); + assert.ok(_.isEqual(a, b), 'Objects containing circular references are equal'); a.def = 75; b.def = 75; - ok(_.isEqual(a, b), 'Objects containing circular references and equivalent properties are equal'); + assert.ok(_.isEqual(a, b), 'Objects containing circular references and equivalent properties are equal'); a.def = new Number(75); b.def = new Number(63); - ok(!_.isEqual(a, b), 'Objects containing circular references and different properties are not equal'); + assert.ok(!_.isEqual(a, b), 'Objects containing circular references and different properties are not equal'); // More circular objects #767. a = {everything: 'is checked', but: 'this', is: 'not'}; a.but = a; b = {everything: 'is checked', but: {that: 'object'}, is: 'not'}; - ok(!_.isEqual(a, b), 'Comparison of circular references with non-circular object references are not equal'); + assert.ok(!_.isEqual(a, b), 'Comparison of circular references with non-circular object references are not equal'); // Cyclic Structures. a = [{abc: null}]; b = [{abc: null}]; (a[0].abc = a).push(a); (b[0].abc = b).push(b); - ok(_.isEqual(a, b), 'Cyclic structures are equal'); + assert.ok(_.isEqual(a, b), 'Cyclic structures are equal'); a[0].def = 'Larry'; b[0].def = 'Larry'; - ok(_.isEqual(a, b), 'Cyclic structures containing equivalent properties are equal'); + assert.ok(_.isEqual(a, b), 'Cyclic structures containing equivalent properties are equal'); a[0].def = new String('Larry'); b[0].def = new String('Curly'); - ok(!_.isEqual(a, b), 'Cyclic structures containing different properties are not equal'); + assert.ok(!_.isEqual(a, b), 'Cyclic structures containing different properties are not equal'); // Complex Circular References. a = {foo: {b: {foo: {c: {foo: null}}}}}; b = {foo: {b: {foo: {c: {foo: null}}}}}; a.foo.b.foo.c.foo = a; b.foo.b.foo.c.foo = b; - ok(_.isEqual(a, b), 'Cyclic structures with nested and identically-named properties are equal'); + assert.ok(_.isEqual(a, b), 'Cyclic structures with nested and identically-named properties are equal'); // Chaining. - ok(!_.isEqual(_({x: 1, y: void 0}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal'); + assert.ok(!_.isEqual(_({x: 1, y: void 0}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal'); a = _({x: 1, y: 2}).chain(); b = _({x: 1, y: 2}).chain(); - equal(_.isEqual(a.isEqual(b), _(true)), true, '`isEqual` can be chained'); + assert.equal(_.isEqual(a.isEqual(b), _(true)), true, '`isEqual` can be chained'); // Objects without a `constructor` property if (Object.create) { a = Object.create(null, {x: {value: 1, enumerable: true}}); b = {x: 1}; - ok(_.isEqual(a, b), 'Handles objects without a constructor (e.g. from Object.create'); + assert.ok(_.isEqual(a, b), 'Handles objects without a constructor (e.g. from Object.create'); } function Foo() { this.a = 1; } Foo.prototype.constructor = null; var other = {a: 1}; - strictEqual(_.isEqual(new Foo, other), false, 'Objects from different constructors are not equal'); + assert.strictEqual(_.isEqual(new Foo, other), false, 'Objects from different constructors are not equal'); // Tricky object cases val comparisions - equal(_.isEqual([0], [-0]), false); - equal(_.isEqual({a: 0}, {a: -0}), false); - equal(_.isEqual([NaN], [NaN]), true); - equal(_.isEqual({a: NaN}, {a: NaN}), true); + assert.equal(_.isEqual([0], [-0]), false); + assert.equal(_.isEqual({a: 0}, {a: -0}), false); + assert.equal(_.isEqual([NaN], [NaN]), true); + assert.equal(_.isEqual({a: NaN}, {a: NaN}), true); }); - test('isEmpty', function() { - ok(!_([1]).isEmpty(), '[1] is not empty'); - ok(_.isEmpty([]), '[] is empty'); - ok(!_.isEmpty({one: 1}), '{one: 1} is not empty'); - ok(_.isEmpty({}), '{} is empty'); - ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty'); - ok(_.isEmpty(null), 'null is empty'); - ok(_.isEmpty(), 'undefined is empty'); - ok(_.isEmpty(''), 'the empty string is empty'); - ok(!_.isEmpty('moe'), 'but other strings are not'); + test('isEmpty', function(assert) { + assert.ok(!_([1]).isEmpty(), '[1] is not empty'); + assert.ok(_.isEmpty([]), '[] is empty'); + assert.ok(!_.isEmpty({one: 1}), '{one: 1} is not empty'); + assert.ok(_.isEmpty({}), '{} is empty'); + assert.ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty'); + assert.ok(_.isEmpty(null), 'null is empty'); + assert.ok(_.isEmpty(), 'undefined is empty'); + assert.ok(_.isEmpty(''), 'the empty string is empty'); + assert.ok(!_.isEmpty('moe'), 'but other strings are not'); var obj = {one: 1}; delete obj.one; - ok(_.isEmpty(obj), 'deleting all the keys from an object empties it'); + assert.ok(_.isEmpty(obj), 'deleting all the keys from an object empties it'); var args = function(){ return arguments; }; - ok(_.isEmpty(args()), 'empty arguments object is empty'); - ok(!_.isEmpty(args('')), 'non-empty arguments object is not empty'); + assert.ok(_.isEmpty(args()), 'empty arguments object is empty'); + assert.ok(!_.isEmpty(args('')), 'non-empty arguments object is not empty'); // covers collecting non-enumerable properties in IE < 9 var nonEnumProp = {toString: 5}; - ok(!_.isEmpty(nonEnumProp), 'non-enumerable property is not empty'); + assert.ok(!_.isEmpty(nonEnumProp), 'non-enumerable property is not empty'); }); if (typeof document === 'object') { - test('isElement', function() { - ok(!_.isElement('div'), 'strings are not dom elements'); - ok(_.isElement(testElement), 'an element is a DOM element'); + test('isElement', function(assert) { + assert.ok(!_.isElement('div'), 'strings are not dom elements'); + assert.ok(_.isElement(testElement), 'an element is a DOM element'); }); } - test('isArguments', function() { + test('isArguments', function(assert) { var args = (function(){ return arguments; }(1, 2, 3)); - ok(!_.isArguments('string'), 'a string is not an arguments object'); - ok(!_.isArguments(_.isArguments), 'a function is not an arguments object'); - ok(_.isArguments(args), 'but the arguments object is an arguments object'); - ok(!_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array'); - ok(!_.isArguments([1, 2, 3]), 'and not vanilla arrays.'); + assert.ok(!_.isArguments('string'), 'a string is not an arguments object'); + assert.ok(!_.isArguments(_.isArguments), 'a function is not an arguments object'); + assert.ok(_.isArguments(args), 'but the arguments object is an arguments object'); + assert.ok(!_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array'); + assert.ok(!_.isArguments([1, 2, 3]), 'and not vanilla arrays.'); }); - test('isObject', function() { - ok(_.isObject(arguments), 'the arguments object is object'); - ok(_.isObject([1, 2, 3]), 'and arrays'); + test('isObject', function(assert) { + assert.ok(_.isObject(arguments), 'the arguments object is object'); + assert.ok(_.isObject([1, 2, 3]), 'and arrays'); if (testElement) { - ok(_.isObject(testElement), 'and DOM element'); + assert.ok(_.isObject(testElement), 'and DOM element'); } - ok(_.isObject(function() {}), 'and functions'); - ok(!_.isObject(null), 'but not null'); - ok(!_.isObject(void 0), 'and not undefined'); - ok(!_.isObject('string'), 'and not string'); - ok(!_.isObject(12), 'and not number'); - ok(!_.isObject(true), 'and not boolean'); - ok(_.isObject(new String('string')), 'but new String()'); + assert.ok(_.isObject(function() {}), 'and functions'); + assert.ok(!_.isObject(null), 'but not null'); + assert.ok(!_.isObject(void 0), 'and not undefined'); + assert.ok(!_.isObject('string'), 'and not string'); + assert.ok(!_.isObject(12), 'and not number'); + assert.ok(!_.isObject(true), 'and not boolean'); + assert.ok(_.isObject(new String('string')), 'but new String()'); }); - test('isArray', function() { - ok(!_.isArray(void 0), 'undefined vars are not arrays'); - ok(!_.isArray(arguments), 'the arguments object is not an array'); - ok(_.isArray([1, 2, 3]), 'but arrays are'); + test('isArray', function(assert) { + assert.ok(!_.isArray(void 0), 'undefined vars are not arrays'); + assert.ok(!_.isArray(arguments), 'the arguments object is not an array'); + assert.ok(_.isArray([1, 2, 3]), 'but arrays are'); }); - test('isString', function() { + test('isString', function(assert) { var obj = new String('I am a string object'); if (testElement) { - ok(!_.isString(testElement), 'an element is not a string'); + assert.ok(!_.isString(testElement), 'an element is not a string'); } - ok(_.isString([1, 2, 3].join(', ')), 'but strings are'); - strictEqual(_.isString('I am a string literal'), true, 'string literals are'); - ok(_.isString(obj), 'so are String objects'); - strictEqual(_.isString(1), false); + assert.ok(_.isString([1, 2, 3].join(', ')), 'but strings are'); + assert.strictEqual(_.isString('I am a string literal'), true, 'string literals are'); + assert.ok(_.isString(obj), 'so are String objects'); + assert.strictEqual(_.isString(1), false); }); - test('isNumber', function() { - ok(!_.isNumber('string'), 'a string is not a number'); - ok(!_.isNumber(arguments), 'the arguments object is not a number'); - ok(!_.isNumber(void 0), 'undefined is not a number'); - ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are'); - ok(_.isNumber(NaN), 'NaN *is* a number'); - ok(_.isNumber(Infinity), 'Infinity is a number'); - ok(!_.isNumber('1'), 'numeric strings are not numbers'); + test('isNumber', function(assert) { + assert.ok(!_.isNumber('string'), 'a string is not a number'); + assert.ok(!_.isNumber(arguments), 'the arguments object is not a number'); + assert.ok(!_.isNumber(void 0), 'undefined is not a number'); + assert.ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are'); + assert.ok(_.isNumber(NaN), 'NaN *is* a number'); + assert.ok(_.isNumber(Infinity), 'Infinity is a number'); + assert.ok(!_.isNumber('1'), 'numeric strings are not numbers'); }); - test('isBoolean', function() { - ok(!_.isBoolean(2), 'a number is not a boolean'); - ok(!_.isBoolean('string'), 'a string is not a boolean'); - ok(!_.isBoolean('false'), 'the string "false" is not a boolean'); - ok(!_.isBoolean('true'), 'the string "true" is not a boolean'); - ok(!_.isBoolean(arguments), 'the arguments object is not a boolean'); - ok(!_.isBoolean(void 0), 'undefined is not a boolean'); - ok(!_.isBoolean(NaN), 'NaN is not a boolean'); - ok(!_.isBoolean(null), 'null is not a boolean'); - ok(_.isBoolean(true), 'but true is'); - ok(_.isBoolean(false), 'and so is false'); + test('isBoolean', function(assert) { + assert.ok(!_.isBoolean(2), 'a number is not a boolean'); + assert.ok(!_.isBoolean('string'), 'a string is not a boolean'); + assert.ok(!_.isBoolean('false'), 'the string "false" is not a boolean'); + assert.ok(!_.isBoolean('true'), 'the string "true" is not a boolean'); + assert.ok(!_.isBoolean(arguments), 'the arguments object is not a boolean'); + assert.ok(!_.isBoolean(void 0), 'undefined is not a boolean'); + assert.ok(!_.isBoolean(NaN), 'NaN is not a boolean'); + assert.ok(!_.isBoolean(null), 'null is not a boolean'); + assert.ok(_.isBoolean(true), 'but true is'); + assert.ok(_.isBoolean(false), 'and so is false'); }); - test('isFunction', function() { - ok(!_.isFunction(void 0), 'undefined vars are not functions'); - ok(!_.isFunction([1, 2, 3]), 'arrays are not functions'); - ok(!_.isFunction('moe'), 'strings are not functions'); - ok(_.isFunction(_.isFunction), 'but functions are'); - ok(_.isFunction(function(){}), 'even anonymous ones'); + test('isFunction', function(assert) { + assert.ok(!_.isFunction(void 0), 'undefined vars are not functions'); + assert.ok(!_.isFunction([1, 2, 3]), 'arrays are not functions'); + assert.ok(!_.isFunction('moe'), 'strings are not functions'); + assert.ok(_.isFunction(_.isFunction), 'but functions are'); + assert.ok(_.isFunction(function(){}), 'even anonymous ones'); if (testElement) { - ok(!_.isFunction(testElement), 'elements are not functions'); + assert.ok(!_.isFunction(testElement), 'elements are not functions'); } var nodelist = typeof document != 'undefined' && document.childNodes; if (nodelist) { - ok(!_.isFunction(nodelist)); + assert.ok(!_.isFunction(nodelist)); } }); if (typeof Int8Array !== 'undefined') { - test('#1929 Typed Array constructors are functions', function() { + test('#1929 Typed Array constructors are functions', function(assert) { _.chain(['Float32Array', 'Float64Array', 'Int8Array', 'Int16Array', 'Int32Array', 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array']) .map(_.propertyOf(typeof GLOBAL != 'undefined' ? GLOBAL : window)) .compact() .each(function(TypedArray) { // PhantomJS reports `typeof UInt8Array == 'object'` and doesn't report toString TypeArray // as a function - strictEqual(_.isFunction(TypedArray), Object.prototype.toString.call(TypedArray) === '[object Function]'); + assert.strictEqual(_.isFunction(TypedArray), Object.prototype.toString.call(TypedArray) === '[object Function]'); }); }); } - test('isDate', function() { - ok(!_.isDate(100), 'numbers are not dates'); - ok(!_.isDate({}), 'objects are not dates'); - ok(_.isDate(new Date()), 'but dates are'); + test('isDate', function(assert) { + assert.ok(!_.isDate(100), 'numbers are not dates'); + assert.ok(!_.isDate({}), 'objects are not dates'); + assert.ok(_.isDate(new Date()), 'but dates are'); }); - test('isRegExp', function() { - ok(!_.isRegExp(_.identity), 'functions are not RegExps'); - ok(_.isRegExp(/identity/), 'but RegExps are'); + test('isRegExp', function(assert) { + assert.ok(!_.isRegExp(_.identity), 'functions are not RegExps'); + assert.ok(_.isRegExp(/identity/), 'but RegExps are'); }); - test('isFinite', function() { - ok(!_.isFinite(void 0), 'undefined is not finite'); - ok(!_.isFinite(null), 'null is not finite'); - ok(!_.isFinite(NaN), 'NaN is not finite'); - ok(!_.isFinite(Infinity), 'Infinity is not finite'); - ok(!_.isFinite(-Infinity), '-Infinity is not finite'); - ok(_.isFinite('12'), 'Numeric strings are numbers'); - ok(!_.isFinite('1a'), 'Non numeric strings are not numbers'); - ok(!_.isFinite(''), 'Empty strings are not numbers'); + test('isFinite', function(assert) { + assert.ok(!_.isFinite(void 0), 'undefined is not finite'); + assert.ok(!_.isFinite(null), 'null is not finite'); + assert.ok(!_.isFinite(NaN), 'NaN is not finite'); + assert.ok(!_.isFinite(Infinity), 'Infinity is not finite'); + assert.ok(!_.isFinite(-Infinity), '-Infinity is not finite'); + assert.ok(_.isFinite('12'), 'Numeric strings are numbers'); + assert.ok(!_.isFinite('1a'), 'Non numeric strings are not numbers'); + assert.ok(!_.isFinite(''), 'Empty strings are not numbers'); var obj = new Number(5); - ok(_.isFinite(obj), 'Number instances can be finite'); - ok(_.isFinite(0), '0 is finite'); - ok(_.isFinite(123), 'Ints are finite'); - ok(_.isFinite(-12.44), 'Floats are finite'); + assert.ok(_.isFinite(obj), 'Number instances can be finite'); + assert.ok(_.isFinite(0), '0 is finite'); + assert.ok(_.isFinite(123), 'Ints are finite'); + assert.ok(_.isFinite(-12.44), 'Floats are finite'); }); - test('isNaN', function() { - ok(!_.isNaN(void 0), 'undefined is not NaN'); - ok(!_.isNaN(null), 'null is not NaN'); - ok(!_.isNaN(0), '0 is not NaN'); - ok(!_.isNaN(new Number(0)), 'wrapped 0 is not NaN'); - ok(_.isNaN(NaN), 'but NaN is'); - ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN'); + test('isNaN', function(assert) { + assert.ok(!_.isNaN(void 0), 'undefined is not NaN'); + assert.ok(!_.isNaN(null), 'null is not NaN'); + assert.ok(!_.isNaN(0), '0 is not NaN'); + assert.ok(!_.isNaN(new Number(0)), 'wrapped 0 is not NaN'); + assert.ok(_.isNaN(NaN), 'but NaN is'); + assert.ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN'); }); - test('isNull', function() { - ok(!_.isNull(void 0), 'undefined is not null'); - ok(!_.isNull(NaN), 'NaN is not null'); - ok(_.isNull(null), 'but null is'); + test('isNull', function(assert) { + assert.ok(!_.isNull(void 0), 'undefined is not null'); + assert.ok(!_.isNull(NaN), 'NaN is not null'); + assert.ok(_.isNull(null), 'but null is'); }); - test('isUndefined', function() { - ok(!_.isUndefined(1), 'numbers are defined'); - ok(!_.isUndefined(null), 'null is defined'); - ok(!_.isUndefined(false), 'false is defined'); - ok(!_.isUndefined(NaN), 'NaN is defined'); - ok(_.isUndefined(), 'nothing is undefined'); - ok(_.isUndefined(void 0), 'undefined is undefined'); + test('isUndefined', function(assert) { + assert.ok(!_.isUndefined(1), 'numbers are defined'); + assert.ok(!_.isUndefined(null), 'null is defined'); + assert.ok(!_.isUndefined(false), 'false is defined'); + assert.ok(!_.isUndefined(NaN), 'NaN is defined'); + assert.ok(_.isUndefined(), 'nothing is undefined'); + assert.ok(_.isUndefined(void 0), 'undefined is undefined'); }); - test('isError', function() { - ok(!_.isError(1), 'numbers are not Errors'); - ok(!_.isError(null), 'null is not an Error'); - ok(!_.isError(Error), 'functions are not Errors'); - ok(_.isError(new Error()), 'Errors are Errors'); - ok(_.isError(new EvalError()), 'EvalErrors are Errors'); - ok(_.isError(new RangeError()), 'RangeErrors are Errors'); - ok(_.isError(new ReferenceError()), 'ReferenceErrors are Errors'); - ok(_.isError(new SyntaxError()), 'SyntaxErrors are Errors'); - ok(_.isError(new TypeError()), 'TypeErrors are Errors'); - ok(_.isError(new URIError()), 'URIErrors are Errors'); + test('isError', function(assert) { + assert.ok(!_.isError(1), 'numbers are not Errors'); + assert.ok(!_.isError(null), 'null is not an Error'); + assert.ok(!_.isError(Error), 'functions are not Errors'); + assert.ok(_.isError(new Error()), 'Errors are Errors'); + assert.ok(_.isError(new EvalError()), 'EvalErrors are Errors'); + assert.ok(_.isError(new RangeError()), 'RangeErrors are Errors'); + assert.ok(_.isError(new ReferenceError()), 'ReferenceErrors are Errors'); + assert.ok(_.isError(new SyntaxError()), 'SyntaxErrors are Errors'); + assert.ok(_.isError(new TypeError()), 'TypeErrors are Errors'); + assert.ok(_.isError(new URIError()), 'URIErrors are Errors'); }); - test('tap', function() { + test('tap', function(assert) { var intercepted = null; var interceptor = function(obj) { intercepted = obj; }; var returned = _.tap(1, interceptor); - equal(intercepted, 1, 'passes tapped object to interceptor'); - equal(returned, 1, 'returns tapped object'); + assert.equal(intercepted, 1, 'passes tapped object to interceptor'); + assert.equal(returned, 1, 'returns tapped object'); returned = _([1, 2, 3]).chain(). map(function(n){ return n * 2; }). max(). tap(interceptor). value(); - equal(returned, 6, 'can use tapped objects in a chain'); - equal(intercepted, returned, 'can use tapped objects in a chain'); + assert.equal(returned, 6, 'can use tapped objects in a chain'); + assert.equal(intercepted, returned, 'can use tapped objects in a chain'); }); - test('has', function() { + test('has', function(assert) { var obj = {foo: 'bar', func: function(){}}; - ok(_.has(obj, 'foo'), 'has() checks that the object has a property.'); - ok(!_.has(obj, 'baz'), "has() returns false if the object doesn't have the property."); - ok(_.has(obj, 'func'), 'has() works for functions too.'); + assert.ok(_.has(obj, 'foo'), 'has() checks that the object has a property.'); + assert.ok(!_.has(obj, 'baz'), "has() returns false if the object doesn't have the property."); + assert.ok(_.has(obj, 'func'), 'has() works for functions too.'); obj.hasOwnProperty = null; - ok(_.has(obj, 'foo'), 'has() works even when the hasOwnProperty method is deleted.'); + assert.ok(_.has(obj, 'foo'), 'has() works even when the hasOwnProperty method is deleted.'); var child = {}; child.prototype = obj; - ok(!_.has(child, 'foo'), 'has() does not check the prototype chain for a property.'); - strictEqual(_.has(null, 'foo'), false, 'has() returns false for null'); - strictEqual(_.has(void 0, 'foo'), false, 'has() returns false for undefined'); + assert.ok(!_.has(child, 'foo'), 'has() does not check the prototype chain for a property.'); + assert.strictEqual(_.has(null, 'foo'), false, 'has() returns false for null'); + assert.strictEqual(_.has(void 0, 'foo'), false, 'has() returns false for undefined'); }); - test('isMatch', function() { + test('isMatch', function(assert) { var moe = {name: 'Moe Howard', hair: true}; var curly = {name: 'Curly Howard', hair: false}; - equal(_.isMatch(moe, {hair: true}), true, 'Returns a boolean'); - equal(_.isMatch(curly, {hair: true}), false, 'Returns a boolean'); + assert.equal(_.isMatch(moe, {hair: true}), true, 'Returns a boolean'); + assert.equal(_.isMatch(curly, {hair: true}), false, 'Returns a boolean'); - equal(_.isMatch(5, {__x__: void 0}), false, 'can match undefined props on primitives'); - equal(_.isMatch({__x__: void 0}, {__x__: void 0}), true, 'can match undefined props'); + assert.equal(_.isMatch(5, {__x__: void 0}), false, 'can match undefined props on primitives'); + assert.equal(_.isMatch({__x__: void 0}, {__x__: void 0}), true, 'can match undefined props'); - equal(_.isMatch(null, {}), true, 'Empty spec called with null object returns true'); - equal(_.isMatch(null, {a: 1}), false, 'Non-empty spec called with null object returns false'); + assert.equal(_.isMatch(null, {}), true, 'Empty spec called with null object returns true'); + assert.equal(_.isMatch(null, {a: 1}), false, 'Non-empty spec called with null object returns false'); - _.each([null, void 0], function(item) { strictEqual(_.isMatch(item, null), true, 'null matches null'); }); - _.each([null, void 0], function(item) { strictEqual(_.isMatch(item, null), true, 'null matches {}'); }); - strictEqual(_.isMatch({b: 1}, {a: void 0}), false, 'handles undefined values (1683)'); + _.each([null, void 0], function(item) { assert.strictEqual(_.isMatch(item, null), true, 'null matches null'); }); + _.each([null, void 0], function(item) { assert.strictEqual(_.isMatch(item, null), true, 'null matches {}'); }); + assert.strictEqual(_.isMatch({b: 1}, {a: void 0}), false, 'handles undefined values (1683)'); _.each([true, 5, NaN, null, void 0], function(item) { - strictEqual(_.isMatch({a: 1}, item), true, 'treats primitives as empty'); + assert.strictEqual(_.isMatch({a: 1}, item), true, 'treats primitives as empty'); }); function Prototest() {} Prototest.prototype.x = 1; var specObj = new Prototest; - equal(_.isMatch({x: 2}, specObj), true, 'spec is restricted to own properties'); + assert.equal(_.isMatch({x: 2}, specObj), true, 'spec is restricted to own properties'); specObj.y = 5; - equal(_.isMatch({x: 1, y: 5}, specObj), true); - equal(_.isMatch({x: 1, y: 4}, specObj), false); + assert.equal(_.isMatch({x: 1, y: 5}, specObj), true); + assert.equal(_.isMatch({x: 1, y: 4}, specObj), false); - ok(_.isMatch(specObj, {x: 1, y: 5}), 'inherited and own properties are checked on the test object'); + assert.ok(_.isMatch(specObj, {x: 1, y: 5}), 'inherited and own properties are checked on the test object'); Prototest.x = 5; - ok(_.isMatch({x: 5, y: 1}, Prototest), 'spec can be a function'); + assert.ok(_.isMatch({x: 5, y: 1}, Prototest), 'spec can be a function'); //null edge cases var oCon = {constructor: Object}; - deepEqual(_.map([null, void 0, 5, {}], _.partial(_.isMatch, _, oCon)), [false, false, false, true], 'doesnt falsey match constructor on undefined/null'); + assert.deepEqual(_.map([null, void 0, 5, {}], _.partial(_.isMatch, _, oCon)), [false, false, false, true], 'doesnt falsey match constructor on undefined/null'); }); - test('matcher', function() { + test('matcher', function(assert) { var moe = {name: 'Moe Howard', hair: true}; var curly = {name: 'Curly Howard', hair: false}; var stooges = [moe, curly]; - equal(_.matcher({hair: true})(moe), true, 'Returns a boolean'); - equal(_.matcher({hair: true})(curly), false, 'Returns a boolean'); + assert.equal(_.matcher({hair: true})(moe), true, 'Returns a boolean'); + assert.equal(_.matcher({hair: true})(curly), false, 'Returns a boolean'); - equal(_.matcher({__x__: void 0})(5), false, 'can match undefined props on primitives'); - equal(_.matcher({__x__: void 0})({__x__: void 0}), true, 'can match undefined props'); + assert.equal(_.matcher({__x__: void 0})(5), false, 'can match undefined props on primitives'); + assert.equal(_.matcher({__x__: void 0})({__x__: void 0}), true, 'can match undefined props'); - equal(_.matcher({})(null), true, 'Empty spec called with null object returns true'); - equal(_.matcher({a: 1})(null), false, 'Non-empty spec called with null object returns false'); + assert.equal(_.matcher({})(null), true, 'Empty spec called with null object returns true'); + assert.equal(_.matcher({a: 1})(null), false, 'Non-empty spec called with null object returns false'); - ok(_.find(stooges, _.matcher({hair: false})) === curly, 'returns a predicate that can be used by finding functions.'); - ok(_.find(stooges, _.matcher(moe)) === moe, 'can be used to locate an object exists in a collection.'); - deepEqual(_.where([null, void 0], {a: 1}), [], 'Do not throw on null values.'); + assert.ok(_.find(stooges, _.matcher({hair: false})) === curly, 'returns a predicate that can be used by finding functions.'); + assert.ok(_.find(stooges, _.matcher(moe)) === moe, 'can be used to locate an object exists in a collection.'); + assert.deepEqual(_.where([null, void 0], {a: 1}), [], 'Do not throw on null values.'); - deepEqual(_.where([null, void 0], null), [null, void 0], 'null matches null'); - deepEqual(_.where([null, void 0], {}), [null, void 0], 'null matches {}'); - deepEqual(_.where([{b: 1}], {a: void 0}), [], 'handles undefined values (1683)'); + assert.deepEqual(_.where([null, void 0], null), [null, void 0], 'null matches null'); + assert.deepEqual(_.where([null, void 0], {}), [null, void 0], 'null matches {}'); + assert.deepEqual(_.where([{b: 1}], {a: void 0}), [], 'handles undefined values (1683)'); _.each([true, 5, NaN, null, void 0], function(item) { - deepEqual(_.where([{a: 1}], item), [{a: 1}], 'treats primitives as empty'); + assert.deepEqual(_.where([{a: 1}], item), [{a: 1}], 'treats primitives as empty'); }); function Prototest() {} Prototest.prototype.x = 1; var specObj = new Prototest; var protospec = _.matcher(specObj); - equal(protospec({x: 2}), true, 'spec is restricted to own properties'); + assert.equal(protospec({x: 2}), true, 'spec is restricted to own properties'); specObj.y = 5; protospec = _.matcher(specObj); - equal(protospec({x: 1, y: 5}), true); - equal(protospec({x: 1, y: 4}), false); + assert.equal(protospec({x: 1, y: 5}), true); + assert.equal(protospec({x: 1, y: 4}), false); - ok(_.matcher({x: 1, y: 5})(specObj), 'inherited and own properties are checked on the test object'); + assert.ok(_.matcher({x: 1, y: 5})(specObj), 'inherited and own properties are checked on the test object'); Prototest.x = 5; - ok(_.matcher(Prototest)({x: 5, y: 1}), 'spec can be a function'); + assert.ok(_.matcher(Prototest)({x: 5, y: 1}), 'spec can be a function'); // #1729 var o = {b: 1}; var m = _.matcher(o); - equal(m({b: 1}), true); + assert.equal(m({b: 1}), true); o.b = 2; o.a = 1; - equal(m({b: 1}), true, 'changing spec object doesnt change matches result'); + assert.equal(m({b: 1}), true, 'changing spec object doesnt change matches result'); //null edge cases var oCon = _.matcher({constructor: Object}); - deepEqual(_.map([null, void 0, 5, {}], oCon), [false, false, false, true], 'doesnt falsey match constructor on undefined/null'); + assert.deepEqual(_.map([null, void 0, 5, {}], oCon), [false, false, false, true], 'doesnt falsey match constructor on undefined/null'); }); - test('findKey', function() { + test('matches', function(assert) { + assert.strictEqual(_.matches, _.matcher, 'is an alias for matcher'); + }); + + test('findKey', function(assert) { var objects = { a: {a: 0, b: 0}, b: {a: 1, b: 1}, c: {a: 2, b: 2} }; - equal(_.findKey(objects, function(obj) { + assert.equal(_.findKey(objects, function(obj) { return obj.a === 0; }), 'a'); - equal(_.findKey(objects, function(obj) { + assert.equal(_.findKey(objects, function(obj) { return obj.b * obj.a === 4; }), 'c'); - equal(_.findKey(objects, 'a'), 'b', 'Uses lookupIterator'); + assert.equal(_.findKey(objects, 'a'), 'b', 'Uses lookupIterator'); - equal(_.findKey(objects, function(obj) { + assert.equal(_.findKey(objects, function(obj) { return obj.b * obj.a === 5; }), void 0); - strictEqual(_.findKey([1, 2, 3, 4, 5, 6], function(obj) { + assert.strictEqual(_.findKey([1, 2, 3, 4, 5, 6], function(obj) { return obj === 3; }), '2', 'Keys are strings'); - strictEqual(_.findKey(objects, function(a) { + assert.strictEqual(_.findKey(objects, function(a) { return a.foo === null; }), void 0); _.findKey({a: {a: 1}}, function(a, key, obj) { - equal(key, 'a'); - deepEqual(obj, {a: {a: 1}}); - strictEqual(this, objects, 'called with context'); + assert.equal(key, 'a'); + assert.deepEqual(obj, {a: {a: 1}}); + assert.strictEqual(this, objects, 'called with context'); }, objects); var array = [1, 2, 3, 4]; array.match = 55; - strictEqual(_.findKey(array, function(x) { return x === 55; }), 'match', 'matches array-likes keys'); + assert.strictEqual(_.findKey(array, function(x) { return x === 55; }), 'match', 'matches array-likes keys'); }); - test('mapObject', function() { + test('mapObject', function(assert) { var obj = {a: 1, b: 2}; var objects = { a: {a: 0, b: 0}, @@ -928,49 +936,49 @@ c: {a: 2, b: 2} }; - deepEqual(_.mapObject(obj, function(val) { + assert.deepEqual(_.mapObject(obj, function(val) { return val * 2; }), {a: 2, b: 4}, 'simple objects'); - deepEqual(_.mapObject(objects, function(val) { + assert.deepEqual(_.mapObject(objects, function(val) { return _.reduce(val, function(memo, v){ return memo + v; }, 0); }), {a: 0, b: 2, c: 4}, 'nested objects'); - deepEqual(_.mapObject(obj, function(val, key, o) { + assert.deepEqual(_.mapObject(obj, function(val, key, o) { return o[key] * 2; }), {a: 2, b: 4}, 'correct keys'); - deepEqual(_.mapObject([1, 2], function(val) { + assert.deepEqual(_.mapObject([1, 2], function(val) { return val * 2; }), {0: 2, 1: 4}, 'check behavior for arrays'); - deepEqual(_.mapObject(obj, function(val) { + assert.deepEqual(_.mapObject(obj, function(val) { return val * this.multiplier; }, {multiplier: 3}), {a: 3, b: 6}, 'keep context'); - deepEqual(_.mapObject({a: 1}, function() { + assert.deepEqual(_.mapObject({a: 1}, function() { return this.length; }, [1, 2]), {a: 2}, 'called with context'); var ids = _.mapObject({length: 2, 0: {id: '1'}, 1: {id: '2'}}, function(n){ return n.id; }); - deepEqual(ids, {length: void 0, 0: '1', 1: '2'}, 'Check with array-like objects'); + assert.deepEqual(ids, {length: void 0, 0: '1', 1: '2'}, 'Check with array-like objects'); // Passing a property name like _.pluck. var people = {a: {name: 'moe', age: 30}, b: {name: 'curly', age: 50}}; - deepEqual(_.mapObject(people, 'name'), {a: 'moe', b: 'curly'}, 'predicate string map to object properties'); + assert.deepEqual(_.mapObject(people, 'name'), {a: 'moe', b: 'curly'}, 'predicate string map to object properties'); _.each([null, void 0, 1, 'abc', [], {}, void 0], function(val){ - deepEqual(_.mapObject(val, _.identity), {}, 'mapValue identity'); + assert.deepEqual(_.mapObject(val, _.identity), {}, 'mapValue identity'); }); var Proto = function(){ this.a = 1; }; Proto.prototype.b = 1; var protoObj = new Proto(); - deepEqual(_.mapObject(protoObj, _.identity), {a: 1}, 'ignore inherited values from prototypes'); + assert.deepEqual(_.mapObject(protoObj, _.identity), {a: 1}, 'ignore inherited values from prototypes'); }); }()); diff --git a/vendor/underscore/test/utility.js b/vendor/underscore/test/utility.js index 61c0347a4..09cd54d62 100644 --- a/vendor/underscore/test/utility.js +++ b/vendor/underscore/test/utility.js @@ -15,18 +15,20 @@ }); if (typeof this == 'object') { - test('noConflict', function() { + test('noConflict', function(assert) { var underscore = _.noConflict(); - equal(underscore.identity(1), 1); + assert.equal(underscore.identity(1), 1); if (typeof require != 'function') { - equal(this._, void 0, 'global underscore is removed'); + assert.equal(this._, void 0, 'global underscore is removed'); this._ = underscore; + } else if (typeof global !== 'undefined') { + delete global._; } }); } if (typeof require == 'function') { - asyncTest('noConflict (node vm)', 2, function() { + asyncTest('noConflict (node vm)', 2, function(assert) { var fs = require('fs'); var vm = require('vm'); var filename = __dirname + '/../underscore.js'; @@ -37,179 +39,179 @@ ); var context = {_: 'oldvalue'}; sandbox.runInNewContext(context); - equal(context._, 'oldvalue'); - equal(context.underscore.VERSION, _.VERSION); + assert.equal(context._, 'oldvalue'); + assert.equal(context.underscore.VERSION, _.VERSION); start(); }); }); } - test('#750 - Return _ instance.', 2, function() { + test('#750 - Return _ instance.', 2, function(assert) { var instance = _([]); - ok(_(instance) === instance); - ok(new _(instance) === instance); + assert.ok(_(instance) === instance); + assert.ok(new _(instance) === instance); }); - test('identity', function() { + test('identity', function(assert) { var stooge = {name: 'moe'}; - equal(_.identity(stooge), stooge, 'stooge is the same as his identity'); + assert.equal(_.identity(stooge), stooge, 'stooge is the same as his identity'); }); - test('constant', function() { + test('constant', function(assert) { var stooge = {name: 'moe'}; - equal(_.constant(stooge)(), stooge, 'should create a function that returns stooge'); + assert.equal(_.constant(stooge)(), stooge, 'should create a function that returns stooge'); }); - test('noop', function() { - strictEqual(_.noop('curly', 'larry', 'moe'), void 0, 'should always return undefined'); + test('noop', function(assert) { + assert.strictEqual(_.noop('curly', 'larry', 'moe'), void 0, 'should always return undefined'); }); - test('property', function() { + test('property', function(assert) { var stooge = {name: 'moe'}; - equal(_.property('name')(stooge), 'moe', 'should return the property with the given name'); - equal(_.property('name')(null), void 0, 'should return undefined for null values'); - equal(_.property('name')(void 0), void 0, 'should return undefined for undefined values'); + assert.equal(_.property('name')(stooge), 'moe', 'should return the property with the given name'); + assert.equal(_.property('name')(null), void 0, 'should return undefined for null values'); + assert.equal(_.property('name')(void 0), void 0, 'should return undefined for undefined values'); }); - test('propertyOf', function() { + test('propertyOf', function(assert) { var stoogeRanks = _.propertyOf({curly: 2, moe: 1, larry: 3}); - equal(stoogeRanks('curly'), 2, 'should return the property with the given name'); - equal(stoogeRanks(null), void 0, 'should return undefined for null values'); - equal(stoogeRanks(void 0), void 0, 'should return undefined for undefined values'); + assert.equal(stoogeRanks('curly'), 2, 'should return the property with the given name'); + assert.equal(stoogeRanks(null), void 0, 'should return undefined for null values'); + assert.equal(stoogeRanks(void 0), void 0, 'should return undefined for undefined values'); function MoreStooges() { this.shemp = 87; } MoreStooges.prototype = {curly: 2, moe: 1, larry: 3}; var moreStoogeRanks = _.propertyOf(new MoreStooges()); - equal(moreStoogeRanks('curly'), 2, 'should return properties from further up the prototype chain'); + assert.equal(moreStoogeRanks('curly'), 2, 'should return properties from further up the prototype chain'); var nullPropertyOf = _.propertyOf(null); - equal(nullPropertyOf('curly'), void 0, 'should return undefined when obj is null'); + assert.equal(nullPropertyOf('curly'), void 0, 'should return undefined when obj is null'); var undefPropertyOf = _.propertyOf(void 0); - equal(undefPropertyOf('curly'), void 0, 'should return undefined when obj is undefined'); + assert.equal(undefPropertyOf('curly'), void 0, 'should return undefined when obj is undefined'); }); - test('random', function() { + test('random', function(assert) { var array = _.range(1000); var min = Math.pow(2, 31); var max = Math.pow(2, 62); - ok(_.every(array, function() { + assert.ok(_.every(array, function() { return _.random(min, max) >= min; }), 'should produce a random number greater than or equal to the minimum number'); - ok(_.some(array, function() { + assert.ok(_.some(array, function() { return _.random(Number.MAX_VALUE) > 0; }), 'should produce a random number when passed `Number.MAX_VALUE`'); }); - test('now', function() { + test('now', function(assert) { var diff = _.now() - new Date().getTime(); - ok(diff <= 0 && diff > -5, 'Produces the correct time in milliseconds');//within 5ms + assert.ok(diff <= 0 && diff > -5, 'Produces the correct time in milliseconds');//within 5ms }); - test('uniqueId', function() { + test('uniqueId', function(assert) { var ids = [], i = 0; while (i++ < 100) ids.push(_.uniqueId()); - equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids'); + assert.equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids'); }); - test('times', function() { + test('times', function(assert) { var vals = []; _.times(3, function(i) { vals.push(i); }); - deepEqual(vals, [0, 1, 2], 'is 0 indexed'); + assert.deepEqual(vals, [0, 1, 2], 'is 0 indexed'); // vals = []; _(3).times(function(i) { vals.push(i); }); - deepEqual(vals, [0, 1, 2], 'works as a wrapper'); + assert.deepEqual(vals, [0, 1, 2], 'works as a wrapper'); // collects return values - deepEqual([0, 1, 2], _.times(3, function(i) { return i; }), 'collects return values'); + assert.deepEqual([0, 1, 2], _.times(3, function(i) { return i; }), 'collects return values'); - deepEqual(_.times(0, _.identity), []); - deepEqual(_.times(-1, _.identity), []); - deepEqual(_.times(parseFloat('-Infinity'), _.identity), []); + assert.deepEqual(_.times(0, _.identity), []); + assert.deepEqual(_.times(-1, _.identity), []); + assert.deepEqual(_.times(parseFloat('-Infinity'), _.identity), []); }); - test('mixin', function() { + test('mixin', function(assert) { _.mixin({ myReverse: function(string) { return string.split('').reverse().join(''); } }); - equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _'); - equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); + assert.equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _'); + assert.equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); }); - test('_.escape', function() { - equal(_.escape(null), ''); + test('_.escape', function(assert) { + assert.equal(_.escape(null), ''); }); - test('_.unescape', function() { + test('_.unescape', function(assert) { var string = 'Curly & Moe'; - equal(_.unescape(null), ''); - equal(_.unescape(_.escape(string)), string); - equal(_.unescape(string), string, 'don\'t unescape unnecessarily'); + assert.equal(_.unescape(null), ''); + assert.equal(_.unescape(_.escape(string)), string); + assert.equal(_.unescape(string), string, 'don\'t unescape unnecessarily'); }); // Don't care what they escape them to just that they're escaped and can be unescaped - test('_.escape & unescape', function() { + test('_.escape & unescape', function(assert) { // test & (&) seperately obviously var escapeCharacters = ['<', '>', '"', '\'', '`']; _.each(escapeCharacters, function(escapeChar) { var s = 'a ' + escapeChar + ' string escaped'; var e = _.escape(s); - notEqual(s, e, escapeChar + ' is escaped'); - equal(s, _.unescape(e), escapeChar + ' can be unescaped'); + assert.notEqual(s, e, escapeChar + ' is escaped'); + assert.equal(s, _.unescape(e), escapeChar + ' can be unescaped'); s = 'a ' + escapeChar + escapeChar + escapeChar + 'some more string' + escapeChar; e = _.escape(s); - equal(e.indexOf(escapeChar), -1, 'can escape multiple occurances of ' + escapeChar); - equal(_.unescape(e), s, 'multiple occurrences of ' + escapeChar + ' can be unescaped'); + assert.equal(e.indexOf(escapeChar), -1, 'can escape multiple occurances of ' + escapeChar); + assert.equal(_.unescape(e), s, 'multiple occurrences of ' + escapeChar + ' can be unescaped'); }); // handles multiple escape characters at once var joiner = ' other stuff '; var allEscaped = escapeCharacters.join(joiner); allEscaped += allEscaped; - ok(_.every(escapeCharacters, function(escapeChar) { + assert.ok(_.every(escapeCharacters, function(escapeChar) { return allEscaped.indexOf(escapeChar) !== -1; }), 'handles multiple characters'); - ok(allEscaped.indexOf(joiner) >= 0, 'can escape multiple escape characters at the same time'); + assert.ok(allEscaped.indexOf(joiner) >= 0, 'can escape multiple escape characters at the same time'); // test & -> & var str = 'some string & another string & yet another'; var escaped = _.escape(str); - ok(escaped.indexOf('&') !== -1, 'handles & aka &'); - equal(_.unescape(str), str, 'can unescape &'); + assert.ok(escaped.indexOf('&') !== -1, 'handles & aka &'); + assert.equal(_.unescape(str), str, 'can unescape &'); }); - test('template', function() { + test('template', function(assert) { var basicTemplate = _.template("<%= thing %> is gettin' on my noives!"); var result = basicTemplate({thing: 'This'}); - equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation'); + assert.equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation'); var sansSemicolonTemplate = _.template('A <% this %> B'); - equal(sansSemicolonTemplate(), 'A B'); + assert.equal(sansSemicolonTemplate(), 'A B'); var backslashTemplate = _.template('<%= thing %> is \\ridanculous'); - equal(backslashTemplate({thing: 'This'}), 'This is \\ridanculous'); + assert.equal(backslashTemplate({thing: 'This'}), 'This is \\ridanculous'); var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>'); - equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.'); + assert.equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.'); var fancyTemplate = _.template(''); result = fancyTemplate({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}}); - equal(result, '', 'can run arbitrary javascript in templates'); + assert.equal(result, '', 'can run arbitrary javascript in templates'); var escapedCharsInJavascriptTemplate = _.template(''); result = escapedCharsInJavascriptTemplate({numbers: 'one\ntwo\nthree\nfour'}); - equal(result, '', 'Can use escaped characters (e.g. \\n) in JavaScript'); + assert.equal(result, '', 'Can use escaped characters (e.g. \\n) in JavaScript'); var namespaceCollisionTemplate = _.template('<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %>
<% }); %>'); result = namespaceCollisionTemplate({ @@ -220,32 +222,32 @@ 3: 'p3-thumbnail.gif' } }); - equal(result, '3 p3-thumbnail.gif
'); + assert.equal(result, '3 p3-thumbnail.gif
'); var noInterpolateTemplate = _.template('

Just some text. Hey, I know this is silly but it aids consistency.

'); result = noInterpolateTemplate(); - equal(result, '

Just some text. Hey, I know this is silly but it aids consistency.

'); + assert.equal(result, '

Just some text. Hey, I know this is silly but it aids consistency.

'); var quoteTemplate = _.template("It's its, not it's"); - equal(quoteTemplate({}), "It's its, not it's"); + assert.equal(quoteTemplate({}), "It's its, not it's"); var quoteInStatementAndBody = _.template('<% ' + " if(foo == 'bar'){ " + "%>Statement quotes and 'quotes'.<% } %>"); - equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'."); + assert.equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'."); var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.'); - equal(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.'); + assert.equal(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.'); var template = _.template('<%- value %>'); result = template({value: '