8
8
fireEvent ,
9
9
screen ,
10
10
strictModeDoubleLoggingSuppressed ,
11
+ waitFor ,
11
12
} from 'test/utils' ;
12
13
import Tab from '@mui/material/Tab' ;
13
14
import Tabs , { tabsClasses as classes } from '@mui/material/Tabs' ;
@@ -493,7 +494,6 @@ describe('<Tabs />', () => {
493
494
} ) ;
494
495
495
496
describe ( 'prop: variant="scrollable"' , ( ) => {
496
- clock . withFakeTimers ( ) ;
497
497
const tabs = (
498
498
< Tabs value = { 0 } style = { { width : 200 } } variant = "scrollable" >
499
499
< Tab style = { { width : 120 , minWidth : 'auto' } } />
@@ -509,34 +509,6 @@ describe('<Tabs />', () => {
509
509
expect ( container . querySelectorAll ( selector ) ) . to . have . lengthOf ( 1 ) ;
510
510
} ) ;
511
511
512
- it ( 'should response to scroll events' , function test ( ) {
513
- if ( isJSDOM ) {
514
- this . skip ( ) ;
515
- }
516
- const { container, forceUpdate, getByRole } = render ( tabs ) ;
517
- const tablistContainer = getByRole ( 'tablist' ) . parentElement ;
518
-
519
- Object . defineProperty ( tablistContainer , 'clientWidth' , { value : 200 - 40 * 2 } ) ;
520
- tablistContainer . scrollLeft = 10 ;
521
- Object . defineProperty ( tablistContainer , 'scrollWidth' , { value : 216 } ) ;
522
- Object . defineProperty ( tablistContainer , 'getBoundingClientRect' , {
523
- value : ( ) => ( {
524
- left : 0 ,
525
- right : 50 ,
526
- } ) ,
527
- } ) ;
528
- forceUpdate ( ) ;
529
- clock . tick ( 1000 ) ;
530
- expect ( hasLeftScrollButton ( container ) ) . to . equal ( true ) ;
531
- expect ( hasRightScrollButton ( container ) ) . to . equal ( true ) ;
532
- tablistContainer . scrollLeft = 0 ;
533
- fireEvent . scroll ( container . querySelector ( `.${ classes . scroller } .${ classes . scrollableX } ` ) ) ;
534
- clock . tick ( 166 ) ;
535
-
536
- expect ( hasLeftScrollButton ( container ) ) . to . equal ( false ) ;
537
- expect ( hasRightScrollButton ( container ) ) . to . equal ( true ) ;
538
- } ) ;
539
-
540
512
it ( 'should get a scrollbar size listener' , ( ) => {
541
513
const { setProps, getByRole } = render (
542
514
< Tabs value = { 0 } >
@@ -569,8 +541,6 @@ describe('<Tabs />', () => {
569
541
} ) ;
570
542
571
543
describe ( 'prop: scrollButtons' , ( ) => {
572
- clock . withFakeTimers ( ) ;
573
-
574
544
it ( 'should render scroll buttons' , ( ) => {
575
545
const { container } = render (
576
546
< Tabs value = { 0 } variant = "scrollable" scrollButtons >
@@ -608,65 +578,27 @@ describe('<Tabs />', () => {
608
578
expect ( container . querySelectorAll ( `.${ classes . scrollButtonsHideMobile } ` ) ) . to . have . lengthOf ( 0 ) ;
609
579
} ) ;
610
580
611
- it ( 'should handle window resize event' , function test ( ) {
612
- if ( isJSDOM ) {
613
- this . skip ( ) ;
614
- }
615
-
616
- const { container, forceUpdate, getByRole } = render (
617
- < Tabs value = { 0 } variant = "scrollable" scrollButtons style = { { width : 200 } } >
618
- < Tab />
619
- < Tab />
620
- < Tab />
621
- </ Tabs > ,
622
- ) ;
623
-
624
- const tablistContainer = getByRole ( 'tablist' ) . parentElement ;
625
-
626
- Object . defineProperty ( tablistContainer , 'clientWidth' , { value : 200 - 40 * 2 } ) ;
627
- tablistContainer . scrollLeft = 10 ;
628
- Object . defineProperty ( tablistContainer , 'scrollWidth' , { value : 216 } ) ;
629
- Object . defineProperty ( tablistContainer , 'getBoundingClientRect' , {
630
- value : ( ) => ( {
631
- left : 0 ,
632
- right : 100 ,
633
- } ) ,
634
- } ) ;
635
- forceUpdate ( ) ;
636
- clock . tick ( 1000 ) ;
637
- expect ( hasLeftScrollButton ( container ) ) . to . equal ( true ) ;
638
- expect ( hasRightScrollButton ( container ) ) . to . equal ( true ) ;
639
- tablistContainer . scrollLeft = 0 ;
640
-
641
- act ( ( ) => {
642
- window . dispatchEvent ( new window . Event ( 'resize' , { } ) ) ;
643
- } ) ;
644
- clock . tick ( 166 ) ;
645
-
646
- expect ( hasLeftScrollButton ( container ) ) . to . equal ( false ) ;
647
- expect ( hasRightScrollButton ( container ) ) . to . equal ( true ) ;
648
- } ) ;
649
-
650
581
describe ( 'scroll button visibility states' , ( ) => {
651
- it ( 'should set neither left nor right scroll button state' , ( ) => {
652
- const { container, forceUpdate, getByRole } = render (
582
+ it ( 'should set neither left nor right scroll button state' , function test ( ) {
583
+ if ( isJSDOM ) {
584
+ this . skip ( ) ;
585
+ }
586
+ const { container } = render (
653
587
< Tabs value = { 0 } variant = "scrollable" scrollButtons style = { { width : 200 } } >
654
588
< Tab style = { { width : 50 , minWidth : 'auto' } } />
655
589
< Tab style = { { width : 50 , minWidth : 'auto' } } />
656
590
</ Tabs > ,
657
591
) ;
658
- const tablistContainer = getByRole ( 'tablist' ) . parentElement ;
659
-
660
- Object . defineProperty ( tablistContainer , 'clientWidth' , { value : 200 - 40 * 2 } ) ;
661
- Object . defineProperty ( tablistContainer , 'scrollWidth' , { value : 200 - 40 * 2 } ) ;
662
592
663
- forceUpdate ( ) ;
664
593
expect ( hasLeftScrollButton ( container ) ) . to . equal ( false ) ;
665
594
expect ( hasRightScrollButton ( container ) ) . to . equal ( false ) ;
666
595
} ) ;
667
596
668
- it ( 'should set only left scroll button state' , ( ) => {
669
- const { container, forceUpdate, getByRole } = render (
597
+ it ( 'should set only left scroll button state' , async function test ( ) {
598
+ if ( isJSDOM ) {
599
+ this . skip ( ) ;
600
+ }
601
+ const { container, getByRole } = render (
670
602
< Tabs value = { 0 } variant = "scrollable" scrollButtons style = { { width : 200 } } >
671
603
< Tab style = { { width : 120 , minWidth : 'auto' } } />
672
604
< Tab style = { { width : 120 , minWidth : 'auto' } } />
@@ -675,17 +607,19 @@ describe('<Tabs />', () => {
675
607
) ;
676
608
const tablistContainer = getByRole ( 'tablist' ) . parentElement ;
677
609
678
- Object . defineProperty ( tablistContainer , 'clientWidth' , { value : 200 - 40 * 2 } ) ;
679
- Object . defineProperty ( tablistContainer , 'scrollWidth' , { value : 216 } ) ;
680
- tablistContainer . scrollLeft = 96 ;
610
+ tablistContainer . scrollLeft = 240 ;
681
611
682
- forceUpdate ( ) ;
683
- expect ( hasLeftScrollButton ( container ) ) . to . equal ( true ) ;
684
- expect ( hasRightScrollButton ( container ) ) . to . equal ( false ) ;
612
+ await waitFor ( ( ) => {
613
+ expect ( hasLeftScrollButton ( container ) ) . to . equal ( true ) ;
614
+ expect ( hasRightScrollButton ( container ) ) . to . equal ( false ) ;
615
+ } ) ;
685
616
} ) ;
686
617
687
- it ( 'should set only right scroll button state' , ( ) => {
688
- const { container, forceUpdate, getByRole } = render (
618
+ it ( 'should set only right scroll button state' , async function test ( ) {
619
+ if ( isJSDOM ) {
620
+ this . skip ( ) ;
621
+ }
622
+ const { container, getByRole } = render (
689
623
< Tabs value = { 0 } variant = "scrollable" scrollButtons style = { { width : 200 } } >
690
624
< Tab />
691
625
< Tab />
@@ -694,67 +628,70 @@ describe('<Tabs />', () => {
694
628
) ;
695
629
const tablistContainer = getByRole ( 'tablist' ) . parentElement ;
696
630
697
- Object . defineProperty ( tablistContainer , 'clientWidth' , { value : 200 - 40 * 2 } ) ;
698
- Object . defineProperty ( tablistContainer , 'scrollWidth' , { value : 216 } ) ;
699
631
tablistContainer . scrollLeft = 0 ;
700
632
701
- forceUpdate ( ) ;
702
- expect ( hasLeftScrollButton ( container ) ) . to . equal ( false ) ;
703
- expect ( hasRightScrollButton ( container ) ) . to . equal ( true ) ;
633
+ await waitFor ( ( ) => {
634
+ expect ( hasLeftScrollButton ( container ) ) . to . equal ( false ) ;
635
+ expect ( hasRightScrollButton ( container ) ) . to . equal ( true ) ;
636
+ } ) ;
704
637
} ) ;
705
638
706
- it ( 'should set both left and right scroll button state' , ( ) => {
707
- const { container, forceUpdate, getByRole } = render (
639
+ it ( 'should set both left and right scroll button state' , async function test ( ) {
640
+ if ( isJSDOM ) {
641
+ this . skip ( ) ;
642
+ }
643
+ const { container, getByRole } = render (
708
644
< Tabs value = { 0 } variant = "scrollable" scrollButtons style = { { width : 200 } } >
709
645
< Tab style = { { width : 120 , minWidth : 'auto' } } />
710
646
< Tab style = { { width : 120 , minWidth : 'auto' } } />
711
647
</ Tabs > ,
712
648
) ;
713
649
const tablistContainer = getByRole ( 'tablist' ) . parentElement ;
714
650
715
- Object . defineProperty ( tablistContainer , 'clientWidth' , { value : 200 - 40 * 2 } ) ;
716
- Object . defineProperty ( tablistContainer , 'scrollWidth' , { value : 216 } ) ;
717
651
tablistContainer . scrollLeft = 5 ;
718
652
719
- forceUpdate ( ) ;
720
- expect ( hasLeftScrollButton ( container ) ) . to . equal ( true ) ;
721
- expect ( hasRightScrollButton ( container ) ) . to . equal ( true ) ;
653
+ await waitFor ( ( ) => {
654
+ expect ( hasLeftScrollButton ( container ) ) . to . equal ( true ) ;
655
+ expect ( hasRightScrollButton ( container ) ) . to . equal ( true ) ;
656
+ } ) ;
722
657
} ) ;
723
658
} ) ;
724
659
} ) ;
725
660
726
661
describe ( 'scroll button behavior' , ( ) => {
727
662
clock . withFakeTimers ( ) ;
728
663
729
- it ( 'should scroll visible items' , ( ) => {
730
- const { container, forceUpdate, getByRole, getAllByRole } = render (
664
+ it ( 'should scroll visible items' , async function test ( ) {
665
+ clock . restore ( ) ;
666
+ if ( isJSDOM ) {
667
+ this . skip ( ) ;
668
+ }
669
+ const { container, getByRole } = render (
731
670
< Tabs value = { 0 } variant = "scrollable" scrollButtons style = { { width : 200 } } >
732
671
< Tab style = { { width : 100 , minWidth : 'auto' } } />
733
672
< Tab style = { { width : 50 , minWidth : 'auto' } } />
734
673
< Tab style = { { width : 100 , minWidth : 'auto' } } />
735
674
</ Tabs > ,
736
675
) ;
737
676
const tablistContainer = getByRole ( 'tablist' ) . parentElement ;
738
- const tabs = getAllByRole ( 'tab' ) ;
739
- Object . defineProperty ( tablistContainer , 'clientWidth' , { value : 200 - 40 * 2 } ) ;
740
- Object . defineProperty ( tabs [ 0 ] , 'clientWidth' , { value : 100 } ) ;
741
- Object . defineProperty ( tabs [ 1 ] , 'clientWidth' , { value : 50 } ) ;
742
- Object . defineProperty ( tabs [ 2 ] , 'clientWidth' , { value : 100 } ) ;
743
- Object . defineProperty ( tablistContainer , 'scrollWidth' , { value : 100 + 50 + 100 } ) ;
677
+
744
678
tablistContainer . scrollLeft = 20 ;
745
- forceUpdate ( ) ;
746
- clock . tick ( 1000 ) ;
747
- expect ( hasLeftScrollButton ( container ) ) . to . equal ( true ) ;
748
- expect ( hasRightScrollButton ( container ) ) . to . equal ( true ) ;
679
+
680
+ await waitFor ( ( ) => {
681
+ expect ( hasLeftScrollButton ( container ) ) . to . equal ( true ) ;
682
+ expect ( hasRightScrollButton ( container ) ) . to . equal ( true ) ;
683
+ } ) ;
749
684
750
685
fireEvent . click ( findScrollButton ( container , 'left' ) ) ;
751
- clock . tick ( 1000 ) ;
752
- expect ( tablistContainer . scrollLeft ) . not . to . be . above ( 0 ) ;
686
+ await waitFor ( ( ) => {
687
+ expect ( tablistContainer . scrollLeft ) . not . to . be . above ( 0 ) ;
688
+ } ) ;
753
689
754
690
tablistContainer . scrollLeft = 0 ;
755
691
fireEvent . click ( findScrollButton ( container , 'right' ) ) ;
756
- clock . tick ( 1000 ) ;
757
- expect ( tablistContainer . scrollLeft ) . equal ( 100 ) ;
692
+ await waitFor ( ( ) => {
693
+ expect ( tablistContainer . scrollLeft ) . equal ( 100 ) ;
694
+ } ) ;
758
695
} ) ;
759
696
760
697
it ( 'should horizontally scroll by width of partially visible item' , ( ) => {
@@ -1397,4 +1334,76 @@ describe('<Tabs />', () => {
1397
1334
] ) ;
1398
1335
} ) ;
1399
1336
} ) ;
1337
+
1338
+ describe ( 'dynamic tabs' , ( ) => {
1339
+ const pause = ( timeout ) =>
1340
+ new Promise ( ( resolve ) => {
1341
+ setTimeout ( ( ) => {
1342
+ resolve ( ) ;
1343
+ } , timeout ) ;
1344
+ } ) ;
1345
+
1346
+ // https://github.com/mui/material-ui/issues/31936
1347
+ it ( 'should not show scroll buttons if a tab added or removed in vertical mode' , async function test ( ) {
1348
+ if ( isJSDOM ) {
1349
+ this . skip ( ) ;
1350
+ }
1351
+ function DynamicTabs ( ) {
1352
+ const [ value , setValue ] = React . useState ( 0 ) ;
1353
+ const handleChange = ( event , newValue ) => {
1354
+ setValue ( newValue ) ;
1355
+ } ;
1356
+ const [ tabs , setTabs ] = React . useState ( [ 'item1' , 'item2' ] ) ;
1357
+ return (
1358
+ < React . Fragment >
1359
+ < button
1360
+ data-testid = "add"
1361
+ onClick = { ( ) => {
1362
+ setTabs ( [ ...tabs , `item${ tabs . length + 1 } ` ] ) ;
1363
+ } }
1364
+ >
1365
+ add
1366
+ </ button >
1367
+ < button
1368
+ data-testid = "delete"
1369
+ onClick = { ( ) => {
1370
+ setTabs ( tabs . slice ( 0 , tabs . length - 1 ) ) ;
1371
+ setValue ( 0 ) ;
1372
+ } }
1373
+ >
1374
+ delete
1375
+ </ button >
1376
+ < Tabs
1377
+ onChange = { handleChange }
1378
+ value = { value }
1379
+ orientation = "vertical"
1380
+ variant = "scrollable"
1381
+ scrollButtons
1382
+ style = { { width : '260px' } }
1383
+ >
1384
+ { tabs . map ( ( label , index ) => (
1385
+ < Tab key = { `tab${ index } ` } label = { label } />
1386
+ ) ) }
1387
+ </ Tabs >
1388
+ </ React . Fragment >
1389
+ ) ;
1390
+ }
1391
+ const { container, getByTestId, getAllByRole } = render ( < DynamicTabs /> ) ;
1392
+ const addButton = getByTestId ( 'add' ) ;
1393
+ const deleteButton = getByTestId ( 'delete' ) ;
1394
+
1395
+ fireEvent . click ( addButton ) ;
1396
+ expect ( hasLeftScrollButton ( container ) ) . to . equal ( false ) ;
1397
+ expect ( hasRightScrollButton ( container ) ) . to . equal ( false ) ;
1398
+
1399
+ const tabs = getAllByRole ( 'tab' ) ;
1400
+ const lastTab = tabs [ tabs . length - 1 ] ;
1401
+ fireEvent . click ( lastTab ) ;
1402
+ await pause ( 400 ) ;
1403
+
1404
+ fireEvent . click ( deleteButton ) ;
1405
+ expect ( hasLeftScrollButton ( container ) ) . to . equal ( false ) ;
1406
+ expect ( hasRightScrollButton ( container ) ) . to . equal ( false ) ;
1407
+ } ) ;
1408
+ } ) ;
1400
1409
} ) ;
0 commit comments