Added TreeContext tests
Brian Vaughn committed
May 9, 2019 at 15:52 UTC
427f0f63c1eeba330dc80b6fb3ac2930bc17e7fd
4 files changed
+1151
-10
src/__tests__/__snapshots__/treeContext-test.js.snap
new
+713
@@ -0,0 +1,713 @@
1
+// Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+exports[`TreeListContext owners state should support entering and existing the owners tree view: 0: mount 1`] = `
4
+[root]
5
+ ▾ <Grandparent>
6
+ ▾ <Parent>
7
+ <Child>
8
+ <Child>
9
+`;
10
+
11
+exports[`TreeListContext owners state should support entering and existing the owners tree view: 1: initial state 1`] = `
12
+Object {
13
+ "inspectedElementID": null,
14
+ "numElements": 4,
15
+ "ownerFlatTree": null,
16
+ "ownerID": null,
17
+ "searchIndex": null,
18
+ "searchResults": Array [],
19
+ "searchText": "",
20
+ "selectedElementID": null,
21
+ "selectedElementIndex": null,
22
+}
23
+`;
24
+
25
+exports[`TreeListContext owners state should support entering and existing the owners tree view: 2: parent owners tree 1`] = `
26
+Object {
27
+ "inspectedElementID": 3,
28
+ "numElements": 3,
29
+ "ownerFlatTree": Array [
30
+ Object {
31
+ "children": Array [
32
+ 4,
33
+ 5,
34
+ ],
35
+ "depth": 0,
36
+ "displayName": "Parent",
37
+ "id": 3,
38
+ "isCollapsed": false,
39
+ "key": null,
40
+ "ownerID": 2,
41
+ "parentID": 2,
42
+ "type": 5,
43
+ "weight": 3,
44
+ },
45
+ Object {
46
+ "children": Array [],
47
+ "depth": 1,
48
+ "displayName": "Child",
49
+ "id": 4,
50
+ "isCollapsed": false,
51
+ "key": null,
52
+ "ownerID": 3,
53
+ "parentID": 3,
54
+ "type": 5,
55
+ "weight": 1,
56
+ },
57
+ Object {
58
+ "children": Array [],
59
+ "depth": 1,
60
+ "displayName": "Child",
61
+ "id": 5,
62
+ "isCollapsed": false,
63
+ "key": null,
64
+ "ownerID": 3,
65
+ "parentID": 3,
66
+ "type": 5,
67
+ "weight": 1,
68
+ },
69
+ ],
70
+ "ownerID": 3,
71
+ "searchIndex": null,
72
+ "searchResults": Array [],
73
+ "searchText": "",
74
+ "selectedElementID": 3,
75
+ "selectedElementIndex": 0,
76
+}
77
+`;
78
+
79
+exports[`TreeListContext owners state should support entering and existing the owners tree view: 3: final state 1`] = `
80
+Object {
81
+ "inspectedElementID": 3,
82
+ "numElements": 4,
83
+ "ownerFlatTree": null,
84
+ "ownerID": null,
85
+ "searchIndex": null,
86
+ "searchResults": Array [],
87
+ "searchText": "",
88
+ "selectedElementID": 3,
89
+ "selectedElementIndex": 1,
90
+}
91
+`;
92
+
93
+exports[`TreeListContext search state should add newly mounted elements to the search results set if they match the current text: 0: mount 1`] = `
94
+[root]
95
+ <Foo>
96
+ <Bar>
97
+`;
98
+
99
+exports[`TreeListContext search state should add newly mounted elements to the search results set if they match the current text: 1: initial state 1`] = `
100
+Object {
101
+ "inspectedElementID": null,
102
+ "numElements": 2,
103
+ "ownerFlatTree": null,
104
+ "ownerID": null,
105
+ "searchIndex": null,
106
+ "searchResults": Array [],
107
+ "searchText": "",
108
+ "selectedElementID": null,
109
+ "selectedElementIndex": null,
110
+}
111
+`;
112
+
113
+exports[`TreeListContext search state should add newly mounted elements to the search results set if they match the current text: 2: search for "ba" 1`] = `
114
+Object {
115
+ "inspectedElementID": 3,
116
+ "numElements": 2,
117
+ "ownerFlatTree": null,
118
+ "ownerID": null,
119
+ "searchIndex": 0,
120
+ "searchResults": Array [
121
+ 3,
122
+ ],
123
+ "searchText": "ba",
124
+ "selectedElementID": 3,
125
+ "selectedElementIndex": 1,
126
+}
127
+`;
128
+
129
+exports[`TreeListContext search state should add newly mounted elements to the search results set if they match the current text: 3: mount Baz 1`] = `
130
+Object {
131
+ "inspectedElementID": 3,
132
+ "numElements": 3,
133
+ "ownerFlatTree": null,
134
+ "ownerID": null,
135
+ "searchIndex": 0,
136
+ "searchResults": Array [
137
+ 3,
138
+ 4,
139
+ ],
140
+ "searchText": "ba",
141
+ "selectedElementID": 3,
142
+ "selectedElementIndex": 1,
143
+}
144
+`;
145
+
146
+exports[`TreeListContext search state should find elements matching search text: 0: mount 1`] = `
147
+[root]
148
+ <Foo>
149
+ <Bar>
150
+ <Baz>
151
+`;
152
+
153
+exports[`TreeListContext search state should find elements matching search text: 1: initial state 1`] = `
154
+Object {
155
+ "inspectedElementID": null,
156
+ "numElements": 3,
157
+ "ownerFlatTree": null,
158
+ "ownerID": null,
159
+ "searchIndex": null,
160
+ "searchResults": Array [],
161
+ "searchText": "",
162
+ "selectedElementID": null,
163
+ "selectedElementIndex": null,
164
+}
165
+`;
166
+
167
+exports[`TreeListContext search state should find elements matching search text: 2: search for "ba" 1`] = `
168
+Object {
169
+ "inspectedElementID": 3,
170
+ "numElements": 3,
171
+ "ownerFlatTree": null,
172
+ "ownerID": null,
173
+ "searchIndex": 0,
174
+ "searchResults": Array [
175
+ 3,
176
+ 4,
177
+ ],
178
+ "searchText": "ba",
179
+ "selectedElementID": 3,
180
+ "selectedElementIndex": 1,
181
+}
182
+`;
183
+
184
+exports[`TreeListContext search state should find elements matching search text: 3: search for "f" 1`] = `
185
+Object {
186
+ "inspectedElementID": 2,
187
+ "numElements": 3,
188
+ "ownerFlatTree": null,
189
+ "ownerID": null,
190
+ "searchIndex": 0,
191
+ "searchResults": Array [
192
+ 2,
193
+ ],
194
+ "searchText": "f",
195
+ "selectedElementID": 2,
196
+ "selectedElementIndex": 0,
197
+}
198
+`;
199
+
200
+exports[`TreeListContext search state should find elements matching search text: 4: search for "q" 1`] = `
201
+Object {
202
+ "inspectedElementID": 2,
203
+ "numElements": 3,
204
+ "ownerFlatTree": null,
205
+ "ownerID": null,
206
+ "searchIndex": null,
207
+ "searchResults": Array [],
208
+ "searchText": "q",
209
+ "selectedElementID": 2,
210
+ "selectedElementIndex": 0,
211
+}
212
+`;
213
+
214
+exports[`TreeListContext search state should remove unmounted elements from the search results set: 0: mount 1`] = `
215
+[root]
216
+ <Foo>
217
+ <Bar>
218
+ <Baz>
219
+`;
220
+
221
+exports[`TreeListContext search state should remove unmounted elements from the search results set: 1: initial state 1`] = `
222
+Object {
223
+ "inspectedElementID": null,
224
+ "numElements": 3,
225
+ "ownerFlatTree": null,
226
+ "ownerID": null,
227
+ "searchIndex": null,
228
+ "searchResults": Array [],
229
+ "searchText": "",
230
+ "selectedElementID": null,
231
+ "selectedElementIndex": null,
232
+}
233
+`;
234
+
235
+exports[`TreeListContext search state should remove unmounted elements from the search results set: 2: search for "ba" 1`] = `
236
+Object {
237
+ "inspectedElementID": 3,
238
+ "numElements": 3,
239
+ "ownerFlatTree": null,
240
+ "ownerID": null,
241
+ "searchIndex": 0,
242
+ "searchResults": Array [
243
+ 3,
244
+ 4,
245
+ ],
246
+ "searchText": "ba",
247
+ "selectedElementID": 3,
248
+ "selectedElementIndex": 1,
249
+}
250
+`;
251
+
252
+exports[`TreeListContext search state should remove unmounted elements from the search results set: 3: go to second result 1`] = `
253
+Object {
254
+ "inspectedElementID": 4,
255
+ "numElements": 3,
256
+ "ownerFlatTree": null,
257
+ "ownerID": null,
258
+ "searchIndex": 1,
259
+ "searchResults": Array [
260
+ 3,
261
+ 4,
262
+ ],
263
+ "searchText": "ba",
264
+ "selectedElementID": 4,
265
+ "selectedElementIndex": 2,
266
+}
267
+`;
268
+
269
+exports[`TreeListContext search state should remove unmounted elements from the search results set: 4: unmount Baz 1`] = `
270
+Object {
271
+ "inspectedElementID": null,
272
+ "numElements": 2,
273
+ "ownerFlatTree": null,
274
+ "ownerID": null,
275
+ "searchIndex": 0,
276
+ "searchResults": Array [
277
+ 3,
278
+ ],
279
+ "searchText": "ba",
280
+ "selectedElementID": null,
281
+ "selectedElementIndex": null,
282
+}
283
+`;
284
+
285
+exports[`TreeListContext search state should select the next and previous items within the search results: 0: mount 1`] = `
286
+[root]
287
+ <Foo>
288
+ <Baz>
289
+ <Bar>
290
+ <Baz>
291
+`;
292
+
293
+exports[`TreeListContext search state should select the next and previous items within the search results: 1: initial state 1`] = `
294
+Object {
295
+ "inspectedElementID": null,
296
+ "numElements": 4,
297
+ "ownerFlatTree": null,
298
+ "ownerID": null,
299
+ "searchIndex": null,
300
+ "searchResults": Array [],
301
+ "searchText": "",
302
+ "selectedElementID": null,
303
+ "selectedElementIndex": null,
304
+}
305
+`;
306
+
307
+exports[`TreeListContext search state should select the next and previous items within the search results: 2: search for "ba" 1`] = `
308
+Object {
309
+ "inspectedElementID": 3,
310
+ "numElements": 4,
311
+ "ownerFlatTree": null,
312
+ "ownerID": null,
313
+ "searchIndex": 0,
314
+ "searchResults": Array [
315
+ 3,
316
+ 4,
317
+ 5,
318
+ ],
319
+ "searchText": "ba",
320
+ "selectedElementID": 3,
321
+ "selectedElementIndex": 1,
322
+}
323
+`;
324
+
325
+exports[`TreeListContext search state should select the next and previous items within the search results: 3: go to second result 1`] = `
326
+Object {
327
+ "inspectedElementID": 4,
328
+ "numElements": 4,
329
+ "ownerFlatTree": null,
330
+ "ownerID": null,
331
+ "searchIndex": 1,
332
+ "searchResults": Array [
333
+ 3,
334
+ 4,
335
+ 5,
336
+ ],
337
+ "searchText": "ba",
338
+ "selectedElementID": 4,
339
+ "selectedElementIndex": 2,
340
+}
341
+`;
342
+
343
+exports[`TreeListContext search state should select the next and previous items within the search results: 4: go to third result 1`] = `
344
+Object {
345
+ "inspectedElementID": 5,
346
+ "numElements": 4,
347
+ "ownerFlatTree": null,
348
+ "ownerID": null,
349
+ "searchIndex": 2,
350
+ "searchResults": Array [
351
+ 3,
352
+ 4,
353
+ 5,
354
+ ],
355
+ "searchText": "ba",
356
+ "selectedElementID": 5,
357
+ "selectedElementIndex": 3,
358
+}
359
+`;
360
+
361
+exports[`TreeListContext search state should select the next and previous items within the search results: 5: go to second result 1`] = `
362
+Object {
363
+ "inspectedElementID": 4,
364
+ "numElements": 4,
365
+ "ownerFlatTree": null,
366
+ "ownerID": null,
367
+ "searchIndex": 1,
368
+ "searchResults": Array [
369
+ 3,
370
+ 4,
371
+ 5,
372
+ ],
373
+ "searchText": "ba",
374
+ "selectedElementID": 4,
375
+ "selectedElementIndex": 2,
376
+}
377
+`;
378
+
379
+exports[`TreeListContext search state should select the next and previous items within the search results: 6: go to first result 1`] = `
380
+Object {
381
+ "inspectedElementID": 3,
382
+ "numElements": 4,
383
+ "ownerFlatTree": null,
384
+ "ownerID": null,
385
+ "searchIndex": 0,
386
+ "searchResults": Array [
387
+ 3,
388
+ 4,
389
+ 5,
390
+ ],
391
+ "searchText": "ba",
392
+ "selectedElementID": 3,
393
+ "selectedElementIndex": 1,
394
+}
395
+`;
396
+
397
+exports[`TreeListContext search state should select the next and previous items within the search results: 7: wrap to last result 1`] = `
398
+Object {
399
+ "inspectedElementID": 5,
400
+ "numElements": 4,
401
+ "ownerFlatTree": null,
402
+ "ownerID": null,
403
+ "searchIndex": 2,
404
+ "searchResults": Array [
405
+ 3,
406
+ 4,
407
+ 5,
408
+ ],
409
+ "searchText": "ba",
410
+ "selectedElementID": 5,
411
+ "selectedElementIndex": 3,
412
+}
413
+`;
414
+
415
+exports[`TreeListContext search state should select the next and previous items within the search results: 8: wrap to first result 1`] = `
416
+Object {
417
+ "inspectedElementID": 3,
418
+ "numElements": 4,
419
+ "ownerFlatTree": null,
420
+ "ownerID": null,
421
+ "searchIndex": 0,
422
+ "searchResults": Array [
423
+ 3,
424
+ 4,
425
+ 5,
426
+ ],
427
+ "searchText": "ba",
428
+ "selectedElementID": 3,
429
+ "selectedElementIndex": 1,
430
+}
431
+`;
432
+
433
+exports[`TreeListContext tree state should select child elements: 0: mount 1`] = `
434
+[root]
435
+ ▾ <Grandparent>
436
+ ▾ <Parent>
437
+ <Child>
438
+ <Child>
439
+ ▾ <Parent>
440
+ <Child>
441
+ <Child>
442
+`;
443
+
444
+exports[`TreeListContext tree state should select child elements: 1: initial state 1`] = `
445
+Object {
446
+ "inspectedElementID": null,
447
+ "numElements": 7,
448
+ "ownerFlatTree": null,
449
+ "ownerID": null,
450
+ "searchIndex": null,
451
+ "searchResults": Array [],
452
+ "searchText": "",
453
+ "selectedElementID": null,
454
+ "selectedElementIndex": null,
455
+}
456
+`;
457
+
458
+exports[`TreeListContext tree state should select child elements: 2: select first element 1`] = `
459
+Object {
460
+ "inspectedElementID": 2,
461
+ "numElements": 7,
462
+ "ownerFlatTree": null,
463
+ "ownerID": null,
464
+ "searchIndex": null,
465
+ "searchResults": Array [],
466
+ "searchText": "",
467
+ "selectedElementID": 2,
468
+ "selectedElementIndex": 0,
469
+}
470
+`;
471
+
472
+exports[`TreeListContext tree state should select child elements: 3: select Parent 1`] = `
473
+Object {
474
+ "inspectedElementID": 3,
475
+ "numElements": 7,
476
+ "ownerFlatTree": null,
477
+ "ownerID": null,
478
+ "searchIndex": null,
479
+ "searchResults": Array [],
480
+ "searchText": "",
481
+ "selectedElementID": 3,
482
+ "selectedElementIndex": 1,
483
+}
484
+`;
485
+
486
+exports[`TreeListContext tree state should select child elements: 4: select Child 1`] = `
487
+Object {
488
+ "inspectedElementID": 4,
489
+ "numElements": 7,
490
+ "ownerFlatTree": null,
491
+ "ownerID": null,
492
+ "searchIndex": null,
493
+ "searchResults": Array [],
494
+ "searchText": "",
495
+ "selectedElementID": 4,
496
+ "selectedElementIndex": 2,
497
+}
498
+`;
499
+
500
+exports[`TreeListContext tree state should select parent elements and then collapse: 0: mount 1`] = `
501
+[root]
502
+ ▾ <Grandparent>
503
+ ▾ <Parent>
504
+ <Child>
505
+ <Child>
506
+ ▾ <Parent>
507
+ <Child>
508
+ <Child>
509
+`;
510
+
511
+exports[`TreeListContext tree state should select parent elements and then collapse: 1: initial state 1`] = `
512
+Object {
513
+ "inspectedElementID": null,
514
+ "numElements": 7,
515
+ "ownerFlatTree": null,
516
+ "ownerID": null,
517
+ "searchIndex": null,
518
+ "searchResults": Array [],
519
+ "searchText": "",
520
+ "selectedElementID": null,
521
+ "selectedElementIndex": null,
522
+}
523
+`;
524
+
525
+exports[`TreeListContext tree state should select parent elements and then collapse: 2: select last child 1`] = `
526
+Object {
527
+ "inspectedElementID": 8,
528
+ "numElements": 7,
529
+ "ownerFlatTree": null,
530
+ "ownerID": null,
531
+ "searchIndex": null,
532
+ "searchResults": Array [],
533
+ "searchText": "",
534
+ "selectedElementID": 8,
535
+ "selectedElementIndex": 6,
536
+}
537
+`;
538
+
539
+exports[`TreeListContext tree state should select parent elements and then collapse: 3: select Parent 1`] = `
540
+Object {
541
+ "inspectedElementID": 6,
542
+ "numElements": 7,
543
+ "ownerFlatTree": null,
544
+ "ownerID": null,
545
+ "searchIndex": null,
546
+ "searchResults": Array [],
547
+ "searchText": "",
548
+ "selectedElementID": 6,
549
+ "selectedElementIndex": 4,
550
+}
551
+`;
552
+
553
+exports[`TreeListContext tree state should select parent elements and then collapse: 4: select Grandparent 1`] = `
554
+Object {
555
+ "inspectedElementID": 2,
556
+ "numElements": 7,
557
+ "ownerFlatTree": null,
558
+ "ownerID": null,
559
+ "searchIndex": null,
560
+ "searchResults": Array [],
561
+ "searchText": "",
562
+ "selectedElementID": 2,
563
+ "selectedElementIndex": 0,
564
+}
565
+`;
566
+
567
+exports[`TreeListContext tree state should select the next and previous elements in the tree: 0: mount 1`] = `
568
+[root]
569
+ ▾ <Grandparent>
570
+ ▾ <Parent>
571
+ <Child>
572
+ <Child>
573
+`;
574
+
575
+exports[`TreeListContext tree state should select the next and previous elements in the tree: 1: initial state 1`] = `
576
+Object {
577
+ "inspectedElementID": null,
578
+ "numElements": 4,
579
+ "ownerFlatTree": null,
580
+ "ownerID": null,
581
+ "searchIndex": null,
582
+ "searchResults": Array [],
583
+ "searchText": "",
584
+ "selectedElementID": null,
585
+ "selectedElementIndex": null,
586
+}
587
+`;
588
+
589
+exports[`TreeListContext tree state should select the next and previous elements in the tree: 2: select first element 1`] = `
590
+Object {
591
+ "inspectedElementID": 2,
592
+ "numElements": 4,
593
+ "ownerFlatTree": null,
594
+ "ownerID": null,
595
+ "searchIndex": null,
596
+ "searchResults": Array [],
597
+ "searchText": "",
598
+ "selectedElementID": 2,
599
+ "selectedElementIndex": 0,
600
+}
601
+`;
602
+
603
+exports[`TreeListContext tree state should select the next and previous elements in the tree: 3: select element after (0) 1`] = `
604
+Object {
605
+ "inspectedElementID": 3,
606
+ "numElements": 4,
607
+ "ownerFlatTree": null,
608
+ "ownerID": null,
609
+ "searchIndex": null,
610
+ "searchResults": Array [],
611
+ "searchText": "",
612
+ "selectedElementID": 3,
613
+ "selectedElementIndex": 1,
614
+}
615
+`;
616
+
617
+exports[`TreeListContext tree state should select the next and previous elements in the tree: 3: select element after (1) 1`] = `
618
+Object {
619
+ "inspectedElementID": 4,
620
+ "numElements": 4,
621
+ "ownerFlatTree": null,
622
+ "ownerID": null,
623
+ "searchIndex": null,
624
+ "searchResults": Array [],
625
+ "searchText": "",
626
+ "selectedElementID": 4,
627
+ "selectedElementIndex": 2,
628
+}
629
+`;
630
+
631
+exports[`TreeListContext tree state should select the next and previous elements in the tree: 3: select element after (2) 1`] = `
632
+Object {
633
+ "inspectedElementID": 5,
634
+ "numElements": 4,
635
+ "ownerFlatTree": null,
636
+ "ownerID": null,
637
+ "searchIndex": null,
638
+ "searchResults": Array [],
639
+ "searchText": "",
640
+ "selectedElementID": 5,
641
+ "selectedElementIndex": 3,
642
+}
643
+`;
644
+
645
+exports[`TreeListContext tree state should select the next and previous elements in the tree: 4: select element before (1) 1`] = `
646
+Object {
647
+ "inspectedElementID": 2,
648
+ "numElements": 4,
649
+ "ownerFlatTree": null,
650
+ "ownerID": null,
651
+ "searchIndex": null,
652
+ "searchResults": Array [],
653
+ "searchText": "",
654
+ "selectedElementID": 2,
655
+ "selectedElementIndex": 0,
656
+}
657
+`;
658
+
659
+exports[`TreeListContext tree state should select the next and previous elements in the tree: 4: select element before (2) 1`] = `
660
+Object {
661
+ "inspectedElementID": 3,
662
+ "numElements": 4,
663
+ "ownerFlatTree": null,
664
+ "ownerID": null,
665
+ "searchIndex": null,
666
+ "searchResults": Array [],
667
+ "searchText": "",
668
+ "selectedElementID": 3,
669
+ "selectedElementIndex": 1,
670
+}
671
+`;
672
+
673
+exports[`TreeListContext tree state should select the next and previous elements in the tree: 4: select element before (3) 1`] = `
674
+Object {
675
+ "inspectedElementID": 4,
676
+ "numElements": 4,
677
+ "ownerFlatTree": null,
678
+ "ownerID": null,
679
+ "searchIndex": null,
680
+ "searchResults": Array [],
681
+ "searchText": "",
682
+ "selectedElementID": 4,
683
+ "selectedElementIndex": 2,
684
+}
685
+`;
686
+
687
+exports[`TreeListContext tree state should select the next and previous elements in the tree: 5: select previous wraps around to last 1`] = `
688
+Object {
689
+ "inspectedElementID": 5,
690
+ "numElements": 4,
691
+ "ownerFlatTree": null,
692
+ "ownerID": null,
693
+ "searchIndex": null,
694
+ "searchResults": Array [],
695
+ "searchText": "",
696
+ "selectedElementID": 5,
697
+ "selectedElementIndex": 3,
698
+}
699
+`;
700
+
701
+exports[`TreeListContext tree state should select the next and previous elements in the tree: 6: select next wraps around to first 1`] = `
702
+Object {
703
+ "inspectedElementID": 2,
704
+ "numElements": 4,
705
+ "ownerFlatTree": null,
706
+ "ownerID": null,
707
+ "searchIndex": null,
708
+ "searchResults": Array [],
709
+ "searchText": "",
710
+ "selectedElementID": 2,
711
+ "selectedElementIndex": 0,
712
+}
713
+`;
src/__tests__/ownersListContext-test.js
+8
-8
@@ -53,15 +53,15 @@ describe('OwnersListContext', () => {
53
54
it('should fetch the owners list for the selected element', async done => {
55
const Grandparent = () => <Parent />;
56
- const Parent = ({ count }) => {
56
+ const Parent = () => {
57
return (
58
<React.Fragment>
59
- <Child duration={1} />
60
- <Child duration={2} />
59
+ <Child />
60
+ <Child />
61
</React.Fragment>
62
);
63
};
64
- const Child = ({ duration }) => null;
64
+ const Child = () => null;
65
66
utils.act(() =>
67
ReactDOM.render(<Grandparent />, document.createElement('div'))
@@ -118,15 +118,15 @@ describe('OwnersListContext', () => {
118
store.componentFilters = [utils.createDisplayNameFilter('^Parent$')];
119
120
const Grandparent = () => <Parent />;
121
- const Parent = ({ count }) => {
121
+ const Parent = () => {
122
return (
123
<React.Fragment>
124
- <Child duration={1} />
125
- <Child duration={2} />
124
+ <Child />
125
+ <Child />
126
</React.Fragment>
127
);
128
};
129
- const Child = ({ duration }) => null;
129
+ const Child = () => null;
130
131
utils.act(() =>
132
ReactDOM.render(<Grandparent />, document.createElement('div'))
src/__tests__/treeContext-test.js
new
+428
@@ -0,0 +1,428 @@
1
+// @flow
2
+
3
+import typeof ReactTestRenderer from 'react-test-renderer';
4
+import type Bridge from 'src/bridge';
5
+import type Store from 'src/devtools/store';
6
+import type {
7
+ DispatcherContext,
8
+ StateContext,
9
+} from 'src/devtools/views/Components/TreeContext';
10
+
11
+describe('TreeListContext', () => {
12
+ let React;
13
+ let ReactDOM;
14
+ let TestRenderer: ReactTestRenderer;
15
+ let bridge: Bridge;
16
+ let store: Store;
17
+ let utils;
18
+
19
+ let BridgeContext;
20
+ let StoreContext;
21
+ let TreeContext;
22
+
23
+ let dispatch: DispatcherContext;
24
+ let state: StateContext;
25
+
26
+ beforeEach(() => {
27
+ utils = require('./utils');
28
+ utils.beforeEachProfiling();
29
+
30
+ bridge = global.bridge;
31
+ store = global.store;
32
+ store.collapseNodesByDefault = false;
33
+
34
+ React = require('react');
35
+ ReactDOM = require('react-dom');
36
+ TestRenderer = utils.requireTestRenderer();
37
+
38
+ BridgeContext = require('src/devtools/views/context').BridgeContext;
39
+ StoreContext = require('src/devtools/views/context').StoreContext;
40
+ TreeContext = require('src/devtools/views/Components/TreeContext');
41
+ });
42
+
43
+ afterEach(() => {
44
+ // Reset between tests
45
+ dispatch = ((null: any): DispatcherContext);
46
+ state = ((null: any): StateContext);
47
+ });
48
+
49
+ const Capture = () => {
50
+ dispatch = React.useContext(TreeContext.TreeDispatcherContext);
51
+ state = React.useContext(TreeContext.TreeStateContext);
52
+ return null;
53
+ };
54
+
55
+ const Contexts = () => {
56
+ return (
57
+ <BridgeContext.Provider value={bridge}>
58
+ <StoreContext.Provider value={store}>
59
+ <TreeContext.TreeContextController>
60
+ <Capture />
61
+ </TreeContext.TreeContextController>
62
+ </StoreContext.Provider>
63
+ </BridgeContext.Provider>
64
+ );
65
+ };
66
+
67
+ describe('tree state', () => {
68
+ it('should select the next and previous elements in the tree', () => {
69
+ const Grandparent = () => <Parent />;
70
+ const Parent = () => (
71
+ <React.Fragment>
72
+ <Child />
73
+ <Child />
74
+ </React.Fragment>
75
+ );
76
+ const Child = () => null;
77
+
78
+ utils.act(() =>
79
+ ReactDOM.render(<Grandparent />, document.createElement('div'))
80
+ );
81
+
82
+ expect(store).toMatchSnapshot('0: mount');
83
+
84
+ let renderer;
85
+ utils.act(() => (renderer = TestRenderer.create(<Contexts />)));
86
+ expect(state).toMatchSnapshot('1: initial state');
87
+
88
+ utils.act(() => dispatch({ type: 'SELECT_NEXT_ELEMENT_IN_TREE' }));
89
+ utils.act(() => renderer.update(<Contexts />));
90
+ expect(state).toMatchSnapshot('2: select first element');
91
+
92
+ while (
93
+ state.selectedElementIndex !== null &&
94
+ state.selectedElementIndex < store.numElements - 1
95
+ ) {
96
+ const index = ((state.selectedElementIndex: any): number);
97
+ utils.act(() => dispatch({ type: 'SELECT_NEXT_ELEMENT_IN_TREE' }));
98
+ utils.act(() => renderer.update(<Contexts />));
99
+ expect(state).toMatchSnapshot(`3: select element after (${index})`);
100
+ }
101
+
102
+ while (
103
+ state.selectedElementIndex !== null &&
104
+ state.selectedElementIndex > 0
105
+ ) {
106
+ const index = ((state.selectedElementIndex: any): number);
107
+ utils.act(() => dispatch({ type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE' }));
108
+ utils.act(() => renderer.update(<Contexts />));
109
+ expect(state).toMatchSnapshot(`4: select element before (${index})`);
110
+ }
111
+
112
+ utils.act(() => dispatch({ type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE' }));
113
+ utils.act(() => renderer.update(<Contexts />));
114
+ expect(state).toMatchSnapshot('5: select previous wraps around to last');
115
+
116
+ utils.act(() => dispatch({ type: 'SELECT_NEXT_ELEMENT_IN_TREE' }));
117
+ utils.act(() => renderer.update(<Contexts />));
118
+ expect(state).toMatchSnapshot('6: select next wraps around to first');
119
+ });
120
+
121
+ it('should select child elements', () => {
122
+ const Grandparent = () => (
123
+ <React.Fragment>
124
+ <Parent />
125
+ <Parent />
126
+ </React.Fragment>
127
+ );
128
+ const Parent = () => (
129
+ <React.Fragment>
130
+ <Child />
131
+ <Child />
132
+ </React.Fragment>
133
+ );
134
+ const Child = () => null;
135
+
136
+ utils.act(() =>
137
+ ReactDOM.render(<Grandparent />, document.createElement('div'))
138
+ );
139
+
140
+ expect(store).toMatchSnapshot('0: mount');
141
+
142
+ let renderer;
143
+ utils.act(() => (renderer = TestRenderer.create(<Contexts />)));
144
+ expect(state).toMatchSnapshot('1: initial state');
145
+
146
+ utils.act(() =>
147
+ dispatch({ type: 'SELECT_ELEMENT_AT_INDEX', payload: 0 })
148
+ );
149
+ utils.act(() => renderer.update(<Contexts />));
150
+ expect(state).toMatchSnapshot('2: select first element');
151
+
152
+ utils.act(() => dispatch({ type: 'SELECT_CHILD_ELEMENT_IN_TREE' }));
153
+ utils.act(() => renderer.update(<Contexts />));
154
+ expect(state).toMatchSnapshot('3: select Parent');
155
+
156
+ utils.act(() => dispatch({ type: 'SELECT_CHILD_ELEMENT_IN_TREE' }));
157
+ utils.act(() => renderer.update(<Contexts />));
158
+ expect(state).toMatchSnapshot('4: select Child');
159
+
160
+ const previousState = state;
161
+
162
+ // There are no more children to select, so this should be a no-op
163
+ utils.act(() => dispatch({ type: 'SELECT_CHILD_ELEMENT_IN_TREE' }));
164
+ utils.act(() => renderer.update(<Contexts />));
165
+ expect(state).toEqual(previousState);
166
+ });
167
+
168
+ it('should select parent elements and then collapse', () => {
169
+ const Grandparent = () => (
170
+ <React.Fragment>
171
+ <Parent />
172
+ <Parent />
173
+ </React.Fragment>
174
+ );
175
+ const Parent = () => (
176
+ <React.Fragment>
177
+ <Child />
178
+ <Child />
179
+ </React.Fragment>
180
+ );
181
+ const Child = () => null;
182
+
183
+ utils.act(() =>
184
+ ReactDOM.render(<Grandparent />, document.createElement('div'))
185
+ );
186
+
187
+ expect(store).toMatchSnapshot('0: mount');
188
+
189
+ let renderer;
190
+ utils.act(() => (renderer = TestRenderer.create(<Contexts />)));
191
+ expect(state).toMatchSnapshot('1: initial state');
192
+
193
+ const lastChildID = store.getElementIDAtIndex(store.numElements - 1);
194
+
195
+ utils.act(() =>
196
+ dispatch({ type: 'SELECT_ELEMENT_BY_ID', payload: lastChildID })
197
+ );
198
+ utils.act(() => renderer.update(<Contexts />));
199
+ expect(state).toMatchSnapshot('2: select last child');
200
+
201
+ utils.act(() => dispatch({ type: 'SELECT_PARENT_ELEMENT_IN_TREE' }));
202
+ utils.act(() => renderer.update(<Contexts />));
203
+ expect(state).toMatchSnapshot('3: select Parent');
204
+
205
+ utils.act(() => dispatch({ type: 'SELECT_PARENT_ELEMENT_IN_TREE' }));
206
+ utils.act(() => renderer.update(<Contexts />));
207
+ expect(state).toMatchSnapshot('4: select Grandparent');
208
+
209
+ const previousState = state;
210
+
211
+ // There are no more ancestors to select, so this should be a no-op
212
+ utils.act(() => dispatch({ type: 'SELECT_PARENT_ELEMENT_IN_TREE' }));
213
+ utils.act(() => renderer.update(<Contexts />));
214
+ expect(state).toEqual(previousState);
215
+ });
216
+ });
217
+
218
+ describe('search state', () => {
219
+ it('should find elements matching search text', () => {
220
+ const Foo = () => null;
221
+ const Bar = () => null;
222
+ const Baz = () => null;
223
+
224
+ utils.act(() =>
225
+ ReactDOM.render(
226
+ <React.Fragment>
227
+ <Foo />
228
+ <Bar />
229
+ <Baz />
230
+ </React.Fragment>,
231
+ document.createElement('div')
232
+ )
233
+ );
234
+
235
+ expect(store).toMatchSnapshot('0: mount');
236
+
237
+ let renderer;
238
+ utils.act(() => (renderer = TestRenderer.create(<Contexts />)));
239
+ expect(state).toMatchSnapshot('1: initial state');
240
+
241
+ utils.act(() => dispatch({ type: 'SET_SEARCH_TEXT', payload: 'ba' }));
242
+ utils.act(() => renderer.update(<Contexts />));
243
+ expect(state).toMatchSnapshot('2: search for "ba"');
244
+
245
+ utils.act(() => dispatch({ type: 'SET_SEARCH_TEXT', payload: 'f' }));
246
+ utils.act(() => renderer.update(<Contexts />));
247
+ expect(state).toMatchSnapshot('3: search for "f"');
248
+
249
+ utils.act(() => dispatch({ type: 'SET_SEARCH_TEXT', payload: 'q' }));
250
+ utils.act(() => renderer.update(<Contexts />));
251
+ expect(state).toMatchSnapshot('4: search for "q"');
252
+ });
253
+
254
+ it('should select the next and previous items within the search results', () => {
255
+ const Foo = () => null;
256
+ const Bar = () => null;
257
+ const Baz = () => null;
258
+
259
+ utils.act(() =>
260
+ ReactDOM.render(
261
+ <React.Fragment>
262
+ <Foo />
263
+ <Baz />
264
+ <Bar />
265
+ <Baz />
266
+ </React.Fragment>,
267
+ document.createElement('div')
268
+ )
269
+ );
270
+
271
+ expect(store).toMatchSnapshot('0: mount');
272
+
273
+ let renderer;
274
+ utils.act(() => (renderer = TestRenderer.create(<Contexts />)));
275
+ expect(state).toMatchSnapshot('1: initial state');
276
+
277
+ utils.act(() => dispatch({ type: 'SET_SEARCH_TEXT', payload: 'ba' }));
278
+ utils.act(() => renderer.update(<Contexts />));
279
+ expect(state).toMatchSnapshot('2: search for "ba"');
280
+
281
+ utils.act(() => dispatch({ type: 'GO_TO_NEXT_SEARCH_RESULT' }));
282
+ utils.act(() => renderer.update(<Contexts />));
283
+ expect(state).toMatchSnapshot('3: go to second result');
284
+
285
+ utils.act(() => dispatch({ type: 'GO_TO_NEXT_SEARCH_RESULT' }));
286
+ utils.act(() => renderer.update(<Contexts />));
287
+ expect(state).toMatchSnapshot('4: go to third result');
288
+
289
+ utils.act(() => dispatch({ type: 'GO_TO_PREVIOUS_SEARCH_RESULT' }));
290
+ utils.act(() => renderer.update(<Contexts />));
291
+ expect(state).toMatchSnapshot('5: go to second result');
292
+
293
+ utils.act(() => dispatch({ type: 'GO_TO_PREVIOUS_SEARCH_RESULT' }));
294
+ utils.act(() => renderer.update(<Contexts />));
295
+ expect(state).toMatchSnapshot('6: go to first result');
296
+
297
+ utils.act(() => dispatch({ type: 'GO_TO_PREVIOUS_SEARCH_RESULT' }));
298
+ utils.act(() => renderer.update(<Contexts />));
299
+ expect(state).toMatchSnapshot('7: wrap to last result');
300
+
301
+ utils.act(() => dispatch({ type: 'GO_TO_NEXT_SEARCH_RESULT' }));
302
+ utils.act(() => renderer.update(<Contexts />));
303
+ expect(state).toMatchSnapshot('8: wrap to first result');
304
+ });
305
+
306
+ it('should add newly mounted elements to the search results set if they match the current text', async done => {
307
+ const Foo = () => null;
308
+ const Bar = () => null;
309
+ const Baz = () => null;
310
+
311
+ const container = document.createElement('div');
312
+
313
+ utils.act(() =>
314
+ ReactDOM.render(
315
+ <React.Fragment>
316
+ <Foo />
317
+ <Bar />
318
+ </React.Fragment>,
319
+ container
320
+ )
321
+ );
322
+
323
+ expect(store).toMatchSnapshot('0: mount');
324
+
325
+ let renderer;
326
+ utils.act(() => (renderer = TestRenderer.create(<Contexts />)));
327
+ expect(state).toMatchSnapshot('1: initial state');
328
+
329
+ utils.act(() => dispatch({ type: 'SET_SEARCH_TEXT', payload: 'ba' }));
330
+ utils.act(() => renderer.update(<Contexts />));
331
+ expect(state).toMatchSnapshot('2: search for "ba"');
332
+
333
+ await utils.actSuspense(() =>
334
+ ReactDOM.render(
335
+ <React.Fragment>
336
+ <Foo />
337
+ <Bar />
338
+ <Baz />
339
+ </React.Fragment>,
340
+ container
341
+ )
342
+ );
343
+ utils.act(() => renderer.update(<Contexts />));
344
+ expect(state).toMatchSnapshot('3: mount Baz');
345
+
346
+ done();
347
+ });
348
+
349
+ it('should remove unmounted elements from the search results set', async done => {
350
+ const Foo = () => null;
351
+ const Bar = () => null;
352
+ const Baz = () => null;
353
+
354
+ const container = document.createElement('div');
355
+
356
+ utils.act(() =>
357
+ ReactDOM.render(
358
+ <React.Fragment>
359
+ <Foo />
360
+ <Bar />
361
+ <Baz />
362
+ </React.Fragment>,
363
+ container
364
+ )
365
+ );
366
+
367
+ expect(store).toMatchSnapshot('0: mount');
368
+
369
+ let renderer;
370
+ utils.act(() => (renderer = TestRenderer.create(<Contexts />)));
371
+ expect(state).toMatchSnapshot('1: initial state');
372
+
373
+ utils.act(() => dispatch({ type: 'SET_SEARCH_TEXT', payload: 'ba' }));
374
+ utils.act(() => renderer.update(<Contexts />));
375
+ expect(state).toMatchSnapshot('2: search for "ba"');
376
+
377
+ utils.act(() => dispatch({ type: 'GO_TO_NEXT_SEARCH_RESULT' }));
378
+ utils.act(() => renderer.update(<Contexts />));
379
+ expect(state).toMatchSnapshot('3: go to second result');
380
+
381
+ await utils.actSuspense(() =>
382
+ ReactDOM.render(
383
+ <React.Fragment>
384
+ <Foo />
385
+ <Bar />
386
+ </React.Fragment>,
387
+ container
388
+ )
389
+ );
390
+ utils.act(() => renderer.update(<Contexts />));
391
+ expect(state).toMatchSnapshot('4: unmount Baz');
392
+
393
+ done();
394
+ });
395
+ });
396
+
397
+ describe('owners state', () => {
398
+ it('should support entering and existing the owners tree view', () => {
399
+ const Grandparent = () => <Parent />;
400
+ const Parent = () => (
401
+ <React.Fragment>
402
+ <Child />
403
+ <Child />
404
+ </React.Fragment>
405
+ );
406
+ const Child = () => null;
407
+
408
+ utils.act(() =>
409
+ ReactDOM.render(<Grandparent />, document.createElement('div'))
410
+ );
411
+
412
+ expect(store).toMatchSnapshot('0: mount');
413
+
414
+ let renderer;
415
+ utils.act(() => (renderer = TestRenderer.create(<Contexts />)));
416
+ expect(state).toMatchSnapshot('1: initial state');
417
+
418
+ let parentID = ((store.getElementIDAtIndex(1): any): number);
419
+ utils.act(() => dispatch({ type: 'SELECT_OWNER', payload: parentID }));
420
+ utils.act(() => renderer.update(<Contexts />));
421
+ expect(state).toMatchSnapshot('2: parent owners tree');
422
+
423
+ utils.act(() => dispatch({ type: 'RESET_OWNER_STACK' }));
424
+ utils.act(() => renderer.update(<Contexts />));
425
+ expect(state).toMatchSnapshot('3: final state');
426
+ });
427
+ });
428
+});
src/devtools/views/Components/TreeContext.js
+2
-2
@@ -38,7 +38,7 @@ import Store from '../../store';
38
39
import type { Element } from './types';
40
41
-type StateContext = {|
41
+export type StateContext = {|
42
// Tree
43
numElements: number,
44
selectedElementID: number | null,
@@ -117,7 +117,7 @@ type Action =
117
| ACTION_SET_SEARCH_TEXT
118
| ACTION_UPDATE_INSPECTED_ELEMENT_ID;
119
120
-type DispatcherContext = (action: Action) => void;
120
+export type DispatcherContext = (action: Action) => void;
121
122
const TreeStateContext = createContext<StateContext>(
123
((null: any): StateContext)