@@ -623,6 +623,196 @@ test.describe('Keyboard Behavior', () => {
623623 } ) ;
624624 } ) ;
625625
626+ test . describe ( 'looping' , ( ) => {
627+ test . describe ( 'loop disabled' , ( ) => {
628+ test ( `GIVEN an open basic select
629+ AND the last option is data-highlighted
630+ WHEN the down key is pressed
631+ THEN data-highlighted should stay on the last option` , async ( { page } ) => {
632+ const { getTrigger, getOptions, openListbox } = await setup (
633+ page ,
634+ 'select-hero-test' ,
635+ ) ;
636+
637+ // initially last option is highlighted
638+ await openListbox ( 'Enter' ) ;
639+ await getTrigger ( ) . focus ( ) ;
640+ await getTrigger ( ) . press ( 'End' ) ;
641+ const options = await getOptions ( ) ;
642+ await expect ( options [ options . length - 1 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
643+
644+ await getTrigger ( ) . focus ( ) ;
645+ await getTrigger ( ) . press ( 'ArrowDown' ) ;
646+ await expect ( options [ options . length - 1 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
647+ } ) ;
648+
649+ test ( `GIVEN an open basic select
650+ AND the first option is data-highlighted
651+ WHEN the up arrow key is pressed
652+ THEN data-highlighted should stay on the first option` , async ( { page } ) => {
653+ const { getTrigger, getOptions, openListbox } = await setup (
654+ page ,
655+ 'select-hero-test' ,
656+ ) ;
657+
658+ await openListbox ( 'Enter' ) ;
659+ const options = await getOptions ( ) ;
660+ await expect ( options [ 0 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
661+ await getTrigger ( ) . focus ( ) ;
662+ await getTrigger ( ) . press ( 'ArrowUp' ) ;
663+ await expect ( options [ 0 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
664+ } ) ;
665+
666+ test ( `GIVEN a closed basic select
667+ AND the last option is selected
668+ WHEN the right arrow key is pressed
669+ THEN it should stay on the last option` , async ( { page } ) => {
670+ const { getTrigger, getOptions, getListbox, openListbox } = await setup (
671+ page ,
672+ 'select-hero-test' ,
673+ ) ;
674+
675+ // initially last option is highlighted & listbox closed
676+ await openListbox ( 'Enter' ) ;
677+ await getTrigger ( ) . focus ( ) ;
678+ await getTrigger ( ) . press ( 'End' ) ;
679+ const options = await getOptions ( ) ;
680+ await expect ( options [ options . length - 1 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
681+ await getTrigger ( ) . press ( 'Enter' ) ;
682+ await expect ( options [ options . length - 1 ] ) . toHaveAttribute (
683+ 'aria-selected' ,
684+ 'true' ,
685+ ) ;
686+ await expect ( getListbox ( ) ) . toBeHidden ( ) ;
687+
688+ await getTrigger ( ) . focus ( ) ;
689+ await getTrigger ( ) . press ( 'ArrowRight' ) ;
690+ await expect ( options [ options . length - 1 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
691+ await expect ( options [ options . length - 1 ] ) . toHaveAttribute (
692+ 'aria-selected' ,
693+ 'true' ,
694+ ) ;
695+ } ) ;
696+
697+ test ( `GIVEN a closed basic select
698+ AND the first option is selected
699+ WHEN the left arrow key is pressed
700+ THEN it should stay on the first option` , async ( { page } ) => {
701+ const { getTrigger, getOptions, getListbox, openListbox } = await setup (
702+ page ,
703+ 'select-hero-test' ,
704+ ) ;
705+
706+ // initially first option is highlighted & listbox closed
707+ await openListbox ( 'Enter' ) ;
708+ await getTrigger ( ) . focus ( ) ;
709+ await getTrigger ( ) . press ( 'Enter' ) ;
710+ const options = await getOptions ( ) ;
711+ await expect ( options [ 0 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
712+ await expect ( options [ 0 ] ) . toHaveAttribute ( 'aria-selected' , 'true' ) ;
713+ await expect ( getListbox ( ) ) . toBeHidden ( ) ;
714+
715+ await getTrigger ( ) . focus ( ) ;
716+ await getTrigger ( ) . press ( 'ArrowLeft' ) ;
717+ await expect ( options [ 0 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
718+ await expect ( options [ 0 ] ) . toHaveAttribute ( 'aria-selected' , 'true' ) ;
719+ } ) ;
720+ } ) ;
721+
722+ test . describe ( 'loop enabled' , ( ) => {
723+ test ( `GIVEN an open select with loop enabled
724+ AND the last option is data-highlighted
725+ WHEN the down arrow key is pressed
726+ THEN the first option should have data-highlighted` , async ( { page } ) => {
727+ const { getTrigger, getOptions, openListbox } = await setup (
728+ page ,
729+ 'select-loop-test' ,
730+ ) ;
731+
732+ // initially last option is highlighted
733+ await openListbox ( 'Enter' ) ;
734+ await getTrigger ( ) . focus ( ) ;
735+ await getTrigger ( ) . press ( 'End' ) ;
736+ const options = await getOptions ( ) ;
737+ await expect ( options [ options . length - 1 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
738+
739+ await getTrigger ( ) . focus ( ) ;
740+ await getTrigger ( ) . press ( 'ArrowDown' ) ;
741+ await expect ( options [ 0 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
742+ } ) ;
743+
744+ test ( `GIVEN an open select with loop enabled
745+ AND the first option is data-highlighted
746+ WHEN the up arrow key is pressed
747+ THEN the last option should have data-highlighted` , async ( { page } ) => {
748+ const { getTrigger, getOptions, openListbox } = await setup (
749+ page ,
750+ 'select-loop-test' ,
751+ ) ;
752+
753+ // initially last option is highlighted
754+ await openListbox ( 'Enter' ) ;
755+ const options = await getOptions ( ) ;
756+ await expect ( options [ 0 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
757+
758+ await getTrigger ( ) . focus ( ) ;
759+ await getTrigger ( ) . press ( 'ArrowUp' ) ;
760+ await expect ( options [ options . length - 1 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
761+ } ) ;
762+
763+ test ( `GIVEN a closed select with loop enabled
764+ AND the last option is selected
765+ WHEN the right arrow key is pressed
766+ THEN it should loop to the first option` , async ( { page } ) => {
767+ const { getTrigger, getOptions, openListbox } = await setup (
768+ page ,
769+ 'select-loop-test' ,
770+ ) ;
771+
772+ // initially last option is highlighted
773+ await openListbox ( 'Enter' ) ;
774+ await getTrigger ( ) . focus ( ) ;
775+ await getTrigger ( ) . press ( 'End' ) ;
776+ await getTrigger ( ) . press ( 'Enter' ) ;
777+ const options = await getOptions ( ) ;
778+ await expect ( options [ options . length - 1 ] ) . toHaveAttribute (
779+ 'aria-selected' ,
780+ 'true' ,
781+ ) ;
782+
783+ await getTrigger ( ) . focus ( ) ;
784+ await getTrigger ( ) . press ( 'ArrowRight' ) ;
785+ await expect ( options [ 0 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
786+ await expect ( options [ 0 ] ) . toHaveAttribute ( 'aria-selected' , 'true' ) ;
787+ } ) ;
788+
789+ test ( `GIVEN a closed select with loop enabled
790+ AND the first option is selected
791+ WHEN the right arrow key is pressed
792+ THEN it should loop to the first option` , async ( { page } ) => {
793+ const { getTrigger, getOptions, openListbox } = await setup (
794+ page ,
795+ 'select-loop-test' ,
796+ ) ;
797+
798+ // initially select first option
799+ await openListbox ( 'Enter' ) ;
800+ await getTrigger ( ) . focus ( ) ;
801+ await getTrigger ( ) . press ( 'Enter' ) ;
802+ const options = await getOptions ( ) ;
803+ await expect ( options [ 0 ] ) . toHaveAttribute ( 'aria-selected' , 'true' ) ;
804+
805+ await getTrigger ( ) . focus ( ) ;
806+ await getTrigger ( ) . press ( 'ArrowLeft' ) ;
807+ await expect ( options [ options . length - 1 ] ) . toHaveAttribute ( 'data-highlighted' ) ;
808+ await expect ( options [ options . length - 1 ] ) . toHaveAttribute (
809+ 'aria-selected' ,
810+ 'true' ,
811+ ) ;
812+ } ) ;
813+ } ) ;
814+ } ) ;
815+
626816 test ( `GIVEN an open select with multiple groups and a scrollable listbox
627817 AND the last option is not visible
628818 WHEN the end key is pressed
0 commit comments