@samitouri / QOS-React / commits / 2723323006

Remove OrderedMap and ReactPropTransferer

These are not exposed publicly and have been deprecated.

Dan Abramov committed Mar 31, 2016 at 14:38 UTC 27233230064316a8820cd1eb825adf3ea68b8160
3 files changed -1553
src/isomorphic/deprecated/OrderedMap.js deleted
-505
@@ -1,505 +0,0 @@
1 -/**
2 - * Copyright 2013-present, Facebook, Inc.
3 - * All rights reserved.
4 - *
5 - * This source code is licensed under the BSD-style license found in the
6 - * LICENSE file in the root directory of this source tree. An additional grant
7 - * of patent rights can be found in the PATENTS file in the same directory.
8 - *
9 - * @providesModule OrderedMap
10 - */
11 -
12 -'use strict';
13 -
14 -var invariant = require('invariant');
15 -
16 -var PREFIX = 'key:';
17 -
18 -/**
19 - * Utility to extract a backing object from an initialization `Array`, allowing
20 - * the caller to assist in resolving the unique ID for each entry via the
21 - * `keyExtractor` callback. The `keyExtractor` must extract non-empty strings or
22 - * numbers.
23 - * @param {Array<Object!>} arr Array of items.
24 - * @param {function} keyExtractor Extracts a unique key from each item.
25 - * @return {Object} Map from unique key to originating value that the key was
26 - * extracted from.
27 - * @throws Exception if the initialization array has duplicate extracted keys.
28 - */
29 -function extractObjectFromArray(arr, keyExtractor) {
30 - var normalizedObj = {};
31 - for (var i = 0; i < arr.length; i++) {
32 - var item = arr[i];
33 - var key = keyExtractor(item);
34 - assertValidPublicKey(key);
35 - var normalizedKey = PREFIX + key;
36 - invariant(
37 - !(normalizedKey in normalizedObj),
38 - 'OrderedMap: IDs returned by the key extraction function must be unique.'
39 - );
40 - normalizedObj[normalizedKey] = item;
41 - }
42 - return normalizedObj;
43 -}
44 -
45 -/**
46 - * Utility class for mappings with ordering. This class is to be used in an
47 - * immutable manner. A `OrderedMap` is very much like the native JavaScript
48 - * object, where keys map to values via the `get()` function. Also, like the
49 - * native JavaScript object, there is an ordering associated with the mapping.
50 - * This class is helpful because it eliminates many of the pitfalls that come
51 - * with the native JavaScript ordered mappings. Specifically, there are
52 - * inconsistencies with numeric keys in some JavaScript implementations
53 - * (enumeration ordering). This class protects against those pitfalls and
54 - * provides functional utilities for dealing with these `OrderedMap`s.
55 - *
56 - * - TODO:
57 - * - orderedMergeExclusive: Merges mutually exclusive `OrderedMap`s.
58 - * - mapReverse().
59 - *
60 - * @class {OrderedMap}
61 - * @constructor {OrderedMap}
62 - * @param {Object} normalizedObj Object that is known to be a defensive copy of
63 - * caller supplied data. We require a defensive copy to guard against callers
64 - * mutating. It is also assumed that the keys of `normalizedObj` have been
65 - * normalized and do not contain any numeric-appearing strings.
66 - * @param {number} computedLength The precomputed length of `_normalizedObj`
67 - * keys.
68 - * @private
69 - */
70 -function OrderedMapImpl(normalizedObj, computedLength) {
71 - this._normalizedObj = normalizedObj;
72 - this._computedPositions = null;
73 - this.length = computedLength;
74 -}
75 -
76 -/**
77 - * Validates a "public" key - that is, one that the public facing API supplies.
78 - * The key is then normalized for internal storage. In order to be considered
79 - * valid, all keys must be non-empty, defined, non-null strings or numbers.
80 - *
81 - * @param {string?} key Validates that the key is suitable for use in a
82 - * `OrderedMap`.
83 - * @throws Error if key is not appropriate for use in `OrderedMap`.
84 - */
85 -function assertValidPublicKey(key) {
86 - invariant(
87 - key !== '' && (typeof key === 'string' || typeof key === 'number'),
88 - 'OrderedMap: Key must be non-empty, non-null string or number.'
89 - );
90 -}
91 -
92 -/**
93 - * Validates that arguments to range operations are within the correct limits.
94 - *
95 - * @param {number} start Start of range.
96 - * @param {number} length Length of range.
97 - * @param {number} actualLen Actual length of range that should not be
98 - * exceeded.
99 - * @throws Error if range arguments are out of bounds.
100 - */
101 -function assertValidRangeIndices(start, length, actualLen) {
102 - invariant(
103 - typeof start === 'number' &&
104 - typeof length === 'number' &&
105 - length >= 0 &&
106 - start >= 0 &&
107 - start + length <= actualLen,
108 - 'OrderedMap: `mapRange` and `forEachRange` expect non-negative start and ' +
109 - 'length arguments within the bounds of the instance.'
110 - );
111 -}
112 -
113 -/**
114 - * Merges two "normalized" objects (objects who's key have been normalized) into
115 - * a `OrderedMap`.
116 - *
117 - * @param {Object} a Object of key value pairs.
118 - * @param {Object} b Object of key value pairs.
119 - * @return {OrderedMap} new `OrderedMap` that results in merging `a` and `b`.
120 - */
121 -function _fromNormalizedObjects(a, b) {
122 - // Second optional, both must be plain JavaScript objects.
123 - invariant(
124 - a && a.constructor === Object && (!b || b.constructor === Object),
125 - 'OrderedMap: Corrupted instance of OrderedMap detected.'
126 - );
127 -
128 - var newSet = {};
129 - var length = 0;
130 - var key;
131 - for (key in a) {
132 - if (a.hasOwnProperty(key)) {
133 - newSet[key] = a[key];
134 - length++;
135 - }
136 - }
137 -
138 - for (key in b) {
139 - if (b.hasOwnProperty(key)) {
140 - // Increment length if not already added via first object (a)
141 - if (!(key in newSet)) {
142 - length++;
143 - }
144 - newSet[key] = b[key];
145 - }
146 - }
147 - return new OrderedMapImpl(newSet, length);
148 -}
149 -
150 -/**
151 - * Methods for `OrderedMap` instances.
152 - *
153 - * @lends OrderedMap.prototype
154 - * TODO: Make this data structure lazy, unify with LazyArray.
155 - * TODO: Unify this with ImmutableObject - it is to be used immutably.
156 - * TODO: If so, consider providing `fromObject` API.
157 - * TODO: Create faster implementation of merging/mapping from original Array,
158 - * without having to first create an object - simply for the sake of merging.
159 - */
160 -var OrderedMapMethods = {
161 -
162 - /**
163 - * Returns whether or not a given key is present in the map.
164 - *
165 - * @param {string} key Valid string key to lookup membership for.
166 - * @return {boolean} Whether or not `key` is a member of the map.
167 - * @throws Error if provided known invalid key.
168 - */
169 - has: function(key) {
170 - assertValidPublicKey(key);
171 - var normalizedKey = PREFIX + key;
172 - return normalizedKey in this._normalizedObj;
173 - },
174 -
175 - /**
176 - * Returns the object for a given key, or `undefined` if not present. To
177 - * distinguish an undefined entry vs not being in the set, use `has()`.
178 - *
179 - * @param {string} key String key to lookup the value for.
180 - * @return {Object?} Object at key `key`, or undefined if not in map.
181 - * @throws Error if provided known invalid key.
182 - */
183 - get: function(key) {
184 - assertValidPublicKey(key);
185 - var normalizedKey = PREFIX + key;
186 - return this.has(key) ? this._normalizedObj[normalizedKey] : undefined;
187 - },
188 -
189 - /**
190 - * Merges, appending new keys to the end of the ordering. Keys in `orderedMap`
191 - * that are redundant with `this`, maintain the same ordering index that they
192 - * had in `this`. This is how standard JavaScript object merging would work.
193 - * If you wish to prepend a `OrderedMap` to the beginning of another
194 - * `OrderedMap` then simply reverse the order of operation. This is the analog
195 - * to `merge(x, y)`.
196 - *
197 - * @param {OrderedMap} orderedMap OrderedMap to merge onto the end.
198 - * @return {OrderedMap} New OrderedMap that represents the result of the
199 - * merge.
200 - */
201 - merge: function(orderedMap) {
202 - invariant(
203 - orderedMap instanceof OrderedMapImpl,
204 - 'OrderedMap.merge(...): Expected an OrderedMap instance.'
205 - );
206 - return _fromNormalizedObjects(
207 - this._normalizedObj,
208 - orderedMap._normalizedObj
209 - );
210 - },
211 -
212 - /**
213 - * Functional map API. Returns a new `OrderedMap`.
214 - *
215 - * @param {Function} cb Callback to invoke for each item.
216 - * @param {Object?=} context Context to invoke callback from.
217 - * @return {OrderedMap} OrderedMap that results from mapping.
218 - */
219 - map: function(cb, context) {
220 - return this.mapRange(cb, 0, this.length, context);
221 - },
222 -
223 - /**
224 - * The callback `cb` is invoked with the arguments (item, key,
225 - * indexInOriginal).
226 - *
227 - * @param {Function} cb Determines result for each item.
228 - * @param {number} start Start index of map range.
229 - * @param {end} length End index of map range.
230 - * @param {*!?} context Context of callback invocation.
231 - * @return {OrderedMap} OrderedMap resulting from mapping the range.
232 - */
233 - mapRange: function(cb, start, length, context) {
234 - var thisSet = this._normalizedObj;
235 - var newSet = {};
236 - var i = 0;
237 - assertValidRangeIndices(start, length, this.length);
238 - var end = start + length - 1;
239 - for (var key in thisSet) {
240 - if (thisSet.hasOwnProperty(key)) {
241 - if (i >= start) {
242 - if (i > end) {
243 - break;
244 - }
245 - var item = thisSet[key];
246 - newSet[key] = cb.call(context, item, key.substr(PREFIX.length), i);
247 - }
248 - i++;
249 - }
250 - }
251 - return new OrderedMapImpl(newSet, length);
252 - },
253 -
254 - /**
255 - * Function filter API. Returns new `OrderedMap`.
256 - *
257 - * @param {Function} cb Callback to invoke for each item.
258 - * @param {Object?=} context Context to invoke callback from.
259 - * @return {OrderedMap} OrderedMap that results from filtering.
260 - */
261 - filter: function(cb, context) {
262 - return this.filterRange(cb, 0, this.length, context);
263 - },
264 -
265 - /**
266 - * The callback `cb` is invoked with the arguments (item, key,
267 - * indexInOriginal).
268 - *
269 - * @param {Function} cb Returns true if item should be in result.
270 - * @param {number} start Start index of filter range.
271 - * @param {number} length End index of map range.
272 - * @param {*!?} context Context of callback invocation.
273 - * @return {OrderedMap} OrderedMap resulting from filtering the range.
274 - */
275 - filterRange: function(cb, start, length, context) {
276 - var newSet = {};
277 - var newSetLength = 0;
278 - this.forEachRange(function(item, key, originalIndex) {
279 - if (cb.call(context, item, key, originalIndex)) {
280 - var normalizedKey = PREFIX + key;
281 - newSet[normalizedKey] = item;
282 - newSetLength++;
283 - }
284 - }, start, length);
285 - return new OrderedMapImpl(newSet, newSetLength);
286 - },
287 -
288 - forEach: function(cb, context) {
289 - this.forEachRange(cb, 0, this.length, context);
290 - },
291 -
292 - forEachRange: function(cb, start, length, context) {
293 - assertValidRangeIndices(start, length, this.length);
294 - var thisSet = this._normalizedObj;
295 - var i = 0;
296 - var end = start + length - 1;
297 - for (var key in thisSet) {
298 - if (thisSet.hasOwnProperty(key)) {
299 - if (i >= start) {
300 - if (i > end) {
301 - break;
302 - }
303 - var item = thisSet[key];
304 - cb.call(context, item, key.substr(PREFIX.length), i);
305 - }
306 - i++;
307 - }
308 - }
309 - },
310 -
311 - /**
312 - * Even though `mapRange`/`forEachKeyRange` allow zero length mappings, we'll
313 - * impose an additional restriction here that the length of mapping be greater
314 - * than zero - the only reason is that there are many ways to express length
315 - * zero in terms of two keys and that is confusing.
316 - */
317 - mapKeyRange: function(cb, startKey, endKey, context) {
318 - var startIndex = this.indexOfKey(startKey);
319 - var endIndex = this.indexOfKey(endKey);
320 - invariant(
321 - startIndex !== undefined && endIndex !== undefined,
322 - 'mapKeyRange must be given keys that are present.'
323 - );
324 - invariant(
325 - endIndex >= startIndex,
326 - 'OrderedMap.mapKeyRange(...): `endKey` must not come before `startIndex`.'
327 - );
328 - return this.mapRange(cb, startIndex, (endIndex - startIndex) + 1, context);
329 - },
330 -
331 - forEachKeyRange: function(cb, startKey, endKey, context) {
332 - var startIndex = this.indexOfKey(startKey);
333 - var endIndex = this.indexOfKey(endKey);
334 - invariant(
335 - startIndex !== undefined && endIndex !== undefined,
336 - 'forEachKeyRange must be given keys that are present.'
337 - );
338 - invariant(
339 - endIndex >= startIndex,
340 - 'OrderedMap.forEachKeyRange(...): `endKey` must not come before ' +
341 - '`startIndex`.'
342 - );
343 - this.forEachRange(cb, startIndex, (endIndex - startIndex) + 1, context);
344 - },
345 -
346 - /**
347 - * @param {number} pos Index to search for key at.
348 - * @return {string|undefined} Either the key at index `pos` or undefined if
349 - * not in map.
350 - */
351 - keyAtIndex: function(pos) {
352 - var computedPositions = this._getOrComputePositions();
353 - var keyAtPos = computedPositions.keyByIndex[pos];
354 - return keyAtPos ? keyAtPos.substr(PREFIX.length) : undefined;
355 - },
356 -
357 - /**
358 - * @param {string} key String key from which to find the next key.
359 - * @return {string|undefined} Either the next key, or undefined if there is no
360 - * next key.
361 - * @throws Error if `key` is not in this `OrderedMap`.
362 - */
363 - keyAfter: function(key) {
364 - return this.nthKeyAfter(key, 1);
365 - },
366 -
367 - /**
368 - * @param {string} key String key from which to find the preceding key.
369 - * @return {string|undefined} Either the preceding key, or undefined if there
370 - * is no preceding.key.
371 - * @throws Error if `key` is not in this `OrderedMap`.
372 - */
373 - keyBefore: function(key) {
374 - return this.nthKeyBefore(key, 1);
375 - },
376 -
377 - /**
378 - * @param {string} key String key from which to find a following key.
379 - * @param {number} n Distance to scan forward after `key`.
380 - * @return {string|undefined} Either the nth key after `key`, or undefined if
381 - * there is no next key.
382 - * @throws Error if `key` is not in this `OrderedMap`.
383 - */
384 - nthKeyAfter: function(key, n) {
385 - var curIndex = this.indexOfKey(key);
386 - invariant(
387 - curIndex !== undefined,
388 - 'OrderedMap.nthKeyAfter: The key `%s` does not exist in this instance.',
389 - key
390 - );
391 - return this.keyAtIndex(curIndex + n);
392 - },
393 -
394 - /**
395 - * @param {string} key String key from which to find a preceding key.
396 - * @param {number} n Distance to scan backwards before `key`.
397 - * @return {string|undefined} Either the nth key before `key`, or undefined if
398 - * there is no previous key.
399 - * @throws Error if `key` is not in this `OrderedMap`.
400 - */
401 - nthKeyBefore: function(key, n) {
402 - return this.nthKeyAfter(key, -n);
403 - },
404 -
405 - /**
406 - * @param {string} key Key to find the index of.
407 - * @return {number|undefined} Index of the provided key, or `undefined` if the
408 - * key is not found.
409 - */
410 - indexOfKey: function(key) {
411 - assertValidPublicKey(key);
412 - var normalizedKey = PREFIX + key;
413 - var computedPositions = this._getOrComputePositions();
414 - var computedPosition = computedPositions.indexByKey[normalizedKey];
415 - // Just writing it this way to make it clear this is intentional.
416 - return computedPosition === undefined ? undefined : computedPosition;
417 - },
418 -
419 - /**
420 - * @return {Array} An ordered array of this object's values.
421 - */
422 - toArray: function() {
423 - var result = [];
424 - var thisSet = this._normalizedObj;
425 - for (var key in thisSet) {
426 - if (thisSet.hasOwnProperty(key)) {
427 - result.push(thisSet[key]);
428 - }
429 - }
430 - return result;
431 - },
432 -
433 - /**
434 - * Finds the key at a given position, or indicates via `undefined` that that
435 - * position does not exist in the `OrderedMap`. It is appropriate to return
436 - * undefined, indicating that the key doesn't exist in the `OrderedMap`
437 - * because `undefined` is not ever a valid `OrderedMap` key.
438 - *
439 - * @private
440 - * @return {string?} Name of the item at position `pos`, or `undefined` if
441 - * there is no item at that position.
442 - */
443 - _getOrComputePositions: function() {
444 - // TODO: Entertain computing this at construction time in some less
445 - // performance critical paths.
446 - var computedPositions = this._computedPositions;
447 - if (!computedPositions) {
448 - this._computePositions();
449 - }
450 - return this._computedPositions;
451 - },
452 -
453 - /**
454 - * Precomputes the index/key mapping for future lookup. Since `OrderedMap`s
455 - * are immutable, there is only ever a need to perform this once.
456 - * @private
457 - */
458 - _computePositions: function() {
459 - this._computedPositions = {
460 - keyByIndex: {},
461 - indexByKey: {},
462 - };
463 - var keyByIndex = this._computedPositions.keyByIndex;
464 - var indexByKey = this._computedPositions.indexByKey;
465 - var index = 0;
466 - var thisSet = this._normalizedObj;
467 - for (var key in thisSet) {
468 - if (thisSet.hasOwnProperty(key)) {
469 - keyByIndex[index] = key;
470 - indexByKey[key] = index;
471 - index++;
472 - }
473 - }
474 - },
475 -};
476 -
477 -Object.assign(OrderedMapImpl.prototype, OrderedMapMethods);
478 -
479 -var OrderedMap = {
480 - from: function(orderedMap) {
481 - invariant(
482 - orderedMap instanceof OrderedMapImpl,
483 - 'OrderedMap.from(...): Expected an OrderedMap instance.'
484 - );
485 - return _fromNormalizedObjects(orderedMap._normalizedObj, null);
486 - },
487 -
488 - fromArray: function(arr, keyExtractor) {
489 - invariant(
490 - Array.isArray(arr),
491 - 'OrderedMap.fromArray(...): First argument must be an array.'
492 - );
493 - invariant(
494 - typeof keyExtractor === 'function',
495 - 'OrderedMap.fromArray(...): Second argument must be a function used ' +
496 - 'to determine the unique key for each entry.'
497 - );
498 - return new OrderedMapImpl(
499 - extractObjectFromArray(arr, keyExtractor),
500 - arr.length
501 - );
502 - },
503 -};
504 -
505 -module.exports = OrderedMap;
src/isomorphic/deprecated/ReactPropTransferer.js deleted
-107
@@ -1,107 +0,0 @@
1 -/**
2 - * Copyright 2013-present, Facebook, Inc.
3 - * All rights reserved.
4 - *
5 - * This source code is licensed under the BSD-style license found in the
6 - * LICENSE file in the root directory of this source tree. An additional grant
7 - * of patent rights can be found in the PATENTS file in the same directory.
8 - *
9 - * @providesModule ReactPropTransferer
10 - */
11 -
12 -'use strict';
13 -
14 -var emptyFunction = require('emptyFunction');
15 -var joinClasses = require('joinClasses');
16 -
17 -/**
18 - * Creates a transfer strategy that will merge prop values using the supplied
19 - * `mergeStrategy`. If a prop was previously unset, this just sets it.
20 - *
21 - * @param {function} mergeStrategy
22 - * @return {function}
23 - */
24 -function createTransferStrategy(mergeStrategy) {
25 - return function(props, key, value) {
26 - if (!props.hasOwnProperty(key)) {
27 - props[key] = value;
28 - } else {
29 - props[key] = mergeStrategy(props[key], value);
30 - }
31 - };
32 -}
33 -
34 -var transferStrategyMerge = createTransferStrategy(function(a, b) {
35 - // `merge` overrides the first object's (`props[key]` above) keys using the
36 - // second object's (`value`) keys. An object's style's existing `propA` would
37 - // get overridden. Flip the order here.
38 - return Object.assign({}, b, a);
39 -});
40 -
41 -/**
42 - * Transfer strategies dictate how props are transferred by `transferPropsTo`.
43 - * NOTE: if you add any more exceptions to this list you should be sure to
44 - * update `cloneWithProps()` accordingly.
45 - */
46 -var TransferStrategies = {
47 - /**
48 - * Never transfer `children`.
49 - */
50 - children: emptyFunction,
51 - /**
52 - * Transfer the `className` prop by merging them.
53 - */
54 - className: createTransferStrategy(joinClasses),
55 - /**
56 - * Transfer the `style` prop (which is an object) by merging them.
57 - */
58 - style: transferStrategyMerge,
59 -};
60 -
61 -/**
62 - * Mutates the first argument by transferring the properties from the second
63 - * argument.
64 - *
65 - * @param {object} props
66 - * @param {object} newProps
67 - * @return {object}
68 - */
69 -function transferInto(props, newProps) {
70 - for (var thisKey in newProps) {
71 - if (!newProps.hasOwnProperty(thisKey)) {
72 - continue;
73 - }
74 -
75 - var transferStrategy = TransferStrategies[thisKey];
76 -
77 - if (transferStrategy && TransferStrategies.hasOwnProperty(thisKey)) {
78 - transferStrategy(props, thisKey, newProps[thisKey]);
79 - } else if (!props.hasOwnProperty(thisKey)) {
80 - props[thisKey] = newProps[thisKey];
81 - }
82 - }
83 - return props;
84 -}
85 -
86 -/**
87 - * ReactPropTransferer are capable of transferring props to another component
88 - * using a `transferPropsTo` method.
89 - *
90 - * @class ReactPropTransferer
91 - */
92 -var ReactPropTransferer = {
93 -
94 - /**
95 - * Merge two props objects using TransferStrategies.
96 - *
97 - * @param {object} oldProps original props (they take precedence)
98 - * @param {object} newProps new props to merge in
99 - * @return {object} a new object containing both sets of props merged.
100 - */
101 - mergeProps: function(oldProps, newProps) {
102 - return transferInto(Object.assign({}, oldProps), newProps);
103 - },
104 -
105 -};
106 -
107 -module.exports = ReactPropTransferer;
src/shared/utils/__tests__/OrderedMap-test.js deleted
-941
@@ -1,941 +0,0 @@
1 -/**
2 - * Copyright 2013-present, Facebook, Inc.
3 - * All rights reserved.
4 - *
5 - * This source code is licensed under the BSD-style license found in the
6 - * LICENSE file in the root directory of this source tree. An additional grant
7 - * of patent rights can be found in the PATENTS file in the same directory.
8 - *
9 - * @emails react-core
10 - */
11 -
12 -'use strict';
13 -
14 -var OrderedMap;
15 -
16 -/**
17 - * Shared, reusable objects.
18 - */
19 -var hasEmptyStringKey = {
20 - 'thisKeyIsFine': {data: []},
21 - '': {thisShouldCauseAFailure: []},
22 - 'thisKeyIsAlsoFine': {data: []},
23 -};
24 -
25 -/**
26 - * Used as map/forEach callback.
27 - */
28 -var duplicate = function(itm, key, count) {
29 - return {
30 - uniqueID: itm.uniqueID,
31 - val: itm.val + key + count + this.justToTestScope,
32 - };
33 -};
34 -
35 -// Should not be allowed - because then null/'null' become impossible to
36 -// distinguish. Every key MUST be a string period!
37 -var hasNullAndUndefStringKey = [
38 - {uniqueID: 'undefined', val: 'thisIsUndefined'},
39 - {uniqueID: 'null', val: 'thisIsNull'},
40 -];
41 -var hasNullKey = [
42 - {uniqueID: 'thisKeyIsFine', data: []},
43 - {uniqueID: 'thisKeyIsAlsoFine', data: []},
44 - {uniqueID: null, data: []},
45 -];
46 -
47 -var hasObjectKey = [
48 - {uniqueID: 'thisKeyIsFine', data: []},
49 - {uniqueID: 'thisKeyIsAlsoFine', data: []},
50 - {uniqueID: {}, data: []},
51 -];
52 -
53 -var hasArrayKey = [
54 - {uniqueID: 'thisKeyIsFine', data: []},
55 - {uniqueID: 'thisKeyIsAlsoFine', data: []},
56 - {uniqueID: [], data: []},
57 -];
58 -
59 -// This should be allowed
60 -var hasNullStringKey = [
61 - {uniqueID: 'thisKeyIsFine', data: []},
62 - {uniqueID: 'thisKeyIsAlsoFine', data: []},
63 - {uniqueID: 'null', data: []},
64 -];
65 -
66 -var hasUndefinedKey = [
67 - {uniqueID: 'thisKeyIsFine', data: []},
68 - {uniqueID: 'thisKeyIsAlsoFine', data: []},
69 - {uniqueID: undefined, data: []},
70 -];
71 -
72 -var hasUndefinedStringKey = [
73 - {uniqueID: 'thisKeyIsFine', data: []},
74 - {uniqueID: 'thisKeyIsAlsoFine', data: []},
75 - {uniqueID: 'undefined', data: []},
76 -];
77 -
78 -var hasPositiveNumericKey = [
79 - {uniqueID: 'notANumber', data: []},
80 - {uniqueID: '5', data: []},
81 - {uniqueID: 'notAnotherNumber', data: []},
82 -];
83 -
84 -var hasZeroStringKey = [
85 - {uniqueID: 'greg', data: 'grego'},
86 - {uniqueID: '0', data: '0o'},
87 - {uniqueID: 'tom', data: 'tomo'},
88 -];
89 -
90 -var hasZeroNumberKey = [
91 - {uniqueID: 'greg', data: 'grego'},
92 - {uniqueID: 0, data: '0o'},
93 - {uniqueID: 'tom', data: 'tomo'},
94 -];
95 -
96 -var hasAllNumericStringKeys = [
97 - {uniqueID: '0', name: 'Gregory'},
98 - {uniqueID: '2', name: 'James'},
99 - {uniqueID: '1', name: 'Tom'},
100 -];
101 -
102 -var hasAllNumericKeys = [
103 - {uniqueID: 0, name: 'Gregory'},
104 - {uniqueID: 2, name: 'James'},
105 - {uniqueID: 1, name: 'Tom'},
106 -];
107 -
108 -var hasAllValidKeys = [
109 - {uniqueID: 'keyOne', value: 'valueOne'},
110 - {uniqueID: 'keyTwo', value: 'valueTwo'},
111 -];
112 -
113 -var hasDuplicateKeys = [
114 - {uniqueID: 'keyOne', value: 'valueOne'},
115 - {uniqueID: 'keyTwo', value: 'valueTwo'},
116 - {uniqueID: 'keyOne', value: 'valueThree'},
117 -];
118 -
119 -var idEntities = [
120 - {uniqueID: 'greg', name: 'Gregory'},
121 - {uniqueID: 'james', name: 'James'},
122 - {uniqueID: 'tom', name: 'Tom'},
123 -];
124 -
125 -var hasEmptyKey = [
126 - {uniqueID: 'greg', name: 'Gregory'},
127 - {uniqueID: '', name: 'James'},
128 - {uniqueID: 'tom', name: 'Tom'},
129 -];
130 -
131 -var extractUniqueID = function(entity) {
132 - return entity.uniqueID;
133 -};
134 -
135 -describe('OrderedMap', function() {
136 - beforeEach(function() {
137 - jest.resetModuleRegistry();
138 - OrderedMap = require('OrderedMap');
139 - });
140 -
141 - it('should create according to simple object with keys', function() {
142 - OrderedMap.fromArray(hasAllValidKeys, extractUniqueID);
143 - // Iterate over and ensure key order.
144 - });
145 -
146 - it('should create from array when providing an identity CB', function() {
147 - expect(function() {
148 - OrderedMap.fromArray(idEntities, extractUniqueID);
149 - }).not.toThrow();
150 - });
151 -
152 - it('should throw if constructing from Array without identity CB', function() {
153 - OrderedMap.fromArray(idEntities, extractUniqueID);
154 - // Iterate and ensure key order
155 - });
156 -
157 - it('should not throw when fromArray extracts a numeric key', function() {
158 - expect(function() {
159 - OrderedMap.fromArray(hasPositiveNumericKey, extractUniqueID);
160 - }).not.toThrow();
161 -
162 - });
163 -
164 - it('should throw when any key is the empty string', function() {
165 - expect(function() {
166 - OrderedMap.fromArray(hasEmptyKey, extractUniqueID);
167 - }).toThrow();
168 - });
169 -
170 - it('should not throw when a key is the string "undefined" or "null"',
171 - function() {
172 - var om = OrderedMap.fromArray(hasNullAndUndefStringKey, extractUniqueID);
173 - expect(om.length).toBe(2);
174 - expect(om.indexOfKey('undefined')).toBe(0);
175 - expect(om.indexOfKey('null')).toBe(1);
176 - expect(om.keyAfter('undefined')).toBe('null');
177 - expect(om.keyAfter('null')).toBe(undefined);
178 - expect(om.keyBefore('undefined')).toBe(undefined);
179 - expect(om.has('undefined')).toBe(true);
180 - expect(om.has('null')).toBe(true);
181 - expect(om.get('undefined').val).toBe('thisIsUndefined');
182 - expect(om.get('null').val).toBe('thisIsNull');
183 - });
184 -
185 -
186 - /**
187 - * Numeric keys are cast to strings.
188 - */
189 - it('should not throw when a key is the number zero', function() {
190 - var om = OrderedMap.fromArray(hasZeroNumberKey, extractUniqueID);
191 - expect(om.length).toBe(3);
192 - expect(om.indexOfKey('0')).toBe(1);
193 - expect(om.indexOfKey(0)).toBe(1);
194 - });
195 -
196 - it('should throw when any key is falsey', function() {
197 - expect(function() {
198 - OrderedMap.fromArray(hasEmptyStringKey, extractUniqueID);
199 - }).toThrow();
200 -
201 - expect(function() {
202 - OrderedMap.fromArray(hasNullKey, extractUniqueID);
203 - }).toThrow();
204 -
205 - expect(function() {
206 - OrderedMap.fromArray(hasUndefinedKey, extractUniqueID);
207 - }).toThrow();
208 - });
209 -
210 - it('should not throw on string keys "undefined/null"', function() {
211 - expect(function() {
212 - OrderedMap.fromArray(hasNullStringKey, extractUniqueID);
213 - }).not.toThrow();
214 -
215 - expect(function() {
216 - OrderedMap.fromArray(hasUndefinedStringKey, extractUniqueID);
217 - }).not.toThrow();
218 - });
219 -
220 - it('should throw on extracting keys that are not strings/nums', function() {
221 - expect(function() {
222 - OrderedMap.fromArray(hasObjectKey, extractUniqueID);
223 - }).toThrow();
224 -
225 - expect(function() {
226 - OrderedMap.fromArray(hasArrayKey, extractUniqueID);
227 - }).toThrow();
228 - });
229 -
230 - it('should throw if instantiating with duplicate key', function() {
231 - expect(function() {
232 - OrderedMap.fromArray(hasDuplicateKeys, extractUniqueID);
233 - }).toThrow();
234 - });
235 -
236 - it('should not throw when a key is the string "0"', function() {
237 - var verifyOM = function(om) {
238 - expect(om.length).toBe(3);
239 - expect(om.indexOfKey('greg')).toBe(0);
240 - expect(om.indexOfKey('0')).toBe(1);
241 - expect(om.indexOfKey(0)).toBe(1); // Casts on writes and reads.
242 - expect(om.indexOfKey('tom')).toBe(2);
243 - expect(om.keyAfter('greg')).toBe('0');
244 - expect(om.keyAfter('0')).toBe('tom');
245 - expect(om.keyAfter(0)).toBe('tom');
246 - expect(om.keyAfter('tom')).toBe(undefined);
247 - expect(om.keyBefore('greg')).toBe(undefined);
248 - expect(om.keyBefore(0)).toBe('greg');
249 - expect(om.keyBefore('0')).toBe('greg');
250 - expect(om.keyBefore('tom')).toBe('0');
251 - expect(om.has('undefined')).toBe(false);
252 - expect(om.has(0)).toBe(true);
253 - expect(om.has('0')).toBe(true);
254 - };
255 - verifyOM(OrderedMap.fromArray(hasZeroStringKey, extractUniqueID));
256 - verifyOM(OrderedMap.fromArray(hasZeroNumberKey, extractUniqueID));
257 - });
258 -
259 - it('should throw when getting invalid public key', function() {
260 - var om = OrderedMap.fromArray(hasAllValidKeys, extractUniqueID);
261 - expect(function() {
262 - om.has(undefined);
263 - }).toThrow();
264 - expect(function() {
265 - om.get(undefined);
266 - }).toThrow();
267 - expect(function() {
268 - om.has(null);
269 - }).toThrow();
270 - expect(function() {
271 - om.get(null);
272 - }).toThrow();
273 - expect(function() {
274 - om.has('');
275 - }).toThrow();
276 - expect(function() {
277 - om.get('');
278 - }).toThrow();
279 - });
280 -
281 - it('should throw when any key is falsey', function() {
282 - expect(function() {
283 - OrderedMap.fromArray(hasEmptyStringKey, extractUniqueID);
284 - }).toThrow();
285 -
286 - expect(function() {
287 - OrderedMap.fromArray(hasNullKey, extractUniqueID);
288 - }).toThrow();
289 -
290 - expect(function() {
291 - OrderedMap.fromArray(hasUndefinedKey, extractUniqueID);
292 - }).toThrow();
293 - });
294 -
295 -
296 - it('should throw when fromArray is passed crazy args', function() {
297 - // Test passing another OrderedMap (when it expects a plain object.)
298 - // This is probably not what you meant to do! We should error.
299 - var validOM = OrderedMap.fromArray(hasAllValidKeys, extractUniqueID);
300 - expect(function() {
301 - OrderedMap.fromArray({uniqueID: 'asdf'}, extractUniqueID);
302 - }).toThrow();
303 - expect(function() {
304 - OrderedMap.fromArray(validOM, extractUniqueID);
305 - }).toThrow();
306 - });
307 -
308 - it('should throw when fromArray is passed crazy things', function() {
309 - expect(function() {
310 - OrderedMap.fromArray(null, extractUniqueID);
311 - }).toThrow();
312 - expect(function() {
313 - OrderedMap.fromArray('stringgg', extractUniqueID);
314 - }).toThrow();
315 - expect(function() {
316 - OrderedMap.fromArray(undefined, extractUniqueID);
317 - }).toThrow();
318 - expect(function() {
319 - OrderedMap.fromArray(new Date(), extractUniqueID);
320 - }).toThrow();
321 - expect(function() {
322 - OrderedMap.fromArray({}, extractUniqueID);
323 - }).toThrow();
324 -
325 - // Test failure without extractor
326 - expect(function() {
327 - OrderedMap.fromArray(idEntities);
328 - }).toThrow();
329 - expect(function() {
330 - OrderedMap.fromArray(idEntities, extractUniqueID);
331 - }).not.toThrow();
332 - });
333 -
334 - // Testing methods that accept other `OrderedMap`s.
335 - it('should throw when from/merge is passed an non-OrderedMap.', function() {
336 - // Test passing an array to construction.
337 - expect(function() {
338 - OrderedMap.from(idEntities, extractUniqueID);
339 - }).toThrow();
340 -
341 - // Test passing an array to merge.
342 - expect(function() {
343 - OrderedMap.fromArray(idEntities, extractUniqueID)
344 - .merge(idEntities, extractUniqueID);
345 - }).toThrow();
346 -
347 -
348 - // Test passing a plain object to merge.
349 - expect(function() {
350 - OrderedMap.fromArray(
351 - idEntities,
352 - extractUniqueID
353 - ).merge({blah: 'willFail'});
354 - }).toThrow();
355 - });
356 -
357 - it('should throw when accessing key before/after of non-key', function() {
358 - var om = OrderedMap.fromArray(
359 - [
360 - {uniqueID: 'first'},
361 - {uniqueID: 'two'},
362 - ], extractUniqueID
363 - );
364 - expect(function() {
365 - om.keyBefore('dog');
366 - }).toThrow();
367 - expect(function() {
368 - om.keyAfter('cat');
369 - }).toThrow();
370 - expect(function() {
371 - om.keyAfter(null);
372 - }).toThrow();
373 - expect(function() {
374 - om.keyAfter(undefined);
375 - }).toThrow();
376 - });
377 -
378 - it('should throw passing invalid/not-present-keys to before/after',
379 - function() {
380 - var om = OrderedMap.fromArray([
381 - {uniqueID: 'one', val: 'first'},
382 - {uniqueID: 'two', val: 'second'},
383 - {uniqueID: 'three', val: 'third'},
384 - {uniqueID: 'four', val: 'fourth'},
385 - ], extractUniqueID);
386 -
387 - expect(function() {
388 - om.keyBefore('');
389 - }).toThrow();
390 - expect(function() {
391 - om.keyBefore(null);
392 - }).toThrow();
393 - expect(function() {
394 - om.keyBefore(undefined);
395 - }).toThrow();
396 - expect(function() {
397 - om.keyBefore('notInTheOrderedMap!');
398 - }).toThrow();
399 -
400 - expect(function() {
401 - om.keyAfter('');
402 - }).toThrow();
403 - expect(function() {
404 - om.keyAfter(null);
405 - }).toThrow();
406 - expect(function() {
407 - om.keyAfter(undefined);
408 - }).toThrow();
409 - expect(function() {
410 - om.keyAfter('notInTheOrderedMap!');
411 - }).toThrow();
412 -
413 - expect(function() {
414 - om.nthKeyAfter('', 1);
415 - }).toThrow();
416 - expect(function() {
417 - om.nthKeyAfter(null, 1);
418 - }).toThrow();
419 - expect(function() {
420 - om.nthKeyAfter(undefined, 1);
421 - }).toThrow();
422 - expect(function() {
423 - om.nthKeyAfter('notInTheOrderedMap!', 1);
424 - }).toThrow();
425 -
426 - expect(function() {
427 - om.nthKeyBefore('', 1);
428 - }).toThrow();
429 - expect(function() {
430 - om.nthKeyBefore(null, 1);
431 - }).toThrow();
432 - expect(function() {
433 - om.nthKeyBefore(undefined, 1);
434 - }).toThrow();
435 - expect(function() {
436 - om.nthKeyBefore('notInTheOrderedMap!', 1);
437 - }).toThrow();
438 - });
439 -
440 - it('should correctly determine the nth key after before', function() {
441 - var om = OrderedMap.fromArray([
442 - {uniqueID: 'one', val: 'first'},
443 - {uniqueID: 'two', val: 'second'},
444 - {uniqueID: 'three', val: 'third'},
445 - {uniqueID: 'four', val: 'fourth'},
446 - ], extractUniqueID);
447 - expect(om.keyBefore('one')).toBe(undefined); // first key
448 - expect(om.keyBefore('two')).toBe('one');
449 - expect(om.keyBefore('three')).toBe('two');
450 - expect(om.keyBefore('four')).toBe('three');
451 -
452 - expect(om.keyAfter('one')).toBe('two'); // first key
453 - expect(om.keyAfter('two')).toBe('three');
454 - expect(om.keyAfter('three')).toBe('four');
455 - expect(om.keyAfter('four')).toBe(undefined);
456 -
457 - expect(om.nthKeyBefore('one', 0)).toBe('one'); // first key
458 - expect(om.nthKeyBefore('one', 1)).toBe(undefined);
459 - expect(om.nthKeyBefore('one', 2)).toBe(undefined);
460 - expect(om.nthKeyBefore('two', 0)).toBe('two');
461 - expect(om.nthKeyBefore('two', 1)).toBe('one');
462 - expect(om.nthKeyBefore('four', 0)).toBe('four');
463 - expect(om.nthKeyBefore('four', 1)).toBe('three');
464 -
465 - expect(om.nthKeyAfter('one', 0)).toBe('one');
466 - expect(om.nthKeyAfter('one', 1)).toBe('two');
467 - expect(om.nthKeyAfter('one', 2)).toBe('three');
468 - expect(om.nthKeyAfter('two', 0)).toBe('two');
469 - expect(om.nthKeyAfter('two', 1)).toBe('three');
470 - expect(om.nthKeyAfter('four', 0)).toBe('four');
471 - expect(om.nthKeyAfter('four', 1)).toBe(undefined);
472 - });
473 -
474 - it('should compute key indices correctly', function() {
475 - var om = OrderedMap.fromArray([
476 - {uniqueID: 'one', val: 'first'},
477 - {uniqueID: 'two', val: 'second'},
478 - ], extractUniqueID);
479 - expect(om.keyAtIndex(0)).toBe('one');
480 - expect(om.keyAtIndex(1)).toBe('two');
481 - expect(om.keyAtIndex(2)).toBe(undefined);
482 - expect(om.indexOfKey('one')).toBe(0);
483 - expect(om.indexOfKey('two')).toBe(1);
484 - expect(om.indexOfKey('nope')).toBe(undefined);
485 - expect(function() {
486 - om.indexOfKey(null);
487 - }).toThrow();
488 - expect(function() {
489 - om.indexOfKey(undefined);
490 - }).toThrow();
491 - expect(function() {
492 - om.indexOfKey(''); // Empty key is not allowed
493 - }).toThrow();
494 - });
495 -
496 - it('should compute indices on array that extracted numeric ids', function() {
497 - var som = OrderedMap.fromArray(hasZeroStringKey, extractUniqueID);
498 - expect(som.keyAtIndex(0)).toBe('greg');
499 - expect(som.keyAtIndex(1)).toBe('0');
500 - expect(som.keyAtIndex(2)).toBe('tom');
501 - expect(som.indexOfKey('greg')).toBe(0);
502 - expect(som.indexOfKey('0')).toBe(1);
503 - expect(som.indexOfKey('tom')).toBe(2);
504 -
505 -
506 - var verifyNumericKeys = function(nom) {
507 - expect(nom.keyAtIndex(0)).toBe('0');
508 - expect(nom.keyAtIndex(1)).toBe('2');
509 - expect(nom.keyAtIndex(2)).toBe('1');
510 - expect(nom.indexOfKey('0')).toBe(0);
511 - expect(nom.indexOfKey('2')).toBe(1); // Prove these are not ordered by
512 - expect(nom.indexOfKey('1')).toBe(2); // their keys
513 - };
514 - var omStringNumberKeys =
515 - OrderedMap.fromArray(hasAllNumericStringKeys, extractUniqueID);
516 - verifyNumericKeys(omStringNumberKeys);
517 - var omNumericKeys =
518 - OrderedMap.fromArray(hasAllNumericKeys, extractUniqueID);
519 - verifyNumericKeys(omNumericKeys);
520 - });
521 -
522 - it('should compute indices on mutually exclusive merge', function() {
523 - var om = OrderedMap.fromArray([
524 - {uniqueID: 'one', val: 'first'},
525 - {uniqueID: 'two', val: 'second'},
526 - ], extractUniqueID);
527 - var om2 = OrderedMap.fromArray([
528 - {uniqueID: 'three', val: 'third'},
529 - ], extractUniqueID);
530 - var res = om.merge(om2);
531 -
532 - expect(res.length).toBe(3);
533 -
534 - expect(res.keyAtIndex(0)).toBe('one');
535 - expect(res.keyAtIndex(1)).toBe('two');
536 - expect(res.keyAtIndex(2)).toBe('three');
537 - expect(res.keyAtIndex(3)).toBe(undefined);
538 -
539 - expect(res.indexOfKey('one')).toBe(0);
540 - expect(res.indexOfKey('two')).toBe(1);
541 - expect(res.indexOfKey('three')).toBe(2);
542 - expect(res.indexOfKey('dog')).toBe(undefined);
543 -
544 - expect(res.has('one')).toBe(true);
545 - expect(res.has('two')).toBe(true);
546 - expect(res.has('three')).toBe(true);
547 - expect(res.has('dog')).toBe(false);
548 -
549 - expect(res.get('one').val).toBe('first');
550 - expect(res.get('two').val).toBe('second');
551 - expect(res.get('three').val).toBe('third');
552 - expect(res.get('dog')).toBe(undefined);
553 - });
554 -
555 - it('should compute indices on intersected merge', function() {
556 - var oneTwo = OrderedMap.fromArray([
557 - {uniqueID: 'one', val: 'first'},
558 - {uniqueID: 'two', val: 'secondOM1'},
559 - ], extractUniqueID);
560 -
561 - var testOneTwoMergedWithTwoThree = function(res) {
562 - expect(res.length).toBe(3);
563 - expect(res.keyAtIndex(0)).toBe('one');
564 - expect(res.keyAtIndex(1)).toBe('two');
565 - expect(res.keyAtIndex(2)).toBe('three');
566 - expect(res.keyAtIndex(3)).toBe(undefined);
567 - expect(res.indexOfKey('one')).toBe(0);
568 - expect(res.indexOfKey('two')).toBe(1);
569 - expect(res.indexOfKey('three')).toBe(2);
570 - expect(res.indexOfKey('dog')).toBe(undefined);
571 - expect(res.has('one')).toBe(true);
572 - expect(res.has('two')).toBe(true);
573 - expect(res.has('three')).toBe(true);
574 - expect(res.has('dog')).toBe(false);
575 - expect(res.get('one').val).toBe('first');
576 - expect(res.get('two').val).toBe('secondOM2');
577 - expect(res.get('three').val).toBe('third');
578 - expect(res.get('dog')).toBe(undefined);
579 - };
580 -
581 - var result =
582 - oneTwo.merge(OrderedMap.fromArray([
583 - {uniqueID: 'two', val: 'secondOM2'},
584 - {uniqueID: 'three', val: 'third'},
585 - ], extractUniqueID));
586 - testOneTwoMergedWithTwoThree(result);
587 -
588 - // Everything should be exactly as before, since the ordering of `two` was
589 - // already determined by `om`.
590 - result = oneTwo.merge(
591 - OrderedMap.fromArray([
592 - {uniqueID: 'three', val: 'third'},
593 - {uniqueID: 'two', val:'secondOM2'},
594 - ], extractUniqueID)
595 - );
596 - testOneTwoMergedWithTwoThree(result);
597 -
598 -
599 - var testTwoThreeMergedWithOneTwo = function(res) {
600 - expect(res.length).toBe(3);
601 - expect(res.keyAtIndex(0)).toBe('two');
602 - expect(res.keyAtIndex(1)).toBe('three');
603 - expect(res.keyAtIndex(2)).toBe('one');
604 - expect(res.keyAtIndex(3)).toBe(undefined);
605 - expect(res.indexOfKey('two')).toBe(0);
606 - expect(res.indexOfKey('three')).toBe(1);
607 - expect(res.indexOfKey('one')).toBe(2);
608 - expect(res.indexOfKey('cat')).toBe(undefined);
609 - expect(res.has('two')).toBe(true);
610 - expect(res.has('three')).toBe(true);
611 - expect(res.has('one')).toBe(true);
612 - expect(res.has('dog')).toBe(false);
613 - expect(res.get('one').val).toBe('first');
614 - expect(res.get('two').val).toBe('secondOM1');
615 - expect(res.get('three').val).toBe('third');
616 - expect(res.get('dog')).toBe(undefined);
617 - };
618 - result = OrderedMap.fromArray([
619 - {uniqueID: 'two', val: 'secondOM2'},
620 - {uniqueID: 'three', val: 'third'},
621 - ], extractUniqueID).merge(oneTwo);
622 - testTwoThreeMergedWithOneTwo(result);
623 -
624 - });
625 -
626 - it('should merge mutually exclusive keys to the end.', function() {
627 - var om = OrderedMap.fromArray([
628 - {uniqueID: 'one', val: 'first'},
629 - {uniqueID: 'two', val: 'second'},
630 - ], extractUniqueID);
631 - var om2 = OrderedMap.fromArray([
632 - {uniqueID: 'three', val: 'first'},
633 - {uniqueID: 'four', val: 'second'},
634 - ], extractUniqueID);
635 - var res = om.merge(om2);
636 - expect(res.length).toBe(4);
637 -
638 - });
639 -
640 - it('should map correctly', function() {
641 - var om = OrderedMap.fromArray([
642 - {uniqueID: 'x', val: 'xx'},
643 - {uniqueID: 'y', val: 'yy'},
644 - {uniqueID: 'z', val: 'zz'},
645 - ], extractUniqueID);
646 - var scope = {justToTestScope: 'justTestingScope'};
647 - var verifyResult = function(omResult) {
648 - expect(omResult.length).toBe(3);
649 - expect(omResult.keyAtIndex(0)).toBe('x');
650 - expect(omResult.keyAtIndex(1)).toBe('y');
651 - expect(omResult.keyAtIndex(2)).toBe('z');
652 - expect(omResult.get('x').val).toBe('xxx0justTestingScope');
653 - expect(omResult.get('y').val).toBe('yyy1justTestingScope');
654 - expect(omResult.get('z').val).toBe('zzz2justTestingScope');
655 - };
656 - var resultOM = om.map(function(itm, key, count) {
657 - return {
658 - uniqueID: itm.uniqueID,
659 - val: itm.val + key + count + this.justToTestScope,
660 - };
661 - }, scope);
662 - verifyResult(resultOM);
663 -
664 - var resArray = [];
665 - om.forEach(function(itm, key, count) {
666 - resArray.push({
667 - uniqueID: itm.uniqueID,
668 - val: itm.val + key + count + this.justToTestScope,
669 - });
670 - }, scope);
671 - resultOM = OrderedMap.fromArray(resArray, extractUniqueID);
672 - verifyResult(resultOM);
673 - });
674 -
675 - it('should filter correctly', function() {
676 - var om = OrderedMap.fromArray([
677 - {uniqueID: 'x', val: 'xx'},
678 - {uniqueID: 'y', val: 'yy'},
679 - {uniqueID: 'z', val: 'zz'},
680 - ], extractUniqueID);
681 - var scope = {justToTestScope: 'justTestingScope'};
682 -
683 - var filteringCallback = function(item, key, indexInOriginal) {
684 - expect(this).toBe(scope);
685 - expect(key === 'x' || key === 'y' || key === 'z').toBe(true);
686 - if (key === 'x') {
687 - expect(item.val).toBe('xx');
688 - expect(indexInOriginal).toBe(0);
689 - return false;
690 - } else if (key === 'y') {
691 - expect(item.val).toBe('yy');
692 - expect(indexInOriginal).toBe(1);
693 - return true;
694 - } else {
695 - expect(item.val).toBe('zz');
696 - expect(indexInOriginal).toBe(2);
697 - return true;
698 - }
699 - };
700 -
701 - var verifyResult = function(omResult) {
702 - expect(omResult.length).toBe(2);
703 - expect(omResult.keyAtIndex(0)).toBe('y');
704 - expect(omResult.keyAtIndex(1)).toBe('z');
705 - expect(omResult.has('x')).toBe(false);
706 - expect(omResult.has('z')).toBe(true);
707 - expect(omResult.get('z').val).toBe('zz');
708 - expect(omResult.has('y')).toBe(true);
709 - expect(omResult.get('y').val).toBe('yy');
710 - };
711 -
712 - var resultOM = om.filter(filteringCallback, scope);
713 - verifyResult(resultOM);
714 - });
715 -
716 - it('should throw when providing invalid ranges to ranging', function() {
717 - var om = OrderedMap.fromArray([
718 - {uniqueID: 'x', val: 'xx'},
719 - {uniqueID: 'y', val: 'yy'},
720 - {uniqueID: 'z', val: 'zz'},
721 - ], extractUniqueID);
722 - var scope = {justToTestScope: 'justTestingScope'};
723 -
724 - expect(function() {
725 - om.mapRange(duplicate, 0, 3, scope);
726 - }).not.toThrow();
727 - expect(function() {
728 - om.filterRange(duplicate, 0, 3, scope);
729 - }).not.toThrow();
730 - expect(function() {
731 - om.forEachRange(duplicate, 0, 3, scope);
732 - }).not.toThrow();
733 - expect(function() {
734 - om.mapKeyRange(duplicate, 'x', 3, scope);
735 - }).toThrow(
736 - 'mapKeyRange must be given keys that are present.'
737 - );
738 - expect(function() {
739 - om.forEachKeyRange(duplicate, 'x', 3, scope);
740 - }).toThrow(
741 - 'forEachKeyRange must be given keys that are present.'
742 - );
743 -
744 - expect(function() {
745 - om.mapRange(duplicate, 0, 4, scope);
746 - }).toThrow();
747 - expect(function() {
748 - om.filterRange(duplicate, 0, 4, scope);
749 - }).toThrow();
750 - expect(function() {
751 - om.forEachRange(duplicate, 0, 4, scope);
752 - }).toThrow();
753 - expect(function() {
754 - om.mapKeyRange(duplicate, 'x', null, scope);
755 - }).toThrow();
756 - expect(function() {
757 - om.forEachKeyRange(duplicate, 'x', null, scope);
758 - }).toThrow();
759 -
760 - expect(function() {
761 - om.mapRange(duplicate, -1, 1, scope);
762 - }).toThrow();
763 - expect(function() {
764 - om.filterRange(duplicate, -1, 1, scope);
765 - }).toThrow();
766 - expect(function() {
767 - om.forEachRange(duplicate, -1, 1, scope);
768 - }).toThrow();
769 - expect(function() {
770 - om.mapKeyRange(duplicate, null, 'y', scope);
771 - }).toThrow();
772 - expect(function() {
773 - om.forEachKeyRange(duplicate, null, 'y', scope);
774 - }).toThrow();
775 -
776 - expect(function() {
777 - om.mapRange(duplicate, 0, 0, scope);
778 - }).not.toThrow();
779 - expect(function() {
780 - om.filterRange(duplicate, 0, 0, scope);
781 - }).not.toThrow();
782 - expect(function() {
783 - om.forEachRange(duplicate, 0, 0, scope);
784 - }).not.toThrow();
785 - expect(function() {
786 - om.mapKeyRange(duplicate, 'x', 'x', scope);
787 - }).not.toThrow();
788 - expect(function() {
789 - om.forEachKeyRange(duplicate, 'x', 'x', scope);
790 - }).not.toThrow();
791 -
792 - expect(function() {
793 - om.mapRange(duplicate, 0, -1, scope);
794 - }).toThrow();
795 - expect(function() {
796 - om.filterRange(duplicate, 0, -1, scope);
797 - }).toThrow();
798 - expect(function() {
799 - om.forEachRange(duplicate, 0, -1, scope);
800 - }).toThrow();
801 - expect(function() {
802 - om.mapKeyRange(duplicate, 'x', null, scope);
803 - }).toThrow();
804 - expect(function() {
805 - om.forEachKeyRange(duplicate, 'x', null, scope);
806 - }).toThrow();
807 -
808 - expect(function() {
809 - om.mapRange(duplicate, 2, 1, scope);
810 - }).not.toThrow();
811 - expect(function() {
812 - om.filterRange(duplicate, 2, 1, scope);
813 - }).not.toThrow();
814 - expect(function() {
815 - om.forEachRange(duplicate, 2, 1, scope);
816 - }).not.toThrow();
817 - expect(function() {
818 - om.mapKeyRange(duplicate, 'z', 'z', scope);
819 - }).not.toThrow();
820 - expect(function() {
821 - om.forEachKeyRange(duplicate, 'z', 'z', scope);
822 - }).not.toThrow();
823 -
824 - expect(function() {
825 - om.mapRange(duplicate, 2, 2, scope);
826 - }).toThrow();
827 - expect(function() {
828 - om.filterRange(duplicate, 2, 2, scope);
829 - }).toThrow();
830 - expect(function() {
831 - om.forEachRange(duplicate, 2, 2, scope);
832 - }).toThrow();
833 - expect(function() {
834 - om.mapKeyRange(duplicate, 'z', null, scope);
835 - }).toThrow();
836 - expect(function() {
837 - om.forEachKeyRange(duplicate, 'z', null, scope);
838 - }).toThrow();
839 -
840 - // Provide keys in reverse order - should throw.
841 - expect(function() {
842 - om.mapKeyRange(duplicate, 'y', 'x', scope);
843 - }).toThrow();
844 - expect(function() {
845 - om.forEachKeyRange(duplicate, 'y', 'x', scope);
846 - }).toThrow();
847 - });
848 -
849 - // TEST length zero map, or keyrange start===end
850 -
851 - it('should map range correctly', function() {
852 - var om = OrderedMap.fromArray([
853 - {uniqueID: 'x', val: 'xx'},
854 - {uniqueID: 'y', val: 'yy'},
855 - {uniqueID: 'z', val: 'zz'},
856 - ], extractUniqueID);
857 - var scope = {justToTestScope: 'justTestingScope'};
858 - var verifyThreeItems = function(omResult) {
859 - expect(omResult.length).toBe(3);
860 - expect(omResult.keyAtIndex(0)).toBe('x');
861 - expect(omResult.keyAtIndex(1)).toBe('y');
862 - expect(omResult.keyAtIndex(2)).toBe('z');
863 - expect(omResult.get('x').val).toBe('xxx0justTestingScope');
864 - expect(omResult.get('y').val).toBe('yyy1justTestingScope');
865 - expect(omResult.get('z').val).toBe('zzz2justTestingScope');
866 - };
867 - var verifyFirstTwoItems = function(omResult) {
868 - expect(omResult.length).toBe(2);
869 - expect(omResult.keyAtIndex(0)).toBe('x');
870 - expect(omResult.keyAtIndex(1)).toBe('y');
871 - expect(omResult.get('x').val).toBe('xxx0justTestingScope');
872 - expect(omResult.get('y').val).toBe('yyy1justTestingScope');
873 - };
874 -
875 - var verifyLastTwoItems = function(omResult) {
876 - expect(omResult.length).toBe(2);
877 - expect(omResult.keyAtIndex(0)).toBe('y');
878 - expect(omResult.keyAtIndex(1)).toBe('z');
879 - expect(omResult.get('y').val).toBe('yyy1justTestingScope');
880 - expect(omResult.get('z').val).toBe('zzz2justTestingScope');
881 - };
882 -
883 - var verifyMiddleItem = function(omResult) {
884 - expect(omResult.length).toBe(1);
885 - expect(omResult.keyAtIndex(0)).toBe('y');
886 - expect(omResult.get('y').val).toBe('yyy1justTestingScope');
887 - };
888 -
889 - var verifyEmpty = function(omResult) {
890 - expect(omResult.length).toBe(0);
891 - };
892 -
893 - var omResultThree = om.mapRange(duplicate, 0, 3, scope);
894 - verifyThreeItems(omResultThree);
895 - var resArray = [];
896 - var pushToResArray = function(itm, key, count) {
897 - resArray.push({
898 - uniqueID: itm.uniqueID,
899 - val: itm.val + key + count + this.justToTestScope,
900 - });
901 - };
902 -
903 - om.forEachRange(pushToResArray, 0, 3, scope);
904 - omResultThree = OrderedMap.fromArray(resArray, extractUniqueID);
905 - verifyThreeItems(omResultThree);
906 -
907 - var omResultFirstTwo = om.mapRange(duplicate, 0, 2, scope);
908 - verifyFirstTwoItems(omResultFirstTwo);
909 - resArray = [];
910 - om.forEachRange(pushToResArray, 0, 2, scope);
911 - omResultFirstTwo = OrderedMap.fromArray(resArray, extractUniqueID);
912 - verifyFirstTwoItems(omResultFirstTwo);
913 -
914 - var omResultLastTwo = om.mapRange(duplicate, 1, 2, scope);
915 - verifyLastTwoItems(omResultLastTwo);
916 - resArray = [];
917 - om.forEachRange(pushToResArray, 1, 2, scope);
918 - omResultLastTwo = OrderedMap.fromArray(resArray, extractUniqueID);
919 - verifyLastTwoItems(omResultLastTwo);
920 -
921 - var omResultMiddle = om.mapRange(duplicate, 1, 1, scope);
922 - verifyMiddleItem(omResultMiddle);
923 - resArray = [];
924 - om.forEachRange(pushToResArray, 1, 1, scope);
925 - omResultMiddle = OrderedMap.fromArray(resArray, extractUniqueID);
926 - verifyMiddleItem(omResultMiddle);
927 -
928 - var omResultNone = om.mapRange(duplicate, 1, 0, scope);
929 - verifyEmpty(omResultNone);
930 - });
931 -
932 - it('should extract the original array correctly', function() {
933 - var sourceArray = [
934 - {uniqueID: 'x', val: 'xx'},
935 - {uniqueID: 'y', val: 'yy'},
936 - {uniqueID: 'z', val: 'zz'},
937 - ];
938 - var om = OrderedMap.fromArray(sourceArray, extractUniqueID);
939 - expect(om.toArray()).toEqual(sourceArray);
940 - });
941 -});