source: imaps-frontend/node_modules/jsx-ast-utils/__tests__/src/getPropValue-babelparser-test.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 37.1 KB
Line 
1/* eslint-env mocha */
2/* eslint no-template-curly-in-string: 0 */
3import assert from 'assert';
4import {
5 extractProp,
6 changePlugins,
7 fallbackToBabylon,
8 describeIfNotBabylon,
9 setParserName,
10} from '../helper';
11import getPropValue from '../../src/getPropValue';
12
13describe('getPropValue', () => {
14 beforeEach(() => {
15 setParserName('babel');
16 });
17
18 it('should export a function', () => {
19 const expected = 'function';
20 const actual = typeof getPropValue;
21
22 assert.equal(actual, expected);
23 });
24
25 it('should return undefined when not provided with a JSXAttribute', () => {
26 const expected = undefined;
27 const actual = getPropValue(1);
28
29 assert.equal(actual, expected);
30 });
31
32 it('should not throw error when trying to get value from unknown node type', () => {
33 const prop = {
34 type: 'JSXAttribute',
35 value: {
36 type: 'JSXExpressionContainer',
37 },
38 };
39 let counter = 0;
40 // eslint-disable-next-line no-console
41 const errorOrig = console.error;
42 // eslint-disable-next-line no-console
43 console.error = () => {
44 counter += 1;
45 };
46 let value;
47 assert.doesNotThrow(() => {
48 value = getPropValue(prop);
49 }, Error);
50
51 assert.equal(null, value);
52 assert.equal(counter, 1);
53 // eslint-disable-next-line no-console
54 console.error = errorOrig;
55 });
56
57 describe('Null', () => {
58 it('should return true when no value is given', () => {
59 const prop = extractProp('<div foo />');
60
61 const expected = true;
62 const actual = getPropValue(prop);
63
64 assert.equal(actual, expected);
65 });
66 });
67
68 describe('Literal', () => {
69 it('should return correct string if value is a string', () => {
70 const prop = extractProp('<div foo="bar" />');
71
72 const expected = 'bar';
73 const actual = getPropValue(prop);
74
75 assert.equal(actual, expected);
76 });
77
78 it('should return correct string if value is a string expression', () => {
79 const prop = extractProp('<div foo={"bar"} />');
80
81 const expected = 'bar';
82 const actual = getPropValue(prop);
83
84 assert.equal(actual, expected);
85 });
86
87 it('should return correct integer if value is a integer expression', () => {
88 const prop = extractProp('<div foo={1} />');
89
90 const expected = 1;
91 const actual = getPropValue(prop);
92
93 assert.equal(actual, expected);
94 });
95
96 it('should convert "true" to boolean type', () => {
97 const prop = extractProp('<div foo="true" />');
98
99 const expected = true;
100 const actual = getPropValue(prop);
101
102 assert.equal(actual, expected);
103 });
104
105 it('should convert "false" to boolean type', () => {
106 const prop = extractProp('<div foo="false" />');
107
108 const expected = false;
109 const actual = getPropValue(prop);
110
111 assert.equal(actual, expected);
112 });
113 });
114
115 describe('JSXElement', () => {
116 it('should return correct representation of JSX element as a string', () => {
117 const prop = extractProp('<div foo={<bar />} />');
118
119 const expected = '<bar />';
120 const actual = getPropValue(prop);
121
122 assert.equal(actual, expected);
123 });
124
125 it('should return correct representation of JSX element with children as a string', () => {
126 const prop = extractProp('<div foo={<bar><baz />foo</bar>} />');
127
128 const expected = '<bar><baz />foo</bar>';
129 const actual = getPropValue(prop);
130
131 assert.equal(actual, expected);
132 });
133 });
134
135 (fallbackToBabylon ? describe.skip : describe)('JSXFragment', () => {
136 it('should return correct representation of JSX fragment as a string', () => {
137 const prop = extractProp('<div foo={<></>} />');
138
139 const expected = '<></>';
140 const actual = getPropValue(prop);
141
142 assert.equal(actual, expected);
143 });
144
145 it('should return correct representation of JSX fragment with children as a string', () => {
146 const prop = extractProp('<div foo={<><div />abc</>} />');
147
148 const expected = '<><div />abc</>';
149 const actual = getPropValue(prop);
150
151 assert.equal(actual, expected);
152 });
153
154 it('supports a prop value containing nested fragments', () => {
155 const propCode = `
156 <>
157 <div>Hello</div>
158 <>
159 <div>There</div>
160 </>
161 </>
162 `;
163 const code = `
164 <Hello
165 role="checkbox"
166 frag={${propCode}}
167 />
168 `;
169
170 const prop = extractProp(code, 'frag');
171 const actual = getPropValue(prop);
172
173 assert.deepEqual(actual, propCode.trim());
174 });
175 });
176
177 describe('Identifier', () => {
178 it('should return string representation of variable identifier', () => {
179 const prop = extractProp('<div foo={bar} />');
180
181 const expected = 'bar';
182 const actual = getPropValue(prop);
183
184 assert.equal(actual, expected);
185 });
186
187 it('should return undefined when identifier is literally `undefined`', () => {
188 const prop = extractProp('<div foo={undefined} />');
189
190 const expected = undefined;
191 const actual = getPropValue(prop);
192
193 assert.equal(actual, expected);
194 });
195
196 it('should return String object when using a reserved JavaScript object', () => {
197 const prop = extractProp('<div foo={String} />');
198
199 const expected = String;
200 const actual = getPropValue(prop);
201
202 assert.equal(actual, expected);
203 });
204
205 it('should return Array object when using a reserved JavaScript object', () => {
206 const prop = extractProp('<div foo={Array} />');
207
208 const expected = Array;
209 const actual = getPropValue(prop);
210
211 assert.equal(actual, expected);
212 });
213
214 it('should return Date object when using a reserved JavaScript object', () => {
215 const prop = extractProp('<div foo={Date} />');
216
217 const expected = Date;
218 const actual = getPropValue(prop);
219
220 assert.equal(actual, expected);
221 });
222
223 it('should return Infinity object when using a reserved JavaScript object', () => {
224 const prop = extractProp('<div foo={Infinity} />');
225
226 const expected = Infinity;
227 const actual = getPropValue(prop);
228
229 assert.equal(actual, expected);
230 });
231
232 it('should return Math object when using a reserved JavaScript object', () => {
233 const prop = extractProp('<div foo={Math} />');
234
235 const expected = Math;
236 const actual = getPropValue(prop);
237
238 assert.equal(actual, expected);
239 });
240
241 it('should return Number object when using a reserved JavaScript object', () => {
242 const prop = extractProp('<div foo={Number} />');
243
244 const expected = Number;
245 const actual = getPropValue(prop);
246
247 assert.equal(actual, expected);
248 });
249
250 it('should return Object object when using a reserved JavaScript object', () => {
251 const prop = extractProp('<div foo={Object} />');
252
253 const expected = Object;
254 const actual = getPropValue(prop);
255
256 assert.equal(actual, expected);
257 });
258 });
259
260 describe('Template literal', () => {
261 it('should return template literal with vars wrapped in curly braces', () => {
262 const prop = extractProp('<div foo={`bar ${baz}`} />');
263
264 const expected = 'bar {baz}';
265 const actual = getPropValue(prop);
266
267 assert.equal(actual, expected);
268 });
269
270 it('should return string "undefined" for expressions that evaluate to undefined', () => {
271 const prop = extractProp('<div foo={`bar ${undefined}`} />');
272
273 const expected = 'bar undefined';
274 const actual = getPropValue(prop);
275
276 assert.equal(actual, expected);
277 });
278
279 it('should return template literal with expression type wrapped in curly braces', () => {
280 const prop = extractProp('<div foo={`bar ${baz()}`} />');
281
282 const expected = 'bar {CallExpression}';
283 const actual = getPropValue(prop);
284
285 assert.equal(actual, expected);
286 });
287
288 it('should ignore non-expressions in the template literal', () => {
289 const prop = extractProp('<div foo={`bar ${<baz />}`} />');
290
291 const expected = 'bar ';
292 const actual = getPropValue(prop);
293
294 assert.equal(actual, expected);
295 });
296 });
297
298 describe('Tagged Template literal', () => {
299 it('should return template literal with vars wrapped in curly braces', () => {
300 const prop = extractProp('<div foo={noop`bar ${baz}`} />');
301
302 const expected = 'bar {baz}';
303 const actual = getPropValue(prop);
304
305 assert.equal(actual, expected);
306 });
307
308 it('should return string "undefined" for expressions that evaluate to undefined', () => {
309 const prop = extractProp('<div foo={noop`bar ${undefined}`} />');
310
311 const expected = 'bar undefined';
312 const actual = getPropValue(prop);
313
314 assert.equal(actual, expected);
315 });
316
317 it('should return template literal with expression type wrapped in curly braces', () => {
318 const prop = extractProp('<div foo={noop`bar ${baz()}`} />');
319
320 const expected = 'bar {CallExpression}';
321 const actual = getPropValue(prop);
322
323 assert.equal(actual, expected);
324 });
325
326 it('should ignore non-expressions in the template literal', () => {
327 const prop = extractProp('<div foo={noop`bar ${<baz />}`} />');
328
329 const expected = 'bar ';
330 const actual = getPropValue(prop);
331
332 assert.equal(actual, expected);
333 });
334 });
335
336 describe('Arrow function expression', () => {
337 it('should return a function', () => {
338 const prop = extractProp('<div foo={ () => { return "bar"; }} />');
339
340 const expected = 'function';
341 const actual = getPropValue(prop);
342
343 assert.equal(expected, typeof actual);
344
345 // For code coverage ¯\_(ツ)_/¯
346 actual();
347 });
348 it('should handle ArrowFunctionExpression as conditional consequent', () => {
349 const prop = extractProp('<div foo={ (true) ? () => null : () => ({})} />');
350
351 const expected = 'function';
352 const actual = getPropValue(prop);
353
354 assert.equal(expected, typeof actual);
355
356 // For code coverage ¯\_(ツ)_/¯
357 actual();
358 });
359 });
360
361 describe('Function expression', () => {
362 it('should return a function', () => {
363 const prop = extractProp('<div foo={ function() { return "bar"; } } />');
364
365 const expected = 'function';
366 const actual = getPropValue(prop);
367
368 assert.equal(expected, typeof actual);
369
370 // For code coverage ¯\_(ツ)_/¯
371 actual();
372 });
373 });
374
375 describe('Logical expression', () => {
376 it('should correctly infer result of && logical expression based on derived values', () => {
377 const prop = extractProp('<div foo={bar && baz} />');
378
379 const expected = 'baz';
380 const actual = getPropValue(prop);
381
382 assert.equal(actual, expected);
383 });
384
385 it('should return undefined when evaluating `undefined && undefined` ', () => {
386 const prop = extractProp('<div foo={undefined && undefined} />');
387
388 const expected = undefined;
389 const actual = getPropValue(prop);
390
391 assert.equal(actual, expected);
392 });
393
394 it('should correctly infer result of || logical expression based on derived values', () => {
395 const prop = extractProp('<div foo={bar || baz} />');
396
397 const expected = 'bar';
398 const actual = getPropValue(prop);
399
400 assert.equal(actual, expected);
401 });
402
403 it('should correctly infer result of || logical expression based on derived values', () => {
404 const prop = extractProp('<div foo={undefined || baz} />');
405
406 const expected = 'baz';
407 const actual = getPropValue(prop);
408
409 assert.equal(actual, expected);
410 });
411
412 it('should return undefined when evaluating `undefined || undefined` ', () => {
413 const prop = extractProp('<div foo={undefined || undefined} />');
414
415 const expected = undefined;
416 const actual = getPropValue(prop);
417
418 assert.equal(actual, expected);
419 });
420
421 it('should correctly infer result of ?? logical expression based on derived values', () => {
422 const runTest = () => {
423 const prop = extractProp('<div foo={bar ?? baz} />');
424
425 const expected = 'bar';
426 const actual = getPropValue(prop);
427
428 assert.equal(actual, expected);
429 };
430
431 if (fallbackToBabylon) {
432 // eslint-disable-next-line no-undef
433 expect(runTest).toThrow();
434 } else {
435 runTest();
436 }
437 });
438
439 it('should correctly infer result of ?? logical expression based on derived values', () => {
440 const runTest = () => {
441 const prop = extractProp('<div foo={undefined ?? baz} />');
442
443 const expected = 'baz';
444 const actual = getPropValue(prop);
445
446 assert.equal(actual, expected);
447 };
448
449 if (fallbackToBabylon) {
450 // eslint-disable-next-line no-undef
451 expect(runTest).toThrow();
452 } else {
453 runTest();
454 }
455 });
456
457 it('should return undefined when evaluating `undefined ?? undefined` ', () => {
458 const runTest = () => {
459 const prop = extractProp('<div foo={undefined ?? undefined} />');
460
461 const expected = undefined;
462 const actual = getPropValue(prop);
463
464 assert.equal(actual, expected);
465 };
466
467 if (fallbackToBabylon) {
468 // eslint-disable-next-line no-undef
469 expect(runTest).toThrow();
470 } else {
471 runTest();
472 }
473 });
474
475 it('should return undefined when evaluating `null ?? undefined` ', () => {
476 const runTest = () => {
477 const prop = extractProp('<div foo={null ?? undefined} />');
478
479 const expected = undefined;
480 const actual = getPropValue(prop);
481
482 assert.equal(actual, expected);
483 };
484
485 if (fallbackToBabylon) {
486 // eslint-disable-next-line no-undef
487 expect(runTest).toThrow();
488 } else {
489 runTest();
490 }
491 });
492
493 it('should return undefined when evaluating `undefined ?? null` ', () => {
494 const runTest = () => {
495 const prop = extractProp('<div foo={undefined ?? null} />');
496
497 const expected = null;
498 const actual = getPropValue(prop);
499
500 assert.equal(actual, expected);
501 };
502
503 if (fallbackToBabylon) {
504 // eslint-disable-next-line no-undef
505 expect(runTest).toThrow();
506 } else {
507 runTest();
508 }
509 });
510
511 it('should return null when evaluating `null ?? null` ', () => {
512 const runTest = () => {
513 const prop = extractProp('<div foo={null ?? null} />');
514
515 const expected = null;
516 const actual = getPropValue(prop);
517
518 assert.equal(actual, expected);
519 };
520
521 if (fallbackToBabylon) {
522 // eslint-disable-next-line no-undef
523 expect(runTest).toThrow();
524 } else {
525 runTest();
526 }
527 });
528 });
529
530 describe('Member expression', () => {
531 it('should return string representation of form `object.property`', () => {
532 const prop = extractProp('<div foo={bar.baz} />');
533
534 const expected = 'bar.baz';
535 const actual = getPropValue(prop);
536
537 assert.equal(actual, expected);
538 });
539
540 it('should evaluate to a correct representation of member expression with a nullable member', () => {
541 const runTest = () => {
542 const prop = extractProp('<div foo={bar?.baz} />');
543
544 const expected = 'bar?.baz';
545 const actual = getPropValue(prop);
546
547 assert.equal(actual, expected);
548 };
549
550 if (fallbackToBabylon) {
551 // eslint-disable-next-line no-undef
552 expect(runTest).toThrow();
553 } else {
554 runTest();
555 }
556 });
557
558 it('should evaluate to a correct representation of optional call expression', () => {
559 const runTest = () => {
560 const prop = extractProp('<div foo={bar.baz?.(quux)} />');
561
562 const expected = 'bar.baz?.(quux)';
563 const actual = getPropValue(prop);
564
565 assert.equal(actual, expected);
566 };
567
568 if (fallbackToBabylon) {
569 // eslint-disable-next-line no-undef
570 expect(runTest).toThrow();
571 } else {
572 runTest();
573 }
574 });
575 });
576
577 describe('Call expression', () => {
578 it('should return string representation of callee', () => {
579 const prop = extractProp('<div foo={bar()} />');
580
581 const expected = 'bar()';
582 const actual = getPropValue(prop);
583
584 assert.equal(actual, expected);
585 });
586
587 it('should return string representation of callee', () => {
588 const prop = extractProp('<div foo={bar.call()} />');
589
590 const expected = 'bar.call()';
591 const actual = getPropValue(prop);
592
593 assert.equal(actual, expected);
594 });
595 });
596
597 describe('Unary expression', () => {
598 it('should correctly evaluate an expression that prefixes with -', () => {
599 const prop = extractProp('<div foo={-bar} />');
600
601 // -"bar" => NaN
602 const expected = true;
603 const actual = Number.isNaN(getPropValue(prop));
604
605 assert.equal(actual, expected);
606 });
607
608 it('should correctly evaluate an expression that prefixes with -', () => {
609 const prop = extractProp('<div foo={-42} />');
610
611 const expected = -42;
612 const actual = getPropValue(prop);
613
614 assert.equal(actual, expected);
615 });
616
617 it('should correctly evaluate an expression that prefixes with +', () => {
618 const prop = extractProp('<div foo={+bar} />');
619
620 // +"bar" => NaN
621 const expected = true;
622 const actual = Number.isNaN(getPropValue(prop));
623
624 assert.equal(actual, expected);
625 });
626
627 it('should correctly evaluate an expression that prefixes with +', () => {
628 const prop = extractProp('<div foo={+42} />');
629
630 const expected = 42;
631 const actual = getPropValue(prop);
632
633 assert.equal(actual, expected);
634 });
635
636 it('should correctly evaluate an expression that prefixes with !', () => {
637 const prop = extractProp('<div foo={!bar} />');
638
639 const expected = false; // !"bar" === false
640 const actual = getPropValue(prop);
641
642 assert.equal(actual, expected);
643 });
644
645 it('should correctly evaluate an expression that prefixes with ~', () => {
646 const prop = extractProp('<div foo={~bar} />');
647
648 const expected = -1; // ~"bar" === -1
649 const actual = getPropValue(prop);
650
651 assert.equal(actual, expected);
652 });
653
654 it('should return true when evaluating `delete foo`', () => {
655 const prop = extractProp('<div foo={delete x} />');
656
657 const expected = true;
658 const actual = getPropValue(prop);
659
660 assert.equal(actual, expected);
661 });
662
663 it('should return undefined when evaluating `void foo`', () => {
664 const prop = extractProp('<div foo={void x} />');
665
666 const expected = undefined;
667 const actual = getPropValue(prop);
668
669 assert.equal(actual, expected);
670 });
671
672 // TODO: We should fix this to check to see if we can evaluate it.
673 it('should return undefined when evaluating `typeof foo`', () => {
674 const prop = extractProp('<div foo={typeof x} />');
675
676 const expected = undefined;
677 const actual = getPropValue(prop);
678
679 assert.equal(actual, expected);
680 });
681 });
682
683 describe('Update expression', () => {
684 it('should correctly evaluate an expression that prefixes with ++', () => {
685 const prop = extractProp('<div foo={++bar} />');
686
687 // ++"bar" => NaN
688 const expected = true;
689 const actual = Number.isNaN(getPropValue(prop));
690
691 assert.equal(actual, expected);
692 });
693
694 it('should correctly evaluate an expression that prefixes with --', () => {
695 const prop = extractProp('<div foo={--bar} />');
696
697 const expected = true;
698 const actual = Number.isNaN(getPropValue(prop));
699
700 assert.equal(actual, expected);
701 });
702
703 it('should correctly evaluate an expression that suffixes with ++', () => {
704 const prop = extractProp('<div foo={bar++} />');
705
706 // "bar"++ => NaN
707 const expected = true;
708 const actual = Number.isNaN(getPropValue(prop));
709
710 assert.equal(actual, expected);
711 });
712
713 it('should correctly evaluate an expression that suffixes with --', () => {
714 const prop = extractProp('<div foo={bar--} />');
715
716 const expected = true;
717 const actual = Number.isNaN(getPropValue(prop));
718
719 assert.equal(actual, expected);
720 });
721 });
722
723 describe('This expression', () => {
724 it('should return string value `this`', () => {
725 const prop = extractProp('<div foo={this} />');
726
727 const expected = 'this';
728 const actual = getPropValue(prop);
729
730 assert.equal(actual, expected);
731 });
732 });
733
734 describe('Conditional expression', () => {
735 it('should evaluate the conditional based on the derived values correctly', () => {
736 const prop = extractProp('<div foo={bar ? baz : bam} />');
737
738 const expected = 'baz';
739 const actual = getPropValue(prop);
740
741 assert.equal(actual, expected);
742 });
743
744 it('should evaluate the conditional based on the derived values correctly', () => {
745 const prop = extractProp('<div foo={undefined ? baz : bam} />');
746
747 const expected = 'bam';
748 const actual = getPropValue(prop);
749
750 assert.equal(actual, expected);
751 });
752
753 it('should evaluate the conditional based on the derived values correctly', () => {
754 const prop = extractProp('<div foo={(1 > 2) ? baz : bam} />');
755
756 const expected = 'bam';
757 const actual = getPropValue(prop);
758
759 assert.equal(actual, expected);
760 });
761 });
762
763 describe('Binary expression', () => {
764 it('should evaluate the `==` operator correctly', () => {
765 const trueProp = extractProp('<div foo={1 == "1"} />');
766 const falseProp = extractProp('<div foo={1 == bar} />');
767
768 const trueVal = getPropValue(trueProp);
769 const falseVal = getPropValue(falseProp);
770
771 assert.equal(true, trueVal);
772 assert.equal(false, falseVal);
773 });
774
775 it('should evaluate the `!=` operator correctly', () => {
776 const trueProp = extractProp('<div foo={1 != "2"} />');
777 const falseProp = extractProp('<div foo={1 != "1"} />');
778
779 const trueVal = getPropValue(trueProp);
780 const falseVal = getPropValue(falseProp);
781
782 assert.equal(true, trueVal);
783 assert.equal(false, falseVal);
784 });
785
786 it('should evaluate the `===` operator correctly', () => {
787 const trueProp = extractProp('<div foo={1 === 1} />');
788 const falseProp = extractProp('<div foo={1 === "1"} />');
789
790 const trueVal = getPropValue(trueProp);
791 const falseVal = getPropValue(falseProp);
792
793 assert.equal(true, trueVal);
794 assert.equal(false, falseVal);
795 });
796
797 it('should evaluate the `!==` operator correctly', () => {
798 const trueProp = extractProp('<div foo={1 !== "1"} />');
799 const falseProp = extractProp('<div foo={1 !== 1} />');
800
801 const trueVal = getPropValue(trueProp);
802 const falseVal = getPropValue(falseProp);
803
804 assert.equal(true, trueVal);
805 assert.equal(false, falseVal);
806 });
807
808 it('should evaluate the `<` operator correctly', () => {
809 const trueProp = extractProp('<div foo={1 < 2} />');
810 const falseProp = extractProp('<div foo={1 < 0} />');
811
812 const trueVal = getPropValue(trueProp);
813 const falseVal = getPropValue(falseProp);
814
815 assert.equal(true, trueVal);
816 assert.equal(false, falseVal);
817 });
818
819 it('should evaluate the `>` operator correctly', () => {
820 const trueProp = extractProp('<div foo={1 > 0} />');
821 const falseProp = extractProp('<div foo={1 > 2} />');
822
823 const trueVal = getPropValue(trueProp);
824 const falseVal = getPropValue(falseProp);
825
826 assert.equal(true, trueVal);
827 assert.equal(false, falseVal);
828 });
829
830 it('should evaluate the `<=` operator correctly', () => {
831 const trueProp = extractProp('<div foo={1 <= 1} />');
832 const falseProp = extractProp('<div foo={1 <= 0} />');
833
834 const trueVal = getPropValue(trueProp);
835 const falseVal = getPropValue(falseProp);
836
837 assert.equal(true, trueVal);
838 assert.equal(false, falseVal);
839 });
840
841 it('should evaluate the `>=` operator correctly', () => {
842 const trueProp = extractProp('<div foo={1 >= 1} />');
843 const falseProp = extractProp('<div foo={1 >= 2} />');
844
845 const trueVal = getPropValue(trueProp);
846 const falseVal = getPropValue(falseProp);
847
848 assert.equal(true, trueVal);
849 assert.equal(false, falseVal);
850 });
851
852 it('should evaluate the `<<` operator correctly', () => {
853 const prop = extractProp('<div foo={1 << 2} />');
854
855 const expected = 4;
856 const actual = getPropValue(prop);
857
858 assert.equal(actual, expected);
859 });
860
861 it('should evaluate the `>>` operator correctly', () => {
862 const prop = extractProp('<div foo={1 >> 2} />');
863
864 const expected = 0;
865 const actual = getPropValue(prop);
866
867 assert.equal(actual, expected);
868 });
869
870 it('should evaluate the `>>>` operator correctly', () => {
871 const prop = extractProp('<div foo={2 >>> 1} />');
872
873 const expected = 1;
874 const actual = getPropValue(prop);
875
876 assert.equal(actual, expected);
877 });
878
879 it('should evaluate the `+` operator correctly', () => {
880 const prop = extractProp('<div foo={1 + 1} />');
881
882 const expected = 2;
883 const actual = getPropValue(prop);
884
885 assert.equal(actual, expected);
886 });
887
888 it('should evaluate the `-` operator correctly', () => {
889 const prop = extractProp('<div foo={1 - 1} />');
890
891 const expected = 0;
892 const actual = getPropValue(prop);
893
894 assert.equal(actual, expected);
895 });
896
897 it('should evaluate the `*` operator correctly', () => {
898 const prop = extractProp('<div foo={10 * 10} />');
899
900 const expected = 100;
901 const actual = getPropValue(prop);
902
903 assert.equal(actual, expected);
904 });
905
906 it('should evaluate the `/` operator correctly', () => {
907 const prop = extractProp('<div foo={10 / 2} />');
908
909 const expected = 5;
910 const actual = getPropValue(prop);
911
912 assert.equal(actual, expected);
913 });
914
915 it('should evaluate the `%` operator correctly', () => {
916 const prop = extractProp('<div foo={10 % 3} />');
917
918 const expected = 1;
919 const actual = getPropValue(prop);
920
921 assert.equal(actual, expected);
922 });
923
924 it('should evaluate the `|` operator correctly', () => {
925 const prop = extractProp('<div foo={10 | 1} />');
926
927 const expected = 11;
928 const actual = getPropValue(prop);
929
930 assert.equal(actual, expected);
931 });
932
933 it('should evaluate the `^` operator correctly', () => {
934 const prop = extractProp('<div foo={10 ^ 1} />');
935
936 const expected = 11;
937 const actual = getPropValue(prop);
938
939 assert.equal(actual, expected);
940 });
941
942 it('should evaluate the `&` operator correctly', () => {
943 const prop = extractProp('<div foo={10 & 1} />');
944
945 const expected = 0;
946 const actual = getPropValue(prop);
947
948 assert.equal(actual, expected);
949 });
950
951 it('should evaluate the `in` operator correctly', () => {
952 const prop = extractProp('<div foo={foo in bar} />');
953
954 const expected = false;
955 const actual = getPropValue(prop);
956
957 assert.equal(actual, expected);
958 });
959
960 it('should evaluate the `instanceof` operator correctly', () => {
961 const prop = extractProp('<div foo={{} instanceof Object} />');
962
963 const expected = true;
964 const actual = getPropValue(prop);
965
966 assert.equal(actual, expected);
967 });
968
969 it('should evaluate the `instanceof` operator when right side is not a function', () => {
970 const prop = extractProp('<div foo={"bar" instanceof Baz} />');
971
972 const expected = false;
973 const actual = getPropValue(prop);
974
975 assert.equal(actual, expected);
976 });
977 });
978
979 describe('Object expression', () => {
980 it('should evaluate to a correct representation of the object in props', () => {
981 const prop = extractProp('<div foo={ { bar: "baz" } } />');
982
983 const expected = { bar: 'baz' };
984 const actual = getPropValue(prop);
985
986 assert.deepEqual(actual, expected);
987 });
988
989 it('should evaluate to a correct representation of the object, ignore spread properties', () => {
990 const prop = extractProp('<div foo={{bar: "baz", ...{baz: "bar", foo: {...{bar: "meh"}}}}} />');
991
992 const expected = { bar: 'baz', baz: 'bar', foo: { bar: 'meh' } };
993 const actual = getPropValue(prop);
994
995 assert.deepEqual(actual, expected);
996 });
997
998 it('should evaluate to a correct representation of the object, ignore spread properties', () => {
999 const prop = extractProp('<div foo={{ pathname: manageRoute, state: {...data}}} />');
1000
1001 const expected = { pathname: 'manageRoute', state: {} };
1002 const actual = getPropValue(prop);
1003
1004 assert.deepEqual(actual, expected);
1005 });
1006 });
1007
1008 describe('New expression', () => {
1009 it('should return a new empty object', () => {
1010 const prop = extractProp('<div foo={new Bar()} />');
1011
1012 const expected = {};
1013 const actual = getPropValue(prop);
1014
1015 assert.deepEqual(actual, expected);
1016 });
1017 });
1018
1019 describe('Array expression', () => {
1020 it('should evaluate to correct representation of the the array in props', () => {
1021 const prop = extractProp('<div foo={["bar", 42, , null]} />');
1022
1023 const expected = ['bar', 42, undefined, null];
1024 const actual = getPropValue(prop);
1025
1026 assert.deepEqual(actual, expected);
1027 });
1028
1029 it('should evaluate to a correct representation of an array with spread elements', () => {
1030 const prop = extractProp('<div foo={[...this.props.params, bar]} />');
1031
1032 const expected = [undefined, 'bar'];
1033 const actual = getPropValue(prop);
1034
1035 assert.deepEqual(actual, expected);
1036 });
1037 });
1038
1039 it('should return an empty array provided an empty array in props', () => {
1040 const prop = extractProp('<div foo={[]} />');
1041
1042 const expected = [];
1043 const actual = getPropValue(prop);
1044
1045 assert.deepEqual(actual, expected);
1046 });
1047
1048 describe('Bind expression', () => {
1049 it('should return string representation of bind function call when object is null', () => {
1050 const prop = extractProp('<div foo={::this.handleClick} />');
1051
1052 const expected = 'this.handleClick.bind(this)';
1053 const actual = getPropValue(prop);
1054
1055 assert.deepEqual(actual, expected);
1056 });
1057
1058 it('should return string representation of bind function call when object is not null', () => {
1059 const prop = extractProp('<div foo={foo::bar} />');
1060
1061 const expected = 'bar.bind(foo)';
1062 const actual = getPropValue(prop);
1063
1064 assert.deepEqual(actual, expected);
1065 });
1066
1067 it('should return string representation of bind function call when binding to object properties', () => {
1068 const prop = extractProp('<div foo={a.b::c} />');
1069 const otherProp = extractProp('<div foo={::a.b.c} />');
1070
1071 const expected = 'a.b.c.bind(a.b)';
1072 const actual = getPropValue(prop);
1073
1074 const otherExpected = 'a.b.c.bind(a.b)';
1075 const otherActual = getPropValue(otherProp);
1076
1077 assert.deepEqual(actual, expected);
1078 assert.deepEqual(otherExpected, otherActual);
1079 });
1080 });
1081
1082 describe('Type Cast Expression', () => {
1083 it('should throw a parsing error', () => {
1084 let counter = 0;
1085 // eslint-disable-next-line no-console
1086 const warnOrig = console.warn;
1087 // eslint-disable-next-line no-console
1088 console.warn = () => {
1089 counter += 1;
1090 };
1091 // eslint-disable-next-line no-undef
1092 expect(() => {
1093 extractProp('<div foo={(this.handleClick: (event: MouseEvent) => void))} />');
1094 }).toThrow();
1095 assert.equal(counter, 1);
1096 // eslint-disable-next-line no-console
1097 console.warn = warnOrig;
1098 });
1099 });
1100
1101 describe('AssignmentExpression', () => {
1102 it('should recognize and extract assignment', () => {
1103 const prop = extractProp('<div foo={foo = bar} />');
1104
1105 const expected = 'foo = bar';
1106 const actual = getPropValue(prop);
1107
1108 assert.deepEqual(actual, expected);
1109 });
1110
1111 it('should recognize and extract combination assignments', () => {
1112 const prop = extractProp('<div foo={foo += bar} />');
1113
1114 const expected = 'foo += bar';
1115 const actual = getPropValue(prop);
1116
1117 assert.deepEqual(actual, expected);
1118 });
1119 });
1120
1121 describeIfNotBabylon('Typescript', () => {
1122 beforeEach(() => {
1123 changePlugins((pls) => [...pls, 'typescript']);
1124 });
1125
1126 it('should return string representation of variable identifier wrapped in a Typescript non-null assertion', () => {
1127 const prop = extractProp('<div foo={bar!} />');
1128
1129 const expected = 'bar!';
1130 const actual = getPropValue(prop);
1131
1132 assert.equal(actual, expected);
1133 });
1134
1135 it('should return string representation of variable identifier wrapped in a deep Typescript non-null assertion', () => {
1136 const prop = extractProp('<div foo={(bar!)!} />');
1137
1138 const expected = '(bar!)!';
1139 const actual = getPropValue(prop);
1140
1141 assert.equal(actual, expected);
1142 });
1143
1144 it('should return string representation of variable identifier wrapped in a Typescript type coercion', () => {
1145 const prop = extractProp('<div foo={bar as any} />');
1146
1147 const expected = 'bar';
1148 const actual = getPropValue(prop);
1149
1150 assert.equal(actual, expected);
1151 });
1152 });
1153
1154 describeIfNotBabylon('TSNonNullExpression', () => {
1155 beforeEach(() => {
1156 changePlugins((pls) => [...pls, 'typescript']);
1157 });
1158
1159 it('should return string representation of a TSNonNullExpression of form `variable!`', () => {
1160 const prop = extractProp('<div foo={bar!} />');
1161 const expected = 'bar!';
1162 const actual = getPropValue(prop);
1163 assert.equal(actual, expected);
1164 });
1165
1166 it('should return string representation of a TSNonNullExpression of form `object!.property`', () => {
1167 const prop = extractProp('<div foo={bar!.bar} />');
1168 const expected = 'bar!.bar';
1169 const actual = getPropValue(prop);
1170 assert.equal(actual, expected);
1171 });
1172
1173 it('should return string representation of a TSNonNullExpression of form `function()!.property`', () => {
1174 const prop = extractProp('<div foo={bar()!.bar} />');
1175 const expected = 'bar()!.bar';
1176 const actual = getPropValue(prop);
1177 assert.equal(actual, expected);
1178 });
1179
1180 it('should return string representation of a TSNonNullExpression of form `object!.property!`', () => {
1181 const prop = extractProp('<div foo={bar!.bar!} />');
1182 const actual = getPropValue(prop);
1183 const expected = 'bar!.bar!';
1184 assert.equal(actual, expected);
1185 });
1186
1187 it('should return string representation of a TSNonNullExpression of form `object.property!`', () => {
1188 const prop = extractProp('<div foo={bar.bar!} />');
1189 const actual = getPropValue(prop);
1190 const expected = 'bar.bar!';
1191 assert.equal(actual, expected);
1192 });
1193
1194 it('should return string representation of a TSNonNullExpression of form `object.property.property!`', () => {
1195 const prop = extractProp('<div foo={bar.bar.bar!} />');
1196 const actual = getPropValue(prop);
1197 const expected = 'bar.bar.bar!';
1198 assert.equal(actual, expected);
1199 });
1200
1201 it('should return string representation of a TSNonNullExpression of form `object!.property.property!`', () => {
1202 const prop = extractProp('<div foo={bar!.bar.bar!} />');
1203 const actual = getPropValue(prop);
1204 const expected = 'bar!.bar.bar!';
1205 assert.equal(actual, expected);
1206 });
1207
1208 it('should return string representation of an object wrapped in a deep Typescript non-null assertion', () => {
1209 const prop = extractProp('<div foo={(bar!.bar)!} />');
1210 const expected = '(bar!.bar)!';
1211 const actual = getPropValue(prop);
1212 assert.equal(actual, expected);
1213 });
1214
1215 it('should return string representation of a cast wrapped in a deep Typescript non-null assertion', () => {
1216 const prop = extractProp('<div foo={(bar as Bar).baz!} />');
1217 const actual = getPropValue(prop);
1218 const expected = 'bar.baz!';
1219 assert.equal(actual, expected);
1220 });
1221
1222 it('should return string representation of an object wrapped in a deep Typescript non-null assertion', () => {
1223 const prop = extractProp('<div foo={(bar.bar)!} />');
1224 const expected = '(bar.bar)!';
1225 const actual = getPropValue(prop);
1226 assert.equal(actual, expected);
1227 });
1228
1229 it('should return string representation of an object wrapped in a deep Typescript non-null assertion', () => {
1230 const prop = extractProp('<div foo={(bar!.bar.bar!)!} />');
1231 const expected = '(bar!.bar.bar!)!';
1232 const actual = getPropValue(prop);
1233 assert.equal(actual, expected);
1234 });
1235
1236 it('should return string representation of variable identifier wrapped in a deep Typescript non-null assertion', () => {
1237 const prop = extractProp('<div foo={(bar!)!} />');
1238 const expected = '(bar!)!';
1239 const actual = getPropValue(prop);
1240 assert.equal(actual, expected);
1241 });
1242
1243 it('should work with a this.props value', () => {
1244 const prop = extractProp('<a foo={this.props.href!}>Download</a>');
1245 const expected = 'this.props.href!';
1246 const actual = getPropValue(prop);
1247 assert.equal(actual, expected);
1248 });
1249
1250 it('should correctly evaluate a bracketed navigation expression that prefixes with !', () => {
1251 const prop = extractProp('<Link foo={data![0].url} />');
1252
1253 const expected = 'data![0].url';
1254 const actual = getPropValue(prop);
1255
1256 assert.equal(actual, expected);
1257 });
1258
1259 it('works with an optional chain with an `as`', () => {
1260 const prop = extractProp('<img src={images?.footer as string} />', 'src');
1261
1262 const expected = 'images?.footer';
1263 const actual = getPropValue(prop, 'src');
1264
1265 assert.equal(actual, expected);
1266 });
1267 });
1268
1269 describe('JSX empty expression', () => {
1270 it('should work with an empty expression', () => {
1271 const prop = extractProp('<div>\n{/* Hello there */}\n</div>', 'children');
1272 const expected = undefined;
1273 const actual = getPropValue(prop);
1274 assert.equal(actual, expected);
1275 });
1276 });
1277});
Note: See TracBrowser for help on using the repository browser.