Update vendors.

This commit is contained in:
John-David Dalton
2016-07-05 21:39:36 -07:00
parent 5669cc0a0b
commit 6eeac45d23
19 changed files with 515 additions and 373 deletions

View File

@@ -46,7 +46,7 @@
"markdown-doctest": "^0.8.1", "markdown-doctest": "^0.8.1",
"platform": "^1.3.1", "platform": "^1.3.1",
"qunit-extras": "^2.0.1", "qunit-extras": "^2.0.1",
"qunitjs": "^1.23.1", "qunitjs": "^2.0.0",
"request": "^2.69.0", "request": "^2.69.0",
"requirejs": "^2.2.0", "requirejs": "^2.2.0",
"sauce-tunnel": "^2.5.0", "sauce-tunnel": "^2.5.0",

View File

@@ -26472,8 +26472,6 @@
if (!document) { if (!document) {
QUnit.config.noglobals = true; QUnit.config.noglobals = true;
QUnit.load(); QUnit.load();
if (!QUnit.init) { QUnit.start();
QUnit.start();
}
} }
}.call(this)); }.call(this));

View File

@@ -56,9 +56,6 @@
'works on an arguments object', 'works on an arguments object',
'can handle very deep arrays' 'can handle very deep arrays'
], ],
'head': [
'is an alias for first'
],
'indexOf': [ 'indexOf': [
"sorted indexOf doesn't uses binary search", "sorted indexOf doesn't uses binary search",
'0' '0'
@@ -86,9 +83,6 @@
'an array of pairs zipped together into an object', 'an array of pairs zipped together into an object',
'an object converted to pairs and back to an object' 'an object converted to pairs and back to an object'
], ],
'range': [
'range with two arguments a & b, b<a generates an empty array'
],
'rest': [ 'rest': [
'returns the whole array when index is 0', 'returns the whole array when index is 0',
'returns elements starting at the given index', 'returns elements starting at the given index',
@@ -129,7 +123,8 @@
'Iterating objects with sketchy length properties': true, 'Iterating objects with sketchy length properties': true,
'Resistant to collection length and properties changing while iterating': true, 'Resistant to collection length and properties changing while iterating': true,
'countBy': [ 'countBy': [
'true' '{}',
'[{}]'
], ],
'each': [ 'each': [
'context object property accessed' 'context object property accessed'
@@ -141,24 +136,17 @@
], ],
'filter': [ 'filter': [
'given context', 'given context',
'[{"a":1,"b":2},{"a":1,"b":3},{"a":1,"b":4}]',
'[{"a":1,"b":2},{"a":2,"b":2}]',
'Empty object accepts all items',
'OO-filter' 'OO-filter'
], ],
'find': [ 'find': [
'{"a":1,"b":4}',
'undefined when not found',
'undefined when searching empty list',
'works on objects',
'undefined',
'called with context' 'called with context'
], ],
'findWhere': [ 'findWhere': [
'checks properties given function' 'checks properties given function'
], ],
'groupBy': [ 'groupBy': [
'true' '{}',
'[{}]'
], ],
'includes': [ 'includes': [
"doesn't delegate to binary search" "doesn't delegate to binary search"
@@ -198,8 +186,7 @@
'partition': [ 'partition': [
'can reference the array index', 'can reference the array index',
'Died on test #8', 'Died on test #8',
'partition takes a context argument', 'partition takes a context argument'
'function(a){[code]}'
], ],
'pluck': [ 'pluck': [
'[1]' '[1]'
@@ -223,8 +210,7 @@
'checks properties given function' 'checks properties given function'
], ],
'Can use various collection methods on NodeLists': [ 'Can use various collection methods on NodeLists': [
'<span id="id2"></span>', '<span id="id2"></span>'
'<span id="id1"></span>'
] ]
}, },
'Functions': { 'Functions': {
@@ -245,17 +231,14 @@
'bindAll': [ 'bindAll': [
'throws an error for bindAll with no functions named' 'throws an error for bindAll with no functions named'
], ],
'iteratee': [
'"bbiz"',
'"foo"',
'1'
],
'memoize': [ 'memoize': [
'{"bar":"BAR","foo":"FOO"}', '{"bar":"BAR","foo":"FOO"}',
'Died on test #8' 'Died on test #8'
],
'partial':[
'can partially apply with placeholders',
'accepts more arguments than the number of placeholders',
'accepts fewer arguments than the number of placeholders',
'unfilled placeholders are undefined',
'keeps prototype',
'allows the placeholder to be swapped out'
] ]
}, },
'Objects': { 'Objects': {
@@ -265,10 +248,6 @@
'is not fooled by sparse arrays with additional properties', 'is not fooled by sparse arrays with additional properties',
'[]' '[]'
], ],
'defaults': [
'defaults skips nulls',
'defaults skips undefined'
],
'extend': [ 'extend': [
'extending null results in null', 'extending null results in null',
'extending undefined results in undefined' 'extending undefined results in undefined'
@@ -292,12 +271,6 @@
'Numeric strings are numbers', 'Numeric strings are numbers',
'Number instances can be finite' 'Number instances can be finite'
], ],
'isMatch': [
'doesnt falsey match constructor on undefined/null'
],
'isSet': [
'Died on test #9'
],
'findKey': [ 'findKey': [
'called with context' 'called with context'
], ],
@@ -310,10 +283,6 @@
'called with context', 'called with context',
'mapValue identity' 'mapValue identity'
], ],
'matcher': [
'null matches null',
'treats primitives as empty'
],
'omit': [ 'omit': [
'can accept a predicate', 'can accept a predicate',
'function is given context' 'function is given context'
@@ -324,7 +293,6 @@
] ]
}, },
'Utility': { 'Utility': {
'noConflict (node vm)': true,
'now': [ 'now': [
'Produces the correct time in milliseconds' 'Produces the correct time in milliseconds'
], ],

View File

@@ -394,6 +394,7 @@
var Model = Backbone.Model = function(attributes, options) { var Model = Backbone.Model = function(attributes, options) {
var attrs = attributes || {}; var attrs = attributes || {};
options || (options = {}); options || (options = {});
this.preinitialize.apply(this, arguments);
this.cid = _.uniqueId(this.cidPrefix); this.cid = _.uniqueId(this.cidPrefix);
this.attributes = {}; this.attributes = {};
if (options.collection) this.collection = options.collection; if (options.collection) this.collection = options.collection;
@@ -422,6 +423,10 @@
// You may want to override this if you're experiencing name clashes with model ids. // You may want to override this if you're experiencing name clashes with model ids.
cidPrefix: 'c', cidPrefix: 'c',
// preinitialize is an empty function by default. You can override it with a function
// or object. preinitialize will run before any instantiation logic is run in the Model.
preinitialize: function(){},
// Initialize is an empty function by default. Override it with your own // Initialize is an empty function by default. Override it with your own
// initialization logic. // initialization logic.
initialize: function(){}, initialize: function(){},
@@ -562,12 +567,14 @@
if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
var old = this._changing ? this._previousAttributes : this.attributes; var old = this._changing ? this._previousAttributes : this.attributes;
var changed = {}; var changed = {};
var hasChanged;
for (var attr in diff) { for (var attr in diff) {
var val = diff[attr]; var val = diff[attr];
if (_.isEqual(old[attr], val)) continue; if (_.isEqual(old[attr], val)) continue;
changed[attr] = val; changed[attr] = val;
hasChanged = true;
} }
return _.size(changed) ? changed : false; return hasChanged ? changed : false;
}, },
// Get the previous value of an attribute, recorded at the time the last // Get the previous value of an attribute, recorded at the time the last
@@ -754,6 +761,7 @@
// its models in sort order, as they're added and removed. // its models in sort order, as they're added and removed.
var Collection = Backbone.Collection = function(models, options) { var Collection = Backbone.Collection = function(models, options) {
options || (options = {}); options || (options = {});
this.preinitialize.apply(this, arguments);
if (options.model) this.model = options.model; if (options.model) this.model = options.model;
if (options.comparator !== void 0) this.comparator = options.comparator; if (options.comparator !== void 0) this.comparator = options.comparator;
this._reset(); this._reset();
@@ -783,6 +791,11 @@
// This should be overridden in most cases. // This should be overridden in most cases.
model: Model, model: Model,
// preinitialize is an empty function by default. You can override it with a function
// or object. preinitialize will run before any instantiation logic is run in the Collection.
preinitialize: function(){},
// Initialize is an empty function by default. Override it with your own // Initialize is an empty function by default. Override it with your own
// initialization logic. // initialization logic.
initialize: function(){}, initialize: function(){},
@@ -1219,6 +1232,7 @@
// if an existing element is not provided... // if an existing element is not provided...
var View = Backbone.View = function(options) { var View = Backbone.View = function(options) {
this.cid = _.uniqueId('view'); this.cid = _.uniqueId('view');
this.preinitialize.apply(this, arguments);
_.extend(this, _.pick(options, viewOptions)); _.extend(this, _.pick(options, viewOptions));
this._ensureElement(); this._ensureElement();
this.initialize.apply(this, arguments); this.initialize.apply(this, arguments);
@@ -1242,6 +1256,10 @@
return this.$el.find(selector); return this.$el.find(selector);
}, },
// preinitialize is an empty function by default. You can override it with a function
// or object. preinitialize will run before any instantiation logic is run in the View
preinitialize: function(){},
// Initialize is an empty function by default. Override it with your own // Initialize is an empty function by default. Override it with your own
// initialization logic. // initialization logic.
initialize: function(){}, initialize: function(){},
@@ -1467,6 +1485,7 @@
// matched. Creating a new one sets its `routes` hash, if not set statically. // matched. Creating a new one sets its `routes` hash, if not set statically.
var Router = Backbone.Router = function(options) { var Router = Backbone.Router = function(options) {
options || (options = {}); options || (options = {});
this.preinitialize.apply(this, arguments);
if (options.routes) this.routes = options.routes; if (options.routes) this.routes = options.routes;
this._bindRoutes(); this._bindRoutes();
this.initialize.apply(this, arguments); this.initialize.apply(this, arguments);
@@ -1482,6 +1501,10 @@
// Set up all inheritable **Backbone.Router** properties and methods. // Set up all inheritable **Backbone.Router** properties and methods.
_.extend(Router.prototype, Events, { _.extend(Router.prototype, Events, {
// preinitialize is an empty function by default. You can override it with a function
// or object. preinitialize will run before any instantiation logic is run in the Router.
preinitialize: function(){},
// Initialize is an empty function by default. Override it with your own // Initialize is an empty function by default. Override it with your own
// initialization logic. // initialization logic.
initialize: function(){}, initialize: function(){},
@@ -1812,11 +1835,14 @@
} }
var url = rootPath + fragment; var url = rootPath + fragment;
// Strip the hash and decode for matching. // Strip the fragment of the query and hash for matching.
fragment = this.decodeFragment(fragment.replace(pathStripper, '')); fragment = fragment.replace(pathStripper, '');
if (this.fragment === fragment) return; // Decode for matching.
this.fragment = fragment; var decodedFragment = this.decodeFragment(fragment);
if (this.fragment === decodedFragment) return;
this.fragment = decodedFragment;
// If pushState is available, we use it to set the fragment as a real URL. // If pushState is available, we use it to set the fragment as a real URL.
if (this._usePushState) { if (this._usePushState) {

View File

@@ -1,4 +1,4 @@
(function() { (function(QUnit) {
var a, b, c, d, e, col, otherCol; var a, b, c, d, e, col, otherCol;
@@ -593,7 +593,7 @@
assert.equal(error, 'fail'); assert.equal(error, 'fail');
assert.equal(options.validationError, 'fail'); assert.equal(options.validationError, 'fail');
}); });
assert.equal(collection.create({'foo': 'bar'}, {validate: true}), false); assert.equal(collection.create({foo: 'bar'}, {validate: true}), false);
}); });
QUnit.test('create will pass extra options to success callback', function(assert) { QUnit.test('create will pass extra options to success callback', function(assert) {
@@ -661,6 +661,31 @@
assert.equal(coll.one, 1); assert.equal(coll.one, 1);
}); });
QUnit.test('preinitialize', function(assert) {
assert.expect(1);
var Collection = Backbone.Collection.extend({
preinitialize: function() {
this.one = 1;
}
});
var coll = new Collection;
assert.equal(coll.one, 1);
});
QUnit.test('preinitialize occurs before the collection is set up', function(assert) {
assert.expect(2);
var Collection = Backbone.Collection.extend({
preinitialize: function() {
assert.notEqual(this.model, FooModel);
}
});
var FooModel = Backbone.Model.extend({id: 'foo'});
var coll = new Collection({}, {
model: FooModel
});
assert.equal(coll.model, FooModel);
});
QUnit.test('toJSON', function(assert) { QUnit.test('toJSON', function(assert) {
assert.expect(1); assert.expect(1);
assert.equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]'); assert.equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]');
@@ -1724,10 +1749,10 @@
return new M(attrs); return new M(attrs);
} }
}); });
var c2 = new C2({'_id': 1}); var c2 = new C2({_id: 1});
assert.equal(c2.get(1), void 0); assert.equal(c2.get(1), void 0);
assert.equal(c2.modelId(c2.at(0).attributes), void 0); assert.equal(c2.modelId(c2.at(0).attributes), void 0);
var m = new M({'_id': 2}); var m = new M({_id: 2});
c2.add(m); c2.add(m);
assert.equal(c2.get(2), void 0); assert.equal(c2.get(2), void 0);
assert.equal(c2.modelId(m.attributes), void 0); assert.equal(c2.modelId(m.attributes), void 0);
@@ -1995,4 +2020,4 @@
assert.equal(fired, false); assert.equal(fired, false);
}); });
})(); })(QUnit);

View File

@@ -1,4 +1,4 @@
(function() { (function(QUnit) {
QUnit.module('Backbone.Events'); QUnit.module('Backbone.Events');
@@ -703,4 +703,4 @@
two.trigger('y', 2); two.trigger('y', 2);
}); });
})(); })(QUnit);

View File

@@ -1,4 +1,4 @@
(function() { (function(QUnit) {
var ProxyModel = Backbone.Model.extend(); var ProxyModel = Backbone.Model.extend();
var Klass = Backbone.Collection.extend({ var Klass = Backbone.Collection.extend({
@@ -63,6 +63,36 @@
assert.equal(model.get('value'), 2); assert.equal(model.get('value'), 2);
}); });
QUnit.test('preinitialize', function(assert) {
assert.expect(2);
var Model = Backbone.Model.extend({
preinitialize: function() {
this.one = 1;
}
});
var model = new Model({}, {collection: collection});
assert.equal(model.one, 1);
assert.equal(model.collection, collection);
});
QUnit.test('preinitialize occurs before the model is set up', function(assert) {
assert.expect(6);
var Model = Backbone.Model.extend({
preinitialize: function() {
assert.equal(this.collection, undefined);
assert.equal(this.cid, undefined);
assert.equal(this.id, undefined);
}
});
var model = new Model({id: 'foo'}, {collection: collection});
assert.equal(model.collection, collection);
assert.equal(model.id, 'foo');
assert.notEqual(model.cid, undefined);
});
QUnit.test('parse can return null', function(assert) { QUnit.test('parse can return null', function(assert) {
assert.expect(1); assert.expect(1);
var Model = Backbone.Model.extend({ var Model = Backbone.Model.extend({
@@ -1415,4 +1445,4 @@
assert.equal(model.id, 3); assert.equal(model.id, 3);
}); });
})(); })(QUnit);

View File

@@ -1,4 +1,4 @@
(function() { (function(QUnit) {
QUnit.module('Backbone.noConflict'); QUnit.module('Backbone.noConflict');
@@ -10,4 +10,4 @@
assert.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');
}); });
})(); })(QUnit);

View File

@@ -1,4 +1,4 @@
(function() { (function(QUnit) {
var router = null; var router = null;
var location = null; var location = null;
@@ -28,7 +28,8 @@
'fragment', 'fragment',
'pathname', 'pathname',
'protocol' 'protocol'
)); ));
// In IE, anchor.pathname does not contain a leading slash though // In IE, anchor.pathname does not contain a leading slash though
// window.location.pathname does. // window.location.pathname does.
if (!/^\//.test(this.pathname)) this.pathname = '/' + this.pathname; if (!/^\//.test(this.pathname)) this.pathname = '/' + this.pathname;
@@ -42,7 +43,7 @@
QUnit.module('Backbone.Router', { QUnit.module('Backbone.Router', {
setup: function() { beforeEach: function() {
location = new Location('http://example.com'); location = new Location('http://example.com');
Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history = _.extend(new Backbone.History, {location: location});
router = new Router({testing: 101}); router = new Router({testing: 101});
@@ -53,7 +54,7 @@
Backbone.history.on('route', onRoute); Backbone.history.on('route', onRoute);
}, },
teardown: function() { afterEach: function() {
Backbone.history.stop(); Backbone.history.stop();
Backbone.history.off('route', onRoute); Backbone.history.off('route', onRoute);
} }
@@ -95,6 +96,10 @@
'*anything': 'anything' '*anything': 'anything'
}, },
preinitialize: function(options) {
this.testpreinit = 'foo';
},
initialize: function(options) { initialize: function(options) {
this.testing = options.testing; this.testing = options.testing;
this.route('implicit', 'implicit'); this.route('implicit', 'implicit');
@@ -121,19 +126,19 @@
this.charType = 'escaped'; this.charType = 'escaped';
}, },
contacts: function(){ contacts: function() {
this.contact = 'index'; this.contact = 'index';
}, },
newContact: function(){ newContact: function() {
this.contact = 'new'; this.contact = 'new';
}, },
loadContact: function(){ loadContact: function() {
this.contact = 'load'; this.contact = 'load';
}, },
optionalItem: function(arg){ optionalItem: function(arg) {
this.arg = arg !== void 0 ? arg : null; this.arg = arg !== void 0 ? arg : null;
}, },
@@ -181,6 +186,11 @@
assert.equal(router.testing, 101); assert.equal(router.testing, 101);
}); });
QUnit.test('preinitialize', function(assert) {
assert.expect(1);
assert.equal(router.testpreinit, 'foo');
});
QUnit.test('routes (simple)', function(assert) { QUnit.test('routes (simple)', function(assert) {
assert.expect(4); assert.expect(4);
location.replace('http://example.com#search/news'); location.replace('http://example.com#search/news');
@@ -234,10 +244,11 @@
assert.ok(Backbone.history.navigate('search/manhattan/p20', true)); assert.ok(Backbone.history.navigate('search/manhattan/p20', true));
}); });
QUnit.test('route precedence via navigate', function(assert){ QUnit.test('route precedence via navigate', function(assert) {
assert.expect(6); assert.expect(6);
// check both 0.9.x and backwards-compatibility options
_.each([{trigger: true}, true], function( options ){ // Check both 0.9.x and backwards-compatibility options
_.each([{trigger: true}, true], function(options) {
Backbone.history.navigate('contacts', options); Backbone.history.navigate('contacts', options);
assert.equal(router.contact, 'index'); assert.equal(router.contact, 'index');
Backbone.history.navigate('contacts/new', options); Backbone.history.navigate('contacts/new', options);
@@ -249,7 +260,7 @@
QUnit.test('loadUrl is not called for identical routes.', function(assert) { QUnit.test('loadUrl is not called for identical routes.', function(assert) {
assert.expect(0); assert.expect(0);
Backbone.history.loadUrl = function(){ assert.ok(false); }; Backbone.history.loadUrl = function() { assert.ok(false); };
location.replace('http://example.com#route'); location.replace('http://example.com#route');
Backbone.history.navigate('route'); Backbone.history.navigate('route');
Backbone.history.navigate('/route'); Backbone.history.navigate('/route');
@@ -345,9 +356,9 @@
assert.strictEqual(router.path, 'c/d/e'); assert.strictEqual(router.path, 'c/d/e');
}); });
QUnit.test("fires event when router doesn't have callback on it", function(assert) { QUnit.test('fires event when router doesn\'t have callback on it', function(assert) {
assert.expect(1); assert.expect(1);
router.on('route:noCallback', function(){ assert.ok(true); }); router.on('route:noCallback', function() { assert.ok(true); });
location.replace('http://example.com#noCallback'); location.replace('http://example.com#noCallback');
Backbone.history.checkUrl(); Backbone.history.checkUrl();
}); });
@@ -536,8 +547,8 @@
Backbone.history = _.extend(new Backbone.History, { Backbone.history = _.extend(new Backbone.History, {
location: location, location: location,
history: { history: {
pushState: function(){}, pushState: function() {},
replaceState: function(){} replaceState: function() {}
} }
}); });
Backbone.history.start({root: 'root'}); Backbone.history.start({root: 'root'});
@@ -551,8 +562,8 @@
Backbone.history = _.extend(new Backbone.History, { Backbone.history = _.extend(new Backbone.History, {
location: location, location: location,
history: { history: {
pushState: function(){}, pushState: function() {},
replaceState: function(state, title, url){ replaceState: function(state, title, url) {
assert.strictEqual(url, '/root/x/y'); assert.strictEqual(url, '/root/x/y');
} }
} }
@@ -570,8 +581,8 @@
Backbone.history = _.extend(new Backbone.History, { Backbone.history = _.extend(new Backbone.History, {
location: location, location: location,
history: { history: {
pushState: function(){}, pushState: function() {},
replaceState: function(){} replaceState: function() {}
} }
}); });
Backbone.history.start({root: ''}); Backbone.history.start({root: ''});
@@ -625,8 +636,8 @@
Backbone.history = _.extend(new Backbone.History, { Backbone.history = _.extend(new Backbone.History, {
location: location, location: location,
history: { history: {
pushState: function(){}, pushState: function() {},
replaceState: function(state, title, url){ replaceState: function(state, title, url) {
assert.strictEqual(url, '/root/x/y?a=b'); assert.strictEqual(url, '/root/x/y?a=b');
} }
} }
@@ -641,8 +652,8 @@
assert.expect(1); assert.expect(1);
var MyRouter = Backbone.Router.extend({ var MyRouter = Backbone.Router.extend({
routes: {'': 'empty'}, routes: {'': 'empty'},
empty: function(){}, empty: function() {},
route: function(route){ route: function(route) {
assert.strictEqual(route, ''); assert.strictEqual(route, '');
} }
}); });
@@ -655,7 +666,8 @@
assert.strictEqual(history.getFragment('fragment '), 'fragment'); assert.strictEqual(history.getFragment('fragment '), 'fragment');
}); });
QUnit.test('#1820 - Leading slash and trailing space.', 1, function(assert) { QUnit.test('#1820 - Leading slash and trailing space.', function(assert) {
assert.expect(1);
var history = new Backbone.History; var history = new Backbone.History;
assert.strictEqual(history.getFragment('/fragment '), 'fragment'); assert.strictEqual(history.getFragment('/fragment '), 'fragment');
}); });
@@ -670,7 +682,7 @@
assert.strictEqual(router.z, '123'); assert.strictEqual(router.z, '123');
}); });
QUnit.test("#2062 - Trigger 'route' event on router instance.", function(assert) { QUnit.test('#2062 - Trigger "route" event on router instance.', function(assert) {
assert.expect(2); assert.expect(2);
router.on('route', function(name, args) { router.on('route', function(name, args) {
assert.strictEqual(name, 'routeEvent'); assert.strictEqual(name, 'routeEvent');
@@ -709,8 +721,8 @@
Backbone.history = _.extend(new Backbone.History, { Backbone.history = _.extend(new Backbone.History, {
location: location, location: location,
history: { history: {
pushState: function(){}, pushState: function() {},
replaceState: function(){ assert.ok(false); } replaceState: function() { assert.ok(false); }
} }
}); });
Backbone.history.start({ Backbone.history.start({
@@ -726,8 +738,8 @@
Backbone.history = _.extend(new Backbone.History, { Backbone.history = _.extend(new Backbone.History, {
location: location, location: location,
history: { history: {
pushState: function(){}, pushState: function() {},
replaceState: function(){} replaceState: function() {}
} }
}); });
@@ -753,7 +765,7 @@
Backbone.history = _.extend(new Backbone.History, { Backbone.history = _.extend(new Backbone.History, {
location: location, location: location,
history: { history: {
pushState: function(state, title, url){ pushState: function(state, title, url) {
assert.strictEqual(url, '/root'); assert.strictEqual(url, '/root');
} }
} }
@@ -785,7 +797,7 @@
Backbone.history = _.extend(new Backbone.History, { Backbone.history = _.extend(new Backbone.History, {
location: location, location: location,
history: { history: {
pushState: function(state, title, url){ pushState: function(state, title, url) {
assert.strictEqual(url, '/root?x=1'); assert.strictEqual(url, '/root?x=1');
} }
} }
@@ -823,7 +835,7 @@
assert.expect(1); assert.expect(1);
var MyRouter = Backbone.Router.extend({ var MyRouter = Backbone.Router.extend({
routes: { routes: {
path: function(params){ path: function(params) {
assert.strictEqual(params, 'x=y%3Fz'); assert.strictEqual(params, 'x=y%3Fz');
} }
} }
@@ -921,7 +933,7 @@
Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history = _.extend(new Backbone.History, {location: location});
var MyRouter = Backbone.Router.extend({ var MyRouter = Backbone.Router.extend({
routes: {'foo/:id/bar': 'foo'}, routes: {'foo/:id/bar': 'foo'},
foo: function(){}, foo: function() {},
execute: function(callback, args, name) { execute: function(callback, args, name) {
assert.strictEqual(callback, this.foo); assert.strictEqual(callback, this.foo);
assert.deepEqual(args, ['123', 'x=y']); assert.deepEqual(args, ['123', 'x=y']);
@@ -953,8 +965,8 @@
Backbone.history = _.extend(new Backbone.History, { Backbone.history = _.extend(new Backbone.History, {
location: location, location: location,
history: { history: {
pushState: function(){ assert.ok(false); }, pushState: function() { assert.ok(false); },
replaceState: function(){ assert.ok(false); } replaceState: function() { assert.ok(false); }
} }
}); });
Backbone.history.start({pushState: true}); Backbone.history.start({pushState: true});
@@ -991,14 +1003,14 @@
Backbone.history.start({root: '/root', pushState: true}); Backbone.history.start({root: '/root', pushState: true});
}); });
QUnit.test("Paths that don't match the root should not match no root", function(assert) { QUnit.test('Paths that don\'t match the root should not match no root', function(assert) {
assert.expect(0); assert.expect(0);
location.replace('http://example.com/foo'); location.replace('http://example.com/foo');
Backbone.history.stop(); Backbone.history.stop();
Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history = _.extend(new Backbone.History, {location: location});
var MyRouter = Backbone.Router.extend({ var MyRouter = Backbone.Router.extend({
routes: { routes: {
foo: function(){ foo: function() {
assert.ok(false, 'should not match unless root matches'); assert.ok(false, 'should not match unless root matches');
} }
} }
@@ -1007,14 +1019,14 @@
Backbone.history.start({root: 'root', pushState: true}); Backbone.history.start({root: 'root', pushState: true});
}); });
QUnit.test("Paths that don't match the root should not match roots of the same length", function(assert) { QUnit.test('Paths that don\'t match the root should not match roots of the same length', function(assert) {
assert.expect(0); assert.expect(0);
location.replace('http://example.com/xxxx/foo'); location.replace('http://example.com/xxxx/foo');
Backbone.history.stop(); Backbone.history.stop();
Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history = _.extend(new Backbone.History, {location: location});
var MyRouter = Backbone.Router.extend({ var MyRouter = Backbone.Router.extend({
routes: { routes: {
foo: function(){ foo: function() {
assert.ok(false, 'should not match unless root matches'); assert.ok(false, 'should not match unless root matches');
} }
} }
@@ -1029,7 +1041,7 @@
Backbone.history.stop(); Backbone.history.stop();
Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history = _.extend(new Backbone.History, {location: location});
var MyRouter = Backbone.Router.extend({ var MyRouter = Backbone.Router.extend({
routes: {foo: function(){ assert.ok(true); }} routes: {foo: function() { assert.ok(true); }}
}); });
var myRouter = new MyRouter; var myRouter = new MyRouter;
Backbone.history.start({root: 'x+y.z', pushState: true}); Backbone.history.start({root: 'x+y.z', pushState: true});
@@ -1041,7 +1053,7 @@
Backbone.history.stop(); Backbone.history.stop();
Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history = _.extend(new Backbone.History, {location: location});
var MyRouter = Backbone.Router.extend({ var MyRouter = Backbone.Router.extend({
routes: {foo: function(){ assert.ok(true); }} routes: {foo: function() { assert.ok(true); }}
}); });
var myRouter = new MyRouter; var myRouter = new MyRouter;
Backbone.history.start({root: '®ooτ', pushState: true}); Backbone.history.start({root: '®ooτ', pushState: true});
@@ -1053,10 +1065,17 @@
Backbone.history.stop(); Backbone.history.stop();
Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history = _.extend(new Backbone.History, {location: location});
var MyRouter = Backbone.Router.extend({ var MyRouter = Backbone.Router.extend({
routes: {'': function(){ assert.ok(true); }} routes: {'': function() { assert.ok(true); }}
}); });
var myRouter = new MyRouter; var myRouter = new MyRouter;
Backbone.history.start({root: '®ooτ', pushState: true}); Backbone.history.start({root: '®ooτ', pushState: true});
}); });
})(); QUnit.test('#4025 - navigate updates URL hash as is', function(assert) {
assert.expect(1);
var route = 'search/has%20space';
Backbone.history.navigate(route);
assert.strictEqual(location.hash, '#' + route);
});
})(QUnit);

View File

@@ -1,4 +1,4 @@
(function() { (function(QUnit) {
var sync = Backbone.sync; var sync = Backbone.sync;
var ajax = Backbone.ajax; var ajax = Backbone.ajax;
@@ -14,7 +14,7 @@
var env = QUnit.config.current.testEnvironment; var env = QUnit.config.current.testEnvironment;
// We never want to actually call these during tests. // We never want to actually call these during tests.
history.pushState = history.replaceState = function(){}; history.pushState = history.replaceState = function() {};
// Capture ajax settings for comparison. // Capture ajax settings for comparison.
Backbone.ajax = function(settings) { Backbone.ajax = function(settings) {
@@ -42,4 +42,4 @@
history.replaceState = replaceState; history.replaceState = replaceState;
}); });
})(); })(QUnit);

View File

@@ -1,4 +1,4 @@
(function() { (function(QUnit) {
var Library = Backbone.Collection.extend({ var Library = Backbone.Collection.extend({
url: function() { return '/library'; } url: function() { return '/library'; }
@@ -158,7 +158,7 @@
QUnit.test('Backbone.ajax', function(assert) { QUnit.test('Backbone.ajax', function(assert) {
assert.expect(1); assert.expect(1);
Backbone.ajax = function(settings){ Backbone.ajax = function(settings) {
assert.strictEqual(settings.url, '/test'); assert.strictEqual(settings.url, '/test');
}; };
var model = new Backbone.Model(); var model = new Backbone.Model();
@@ -236,4 +236,4 @@
this.ajaxSettings.error({}, 'textStatus', 'errorThrown'); this.ajaxSettings.error({}, 'textStatus', 'errorThrown');
}); });
})(); })(QUnit);

View File

@@ -1,13 +1,13 @@
(function() { (function(QUnit) {
var view; var view;
QUnit.module('Backbone.View', { QUnit.module('Backbone.View', {
beforeEach: function(assert) { beforeEach: function() {
$('#qunit-fixture').append( $('#qunit-fixture').append(
'<div id="testElement"><h1>Test</h1></div>' '<div id="testElement"><h1>Test</h1></div>'
); );
view = new Backbone.View({ view = new Backbone.View({
id: 'test-view', id: 'test-view',
@@ -61,6 +61,28 @@
assert.strictEqual(new View().one, 1); assert.strictEqual(new View().one, 1);
}); });
QUnit.test('preinitialize', function(assert) {
assert.expect(1);
var View = Backbone.View.extend({
preinitialize: function() {
this.one = 1;
}
});
assert.strictEqual(new View().one, 1);
});
QUnit.test('preinitialize occurs before the view is set up', function(assert) {
assert.expect(2);
var View = Backbone.View.extend({
preinitialize: function() {
assert.equal(this.el, undefined);
}
});
var _view = new View({});
assert.notEqual(_view.el, undefined);
});
QUnit.test('render', function(assert) { QUnit.test('render', function(assert) {
assert.expect(1); assert.expect(1);
var myView = new Backbone.View; var myView = new Backbone.View;
@@ -72,8 +94,8 @@
var counter1 = 0, counter2 = 0; var counter1 = 0, counter2 = 0;
var myView = new Backbone.View({el: '#testElement'}); var myView = new Backbone.View({el: '#testElement'});
myView.increment = function(){ counter1++; }; myView.increment = function() { counter1++; };
myView.$el.on('click', function(){ counter2++; }); myView.$el.on('click', function() { counter2++; });
var events = {'click h1': 'increment'}; var events = {'click h1': 'increment'};
@@ -129,11 +151,10 @@
assert.equal(myView.counter, 3); assert.equal(myView.counter, 3);
}); });
QUnit.test('delegateEvents ignore undefined methods', function(assert) { QUnit.test('delegateEvents ignore undefined methods', function(assert) {
assert.expect(0); assert.expect(0);
var myView = new Backbone.View({el: '<p></p>'}); var myView = new Backbone.View({el: '<p></p>'});
myView.delegateEvents({'click': 'undefinedMethod'}); myView.delegateEvents({click: 'undefinedMethod'});
myView.$el.trigger('click'); myView.$el.trigger('click');
}); });
@@ -142,8 +163,8 @@
var counter1 = 0, counter2 = 0; var counter1 = 0, counter2 = 0;
var myView = new Backbone.View({el: '#testElement'}); var myView = new Backbone.View({el: '#testElement'});
myView.increment = function(){ counter1++; }; myView.increment = function() { counter1++; };
myView.$el.on('click', function(){ counter2++; }); myView.$el.on('click', function() { counter2++; });
var events = {'click h1': 'increment'}; var events = {'click h1': 'increment'};
@@ -203,7 +224,7 @@
assert.expect(2); assert.expect(2);
var myView = new Backbone.View({el: '#testElement'}); var myView = new Backbone.View({el: '#testElement'});
myView.delegate('click', function() { assert.ok(true); }); myView.delegate('click', function() { assert.ok(true); });
var handler = function(){ assert.ok(false); }; var handler = function() { assert.ok(false); };
myView.delegate('click', 'h1', handler); myView.delegate('click', 'h1', handler);
myView.undelegate('click', 'h1', handler); myView.undelegate('click', 'h1', handler);
myView.$('h1').trigger('click'); myView.$('h1').trigger('click');
@@ -405,8 +426,8 @@
assert.expect(0); assert.expect(0);
var View = Backbone.View.extend({ var View = Backbone.View.extend({
initialize: function() { initialize: function() {
this.listenTo(this.model, 'all x', function(){ assert.ok(false); }); this.listenTo(this.model, 'all x', function() { assert.ok(false); });
this.listenTo(this.collection, 'all x', function(){ assert.ok(false); }); this.listenTo(this.collection, 'all x', function() { assert.ok(false); });
} }
}); });
@@ -492,4 +513,4 @@
assert.notEqual($oldEl, myView.$el); assert.notEqual($oldEl, myView.$el);
}); });
})(); })(QUnit);

View File

@@ -15,6 +15,10 @@
result = _.map([[1, 2, 3], [1, 2, 3]], _.first); result = _.map([[1, 2, 3], [1, 2, 3]], _.first);
assert.deepEqual(result, [1, 1], 'works well with _.map'); assert.deepEqual(result, [1, 1], 'works well with _.map');
assert.equal(_.first(null), void 0, 'returns undefined when called on null'); assert.equal(_.first(null), void 0, 'returns undefined when called on null');
Array.prototype[0] = 'boo';
assert.equal(_.first([]), void 0, 'return undefined when called on a empty array');
delete Array.prototype[0];
}); });
QUnit.test('head', function(assert) { QUnit.test('head', function(assert) {
@@ -66,6 +70,10 @@
result = _.map([[1, 2, 3], [1, 2, 3]], _.last); result = _.map([[1, 2, 3], [1, 2, 3]], _.last);
assert.deepEqual(result, [3, 3], 'works well with _.map'); assert.deepEqual(result, [3, 3], 'works well with _.map');
assert.equal(_.last(null), void 0, 'returns undefined when called on null'); assert.equal(_.last(null), void 0, 'returns undefined when called on null');
var arr = [];
arr[-1] = 'boo';
assert.equal(_.last(arr), void 0, 'return undefined when called on a empty array');
}); });
QUnit.test('compact', function(assert) { QUnit.test('compact', function(assert) {

View File

@@ -188,7 +188,7 @@
var prod = _.reduce([1, 2, 3, 4], function(memo, num){ return memo * num; }); var prod = _.reduce([1, 2, 3, 4], function(memo, num){ return memo * num; });
assert.equal(prod, 24, 'can reduce via multiplication'); assert.equal(prod, 24, 'can reduce via multiplication');
assert.ok(_.reduce(null, _.noop, 138) === 138, 'handles a null (with initial value) properly'); assert.strictEqual(_.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, 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), _, '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'); assert.equal(_.reduce([], _.noop), void 0, 'returns undefined when collection is empty and no initial value');
@@ -212,7 +212,7 @@
var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(memo, num){ return memo + num; }); var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(memo, num){ return memo + num; });
assert.equal(sum, 6, 'default initial value on object'); assert.equal(sum, 6, 'default initial value on object');
assert.ok(_.reduceRight(null, _.noop, 138) === 138, 'handles a null (with initial value) properly'); assert.strictEqual(_.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'); assert.equal(_.reduceRight([_], _.noop), _, 'collection of length one with no initial value returns the first item');
assert.equal(_.reduceRight([], _.noop, void 0), void 0, 'undefined can be passed as a special case'); assert.equal(_.reduceRight([], _.noop, void 0), void 0, 'undefined can be passed as a special case');
@@ -268,8 +268,8 @@
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}]; var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}];
assert.deepEqual(_.find(list, {a: 1}), {a: 1, b: 2}, 'can be used as findWhere'); 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.deepEqual(_.find(list, {b: 4}), {a: 1, b: 4});
assert.ok(!_.find(list, {c: 1}), 'undefined when not found'); assert.notOk(_.find(list, {c: 1}), 'undefined when not found');
assert.ok(!_.find([], {c: 1}), 'undefined when searching empty list'); assert.notOk(_.find([], {c: 1}), 'undefined when searching empty list');
var result = _.find([1, 2, 3], function(num){ return num * 2 === 4; }); var result = _.find([1, 2, 3], function(num){ return num * 2 === 4; });
assert.equal(result, 2, 'found the first "2" and broke the loop'); assert.equal(result, 2, 'found the first "2" and broke the loop');
@@ -348,25 +348,25 @@
QUnit.test('every', function(assert) { QUnit.test('every', function(assert) {
assert.ok(_.every([], _.identity), 'the empty set'); assert.ok(_.every([], _.identity), 'the empty set');
assert.ok(_.every([true, true, true], _.identity), 'every true values'); assert.ok(_.every([true, true, true], _.identity), 'every true values');
assert.ok(!_.every([true, false, true], _.identity), 'one false value'); assert.notOk(_.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, 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.notOk(_.every([0, 11, 28], function(num){ return num % 2 === 0; }), 'an odd number');
assert.ok(_.every([1], _.identity) === true, 'cast to boolean - true'); assert.strictEqual(_.every([1], _.identity), true, 'cast to boolean - true');
assert.ok(_.every([0], _.identity) === false, 'cast to boolean - false'); assert.strictEqual(_.every([0], _.identity), false, 'cast to boolean - false');
assert.ok(!_.every([void 0, void 0, void 0], _.identity), 'works with arrays of undefined'); assert.notOk(_.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}]; var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}];
assert.ok(!_.every(list, {a: 1, b: 2}), 'Can be called with object'); assert.notOk(_.every(list, {a: 1, b: 2}), 'Can be called with object');
assert.ok(_.every(list, 'a'), 'String mapped to object property'); assert.ok(_.every(list, 'a'), 'String mapped to object property');
list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}]; list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}];
assert.ok(_.every(list, {b: 2}), 'Can be called with object'); assert.ok(_.every(list, {b: 2}), 'Can be called with object');
assert.ok(!_.every(list, 'c'), 'String mapped to object property'); assert.notOk(_.every(list, 'c'), 'String mapped to object property');
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}, _.isNumber), 'takes objects');
assert.ok(!_.every({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); assert.notOk(_.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'], _.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'); assert.notOk(_.every(['a', 'b', 'c', 'd', 'f'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works');
}); });
QUnit.test('all', function(assert) { QUnit.test('all', function(assert) {
@@ -374,29 +374,29 @@
}); });
QUnit.test('some', function(assert) { QUnit.test('some', function(assert) {
assert.ok(!_.some([]), 'the empty set'); assert.notOk(_.some([]), 'the empty set');
assert.ok(!_.some([false, false, false]), 'all false values'); assert.notOk(_.some([false, false, false]), 'all false values');
assert.ok(_.some([false, false, true]), 'one true value'); assert.ok(_.some([false, false, true]), 'one true value');
assert.ok(_.some([null, 0, 'yes', false]), 'a string'); assert.ok(_.some([null, 0, 'yes', false]), 'a string');
assert.ok(!_.some([null, 0, '', false]), 'falsy values'); assert.notOk(_.some([null, 0, '', false]), 'falsy values');
assert.ok(!_.some([1, 11, 29], function(num){ return num % 2 === 0; }), 'all odd numbers'); assert.notOk(_.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, 10, 29], function(num){ return num % 2 === 0; }), 'an even number');
assert.ok(_.some([1], _.identity) === true, 'cast to boolean - true'); assert.strictEqual(_.some([1], _.identity), true, 'cast to boolean - true');
assert.ok(_.some([0], _.identity) === false, 'cast to boolean - false'); assert.strictEqual(_.some([0], _.identity), false, 'cast to boolean - false');
assert.ok(_.some([false, false, true])); assert.ok(_.some([false, false, true]));
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}];
assert.ok(!_.some(list, {a: 5, b: 2}), 'Can be called with object'); assert.notOk(_.some(list, {a: 5, b: 2}), 'Can be called with object');
assert.ok(_.some(list, 'a'), 'String mapped to object property'); assert.ok(_.some(list, 'a'), 'String mapped to object property');
list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}]; list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}];
assert.ok(_.some(list, {b: 2}), 'Can be called with object'); assert.ok(_.some(list, {b: 2}), 'Can be called with object');
assert.ok(!_.some(list, 'd'), 'String mapped to object property'); assert.notOk(_.some(list, 'd'), 'String mapped to object property');
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', e: 6}, _.isNumber), 'takes objects');
assert.ok(!_.some({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); assert.notOk(_.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(['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'); assert.notOk(_.some(['x', 'y', 'z'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works');
}); });
QUnit.test('any', function(assert) { QUnit.test('any', function(assert) {
@@ -408,11 +408,11 @@
assert.strictEqual(_.includes(val, 'hasOwnProperty'), false); assert.strictEqual(_.includes(val, 'hasOwnProperty'), false);
}); });
assert.strictEqual(_.includes([1, 2, 3], 2), true, 'two is 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'); assert.notOk(_.includes([1, 3, 9], 2), 'two is not in the array');
assert.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');
assert.ok(_.includes({moe: 1, larry: 3, curly: 9}, 3) === true, '_.includes on objects checks their values'); assert.strictEqual(_.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'); assert.ok(_([1, 2, 3]).includes(2), 'OO-style includes');
var numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; var numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
@@ -549,7 +549,7 @@
assert.equal(-Infinity, _.max(void 0), 'can handle null/undefined'); assert.equal(-Infinity, _.max(void 0), 'can handle null/undefined');
assert.equal(-Infinity, _.max(null, _.identity), 'can handle null/undefined'); assert.equal(-Infinity, _.max(null, _.identity), 'can handle null/undefined');
assert.equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); assert.equal(_.max([1, 2, 3]), 3, 'can perform a regular Math.max');
var neg = _.max([1, 2, 3], function(num){ return -num; }); var neg = _.max([1, 2, 3], function(num){ return -num; });
assert.equal(neg, 1, 'can perform a computation-based max'); assert.equal(neg, 1, 'can perform a computation-based max');
@@ -558,24 +558,24 @@
assert.equal(-Infinity, _.max([]), 'Maximum value of an empty array'); assert.equal(-Infinity, _.max([]), 'Maximum value of an empty array');
assert.equal(_.max({a: 'a'}), -Infinity, 'Maximum value of a non-numeric collection'); assert.equal(_.max({a: 'a'}), -Infinity, 'Maximum value of a non-numeric collection');
assert.equal(299999, _.max(_.range(1, 300000)), 'Maximum value of a too-big array'); assert.equal(_.max(_.range(1, 300000)), 299999, 'Maximum value of a too-big array');
assert.equal(3, _.max([1, 2, 3, 'test']), 'Finds correct max in array starting with num and containing a NaN'); assert.equal(_.max([1, 2, 3, 'test']), 3, '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'); assert.equal(_.max(['test', 1, 2, 3]), 3, 'Finds correct max in array starting with NaN');
assert.equal(3, _.max([1, 2, 3, null]), 'Finds correct max in array starting with num and containing a `null`'); assert.equal(_.max([1, 2, 3, null]), 3, '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(_.max([null, 1, 2, 3]), 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(_.max([1, 2, 3, '']), 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(_.max(['', 1, 2, 3]), 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(_.max([1, 2, 3, false]), 3, '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(_.max([false, 1, 2, 3]), 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(_.max([0, 1, 2, 3, 4]), 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.equal(_.max([-3, -2, -1, 0]), 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'); assert.deepEqual(_.map([[1, 2, 3], [4, 5, 6]], _.max), [3, 6], 'Finds correct max in array when mapping through multiple arrays');
var a = {x: -Infinity}; var a = {x: -Infinity};
var b = {x: -Infinity}; var b = {x: -Infinity};
@@ -590,35 +590,35 @@
}); });
QUnit.test('min', function(assert) { QUnit.test('min', function(assert) {
assert.equal(Infinity, _.min(null), 'can handle null/undefined'); assert.equal(_.min(null), Infinity, 'can handle null/undefined');
assert.equal(Infinity, _.min(void 0), 'can handle null/undefined'); assert.equal(_.min(void 0), Infinity, 'can handle null/undefined');
assert.equal(Infinity, _.min(null, _.identity), 'can handle null/undefined'); assert.equal(_.min(null, _.identity), Infinity, 'can handle null/undefined');
assert.equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min'); assert.equal(_.min([1, 2, 3]), 1, 'can perform a regular Math.min');
var neg = _.min([1, 2, 3], function(num){ return -num; }); var neg = _.min([1, 2, 3], function(num){ return -num; });
assert.equal(neg, 3, 'can perform a computation-based min'); assert.equal(neg, 3, 'can perform a computation-based min');
assert.equal(Infinity, _.min({}), 'Minimum value of an empty object'); assert.equal(_.min({}), Infinity, 'Minimum value of an empty object');
assert.equal(Infinity, _.min([]), 'Minimum value of an empty array'); assert.equal(_.min([]), Infinity, 'Minimum value of an empty array');
assert.equal(_.min({a: 'a'}), Infinity, 'Minimum value of a non-numeric collection'); assert.equal(_.min({a: 'a'}), Infinity, 'Minimum value of a non-numeric collection');
assert.deepEqual([1, 4], _.map([[1, 2, 3], [4, 5, 6]], _.min), 'Finds correct min in array when mapping through multiple arrays'); assert.deepEqual(_.map([[1, 2, 3], [4, 5, 6]], _.min), [1, 4], 'Finds correct min in array when mapping through multiple arrays');
var now = new Date(9999999999); var now = new Date(9999999999);
var then = new Date(0); var then = new Date(0);
assert.equal(_.min([now, then]), then); assert.equal(_.min([now, then]), then);
assert.equal(1, _.min(_.range(1, 300000)), 'Minimum value of a too-big array'); assert.equal(_.min(_.range(1, 300000)), 1, 'Minimum value of a too-big array');
assert.equal(1, _.min([1, 2, 3, 'test']), 'Finds correct min in array starting with num and containing a NaN'); assert.equal(_.min([1, 2, 3, 'test']), 1, '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(_.min(['test', 1, 2, 3]), 1, '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(_.min([1, 2, 3, null]), 1, '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(_.min([null, 1, 2, 3]), 1, '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(_.min([0, 1, 2, 3, 4]), 0, 'Finds correct min in array containing a zero');
assert.equal(-3, _.min([-3, -2, -1, 0]), 'Finds correct min in array containing negative numbers'); assert.equal(_.min([-3, -2, -1, 0]), -3, 'Finds correct min in array containing negative numbers');
var a = {x: Infinity}; var a = {x: Infinity};
var b = {x: Infinity}; var b = {x: Infinity};
@@ -692,7 +692,7 @@
assert.deepEqual(grouped['5'], ['three', 'seven', 'eight']); assert.deepEqual(grouped['5'], ['three', 'seven', 'eight']);
var context = {}; var context = {};
_.groupBy([{}], function(){ assert.ok(this === context); }, context); _.groupBy([{}], function(){ assert.strictEqual(this, context); }, context);
grouped = _.groupBy([4.2, 6.1, 6.4], function(num) { grouped = _.groupBy([4.2, 6.1, 6.4], function(num) {
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';
@@ -701,7 +701,7 @@
assert.equal(grouped.hasOwnProperty.length, 2); assert.equal(grouped.hasOwnProperty.length, 2);
var array = [{}]; var array = [{}];
_.groupBy(array, function(value, index, obj){ assert.ok(obj === array); }); _.groupBy(array, function(value, index, obj){ assert.strictEqual(obj, array); });
array = [1, 2, 1, 2, 3]; array = [1, 2, 1, 2, 3];
grouped = _.groupBy(array); grouped = _.groupBy(array);
@@ -747,7 +747,7 @@
assert.equal(grouped['5'], 3); assert.equal(grouped['5'], 3);
var context = {}; var context = {};
_.countBy([{}], function(){ assert.ok(this === context); }, context); _.countBy([{}], function(){ assert.strictEqual(this, context); }, context);
grouped = _.countBy([4.2, 6.1, 6.4], function(num) { grouped = _.countBy([4.2, 6.1, 6.4], function(num) {
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';
@@ -756,7 +756,7 @@
assert.equal(grouped.hasOwnProperty, 2); assert.equal(grouped.hasOwnProperty, 2);
var array = [{}]; var array = [{}];
_.countBy(array, function(value, index, obj){ assert.ok(obj === array); }); _.countBy(array, function(value, index, obj){ assert.strictEqual(obj, array); });
array = [1, 2, 1, 2, 3]; array = [1, 2, 1, 2, 3];
grouped = _.countBy(array); grouped = _.countBy(array);
@@ -797,10 +797,10 @@
}); });
QUnit.test('toArray', function(assert) { QUnit.test('toArray', function(assert) {
assert.ok(!_.isArray(arguments), 'arguments object is not an array'); assert.notOk(_.isArray(arguments), 'arguments object is not an array');
assert.ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); assert.ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array');
var a = [1, 2, 3]; var a = [1, 2, 3];
assert.ok(_.toArray(a) !== a, 'array is cloned'); assert.notStrictEqual(_.toArray(a), a, 'array is cloned');
assert.deepEqual(_.toArray(a), [1, 2, 3], 'cloned array contains same elements'); assert.deepEqual(_.toArray(a), [1, 2, 3], 'cloned array contains same elements');
var numbers = _.toArray({one: 1, two: 2, three: 3}); var numbers = _.toArray({one: 1, two: 2, three: 3});
@@ -882,7 +882,7 @@
assert.deepEqual(_.map(elementChildren, 'id'), ['id1', 'id2']); assert.deepEqual(_.map(elementChildren, 'id'), ['id1', 'id2']);
assert.deepEqual(_.map(parent.childNodes, 'nodeType'), [1, 3, 1]); assert.deepEqual(_.map(parent.childNodes, 'nodeType'), [1, 3, 1]);
assert.ok(!_.every(parent.childNodes, _.isElement)); assert.notOk(_.every(parent.childNodes, _.isElement));
assert.ok(_.some(parent.childNodes, _.isElement)); assert.ok(_.some(parent.childNodes, _.isElement));
function compareNode(node) { function compareNode(node) {

View File

@@ -35,7 +35,7 @@
QUnit.test('isEqual', function(assert) { QUnit.test('isEqual', function(assert) {
assert.ok(!_.isEqual(iNumber, 101)); assert.notOk(_.isEqual(iNumber, 101));
assert.ok(_.isEqual(iNumber, 100)); assert.ok(_.isEqual(iNumber, 100));
// Objects from another frame. // Objects from another frame.
@@ -46,13 +46,13 @@
}); });
QUnit.test('isEmpty', function(assert) { QUnit.test('isEmpty', function(assert) {
assert.ok(!_([iNumber]).isEmpty(), '[1] is not empty'); assert.notOk(_([iNumber]).isEmpty(), '[1] is not empty');
assert.ok(!_.isEmpty(iArray), '[] is empty'); assert.notOk(_.isEmpty(iArray), '[] is empty');
assert.ok(_.isEmpty(iObject), '{} is empty'); assert.ok(_.isEmpty(iObject), '{} is empty');
}); });
QUnit.test('isElement', function(assert) { QUnit.test('isElement', function(assert) {
assert.ok(!_.isElement('div'), 'strings are not dom elements'); assert.notOk(_.isElement('div'), 'strings are not dom elements');
assert.ok(_.isElement(document.body), 'the body tag is a DOM element'); assert.ok(_.isElement(document.body), 'the body tag is a DOM element');
assert.ok(_.isElement(iElement), 'even from another frame'); assert.ok(_.isElement(iElement), 'even from another frame');
}); });
@@ -113,12 +113,12 @@
if (typeof ActiveXObject != 'undefined') { if (typeof ActiveXObject != 'undefined') {
QUnit.test('IE host objects', function(assert) { QUnit.test('IE host objects', function(assert) {
var xml = new ActiveXObject('Msxml2.DOMDocument.3.0'); var xml = new ActiveXObject('Msxml2.DOMDocument.3.0');
assert.ok(!_.isNumber(xml)); assert.notOk(_.isNumber(xml));
assert.ok(!_.isBoolean(xml)); assert.notOk(_.isBoolean(xml));
assert.ok(!_.isNaN(xml)); assert.notOk(_.isNaN(xml));
assert.ok(!_.isFunction(xml)); assert.notOk(_.isFunction(xml));
assert.ok(!_.isNull(xml)); assert.notOk(_.isNull(xml));
assert.ok(!_.isUndefined(xml)); assert.notOk(_.isUndefined(xml));
}); });
QUnit.test('#1621 IE 11 compat mode DOM elements are not functions', function(assert) { QUnit.test('#1621 IE 11 compat mode DOM elements are not functions', function(assert) {

View File

@@ -180,7 +180,7 @@
var done = assert.async(); var done = assert.async();
var delayed = false; var delayed = false;
_.delay(function(){ delayed = true; }, 100); _.delay(function(){ delayed = true; }, 100);
setTimeout(function(){ assert.ok(!delayed, "didn't delay the function quite yet"); }, 50); setTimeout(function(){ assert.notOk(delayed, "didn't delay the function quite yet"); }, 50);
setTimeout(function(){ assert.ok(delayed, 'delayed the function'); done(); }, 150); setTimeout(function(){ assert.ok(delayed, 'delayed the function'); done(); }, 150);
}); });
@@ -694,6 +694,43 @@
assert.deepEqual(_.toArray(cb(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), _.range(1, 11)); assert.deepEqual(_.toArray(cb(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), _.range(1, 11));
}); });
// Test custom iteratee
var builtinIteratee = _.iteratee;
_.iteratee = function(value) {
// RegEx values return a function that returns the number of matches
if (_.isRegExp(value)) return function(obj) {
return (obj.match(value) || []).length;
};
return value;
};
var collection = ['foo', 'bar', 'bbiz'];
// Test all methods that claim to be transformed through `_.iteratee`
assert.deepEqual(_.countBy(collection, /b/g), {0: 1, 1: 1, 2: 1});
assert.equal(_.every(collection, /b/g), false);
assert.deepEqual(_.filter(collection, /b/g), ['bar', 'bbiz']);
assert.equal(_.find(collection, /b/g), 'bar');
assert.equal(_.findIndex(collection, /b/g), 1);
assert.equal(_.findKey(collection, /b/g), 1);
assert.equal(_.findLastIndex(collection, /b/g), 2);
assert.deepEqual(_.groupBy(collection, /b/g), {0: ['foo'], 1: ['bar'], 2: ['bbiz']});
assert.deepEqual(_.indexBy(collection, /b/g), {0: 'foo', 1: 'bar', 2: 'bbiz'});
assert.deepEqual(_.map(collection, /b/g), [0, 1, 2]);
assert.equal(_.max(collection, /b/g), 'bbiz');
assert.equal(_.min(collection, /b/g), 'foo');
assert.deepEqual(_.partition(collection, /b/g), [['bar', 'bbiz'], ['foo']]);
assert.deepEqual(_.reject(collection, /b/g), ['foo']);
assert.equal(_.some(collection, /b/g), true);
assert.deepEqual(_.sortBy(collection, /b/g), ['foo', 'bar', 'bbiz']);
assert.equal(_.sortedIndex(collection, 'blah', /b/g), 1);
assert.deepEqual(_.uniq(collection, /b/g), ['foo', 'bar', 'bbiz']);
var objCollection = {a: 'foo', b: 'bar', c: 'bbiz'};
assert.deepEqual(_.mapObject(objCollection, /b/g), {a: 0, b: 1, c: 2});
// Restore the builtin iteratee
_.iteratee = builtinIteratee;
}); });
QUnit.test('restArgs', function(assert) { QUnit.test('restArgs', function(assert) {

View File

@@ -123,7 +123,7 @@
subObj.c = 'd'; subObj.c = 'd';
assert.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, {}); _.extend(subObj, {});
assert.ok(!subObj.hasOwnProperty('a'), "extend does not convert destination object's 'in' properties to 'own' properties"); assert.notOk(subObj.hasOwnProperty('a'), "extend does not convert destination object's 'in' properties to 'own' properties");
try { try {
result = {}; result = {};
@@ -205,7 +205,7 @@
return this[key] === 3 && this === instance; return this[key] === 3 && this === instance;
}, instance), {c: 3}, 'function is given context'); }, instance), {c: 3}, 'function is given context');
assert.ok(!_.has(_.pick({}, 'foo'), 'foo'), 'does not set own property if property not in object'); assert.notOk(_.has(_.pick({}, 'foo'), 'foo'), 'does not set own property if property not in object');
_.pick(data, function(value, key, obj) { _.pick(data, function(value, key, obj) {
assert.equal(obj, data, 'passes same object as third parameter of iteratee'); assert.equal(obj, data, 'passes same object as third parameter of iteratee');
}); });
@@ -309,7 +309,7 @@
Child.prototype.foo = 'foo'; Child.prototype.foo = 'foo';
var created = _.create(Child.prototype, new Child); var created = _.create(Child.prototype, new Child);
assert.ok(!created.hasOwnProperty('foo'), 'should only add own properties'); assert.notOk(created.hasOwnProperty('foo'), 'should only add own properties');
}); });
QUnit.test('isEqual', function(assert) { QUnit.test('isEqual', function(assert) {
@@ -326,10 +326,10 @@
assert.ok(_.isEqual(null, null), '`null` is equal to `null`'); assert.ok(_.isEqual(null, null), '`null` is equal to `null`');
assert.ok(_.isEqual(), '`undefined` is equal to `undefined`'); assert.ok(_.isEqual(), '`undefined` is equal to `undefined`');
assert.ok(!_.isEqual(0, -0), '`0` is not equal to `-0`'); assert.notOk(_.isEqual(0, -0), '`0` is not equal to `-0`');
assert.ok(!_.isEqual(-0, 0), 'Commutative equality is implemented for `0` and `-0`'); assert.notOk(_.isEqual(-0, 0), 'Commutative equality is implemented for `0` and `-0`');
assert.ok(!_.isEqual(null, void 0), '`null` is not equal to `undefined`'); assert.notOk(_.isEqual(null, void 0), '`null` is not equal to `undefined`');
assert.ok(!_.isEqual(void 0, null), 'Commutative equality is implemented for `null` and `undefined`'); assert.notOk(_.isEqual(void 0, null), 'Commutative equality is implemented for `null` and `undefined`');
// String object and primitive comparisons. // String object and primitive comparisons.
assert.ok(_.isEqual('Curly', 'Curly'), 'Identical string primitives are equal'); assert.ok(_.isEqual('Curly', 'Curly'), 'Identical string primitives are equal');
@@ -337,76 +337,76 @@
assert.ok(_.isEqual(new String('Curly'), 'Curly'), 'String primitives and their corresponding object wrappers 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'); assert.ok(_.isEqual('Curly', new String('Curly')), 'Commutative equality is implemented for string objects and primitives');
assert.ok(!_.isEqual('Curly', 'Larry'), 'String primitives with different values are not equal'); assert.notOk(_.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.notOk(_.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'); assert.notOk(_.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. // Number object and primitive comparisons.
assert.ok(_.isEqual(75, 75), 'Identical number primitives are equal'); 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(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(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(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.notOk(_.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`'); assert.notOk(_.isEqual(0, new Number(-0)), 'Commutative equality is implemented for `new Number(0)` and `-0`');
assert.ok(!_.isEqual(new Number(75), new Number(63)), 'Number objects with different primitive values are not equal'); assert.notOk(_.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'); assert.notOk(_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), 'Number objects and objects with a `valueOf` method are not equal');
// Comparisons involving `NaN`. // Comparisons involving `NaN`.
assert.ok(_.isEqual(NaN, NaN), '`NaN` is 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(new Number(NaN), NaN), 'Object(`NaN`) is equal to `NaN`');
assert.ok(!_.isEqual(61, NaN), 'A number primitive is not equal to `NaN`'); assert.notOk(_.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.notOk(_.isEqual(new Number(79), NaN), 'A number object is not equal to `NaN`');
assert.ok(!_.isEqual(Infinity, NaN), '`Infinity` is not equal to `NaN`'); assert.notOk(_.isEqual(Infinity, NaN), '`Infinity` is not equal to `NaN`');
// Boolean object and primitive comparisons. // Boolean object and primitive comparisons.
assert.ok(_.isEqual(true, true), 'Identical boolean primitives are 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(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(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), true), 'Commutative equality is implemented for booleans');
assert.ok(!_.isEqual(new Boolean(true), new Boolean), 'Boolean objects with different primitive values are not equal'); assert.notOk(_.isEqual(new Boolean(true), new Boolean), 'Boolean objects with different primitive values are not equal');
// Common type coercions. // Common type coercions.
assert.ok(!_.isEqual(new Boolean(false), true), '`new Boolean(false)` is not equal to `true`'); assert.notOk(_.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.notOk(_.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.notOk(_.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.notOk(_.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.notOk(_.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.notOk(_.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.notOk(_.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.notOk(_.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'); assert.notOk(_.isEqual(12564504e5, new Date(2009, 9, 25)), 'Dates and their corresponding numeric primitive values are not equal');
// Dates. // Dates.
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, 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.notOk(_.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), { assert.notOk(_.isEqual(new Date(2009, 11, 13), {
getTime: function(){ getTime: function(){
return 12606876e5; return 12606876e5;
} }
}), 'Date objects and objects with a `getTime` method are not equal'); }), 'Date objects and objects with a `getTime` method are not equal');
assert.ok(!_.isEqual(new Date('Curly'), new Date('Curly')), 'Invalid dates are not equal'); assert.notOk(_.isEqual(new Date('Curly'), new Date('Curly')), 'Invalid dates are not equal');
// Functions. // Functions.
assert.ok(!_.isEqual(First, Second), 'Different functions with identical bodies and source code representations are not equal'); assert.notOk(_.isEqual(First, Second), 'Different functions with identical bodies and source code representations are not equal');
// RegExps. // RegExps.
assert.ok(_.isEqual(/(?:)/gim, /(?:)/gim), 'RegExps with equivalent patterns and flags are 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(/(?:)/gi, /(?:)/ig), 'Flag order is not significant');
assert.ok(!_.isEqual(/(?:)/g, /(?:)/gi), 'RegExps with equivalent patterns and different flags are not equal'); assert.notOk(_.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.notOk(_.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.notOk(_.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'); assert.notOk(_.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. // Empty arrays, array-like objects, and object literals.
assert.ok(_.isEqual({}, {}), 'Empty object literals are equal'); assert.ok(_.isEqual({}, {}), 'Empty object literals are equal');
assert.ok(_.isEqual([], []), 'Empty array literals are equal'); assert.ok(_.isEqual([], []), 'Empty array literals are equal');
assert.ok(_.isEqual([{}], [{}]), 'Empty nested arrays and objects 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.notOk(_.isEqual({length: 0}, []), 'Array-like objects and arrays are not equal.');
assert.ok(!_.isEqual([], {length: 0}), 'Commutative equality is implemented for array-like objects'); assert.notOk(_.isEqual([], {length: 0}), 'Commutative equality is implemented for array-like objects');
assert.ok(!_.isEqual({}, []), 'Object literals and array literals are not equal'); assert.notOk(_.isEqual({}, []), 'Object literals and array literals are not equal');
assert.ok(!_.isEqual([], {}), 'Commutative equality is implemented for objects and arrays'); assert.notOk(_.isEqual([], {}), 'Commutative equality is implemented for objects and arrays');
// Arrays with primitive and object values. // Arrays with primitive and object values.
assert.ok(_.isEqual([1, 'Larry', true], [1, 'Larry', true]), 'Arrays containing identical primitives are equal'); assert.ok(_.isEqual([1, 'Larry', true], [1, 'Larry', true]), 'Arrays containing identical primitives are equal');
@@ -424,14 +424,14 @@
// Array elements and properties. // Array elements and properties.
assert.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'); a.push('White Rocks');
assert.ok(!_.isEqual(a, b), 'Arrays of different lengths are not equal'); assert.notOk(_.isEqual(a, b), 'Arrays of different lengths are not equal');
a.push('East Boulder'); a.push('East Boulder');
b.push('Gunbarrel Ranch', 'Teller Farm'); b.push('Gunbarrel Ranch', 'Teller Farm');
assert.ok(!_.isEqual(a, b), 'Arrays of identical lengths containing different elements are not equal'); assert.notOk(_.isEqual(a, b), 'Arrays of identical lengths containing different elements are not equal');
// Sparse arrays. // Sparse arrays.
assert.ok(_.isEqual(Array(3), Array(3)), 'Sparse arrays of identical lengths are equal'); 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'); assert.notOk(_.isEqual(Array(3), Array(6)), 'Sparse arrays of different lengths are not equal when both are empty');
var sparse = []; var sparse = [];
sparse[1] = 5; sparse[1] = 5;
@@ -440,11 +440,11 @@
// Simple objects. // Simple objects.
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', 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: /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.notOk(_.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.notOk(_.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.notOk(_.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.notOk(_.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'); assert.notOk(_.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` contains nested objects and arrays.
a = { a = {
@@ -479,9 +479,9 @@
// Instances. // Instances.
assert.ok(_.isEqual(new First, new First), 'Object instances are equal'); 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.notOk(_.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.notOk(_.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'); assert.notOk(_.isEqual({value: 2}, new Second), 'The prototype chain of objects should not be examined');
// Circular Arrays. // Circular Arrays.
(a = []).push(a); (a = []).push(a);
@@ -492,13 +492,13 @@
assert.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'); a.push('Shemp');
b.push('Curly'); b.push('Curly');
assert.ok(!_.isEqual(a, b), 'Arrays containing circular references and different properties are not equal'); assert.notOk(_.isEqual(a, b), 'Arrays containing circular references and different properties are not equal');
// More circular arrays #767. // More circular arrays #767.
a = ['everything is checked but', 'this', 'is not']; a = ['everything is checked but', 'this', 'is not'];
a[1] = a; a[1] = a;
b = ['everything is checked but', ['this', 'array'], 'is not']; b = ['everything is checked but', ['this', 'array'], 'is not'];
assert.ok(!_.isEqual(a, b), 'Comparison of circular references with non-circular references are not equal'); assert.notOk(_.isEqual(a, b), 'Comparison of circular references with non-circular references are not equal');
// Circular Objects. // Circular Objects.
a = {abc: null}; a = {abc: null};
@@ -511,13 +511,13 @@
assert.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); a.def = new Number(75);
b.def = new Number(63); b.def = new Number(63);
assert.ok(!_.isEqual(a, b), 'Objects containing circular references and different properties are not equal'); assert.notOk(_.isEqual(a, b), 'Objects containing circular references and different properties are not equal');
// More circular objects #767. // More circular objects #767.
a = {everything: 'is checked', but: 'this', is: 'not'}; a = {everything: 'is checked', but: 'this', is: 'not'};
a.but = a; a.but = a;
b = {everything: 'is checked', but: {that: 'object'}, is: 'not'}; b = {everything: 'is checked', but: {that: 'object'}, is: 'not'};
assert.ok(!_.isEqual(a, b), 'Comparison of circular references with non-circular object references are not equal'); assert.notOk(_.isEqual(a, b), 'Comparison of circular references with non-circular object references are not equal');
// Cyclic Structures. // Cyclic Structures.
a = [{abc: null}]; a = [{abc: null}];
@@ -530,7 +530,7 @@
assert.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'); a[0].def = new String('Larry');
b[0].def = new String('Curly'); b[0].def = new String('Curly');
assert.ok(!_.isEqual(a, b), 'Cyclic structures containing different properties are not equal'); assert.notOk(_.isEqual(a, b), 'Cyclic structures containing different properties are not equal');
// Complex Circular References. // Complex Circular References.
a = {foo: {b: {foo: {c: {foo: null}}}}}; a = {foo: {b: {foo: {c: {foo: null}}}}};
@@ -540,7 +540,7 @@
assert.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. // Chaining.
assert.ok(!_.isEqual(_({x: 1, y: void 0}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal'); assert.notOk(_.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(); a = _({x: 1, y: 2}).chain();
b = _({x: 1, y: 2}).chain(); b = _({x: 1, y: 2}).chain();
@@ -576,15 +576,15 @@
}); });
QUnit.test('isEmpty', function(assert) { QUnit.test('isEmpty', function(assert) {
assert.ok(!_([1]).isEmpty(), '[1] is not empty'); assert.notOk(_([1]).isEmpty(), '[1] is not empty');
assert.ok(_.isEmpty([]), '[] is empty'); assert.ok(_.isEmpty([]), '[] is empty');
assert.ok(!_.isEmpty({one: 1}), '{one: 1} is not empty'); assert.notOk(_.isEmpty({one: 1}), '{one: 1} is not empty');
assert.ok(_.isEmpty({}), '{} is empty'); assert.ok(_.isEmpty({}), '{} is empty');
assert.ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty'); assert.ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty');
assert.ok(_.isEmpty(null), 'null is empty'); assert.ok(_.isEmpty(null), 'null is empty');
assert.ok(_.isEmpty(), 'undefined is empty'); assert.ok(_.isEmpty(), 'undefined is empty');
assert.ok(_.isEmpty(''), 'the empty string is empty'); assert.ok(_.isEmpty(''), 'the empty string is empty');
assert.ok(!_.isEmpty('moe'), 'but other strings are not'); assert.notOk(_.isEmpty('moe'), 'but other strings are not');
var obj = {one: 1}; var obj = {one: 1};
delete obj.one; delete obj.one;
@@ -592,27 +592,27 @@
var args = function(){ return arguments; }; var args = function(){ return arguments; };
assert.ok(_.isEmpty(args()), 'empty arguments object is empty'); assert.ok(_.isEmpty(args()), 'empty arguments object is empty');
assert.ok(!_.isEmpty(args('')), 'non-empty arguments object is not empty'); assert.notOk(_.isEmpty(args('')), 'non-empty arguments object is not empty');
// covers collecting non-enumerable properties in IE < 9 // covers collecting non-enumerable properties in IE < 9
var nonEnumProp = {toString: 5}; var nonEnumProp = {toString: 5};
assert.ok(!_.isEmpty(nonEnumProp), 'non-enumerable property is not empty'); assert.notOk(_.isEmpty(nonEnumProp), 'non-enumerable property is not empty');
}); });
if (typeof document === 'object') { if (typeof document === 'object') {
QUnit.test('isElement', function(assert) { QUnit.test('isElement', function(assert) {
assert.ok(!_.isElement('div'), 'strings are not dom elements'); assert.notOk(_.isElement('div'), 'strings are not dom elements');
assert.ok(_.isElement(testElement), 'an element is a DOM element'); assert.ok(_.isElement(testElement), 'an element is a DOM element');
}); });
} }
QUnit.test('isArguments', function(assert) { QUnit.test('isArguments', function(assert) {
var args = (function(){ return arguments; }(1, 2, 3)); var args = (function(){ return arguments; }(1, 2, 3));
assert.ok(!_.isArguments('string'), 'a string is not an arguments object'); assert.notOk(_.isArguments('string'), 'a string is not an arguments object');
assert.ok(!_.isArguments(_.isArguments), 'a function is not an arguments object'); assert.notOk(_.isArguments(_.isArguments), 'a function is not an arguments object');
assert.ok(_.isArguments(args), 'but the arguments object is 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.notOk(_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array');
assert.ok(!_.isArguments([1, 2, 3]), 'and not vanilla arrays.'); assert.notOk(_.isArguments([1, 2, 3]), 'and not vanilla arrays.');
}); });
QUnit.test('isObject', function(assert) { QUnit.test('isObject', function(assert) {
@@ -622,24 +622,24 @@
assert.ok(_.isObject(testElement), 'and DOM element'); assert.ok(_.isObject(testElement), 'and DOM element');
} }
assert.ok(_.isObject(function() {}), 'and functions'); assert.ok(_.isObject(function() {}), 'and functions');
assert.ok(!_.isObject(null), 'but not null'); assert.notOk(_.isObject(null), 'but not null');
assert.ok(!_.isObject(void 0), 'and not undefined'); assert.notOk(_.isObject(void 0), 'and not undefined');
assert.ok(!_.isObject('string'), 'and not string'); assert.notOk(_.isObject('string'), 'and not string');
assert.ok(!_.isObject(12), 'and not number'); assert.notOk(_.isObject(12), 'and not number');
assert.ok(!_.isObject(true), 'and not boolean'); assert.notOk(_.isObject(true), 'and not boolean');
assert.ok(_.isObject(new String('string')), 'but new String()'); assert.ok(_.isObject(new String('string')), 'but new String()');
}); });
QUnit.test('isArray', function(assert) { QUnit.test('isArray', function(assert) {
assert.ok(!_.isArray(void 0), 'undefined vars are not arrays'); assert.notOk(_.isArray(void 0), 'undefined vars are not arrays');
assert.ok(!_.isArray(arguments), 'the arguments object is not an array'); assert.notOk(_.isArray(arguments), 'the arguments object is not an array');
assert.ok(_.isArray([1, 2, 3]), 'but arrays are'); assert.ok(_.isArray([1, 2, 3]), 'but arrays are');
}); });
QUnit.test('isString', function(assert) { QUnit.test('isString', function(assert) {
var obj = new String('I am a string object'); var obj = new String('I am a string object');
if (testElement) { if (testElement) {
assert.ok(!_.isString(testElement), 'an element is not a string'); assert.notOk(_.isString(testElement), 'an element is not a string');
} }
assert.ok(_.isString([1, 2, 3].join(', ')), 'but strings are'); assert.ok(_.isString([1, 2, 3].join(', ')), 'but strings are');
assert.strictEqual(_.isString('I am a string literal'), true, 'string literals are'); assert.strictEqual(_.isString('I am a string literal'), true, 'string literals are');
@@ -648,9 +648,9 @@
}); });
QUnit.test('isSymbol', function(assert) { QUnit.test('isSymbol', function(assert) {
assert.ok(!_.isSymbol(0), 'numbers are not symbols'); assert.notOk(_.isSymbol(0), 'numbers are not symbols');
assert.ok(!_.isSymbol(''), 'strings are not symbols'); assert.notOk(_.isSymbol(''), 'strings are not symbols');
assert.ok(!_.isSymbol(_.isSymbol), 'functions are not symbols'); assert.notOk(_.isSymbol(_.isSymbol), 'functions are not symbols');
if (typeof Symbol === 'function') { if (typeof Symbol === 'function') {
assert.ok(_.isSymbol(Symbol()), 'symbols are symbols'); assert.ok(_.isSymbol(Symbol()), 'symbols are symbols');
assert.ok(_.isSymbol(Symbol('description')), 'described symbols are symbols'); assert.ok(_.isSymbol(Symbol('description')), 'described symbols are symbols');
@@ -659,43 +659,43 @@
}); });
QUnit.test('isNumber', function(assert) { QUnit.test('isNumber', function(assert) {
assert.ok(!_.isNumber('string'), 'a string is not a number'); assert.notOk(_.isNumber('string'), 'a string is not a number');
assert.ok(!_.isNumber(arguments), 'the arguments object is not a number'); assert.notOk(_.isNumber(arguments), 'the arguments object is not a number');
assert.ok(!_.isNumber(void 0), 'undefined is not a number'); assert.notOk(_.isNumber(void 0), 'undefined is not a number');
assert.ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are'); assert.ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are');
assert.ok(_.isNumber(NaN), 'NaN *is* a number'); assert.ok(_.isNumber(NaN), 'NaN *is* a number');
assert.ok(_.isNumber(Infinity), 'Infinity is a number'); assert.ok(_.isNumber(Infinity), 'Infinity is a number');
assert.ok(!_.isNumber('1'), 'numeric strings are not numbers'); assert.notOk(_.isNumber('1'), 'numeric strings are not numbers');
}); });
QUnit.test('isBoolean', function(assert) { QUnit.test('isBoolean', function(assert) {
assert.ok(!_.isBoolean(2), 'a number is not a boolean'); assert.notOk(_.isBoolean(2), 'a number is not a boolean');
assert.ok(!_.isBoolean('string'), 'a string is not a boolean'); assert.notOk(_.isBoolean('string'), 'a string is not a boolean');
assert.ok(!_.isBoolean('false'), 'the string "false" is not a boolean'); assert.notOk(_.isBoolean('false'), 'the string "false" is not a boolean');
assert.ok(!_.isBoolean('true'), 'the string "true" is not a boolean'); assert.notOk(_.isBoolean('true'), 'the string "true" is not a boolean');
assert.ok(!_.isBoolean(arguments), 'the arguments object is not a boolean'); assert.notOk(_.isBoolean(arguments), 'the arguments object is not a boolean');
assert.ok(!_.isBoolean(void 0), 'undefined is not a boolean'); assert.notOk(_.isBoolean(void 0), 'undefined is not a boolean');
assert.ok(!_.isBoolean(NaN), 'NaN is not a boolean'); assert.notOk(_.isBoolean(NaN), 'NaN is not a boolean');
assert.ok(!_.isBoolean(null), 'null is not a boolean'); assert.notOk(_.isBoolean(null), 'null is not a boolean');
assert.ok(_.isBoolean(true), 'but true is'); assert.ok(_.isBoolean(true), 'but true is');
assert.ok(_.isBoolean(false), 'and so is false'); assert.ok(_.isBoolean(false), 'and so is false');
}); });
QUnit.test('isMap', function(assert) { QUnit.test('isMap', function(assert) {
assert.ok(!_.isMap('string'), 'a string is not a map'); assert.notOk(_.isMap('string'), 'a string is not a map');
assert.ok(!_.isMap(2), 'a number is not a map'); assert.notOk(_.isMap(2), 'a number is not a map');
assert.ok(!_.isMap({}), 'an object is not a map'); assert.notOk(_.isMap({}), 'an object is not a map');
assert.ok(!_.isMap(false), 'a boolean is not a map'); assert.notOk(_.isMap(false), 'a boolean is not a map');
assert.ok(!_.isMap(void 0), 'undefined is not a map'); assert.notOk(_.isMap(void 0), 'undefined is not a map');
assert.ok(!_.isMap([1, 2, 3]), 'an array is not a map'); assert.notOk(_.isMap([1, 2, 3]), 'an array is not a map');
if (typeof Set === 'function') { if (typeof Set === 'function') {
assert.ok(!_.isMap(new Set()), 'a set is not a map'); assert.notOk(_.isMap(new Set()), 'a set is not a map');
} }
if (typeof WeakSet === 'function') { if (typeof WeakSet === 'function') {
assert.ok(!_.isMap(new WeakSet()), 'a weakset is not a map'); assert.notOk(_.isMap(new WeakSet()), 'a weakset is not a map');
} }
if (typeof WeakMap === 'function') { if (typeof WeakMap === 'function') {
assert.ok(!_.isMap(new WeakMap()), 'a weakmap is not a map'); assert.notOk(_.isMap(new WeakMap()), 'a weakmap is not a map');
} }
if (typeof Map === 'function') { if (typeof Map === 'function') {
var keyString = 'a string'; var keyString = 'a string';
@@ -706,20 +706,20 @@
}); });
QUnit.test('isWeakMap', function(assert) { QUnit.test('isWeakMap', function(assert) {
assert.ok(!_.isWeakMap('string'), 'a string is not a weakmap'); assert.notOk(_.isWeakMap('string'), 'a string is not a weakmap');
assert.ok(!_.isWeakMap(2), 'a number is not a weakmap'); assert.notOk(_.isWeakMap(2), 'a number is not a weakmap');
assert.ok(!_.isWeakMap({}), 'an object is not a weakmap'); assert.notOk(_.isWeakMap({}), 'an object is not a weakmap');
assert.ok(!_.isWeakMap(false), 'a boolean is not a weakmap'); assert.notOk(_.isWeakMap(false), 'a boolean is not a weakmap');
assert.ok(!_.isWeakMap(void 0), 'undefined is not a weakmap'); assert.notOk(_.isWeakMap(void 0), 'undefined is not a weakmap');
assert.ok(!_.isWeakMap([1, 2, 3]), 'an array is not a weakmap'); assert.notOk(_.isWeakMap([1, 2, 3]), 'an array is not a weakmap');
if (typeof Set === 'function') { if (typeof Set === 'function') {
assert.ok(!_.isWeakMap(new Set()), 'a set is not a weakmap'); assert.notOk(_.isWeakMap(new Set()), 'a set is not a weakmap');
} }
if (typeof WeakSet === 'function') { if (typeof WeakSet === 'function') {
assert.ok(!_.isWeakMap(new WeakSet()), 'a weakset is not a weakmap'); assert.notOk(_.isWeakMap(new WeakSet()), 'a weakset is not a weakmap');
} }
if (typeof Map === 'function') { if (typeof Map === 'function') {
assert.ok(!_.isWeakMap(new Map()), 'a map is not a weakmap'); assert.notOk(_.isWeakMap(new Map()), 'a map is not a weakmap');
} }
if (typeof WeakMap === 'function') { if (typeof WeakMap === 'function') {
var keyObj = {}, obj = new WeakMap(); var keyObj = {}, obj = new WeakMap();
@@ -729,20 +729,20 @@
}); });
QUnit.test('isSet', function(assert) { QUnit.test('isSet', function(assert) {
assert.ok(!_.isSet('string'), 'a string is not a set'); assert.notOk(_.isSet('string'), 'a string is not a set');
assert.ok(!_.isSet(2), 'a number is not a set'); assert.notOk(_.isSet(2), 'a number is not a set');
assert.ok(!_.isSet({}), 'an object is not a set'); assert.notOk(_.isSet({}), 'an object is not a set');
assert.ok(!_.isSet(false), 'a boolean is not a set'); assert.notOk(_.isSet(false), 'a boolean is not a set');
assert.ok(!_.isSet(void 0), 'undefined is not a set'); assert.notOk(_.isSet(void 0), 'undefined is not a set');
assert.ok(!_.isSet([1, 2, 3]), 'an array is not a set'); assert.notOk(_.isSet([1, 2, 3]), 'an array is not a set');
if (typeof Map === 'function') { if (typeof Map === 'function') {
assert.ok(!_.isSet(new Map()), 'a map is not a set'); assert.notOk(_.isSet(new Map()), 'a map is not a set');
} }
if (typeof WeakMap === 'function') { if (typeof WeakMap === 'function') {
assert.ok(!_.isSet(new WeakMap()), 'a weakmap is not a set'); assert.notOk(_.isSet(new WeakMap()), 'a weakmap is not a set');
} }
if (typeof WeakSet === 'function') { if (typeof WeakSet === 'function') {
assert.ok(!_.isSet(new WeakSet()), 'a weakset is not a set'); assert.notOk(_.isSet(new WeakSet()), 'a weakset is not a set');
} }
if (typeof Set === 'function') { if (typeof Set === 'function') {
var obj = new Set(); var obj = new Set();
@@ -753,20 +753,20 @@
QUnit.test('isWeakSet', function(assert) { QUnit.test('isWeakSet', function(assert) {
assert.ok(!_.isWeakSet('string'), 'a string is not a weakset'); assert.notOk(_.isWeakSet('string'), 'a string is not a weakset');
assert.ok(!_.isWeakSet(2), 'a number is not a weakset'); assert.notOk(_.isWeakSet(2), 'a number is not a weakset');
assert.ok(!_.isWeakSet({}), 'an object is not a weakset'); assert.notOk(_.isWeakSet({}), 'an object is not a weakset');
assert.ok(!_.isWeakSet(false), 'a boolean is not a weakset'); assert.notOk(_.isWeakSet(false), 'a boolean is not a weakset');
assert.ok(!_.isWeakSet(void 0), 'undefined is not a weakset'); assert.notOk(_.isWeakSet(void 0), 'undefined is not a weakset');
assert.ok(!_.isWeakSet([1, 2, 3]), 'an array is not a weakset'); assert.notOk(_.isWeakSet([1, 2, 3]), 'an array is not a weakset');
if (typeof Map === 'function') { if (typeof Map === 'function') {
assert.ok(!_.isWeakSet(new Map()), 'a map is not a weakset'); assert.notOk(_.isWeakSet(new Map()), 'a map is not a weakset');
} }
if (typeof WeakMap === 'function') { if (typeof WeakMap === 'function') {
assert.ok(!_.isWeakSet(new WeakMap()), 'a weakmap is not a weakset'); assert.notOk(_.isWeakSet(new WeakMap()), 'a weakmap is not a weakset');
} }
if (typeof Set === 'function') { if (typeof Set === 'function') {
assert.ok(!_.isWeakSet(new Set()), 'a set is not a weakset'); assert.notOk(_.isWeakSet(new Set()), 'a set is not a weakset');
} }
if (typeof WeakSet === 'function') { if (typeof WeakSet === 'function') {
var obj = new WeakSet(); var obj = new WeakSet();
@@ -776,19 +776,19 @@
}); });
QUnit.test('isFunction', function(assert) { QUnit.test('isFunction', function(assert) {
assert.ok(!_.isFunction(void 0), 'undefined vars are not functions'); assert.notOk(_.isFunction(void 0), 'undefined vars are not functions');
assert.ok(!_.isFunction([1, 2, 3]), 'arrays are not functions'); assert.notOk(_.isFunction([1, 2, 3]), 'arrays are not functions');
assert.ok(!_.isFunction('moe'), 'strings are not functions'); assert.notOk(_.isFunction('moe'), 'strings are not functions');
assert.ok(_.isFunction(_.isFunction), 'but functions are'); assert.ok(_.isFunction(_.isFunction), 'but functions are');
assert.ok(_.isFunction(function(){}), 'even anonymous ones'); assert.ok(_.isFunction(function(){}), 'even anonymous ones');
if (testElement) { if (testElement) {
assert.ok(!_.isFunction(testElement), 'elements are not functions'); assert.notOk(_.isFunction(testElement), 'elements are not functions');
} }
var nodelist = typeof document != 'undefined' && document.childNodes; var nodelist = typeof document != 'undefined' && document.childNodes;
if (nodelist) { if (nodelist) {
assert.ok(!_.isFunction(nodelist)); assert.notOk(_.isFunction(nodelist));
} }
}); });
@@ -806,65 +806,68 @@
} }
QUnit.test('isDate', function(assert) { QUnit.test('isDate', function(assert) {
assert.ok(!_.isDate(100), 'numbers are not dates'); assert.notOk(_.isDate(100), 'numbers are not dates');
assert.ok(!_.isDate({}), 'objects are not dates'); assert.notOk(_.isDate({}), 'objects are not dates');
assert.ok(_.isDate(new Date()), 'but dates are'); assert.ok(_.isDate(new Date()), 'but dates are');
}); });
QUnit.test('isRegExp', function(assert) { QUnit.test('isRegExp', function(assert) {
assert.ok(!_.isRegExp(_.identity), 'functions are not RegExps'); assert.notOk(_.isRegExp(_.identity), 'functions are not RegExps');
assert.ok(_.isRegExp(/identity/), 'but RegExps are'); assert.ok(_.isRegExp(/identity/), 'but RegExps are');
}); });
QUnit.test('isFinite', function(assert) { QUnit.test('isFinite', function(assert) {
assert.ok(!_.isFinite(void 0), 'undefined is not finite'); assert.notOk(_.isFinite(void 0), 'undefined is not finite');
assert.ok(!_.isFinite(null), 'null is not finite'); assert.notOk(_.isFinite(null), 'null is not finite');
assert.ok(!_.isFinite(NaN), 'NaN is not finite'); assert.notOk(_.isFinite(NaN), 'NaN is not finite');
assert.ok(!_.isFinite(Infinity), 'Infinity is not finite'); assert.notOk(_.isFinite(Infinity), 'Infinity is not finite');
assert.ok(!_.isFinite(-Infinity), '-Infinity is not finite'); assert.notOk(_.isFinite(-Infinity), '-Infinity is not finite');
assert.ok(_.isFinite('12'), 'Numeric strings are numbers'); assert.ok(_.isFinite('12'), 'Numeric strings are numbers');
assert.ok(!_.isFinite('1a'), 'Non numeric strings are not numbers'); assert.notOk(_.isFinite('1a'), 'Non numeric strings are not numbers');
assert.ok(!_.isFinite(''), 'Empty strings are not numbers'); assert.notOk(_.isFinite(''), 'Empty strings are not numbers');
var obj = new Number(5); var obj = new Number(5);
assert.ok(_.isFinite(obj), 'Number instances can be finite'); assert.ok(_.isFinite(obj), 'Number instances can be finite');
assert.ok(_.isFinite(0), '0 is finite'); assert.ok(_.isFinite(0), '0 is finite');
assert.ok(_.isFinite(123), 'Ints are finite'); assert.ok(_.isFinite(123), 'Ints are finite');
assert.ok(_.isFinite(-12.44), 'Floats are finite'); assert.ok(_.isFinite(-12.44), 'Floats are finite');
if (typeof Symbol === 'function') { if (typeof Symbol === 'function') {
assert.ok(!_.isFinite(Symbol()), 'symbols are not numbers'); assert.notOk(_.isFinite(Symbol()), 'symbols are not numbers');
assert.ok(!_.isFinite(Symbol('description')), 'described symbols are not numbers'); assert.notOk(_.isFinite(Symbol('description')), 'described symbols are not numbers');
assert.ok(!_.isFinite(Object(Symbol())), 'boxed symbols are not numbers'); assert.notOk(_.isFinite(Object(Symbol())), 'boxed symbols are not numbers');
} }
}); });
QUnit.test('isNaN', function(assert) { QUnit.test('isNaN', function(assert) {
assert.ok(!_.isNaN(void 0), 'undefined is not NaN'); assert.notOk(_.isNaN(void 0), 'undefined is not NaN');
assert.ok(!_.isNaN(null), 'null is not NaN'); assert.notOk(_.isNaN(null), 'null is not NaN');
assert.ok(!_.isNaN(0), '0 is not NaN'); assert.notOk(_.isNaN(0), '0 is not NaN');
assert.ok(!_.isNaN(new Number(0)), 'wrapped 0 is not NaN'); assert.notOk(_.isNaN(new Number(0)), 'wrapped 0 is not NaN');
assert.ok(_.isNaN(NaN), 'but NaN is'); assert.ok(_.isNaN(NaN), 'but NaN is');
assert.ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN'); assert.ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN');
if (typeof Symbol !== 'undefined'){
assert.notOk(_.isNaN(Symbol()), 'symbol is not NaN');
}
}); });
QUnit.test('isNull', function(assert) { QUnit.test('isNull', function(assert) {
assert.ok(!_.isNull(void 0), 'undefined is not null'); assert.notOk(_.isNull(void 0), 'undefined is not null');
assert.ok(!_.isNull(NaN), 'NaN is not null'); assert.notOk(_.isNull(NaN), 'NaN is not null');
assert.ok(_.isNull(null), 'but null is'); assert.ok(_.isNull(null), 'but null is');
}); });
QUnit.test('isUndefined', function(assert) { QUnit.test('isUndefined', function(assert) {
assert.ok(!_.isUndefined(1), 'numbers are defined'); assert.notOk(_.isUndefined(1), 'numbers are defined');
assert.ok(!_.isUndefined(null), 'null is defined'); assert.notOk(_.isUndefined(null), 'null is defined');
assert.ok(!_.isUndefined(false), 'false is defined'); assert.notOk(_.isUndefined(false), 'false is defined');
assert.ok(!_.isUndefined(NaN), 'NaN is defined'); assert.notOk(_.isUndefined(NaN), 'NaN is defined');
assert.ok(_.isUndefined(), 'nothing is undefined'); assert.ok(_.isUndefined(), 'nothing is undefined');
assert.ok(_.isUndefined(void 0), 'undefined is undefined'); assert.ok(_.isUndefined(void 0), 'undefined is undefined');
}); });
QUnit.test('isError', function(assert) { QUnit.test('isError', function(assert) {
assert.ok(!_.isError(1), 'numbers are not Errors'); assert.notOk(_.isError(1), 'numbers are not Errors');
assert.ok(!_.isError(null), 'null is not an Error'); assert.notOk(_.isError(null), 'null is not an Error');
assert.ok(!_.isError(Error), 'functions are not Errors'); assert.notOk(_.isError(Error), 'functions are not Errors');
assert.ok(_.isError(new Error()), 'Errors are Errors'); assert.ok(_.isError(new Error()), 'Errors are Errors');
assert.ok(_.isError(new EvalError()), 'EvalErrors are Errors'); assert.ok(_.isError(new EvalError()), 'EvalErrors are Errors');
assert.ok(_.isError(new RangeError()), 'RangeErrors are Errors'); assert.ok(_.isError(new RangeError()), 'RangeErrors are Errors');
@@ -893,13 +896,13 @@
QUnit.test('has', function(assert) { QUnit.test('has', function(assert) {
var obj = {foo: 'bar', func: function(){}}; var obj = {foo: 'bar', func: function(){}};
assert.ok(_.has(obj, 'foo'), 'has() checks that the object has a property.'); 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.notOk(_.has(obj, 'baz'), "has() returns false if the object doesn't have the property.");
assert.ok(_.has(obj, 'func'), 'has() works for functions too.'); assert.ok(_.has(obj, 'func'), 'has() works for functions too.');
obj.hasOwnProperty = null; obj.hasOwnProperty = null;
assert.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 = {}; var child = {};
child.prototype = obj; child.prototype = obj;
assert.ok(!_.has(child, 'foo'), 'has() does not check the prototype chain for a property.'); assert.notOk(_.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(null, 'foo'), false, 'has() returns false for null');
assert.strictEqual(_.has(void 0, 'foo'), false, 'has() returns false for undefined'); assert.strictEqual(_.has(void 0, 'foo'), false, 'has() returns false for undefined');
}); });
@@ -958,8 +961,8 @@
assert.equal(_.matcher({})(null), true, 'Empty spec called with null object returns true'); 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'); assert.equal(_.matcher({a: 1})(null), false, 'Non-empty spec called with null object returns false');
assert.ok(_.find(stooges, _.matcher({hair: false})) === curly, 'returns a predicate that can be used by finding functions.'); assert.strictEqual(_.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.strictEqual(_.find(stooges, _.matcher(moe)), moe, 'can be used to locate an object exists in a collection.');
assert.deepEqual(_.filter([null, void 0], _.matcher({a: 1})), [], 'Do not throw on null values.'); assert.deepEqual(_.filter([null, void 0], _.matcher({a: 1})), [], 'Do not throw on null values.');
assert.deepEqual(_.filter([null, void 0], _.matcher(null)), [null, void 0], 'null matches null'); assert.deepEqual(_.filter([null, void 0], _.matcher(null)), [null, void 0], 'null matches null');

View File

@@ -52,8 +52,8 @@
QUnit.test('#750 - Return _ instance.', function(assert) { QUnit.test('#750 - Return _ instance.', function(assert) {
assert.expect(2); assert.expect(2);
var instance = _([]); var instance = _([]);
assert.ok(_(instance) === instance); assert.strictEqual(_(instance), instance);
assert.ok(new _(instance) === instance); assert.strictEqual(new _(instance), instance);
}); });
QUnit.test('identity', function(assert) { QUnit.test('identity', function(assert) {
@@ -137,11 +137,12 @@
}); });
QUnit.test('mixin', function(assert) { QUnit.test('mixin', function(assert) {
_.mixin({ var ret = _.mixin({
myReverse: function(string) { myReverse: function(string) {
return string.split('').reverse().join(''); return string.split('').reverse().join('');
} }
}); });
assert.equal(ret, _, 'returns the _ object to facilitate chaining');
assert.equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _'); assert.equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _');
assert.equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); assert.equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
}); });
@@ -188,7 +189,7 @@
var str = 'some string & another string & yet another'; var str = 'some string & another string & yet another';
var escaped = _.escape(str); var escaped = _.escape(str);
assert.ok(escaped.indexOf('&') !== -1, 'handles & aka &amp;'); assert.notStrictEqual(escaped.indexOf('&'), -1, 'handles & aka &amp;');
assert.equal(_.unescape(str), str, 'can unescape &amp;'); assert.equal(_.unescape(str), str, 'can unescape &amp;');
}); });
@@ -370,9 +371,9 @@
}); });
QUnit.test('#547 - _.templateSettings is unchanged by custom settings.', function(assert) { QUnit.test('#547 - _.templateSettings is unchanged by custom settings.', function(assert) {
assert.ok(!_.templateSettings.variable); assert.notOk(_.templateSettings.variable);
_.template('', {}, {variable: 'x'}); _.template('', {}, {variable: 'x'});
assert.ok(!_.templateSettings.variable); assert.notOk(_.templateSettings.variable);
}); });
QUnit.test('#556 - undefined template variables.', function(assert) { QUnit.test('#556 - undefined template variables.', function(assert) {
@@ -397,11 +398,11 @@
assert.expect(2); assert.expect(2);
var count = 0; var count = 0;
var template = _.template('<%= f() %>'); var template = _.template('<%= f() %>');
template({f: function(){ assert.ok(!count++); }}); template({f: function(){ assert.notOk(count++); }});
var countEscaped = 0; var countEscaped = 0;
var templateEscaped = _.template('<%- f() %>'); var templateEscaped = _.template('<%- f() %>');
templateEscaped({f: function(){ assert.ok(!countEscaped++); }}); templateEscaped({f: function(){ assert.notOk(countEscaped++); }});
}); });
QUnit.test('#746 - _.template settings are not modified.', function(assert) { QUnit.test('#746 - _.template settings are not modified.', function(assert) {

View File

@@ -84,18 +84,23 @@
}; };
}; };
var builtinIteratee;
// An internal function to generate callbacks that can be applied to each // An internal function to generate callbacks that can be applied to each
// element in a collection, returning the desired result — either `identity`, // element in a collection, returning the desired result — either `identity`,
// an arbitrary callback, a property matcher, or a property accessor. // an arbitrary callback, a property matcher, or a property accessor.
var cb = function(value, context, argCount) { var cb = function(value, context, argCount) {
if (_.iteratee !== builtinIteratee) return _.iteratee(value, context);
if (value == null) return _.identity; if (value == null) return _.identity;
if (_.isFunction(value)) return optimizeCb(value, context, argCount); if (_.isFunction(value)) return optimizeCb(value, context, argCount);
if (_.isObject(value)) return _.matcher(value); if (_.isObject(value)) return _.matcher(value);
return _.property(value); return _.property(value);
}; };
// An external wrapper for the internal callback generator. // External wrapper for our callback generator. Users may customize
_.iteratee = function(value, context) { // `_.iteratee` if they want additional predicate/iteratee shorthand styles.
// This abstraction hides the internal-only argCount argument.
_.iteratee = builtinIteratee = function(value, context) {
return cb(value, context, Infinity); return cb(value, context, Infinity);
}; };
@@ -439,7 +444,7 @@
// Keep surrogate pair characters together // Keep surrogate pair characters together
return obj.match(reStrSymbol); return obj.match(reStrSymbol);
} }
if (isArrayLike(obj)) return _.map(obj); if (isArrayLike(obj)) return _.map(obj, _.identity);
return _.values(obj); return _.values(obj);
}; };
@@ -462,7 +467,7 @@
// values in the array. Aliased as `head` and `take`. The **guard** check // values in the array. Aliased as `head` and `take`. The **guard** check
// allows it to work with `_.map`. // allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) { _.first = _.head = _.take = function(array, n, guard) {
if (array == null) return void 0; if (array == null || array.length < 1) return void 0;
if (n == null || guard) return array[0]; if (n == null || guard) return array[0];
return _.initial(array, array.length - n); return _.initial(array, array.length - n);
}; };
@@ -477,7 +482,7 @@
// Get the last element of an array. Passing **n** will return the last N // Get the last element of an array. Passing **n** will return the last N
// values in the array. // values in the array.
_.last = function(array, n, guard) { _.last = function(array, n, guard) {
if (array == null) return void 0; if (array == null || array.length < 1) return void 0;
if (n == null || guard) return array[array.length - 1]; if (n == null || guard) return array[array.length - 1];
return _.rest(array, Math.max(0, array.length - n)); return _.rest(array, Math.max(0, array.length - n));
}; };
@@ -491,7 +496,7 @@
// Trim out all falsy values from an array. // Trim out all falsy values from an array.
_.compact = function(array) { _.compact = function(array) {
return _.filter(array); return _.filter(array, Boolean);
}; };
// Internal implementation of a recursive `flatten` function. // Internal implementation of a recursive `flatten` function.
@@ -1094,7 +1099,7 @@
return result; return result;
}); });
// Return a copy of the object without the blacklisted properties. // Return a copy of the object without the blacklisted properties.
_.omit = restArgs(function(obj, keys) { _.omit = restArgs(function(obj, keys) {
var iteratee = keys[0], context; var iteratee = keys[0], context;
if (_.isFunction(iteratee)) { if (_.isFunction(iteratee)) {
@@ -1403,7 +1408,7 @@
return new Date().getTime(); return new Date().getTime();
}; };
// List of HTML entities for escaping. // List of HTML entities for escaping.
var escapeMap = { var escapeMap = {
'&': '&amp;', '&': '&amp;',
'<': '&lt;', '<': '&lt;',
@@ -1568,6 +1573,7 @@
return chainResult(this, func.apply(_, args)); return chainResult(this, func.apply(_, args));
}; };
}); });
return _;
}; };
// Add all of the Underscore functions to the wrapper object. // Add all of the Underscore functions to the wrapper object.
@@ -1602,7 +1608,7 @@
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value; _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
_.prototype.toString = function() { _.prototype.toString = function() {
return '' + this._wrapped; return String(this._wrapped);
}; };
// AMD registration happens at the end for compatibility with AMD loaders // AMD registration happens at the end for compatibility with AMD loaders