govuk_publishing_components 17.10.0 → 17.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/components/feedback.js +21 -0
  3. data/app/assets/stylesheets/govuk_publishing_components/components/_translation-nav.scss +10 -10
  4. data/app/views/govuk_publishing_components/components/_feedback.html.erb +1 -1
  5. data/app/views/govuk_publishing_components/components/docs/accordion.yml +2 -1
  6. data/app/views/govuk_publishing_components/components/docs/layout_footer.yml +1 -1
  7. data/app/views/govuk_publishing_components/components/docs/layout_for_admin.yml +3 -16
  8. data/app/views/govuk_publishing_components/components/docs/layout_header.yml +1 -1
  9. data/app/views/govuk_publishing_components/components/docs/modal_dialogue.yml +2 -2
  10. data/app/views/govuk_publishing_components/components/docs/skip_link.yml +1 -1
  11. data/app/views/govuk_publishing_components/components/docs/tabs.yml +1 -2
  12. data/app/views/govuk_publishing_components/components/feedback/_survey_signup_form.html.erb +2 -5
  13. data/lib/govuk_publishing_components/version.rb +1 -1
  14. data/node_modules/accessible-autocomplete/package.json +1 -1
  15. data/node_modules/graceful-fs/package.json +15 -15
  16. data/node_modules/graceful-fs/polyfills.js +16 -9
  17. data/node_modules/jsx-ast-utils/CHANGELOG.md +4 -0
  18. data/node_modules/jsx-ast-utils/__tests__/helper.js +41 -3
  19. data/node_modules/jsx-ast-utils/__tests__/src/elementType-test.js +4 -1
  20. data/node_modules/jsx-ast-utils/__tests__/src/getProp-test.js +4 -1
  21. data/node_modules/jsx-ast-utils/__tests__/src/{getPropLiteralValue-test.js → getPropLiteralValue-babelparser-test.js} +23 -5
  22. data/node_modules/jsx-ast-utils/__tests__/src/getPropLiteralValue-flowparser-test.js +522 -0
  23. data/node_modules/jsx-ast-utils/__tests__/src/{getPropValue-test.js → getPropValue-babelparser-test.js} +38 -5
  24. data/node_modules/jsx-ast-utils/__tests__/src/getPropValue-flowparser-test.js +938 -0
  25. data/node_modules/jsx-ast-utils/__tests__/src/hasProp-test.js +4 -1
  26. data/node_modules/jsx-ast-utils/__tests__/src/propName-test.js +4 -1
  27. data/node_modules/jsx-ast-utils/lib/values/expressions/TypeCastExpression.js +19 -0
  28. data/node_modules/jsx-ast-utils/lib/values/expressions/index.js +8 -2
  29. data/node_modules/jsx-ast-utils/package.json +17 -14
  30. data/node_modules/jsx-ast-utils/src/values/expressions/TypeCastExpression.js +13 -0
  31. data/node_modules/jsx-ast-utils/src/values/expressions/index.js +3 -0
  32. data/node_modules/pkg-conf/package.json +1 -1
  33. metadata +8 -4
@@ -6,10 +6,14 @@ import {
6
6
  changePlugins,
7
7
  fallbackToBabylon,
8
8
  describeIfNotBabylon,
9
+ setParserName,
9
10
  } from '../helper';
10
11
  import getPropValue from '../../src/getPropValue';
11
12
 
12
13
  describe('getPropValue', () => {
14
+ beforeEach(() => {
15
+ setParserName('babel');
16
+ });
13
17
  it('should export a function', () => {
14
18
  const expected = 'function';
15
19
  const actual = typeof getPropValue;
@@ -24,19 +28,29 @@ describe('getPropValue', () => {
24
28
  assert.equal(expected, actual);
25
29
  });
26
30
 
27
- it('should throw error when trying to get value from unknown node type', () => {
31
+ it('should not throw error when trying to get value from unknown node type', () => {
28
32
  const prop = {
29
33
  type: 'JSXAttribute',
30
34
  value: {
31
35
  type: 'JSXExpressionContainer',
32
36
  },
33
37
  };
34
-
38
+ let counter = 0;
39
+ // eslint-disable-next-line no-console
40
+ const errorOrig = console.error;
41
+ // eslint-disable-next-line no-console
42
+ console.error = () => {
43
+ counter += 1;
44
+ };
45
+ let value;
35
46
  assert.doesNotThrow(() => {
36
- getPropValue(prop);
47
+ value = getPropValue(prop);
37
48
  }, Error);
38
49
 
39
- assert.equal(null, getPropValue(prop));
50
+ assert.equal(null, value);
51
+ assert.equal(counter, 1);
52
+ // eslint-disable-next-line no-console
53
+ console.error = errorOrig;
40
54
  });
41
55
 
42
56
  describe('Null', () => {
@@ -99,7 +113,7 @@ describe('getPropValue', () => {
99
113
 
100
114
  describe('JSXElement', () => {
101
115
  it('should return correct representation of JSX element as a string', () => {
102
- const prop = extractProp('<div foo=<bar /> />');
116
+ const prop = extractProp('<div foo={<bar />} />');
103
117
 
104
118
  const expected = '<bar />';
105
119
  const actual = getPropValue(prop);
@@ -887,6 +901,25 @@ describe('getPropValue', () => {
887
901
  });
888
902
  });
889
903
 
904
+ describe('Type Cast Expression', () => {
905
+ it('should throw a parsing error', () => {
906
+ let counter = 0;
907
+ // eslint-disable-next-line no-console
908
+ const warnOrig = console.warn;
909
+ // eslint-disable-next-line no-console
910
+ console.warn = () => {
911
+ counter += 1;
912
+ };
913
+ // eslint-disable-next-line no-undef
914
+ expect(() => {
915
+ extractProp('<div foo={(this.handleClick: (event: MouseEvent) => void))} />');
916
+ }).toThrow();
917
+ assert.equal(counter, 1);
918
+ // eslint-disable-next-line no-console
919
+ console.warn = warnOrig;
920
+ });
921
+ });
922
+
890
923
  describeIfNotBabylon('Typescript', () => {
891
924
  beforeEach(() => {
892
925
  changePlugins(pls => [...pls, 'typescript']);
@@ -0,0 +1,938 @@
1
+ /* eslint-env mocha */
2
+ /* eslint no-template-curly-in-string: 0 */
3
+ import assert from 'assert';
4
+ import {
5
+ extractProp,
6
+ changePlugins,
7
+ describeIfNotBabylon,
8
+ setParserName,
9
+ } from '../helper';
10
+ import getPropValue from '../../src/getPropValue';
11
+
12
+ describe('getPropValue', () => {
13
+ beforeEach(() => {
14
+ setParserName('flow');
15
+ });
16
+ it('should export a function', () => {
17
+ const expected = 'function';
18
+ const actual = typeof getPropValue;
19
+
20
+ assert.equal(expected, actual);
21
+ });
22
+
23
+ it('should return undefined when not provided with a JSXAttribute', () => {
24
+ const expected = undefined;
25
+ const actual = getPropValue(1);
26
+
27
+ assert.equal(expected, actual);
28
+ });
29
+
30
+ it('should throw not error when trying to get value from unknown node type', () => {
31
+ const prop = {
32
+ type: 'JSXAttribute',
33
+ value: {
34
+ type: 'JSXExpressionContainer',
35
+ },
36
+ };
37
+ let counter = 0;
38
+ // eslint-disable-next-line no-console
39
+ const errorOrig = console.error;
40
+ // eslint-disable-next-line no-console
41
+ console.error = () => {
42
+ counter += 1;
43
+ };
44
+ let value;
45
+ assert.doesNotThrow(() => {
46
+ value = getPropValue(prop);
47
+ }, Error);
48
+
49
+ assert.equal(null, value);
50
+ assert.equal(counter, 1);
51
+ // eslint-disable-next-line no-console
52
+ console.error = errorOrig;
53
+ });
54
+
55
+ describe('Null', () => {
56
+ it('should return true when no value is given', () => {
57
+ const prop = extractProp('<div foo />');
58
+
59
+ const expected = true;
60
+ const actual = getPropValue(prop);
61
+
62
+ assert.equal(expected, actual);
63
+ });
64
+ });
65
+
66
+ describe('Literal', () => {
67
+ it('should return correct string if value is a string', () => {
68
+ const prop = extractProp('<div foo="bar" />');
69
+
70
+ const expected = 'bar';
71
+ const actual = getPropValue(prop);
72
+
73
+ assert.equal(expected, actual);
74
+ });
75
+
76
+ it('should return correct string if value is a string expression', () => {
77
+ const prop = extractProp('<div foo={"bar"} />');
78
+
79
+ const expected = 'bar';
80
+ const actual = getPropValue(prop);
81
+
82
+ assert.equal(expected, actual);
83
+ });
84
+
85
+ it('should return correct integer if value is a integer expression', () => {
86
+ const prop = extractProp('<div foo={1} />');
87
+
88
+ const expected = 1;
89
+ const actual = getPropValue(prop);
90
+
91
+ assert.equal(expected, actual);
92
+ });
93
+
94
+ it('should convert "true" to boolean type', () => {
95
+ const prop = extractProp('<div foo="true" />');
96
+
97
+ const expected = true;
98
+ const actual = getPropValue(prop);
99
+
100
+ assert.equal(expected, actual);
101
+ });
102
+
103
+ it('should convert "false" to boolean type', () => {
104
+ const prop = extractProp('<div foo="false" />');
105
+
106
+ const expected = false;
107
+ const actual = getPropValue(prop);
108
+
109
+ assert.equal(expected, actual);
110
+ });
111
+ });
112
+
113
+ describe('JSXElement', () => {
114
+ it('should return correct representation of JSX element as a string', () => {
115
+ const prop = extractProp('<div foo={<bar />} />');
116
+
117
+ const expected = '<bar />';
118
+ const actual = getPropValue(prop);
119
+
120
+ assert.equal(expected, actual);
121
+ });
122
+ });
123
+
124
+ describe('Identifier', () => {
125
+ it('should return string representation of variable identifier', () => {
126
+ const prop = extractProp('<div foo={bar} />');
127
+
128
+ const expected = 'bar';
129
+ const actual = getPropValue(prop);
130
+
131
+ assert.equal(expected, actual);
132
+ });
133
+
134
+ it('should return undefined when identifier is literally `undefined`', () => {
135
+ const prop = extractProp('<div foo={undefined} />');
136
+
137
+ const expected = undefined;
138
+ const actual = getPropValue(prop);
139
+
140
+ assert.equal(expected, actual);
141
+ });
142
+
143
+ it('should return String object when using a reserved JavaScript object', () => {
144
+ const prop = extractProp('<div foo={String} />');
145
+
146
+ const expected = String;
147
+ const actual = getPropValue(prop);
148
+
149
+ assert.equal(expected, actual);
150
+ });
151
+
152
+ it('should return Array object when using a reserved JavaScript object', () => {
153
+ const prop = extractProp('<div foo={Array} />');
154
+
155
+ const expected = Array;
156
+ const actual = getPropValue(prop);
157
+
158
+ assert.equal(expected, actual);
159
+ });
160
+
161
+ it('should return Date object when using a reserved JavaScript object', () => {
162
+ const prop = extractProp('<div foo={Date} />');
163
+
164
+ const expected = Date;
165
+ const actual = getPropValue(prop);
166
+
167
+ assert.equal(expected, actual);
168
+ });
169
+
170
+ it('should return Infinity object when using a reserved JavaScript object', () => {
171
+ const prop = extractProp('<div foo={Infinity} />');
172
+
173
+ const expected = Infinity;
174
+ const actual = getPropValue(prop);
175
+
176
+ assert.equal(expected, actual);
177
+ });
178
+
179
+ it('should return Math object when using a reserved JavaScript object', () => {
180
+ const prop = extractProp('<div foo={Math} />');
181
+
182
+ const expected = Math;
183
+ const actual = getPropValue(prop);
184
+
185
+ assert.equal(expected, actual);
186
+ });
187
+
188
+ it('should return Number object when using a reserved JavaScript object', () => {
189
+ const prop = extractProp('<div foo={Number} />');
190
+
191
+ const expected = Number;
192
+ const actual = getPropValue(prop);
193
+
194
+ assert.equal(expected, actual);
195
+ });
196
+
197
+ it('should return Object object when using a reserved JavaScript object', () => {
198
+ const prop = extractProp('<div foo={Object} />');
199
+
200
+ const expected = Object;
201
+ const actual = getPropValue(prop);
202
+
203
+ assert.equal(expected, actual);
204
+ });
205
+ });
206
+
207
+ describe('Template literal', () => {
208
+ it('should return template literal with vars wrapped in curly braces', () => {
209
+ const prop = extractProp('<div foo={`bar ${baz}`} />');
210
+
211
+ const expected = 'bar {baz}';
212
+ const actual = getPropValue(prop);
213
+
214
+ assert.equal(expected, actual);
215
+ });
216
+
217
+ it('should return string "undefined" for expressions that evaluate to undefined', () => {
218
+ const prop = extractProp('<div foo={`bar ${undefined}`} />');
219
+
220
+ const expected = 'bar undefined';
221
+ const actual = getPropValue(prop);
222
+
223
+ assert.equal(expected, actual);
224
+ });
225
+
226
+ it('should return template literal with expression type wrapped in curly braces', () => {
227
+ const prop = extractProp('<div foo={`bar ${baz()}`} />');
228
+
229
+ const expected = 'bar {CallExpression}';
230
+ const actual = getPropValue(prop);
231
+
232
+ assert.equal(expected, actual);
233
+ });
234
+
235
+ it('should ignore non-expressions in the template literal', () => {
236
+ const prop = extractProp('<div foo={`bar ${<baz />}`} />');
237
+
238
+ const expected = 'bar ';
239
+ const actual = getPropValue(prop);
240
+
241
+ assert.equal(expected, actual);
242
+ });
243
+ });
244
+
245
+ describe('Tagged Template literal', () => {
246
+ it('should return template literal with vars wrapped in curly braces', () => {
247
+ const prop = extractProp('<div foo={noop`bar ${baz}`} />');
248
+
249
+ const expected = 'bar {baz}';
250
+ const actual = getPropValue(prop);
251
+
252
+ assert.equal(expected, actual);
253
+ });
254
+
255
+ it('should return string "undefined" for expressions that evaluate to undefined', () => {
256
+ const prop = extractProp('<div foo={noop`bar ${undefined}`} />');
257
+
258
+ const expected = 'bar undefined';
259
+ const actual = getPropValue(prop);
260
+
261
+ assert.equal(expected, actual);
262
+ });
263
+
264
+ it('should return template literal with expression type wrapped in curly braces', () => {
265
+ const prop = extractProp('<div foo={noop`bar ${baz()}`} />');
266
+
267
+ const expected = 'bar {CallExpression}';
268
+ const actual = getPropValue(prop);
269
+
270
+ assert.equal(expected, actual);
271
+ });
272
+
273
+ it('should ignore non-expressions in the template literal', () => {
274
+ const prop = extractProp('<div foo={noop`bar ${<baz />}`} />');
275
+
276
+ const expected = 'bar ';
277
+ const actual = getPropValue(prop);
278
+
279
+ assert.equal(expected, actual);
280
+ });
281
+ });
282
+
283
+ describe('Arrow function expression', () => {
284
+ it('should return a function', () => {
285
+ const prop = extractProp('<div foo={ () => { return "bar"; }} />');
286
+
287
+ const expected = 'function';
288
+ const actual = getPropValue(prop);
289
+
290
+ assert.equal(expected, typeof actual);
291
+
292
+ // For code coverage ¯\_(ツ)_/¯
293
+ actual();
294
+ });
295
+ it('should handle ArrowFunctionExpression as conditional consequent', () => {
296
+ const prop = extractProp('<div foo={ (true) ? () => null : () => ({})} />');
297
+
298
+ const expected = 'function';
299
+ const actual = getPropValue(prop);
300
+
301
+ assert.equal(expected, typeof actual);
302
+
303
+ // For code coverage ¯\_(ツ)_/¯
304
+ actual();
305
+ });
306
+ });
307
+
308
+ describe('Function expression', () => {
309
+ it('should return a function', () => {
310
+ const prop = extractProp('<div foo={ function() { return "bar"; } } />');
311
+
312
+ const expected = 'function';
313
+ const actual = getPropValue(prop);
314
+
315
+ assert.equal(expected, typeof actual);
316
+
317
+ // For code coverage ¯\_(ツ)_/¯
318
+ actual();
319
+ });
320
+ });
321
+
322
+ describe('Logical expression', () => {
323
+ it('should correctly infer result of && logical expression based on derived values', () => {
324
+ const prop = extractProp('<div foo={bar && baz} />');
325
+
326
+ const expected = 'baz';
327
+ const actual = getPropValue(prop);
328
+
329
+ assert.equal(expected, actual);
330
+ });
331
+
332
+ it('should return undefined when evaluating `undefined && undefined` ', () => {
333
+ const prop = extractProp('<div foo={undefined && undefined} />');
334
+
335
+ const expected = undefined;
336
+ const actual = getPropValue(prop);
337
+
338
+ assert.equal(expected, actual);
339
+ });
340
+
341
+ it('should correctly infer result of || logical expression based on derived values', () => {
342
+ const prop = extractProp('<div foo={bar || baz} />');
343
+
344
+ const expected = 'bar';
345
+ const actual = getPropValue(prop);
346
+
347
+ assert.equal(expected, actual);
348
+ });
349
+
350
+ it('should correctly infer result of || logical expression based on derived values', () => {
351
+ const prop = extractProp('<div foo={undefined || baz} />');
352
+
353
+ const expected = 'baz';
354
+ const actual = getPropValue(prop);
355
+
356
+ assert.equal(expected, actual);
357
+ });
358
+
359
+ it('should return undefined when evaluating `undefined || undefined` ', () => {
360
+ const prop = extractProp('<div foo={undefined || undefined} />');
361
+
362
+ const expected = undefined;
363
+ const actual = getPropValue(prop);
364
+
365
+ assert.equal(expected, actual);
366
+ });
367
+ });
368
+
369
+ describe('Member expression', () => {
370
+ it('should return string representation of form `object.property`', () => {
371
+ const prop = extractProp('<div foo={bar.baz} />');
372
+
373
+ const expected = 'bar.baz';
374
+ const actual = getPropValue(prop);
375
+
376
+ assert.equal(expected, actual);
377
+ });
378
+
379
+ it('should evaluate to a correct representation of member expression with a nullable member', () => {
380
+ const prop = extractProp('<div foo={bar?.baz} />');
381
+
382
+ const expected = 'bar?.baz';
383
+ const actual = getPropValue(prop);
384
+
385
+ assert.equal(expected, actual);
386
+ });
387
+ });
388
+
389
+ describe('Call expression', () => {
390
+ it('should return string representation of callee', () => {
391
+ const prop = extractProp('<div foo={bar()} />');
392
+
393
+ const expected = 'bar';
394
+ const actual = getPropValue(prop);
395
+
396
+ assert.equal(expected, actual);
397
+ });
398
+
399
+ it('should return string representation of callee', () => {
400
+ const prop = extractProp('<div foo={bar.call()} />');
401
+
402
+ const expected = 'bar.call';
403
+ const actual = getPropValue(prop);
404
+
405
+ assert.equal(expected, actual);
406
+ });
407
+ });
408
+
409
+ describe('Unary expression', () => {
410
+ it('should correctly evaluate an expression that prefixes with -', () => {
411
+ const prop = extractProp('<div foo={-bar} />');
412
+
413
+ // -"bar" => NaN
414
+ const expected = true;
415
+ const actual = Number.isNaN(getPropValue(prop));
416
+
417
+ assert.equal(expected, actual);
418
+ });
419
+
420
+ it('should correctly evaluate an expression that prefixes with -', () => {
421
+ const prop = extractProp('<div foo={-42} />');
422
+
423
+ const expected = -42;
424
+ const actual = getPropValue(prop);
425
+
426
+ assert.equal(expected, actual);
427
+ });
428
+
429
+ it('should correctly evaluate an expression that prefixes with +', () => {
430
+ const prop = extractProp('<div foo={+bar} />');
431
+
432
+ // +"bar" => NaN
433
+ const expected = true;
434
+ const actual = Number.isNaN(getPropValue(prop));
435
+
436
+ assert.equal(expected, actual);
437
+ });
438
+
439
+ it('should correctly evaluate an expression that prefixes with +', () => {
440
+ const prop = extractProp('<div foo={+42} />');
441
+
442
+ const expected = 42;
443
+ const actual = getPropValue(prop);
444
+
445
+ assert.equal(expected, actual);
446
+ });
447
+
448
+ it('should correctly evaluate an expression that prefixes with !', () => {
449
+ const prop = extractProp('<div foo={!bar} />');
450
+
451
+ const expected = false; // !"bar" === false
452
+ const actual = getPropValue(prop);
453
+
454
+ assert.equal(expected, actual);
455
+ });
456
+
457
+ it('should correctly evaluate an expression that prefixes with ~', () => {
458
+ const prop = extractProp('<div foo={~bar} />');
459
+
460
+ const expected = -1; // ~"bar" === -1
461
+ const actual = getPropValue(prop);
462
+
463
+ assert.equal(expected, actual);
464
+ });
465
+
466
+ it('should return true when evaluating `delete foo`', () => {
467
+ const prop = extractProp('<div foo={delete x} />');
468
+
469
+ const expected = true;
470
+ const actual = getPropValue(prop);
471
+
472
+ assert.equal(expected, actual);
473
+ });
474
+
475
+ it('should return undefined when evaluating `void foo`', () => {
476
+ const prop = extractProp('<div foo={void x} />');
477
+
478
+ const expected = undefined;
479
+ const actual = getPropValue(prop);
480
+
481
+ assert.equal(expected, actual);
482
+ });
483
+
484
+ // TODO: We should fix this to check to see if we can evaluate it.
485
+ it('should return undefined when evaluating `typeof foo`', () => {
486
+ const prop = extractProp('<div foo={typeof x} />');
487
+
488
+ const expected = undefined;
489
+ const actual = getPropValue(prop);
490
+
491
+ assert.equal(expected, actual);
492
+ });
493
+ });
494
+
495
+ describe('Update expression', () => {
496
+ it('should correctly evaluate an expression that prefixes with ++', () => {
497
+ const prop = extractProp('<div foo={++bar} />');
498
+
499
+ // ++"bar" => NaN
500
+ const expected = true;
501
+ const actual = Number.isNaN(getPropValue(prop));
502
+
503
+ assert.equal(expected, actual);
504
+ });
505
+
506
+ it('should correctly evaluate an expression that prefixes with --', () => {
507
+ const prop = extractProp('<div foo={--bar} />');
508
+
509
+ const expected = true;
510
+ const actual = Number.isNaN(getPropValue(prop));
511
+
512
+ assert.equal(expected, actual);
513
+ });
514
+
515
+ it('should correctly evaluate an expression that suffixes with ++', () => {
516
+ const prop = extractProp('<div foo={bar++} />');
517
+
518
+ // "bar"++ => NaN
519
+ const expected = true;
520
+ const actual = Number.isNaN(getPropValue(prop));
521
+
522
+ assert.equal(expected, actual);
523
+ });
524
+
525
+ it('should correctly evaluate an expression that suffixes with --', () => {
526
+ const prop = extractProp('<div foo={bar--} />');
527
+
528
+ const expected = true;
529
+ const actual = Number.isNaN(getPropValue(prop));
530
+
531
+ assert.equal(expected, actual);
532
+ });
533
+ });
534
+
535
+ describe('This expression', () => {
536
+ it('should return string value `this`', () => {
537
+ const prop = extractProp('<div foo={this} />');
538
+
539
+ const expected = 'this';
540
+ const actual = getPropValue(prop);
541
+
542
+ assert.equal(expected, actual);
543
+ });
544
+ });
545
+
546
+ describe('Conditional expression', () => {
547
+ it('should evaluate the conditional based on the derived values correctly', () => {
548
+ const prop = extractProp('<div foo={bar ? baz : bam} />');
549
+
550
+ const expected = 'baz';
551
+ const actual = getPropValue(prop);
552
+
553
+ assert.equal(expected, actual);
554
+ });
555
+
556
+ it('should evaluate the conditional based on the derived values correctly', () => {
557
+ const prop = extractProp('<div foo={undefined ? baz : bam} />');
558
+
559
+ const expected = 'bam';
560
+ const actual = getPropValue(prop);
561
+
562
+ assert.equal(expected, actual);
563
+ });
564
+
565
+ it('should evaluate the conditional based on the derived values correctly', () => {
566
+ const prop = extractProp('<div foo={(1 > 2) ? baz : bam} />');
567
+
568
+ const expected = 'bam';
569
+ const actual = getPropValue(prop);
570
+
571
+ assert.equal(expected, actual);
572
+ });
573
+ });
574
+
575
+ describe('Binary expression', () => {
576
+ it('should evaluate the `==` operator correctly', () => {
577
+ const trueProp = extractProp('<div foo={1 == "1"} />');
578
+ const falseProp = extractProp('<div foo={1 == bar} />');
579
+
580
+ const trueVal = getPropValue(trueProp);
581
+ const falseVal = getPropValue(falseProp);
582
+
583
+ assert.equal(true, trueVal);
584
+ assert.equal(false, falseVal);
585
+ });
586
+
587
+ it('should evaluate the `!=` operator correctly', () => {
588
+ const trueProp = extractProp('<div foo={1 != "2"} />');
589
+ const falseProp = extractProp('<div foo={1 != "1"} />');
590
+
591
+ const trueVal = getPropValue(trueProp);
592
+ const falseVal = getPropValue(falseProp);
593
+
594
+ assert.equal(true, trueVal);
595
+ assert.equal(false, falseVal);
596
+ });
597
+
598
+ it('should evaluate the `===` operator correctly', () => {
599
+ const trueProp = extractProp('<div foo={1 === 1} />');
600
+ const falseProp = extractProp('<div foo={1 === "1"} />');
601
+
602
+ const trueVal = getPropValue(trueProp);
603
+ const falseVal = getPropValue(falseProp);
604
+
605
+ assert.equal(true, trueVal);
606
+ assert.equal(false, falseVal);
607
+ });
608
+
609
+ it('should evaluate the `!==` operator correctly', () => {
610
+ const trueProp = extractProp('<div foo={1 !== "1"} />');
611
+ const falseProp = extractProp('<div foo={1 !== 1} />');
612
+
613
+ const trueVal = getPropValue(trueProp);
614
+ const falseVal = getPropValue(falseProp);
615
+
616
+ assert.equal(true, trueVal);
617
+ assert.equal(false, falseVal);
618
+ });
619
+
620
+ it('should evaluate the `<` operator correctly', () => {
621
+ const trueProp = extractProp('<div foo={1 < 2} />');
622
+ const falseProp = extractProp('<div foo={1 < 0} />');
623
+
624
+ const trueVal = getPropValue(trueProp);
625
+ const falseVal = getPropValue(falseProp);
626
+
627
+ assert.equal(true, trueVal);
628
+ assert.equal(false, falseVal);
629
+ });
630
+
631
+ it('should evaluate the `>` operator correctly', () => {
632
+ const trueProp = extractProp('<div foo={1 > 0} />');
633
+ const falseProp = extractProp('<div foo={1 > 2} />');
634
+
635
+ const trueVal = getPropValue(trueProp);
636
+ const falseVal = getPropValue(falseProp);
637
+
638
+ assert.equal(true, trueVal);
639
+ assert.equal(false, falseVal);
640
+ });
641
+
642
+ it('should evaluate the `<=` operator correctly', () => {
643
+ const trueProp = extractProp('<div foo={1 <= 1} />');
644
+ const falseProp = extractProp('<div foo={1 <= 0} />');
645
+
646
+ const trueVal = getPropValue(trueProp);
647
+ const falseVal = getPropValue(falseProp);
648
+
649
+ assert.equal(true, trueVal);
650
+ assert.equal(false, falseVal);
651
+ });
652
+
653
+ it('should evaluate the `>=` operator correctly', () => {
654
+ const trueProp = extractProp('<div foo={1 >= 1} />');
655
+ const falseProp = extractProp('<div foo={1 >= 2} />');
656
+
657
+ const trueVal = getPropValue(trueProp);
658
+ const falseVal = getPropValue(falseProp);
659
+
660
+ assert.equal(true, trueVal);
661
+ assert.equal(false, falseVal);
662
+ });
663
+
664
+ it('should evaluate the `<<` operator correctly', () => {
665
+ const prop = extractProp('<div foo={1 << 2} />');
666
+
667
+ const expected = 4;
668
+ const actual = getPropValue(prop);
669
+
670
+ assert.equal(expected, actual);
671
+ });
672
+
673
+ it('should evaluate the `>>` operator correctly', () => {
674
+ const prop = extractProp('<div foo={1 >> 2} />');
675
+
676
+ const expected = 0;
677
+ const actual = getPropValue(prop);
678
+
679
+ assert.equal(expected, actual);
680
+ });
681
+
682
+ it('should evaluate the `>>>` operator correctly', () => {
683
+ const prop = extractProp('<div foo={2 >>> 1} />');
684
+
685
+ const expected = 1;
686
+ const actual = getPropValue(prop);
687
+
688
+ assert.equal(expected, actual);
689
+ });
690
+
691
+ it('should evaluate the `+` operator correctly', () => {
692
+ const prop = extractProp('<div foo={1 + 1} />');
693
+
694
+ const expected = 2;
695
+ const actual = getPropValue(prop);
696
+
697
+ assert.equal(expected, actual);
698
+ });
699
+
700
+ it('should evaluate the `-` operator correctly', () => {
701
+ const prop = extractProp('<div foo={1 - 1} />');
702
+
703
+ const expected = 0;
704
+ const actual = getPropValue(prop);
705
+
706
+ assert.equal(expected, actual);
707
+ });
708
+
709
+ it('should evaluate the `*` operator correctly', () => {
710
+ const prop = extractProp('<div foo={10 * 10} />');
711
+
712
+ const expected = 100;
713
+ const actual = getPropValue(prop);
714
+
715
+ assert.equal(expected, actual);
716
+ });
717
+
718
+ it('should evaluate the `/` operator correctly', () => {
719
+ const prop = extractProp('<div foo={10 / 2} />');
720
+
721
+ const expected = 5;
722
+ const actual = getPropValue(prop);
723
+
724
+ assert.equal(expected, actual);
725
+ });
726
+
727
+ it('should evaluate the `%` operator correctly', () => {
728
+ const prop = extractProp('<div foo={10 % 3} />');
729
+
730
+ const expected = 1;
731
+ const actual = getPropValue(prop);
732
+
733
+ assert.equal(expected, actual);
734
+ });
735
+
736
+ it('should evaluate the `|` operator correctly', () => {
737
+ const prop = extractProp('<div foo={10 | 1} />');
738
+
739
+ const expected = 11;
740
+ const actual = getPropValue(prop);
741
+
742
+ assert.equal(expected, actual);
743
+ });
744
+
745
+ it('should evaluate the `^` operator correctly', () => {
746
+ const prop = extractProp('<div foo={10 ^ 1} />');
747
+
748
+ const expected = 11;
749
+ const actual = getPropValue(prop);
750
+
751
+ assert.equal(expected, actual);
752
+ });
753
+
754
+ it('should evaluate the `&` operator correctly', () => {
755
+ const prop = extractProp('<div foo={10 & 1} />');
756
+
757
+ const expected = 0;
758
+ const actual = getPropValue(prop);
759
+
760
+ assert.equal(expected, actual);
761
+ });
762
+
763
+ it('should evaluate the `in` operator correctly', () => {
764
+ const prop = extractProp('<div foo={foo in bar} />');
765
+
766
+ const expected = false;
767
+ const actual = getPropValue(prop);
768
+
769
+ assert.equal(expected, actual);
770
+ });
771
+
772
+ it('should evaluate the `instanceof` operator correctly', () => {
773
+ const prop = extractProp('<div foo={{} instanceof Object} />');
774
+
775
+ const expected = true;
776
+ const actual = getPropValue(prop);
777
+
778
+ assert.equal(expected, actual);
779
+ });
780
+
781
+ it('should evaluate the `instanceof` operator when right side is not a function', () => {
782
+ const prop = extractProp('<div foo={"bar" instanceof Baz} />');
783
+
784
+ const expected = false;
785
+ const actual = getPropValue(prop);
786
+
787
+ assert.equal(expected, actual);
788
+ });
789
+ });
790
+
791
+ describe('Object expression', () => {
792
+ it('should evaluate to a correct representation of the object in props', () => {
793
+ const prop = extractProp('<div foo={ { bar: "baz" } } />');
794
+
795
+ const expected = { bar: 'baz' };
796
+ const actual = getPropValue(prop);
797
+
798
+ assert.deepEqual(expected, actual);
799
+ });
800
+
801
+ it('should evaluate to a correct representation of the object, ignore spread properties', () => {
802
+ const prop = extractProp('<div foo={{bar: "baz", ...{baz: "bar", foo: {...{bar: "meh"}}}}} />');
803
+
804
+ const expected = { bar: 'baz', baz: 'bar', foo: { bar: 'meh' } };
805
+ const actual = getPropValue(prop);
806
+
807
+ assert.deepEqual(expected, actual);
808
+ });
809
+
810
+ it('should evaluate to a correct representation of the object, ignore spread properties', () => {
811
+ const prop = extractProp('<div foo={{ pathname: manageRoute, state: {...data}}} />');
812
+
813
+ const expected = { pathname: 'manageRoute', state: {} };
814
+ const actual = getPropValue(prop);
815
+
816
+ assert.deepEqual(expected, actual);
817
+ });
818
+ });
819
+
820
+ describe('New expression', () => {
821
+ it('should return a new empty object', () => {
822
+ const prop = extractProp('<div foo={new Bar()} />');
823
+
824
+ const expected = {};
825
+ const actual = getPropValue(prop);
826
+
827
+ assert.deepEqual(expected, actual);
828
+ });
829
+ });
830
+
831
+ describe('Array expression', () => {
832
+ it('should evaluate to correct representation of the the array in props', () => {
833
+ const prop = extractProp('<div foo={["bar", 42, null]} />');
834
+
835
+ const expected = ['bar', 42, null];
836
+ const actual = getPropValue(prop);
837
+
838
+ assert.deepEqual(expected, actual);
839
+ });
840
+
841
+ it('should evaluate to a correct representation of an array with spread elements', () => {
842
+ const prop = extractProp('<div foo={[...this.props.params, bar]} />');
843
+
844
+ const expected = [undefined, 'bar'];
845
+ const actual = getPropValue(prop);
846
+
847
+ assert.deepEqual(expected, actual);
848
+ });
849
+ });
850
+
851
+ it('should return an empty array provided an empty array in props', () => {
852
+ const prop = extractProp('<div foo={[]} />');
853
+
854
+ const expected = [];
855
+ const actual = getPropValue(prop);
856
+
857
+ assert.deepEqual(expected, actual);
858
+ });
859
+
860
+ describe('Bind expression', () => {
861
+ it('should return string representation of bind function call when object is null', () => {
862
+ const prop = extractProp('<div foo={::this.handleClick} />');
863
+
864
+ const expected = null;
865
+ const actual = getPropValue(prop);
866
+
867
+ assert.deepEqual(actual, expected);
868
+ });
869
+
870
+ it('should return string representation of bind function call when object is not null', () => {
871
+ const prop = extractProp('<div foo={foo::bar} />');
872
+
873
+ const expected = 'foo';
874
+ const actual = getPropValue(prop);
875
+
876
+ assert.deepEqual(actual, expected);
877
+ });
878
+
879
+ it('should return string representation of bind function call when binding to object properties', () => {
880
+ const prop = extractProp('<div foo={a.b::c} />');
881
+ const otherProp = extractProp('<div foo={::a.b.c} />');
882
+
883
+ const expected = 'a.b';
884
+ const actual = getPropValue(prop);
885
+
886
+ const otherExpected = null;
887
+ const otherActual = getPropValue(otherProp);
888
+
889
+ assert.deepEqual(actual, expected);
890
+ assert.deepEqual(otherActual, otherExpected);
891
+ });
892
+ });
893
+
894
+ describe('Type Cast Expression', () => {
895
+ it('should return the expression from a type cast', () => {
896
+ const prop = extractProp('<div foo={(this.handleClick: (event: MouseEvent) => void))} />');
897
+
898
+ const expected = 'this.handleClick';
899
+ const actual = getPropValue(prop);
900
+
901
+ assert.deepEqual(expected, actual);
902
+ });
903
+ });
904
+
905
+ describeIfNotBabylon('Typescript', () => {
906
+ beforeEach(() => {
907
+ changePlugins(pls => [...pls, 'typescript']);
908
+ });
909
+
910
+ it('should return string representation of variable identifier wrapped in a Typescript non-null assertion', () => {
911
+ const prop = extractProp('<div foo={bar!} />');
912
+
913
+ const expected = 'bar';
914
+ const actual = getPropValue(prop);
915
+
916
+ assert.equal(expected, actual);
917
+ });
918
+
919
+ it('should return string representation of variable identifier wrapped in a deep Typescript non-null assertion', () => {
920
+ const prop = extractProp('<div foo={(bar!)!} />');
921
+
922
+ const expected = 'bar';
923
+ const actual = getPropValue(prop);
924
+
925
+ assert.equal(expected, actual);
926
+ });
927
+
928
+ it('should return string representation of variable identifier wrapped in a Typescript type coercion', () => {
929
+ changePlugins(pls => [...pls, 'typescript']);
930
+ const prop = extractProp('<div foo={bar as any} />');
931
+
932
+ const expected = 'bar';
933
+ const actual = getPropValue(prop);
934
+
935
+ assert.equal(expected, actual);
936
+ });
937
+ });
938
+ });