govuk_publishing_components 17.10.0 → 17.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ });