UNPKG

30.9 kBJavaScriptView Raw
1const {compile, and, or, root, arg0, arg1, setter, splice, bind, chain} = require('../../index');
2const {
3 describeCompilers,
4 evalOrLoad,
5 currentValues,
6 funcLibrary,
7 expectTapFunctionToHaveBeenCalled,
8 rand
9} = require('../test-utils');
10const _ = require('lodash');
11
12describe('testing array', () => {
13 describeCompilers(['simple', 'optimizing', 'bytecode'], compiler => {
14 describe('map', () => {
15 it('simple map', () => {
16 const model = {negated: root.map(val => val.not().call('tap')), set: setter(arg0)};
17 const optCode = evalOrLoad(compile(model, {compiler}));
18 const inst = optCode([true, true, false, false, false], funcLibrary);
19 expect(inst.negated).toEqual([false, false, true, true, true]);
20 expectTapFunctionToHaveBeenCalled(inst.$model.length, compiler);
21 inst.set(1, false);
22 expect(inst.negated).toEqual([false, true, true, true, true]);
23 expectTapFunctionToHaveBeenCalled(1, compiler);
24 });
25 it('simple map with effect', () => {
26 const model = {effect: root.map(val => or(val.ternary(chain(true).effect('tap'), null), val)), set: setter(arg0)};
27 const optCode = evalOrLoad(compile(model, {compiler}));
28 const inst = optCode([true, true, false, false, false], funcLibrary);
29 expect(inst.effect).toEqual([true, true, false, false, false]);
30 expectTapFunctionToHaveBeenCalled(inst.$model.filter(k => k).length, {compiler: 'optimizing'});
31 inst.set(1, false);
32 expect(inst.effect).toEqual([true, false, false, false, false]);
33 expectTapFunctionToHaveBeenCalled(0, {compiler: 'optimizing'});
34 inst.set(2, true);
35 expect(inst.effect).toEqual([true, false, true, false, false]);
36 expectTapFunctionToHaveBeenCalled(1, {compiler: 'optimizing'});
37 });
38 it('map return empty object if falsy', () => {
39 const model = {orEmpty: root.map(val => or(val, {}).call('tap')), set: setter(arg0)};
40 const optCode = evalOrLoad(compile(model, {compiler}));
41 const inst = optCode([{x: 1}, false, {x: 2}], funcLibrary);
42 expect(inst.orEmpty).toEqual([{x: 1}, {}, {x: 2}]);
43 expectTapFunctionToHaveBeenCalled(inst.$model.length, compiler);
44 inst.set(2, false);
45 expect(inst.orEmpty).toEqual([{x: 1}, {}, {}]);
46 expectTapFunctionToHaveBeenCalled(1, compiler);
47 });
48 it('map return empty object if falsy', () => {
49 const model = {orEmpty: root.map(val => or(val, []).call('tap')), set: setter(arg0)};
50 const optCode = evalOrLoad(compile(model, {compiler}));
51 const inst = optCode([[1], false, [2]], funcLibrary);
52 expect(inst.orEmpty).toEqual([[1], [], [2]]);
53 expectTapFunctionToHaveBeenCalled(inst.$model.length, compiler);
54 inst.set(2, false);
55 expect(inst.orEmpty).toEqual([[1], [], []]);
56 expectTapFunctionToHaveBeenCalled(1, compiler);
57 });
58 });
59
60 describe('any', () => {
61 it('simple any', () => {
62 const model = {
63 anyTruthy: root.any(val => val.call('tap')),
64 set: setter(arg0)
65 };
66 const optModel = evalOrLoad(compile(model, {compiler}));
67 const inst = optModel([true, false, false, false, false], funcLibrary);
68 expectTapFunctionToHaveBeenCalled(1, compiler);
69 expect(inst.anyTruthy).toEqual(true);
70 inst.set(0, false);
71 expectTapFunctionToHaveBeenCalled(inst.$model.length, compiler);
72 expect(inst.anyTruthy).toEqual(false);
73 inst.set(3, true);
74 expectTapFunctionToHaveBeenCalled(1, compiler);
75 expect(inst.anyTruthy).toEqual(true);
76 inst.set(4, true);
77 expectTapFunctionToHaveBeenCalled(0, compiler);
78 expect(inst.anyTruthy).toEqual(true);
79 inst.set(3, false);
80 expectTapFunctionToHaveBeenCalled(2, compiler);
81 expect(inst.anyTruthy).toEqual(true);
82 inst.set(4, false);
83 expectTapFunctionToHaveBeenCalled(1, compiler);
84 expect(inst.anyTruthy).toEqual(false);
85 });
86
87 it('any when removing elements', () => {
88 const model = {
89 anyTruthy: root.get('data').any(a => a.get('val')),
90 set: setter('data', arg0),
91 clear: setter('data')
92 };
93 const optModel = evalOrLoad(compile(model, {compiler}));
94 const inst = optModel({data: [{val: false}, {val: true}, {val: false}]}, funcLibrary);
95 expect(inst.anyTruthy).toEqual(true);
96 inst.clear([]);
97 expect(inst.anyTruthy).toEqual(false);
98 });
99 })
100
101 it('simple keyBy', () => {
102 const model = {
103 itemByIdx: root.keyBy(val => val.get('idx')).mapValues(val => val.get('text').call('tap')),
104 set: setter(arg0),
105 splice: splice()
106 };
107 const optModel = evalOrLoad(compile(model, {compiler}));
108 const inst = optModel([{idx: 1, text: 'a'}, {idx: 2, text: 'b'}, {idx: 3, text: 'c'}], funcLibrary);
109 expectTapFunctionToHaveBeenCalled(3, compiler);
110 expect(inst.itemByIdx).toEqual({1: 'a', 2: 'b', 3: 'c'});
111 inst.set(0, {idx: 4, text: 'd'});
112 expectTapFunctionToHaveBeenCalled(1, compiler);
113 expect(inst.itemByIdx).toEqual({4: 'd', 2: 'b', 3: 'c'});
114 inst.splice(1, 2, {idx: 3, text: 'e'});
115 expect(inst.itemByIdx).toEqual({4: 'd', 3: 'e'});
116 expectTapFunctionToHaveBeenCalled(1, compiler);
117 const reverseArray = [...inst.$model].reverse();
118 inst.splice(0, inst.$model.length, ...reverseArray);
119 expect(inst.itemByIdx).toEqual({4: 'd', 3: 'e'});
120 expectTapFunctionToHaveBeenCalled(0, compiler);
121 });
122
123 it('raw keyBy', () => {
124 const model = {
125 itemByIdx: root.keyBy(val => val.get('idx')),
126 set: setter(arg0),
127 splice: splice()
128 };
129 const optModel = evalOrLoad(compile(model, {compiler}));
130 const inst = optModel([{idx: 1, text: 'a', foo: 'bar'}, {idx: 2, text: 'b'}, {idx: 1, text: 'c'}], funcLibrary);
131 expect(inst.itemByIdx).toEqual({1: {idx: 1, text: 'c'}, 2: {idx: 2, text: 'b'}});
132 });
133
134 it('double-valued keyBy', () => {
135 const model = {
136 asObject: root.keyBy(val => val),
137 set: setter(arg0)
138 };
139 const optModel = evalOrLoad(compile(model, {compiler}));
140 const inst = optModel(['a', 'a'], funcLibrary);
141 expect(inst.asObject).toEqual({a: 'a'})
142 inst.set(0, 'b')
143 expect(inst.asObject).toEqual({a: 'a', b: 'b'})
144 });
145
146 it('simple comparison operations', () => {
147 const arr = root.get('arr');
148 const compareTo = root.get('compareTo');
149 const model = {
150 greaterThan: arr.map(val => val.gt(compareTo).call('tap')),
151 lessThan: arr.map(val => val.lt(compareTo).call('tap')),
152 greaterOrEqual: arr.map(val => val.gte(compareTo).call('tap')),
153 lessThanOrEqual: arr.map(val => val.lte(compareTo).call('tap')),
154 setArr: setter('arr', arg0),
155 setCompareTo: setter('compareTo')
156 };
157 const optModel = evalOrLoad(compile(model, {compiler}));
158 const inst = optModel({arr: [0, 1, 2, 3, 4], compareTo: 2}, funcLibrary);
159 expect(currentValues(inst)).toEqual({
160 greaterThan: [false, false, false, true, true],
161 lessThan: [true, true, false, false, false],
162 greaterOrEqual: [false, false, true, true, true],
163 lessThanOrEqual: [true, true, true, false, false]
164 });
165 expectTapFunctionToHaveBeenCalled(20, compiler);
166 inst.setArr(4, 0);
167 expect(currentValues(inst)).toEqual({
168 greaterThan: [false, false, false, true, false],
169 lessThan: [true, true, false, false, true],
170 greaterOrEqual: [false, false, true, true, false],
171 lessThanOrEqual: [true, true, true, false, true]
172 });
173 expectTapFunctionToHaveBeenCalled(4, compiler);
174 inst.setCompareTo(100);
175 expect(currentValues(inst)).toEqual({
176 greaterThan: [false, false, false, false, false],
177 lessThan: [true, true, true, true, true],
178 greaterOrEqual: [false, false, false, false, false],
179 lessThanOrEqual: [true, true, true, true, true]
180 });
181 expectTapFunctionToHaveBeenCalled(6, compiler);
182 });
183 it('test creation of arrays', () => {
184 const sumsTuple = root.map(item => [item.get(0).plus(item.get(1))]);
185 const mapOfSum = sumsTuple.map(item => item.get(0).call('tap'));
186
187 const model = {mapOfSum, set0: setter(arg0, 0), set1: setter(arg0, 1)};
188 const optCode = evalOrLoad(compile(model, {compiler}));
189 const initialData = [[1, 2], [3, 4], [5, 6]];
190 const inst = optCode(initialData, funcLibrary);
191 expect(inst.mapOfSum).toEqual([3, 7, 11]);
192 expectTapFunctionToHaveBeenCalled(3, compiler);
193 inst.set0(0, 7);
194 expect(inst.mapOfSum).toEqual([9, 7, 11]);
195 expectTapFunctionToHaveBeenCalled(1, compiler);
196 inst.$startBatch();
197 inst.set0(1, 4);
198 inst.set1(1, 3);
199 inst.$endBatch();
200 expect(inst.mapOfSum).toEqual([9, 7, 11]);
201 expectTapFunctionToHaveBeenCalled(0, compiler);
202 });
203 it('test assign/defaults', () => {
204 const model = {
205 assign: root.assign().mapValues(val => val.call('tap')),
206 defaults: root.defaults().mapValues(val => val.call('tap')),
207 set: setter(arg0),
208 setInner: setter(arg0, arg1),
209 splice: splice()
210 };
211 const optCode = evalOrLoad(compile(model, {compiler}));
212 const initialData = [{a: 1}, {b: 2}, {a: 5}];
213 const inst = optCode(initialData, funcLibrary);
214 expect(currentValues(inst)).toEqual({assign: {a: 5, b: 2}, defaults: {a: 1, b: 2}});
215 expectTapFunctionToHaveBeenCalled(4, compiler);
216 inst.set(0, {a: 7});
217 expect(currentValues(inst)).toEqual({assign: {a: 5, b: 2}, defaults: {a: 7, b: 2}});
218 expectTapFunctionToHaveBeenCalled(1, compiler);
219 inst.setInner(2, 'a', 9);
220 expect(currentValues(inst)).toEqual({assign: {a: 9, b: 2}, defaults: {a: 7, b: 2}});
221 expectTapFunctionToHaveBeenCalled(1, compiler);
222 inst.splice(1, 1);
223 expect(currentValues(inst)).toEqual({assign: {a: 9}, defaults: {a: 7}});
224 expectTapFunctionToHaveBeenCalled(0, compiler);
225 });
226 it('ranges', () => {
227 const model = {
228 range: root
229 .get('end')
230 .range()
231 .map(item => item.call('tap')),
232 rangeStart: root
233 .get('end')
234 .range(root.get('start'))
235 .map(item => item.call('tap')),
236 rangeStep: root
237 .get('end')
238 .range(root.get('start'), root.get('step'))
239 .map(item => item.call('tap')),
240 setEnd: setter('end'),
241 setStep: setter('step'),
242 setStart: setter('start')
243 };
244 const initialData = {start: 2, end: 5, step: 2};
245 const optCode = evalOrLoad(compile(model, {compiler}));
246 const inst = optCode(initialData, funcLibrary);
247 expect(inst.range).toEqual([0, 1, 2, 3, 4]);
248 expect(inst.rangeStart).toEqual([2, 3, 4]);
249 expect(inst.rangeStep).toEqual([2, 4]);
250 expectTapFunctionToHaveBeenCalled(10, compiler);
251 inst.setEnd(7);
252 expect(inst.range).toEqual([0, 1, 2, 3, 4, 5, 6]);
253 expect(inst.rangeStart).toEqual([2, 3, 4, 5, 6]);
254 expect(inst.rangeStep).toEqual([2, 4, 6]);
255 expectTapFunctionToHaveBeenCalled(5, compiler);
256 });
257 it('test range/size', () => {
258 const matches = root.get('items').filter(val => val.eq(root.get('match')));
259 const model = {
260 fizzBuzz: matches
261 .size()
262 .range(1)
263 .map(val =>
264 val
265 .mod(15)
266 .eq(0)
267 .ternary(
268 'fizzbuzz',
269 val
270 .mod(3)
271 .eq(0)
272 .ternary(
273 'fizz',
274 val
275 .mod(5)
276 .eq(0)
277 .ternary('buzz', val)
278 )
279 )
280 )
281 .map(val => val.call('tap')),
282 spliceItems: splice('items'),
283 setMatch: setter('match')
284 };
285 const initialData = {
286 items: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 2, 2, 2, 2],
287 match: 1
288 };
289 const optCode = evalOrLoad(compile(model, {compiler}));
290 const inst = optCode(initialData, funcLibrary);
291 expect(inst.fizzBuzz).toEqual([1, 2, 'fizz', 4, 'buzz']);
292 inst.setMatch(0);
293 expect(inst.fizzBuzz).toEqual([
294 1,
295 2,
296 'fizz',
297 4,
298 'buzz',
299 'fizz',
300 7,
301 8,
302 'fizz',
303 'buzz',
304 11,
305 'fizz',
306 13,
307 14,
308 'fizzbuzz'
309 ]);
310 inst.setMatch(2);
311 expect(inst.fizzBuzz).toEqual([1, 2, 'fizz']);
312 });
313 it('range from primitive', () => {
314 const model = {
315 result: chain(10)
316 .range()
317 .filter(item => item.mod(root.get('skip')).eq(0))
318 .map(item => item.call('tap')),
319 set: setter('skip')
320 };
321 const optModel = evalOrLoad(compile(model, {compiler}));
322 const initialData = {skip: 3};
323 const inst = optModel(initialData, funcLibrary);
324 expect(inst.result).toEqual([0, 3, 6, 9]);
325 expectTapFunctionToHaveBeenCalled(4, compiler);
326 inst.set(6);
327 expect(inst.result).toEqual([0, 6]);
328 expectTapFunctionToHaveBeenCalled(1, compiler);
329 });
330 it('range to map from length 0', () => {
331 const model = {
332 result: chain(root.get('len'))
333 .range()
334 .map(item => item.plus(root.get('base')).call('tap')),
335 set: setter('len')
336 };
337 const optModel = evalOrLoad(compile(model, {compiler}));
338 const initialData = {len: 0, base: 2};
339 const inst = optModel(initialData, funcLibrary);
340 expect(inst.result).toEqual([]);
341 expectTapFunctionToHaveBeenCalled(0, compiler);
342 inst.set(1);
343 expect(inst.result).toEqual([2]);
344 expectTapFunctionToHaveBeenCalled(1, compiler);
345 });
346 it('flatten thats not deep', () => {
347 const model = {
348 result: root.flatten().map((v) => v),
349 set: setter(arg0)
350 }
351 const optModel = evalOrLoad(compile(model, {compiler}))
352 const initialData = [[1], [3], [4, [5]]]
353 const inst = optModel(initialData, funcLibrary)
354 expect(inst.result).toEqual([1, 3, 4, [5]])
355 inst.set(0, [2])
356 expect(inst.result).toEqual([2, 3, 4, [5]])
357 })
358 it('flatten thats not deep with objects', () => {
359 const model = {
360 result: root.flatten().map((v) => v),
361 set: setter(arg0)
362 }
363 const optModel = evalOrLoad(compile(model, {compiler}))
364 const initialData = [[{a: 1}], [{a: 3}], [{a: 4}]]
365 const inst = optModel(initialData, funcLibrary)
366 expect(inst.result).toEqual([{a: 1}, {a: 3}, {a: 4}])
367 })
368 it('flatten array changes length', () => {
369 const model = {
370 clean: root.get('target'),
371 data: root.get('target').map(v => v),
372 result: root.get('target').map(v => v).flatten(),
373 result2: root.get('target').flatten(),
374 splice: splice('target')
375 }
376 const optModel = evalOrLoad(compile(model, {compiler}))
377 const initialData = {target: [[1], [2], [3], [4]]}
378 const inst = optModel(initialData, funcLibrary)
379 expect(inst.result).toEqual([1, 2, 3, 4])
380 inst.splice(0, 2, [6], [6], [6])
381 expect(inst.data).toEqual([[6], [6], [6], [3], [4]], 'sanity')
382 expect(inst.result).toEqual([6, 6, 6, 3, 4])
383 inst.splice(0, 3, [67, 67])
384 expect(inst.data).toEqual([[67, 67], [3], [4]], 'sanity')
385 expect(inst.result).toEqual([67, 67, 3, 4])
386 expect(inst.result2).toEqual([67, 67, 3, 4])
387 inst.splice(0, 1, [68, 68])
388 expect(inst.data).toEqual([[68, 68], [3], [4]], 'sanity')
389 expect(inst.result).toEqual([68, 68, 3, 4])
390 expect(inst.result2).toEqual([68, 68, 3, 4])
391 })
392 it('flatten root.array changes length', () => {
393 const model = {
394 clean: root,
395 data: root.map(v => v),
396 result: root.map(v => v).flatten(),
397 result2: root.flatten(),
398 splice: splice()
399 }
400 const optModel = evalOrLoad(compile(model, {compiler}))
401 const initialData = [[1], [2], [3], [4]]
402 const inst = optModel(initialData, funcLibrary)
403 expect(inst.result).toEqual([1, 2, 3, 4])
404 inst.splice(0, 2, [6], [6], [6])
405 expect(inst.data).toEqual([[6], [6], [6], [3], [4]], 'sanity')
406 expect(inst.result).toEqual([6, 6, 6, 3, 4])
407 inst.splice(0, 3, [67, 67])
408 expect(inst.data).toEqual([[67, 67], [3], [4]], 'sanity')
409 expect(inst.result).toEqual([67, 67, 3, 4])
410 expect(inst.result2).toEqual([67, 67, 3, 4])
411 inst.splice(0, 1, [68, 68])
412 expect(inst.data).toEqual([[68, 68], [3], [4]], 'sanity')
413 expect(inst.result).toEqual([68, 68, 3, 4])
414 expect(inst.result2).toEqual([68, 68, 3, 4])
415 })
416 it('flatten with two empty arrays', () => {
417 const model = {
418 clean: root.get('target'),
419 data: root.get('target').map(v => v),
420 result: root.get('target').map(v => v).flatten(),
421 result2: root.get('target').flatten(),
422 splice: splice('target')
423 }
424 const optModel = evalOrLoad(compile(model, {compiler}))
425 const initialData = {target: [[], []]}
426 const inst = optModel(initialData, funcLibrary)
427 expect(inst.result).toEqual([])
428 inst.splice(0, 0, [], [], [])
429 expect(inst.result).toEqual([])
430 inst.splice(2, 0, [1])
431 expect(inst.result).toEqual([1])
432 })
433 it('flatten with adding empty array', () => {
434 const model = {
435 clean: root.get('target'),
436 data: root.get('target').map(v => v),
437 result: root.get('target').map(v => v).flatten(),
438 result2: root.get('target').flatten(),
439 splice: splice('target')
440 }
441 const optModel = evalOrLoad(compile(model, {compiler}))
442 const initialData = {target: [[1], [2], [3], [4]]}
443 const inst = optModel(initialData, funcLibrary)
444 expect(inst.result).toEqual([1, 2, 3, 4])
445 inst.splice(0, 2, [], [], [])
446 expect(inst.result).toEqual([3, 4])
447 inst.splice(0, 0, [], [6], [])
448 expect(inst.result).toEqual([6, 3, 4])
449 })
450 it('flatten with empty array', () => {
451 const model = {
452 result: root.flatten(),
453 set: setter(arg0)
454 };
455 const optModel = evalOrLoad(compile(model, {compiler}))
456 const initialData = []
457 const inst = optModel(initialData, funcLibrary)
458 expect(inst.result).toEqual([])
459 })
460 it('sum', () => {
461 const model = {
462 result: root.sum(),
463 set: setter(arg0)
464 };
465 const optModel = evalOrLoad(compile(model, {compiler}));
466 const initialData = [1, 3, 5];
467 const inst = optModel(initialData, funcLibrary);
468 expect(inst.result).toEqual(9);
469 inst.set(2, 1);
470 inst.set(0, 5);
471 expect(inst.result).toEqual(9);
472 });
473 it('sum with empty array', () => {
474 const model = {
475 result: root.sum(),
476 set: setter(arg0)
477 };
478 const optModel = evalOrLoad(compile(model, {compiler}));
479 const initialData = [];
480 const inst = optModel(initialData, funcLibrary);
481 expect(inst.result).toEqual(0);
482 });
483 it('sum with array that changes length', () => {
484 const model = {
485 result: root.sum(),
486 splice: splice(),
487 set: setter(arg0)
488 };
489 const optModel = evalOrLoad(compile(model, {compiler}));
490 const initialData = [1, 2, 3, 4];
491 const inst = optModel(initialData, funcLibrary);
492 expect(inst.result).toEqual(10);
493 inst.splice(0, 1)
494 expect(inst.result).toEqual(9);
495 inst.splice(0, 0, 6)
496 expect(inst.result).toEqual(15)
497 });
498 it('concat', () => {
499 const model = {
500 result: root.get('a').concat(root.get('b')),
501 set: setter('a', arg0)
502 };
503 const optModel = evalOrLoad(compile(model, {compiler}));
504 const initialData = {a: [1, 3, 5], b: [2, 6]};
505 const inst = optModel(initialData, funcLibrary);
506 expect(inst.result).toEqual([1, 3, 5, 2, 6]);
507 inst.set(2, 1);
508 expect(inst.result).toEqual([1, 3, 1, 2, 6]);
509 });
510 it('concat with empty array', () => {
511 const model = {
512 result: root.get('a').concat(root.get('b')),
513 set: setter('a', arg0)
514 };
515 const optModel = evalOrLoad(compile(model, {compiler}));
516 const initialData = {a: [1, 3, 5], b: []};
517 const inst = optModel(initialData, funcLibrary);
518 expect(inst.result).toEqual([1, 3, 5]);
519 inst.set(2, 1);
520 expect(inst.result).toEqual([1, 3, 1]);
521 });
522
523 it('concat with empty array', () => {
524 const model = {
525 result: root.get('b').concat(root.get('a')),
526 set: setter('a', arg0)
527 };
528 const optModel = evalOrLoad(compile(model, {compiler}));
529 const initialData = {a: [1, 3, 5], b: []};
530 const inst = optModel(initialData, funcLibrary);
531 expect(inst.result).toEqual([1, 3, 5]);
532 });
533 it('append with primitive', () => {
534 const initialData = ['a', 'b', 'c'];
535 const model = {
536 result: root.append('d')
537 };
538 const optModel = evalOrLoad(compile(model, {compiler}));
539 const inst = optModel(initialData);
540 expect(inst.result).toEqual(['a', 'b', 'c', 'd']);
541 });
542 it('append with array', () => {
543 const initialData = ['a', 'b', 'c'];
544 const model = {
545 result: root.append(['d'])
546 };
547 const optModel = evalOrLoad(compile(model, {compiler}));
548 const inst = optModel(initialData);
549 expect(inst.result).toEqual(['a', 'b', 'c', ['d']]);
550 });
551 describe('includes', () => {
552 it('should return true if includes value', () => {
553 const initialData = {data: [1, 2, 3]};
554 const value = 1
555 const model = {
556 includes: root.get('data').includes(value)
557 };
558 const optModel = evalOrLoad(compile(model, {compiler}));
559
560 const inst = optModel(initialData);
561 expect(inst.includes).toEqual(_.includes(initialData.data, value));
562 });
563 it('should return false if not includes value', () => {
564 const initialData = {data: [1, 2, 3]};
565 const value = 4
566 const model = {
567 includes: root.get('data').includes(value)
568 };
569 const optModel = evalOrLoad(compile(model, {compiler}));
570
571 const inst = optModel(initialData);
572 expect(inst.includes).toEqual(_.includes(initialData.data, value));
573 });
574 })
575 describe('findIndex', () => {
576 it('should return right index by predicate', () => {
577 const initialData = {data: [{id: 1}, {id: 2}, {id: 3}]};
578 const findId = 2;
579 const model = {
580 findIndex: root.get('data').findIndex(item => item.get('id').eq(findId))
581 };
582 const optModel = evalOrLoad(compile(model, {compiler}));
583
584 const inst = optModel(initialData);
585 expect(inst.findIndex).toEqual(1);
586 });
587 it('should support findding the first element', () => {
588 const initialData = {data: [{id: 1}, {id: 2}, {id: 3}]};
589 const findId = 1;
590 const model = {
591 findIndex: root.get('data').findIndex(item => item.get('id').eq(findId))
592 };
593 const optModel = evalOrLoad(compile(model, {compiler}));
594
595 const inst = optModel(initialData);
596 expect(inst.findIndex).toEqual(0);
597 });
598
599 it('should return -1 if not found', () => {
600 const initialData = {data: [{id: 1}, {id: 2}, {id: 3}]};
601 const findId = 4;
602 const model = {
603 findIndex: root.get('data').findIndex(item => item.get('id').eq(findId))
604 };
605 const optModel = evalOrLoad(compile(model, {compiler}));
606
607 const inst = optModel(initialData);
608 expect(inst.findIndex).toEqual(-1);
609 });
610 })
611 it('branching - soft tracking', () => {
612 const valuesInArrays = root.map(item => or(item.get('arr'), [item.get('val')]));
613 const indexes = root.map((item, idx) => idx);
614 const model = {
615 result: indexes.map(idx => valuesInArrays.get(idx).get(0)),
616 set: setter(arg0)
617 };
618 const optModel = evalOrLoad(compile(model, {compiler}));
619 const initialData = [{arr: [1]}, {val: 2}, {arr: [3]}];
620 const inst = optModel(initialData);
621 expect(inst.result).toEqual([1, 2, 3]);
622 inst.set(0, {val: 4});
623 expect(inst.result).toEqual([4, 2, 3]);
624 inst.set(1, {arr: [5]});
625 expect(inst.result).toEqual([4, 5, 3]);
626 });
627 it('test binding', () => {
628 const model = {
629 doubleFunctions: root.map(item => bind('double', item)).map(item => item.call('tap')),
630 multFunctions: root.map(item => bind('mult', item)).map(item => item.call('tap')),
631 updateFunctions: root.map((item, key) => bind('updateSelf', key, item.mult(2))).map(item => item.call('tap')),
632 set: setter(arg0)
633 };
634 const initialData = [3, 4];
635 const optModel = evalOrLoad(compile(model, {compiler}));
636 const extraFn = {
637 double: x => x * 2,
638 mult: (x, y) => x * y,
639 updateSelf(index, val) {
640 this.set(index, val);
641 }
642 };
643 const inst = optModel(initialData, {...extraFn, ...funcLibrary});
644 expect(inst.doubleFunctions[0]()).toEqual(6);
645 expect(inst.doubleFunctions[1]()).toEqual(8);
646 expect(inst.multFunctions[0](5)).toEqual(15);
647 expect(inst.multFunctions[1](5)).toEqual(20);
648 const old = inst.doubleFunctions[0];
649 expectTapFunctionToHaveBeenCalled(6, compiler);
650 inst.updateFunctions[0]();
651 expectTapFunctionToHaveBeenCalled(0, compiler);
652 expect(inst.doubleFunctions[0]()).toEqual(12);
653 expect(inst.doubleFunctions[1]()).toEqual(8);
654 });
655 it('test reverse', () => {
656 const model = {
657 numbers: root.reverse()
658 };
659 const optModel = evalOrLoad(compile(model, {compiler}));
660 const initialData = [1, 2, 3, 4, 5];
661
662 const inst = optModel(initialData);
663 expect(inst.numbers).toEqual(initialData.reverse());
664 });
665
666 describe('isEmpty', () => {
667 it('should return true for empty array', () => {
668 const initialData = {data: []}
669 const model = {
670 isEmpty: root.get('data').isEmpty()
671 };
672 const optModel = evalOrLoad(compile(model, {compiler}));
673
674 const inst = optModel(initialData);
675 expect(inst.isEmpty).toEqual(true);
676 });
677
678 it('should return false for non empty array', () => {
679 const initialData = {data: [1]}
680 const model = {
681 isEmpty: root.get('data').isEmpty()
682 };
683 const optModel = evalOrLoad(compile(model, {compiler}));
684
685 const inst = optModel(initialData);
686 expect(inst.isEmpty).toEqual(false);
687 });
688 })
689
690 describe('intersection', () => {
691 it('should return an array of unique values that are included in given arrays', () => {
692 const initialData = {a: ['a', 'b', 'c', 'd'], b: ['b', 'd']}
693 const model = {
694 result: root.get('a').intersection(root.get('b'))
695 };
696 const optModel = evalOrLoad(compile(model, {compiler}));
697 const inst = optModel(initialData, funcLibrary);
698 expect(inst.result).toEqual(['b', 'd']);
699 })
700 })
701
702 describe('uniq', () => {
703 it('should return a duplicate-free version of an array', () => {
704 const initialData = {a: ['a', 'a', 'b', 'c', 'c', 'c']}
705 const model = {
706 result: root.get('a').uniq()
707 };
708 const optModel = evalOrLoad(compile(model, {compiler}));
709 const inst = optModel(initialData, funcLibrary);
710 expect(inst.result).toEqual(['a', 'b', 'c']);
711 })
712 })
713
714 it('test head', () => {
715 const model = {
716 first: root.head()
717 };
718 const optModel = evalOrLoad(compile(model, {compiler}));
719 const initialData = ['a', 2, 3, 4, 5];
720
721 const inst = optModel(initialData);
722 expect(inst.first).toEqual(initialData[0]);
723 });
724 it('test last', () => {
725 const model = {
726 last: root.last()
727 };
728 const optModel = evalOrLoad(compile(model, {compiler}));
729 const initialData = [1, 2, 3, 4, 5];
730
731 const inst = optModel(initialData);
732 expect(inst.last).toEqual(initialData[initialData.length - 1]);
733 });
734 it('test compact', () => {
735 const initialData = {data: [null, 1, '', false, 'test']};
736 const model = {
737 compact: root.get('data').compact()
738 };
739 const optModel = evalOrLoad(compile(model, {compiler}));
740
741 const inst = optModel(initialData);
742 expect(inst.compact).toEqual(_.compact(initialData.data));
743 });
744
745 describe('every', () => {
746 it('should return true if predicate returns truthy for all elements in the array', () => {
747 const initialData = {data: [1, 1, 1]};
748 const model = {
749 every: root.get('data').every(item => item.eq(1))
750 };
751 const optModel = evalOrLoad(compile(model, {compiler}));
752
753 const inst = optModel(initialData);
754 expect(inst.every).toBe(true);
755 });
756
757 it('should return false if predicate does not return truthy for all elements in the array', () => {
758 const initialData = {data: [1, 2, 1]};
759 const model = {
760 every: root.get('data').every(item => item.eq(1))
761 };
762 const optModel = evalOrLoad(compile(model, {compiler}));
763
764 const inst = optModel(initialData);
765 expect(inst.every).toBe(false);
766 });
767 });
768 describe('isArray tests', () => {
769 it('should return true if is array', () => {
770 const model = {
771 isArray: root.isArray()
772 };
773 const optModel = evalOrLoad(compile(model, {compiler}));
774 const initialData = [1, 2, 3];
775
776 const inst = optModel(initialData);
777 expect(inst.isArray).toEqual(true);
778 });
779 it('should return false if not array', () => {
780 const model = {
781 isArray: root.isArray()
782 };
783 const optModel = evalOrLoad(compile(model, {compiler}));
784 const initialData = 5;
785
786 const inst = optModel(initialData);
787 expect(inst.isArray).toEqual(false);
788 });
789 });
790 describe('test rewrite local functions', () => {
791 it('should hoist the reused function', () => {
792 const add10 = src => new Array(10).fill().reduce(v => v.plus(1), src)
793 const model = {
794 add30: root.map(val => add10(val).plus(add10(val)).plus(add10(val)))
795 };
796 const src = compile(model, {compiler, prettier: true})
797 if (typeof src === 'string') {
798 expect(src.split(' + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1').length - 1).toEqual(1)
799 }
800 const optModel = evalOrLoad(src);
801 const initialData = [1, 2, 3];
802
803 const inst = optModel(initialData);
804 expect(inst.add30).toEqual([33, 36, 39]);
805 })
806 })
807 });
808});