mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-09 10:27:49 +00:00
Add more unit tests to increase coverage.
This commit is contained in:
@@ -22,6 +22,9 @@
|
|||||||
Array._isArray = Array.isArray;
|
Array._isArray = Array.isArray;
|
||||||
Array.isArray = function() { return false; };
|
Array.isArray = function() { return false; };
|
||||||
|
|
||||||
|
Date._now = Date.now;
|
||||||
|
Date.now = function() {};
|
||||||
|
|
||||||
Function.prototype._bind = Function.prototype.bind;
|
Function.prototype._bind = Function.prototype.bind;
|
||||||
Function.prototype.bind = function() { return function() {}; };
|
Function.prototype.bind = function() { return function() {}; };
|
||||||
|
|
||||||
@@ -34,7 +37,7 @@
|
|||||||
Object._keys = Object.keys;
|
Object._keys = Object.keys;
|
||||||
Object.keys = function() { return []; };
|
Object.keys = function() { return []; };
|
||||||
|
|
||||||
// load Lo-Dash and expose it to the bad `Object.keys` shim
|
// load Lo-Dash and expose it to the bad shims
|
||||||
document.write('<script src="' + (ui.isModularize ? '../lodash.js' : ui.buildPath) + '"><\/script>');
|
document.write('<script src="' + (ui.isModularize ? '../lodash.js' : ui.buildPath) + '"><\/script>');
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
@@ -47,6 +50,11 @@
|
|||||||
} else {
|
} else {
|
||||||
delete Array.isArray;
|
delete Array.isArray;
|
||||||
}
|
}
|
||||||
|
if (Date._now) {
|
||||||
|
Date.now = Date._now;
|
||||||
|
} else {
|
||||||
|
delete Date.now;
|
||||||
|
}
|
||||||
if (Function.prototype._bind) {
|
if (Function.prototype._bind) {
|
||||||
Function.prototype.bind = Function.prototype._bind;
|
Function.prototype.bind = Function.prototype._bind;
|
||||||
} else {
|
} else {
|
||||||
@@ -68,6 +76,7 @@
|
|||||||
delete Object.keys;
|
delete Object.keys;
|
||||||
}
|
}
|
||||||
delete Array._isArray;
|
delete Array._isArray;
|
||||||
|
delete Date._now;
|
||||||
delete Function.prototype._bind;
|
delete Function.prototype._bind;
|
||||||
delete Object._create;
|
delete Object._create;
|
||||||
delete Object._defineProperty;
|
delete Object._defineProperty;
|
||||||
|
|||||||
231
test/test.js
231
test/test.js
@@ -1,6 +1,9 @@
|
|||||||
;(function(root, undefined) {
|
;(function(root, undefined) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
/** Used to store Lo-Dash to test for bad shim detection */
|
||||||
|
var lodashBadShim;
|
||||||
|
|
||||||
/** Method and object shortcuts */
|
/** Method and object shortcuts */
|
||||||
var phantom = root.phantom,
|
var phantom = root.phantom,
|
||||||
amd = root.define && define.amd,
|
amd = root.define && define.amd,
|
||||||
@@ -176,6 +179,18 @@
|
|||||||
/** Used to check problem JScript properties too */
|
/** Used to check problem JScript properties too */
|
||||||
var shadowedObject = _.invert(shadowedProps);
|
var shadowedObject = _.invert(shadowedProps);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all own enumerable properties from a given object.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} object The object to empty.
|
||||||
|
*/
|
||||||
|
function emptyObject(object) {
|
||||||
|
_.forOwn(object, function(value, key, object) {
|
||||||
|
delete object[key];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skips a given number of tests with a passing result.
|
* Skips a given number of tests with a passing result.
|
||||||
*
|
*
|
||||||
@@ -195,6 +210,8 @@
|
|||||||
(function() {
|
(function() {
|
||||||
if (!amd) {
|
if (!amd) {
|
||||||
try {
|
try {
|
||||||
|
emptyObject(require.cache);
|
||||||
|
|
||||||
_.extend(_, require('vm').runInNewContext([
|
_.extend(_, require('vm').runInNewContext([
|
||||||
'({',
|
'({',
|
||||||
"'_arguments': (function() { return arguments; }(1, 2, 3)),",
|
"'_arguments': (function() { return arguments; }(1, 2, 3)),",
|
||||||
@@ -211,6 +228,42 @@
|
|||||||
"'_undefined': undefined,",
|
"'_undefined': undefined,",
|
||||||
'})'
|
'})'
|
||||||
].join('\n')));
|
].join('\n')));
|
||||||
|
|
||||||
|
// set bad shims
|
||||||
|
Array._isArray = Array.isArray;
|
||||||
|
Array.isArray = function() { return false; };
|
||||||
|
|
||||||
|
Date._now = Date.now;
|
||||||
|
Date.now = function() {};
|
||||||
|
|
||||||
|
Function.prototype._bind = Function.prototype.bind;
|
||||||
|
Function.prototype.bind = function() { return function() {}; };
|
||||||
|
|
||||||
|
Object._create = Object.create;
|
||||||
|
Object.create = function() {};
|
||||||
|
|
||||||
|
Object._defineProperty = Object.defineProperty;
|
||||||
|
Object.defineProperty = function() {};
|
||||||
|
|
||||||
|
Object._keys = Object.keys;
|
||||||
|
Object.keys = function() { return []; };
|
||||||
|
|
||||||
|
// load Lo-Dash and expose it to the bad shims
|
||||||
|
lodashBadShim = require(filePath);
|
||||||
|
|
||||||
|
// restore native methods
|
||||||
|
Array.isArray = Array._isArray;
|
||||||
|
Date.now = Date._now;
|
||||||
|
Function.prototype.bind = Function.prototype._bind;
|
||||||
|
Object.create = Object._create;
|
||||||
|
Object.defineProperty = Object._defineProperty;
|
||||||
|
Object.keys = Object._keys;
|
||||||
|
|
||||||
|
delete Array._isArray;
|
||||||
|
delete Function.prototype._bind;
|
||||||
|
delete Object._create;
|
||||||
|
delete Object._defineProperty;
|
||||||
|
delete Object._keys;
|
||||||
} catch(e) { }
|
} catch(e) { }
|
||||||
}
|
}
|
||||||
if (!_._object && document) {
|
if (!_._object && document) {
|
||||||
@@ -307,14 +360,16 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('avoids overwritten native methods', 4, function() {
|
test('avoids overwritten native methods', 5, function() {
|
||||||
|
function Foo() {}
|
||||||
|
|
||||||
function message(methodName) {
|
function message(methodName) {
|
||||||
return '`_.' + methodName + '` should avoid overwritten native methods';
|
return '`_.' + methodName + '` should avoid overwritten native methods';
|
||||||
}
|
}
|
||||||
|
|
||||||
var object = { 'a': true };
|
var object = { 'a': true };
|
||||||
|
|
||||||
if (document) {
|
if (lodashBadShim) {
|
||||||
try {
|
try {
|
||||||
var actual = lodashBadShim.bind(function() { return this.a; }, object)();
|
var actual = lodashBadShim.bind(function() { return this.a; }, object)();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
@@ -322,6 +377,13 @@
|
|||||||
}
|
}
|
||||||
ok(actual, message('bind'));
|
ok(actual, message('bind'));
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual = lodashBadShim.create(Foo.prototype, object);
|
||||||
|
} catch(e) {
|
||||||
|
actual = null;
|
||||||
|
}
|
||||||
|
ok(actual instanceof Foo, message('create'));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
actual = lodashBadShim.isArray([]);
|
actual = lodashBadShim.isArray([]);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
@@ -337,20 +399,14 @@
|
|||||||
deepEqual(actual, ['a'], message('keys'));
|
deepEqual(actual, ['a'], message('keys'));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var Foo = function() {
|
actual = lodashBadShim.now();
|
||||||
this.a = 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
var actual = _.transform(new Foo, function(result, value, key) {
|
|
||||||
result[key] = value * value;
|
|
||||||
});
|
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
actual = null;
|
actual = null;
|
||||||
}
|
}
|
||||||
ok(actual instanceof Foo, message('transform'));
|
ok(typeof actual == 'number', message('now'));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
skipTest(4);
|
skipTest(5);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}());
|
}());
|
||||||
@@ -585,7 +641,6 @@
|
|||||||
function Foo() {
|
function Foo() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
var bound = _.bind(Foo, { 'a': 1 }),
|
var bound = _.bind(Foo, { 'a': 1 }),
|
||||||
newBound = new bound;
|
newBound = new bound;
|
||||||
|
|
||||||
@@ -594,10 +649,15 @@
|
|||||||
ok(newBound instanceof Foo);
|
ok(newBound instanceof Foo);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('ensure `new bound` is an instance of `func`', 1, function() {
|
test('ensure `new bound` is an instance of `func`', 2, function() {
|
||||||
var bound = _.bind(noop, {});
|
function Foo(value) {
|
||||||
|
return value && object;
|
||||||
|
}
|
||||||
|
var bound = _.bind(Foo),
|
||||||
|
object = {};
|
||||||
|
|
||||||
ok(new bound instanceof noop);
|
ok(new bound instanceof Foo);
|
||||||
|
strictEqual(new bound(true), object);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should append array arguments to partially applied arguments (test in IE < 9)', 1, function() {
|
test('should append array arguments to partially applied arguments (test in IE < 9)', 1, function() {
|
||||||
@@ -1276,11 +1336,12 @@
|
|||||||
|
|
||||||
test('should return the function provided if already bound with `Function#bind`', 1, function() {
|
test('should return the function provided if already bound with `Function#bind`', 1, function() {
|
||||||
function a() {}
|
function a() {}
|
||||||
|
var object = {};
|
||||||
|
|
||||||
var bound = a.bind && a.bind({});
|
var bound = a.bind && a.bind(object);
|
||||||
if (bound && !('prototype' in bound)) {
|
if (bound && !('prototype' in bound)) {
|
||||||
var bound = a.bind({});
|
var bound = a.bind(object);
|
||||||
strictEqual(_.createCallback(bound, {}), bound);
|
strictEqual(_.createCallback(bound, object), bound);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
skipTest();
|
skipTest();
|
||||||
@@ -1291,28 +1352,43 @@
|
|||||||
function a() {}
|
function a() {}
|
||||||
function b() { return this.b; }
|
function b() { return this.b; }
|
||||||
|
|
||||||
|
var object = {};
|
||||||
|
|
||||||
if (_.support.funcDecomp) {
|
if (_.support.funcDecomp) {
|
||||||
strictEqual(_.createCallback(a, {}), a);
|
strictEqual(_.createCallback(a, object), a);
|
||||||
notStrictEqual(_.createCallback(b, {}), b);
|
notStrictEqual(_.createCallback(b, object), b);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
skipTest(2);
|
skipTest(2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should only write `__bindData__` to named functions', 2, function() {
|
test('should only write `__bindData__` to named functions', 3, function() {
|
||||||
function a() {};
|
function a() {};
|
||||||
var b = function() {};
|
function c() {};
|
||||||
|
|
||||||
|
var b = function() {},
|
||||||
|
object = {};
|
||||||
|
|
||||||
if (defineProperty && _.support.funcDecomp) {
|
if (defineProperty && _.support.funcDecomp) {
|
||||||
_.createCallback(a, {});
|
_.createCallback(a, object);
|
||||||
ok('__bindData__' in a)
|
ok('__bindData__' in a)
|
||||||
|
|
||||||
_.createCallback(b, {});
|
_.createCallback(b, object);
|
||||||
ok(!('__bindData__' in b));
|
ok(!('__bindData__' in b));
|
||||||
|
|
||||||
|
if (_.support.funcNames) {
|
||||||
|
_.support.funcNames = false;
|
||||||
|
_.createCallback(c, object);
|
||||||
|
ok('__bindData__' in c);
|
||||||
|
_.support.funcNames = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
skipTest(2);
|
skipTest(3);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}());
|
}());
|
||||||
@@ -1354,6 +1430,17 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('ensure `new bound` is an instance of `func`', 2, function() {
|
||||||
|
function Foo(value) {
|
||||||
|
return value && object;
|
||||||
|
}
|
||||||
|
var bound = _.curry(Foo),
|
||||||
|
object = {};
|
||||||
|
|
||||||
|
ok(new bound(false) instanceof Foo);
|
||||||
|
strictEqual(new bound(true), object);
|
||||||
|
});
|
||||||
|
|
||||||
test('should not alter the `this` binding', 9, function() {
|
test('should not alter the `this` binding', 9, function() {
|
||||||
function func(a, b, c) {
|
function func(a, b, c) {
|
||||||
var value = this || {};
|
var value = this || {};
|
||||||
@@ -1797,6 +1884,16 @@
|
|||||||
deepEqual(_.difference(array1, array2), []);
|
deepEqual(_.difference(array1, array2), []);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should work with large arrays of objects', 1, function() {
|
||||||
|
var object = {};
|
||||||
|
|
||||||
|
var largeArray = _.times(largeArraySize, function() {
|
||||||
|
return object;
|
||||||
|
});
|
||||||
|
|
||||||
|
deepEqual(_.difference(largeArray, [object]), []);
|
||||||
|
});
|
||||||
|
|
||||||
test('should ignore individual secondary values', 1, function() {
|
test('should ignore individual secondary values', 1, function() {
|
||||||
var array = [1, null, 3];
|
var array = [1, null, 3];
|
||||||
deepEqual(_.difference(array, null, 3), array);
|
deepEqual(_.difference(array, null, 3), array);
|
||||||
@@ -2004,6 +2101,14 @@
|
|||||||
strictEqual(func(objects, function(object) { return object.a == 3; }), expected[1]);
|
strictEqual(func(objects, function(object) { return object.a == 3; }), expected[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should work with an object for `collection`', 1, function() {
|
||||||
|
var actual = _.find({ 'a': 1, 'b': 2, 'c': 3 }, function(num) {
|
||||||
|
return num > 2;
|
||||||
|
});
|
||||||
|
|
||||||
|
equal(actual, 3);
|
||||||
|
});
|
||||||
|
|
||||||
test('should work with an object for `callback`', 1, function() {
|
test('should work with an object for `callback`', 1, function() {
|
||||||
strictEqual(func(objects, { 'b': 2 }), expected[2]);
|
strictEqual(func(objects, { 'b': 2 }), expected[2]);
|
||||||
});
|
});
|
||||||
@@ -2688,19 +2793,19 @@
|
|||||||
QUnit.module('`__proto__` property bugs');
|
QUnit.module('`__proto__` property bugs');
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var stringLiteral = '__proto__',
|
|
||||||
stringObject = Object(stringLiteral),
|
|
||||||
expected = [stringLiteral, stringObject];
|
|
||||||
|
|
||||||
var array = _.times(largeArraySize, function(count) {
|
|
||||||
return count % 2 ? stringObject : stringLiteral;
|
|
||||||
});
|
|
||||||
|
|
||||||
test('internal data objects should work with the `__proto__` key', 4, function() {
|
test('internal data objects should work with the `__proto__` key', 4, function() {
|
||||||
deepEqual(_.difference(array, array), []);
|
var stringLiteral = '__proto__',
|
||||||
deepEqual(_.intersection(array, array), expected);
|
stringObject = Object(stringLiteral),
|
||||||
deepEqual(_.uniq(array), expected);
|
expected = [stringLiteral, stringObject];
|
||||||
deepEqual(_.without.apply(_, [array].concat(array)), []);
|
|
||||||
|
var largeArray = _.times(largeArraySize, function(count) {
|
||||||
|
return count % 2 ? stringObject : stringLiteral;
|
||||||
|
});
|
||||||
|
|
||||||
|
deepEqual(_.difference(largeArray, largeArray), []);
|
||||||
|
deepEqual(_.intersection(largeArray, largeArray), expected);
|
||||||
|
deepEqual(_.uniq(largeArray), expected);
|
||||||
|
deepEqual(_.without.apply(_, [largeArray].concat(largeArray)), []);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('lodash.memoize should memoize values resolved to the `__proto__` key', 1, function() {
|
test('lodash.memoize should memoize values resolved to the `__proto__` key', 1, function() {
|
||||||
@@ -3123,6 +3228,17 @@
|
|||||||
deepEqual(actual, [1, 2]);
|
deepEqual(actual, [1, 2]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should work with large arrays of objects', 1, function() {
|
||||||
|
var object = {},
|
||||||
|
expected = [object];
|
||||||
|
|
||||||
|
var largeArray = _.times(largeArraySize, function() {
|
||||||
|
return object;
|
||||||
|
});
|
||||||
|
|
||||||
|
deepEqual(_.intersection(expected, largeArray), expected);
|
||||||
|
});
|
||||||
|
|
||||||
test('should return a wrapped value when chaining', 2, function() {
|
test('should return a wrapped value when chaining', 2, function() {
|
||||||
if (!isNpm) {
|
if (!isNpm) {
|
||||||
var actual = _([1, 3, 2]).intersection([5, 2, 1, 4]);
|
var actual = _([1, 3, 2]).intersection([5, 2, 1, 4]);
|
||||||
@@ -4208,6 +4324,8 @@
|
|||||||
QUnit.module('lodash.isPlainObject');
|
QUnit.module('lodash.isPlainObject');
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
var element = document && document.createElement('div');
|
||||||
|
|
||||||
test('should detect plain objects', 5, function() {
|
test('should detect plain objects', 5, function() {
|
||||||
function Foo(a) {
|
function Foo(a) {
|
||||||
this.a = 1;
|
this.a = 1;
|
||||||
@@ -4222,13 +4340,27 @@
|
|||||||
} else {
|
} else {
|
||||||
skipTest();
|
skipTest();
|
||||||
}
|
}
|
||||||
if (document) {
|
if (element) {
|
||||||
strictEqual(_.isPlainObject(body), false);
|
strictEqual(_.isPlainObject(element), false);
|
||||||
} else {
|
} else {
|
||||||
skipTest();
|
skipTest();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should return `true` for plain objects with a custom `valueOf` property', 2, function() {
|
||||||
|
strictEqual(_.isPlainObject({ 'valueOf': 0 }), true);
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
var valueOf = element.valueOf;
|
||||||
|
element.valueOf = 0;
|
||||||
|
strictEqual(_.isPlainObject(element), false);
|
||||||
|
element.valueOf = valueOf;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('should return `true` for empty objects', 1, function() {
|
test('should return `true` for empty objects', 1, function() {
|
||||||
strictEqual(_.isPlainObject({}), true);
|
strictEqual(_.isPlainObject({}), true);
|
||||||
});
|
});
|
||||||
@@ -5502,6 +5634,17 @@
|
|||||||
strictEqual(actual.length, 0);
|
strictEqual(actual.length, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('ensure `new bound` is an instance of `func`', 2, function() {
|
||||||
|
function Foo(value) {
|
||||||
|
return value && object;
|
||||||
|
}
|
||||||
|
var bound = func(Foo),
|
||||||
|
object = {};
|
||||||
|
|
||||||
|
ok(new bound instanceof Foo);
|
||||||
|
strictEqual(new bound(true), object);
|
||||||
|
});
|
||||||
|
|
||||||
test('`_.' + methodName + '` should clone `__bindData__` for created functions', 3, function() {
|
test('`_.' + methodName + '` should clone `__bindData__` for created functions', 3, function() {
|
||||||
function greet(greeting, name) {
|
function greet(greeting, name) {
|
||||||
return greeting + ' ' + name;
|
return greeting + ' ' + name;
|
||||||
@@ -7642,6 +7785,16 @@
|
|||||||
deepEqual(_.uniq(array), [1, 2, 3]);
|
deepEqual(_.uniq(array), [1, 2, 3]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should work with large arrays of objects', 1, function() {
|
||||||
|
var object = {};
|
||||||
|
|
||||||
|
var largeArray = _.times(largeArraySize, function() {
|
||||||
|
return object;
|
||||||
|
});
|
||||||
|
|
||||||
|
deepEqual(_.uniq(largeArray), [object]);
|
||||||
|
});
|
||||||
|
|
||||||
test('should work with a `callback`', 1, function() {
|
test('should work with a `callback`', 1, function() {
|
||||||
var actual = _.uniq(objects, false, function(object) {
|
var actual = _.uniq(objects, false, function(object) {
|
||||||
return object.a;
|
return object.a;
|
||||||
|
|||||||
Reference in New Issue
Block a user