@samitouri / QOS-React-2 / commits / 427f0f63c1

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)