@khanacademy/wonder-blocks-accordion 1.3.7 → 1.3.8

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.
@@ -1,956 +0,0 @@
1
- import * as React from "react";
2
- import {render, screen} from "@testing-library/react";
3
- import {userEvent} from "@testing-library/user-event";
4
-
5
- import {RenderStateRoot} from "@khanacademy/wonder-blocks-core";
6
-
7
- import Accordion from "../accordion";
8
- import AccordionSection from "../accordion-section";
9
-
10
- describe("Accordion", () => {
11
- test("renders", async () => {
12
- // Arrange
13
-
14
- // Act
15
- render(
16
- <Accordion>
17
- <AccordionSection header="Section 1">
18
- Section 1 content
19
- </AccordionSection>
20
- <AccordionSection header="Section 2">
21
- Section 2 content
22
- </AccordionSection>
23
- </Accordion>,
24
- {wrapper: RenderStateRoot},
25
- );
26
-
27
- // Assert
28
- expect(await screen.findByText("Section 1")).toBeVisible();
29
- expect(await screen.findByText("Section 2")).toBeVisible();
30
- });
31
-
32
- test("opens sections when clicked", async () => {
33
- // Arrange
34
- render(
35
- <Accordion>
36
- <AccordionSection header="Section 1">
37
- Section 1 content
38
- </AccordionSection>
39
- <AccordionSection header="Section 2">
40
- Section 2 content
41
- </AccordionSection>
42
- </Accordion>,
43
- {wrapper: RenderStateRoot},
44
- );
45
-
46
- const button1 = await screen.findByRole("button", {name: "Section 1"});
47
- const button2 = await screen.findByRole("button", {name: "Section 2"});
48
-
49
- // Act
50
- button1.click();
51
- button2.click();
52
-
53
- // Assert
54
- expect(await screen.findByText("Section 1 content")).toBeVisible();
55
- expect(await screen.findByText("Section 2 content")).toBeVisible();
56
- });
57
-
58
- test("closes sections when clicked", async () => {
59
- // Arrange
60
- render(
61
- <Accordion>
62
- <AccordionSection header="Section 1">
63
- Section 1 content
64
- </AccordionSection>
65
- <AccordionSection header="Section 2">
66
- Section 2 content
67
- </AccordionSection>
68
- </Accordion>,
69
- {wrapper: RenderStateRoot},
70
- );
71
-
72
- const button1 = await screen.findByRole("button", {name: "Section 1"});
73
- const button2 = await screen.findByRole("button", {name: "Section 2"});
74
-
75
- // Act
76
- // open
77
- button1.click();
78
- button2.click();
79
- // close
80
- button1.click();
81
- button2.click();
82
-
83
- // Assert
84
- expect(screen.queryByText("Section 1 content")).not.toBeVisible();
85
- expect(screen.queryByText("Section 2 content")).not.toBeVisible();
86
- });
87
-
88
- test("initialExpandedIndex opens the correct section", async () => {
89
- // Arrange
90
- render(
91
- <Accordion initialExpandedIndex={1}>
92
- <AccordionSection header="Section 1">
93
- Section 1 content
94
- </AccordionSection>
95
- <AccordionSection header="Section 2">
96
- Section 2 content
97
- </AccordionSection>
98
- <AccordionSection header="Section 3">
99
- Section 3 content
100
- </AccordionSection>
101
- </Accordion>,
102
- {wrapper: RenderStateRoot},
103
- );
104
-
105
- // Act
106
- // Assert
107
- expect(screen.queryByText("Section 1 content")).not.toBeVisible();
108
- expect(await screen.findByText("Section 2 content")).toBeVisible();
109
- expect(screen.queryByText("Section 3 content")).not.toBeVisible();
110
- });
111
-
112
- test("only allows one section to be open at a time when allowMultipleExpanded is false", async () => {
113
- // Arrange
114
- render(
115
- <Accordion initialExpandedIndex={1} allowMultipleExpanded={false}>
116
- <AccordionSection header="Section 1">
117
- Section 1 content
118
- </AccordionSection>
119
- <AccordionSection header="Section 2">
120
- Section 2 content
121
- </AccordionSection>
122
- <AccordionSection header="Section 3">
123
- Section 3 content
124
- </AccordionSection>
125
- </Accordion>,
126
- {wrapper: RenderStateRoot},
127
- );
128
-
129
- // Act
130
- const button = await screen.findByRole("button", {name: "Section 3"});
131
- button.click();
132
-
133
- // Assert
134
- expect(screen.queryByText("Section 1 content")).not.toBeVisible();
135
- expect(screen.queryByText("Section 2 content")).not.toBeVisible();
136
- expect(await screen.findByText("Section 3 content")).toBeVisible();
137
- });
138
-
139
- test("calls child's onToggle when section is clicked", async () => {
140
- // Arrange
141
- const onToggleSpy = jest.fn();
142
- render(
143
- <Accordion>
144
- <AccordionSection header="Section 1" onToggle={onToggleSpy}>
145
- Section 1 content
146
- </AccordionSection>
147
- <AccordionSection header="Section 2">
148
- Section 2 content
149
- </AccordionSection>
150
- </Accordion>,
151
- {wrapper: RenderStateRoot},
152
- );
153
-
154
- const button = await screen.findByRole("button", {name: "Section 1"});
155
-
156
- // Act
157
- button.click();
158
-
159
- // Assert
160
- expect(onToggleSpy).toHaveBeenCalledTimes(1);
161
- });
162
-
163
- test("Other props are passed to the section", async () => {
164
- // Arrange
165
- render(
166
- <Accordion>
167
- <AccordionSection header="Section 1" testId="test-id-1">
168
- Section 1 content
169
- </AccordionSection>
170
- <AccordionSection header="Section 2" testId="test-id-2">
171
- Section 2 content
172
- </AccordionSection>
173
- </Accordion>,
174
- {wrapper: RenderStateRoot},
175
- );
176
-
177
- // Act
178
- const header1 = await screen.findByTestId("test-id-1-header");
179
- const header2 = await screen.findByTestId("test-id-2-header");
180
-
181
- // Assert
182
- expect(header1).toBeVisible();
183
- expect(header2).toBeVisible();
184
- });
185
-
186
- test("Styles the corners based on the square cornerKind", async () => {
187
- // Arrange
188
- render(
189
- <Accordion cornerKind="square">
190
- {[
191
- <AccordionSection
192
- key="section-id"
193
- header="Title"
194
- testId="section-test-id"
195
- >
196
- Section content
197
- </AccordionSection>,
198
- ]}
199
- </Accordion>,
200
- {wrapper: RenderStateRoot},
201
- );
202
-
203
- // Act
204
- const section = await screen.findByTestId("section-test-id");
205
-
206
- // Assert
207
- expect(section).toHaveStyle({
208
- borderRadius: 0,
209
- });
210
- });
211
-
212
- test("Styles the corners based on the rounded cornerKind", async () => {
213
- // Arrange
214
- render(
215
- <Accordion cornerKind="rounded">
216
- {[
217
- <AccordionSection
218
- key="section-id"
219
- header="Title"
220
- testId="section-test-id"
221
- >
222
- Section content
223
- </AccordionSection>,
224
- ]}
225
- </Accordion>,
226
- {wrapper: RenderStateRoot},
227
- );
228
-
229
- // Act
230
- const section = await screen.findByTestId("section-test-id");
231
-
232
- // Assert
233
- expect(section).toHaveStyle({
234
- borderStartStartRadius: "12px",
235
- borderStartEndRadius: "12px",
236
- borderEndStartRadius: "12px",
237
- borderEndEndRadius: "12px",
238
- });
239
- });
240
-
241
- test("Styles the corners based on the rounded-per-section cornerKind", async () => {
242
- // Arrange
243
- render(
244
- <Accordion cornerKind="rounded-per-section">
245
- {[
246
- <AccordionSection
247
- key="section-id"
248
- header="Title"
249
- testId="section-test-id"
250
- >
251
- Section content
252
- </AccordionSection>,
253
- ]}
254
- </Accordion>,
255
- {wrapper: RenderStateRoot},
256
- );
257
-
258
- // Act
259
- const section = await screen.findByTestId("section-test-id");
260
-
261
- // Assert
262
- expect(section).toHaveStyle({
263
- borderRadius: "12px",
264
- });
265
- });
266
-
267
- test("prioritizes the child's cornerKind prop", async () => {
268
- // Arrange
269
- render(
270
- <Accordion cornerKind="square">
271
- {[
272
- <AccordionSection
273
- key="section-id"
274
- header="Title"
275
- cornerKind="rounded-per-section"
276
- testId="section-test-id"
277
- >
278
- Section content
279
- </AccordionSection>,
280
- ]}
281
- </Accordion>,
282
- {wrapper: RenderStateRoot},
283
- );
284
-
285
- // Act
286
- const section = await screen.findByTestId("section-test-id");
287
-
288
- // Assert
289
- expect(section).toHaveStyle({
290
- borderRadius: "12px",
291
- });
292
- });
293
-
294
- test("puts the caret first when caretPosition is start", async () => {
295
- // Arrange
296
- render(
297
- <Accordion caretPosition="start">
298
- {[
299
- <AccordionSection
300
- key="section-id"
301
- header="Title"
302
- testId="section-test-id"
303
- >
304
- Section content
305
- </AccordionSection>,
306
- ]}
307
- </Accordion>,
308
- {wrapper: RenderStateRoot},
309
- );
310
-
311
- // Act
312
- const sectionHeader = await screen.findByTestId(
313
- "section-test-id-header",
314
- );
315
-
316
- // Assert
317
- expect(sectionHeader).toHaveStyle({
318
- flexDirection: "row-reverse",
319
- });
320
- });
321
-
322
- test("puts the caret last when caretPosition is end", async () => {
323
- // Arrange
324
- render(
325
- <Accordion caretPosition="end">
326
- {[
327
- <AccordionSection
328
- key="section-id"
329
- header="Title"
330
- testId="section-test-id"
331
- >
332
- Section content
333
- </AccordionSection>,
334
- ]}
335
- </Accordion>,
336
- {wrapper: RenderStateRoot},
337
- );
338
-
339
- // Act
340
- const sectionHeader = await screen.findByTestId(
341
- "section-test-id-header",
342
- );
343
-
344
- // Assert
345
- expect(sectionHeader).toHaveStyle({
346
- flexDirection: "row",
347
- });
348
- });
349
-
350
- test("prioritizes the child's caretPosition prop", async () => {
351
- // Arrange
352
- render(
353
- <Accordion caretPosition="end">
354
- {[
355
- <AccordionSection
356
- key="section-id"
357
- header="Title"
358
- caretPosition="start"
359
- testId="section-test-id"
360
- >
361
- Section content
362
- </AccordionSection>,
363
- ]}
364
- </Accordion>,
365
- {wrapper: RenderStateRoot},
366
- );
367
-
368
- // Act
369
- const sectionHeader = await screen.findByTestId(
370
- "section-test-id-header",
371
- );
372
-
373
- // Assert
374
- expect(sectionHeader).toHaveStyle({
375
- flexDirection: "row-reverse",
376
- });
377
- });
378
-
379
- test("prioritizes the child's animated prop", async () => {
380
- // Arrange
381
- render(
382
- <Accordion animated={false}>
383
- {[
384
- <AccordionSection
385
- key="section-id"
386
- header="Title"
387
- animated={true}
388
- testId="section-test-id"
389
- >
390
- Section content
391
- </AccordionSection>,
392
- ]}
393
- </Accordion>,
394
- {wrapper: RenderStateRoot},
395
- );
396
-
397
- // Act
398
- const sectionHeader = await screen.findByTestId(
399
- "section-test-id-header",
400
- );
401
-
402
- // Assert
403
- // The child has animated=true, so the parent's animated=false
404
- // should be overridden.
405
- expect(sectionHeader).toHaveStyle({
406
- // The existence of the transition style means that the
407
- // accordion is animated.
408
- transition: "border-radius 300ms",
409
- });
410
- });
411
-
412
- test("applies style to the wrapper", async () => {
413
- // Arrange
414
- render(
415
- <Accordion style={{color: "red"}}>
416
- <AccordionSection header="Section 1">
417
- Section 1 content
418
- </AccordionSection>
419
- <AccordionSection header="Section 2">
420
- Section 2 content
421
- </AccordionSection>
422
- </Accordion>,
423
- {wrapper: RenderStateRoot},
424
- );
425
-
426
- // Act
427
- const wrapper = await screen.findByRole("list");
428
-
429
- // Assert
430
- expect(wrapper).toHaveStyle({color: "red"});
431
- });
432
-
433
- test("applies region role to sections when there are 6 or fewer", async () => {
434
- // Arrange
435
- render(
436
- <Accordion>
437
- <AccordionSection header="Section 1" testId="section-1">
438
- Section 1 content
439
- </AccordionSection>
440
- <AccordionSection header="Section 2">
441
- Section 2 content
442
- </AccordionSection>
443
- <AccordionSection header="Section 3">
444
- Section 3 content
445
- </AccordionSection>
446
- <AccordionSection header="Section 4">
447
- Section 4 content
448
- </AccordionSection>
449
- <AccordionSection header="Section 5">
450
- Section 5 content
451
- </AccordionSection>
452
- <AccordionSection header="Section 6">
453
- Section 6 content
454
- </AccordionSection>
455
- </Accordion>,
456
- {wrapper: RenderStateRoot},
457
- );
458
-
459
- // Act
460
- const section1ContentPanel = await screen.findByTestId(
461
- "section-1-content-panel",
462
- );
463
-
464
- // Assert
465
- expect(section1ContentPanel).toHaveAttribute("role", "region");
466
- });
467
-
468
- test("does not apply region role to sections when there are more than 6", async () => {
469
- // Arrange
470
- render(
471
- <Accordion>
472
- <AccordionSection header="Section 1" testId="section-1">
473
- Section 1 content
474
- </AccordionSection>
475
- <AccordionSection header="Section 2">
476
- Section 2 content
477
- </AccordionSection>
478
- <AccordionSection header="Section 3">
479
- Section 3 content
480
- </AccordionSection>
481
- <AccordionSection header="Section 4">
482
- Section 4 content
483
- </AccordionSection>
484
- <AccordionSection header="Section 5">
485
- Section 5 content
486
- </AccordionSection>
487
- <AccordionSection header="Section 6">
488
- Section 6 content
489
- </AccordionSection>
490
- <AccordionSection header="Section 7">
491
- Section 7 content
492
- </AccordionSection>
493
- </Accordion>,
494
- {wrapper: RenderStateRoot},
495
- );
496
-
497
- // Act
498
- const section1ContentPanel = await screen.findByTestId(
499
- "section-1-content-panel",
500
- );
501
-
502
- // Assert
503
- expect(section1ContentPanel).not.toHaveAttribute("role", "region");
504
- });
505
-
506
- test("appropriately sets aria-labelledby on the content panel", async () => {
507
- // Arrange
508
- render(
509
- <Accordion>
510
- <AccordionSection
511
- id="accordion-section-id-for-test"
512
- header="Section 1"
513
- testId="section-1"
514
- >
515
- Section 1 content
516
- </AccordionSection>
517
- <AccordionSection header="Section 2">
518
- Section 2 content
519
- </AccordionSection>
520
- </Accordion>,
521
- {wrapper: RenderStateRoot},
522
- );
523
-
524
- // Act
525
- const section1ContentPanel = await screen.findByTestId(
526
- "section-1-content-panel",
527
- );
528
-
529
- // Assert
530
- expect(section1ContentPanel).toHaveAttribute(
531
- "aria-labelledby",
532
- "accordion-section-id-for-test-header",
533
- );
534
- });
535
-
536
- describe("keyboard navigation", () => {
537
- test("can open a section with the enter key", async () => {
538
- // Arrange
539
- render(
540
- <Accordion>
541
- <AccordionSection header="Section 1">
542
- Section 1 content
543
- </AccordionSection>
544
- <AccordionSection header="Section 2">
545
- Section 2 content
546
- </AccordionSection>
547
- </Accordion>,
548
- {wrapper: RenderStateRoot},
549
- );
550
-
551
- const button1 = await screen.findByRole("button", {
552
- name: "Section 1",
553
- });
554
-
555
- // Act
556
- // Confirm that the section is closed.
557
- expect(screen.queryByText("Section 1 content")).not.toBeVisible();
558
-
559
- button1.focus();
560
- await userEvent.keyboard("{enter}");
561
-
562
- // Assert
563
- // Confirm that the section is now open.
564
- expect(await screen.findByText("Section 1 content")).toBeVisible();
565
- });
566
-
567
- // TODO(FEI-5533): Key press events aren't working correctly with
568
- // user-event v14. We need to investigate and fix this.
569
- test.skip("can open a section with the space key", async () => {
570
- // Arrange
571
- render(
572
- <Accordion>
573
- <AccordionSection header="Section 1">
574
- Section 1 content
575
- </AccordionSection>
576
- <AccordionSection header="Section 2">
577
- Section 2 content
578
- </AccordionSection>
579
- </Accordion>,
580
- {wrapper: RenderStateRoot},
581
- );
582
-
583
- const button1 = await screen.findByRole("button", {
584
- name: "Section 1",
585
- });
586
-
587
- // Act
588
- // Confirm that the section is closed.
589
- expect(screen.queryByText("Section 1 content")).not.toBeVisible();
590
-
591
- button1.focus();
592
- await userEvent.keyboard("{space}");
593
-
594
- // Assert
595
- // Confirm that the section is now open.
596
- expect(await screen.findByText("Section 1 content")).toBeVisible();
597
- });
598
-
599
- test("can close a section with the enter key", async () => {
600
- // Arrange
601
- render(
602
- <Accordion>
603
- <AccordionSection header="Section 1">
604
- Section 1 content
605
- </AccordionSection>
606
- <AccordionSection header="Section 2">
607
- Section 2 content
608
- </AccordionSection>
609
- </Accordion>,
610
- {wrapper: RenderStateRoot},
611
- );
612
-
613
- const button1 = await screen.findByRole("button", {
614
- name: "Section 1",
615
- });
616
-
617
- // Act
618
- // Confirm that the section is open.
619
- button1.click();
620
- expect(await screen.findByText("Section 1 content")).toBeVisible();
621
-
622
- button1.focus();
623
- await userEvent.keyboard("{enter}");
624
-
625
- // Assert
626
- // Confirm that the section is now closed.
627
- expect(screen.queryByText("Section 1 content")).not.toBeVisible();
628
- });
629
-
630
- // TODO(FEI-5533): Key press events aren't working correctly with
631
- // user-event v14. We need to investigate and fix this.
632
- test.skip("can close a section with the space key", async () => {
633
- // Arrange
634
- render(
635
- <Accordion>
636
- <AccordionSection header="Section 1">
637
- Section 1 content
638
- </AccordionSection>
639
- <AccordionSection header="Section 2">
640
- Section 2 content
641
- </AccordionSection>
642
- </Accordion>,
643
- {wrapper: RenderStateRoot},
644
- );
645
-
646
- const button1 = await screen.findByRole("button", {
647
- name: "Section 1",
648
- });
649
-
650
- // Act
651
- // Confirm that the section is open.
652
- button1.click();
653
- expect(await screen.findByText("Section 1 content")).toBeVisible();
654
-
655
- button1.focus();
656
- await userEvent.keyboard("{space}");
657
-
658
- // Assert
659
- // Confirm that the section is now closed.
660
- expect(screen.queryByText("Section 1 content")).not.toBeVisible();
661
- });
662
-
663
- test("can navigate to the next section with the tab key", async () => {
664
- // Arrange
665
- render(
666
- <Accordion>
667
- <AccordionSection header="Section 1">
668
- Section 1 content
669
- </AccordionSection>
670
- <AccordionSection header="Section 2">
671
- Section 2 content
672
- </AccordionSection>
673
- </Accordion>,
674
- {wrapper: RenderStateRoot},
675
- );
676
-
677
- const button1 = await screen.findByRole("button", {
678
- name: "Section 1",
679
- });
680
- const button2 = await screen.findByRole("button", {
681
- name: "Section 2",
682
- });
683
-
684
- // Act
685
- button1.focus();
686
- await userEvent.tab();
687
-
688
- // Assert
689
- expect(button2).toHaveFocus();
690
- });
691
-
692
- test("can navigate to the previous section with the shift+tab key", async () => {
693
- // Arrange
694
- render(
695
- <Accordion>
696
- <AccordionSection header="Section 1">
697
- Section 1 content
698
- </AccordionSection>
699
- <AccordionSection header="Section 2">
700
- Section 2 content
701
- </AccordionSection>
702
- </Accordion>,
703
- {wrapper: RenderStateRoot},
704
- );
705
-
706
- const button1 = await screen.findByRole("button", {
707
- name: "Section 1",
708
- });
709
- const button2 = await screen.findByRole("button", {
710
- name: "Section 2",
711
- });
712
-
713
- // Act
714
- button2.focus();
715
- await userEvent.tab({shift: true});
716
-
717
- // Assert
718
- expect(button1).toHaveFocus();
719
- });
720
-
721
- test("can navigate to the next section with the arrow down key", async () => {
722
- // Arrange
723
- render(
724
- <Accordion>
725
- <AccordionSection header="Section 1">
726
- Section 1 content
727
- </AccordionSection>
728
- <AccordionSection header="Section 2">
729
- Section 2 content
730
- </AccordionSection>
731
- </Accordion>,
732
- {wrapper: RenderStateRoot},
733
- );
734
-
735
- const button1 = await screen.findByRole("button", {
736
- name: "Section 1",
737
- });
738
- const button2 = await screen.findByRole("button", {
739
- name: "Section 2",
740
- });
741
-
742
- // Act
743
- button1.focus();
744
- await userEvent.keyboard("{arrowdown}");
745
-
746
- // Assert
747
- expect(button2).toHaveFocus();
748
- });
749
-
750
- test("can cycle to the first section with the arrow down key from the last section", async () => {
751
- // Arrange
752
- render(
753
- <Accordion>
754
- <AccordionSection header="Section 1">
755
- Section 1 content
756
- </AccordionSection>
757
- <AccordionSection header="Section 2" testId="section-2">
758
- Section 2 content
759
- </AccordionSection>
760
- <AccordionSection header="Section 3">
761
- Section 3 content
762
- </AccordionSection>
763
- </Accordion>,
764
- {wrapper: RenderStateRoot},
765
- );
766
-
767
- const button1 = await screen.findByRole("button", {
768
- name: "Section 1",
769
- });
770
- const button3 = await screen.findByRole("button", {
771
- name: "Section 3",
772
- });
773
-
774
- // Act
775
- button3.focus();
776
- await userEvent.keyboard("{arrowdown}");
777
-
778
- // Assert
779
- expect(button1).toHaveFocus();
780
- expect(button3).not.toHaveFocus();
781
- });
782
-
783
- test("can navigate to the previous section with the arrow up key", async () => {
784
- // Arrange
785
- render(
786
- <Accordion>
787
- <AccordionSection header="Section 1">
788
- Section 1 content
789
- </AccordionSection>
790
- <AccordionSection header="Section 2">
791
- Section 2 content
792
- </AccordionSection>
793
- </Accordion>,
794
- {wrapper: RenderStateRoot},
795
- );
796
-
797
- const button1 = await screen.findByRole("button", {
798
- name: "Section 1",
799
- });
800
- const button2 = await screen.findByRole("button", {
801
- name: "Section 2",
802
- });
803
-
804
- // Act
805
- button2.focus();
806
- await userEvent.keyboard("{arrowup}");
807
-
808
- // Assert
809
- expect(button1).toHaveFocus();
810
- });
811
-
812
- test("can cycle to the last section with the arrow up key from the first section", async () => {
813
- // Arrange
814
- render(
815
- <Accordion>
816
- <AccordionSection header="Section 1">
817
- Section 1 content
818
- </AccordionSection>
819
- <AccordionSection header="Section 2" testId="section-2">
820
- Section 2 content
821
- </AccordionSection>
822
- <AccordionSection header="Section 3">
823
- Section 3 content
824
- </AccordionSection>
825
- </Accordion>,
826
- {wrapper: RenderStateRoot},
827
- );
828
-
829
- const button1 = await screen.findByRole("button", {
830
- name: "Section 1",
831
- });
832
- const button3 = await screen.findByRole("button", {
833
- name: "Section 3",
834
- });
835
-
836
- // Act
837
- button1.focus();
838
- await userEvent.keyboard("{arrowup}");
839
-
840
- // Assert
841
- expect(button3).toHaveFocus();
842
- expect(button1).not.toHaveFocus();
843
- });
844
-
845
- test("can navigate to the first section with the home key", async () => {
846
- // Arrange
847
- render(
848
- <Accordion>
849
- <AccordionSection header="Section 1">
850
- Section 1 content
851
- </AccordionSection>
852
- <AccordionSection header="Section 2">
853
- Section 2 content
854
- </AccordionSection>
855
- <AccordionSection header="Section 3">
856
- Section 3 content
857
- </AccordionSection>
858
- </Accordion>,
859
- {wrapper: RenderStateRoot},
860
- );
861
-
862
- const button1 = await screen.findByRole("button", {
863
- name: "Section 1",
864
- });
865
- const button2 = await screen.findByRole("button", {
866
- name: "Section 2",
867
- });
868
- const button3 = await screen.findByRole("button", {
869
- name: "Section 3",
870
- });
871
-
872
- // Act
873
- button3.focus();
874
- await userEvent.keyboard("{home}");
875
-
876
- // Assert
877
- expect(button1).toHaveFocus();
878
- expect(button2).not.toHaveFocus();
879
- expect(button3).not.toHaveFocus();
880
- });
881
-
882
- test("can navigate to the last section with the end key", async () => {
883
- // Arrange
884
- render(
885
- <Accordion>
886
- <AccordionSection header="Section 1">
887
- Section 1 content
888
- </AccordionSection>
889
- <AccordionSection header="Section 2">
890
- Section 2 content
891
- </AccordionSection>
892
- <AccordionSection header="Section 3">
893
- Section 3 content
894
- </AccordionSection>
895
- </Accordion>,
896
- {wrapper: RenderStateRoot},
897
- );
898
-
899
- const button1 = await screen.findByRole("button", {
900
- name: "Section 1",
901
- });
902
- const button2 = await screen.findByRole("button", {
903
- name: "Section 2",
904
- });
905
- const button3 = await screen.findByRole("button", {
906
- name: "Section 3",
907
- });
908
-
909
- // Act
910
- button1.focus();
911
- await userEvent.keyboard("{end}");
912
-
913
- // Assert
914
- expect(button1).not.toHaveFocus();
915
- expect(button2).not.toHaveFocus();
916
- expect(button3).toHaveFocus();
917
- });
918
-
919
- test.each(["{end}", "{home}", "{arrowup}", "{arrowdown}"])(
920
- "cannot navigate when header not currently focused",
921
- async (key) => {
922
- // Arrange
923
- render(
924
- <Accordion initialExpandedIndex={0}>
925
- <AccordionSection header="Section 1">
926
- <label>
927
- Focus on this textbox!
928
- <input />
929
- </label>
930
- </AccordionSection>
931
- <AccordionSection header="Section 2">
932
- Section 2 content
933
- </AccordionSection>
934
- </Accordion>,
935
- {wrapper: RenderStateRoot},
936
- );
937
-
938
- const button1 = await screen.findByRole("button", {
939
- name: "Section 1",
940
- });
941
- const button2 = await screen.findByRole("button", {
942
- name: "Section 2",
943
- });
944
-
945
- // Act
946
- const button = await screen.findByRole("textbox");
947
- button.focus();
948
- await userEvent.keyboard(key);
949
-
950
- // Assert
951
- expect(button1).not.toHaveFocus();
952
- expect(button2).not.toHaveFocus();
953
- },
954
- );
955
- });
956
- });