Built motion from commit fd239ea.|0.0.31
[motion.git] / public / bower_components / lodash / vendor / underscore / test / arrays.js
1 (function() {
2   var _ = typeof require == 'function' ? require('..') : window._;
3
4   QUnit.module('Arrays');
5
6   QUnit.test('first', function(assert) {
7     assert.equal(_.first([1, 2, 3]), 1, 'can pull out the first element of an array');
8     assert.equal(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"');
9     assert.deepEqual(_.first([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)');
10     assert.deepEqual(_.first([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)');
11     assert.deepEqual(_.first([1, 2, 3], 2), [1, 2], 'can fetch the first n elements');
12     assert.deepEqual(_.first([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length');
13     var result = (function(){ return _.first(arguments); }(4, 3, 2, 1));
14     assert.equal(result, 4, 'works on an arguments object');
15     result = _.map([[1, 2, 3], [1, 2, 3]], _.first);
16     assert.deepEqual(result, [1, 1], 'works well with _.map');
17     assert.equal(_.first(null), void 0, 'returns undefined when called on null');
18   });
19
20   QUnit.test('head', function(assert) {
21     assert.strictEqual(_.head, _.first, 'is an alias for first');
22   });
23
24   QUnit.test('take', function(assert) {
25     assert.strictEqual(_.take, _.first, 'is an alias for first');
26   });
27
28   QUnit.test('rest', function(assert) {
29     var numbers = [1, 2, 3, 4];
30     assert.deepEqual(_.rest(numbers), [2, 3, 4], 'fetches all but the first element');
31     assert.deepEqual(_.rest(numbers, 0), [1, 2, 3, 4], 'returns the whole array when index is 0');
32     assert.deepEqual(_.rest(numbers, 2), [3, 4], 'returns elements starting at the given index');
33     var result = (function(){ return _(arguments).rest(); }(1, 2, 3, 4));
34     assert.deepEqual(result, [2, 3, 4], 'works on an arguments object');
35     result = _.map([[1, 2, 3], [1, 2, 3]], _.rest);
36     assert.deepEqual(_.flatten(result), [2, 3, 2, 3], 'works well with _.map');
37   });
38
39   QUnit.test('tail', function(assert) {
40     assert.strictEqual(_.tail, _.rest, 'is an alias for rest');
41   });
42
43   QUnit.test('drop', function(assert) {
44     assert.strictEqual(_.drop, _.rest, 'is an alias for rest');
45   });
46
47   QUnit.test('initial', function(assert) {
48     assert.deepEqual(_.initial([1, 2, 3, 4, 5]), [1, 2, 3, 4], 'returns all but the last element');
49     assert.deepEqual(_.initial([1, 2, 3, 4], 2), [1, 2], 'returns all but the last n elements');
50     assert.deepEqual(_.initial([1, 2, 3, 4], 6), [], 'returns an empty array when n > length');
51     var result = (function(){ return _(arguments).initial(); }(1, 2, 3, 4));
52     assert.deepEqual(result, [1, 2, 3], 'works on an arguments object');
53     result = _.map([[1, 2, 3], [1, 2, 3]], _.initial);
54     assert.deepEqual(_.flatten(result), [1, 2, 1, 2], 'works well with _.map');
55   });
56
57   QUnit.test('last', function(assert) {
58     assert.equal(_.last([1, 2, 3]), 3, 'can pull out the last element of an array');
59     assert.equal(_([1, 2, 3]).last(), 3, 'can perform OO-style "last()"');
60     assert.deepEqual(_.last([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)');
61     assert.deepEqual(_.last([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)');
62     assert.deepEqual(_.last([1, 2, 3], 2), [2, 3], 'can fetch the last n elements');
63     assert.deepEqual(_.last([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length');
64     var result = (function(){ return _(arguments).last(); }(1, 2, 3, 4));
65     assert.equal(result, 4, 'works on an arguments object');
66     result = _.map([[1, 2, 3], [1, 2, 3]], _.last);
67     assert.deepEqual(result, [3, 3], 'works well with _.map');
68     assert.equal(_.last(null), void 0, 'returns undefined when called on null');
69   });
70
71   QUnit.test('compact', function(assert) {
72     assert.deepEqual(_.compact([1, false, null, 0, '', void 0, NaN, 2]), [1, 2], 'removes all falsy values');
73     var result = (function(){ return _.compact(arguments); }(0, 1, false, 2, false, 3));
74     assert.deepEqual(result, [1, 2, 3], 'works on an arguments object');
75     result = _.map([[1, false, false], [false, false, 3]], _.compact);
76     assert.deepEqual(result, [[1], [3]], 'works well with _.map');
77   });
78
79   QUnit.test('flatten', function(assert) {
80     assert.deepEqual(_.flatten(null), [], 'supports null');
81     assert.deepEqual(_.flatten(void 0), [], 'supports undefined');
82
83     assert.deepEqual(_.flatten([[], [[]], []]), [], 'supports empty arrays');
84     assert.deepEqual(_.flatten([[], [[]], []], true), [[]], 'can shallowly flatten empty arrays');
85
86     var list = [1, [2], [3, [[[4]]]]];
87     assert.deepEqual(_.flatten(list), [1, 2, 3, 4], 'can flatten nested arrays');
88     assert.deepEqual(_.flatten(list, true), [1, 2, 3, [[[4]]]], 'can shallowly flatten nested arrays');
89     var result = (function(){ return _.flatten(arguments); }(1, [2], [3, [[[4]]]]));
90     assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object');
91     list = [[1], [2], [3], [[4]]];
92     assert.deepEqual(_.flatten(list, true), [1, 2, 3, [4]], 'can shallowly flatten arrays containing only other arrays');
93
94     assert.equal(_.flatten([_.range(10), _.range(10), 5, 1, 3], true).length, 23, 'can flatten medium length arrays');
95     assert.equal(_.flatten([_.range(10), _.range(10), 5, 1, 3]).length, 23, 'can shallowly flatten medium length arrays');
96     assert.equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3]).length, 1056003, 'can handle massive arrays');
97     assert.equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3], true).length, 1056003, 'can handle massive arrays in shallow mode');
98
99     var x = _.range(100000);
100     for (var i = 0; i < 1000; i++) x = [x];
101     assert.deepEqual(_.flatten(x), _.range(100000), 'can handle very deep arrays');
102     assert.deepEqual(_.flatten(x, true), x[0], 'can handle very deep arrays in shallow mode');
103   });
104
105   QUnit.test('without', function(assert) {
106     var list = [1, 2, 1, 0, 3, 1, 4];
107     assert.deepEqual(_.without(list, 0, 1), [2, 3, 4], 'removes all instances of the given values');
108     var result = (function(){ return _.without(arguments, 0, 1); }(1, 2, 1, 0, 3, 1, 4));
109     assert.deepEqual(result, [2, 3, 4], 'works on an arguments object');
110
111     list = [{one: 1}, {two: 2}];
112     assert.deepEqual(_.without(list, {one: 1}), list, 'compares objects by reference (value case)');
113     assert.deepEqual(_.without(list, list[0]), [{two: 2}], 'compares objects by reference (reference case)');
114   });
115
116   QUnit.test('sortedIndex', function(assert) {
117     var numbers = [10, 20, 30, 40, 50];
118     var indexFor35 = _.sortedIndex(numbers, 35);
119     assert.equal(indexFor35, 3, 'finds the index at which a value should be inserted to retain order');
120     var indexFor30 = _.sortedIndex(numbers, 30);
121     assert.equal(indexFor30, 2, 'finds the smallest index at which a value could be inserted to retain order');
122
123     var objects = [{x: 10}, {x: 20}, {x: 30}, {x: 40}];
124     var iterator = function(obj){ return obj.x; };
125     assert.strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2, 'uses the result of `iterator` for order comparisons');
126     assert.strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3, 'when `iterator` is a string, uses that key for order comparisons');
127
128     var context = {1: 2, 2: 3, 3: 4};
129     iterator = function(obj){ return this[obj]; };
130     assert.strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1, 'can execute its iterator in the given context');
131
132     var values = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287,
133         1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647];
134     var largeArray = Array(Math.pow(2, 32) - 1);
135     var length = values.length;
136     // Sparsely populate `array`
137     while (length--) {
138       largeArray[values[length]] = values[length];
139     }
140     assert.equal(_.sortedIndex(largeArray, 2147483648), 2147483648, 'works with large indexes');
141   });
142
143   QUnit.test('uniq', function(assert) {
144     var list = [1, 2, 1, 3, 1, 4];
145     assert.deepEqual(_.uniq(list), [1, 2, 3, 4], 'can find the unique values of an unsorted array');
146
147     list = [1, 1, 1, 2, 2, 3];
148     assert.deepEqual(_.uniq(list, true), [1, 2, 3], 'can find the unique values of a sorted array faster');
149
150     list = [{name: 'moe'}, {name: 'curly'}, {name: 'larry'}, {name: 'curly'}];
151     var iterator = function(value) { return value.name; };
152     assert.deepEqual(_.map(_.uniq(list, false, iterator), iterator), ['moe', 'curly', 'larry'], 'can find the unique values of an array using a custom iterator');
153
154     assert.deepEqual(_.map(_.uniq(list, iterator), iterator), ['moe', 'curly', 'larry'], 'can find the unique values of an array using a custom iterator without specifying whether array is sorted');
155
156     iterator = function(value) { return value + 1; };
157     list = [1, 2, 2, 3, 4, 4];
158     assert.deepEqual(_.uniq(list, true, iterator), [1, 2, 3, 4], 'iterator works with sorted array');
159
160     var kittens = [
161       {kitten: 'Celery', cuteness: 8},
162       {kitten: 'Juniper', cuteness: 10},
163       {kitten: 'Spottis', cuteness: 10}
164     ];
165
166     var expected = [
167       {kitten: 'Celery', cuteness: 8},
168       {kitten: 'Juniper', cuteness: 10}
169     ];
170
171     assert.deepEqual(_.uniq(kittens, true, 'cuteness'), expected, 'string iterator works with sorted array');
172
173
174     var result = (function(){ return _.uniq(arguments); }(1, 2, 1, 3, 1, 4));
175     assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object');
176
177     var a = {}, b = {}, c = {};
178     assert.deepEqual(_.uniq([a, b, a, b, c]), [a, b, c], 'works on values that can be tested for equivalency but not ordered');
179
180     assert.deepEqual(_.uniq(null), []);
181
182     var context = {};
183     list = [3];
184     _.uniq(list, function(value, index, array) {
185       assert.strictEqual(this, context);
186       assert.strictEqual(value, 3);
187       assert.strictEqual(index, 0);
188       assert.strictEqual(array, list);
189     }, context);
190
191     assert.deepEqual(_.uniq([{a: 1, b: 1}, {a: 1, b: 2}, {a: 1, b: 3}, {a: 2, b: 1}], 'a'), [{a: 1, b: 1}, {a: 2, b: 1}], 'can use pluck like iterator');
192     assert.deepEqual(_.uniq([{0: 1, b: 1}, {0: 1, b: 2}, {0: 1, b: 3}, {0: 2, b: 1}], 0), [{0: 1, b: 1}, {0: 2, b: 1}], 'can use falsey pluck like iterator');
193   });
194
195   QUnit.test('unique', function(assert) {
196     assert.strictEqual(_.unique, _.uniq, 'is an alias for uniq');
197   });
198
199   QUnit.test('intersection', function(assert) {
200     var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho'];
201     assert.deepEqual(_.intersection(stooges, leaders), ['moe'], 'can take the set intersection of two arrays');
202     assert.deepEqual(_(stooges).intersection(leaders), ['moe'], 'can perform an OO-style intersection');
203     var result = (function(){ return _.intersection(arguments, leaders); }('moe', 'curly', 'larry'));
204     assert.deepEqual(result, ['moe'], 'works on an arguments object');
205     var theSixStooges = ['moe', 'moe', 'curly', 'curly', 'larry', 'larry'];
206     assert.deepEqual(_.intersection(theSixStooges, leaders), ['moe'], 'returns a duplicate-free array');
207     result = _.intersection([2, 4, 3, 1], [1, 2, 3]);
208     assert.deepEqual(result, [2, 3, 1], 'preserves order of first array');
209     result = _.intersection(null, [1, 2, 3]);
210     assert.equal(Object.prototype.toString.call(result), '[object Array]', 'returns an empty array when passed null as first argument');
211     assert.equal(result.length, 0, 'returns an empty array when passed null as first argument');
212     result = _.intersection([1, 2, 3], null);
213     assert.equal(Object.prototype.toString.call(result), '[object Array]', 'returns an empty array when passed null as argument beyond the first');
214     assert.equal(result.length, 0, 'returns an empty array when passed null as argument beyond the first');
215   });
216
217   QUnit.test('union', function(assert) {
218     var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]);
219     assert.deepEqual(result, [1, 2, 3, 30, 40], 'takes the union of a list of arrays');
220
221     result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]);
222     assert.deepEqual(result, [1, 2, 3, 30, 40, [1]], 'takes the union of a list of nested arrays');
223
224     var args = null;
225     (function(){ args = arguments; }(1, 2, 3));
226     result = _.union(args, [2, 30, 1], [1, 40]);
227     assert.deepEqual(result, [1, 2, 3, 30, 40], 'takes the union of a list of arrays');
228
229     result = _.union([1, 2, 3], 4);
230     assert.deepEqual(result, [1, 2, 3], 'restrict the union to arrays only');
231   });
232
233   QUnit.test('difference', function(assert) {
234     var result = _.difference([1, 2, 3], [2, 30, 40]);
235     assert.deepEqual(result, [1, 3], 'takes the difference of two arrays');
236
237     result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]);
238     assert.deepEqual(result, [3, 4], 'takes the difference of three arrays');
239
240     result = _.difference([1, 2, 3], 1);
241     assert.deepEqual(result, [1, 2, 3], 'restrict the difference to arrays only');
242   });
243
244   QUnit.test('zip', function(assert) {
245     var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true];
246     assert.deepEqual(_.zip(names, ages, leaders), [
247       ['moe', 30, true],
248       ['larry', 40, void 0],
249       ['curly', 50, void 0]
250     ], 'zipped together arrays of different lengths');
251
252     var stooges = _.zip(['moe', 30, 'stooge 1'], ['larry', 40, 'stooge 2'], ['curly', 50, 'stooge 3']);
253     assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], ['stooge 1', 'stooge 2', 'stooge 3']], 'zipped pairs');
254
255     // In the case of different lengths of the tuples, undefined values
256     // should be used as placeholder
257     stooges = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']);
258     assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], [void 0, void 0, 'extra data']], 'zipped pairs with empties');
259
260     var empty = _.zip([]);
261     assert.deepEqual(empty, [], 'unzipped empty');
262
263     assert.deepEqual(_.zip(null), [], 'handles null');
264     assert.deepEqual(_.zip(), [], '_.zip() returns []');
265   });
266
267   QUnit.test('unzip', function(assert) {
268     assert.deepEqual(_.unzip(null), [], 'handles null');
269
270     assert.deepEqual(_.unzip([['a', 'b'], [1, 2]]), [['a', 1], ['b', 2]]);
271
272     // complements zip
273     var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);
274     assert.deepEqual(_.unzip(zipped), [['fred', 'barney'], [30, 40], [true, false]]);
275
276     zipped = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']);
277     assert.deepEqual(_.unzip(zipped), [['moe', 30, void 0], ['larry', 40, void 0], ['curly', 50, 'extra data']], 'Uses length of largest array');
278   });
279
280   QUnit.test('object', function(assert) {
281     var result = _.object(['moe', 'larry', 'curly'], [30, 40, 50]);
282     var shouldBe = {moe: 30, larry: 40, curly: 50};
283     assert.deepEqual(result, shouldBe, 'two arrays zipped together into an object');
284
285     result = _.object([['one', 1], ['two', 2], ['three', 3]]);
286     shouldBe = {one: 1, two: 2, three: 3};
287     assert.deepEqual(result, shouldBe, 'an array of pairs zipped together into an object');
288
289     var stooges = {moe: 30, larry: 40, curly: 50};
290     assert.deepEqual(_.object(_.pairs(stooges)), stooges, 'an object converted to pairs and back to an object');
291
292     assert.deepEqual(_.object(null), {}, 'handles nulls');
293   });
294
295   QUnit.test('indexOf', function(assert) {
296     var numbers = [1, 2, 3];
297     assert.equal(_.indexOf(numbers, 2), 1, 'can compute indexOf');
298     var result = (function(){ return _.indexOf(arguments, 2); }(1, 2, 3));
299     assert.equal(result, 1, 'works on an arguments object');
300
301     _.each([null, void 0, [], false], function(val) {
302       var msg = 'Handles: ' + (_.isArray(val) ? '[]' : val);
303       assert.equal(_.indexOf(val, 2), -1, msg);
304       assert.equal(_.indexOf(val, 2, -1), -1, msg);
305       assert.equal(_.indexOf(val, 2, -20), -1, msg);
306       assert.equal(_.indexOf(val, 2, 15), -1, msg);
307     });
308
309     var num = 35;
310     numbers = [10, 20, 30, 40, 50];
311     var index = _.indexOf(numbers, num, true);
312     assert.equal(index, -1, '35 is not in the list');
313
314     numbers = [10, 20, 30, 40, 50]; num = 40;
315     index = _.indexOf(numbers, num, true);
316     assert.equal(index, 3, '40 is in the list');
317
318     numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40;
319     assert.equal(_.indexOf(numbers, num, true), 1, '40 is in the list');
320     assert.equal(_.indexOf(numbers, 6, true), -1, '6 isnt in the list');
321     assert.equal(_.indexOf([1, 2, 5, 4, 6, 7], 5, true), -1, 'sorted indexOf doesn\'t uses binary search');
322     assert.ok(_.every(['1', [], {}, null], function() {
323       return _.indexOf(numbers, num, {}) === 1;
324     }), 'non-nums as fromIndex make indexOf assume sorted');
325
326     numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
327     index = _.indexOf(numbers, 2, 5);
328     assert.equal(index, 7, 'supports the fromIndex argument');
329
330     index = _.indexOf([,,, 0], void 0);
331     assert.equal(index, 0, 'treats sparse arrays as if they were dense');
332
333     var array = [1, 2, 3, 1, 2, 3];
334     assert.strictEqual(_.indexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index');
335     assert.strictEqual(_.indexOf(array, 1, -2), -1, 'neg `fromIndex` starts at the right index');
336     assert.strictEqual(_.indexOf(array, 2, -3), 4);
337     _.each([-6, -8, -Infinity], function(fromIndex) {
338       assert.strictEqual(_.indexOf(array, 1, fromIndex), 0);
339     });
340     assert.strictEqual(_.indexOf([1, 2, 3], 1, true), 0);
341
342     index = _.indexOf([], void 0, true);
343     assert.equal(index, -1, 'empty array with truthy `isSorted` returns -1');
344   });
345
346   QUnit.test('indexOf with NaN', function(assert) {
347     assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN), 2, 'Expected [1, 2, NaN] to contain NaN');
348     assert.strictEqual(_.indexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN');
349
350     assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, 1), 2, 'startIndex does not affect result');
351     assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, -2), 2, 'startIndex does not affect result');
352
353     (function() {
354       assert.strictEqual(_.indexOf(arguments, NaN), 2, 'Expected arguments [1, 2, NaN] to contain NaN');
355     }(1, 2, NaN, NaN));
356   });
357
358   QUnit.test('indexOf with +- 0', function(assert) {
359     _.each([-0, +0], function(val) {
360       assert.strictEqual(_.indexOf([1, 2, val, val], val), 2);
361       assert.strictEqual(_.indexOf([1, 2, val, val], -val), 2);
362     });
363   });
364
365   QUnit.test('lastIndexOf', function(assert) {
366     var numbers = [1, 0, 1];
367     var falsey = [void 0, '', 0, false, NaN, null, void 0];
368     assert.equal(_.lastIndexOf(numbers, 1), 2);
369
370     numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
371     numbers.lastIndexOf = null;
372     assert.equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
373     assert.equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
374     var result = (function(){ return _.lastIndexOf(arguments, 1); }(1, 0, 1, 0, 0, 1, 0, 0, 0));
375     assert.equal(result, 5, 'works on an arguments object');
376
377     _.each([null, void 0, [], false], function(val) {
378       var msg = 'Handles: ' + (_.isArray(val) ? '[]' : val);
379       assert.equal(_.lastIndexOf(val, 2), -1, msg);
380       assert.equal(_.lastIndexOf(val, 2, -1), -1, msg);
381       assert.equal(_.lastIndexOf(val, 2, -20), -1, msg);
382       assert.equal(_.lastIndexOf(val, 2, 15), -1, msg);
383     });
384
385     numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
386     var index = _.lastIndexOf(numbers, 2, 2);
387     assert.equal(index, 1, 'supports the fromIndex argument');
388
389     var array = [1, 2, 3, 1, 2, 3];
390
391     assert.strictEqual(_.lastIndexOf(array, 1, 0), 0, 'starts at the correct from idx');
392     assert.strictEqual(_.lastIndexOf(array, 3), 5, 'should return the index of the last matched value');
393     assert.strictEqual(_.lastIndexOf(array, 4), -1, 'should return `-1` for an unmatched value');
394
395     assert.strictEqual(_.lastIndexOf(array, 1, 2), 0, 'should work with a positive `fromIndex`');
396
397     _.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) {
398       assert.strictEqual(_.lastIndexOf(array, void 0, fromIndex), -1);
399       assert.strictEqual(_.lastIndexOf(array, 1, fromIndex), 3);
400       assert.strictEqual(_.lastIndexOf(array, '', fromIndex), -1);
401     });
402
403     var expected = _.map(falsey, function(value) {
404       return typeof value == 'number' ? -1 : 5;
405     });
406
407     var actual = _.map(falsey, function(fromIndex) {
408       return _.lastIndexOf(array, 3, fromIndex);
409     });
410
411     assert.deepEqual(actual, expected, 'should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`');
412     assert.strictEqual(_.lastIndexOf(array, 3, '1'), 5, 'should treat non-number `fromIndex` values as `array.length`');
413     assert.strictEqual(_.lastIndexOf(array, 3, true), 5, 'should treat non-number `fromIndex` values as `array.length`');
414
415     assert.strictEqual(_.lastIndexOf(array, 2, -3), 1, 'should work with a negative `fromIndex`');
416     assert.strictEqual(_.lastIndexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index');
417
418     assert.deepEqual(_.map([-6, -8, -Infinity], function(fromIndex) {
419       return _.lastIndexOf(array, 1, fromIndex);
420     }), [0, -1, -1]);
421   });
422
423   QUnit.test('lastIndexOf with NaN', function(assert) {
424     assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN), 3, 'Expected [1, 2, NaN] to contain NaN');
425     assert.strictEqual(_.lastIndexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN');
426
427     assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, 2), 2, 'fromIndex does not affect result');
428     assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, -2), 2, 'fromIndex does not affect result');
429
430     (function() {
431       assert.strictEqual(_.lastIndexOf(arguments, NaN), 3, 'Expected arguments [1, 2, NaN] to contain NaN');
432     }(1, 2, NaN, NaN));
433   });
434
435   QUnit.test('lastIndexOf with +- 0', function(assert) {
436     _.each([-0, +0], function(val) {
437       assert.strictEqual(_.lastIndexOf([1, 2, val, val], val), 3);
438       assert.strictEqual(_.lastIndexOf([1, 2, val, val], -val), 3);
439       assert.strictEqual(_.lastIndexOf([-1, 1, 2], -val), -1);
440     });
441   });
442
443   QUnit.test('findIndex', function(assert) {
444     var objects = [
445       {a: 0, b: 0},
446       {a: 1, b: 1},
447       {a: 2, b: 2},
448       {a: 0, b: 0}
449     ];
450
451     assert.equal(_.findIndex(objects, function(obj) {
452       return obj.a === 0;
453     }), 0);
454
455     assert.equal(_.findIndex(objects, function(obj) {
456       return obj.b * obj.a === 4;
457     }), 2);
458
459     assert.equal(_.findIndex(objects, 'a'), 1, 'Uses lookupIterator');
460
461     assert.equal(_.findIndex(objects, function(obj) {
462       return obj.b * obj.a === 5;
463     }), -1);
464
465     assert.equal(_.findIndex(null, _.noop), -1);
466     assert.strictEqual(_.findIndex(objects, function(a) {
467       return a.foo === null;
468     }), -1);
469     _.findIndex([{a: 1}], function(a, key, obj) {
470       assert.equal(key, 0);
471       assert.deepEqual(obj, [{a: 1}]);
472       assert.strictEqual(this, objects, 'called with context');
473     }, objects);
474
475     var sparse = [];
476     sparse[20] = {a: 2, b: 2};
477     assert.equal(_.findIndex(sparse, function(obj) {
478       return obj && obj.b * obj.a === 4;
479     }), 20, 'Works with sparse arrays');
480
481     var array = [1, 2, 3, 4];
482     array.match = 55;
483     assert.strictEqual(_.findIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys');
484   });
485
486   QUnit.test('findLastIndex', function(assert) {
487     var objects = [
488       {a: 0, b: 0},
489       {a: 1, b: 1},
490       {a: 2, b: 2},
491       {a: 0, b: 0}
492     ];
493
494     assert.equal(_.findLastIndex(objects, function(obj) {
495       return obj.a === 0;
496     }), 3);
497
498     assert.equal(_.findLastIndex(objects, function(obj) {
499       return obj.b * obj.a === 4;
500     }), 2);
501
502     assert.equal(_.findLastIndex(objects, 'a'), 2, 'Uses lookupIterator');
503
504     assert.equal(_.findLastIndex(objects, function(obj) {
505       return obj.b * obj.a === 5;
506     }), -1);
507
508     assert.equal(_.findLastIndex(null, _.noop), -1);
509     assert.strictEqual(_.findLastIndex(objects, function(a) {
510       return a.foo === null;
511     }), -1);
512     _.findLastIndex([{a: 1}], function(a, key, obj) {
513       assert.equal(key, 0);
514       assert.deepEqual(obj, [{a: 1}]);
515       assert.strictEqual(this, objects, 'called with context');
516     }, objects);
517
518     var sparse = [];
519     sparse[20] = {a: 2, b: 2};
520     assert.equal(_.findLastIndex(sparse, function(obj) {
521       return obj && obj.b * obj.a === 4;
522     }), 20, 'Works with sparse arrays');
523
524     var array = [1, 2, 3, 4];
525     array.match = 55;
526     assert.strictEqual(_.findLastIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys');
527   });
528
529   QUnit.test('range', function(assert) {
530     assert.deepEqual(_.range(0), [], 'range with 0 as a first argument generates an empty array');
531     assert.deepEqual(_.range(4), [0, 1, 2, 3], 'range with a single positive argument generates an array of elements 0,1,2,...,n-1');
532     assert.deepEqual(_.range(5, 8), [5, 6, 7], 'range with two arguments a &amp; b, a&lt;b generates an array of elements a,a+1,a+2,...,b-2,b-1');
533     assert.deepEqual(_.range(3, 10, 3), [3, 6, 9], 'range with three arguments a &amp; b &amp; c, c &lt; b-a, a &lt; b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) &lt; c');
534     assert.deepEqual(_.range(3, 10, 15), [3], 'range with three arguments a &amp; b &amp; c, c &gt; b-a, a &lt; b generates an array with a single element, equal to a');
535     assert.deepEqual(_.range(12, 7, -2), [12, 10, 8], 'range with three arguments a &amp; b &amp; c, a &gt; b, c &lt; 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b');
536     assert.deepEqual(_.range(0, -10, -1), [0, -1, -2, -3, -4, -5, -6, -7, -8, -9], 'final example in the Python docs');
537     assert.strictEqual(1 / _.range(-0, 1)[0], -Infinity, 'should preserve -0');
538     assert.deepEqual(_.range(8, 5), [8, 7, 6], 'negative range generates descending array');
539     assert.deepEqual(_.range(-3), [0, -1, -2], 'negative range generates descending array');
540   });
541
542   QUnit.test('chunk', function(assert) {
543     assert.deepEqual(_.chunk([], 2), [], 'chunk for empty array returns an empty array');
544
545     assert.deepEqual(_.chunk([1, 2, 3], 0), [], 'chunk into parts of 0 elements returns empty array');
546     assert.deepEqual(_.chunk([1, 2, 3], -1), [], 'chunk into parts of negative amount of elements returns an empty array');
547     assert.deepEqual(_.chunk([1, 2, 3]), [], 'defaults to empty array (chunk size 0)');
548
549     assert.deepEqual(_.chunk([1, 2, 3], 1), [[1], [2], [3]], 'chunk into parts of 1 elements returns original array');
550
551     assert.deepEqual(_.chunk([1, 2, 3], 3), [[1, 2, 3]], 'chunk into parts of current array length elements returns the original array');
552     assert.deepEqual(_.chunk([1, 2, 3], 5), [[1, 2, 3]], 'chunk into parts of more then current array length elements returns the original array');
553
554     assert.deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 2), [[10, 20], [30, 40], [50, 60], [70]], 'chunk into parts of less then current array length elements');
555     assert.deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 3), [[10, 20, 30], [40, 50, 60], [70]], 'chunk into parts of less then current array length elements');
556   });
557 }());