UNPKG

22.7 kBJavaScriptView Raw
1const {compile, and, or, root, arg0, setter, chain, splice} = require('../../index');
2
3const {
4 describeCompilers,
5 evalOrLoad,
6 currentValues,
7 funcLibrary,
8 expectTapFunctionToHaveBeenCalled,
9 rand
10} = require('../test-utils');
11const _ = require('lodash');
12
13describe('testing objects', () => {
14 describeCompilers(['simple', 'optimizing', 'bytecode'], compiler => {
15 describe('get', () => {
16 it('not passing', () => {
17 const model = {
18 set: setter('model', arg0),
19 result: root.get('model').get('kofnae')
20 // model: root.get('model')
21 };
22 const optModel = evalOrLoad(compile(model, {compiler}));
23 const initialData = {
24 model: {}
25 };
26
27 const inst = optModel(initialData);
28 inst.set('kofnae', 'meod');
29 expect(inst.result).toEqual('meod');
30 });
31 it('passing', () => {
32 const model = {
33 set: setter('model', arg0),
34 result: root.get('model').get('kofnae'),
35 model: root.get('model') // TODO Reut - this is the only difference
36 };
37 const optModel = evalOrLoad(compile(model, {compiler}));
38 const initialData = {
39 model: {}
40 };
41
42 const inst = optModel(initialData);
43 inst.set('kofnae', 'meod');
44 expect(inst.result).toEqual('meod');
45 });
46 });
47 it('mapValues context value', () => {
48 const model = {
49 shared: root.mapValues(item =>
50 root.filterBy((innerItem, innerKey, outerItem) => innerItem.eq(outerItem), item)
51 ),
52 setItem: setter(arg0)
53 };
54 const optModel = evalOrLoad(compile(model, {compiler}));
55 const initialData = {One: 1, Two: 2, First: 1, Second: 2};
56 const inst = optModel(initialData);
57 expect(inst.shared).toEqual({
58 First: {First: 1, One: 1},
59 One: {First: 1, One: 1},
60 Second: {Second: 2, Two: 2},
61 Two: {Second: 2, Two: 2}
62 });
63 inst.setItem('First', 2);
64 expect(inst.shared).toEqual({
65 First: {First: 2, Second: 2, Two: 2},
66 One: {One: 1},
67 Second: {First: 2, Second: 2, Two: 2},
68 Two: {First: 2, Second: 2, Two: 2}
69 });
70 });
71 it('mapValues context key', () => {
72 const model = {
73 shared: root.mapValues((item, key) =>
74 root.filterBy((innerItem, innerKey, outerItem) => innerItem.eq(root.get(outerItem)), key)
75 ),
76 setItem: setter(arg0)
77 };
78 const optModel = evalOrLoad(compile(model, {compiler}));
79 const initalData = {One: 1, Two: 2, First: 1, Second: 2};
80 const inst = optModel(initalData);
81 expect(inst.shared).toEqual({
82 First: {First: 1, One: 1},
83 One: {First: 1, One: 1},
84 Second: {Second: 2, Two: 2},
85 Two: {Second: 2, Two: 2}
86 });
87 inst.setItem('First', 2);
88 expect(inst.shared).toEqual({
89 First: {First: 2, Second: 2, Two: 2},
90 One: {One: 1},
91 Second: {First: 2, Second: 2, Two: 2},
92 Two: {First: 2, Second: 2, Two: 2}
93 });
94 });
95 it('groupBy', () => {
96 const numOfDoneItems = root
97 .groupBy('done')
98 .get('true')
99 .call('tap')
100 .size();
101 const model = {numOfDoneItems, update: setter(arg0, 'done')};
102 const optModel = evalOrLoad(compile(model, {compiler}));
103 const initialData = {
104 a: {done: true, text: 'a'},
105 b: {done: true, text: 'b'},
106 c: {done: false, text: 'c'}
107 };
108 const inst = optModel(initialData, funcLibrary);
109 expect(inst.numOfDoneItems).toEqual(2);
110 expectTapFunctionToHaveBeenCalled(1, compiler);
111 inst.update('b', false);
112 expect(inst.numOfDoneItems).toEqual(1);
113 expectTapFunctionToHaveBeenCalled(1, compiler);
114 });
115 it('groupBy when initial data is empty', () => {
116 const doneItems = root
117 .get('data')
118 .groupBy('done')
119 .get('true')
120 .call('tap');
121 const model = {doneItems, update: setter('data')};
122 const optModel = evalOrLoad(compile(model, {compiler}));
123 const initialData = {
124 data: {}
125 };
126 const inst = optModel(initialData, funcLibrary);
127 expect(inst.doneItems).toEqual(undefined);
128 expectTapFunctionToHaveBeenCalled(1, compiler);
129 const updateData = {
130 a: {done: true, text: 'a'},
131 b: {done: true, text: 'b'},
132 c: {done: false, text: 'c'}
133 };
134 inst.update(updateData);
135 expect(inst.doneItems).toEqual(_.pick(updateData, ['a', 'b']));
136 expectTapFunctionToHaveBeenCalled(1, compiler);
137 });
138
139 it('anyValues when removing elements', () => {
140 const model = {
141 anyTruthy: root.get('data').anyValues(a => a.get('val')),
142 set: setter('data', arg0),
143 clear: setter('data')
144 };
145 const optModel = evalOrLoad(compile(model, {compiler}));
146 const inst = optModel({data: {a: {val: false}, b: {val: true}, c: {val: false}}}, funcLibrary);
147 expect(inst.anyTruthy).toEqual(true);
148 inst.clear({});
149 expect(inst.anyTruthy).toEqual(false);
150 });
151
152 it('should contain only one group after removing item', () => {
153 const doneItems = root
154 .get('data')
155 .groupBy('done')
156 .get('true')
157 .call('tap');
158 const model = {doneItems, update: setter('data', arg0)};
159 const optModel = evalOrLoad(compile(model, {compiler}));
160 const initialData = {
161 data: {
162 a: {done: true, text: 'a'},
163 b: {done: true, text: 'b'},
164 c: {done: false, text: 'c'}
165 }
166 };
167 const inst = optModel(initialData, funcLibrary);
168 expect(inst.doneItems).toEqual({a: {done: true, text: 'a'}, b: {done: true, text: 'b'}});
169 expectTapFunctionToHaveBeenCalled(1, compiler);
170
171 inst.update('c', undefined);
172 expect(Object.keys(inst.doneItems)).toEqual(['a', 'b']);
173 expectTapFunctionToHaveBeenCalled(0, compiler);
174 });
175
176 it('groupBy should invalidate external', () => {
177 const itemsByState = root
178 .groupBy(item => item.get('state'))
179 const numOfDoneItems =
180 chain([itemsByState.get('archive'), itemsByState.get('done')])
181 .assign()
182 .mapValues(item => item.call('tap'))
183 .size();
184 const model = {numOfDoneItems, update: setter(arg0)};
185 const optModel = evalOrLoad(compile(model, {compiler}));
186 const initialData = {
187 a: {state: 'done', text: 'a'},
188 b: {state: 'done', text: 'b'},
189 c: {state: 'archive', text: 'c'},
190 d: {state: 'pending', text: 'd'}
191 };
192 const inst = optModel(initialData, funcLibrary);
193 expect(inst.numOfDoneItems).toEqual(3);
194 expectTapFunctionToHaveBeenCalled(3, compiler);
195 inst.update('e', {state: 'done', text: 'e'});
196 expect(inst.numOfDoneItems).toEqual(4);
197 expectTapFunctionToHaveBeenCalled(1, compiler);
198 })
199
200 it('using simple constant objects', () => {
201 const translate = chain({First: 'a', Second: 'b', Third: 'c'});
202 const model = {
203 lookUp: root
204 .get('source')
205 .mapValues(item => or(and(translate.get(item), root.get('results').get(translate.get(item))), '')),
206 setItem: setter('source', arg0)
207 };
208 const optModel = evalOrLoad(compile(model, {compiler}));
209 const initalData = {
210 source: {One: 'First', Two: 'Second', Three: 'Unknown'},
211 results: {a: 'A', b: 'B', c: 'C'}
212 };
213 const inst = optModel(initalData);
214 expect(inst.lookUp).toEqual({One: 'A', Two: 'B', Three: ''});
215 inst.setItem('Three', 'Third');
216 expect(inst.lookUp).toEqual({One: 'A', Two: 'B', Three: 'C'});
217 });
218 it('mapKeys', () => {
219 const model = {
220 byName: root
221 .mapValues((title, idx) => ({title, idx}))
222 .mapKeys(item => item.get('title'))
223 .mapValues(item => item.call('tap')),
224
225 set: setter(arg0)
226 };
227 const optModel = evalOrLoad(compile(model, {compiler}));
228 const initalData = {1: 'One', 2: 'Two', 3: 'Three'};
229 const inst = optModel(initalData, funcLibrary);
230 expect(inst.byName).toEqual({
231 One: {title: 'One', idx: '1'},
232 Two: {title: 'Two', idx: '2'},
233 Three: {title: 'Three', idx: '3'}
234 });
235 expectTapFunctionToHaveBeenCalled(3, compiler);
236 inst.set('3', 'Third');
237 expect(inst.byName).toEqual({
238 One: {title: 'One', idx: '1'},
239 Two: {title: 'Two', idx: '2'},
240 Third: {title: 'Third', idx: '3'}
241 });
242 expectTapFunctionToHaveBeenCalled(1, compiler);
243 inst.set('3');
244 expect(inst.byName).toEqual({
245 One: {title: 'One', idx: '1'},
246 Two: {title: 'Two', idx: '2'}
247 });
248 expectTapFunctionToHaveBeenCalled(0, compiler);
249 inst.$startBatch();
250 inst.set('1', 'Two');
251 inst.set('2', 'One');
252 inst.$endBatch();
253 expect(inst.byName).toEqual({
254 One: {title: 'One', idx: '2'},
255 Two: {title: 'Two', idx: '1'}
256 });
257 expectTapFunctionToHaveBeenCalled(2, compiler);
258 });
259 it('values/keys', () => {
260 const rangeMin = root.get('center').minus(root.get('range'));
261 const rangeMax = root.get('center').plus(root.get('range'));
262 const model = {
263 inRange: root
264 .get('numbers')
265 .filterBy(val => and(val.gte(rangeMin), val.lte(rangeMax)))
266 .keys()
267 .keyBy(val => val.call('tap')),
268 set: setter('numbers', arg0),
269 setCenter: setter('center'),
270 setRange: setter('range')
271 };
272 const optModel = evalOrLoad(compile(model, {compiler}));
273 const initialData = {
274 numbers: {
275 eight: 8,
276 five: 5,
277 twelve: 12,
278 three: 3,
279 ten: 10,
280 one: 1
281 },
282 center: 4,
283 range: 3
284 };
285 const inst = optModel(initialData, funcLibrary);
286 expect(inst.inRange).toEqual({five: 'five', three: 'three', one: 'one'});
287 expectTapFunctionToHaveBeenCalled(3, compiler);
288 inst.setCenter(9);
289 expect(inst.inRange).toEqual({eight: 'eight', twelve: 'twelve', ten: 'ten'});
290 expectTapFunctionToHaveBeenCalled(3, compiler);
291 inst.setCenter(6);
292 expect(inst.inRange).toEqual({eight: 'eight', five: 'five', three: 'three'});
293 expectTapFunctionToHaveBeenCalled(2, compiler);
294 inst.$startBatch();
295 inst.setRange(7);
296 expectTapFunctionToHaveBeenCalled(0, compiler); // batch
297 inst.setCenter(2);
298 inst.$endBatch();
299 expect(inst.inRange).toEqual({five: 'five', three: 'three', one: 'one', eight: 'eight'});
300 expectTapFunctionToHaveBeenCalled(1, compiler);
301 inst.setCenter(15);
302 expect(inst.inRange).toEqual({twelve: 'twelve', ten: 'ten', eight: 'eight'});
303 expectTapFunctionToHaveBeenCalled(2, compiler);
304 });
305 it('mapValues', () => {
306 const textsIfDone = root
307 .mapValues(val => val.get('done').ternary(val.get('text'), val.get('missingProp')))
308 .mapValues(text => text.call('tap'));
309 const model = {textsIfDone, update: setter(arg0, 'done')};
310 const optModel = evalOrLoad(compile(model, {compiler}));
311 const initialData = {
312 a: {done: true, text: 'a'},
313 b: {done: true, text: 'b'},
314 c: {done: false, text: 'c'}
315 };
316 const inst = optModel(initialData, funcLibrary);
317 expect(inst.textsIfDone).toEqual({a: 'a', b: 'b', c: undefined});
318 expectTapFunctionToHaveBeenCalled(3, compiler);
319 inst.update('b', false);
320 expect(inst.textsIfDone).toEqual({a: 'a', b: undefined, c: undefined});
321 expectTapFunctionToHaveBeenCalled(1, compiler);
322 });
323 it('create objects', () => {
324 const itemsWithKey = root.mapValues((item, key) => ({
325 key,
326 text: item.get('text'),
327 idx: item.get('idx')
328 }));
329 const itemsByIdx = itemsWithKey.values().keyBy(item => item.get('idx'));
330 const model = {
331 itemsByIdx,
332 updateIdx: setter(arg0, 'idx'),
333 updateItem: setter(arg0)
334 };
335 const optModel = evalOrLoad(compile(model, {compiler}));
336 const initialData = {
337 a: {text: 'A', idx: '0'},
338 b: {text: 'B', idx: '1'},
339 c: {text: 'C', idx: '2'}
340 };
341 const inst = optModel(initialData, funcLibrary);
342 expect(inst.itemsByIdx).toEqual({
343 0: {
344 idx: '0',
345 key: 'a',
346 text: 'A'
347 },
348 1: {
349 idx: '1',
350 key: 'b',
351 text: 'B'
352 },
353 2: {
354 idx: '2',
355 key: 'c',
356 text: 'C'
357 }
358 });
359 inst.updateIdx('a', '4');
360 expect(inst.itemsByIdx).toEqual({
361 4: {
362 idx: '4',
363 key: 'a',
364 text: 'A'
365 },
366 1: {
367 idx: '1',
368 key: 'b',
369 text: 'B'
370 },
371 2: {
372 idx: '2',
373 key: 'c',
374 text: 'C'
375 }
376 });
377 inst.updateItem('a'); /// delete key
378 expect(inst.itemsByIdx).toEqual({
379 1: {
380 idx: '1',
381 key: 'b',
382 text: 'B'
383 },
384 2: {
385 idx: '2',
386 key: 'c',
387 text: 'C'
388 }
389 });
390 });
391 it('getIn', () => {
392 const model = {
393 defined: root.getIn(['a', 'b']),
394 notDefined: root.getIn(['c', 'b'])
395 };
396 const optModel = evalOrLoad(compile(model, {compiler}));
397 const initialData = {a: {b: 1}};
398
399 const inst = optModel(initialData);
400 expect(inst.defined).toEqual(1);
401 expect(inst.notDefined).not.toBeDefined();
402 });
403 it('getIn getter', () => {
404 const a = root.get('a');
405 const model = {
406 a,
407 defined: a.getIn(['b', 'c', 'd']),
408 notDefined: root.getIn(['b', 'e', 'b'])
409 };
410 const optModel = evalOrLoad(compile(model, {compiler}));
411 const initialData = {a: {b: {c: {d: 1}}}};
412
413 const inst = optModel(initialData);
414 expect(inst.defined).toEqual(1);
415 expect(inst.notDefined).not.toBeDefined();
416 });
417 it('getIn mapValues', () => {
418 const overrides = root.get('overrides');
419 const src = root.get('source');
420 const select = root.get('select');
421 const model = {
422 projection: src.mapValues((item, itemId) => or(overrides.getIn([select, itemId]), item)),
423 setSelect: setter('select'),
424 updateSrc: setter('source', arg0),
425 updateOverrides: setter('overrides'),
426 updateOneOverride: setter('overrides', arg0)
427 };
428 const optModel = evalOrLoad(compile(model, {compiler}));
429 const initialData = {source: {a: 1, b: 2}, overrides: {first: {b: 3}, second: {a: 4}}, select: 'none'};
430
431 const inst = optModel(initialData);
432 expect(inst.projection).toEqual({a: 1, b: 2});
433 inst.setSelect('first');
434 expect(inst.projection).toEqual({a: 1, b: 3});
435 });
436 describe('find', () => {
437 it('should find value if exists', () => {
438 const initialData = {a: 'nothing', b: 'something'};
439 const model = {
440 find: root.find(val => val.eq('something'))
441 };
442 const optModel = evalOrLoad(compile(model, {compiler}));
443
444 const inst = optModel(initialData);
445 expect(inst.find).toEqual('something');
446 });
447 it('should return undefined if not exists', () => {
448 const initialData = {a: 'nothing', b: 'something'};
449 const model = {
450 find: root.find(val => val.eq('notExists'))
451 };
452 const optModel = evalOrLoad(compile(model, {compiler}));
453
454 const inst = optModel(initialData);
455 expect(inst.find).toEqual(undefined);
456 });
457 it('should find using context', () => {
458 const initialData = {a: 'nothing', b: 'something'};
459 const model = {
460 find: root.find((val, key, ctx) => val.eq(ctx), root.get('b'))
461 };
462 const optModel = evalOrLoad(compile(model, {compiler}));
463
464 const inst = optModel(initialData);
465 expect(inst.find).toEqual('something');
466 });
467 });
468 describe('setIn', () => {
469 it('should setIn simple with array', () => {
470 const initialData = {data: {a: 1}};
471 const path = ['b'];
472 const value = {};
473 const model = {
474 setIn: root.get('data').setIn(path, value)
475 };
476 const optModel = evalOrLoad(compile(model, {compiler}));
477
478 const inst = optModel(initialData);
479 expect(inst.setIn).toEqual(_.set(initialData.data, path, value));
480 });
481 it('should setIn deep with array', () => {
482 const initialData = {data: {a: 1}};
483 const path = ['a', 'b'];
484 const value = {};
485 const model = {
486 setIn: root.get('data').setIn(path, value)
487 };
488 const optModel = evalOrLoad(compile(model, {compiler}));
489
490 const inst = optModel(initialData);
491 expect(inst.setIn).toEqual(_.set(initialData.data, path, value));
492 });
493 it('should setIn deep without destroying other properties with array', () => {
494 const initialData = {data: {a: 1, b: {c: 'hey'}}};
495 const path = ['a', 'b', 'z', 'd'];
496 const value = 'hello';
497 const model = {
498 setIn: root.get('data').setIn(path, value)
499 };
500 const optModel = evalOrLoad(compile(model, {compiler}));
501
502 const inst = optModel(initialData);
503 expect(inst.setIn).toEqual(_.set(initialData.data, path, value));
504 });
505 });
506 describe('includesValue', () => {
507 it('should return true if includes value', () => {
508 const initialData = {data: {a: 1, b: 2}};
509 const value = 1;
510 const model = {
511 includesValue: root.get('data').includesValue(value)
512 };
513 const optModel = evalOrLoad(compile(model, {compiler}));
514
515 const inst = optModel(initialData);
516 expect(inst.includesValue).toEqual(_.includes(initialData.data, value));
517 });
518 it('should return false if not includes value', () => {
519 const initialData = {data: {a: 1, b: 2}};
520 const value = 3;
521 const model = {
522 includesValue: root.get('data').includesValue(value)
523 };
524 const optModel = evalOrLoad(compile(model, {compiler}));
525
526 const inst = optModel(initialData);
527 expect(inst.includesValue).toEqual(_.includes(initialData.data, value));
528 });
529 });
530 describe('pick', () => {
531 it('should pick simple', () => {
532 const initialData = {data: {a: 1, b: 2}};
533 const path = ['b'];
534 const model = {
535 pick: root.get('data').pick(path)
536 };
537 const optModel = evalOrLoad(compile(model, {compiler}));
538
539 const inst = optModel(initialData);
540 expect(inst.pick).toEqual(_.pick(initialData.data, path));
541 });
542 it('should pick with non-exisiting props', () => {
543 const initialData = {data: {a: 1, b: 2}};
544 const path = ['c'];
545 const model = {
546 pick: root.get('data').pick(path)
547 };
548 const optModel = evalOrLoad(compile(model, {compiler}));
549
550 const inst = optModel(initialData);
551 expect(inst.pick).toEqual(_.pick(initialData.data, path));
552 });
553 it('should pick with empty array', () => {
554 const initialData = {data: {a: 1, b: 2}};
555 const path = [];
556 const model = {
557 pick: root.get('data').pick(path)
558 };
559 const optModel = evalOrLoad(compile(model, {compiler}));
560
561 const inst = optModel(initialData);
562 expect(inst.pick).toEqual(_.pick(initialData.data, path));
563 });
564 it('should pick with complex', () => {
565 const initialData = {data: {a: 1, b: 2, c: {d: 1}, e: [1, 2, 3, 4]}};
566 const path = ['c', 'd', 'e', 'f'];
567 const model = {
568 pick: root.get('data').pick(path)
569 };
570 const optModel = evalOrLoad(compile(model, {compiler}));
571
572 const inst = optModel(initialData);
573 expect(inst.pick).toEqual(_.pick(initialData.data, path));
574 });
575
576 it('should pick falsy values', () => {
577 const initialData = {data: {a: false, b: 2}};
578 const path = ['a'];
579 const model = {
580 pick: root.get('data').pick(path)
581 };
582 const optModel = evalOrLoad(compile(model, {compiler}));
583
584 const inst = optModel(initialData);
585 expect(inst.pick).toEqual(_.pick(initialData.data, path));
586 });
587 });
588
589 describe('isEmpty', () => {
590 it('should return true for empty object', () => {
591 const initialData = {data: {}}
592 const model = {
593 isEmpty: root.get('data').isEmpty()
594 };
595 const optModel = evalOrLoad(compile(model, {compiler}));
596
597 const inst = optModel(initialData);
598 expect(inst.isEmpty).toEqual(true);
599 });
600
601 it('should return false for non empty object', () => {
602 const initialData = {data: {a: 1}}
603 const model = {
604 isEmpty: root.get('data').isEmpty()
605 };
606 const optModel = evalOrLoad(compile(model, {compiler}));
607
608 const inst = optModel(initialData);
609 expect(inst.isEmpty).toEqual(false);
610 });
611 })
612
613 describe('has', () => {
614 it('should return true if contain key', () => {
615 const initialData = {data: {a: 1, b: 2}};
616 const key = 'b';
617 const model = {
618 has: root.get('data').has(key)
619 };
620 const optModel = evalOrLoad(compile(model, {compiler}));
621
622 const inst = optModel(initialData);
623 expect(inst.has).toEqual(_.has(initialData.data, key));
624 });
625 it('should return true if contains key its value is falsy', () => {
626 const initialData = {data: {a: 1, b: null}};
627 const key = 'b';
628 const model = {
629 has: root.get('data').has(key)
630 };
631 const optModel = evalOrLoad(compile(model, {compiler}));
632
633 const inst = optModel(initialData);
634 expect(inst.has).toEqual(_.has(initialData.data, key));
635 });
636 it('should return false if not contain key', () => {
637 const initialData = {data: {a: 1, b: 2}};
638 const key = 'd';
639 const model = {
640 has: root.get('data').has(key)
641 };
642 const optModel = evalOrLoad(compile(model, {compiler}));
643
644 const inst = optModel(initialData);
645 expect(inst.has).toEqual(_.has(initialData.data, key));
646 });
647 });
648 it('assignIn', () => {
649 const model = {
650 defined: root.assignIn([{a: 'women'}]),
651 notDefined: root.assignIn([{x: 'men'}])
652 };
653 const optModel = evalOrLoad(compile(model, {compiler}));
654 const initialData = {a: {b: 1}};
655
656 const inst = optModel(initialData);
657 expect(inst.defined.a).toEqual('women');
658 expect(inst.notDefined.x).toEqual('men');
659 });
660 });
661});