diff --git a/tests/menu-button-actions/data/assertions.csv b/tests/menu-button-actions/data/assertions.csv
new file mode 100644
index 000000000..5acb76347
--- /dev/null
+++ b/tests/menu-button-actions/data/assertions.csv
@@ -0,0 +1,15 @@
+assertionId,priority,assertionStatement,assertionPhrase,refIds
+nameActions,1,"Name of the menu button, 'Actions', is conveyed","convey name of the menu button, 'Actions'",button
+nameMenuActions,3,"Name of the menu, 'Actions', is conveyed","convey name of the menu, 'Actions'",menu aria-labelledby
+nameFocusedItemAction1,1,"Name of the focused item, 'Action 1', is conveyed","convey name of the focused item, 'Action 1'",menuitem
+nameFocusedItemAction2,1,"Name of the focused item, 'Action 2', is conveyed","convey name of the focused item, 'Action 2'",menuitem
+nameFocusedItemAction4,1,"Name of the focused item, 'Action 4', is conveyed","convey name of the focused item, 'Action 4'",menuitem
+numberItemsMenu4,2,"Number of items in the menu,'(4', is conveyed","convey number of items in the menu, '4'",aria-setsize
+roleFocusedItemMenuItem,2,"Role of the focused item, 'menu item', is conveyed","convey role of the focused item, 'menu item'",menuitem
+roleMenu,3,Role 'menu' is conveyed,convey role 'menu',menu
+roleMenuButton,1,Role 'menu button' is conveyed,convey role 'menu button',button aria-haspopup
+stateCollapsed,1,State 'collapsed' is conveyed,convey state 'collapsed',aria-expanded
+interactionModeEnabled,2,Screen reader switched from reading mode to interaction mode|{screenReader} switched from {readingMode} to {interactionMode},switch from reading mode to interaction mode|switch from {readingMode} to {interactionMode},
+positionFocusedItemMenu1,2,"Position of the focused item in the menu, '1', is conveyed","convey position of the focused item in the menu, '1'",aria-posinset
+positionFocusedItemMenu2,2,"Position of the focused item in the menu, '2', is conveyed","convey position of the focused item in the menu, '2'",aria-posinset
+positionFocusedItemMenu4,2,"Position of the focused item in the menu, '4', is conveyed","convey position of the focused item in the menu, '4'",aria-posinset
diff --git a/tests/menu-button-actions/data/commands.csv b/tests/menu-button-actions/data/commands.csv
deleted file mode 100644
index 888bd5281..000000000
--- a/tests/menu-button-actions/data/commands.csv
+++ /dev/null
@@ -1,42 +0,0 @@
-testId,task,mode,at,commandA,commandB,commandC,commandD,commandE,commandF
-1,navigate forwards to menu button,reading,JAWS,B,F,TAB,DOWN,,
-1,navigate forwards to menu button,reading,NVDA,B,F,TAB,DOWN,,
-2,navigate backwards to menu button,reading,JAWS,SHIFT_B,SHIFT_F,SHIFT_TAB,UP,,
-2,navigate backwards to menu button,reading,NVDA,SHIFT_B,SHIFT_F,SHIFT_TAB,UP,,
-3,navigate forwards to menu button,interaction,JAWS,TAB,,,,,
-3,navigate forwards to menu button,interaction,NVDA,TAB,,,,,
-4,navigate backwards to menu button,interaction,JAWS,SHIFT_TAB,,,,,
-4,navigate backwards to menu button,interaction,NVDA,SHIFT_TAB,,,,,
-5,navigate forwards to menu button,interaction,voiceover_macos,TAB,CTRL_OPT_RIGHT,CTRL_OPT_CMD_J,,,
-6,navigate backwards to menu button,interaction,voiceover_macos,SHIFT_TAB,CTRL_OPT_LEFT,SHIFT_CTRL_OPT_CMD_J,,,
-7,read information about menu button,reading,JAWS,INS_TAB,INS_UP,,,,
-7,read information about menu button,reading,NVDA,INS_TAB,INS_UP,,,,
-8,read information about menu button,interaction,JAWS,INS_TAB,INS_UP,,,,
-8,read information about menu button,interaction,NVDA,INS_TAB,INS_UP,,,,
-9,read information about menu button,interaction,voiceover_macos,CTRL_OPT_F3,CTRL_OPT_F4,,,,
-10,open menu,reading,JAWS,SPACE,ENTER,,,,
-10,open menu,reading,NVDA,SPACE,ENTER,,,,
-11,open menu,interaction,JAWS,SPACE,ENTER,DOWN,,,
-11,open menu,interaction,NVDA,SPACE,ENTER,DOWN,,,
-12,open menu,interaction,voiceover_macos,CTRL_OPT_SPACE,SPACE,ENTER,DOWN,,
-13,open menu to last item,interaction,JAWS,UP,,,,,
-13,open menu to last item,interaction,NVDA,UP,,,,,
-14,open menu to last item,interaction,voiceover_macos,UP,,,,,
-15,read information about menu item,interaction,JAWS,INS_TAB,INS_UP,,,,
-15,read information about menu item,interaction,NVDA,INS_TAB,INS_UP,,,,
-16,read information about menu item,interaction,voiceover_macos,CTRL_OPT_F3,CTRL_OPT_F4,,,,
-17,navigate to first item in menu,interaction,JAWS,HOME,DOWN,,,,
-17,navigate to first item in menu,interaction,NVDA,HOME,DOWN,,,,
-18,navigate to first item in menu,interaction,voiceover_macos,HOME,DOWN,,,,
-19,navigate to last item in menu,interaction,JAWS,END,UP,,,,
-19,navigate to last item in menu,interaction,NVDA,END,UP,,,,
-20,navigate to last item in menu,interaction,voiceover_macos,END,UP,,,,
-21,navigate to item in menu by typing character,interaction,JAWS,A,,,,,
-21,navigate to item in menu by typing character,interaction,NVDA,A,,,,,
-22,navigate to item in menu by typing character,interaction,voiceover_macos,A,,,,,
-23,activate menu item,interaction,JAWS,ENTER,,,,,
-23,activate menu item,interaction,NVDA,ENTER,,,,,
-24,activate menu item,interaction,voiceover_macos,CTRL_OPT_SPACE,ENTER,,,,
-25,close menu,interaction,JAWS,ESC,,,,,
-25,close menu,interaction,NVDA,ESC,,,,,
-26,close menu,interaction,voiceover_macos,ESC,,,,,
diff --git a/tests/menu-button-actions/data/jaws-commands.csv b/tests/menu-button-actions/data/jaws-commands.csv
new file mode 100644
index 000000000..3001af1ef
--- /dev/null
+++ b/tests/menu-button-actions/data/jaws-commands.csv
@@ -0,0 +1,32 @@
+testId,command,settings,assertionExceptions,presentationNumber
+navForwardsToMenuButton,b,virtualCursor,,1
+navForwardsToMenuButton,f,virtualCursor,,1.1
+navForwardsToMenuButton,tab,virtualCursor,2:interactionModeEnabled,1.2
+navForwardsToMenuButton,down,virtualCursor,,1.3
+navBackToMenuButton,shift+b,virtualCursor,,2
+navBackToMenuButton,shift+f,virtualCursor,,2.1
+navBackToMenuButton,shift+tab,virtualCursor,2:interactionModeEnabled,2.2
+navBackToMenuButton,up,virtualCursor,,2.3
+navForwardsToMenuButton,tab,pcCursor,,3
+navBackToMenuButton,shift+tab,pcCursor,,4
+reqInfoAboutMenuButton,ins+tab,virtualCursor,,7
+reqInfoAboutMenuButton,ins+up,virtualCursor,,7.1
+reqInfoAboutMenuButton,ins+tab,pcCursor,,8
+reqInfoAboutMenuButton,ins+up,pcCursor,,8.1
+openMenu,space,virtualCursor,2:interactionModeEnabled,10
+openMenu,enter,virtualCursor,2:interactionModeEnabled,10.1
+openMenu,space,pcCursor,,11
+openMenu,enter,pcCursor,,11.1
+openMenu,down,pcCursor,,11.2
+openMenuToLastItem,up,pcCursor,,13
+reqInfoAboutMenuItem,ins+tab,virtualCursor,,15
+reqInfoAboutMenuItem,ins+up,virtualCursor,0:positionFocusedItemMenu1 0:numberItemsMenu4 0:nameMenuActions 0:roleMenu,15.1
+reqInfoAboutMenuItem,ins+tab,pcCursor,,15.2
+reqInfoAboutMenuItem,ins+up,pcCursor,0:positionFocusedItemMenu1 0:numberItemsMenu4 0:nameMenuActions 0:roleMenu,15.3
+navToFirstItemMenu,home,pcCursor,,17
+navToFirstItemMenu,down,pcCursor,,17.1
+navToLastItemMenu,end,pcCursor,,19
+navToLastItemMenu,up,pcCursor,,19.1
+navToItemMenuByTypingCharacter,a,pcCursor,,21
+activateMenuItem,enter,pcCursor,,23
+closeMenu,esc,pcCursor,,25
diff --git a/tests/menu-button-actions/data/nvda-commands.csv b/tests/menu-button-actions/data/nvda-commands.csv
new file mode 100644
index 000000000..7fd0f003f
--- /dev/null
+++ b/tests/menu-button-actions/data/nvda-commands.csv
@@ -0,0 +1,32 @@
+testId,command,settings,assertionExceptions,presentationNumber
+navForwardsToMenuButton,b,browseMode,,1
+navForwardsToMenuButton,f,browseMode,,1.1
+navForwardsToMenuButton,tab,browseMode,2:interactionModeEnabled,1.2
+navForwardsToMenuButton,down,browseMode,,1.3
+navBackToMenuButton,shift+b,browseMode,,2
+navBackToMenuButton,shift+f,browseMode,,2.1
+navBackToMenuButton,shift+tab,browseMode,2:interactionModeEnabled,2.2
+navBackToMenuButton,up,browseMode,,2.3
+navForwardsToMenuButton,tab,focusMode,,3
+navBackToMenuButton,shift+tab,focusMode,,4
+reqInfoAboutMenuButton,ins+tab,browseMode,,7
+reqInfoAboutMenuButton,ins+up,browseMode,,7.1
+reqInfoAboutMenuButton,ins+tab,focusMode,,8
+reqInfoAboutMenuButton,ins+up,focusMode,,8.1
+openMenu,space,browseMode,2:interactionModeEnabled,10
+openMenu,enter,browseMode,2:interactionModeEnabled,10.1
+openMenu,space,focusMode,,11
+openMenu,enter,focusMode,,11.1
+openMenu,down,focusMode,,11.2
+openMenuToLastItem,up,focusMode,,13
+reqInfoAboutMenuItem,ins+tab,browseMode,,15
+reqInfoAboutMenuItem,ins+up,browseMode,0:positionFocusedItemMenu1 0:numberItemsMenu4 0:nameMenuActions 0:roleMenu,15.1
+reqInfoAboutMenuItem,ins+tab,focusMode,,15.2
+reqInfoAboutMenuItem,ins+up,focusMode,0:positionFocusedItemMenu1 0:numberItemsMenu4 0:nameMenuActions 0:roleMenu,15.3
+navToFirstItemMenu,home,focusMode,,17
+navToFirstItemMenu,down,focusMode,,17.1
+navToLastItemMenu,end,focusMode,,19
+navToLastItemMenu,up,focusMode,,19.1
+navToItemMenuByTypingCharacter,a,focusMode,,21
+activateMenuItem,enter,focusMode,,23
+closeMenu,esc,focusMode,,25
diff --git a/tests/menu-button-actions/data/references.csv b/tests/menu-button-actions/data/references.csv
index 1c2258b36..74007c399 100644
--- a/tests/menu-button-actions/data/references.csv
+++ b/tests/menu-button-actions/data/references.csv
@@ -1,13 +1,16 @@
-refId,value
-author,Isabel Del Castillo
-authorEmail,isa.delcastillo5@gmail.com
-title,Action Menu Button Example Using element.focus()
-reference,reference/2021-1-14_12348/menu-button-actions.html
-designPattern,https://w3c.github.io/aria-practices/#menubutton
-example,https://w3c.github.io/aria-practices/examples/menu-button/menu-button-actions.html
-menu,https://w3c.github.io/aria/#menu
-menuitem,https://w3c.github.io/aria/#menuitem
-aria-haspopup,https://w3c.github.io/aria/#aria-haspopup
-aria-controls,https://w3c.github.io/aria/#aria-controls
-aria-labelledby,https://w3c.github.io/aria/#aria-labelledby
-aria-expanded,https://w3c.github.io/aria/#aria-expanded
+refId,type,value,linkText
+author,metadata,Isabel Del Castillo,
+authorEmail,metadata,isa.delcastillo5@gmail.com,
+title,metadata,Action Menu Button Example Using element.focus(),
+reference,metadata,reference/2024-8-28_1295/menu-button-actions.html,Test Case Page for Action Menu Button Example Using element.focus()
+designPattern,metadata,https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/,APG Pattern: Menu Button
+example,metadata,https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/examples/menu-button-actions-active-descendant/,APG Example: Actions Menu Button Using element.focus()
+menu,aria,menu,menu
+menuitem,aria,menuitem,menuitem
+aria-haspopup,aria,aria-haspopup,aria-haspopup
+aria-controls,aria,aria-controls,aria-controls
+aria-labelledby,aria,aria-labelledby,aria-labelledby
+aria-expanded,aria,aria-expanded,aria-expanded
+aria-posinset,aria,aria-posinset,aria-posinset
+aria-setsize,aria,aria-setsize,aria-setsize
+button,htmlAam,button,button
diff --git a/tests/menu-button-actions/data/scripts.csv b/tests/menu-button-actions/data/scripts.csv
new file mode 100644
index 000000000..25e1351da
--- /dev/null
+++ b/tests/menu-button-actions/data/scripts.csv
@@ -0,0 +1,6 @@
+setupScript,setupScriptDescription
+openMenuAndSetFocusToFirstItem,"opens the menu, and sets focus on 'Action 1'"
+openMenuAndSetFocusToLastItem,"opens the menu, and sets focus on 'Action 4'"
+setFocusAfterMenuButton,sets focus on a link after the menu button
+setFocusBeforeMenuButton,sets focus on a link before the menu button
+setFocusOnMenuButton,sets focus on the menu button
diff --git a/tests/menu-button-actions/data/tests.csv b/tests/menu-button-actions/data/tests.csv
index bcf7dfb4a..e973b9dcf 100644
--- a/tests/menu-button-actions/data/tests.csv
+++ b/tests/menu-button-actions/data/tests.csv
@@ -1,27 +1,12 @@
-testId,title,appliesTo,mode,task,setupScript,setupScriptDescription,refs,instructions,assertion1,assertion2,assertion3,assertion4,assertion5,assertion6,assertion7
-1,Navigate forwards to a menu button in reading mode,"JAWS,NVDA",reading,navigate forwards to menu button,setFocusBeforeMenuButton,sets focus on a link before the menu button,aria-haspopup,Navigate to the menu button.,Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
-2,Navigate backwards to a menu button in reading mode,"JAWS,NVDA",reading,navigate backwards to menu button,setFocusAfterMenuButton,sets focus on a link after the menu button,aria-haspopup,Navigate to the menu button.,Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
-3,Navigate forwards to a menu button in interaction mode,"JAWS,NVDA",interaction,navigate forwards to menu button,setFocusBeforeMenuButton,sets focus on a link before the menu button,aria-haspopup,Navigate to the menu button.,Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
-4,Navigate backwards to a menu button in interaction mode,"JAWS,NVDA",interaction,navigate backwards to menu button,setFocusAfterMenuButton,sets focus on a link after the menu button,aria-haspopup,Navigate to the menu button.,Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
-5,Navigate forwards to a menu button,voiceover_macos,interaction,navigate forwards to menu button,setFocusBeforeMenuButton,sets focus on a link before the menu button,aria-haspopup,Navigate to the menu button.,Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
-6,Navigate backwards to a menu button,voiceover_macos,interaction,navigate backwards to menu button,setFocusAfterMenuButton,sets focus on a link after the menu button,aria-haspopup,Navigate to the menu button.,Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
-7,Read information about a menu button in reading mode,"JAWS,NVDA",reading,read information about menu button,setFocusOnMenuButton,sets focus on the menu button,aria-haspopup,"With the reading cursor on the 'Actions' menu button, read information about the menu button.",Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
-8,Read information about a menu button in interaction mode,"JAWS,NVDA",interaction,read information about menu button,setFocusOnMenuButton,sets focus on the menu button,aria-haspopup,"With focus on the 'Actions' menu button, read information about the menu button.",Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
-9,Read information about a menu button,voiceover_macos,interaction,read information about menu button,setFocusOnMenuButton,sets focus on the menu button,aria-haspopup,"With focus on the 'Actions' menu button, read information about the menu button.",Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
-10,Open a menu in reading mode,"JAWS,NVDA",reading,open menu,setFocusOnMenuButton,sets focus on the menu button,menu aria-labelledby menuitem,"With the reading cursor on the 'Actions' menu button, open the menu.",Role 'menu' is conveyed,Name 'Actions' is conveyed,"2:Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 1', is conveyed",Position of the focused item in the menu (1) is conveyed,Number of items in the menu (4) is conveyed,
-11,Open a menu in interaction mode,"JAWS,NVDA",interaction,open menu,setFocusOnMenuButton,sets focus on the menu button,menu aria-labelledby menuitem,"With focus on the 'Actions' menu button, open the menu.",Role 'menu' is conveyed,Name 'Actions' is conveyed,"2:Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 1', is conveyed",Position of the focused item in the menu (1) is conveyed,Number of items in the menu (4) is conveyed,
-12,Open a menu,voiceover_macos,interaction,Open menu,setFocusOnMenuButton,sets focus on the menu button,menu aria-labelledby menuitem,"With focus on the 'Actions' menu button, open the menu.",Role 'menu' is conveyed,Name 'Actions' is conveyed,"2:Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 1', is conveyed",Position of the focused item in the menu (1) is conveyed,Number of items in the menu (4) is conveyed,
-13,Open a menu to the last item in interaction mode,"JAWS,NVDA",interaction,Open menu to last item,setFocusOnMenuButton,sets focus on the menu button,menu aria-labelledby menuitem,"With focus on the 'Actions' menu button, open the menu.",Role 'menu' is conveyed,Name 'Actions' is conveyed,"2:Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 4', is conveyed",Position of the focused item in the menu (4) is conveyed,Number of items in the menu (4) is conveyed,
-14,Open a menu to the last item,voiceover_macos,interaction,Open menu to last item,setFocusOnMenuButton,sets focus on the menu button,menu aria-labelledby menuitem,"With focus on the 'Actions' menu button, open the menu.",Role 'menu' is conveyed,Name 'Actions' is conveyed,"2:Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 4', is conveyed",Position of the focused item in the menu (4) is conveyed,Number of items in the menu (4) is conveyed,
-15,Read information about a menu item in interaction mode,"JAWS,NVDA",interaction,Read information about menu item,openMenuAndSetFocusToFirstItem,"opens the menu, and sets focus on 'Action 1'",menuitem,"With focus on the 'Action 1' menu item, read information about the menu item.","Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 1', is conveyed",Position of the focused item in the menu (1) is conveyed,Number of items in the menu (4) is conveyed,,,
-16,Read information about a menu item,voiceover_macos,interaction,Read information about menu item,openMenuAndSetFocusToFirstItem,"opens the menu, and sets focus on 'Action 1'",menuitem,"With focus on the 'Action 1' menu item, read information about the menu item.","Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 1', is conveyed",Position of the focused item in the menu (1) is conveyed,Number of items in the menu (4) is conveyed,,,
-17,Navigate to the first item in a menu in interaction mode,"JAWS,NVDA",interaction,navigate to first item in menu,openMenuAndSetFocusToLastItem,"opens the menu, and sets focus on 'Action 4'",menuitem,"With focus on the 'Action 4' menu item, navigate to the first menu item.","2:Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 1', is conveyed",Position of the focused item in the menu (1) is conveyed,Number of items in the menu (4) is conveyed,,,
-18,Navigate to the first item in a menu,voiceover_macos,interaction,navigate to first item in menu,openMenuAndSetFocusToLastItem,"opens the menu, and sets focus on 'Action 4'",menuitem,"With focus on the 'Action 4' menu item, navigate to the first menu item.","2:Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 1', is conveyed",Position of the focused item in the menu (1) is conveyed,Number of items in the menu (4) is conveyed,,,
-19,Navigate to the last item in a menu in interaction mode,"JAWS,NVDA",interaction,navigate to last item in menu,openMenuAndSetFocusToFirstItem,"opens the menu, and sets focus on 'Action 1'",menuitem,"With focus on the 'Action 1' menu item, navigate to the last menu item.","2:Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 4', is conveyed",Position of the focused item in the menu (4) is conveyed,Number of items in the menu (4) is conveyed,,,
-20,Navigate to the last item in a menu,voiceover_macos,interaction,navigate to last item in menu,openMenuAndSetFocusToFirstItem,"opens the menu, and sets focus on 'Action 1'",menuitem,"With focus on the 'Action 1' menu item, navigate to the last menu item.","2:Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 4', is conveyed",Position of the focused item in the menu (4) is conveyed,Number of items in the menu (4) is conveyed,,,
-21,Navigate to an item in a menu by typing a character in interaction mode,"JAWS,NVDA",interaction,navigate to item in menu by typing character,openMenuAndSetFocusToFirstItem,"opens the menu, and sets focus on 'Action 1'",menuitem,"With focus on the 'Action 1' menu item, type a character to navigate to a different menu item.","2:Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 2', is conveyed",Position of the focused item in the menu (2) is conveyed,Number of items in the menu (4) is conveyed,,,
-22,Navigate to an item in a menu by typing a character,voiceover_macos,interaction,navigate to item in menu by typing character,openMenuAndSetFocusToFirstItem,"opens the menu, and sets focus on 'Action 1'",menuitem,"With focus on the 'Action 1' menu item, type a character to navigate to a different menu item.","2:Role of the focused item, 'menu item', is conveyed","Name of the focused item, 'Action 2', is conveyed",Position of the focused item in the menu (2) is conveyed,Number of items in the menu (4) is conveyed,,,
-23,Activate a menu item in interaction mode,"JAWS,NVDA",interaction,activate menu item,openMenuAndSetFocusToFirstItem,"opens the menu, and sets focus on 'Action 1'",aria-haspopup,"With focus on the 'Action 1' menu item, activate the menu item.",Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
-24,Activate a menu item,voiceover_macos,interaction,activate menu item,openMenuAndSetFocusToFirstItem,"opens the menu, and sets focus on 'Action 1'",aria-haspopup,"With focus on the 'Action 1' menu item, activate the menu item.",Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
-25,Close a menu in interaction mode,"JAWS,NVDA",interaction,close menu,openMenuAndSetFocusToFirstItem,"opens the menu, and sets focus on 'Action 1'",aria-haspopup,"With focus on the 'Action 1' menu item, close the menu.",Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
-26,Close a menu,voiceover_macos,interaction,close menu,openMenuAndSetFocusToFirstItem,"opens the menu, and sets focus on 'Action 1'",aria-haspopup,"With focus on the 'Action 1' menu item, close the menu.",Role 'menu button' is conveyed,Name 'Actions' is conveyed,,,,,
+testId,title,presentationNumber,setupScript,instructions,assertions
+navForwardsToMenuButton,Navigate forwards to a menu button,5,setFocusBeforeMenuButton,"Starting at the 'Navigate forwards from here' link, navigate to the menu button.",nameActions roleMenuButton stateCollapsed 0:interactionModeEnabled
+navBackToMenuButton,Navigate backwards to a menu button,6,setFocusAfterMenuButton,"Starting at the 'Navigate backwards from here' link, navigate to the menu button.",nameActions roleMenuButton stateCollapsed 0:interactionModeEnabled
+reqInfoAboutMenuButton,Request information about a menu button,9,setFocusOnMenuButton,"Starting at the 'Actions' menu button, read information about the menu button.",nameActions roleMenuButton stateCollapsed
+openMenu,Open a menu,12,setFocusOnMenuButton,"Starting at the 'Actions' menu button, open the menu.",nameFocusedItemAction1 3:roleFocusedItemMenuItem positionFocusedItemMenu1 numberItemsMenu4 nameMenuActions roleMenu 0:interactionModeEnabled
+openMenuToLastItem,Open a menu to the last item,14,setFocusOnMenuButton,"Starting at the 'Actions' menu button, open the menu.",nameFocusedItemAction4 3:roleFocusedItemMenuItem positionFocusedItemMenu4 numberItemsMenu4 nameMenuActions roleMenu
+reqInfoAboutMenuItem,Request information about a menu item,16,openMenuAndSetFocusToFirstItem,"Starting at the 'Action 1' menu item, read information about the menu item.",nameFocusedItemAction1 roleFocusedItemMenuItem positionFocusedItemMenu1 numberItemsMenu4 nameMenuActions roleMenu
+navToFirstItemMenu,Navigate to the first item in a menu,18,openMenuAndSetFocusToLastItem,"Starting at the 'Action 4' menu item, navigate to the first menu item.",nameFocusedItemAction1 3:roleFocusedItemMenuItem positionFocusedItemMenu1 numberItemsMenu4
+navToLastItemMenu,Navigate to the last item in a menu,20,openMenuAndSetFocusToFirstItem,"Starting at the 'Action 1' menu item, navigate to the last menu item.",nameFocusedItemAction4 3:roleFocusedItemMenuItem positionFocusedItemMenu4 numberItemsMenu4
+navToItemMenuByTypingCharacter,Navigate to an item in a menu by typing a character,22,openMenuAndSetFocusToFirstItem,"Starting at the 'Action 1' menu item, type a character to navigate to a different menu item.",nameFocusedItemAction2 3:roleFocusedItemMenuItem positionFocusedItemMenu2 numberItemsMenu4
+activateMenuItem,Activate a menu item,24,openMenuAndSetFocusToFirstItem,"Starting at the 'Action 1' menu item, activate the menu item.",nameActions roleMenuButton stateCollapsed
+closeMenu,Close a menu,26,openMenuAndSetFocusToFirstItem,"Starting at the 'Action 1' menu item, close the menu.",nameActions roleMenuButton stateCollapsed
diff --git a/tests/menu-button-actions/data/voiceover_macos-commands.csv b/tests/menu-button-actions/data/voiceover_macos-commands.csv
new file mode 100644
index 000000000..4e5cf6515
--- /dev/null
+++ b/tests/menu-button-actions/data/voiceover_macos-commands.csv
@@ -0,0 +1,26 @@
+testId,command,settings,assertionExceptions,presentationNumber
+navForwardsToMenuButton,tab,,,5
+navForwardsToMenuButton,ctrl+opt+right,,,5.1
+navForwardsToMenuButton,b,quickNavOn,,5.2
+navForwardsToMenuButton,j,quickNavOn,,5.3
+navBackToMenuButton,shift+tab,,,6
+navBackToMenuButton,ctrl+opt+left,,,6.1
+navBackToMenuButton,shift+b,quickNavOn,,6.2
+navBackToMenuButton,shift+j,quickNavOn,,6.3
+reqInfoAboutMenuButton,ctrl+opt+f3,,,9
+reqInfoAboutMenuButton,ctrl+opt+f4,,,9.1
+openMenu,ctrl+opt+space,,,12
+openMenu,space,,,12.1
+openMenu,enter,,,12.2
+openMenu,down,quickNavOff,,12.3
+openMenuToLastItem,up,quickNavOff,,14
+reqInfoAboutMenuItem,ctrl+opt+f3,,,16
+reqInfoAboutMenuItem,ctrl+opt+f4,,,16.1
+navToFirstItemMenu,home,,,18
+navToFirstItemMenu,down,quickNavOff,,18.1
+navToLastItemMenu,end,,,20
+navToLastItemMenu,up,quickNavOff,,20.1
+navToItemMenuByTypingCharacter,a,quickNavOff,,22
+activateMenuItem,ctrl+opt+space,,,24
+activateMenuItem,enter,,,24.1
+closeMenu,esc,,,26
diff --git a/tests/menu-button-actions/reference/2021-1-14_12348/menu-button-actions.html b/tests/menu-button-actions/reference/2021-1-14_12348/menu-button-actions.html
deleted file mode 100644
index ac9feab06..000000000
--- a/tests/menu-button-actions/reference/2021-1-14_12348/menu-button-actions.html
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
- Actions Menu Button Example Using element.focus()
-
-
-
-
-
-
-
-
Actions Menu Button Example Using element.focus()
-
- This example demonstrates how the
- menu button design pattern
- can be used to create a button that opens an actions menu.
- In this example, choosing an action from the menu will cause the chosen action to be displayed in the Last Action edit box.
-
- This example demonstrates how the
- menu button design pattern
- can be used to create a button that opens an actions menu.
- In this example, choosing an action from the menu will cause the chosen action to be displayed in the Last Action edit box.
-
- This example demonstrates how the
- menu button design pattern
- can be used to create a button that opens an actions menu.
- In this example, choosing an action from the menu will cause the chosen action to be displayed in the Last Action edit box.
-
- This example demonstrates how the
- menu button design pattern
- can be used to create a button that opens an actions menu.
- In this example, choosing an action from the menu will cause the chosen action to be displayed in the Last Action edit box.
-
- This example demonstrates how the
- menu button design pattern
- can be used to create a button that opens an actions menu.
- In this example, choosing an action from the menu will cause the chosen action to be displayed in the Last Action edit box.
-
- This example demonstrates how the
- menu button design pattern
- can be used to create a button that opens an actions menu.
- In this example, choosing an action from the menu will cause the chosen action to be displayed in the Last Action edit box.
-
-
-
-
diff --git a/tests/menu-button-actions/reference/2021-1-14_12348/css/menu-button-actions.css b/tests/menu-button-actions/reference/2024-8-28_1295/css/menu-button-actions.css
similarity index 97%
rename from tests/menu-button-actions/reference/2021-1-14_12348/css/menu-button-actions.css
rename to tests/menu-button-actions/reference/2024-8-28_1295/css/menu-button-actions.css
index 391043fa3..ec0375f1f 100644
--- a/tests/menu-button-actions/reference/2021-1-14_12348/css/menu-button-actions.css
+++ b/tests/menu-button-actions/reference/2024-8-28_1295/css/menu-button-actions.css
@@ -45,8 +45,8 @@
.menu-button-actions button svg.down {
padding-left: 0.125em;
- fill: currentColor;
- stroke: currentColor;
+ fill: currentcolor;
+ stroke: currentcolor;
}
.menu-button-actions button[aria-expanded="true"] svg.down {
diff --git a/tests/menu-button-actions/reference/2024-8-28_1295/css/menu-button-links.css b/tests/menu-button-actions/reference/2024-8-28_1295/css/menu-button-links.css
new file mode 100644
index 000000000..6ab2b3680
--- /dev/null
+++ b/tests/menu-button-actions/reference/2024-8-28_1295/css/menu-button-links.css
@@ -0,0 +1,78 @@
+.menu-button-links {
+ margin: 0;
+ font-size: 110%;
+}
+
+.menu-button-links button {
+ margin: 0;
+ padding: 6px;
+ display: inline-block;
+ position: relative;
+ background-color: #034575;
+ border: 1px solid #034575;
+ font-size: 0.9em;
+ color: white;
+ border-radius: 5px;
+}
+
+.menu-button-links [role="menu"] {
+ margin: 0;
+ padding: 7px 4px;
+ list-style: none;
+ display: none;
+ position: absolute;
+ border: 2px solid #034575;
+ border-radius: 5px;
+ background-color: #eee;
+}
+
+.menu-button-links [role="menuitem"],
+.menu-button-links [role="separator"] {
+ margin: 0;
+ padding: 6px;
+ display: block;
+ width: 24em;
+ background-color: #eee;
+ border: none;
+ color: black;
+ border-radius: 5px;
+}
+
+.menu-button-links [role="separator"] {
+ padding-top: 3px;
+ background-image: url("../images/separator.svg");
+ background-position: center;
+ background-repeat: repeat-x;
+}
+
+.menu-button-links button svg.down {
+ padding-left: 0.125em;
+ fill: currentcolor;
+ stroke: currentcolor;
+}
+
+.menu-button-links button[aria-expanded="true"] svg.down {
+ transform: rotate(180deg);
+}
+
+/* focus styling */
+
+.menu-button-links button:hover,
+.menu-button-links button:focus,
+.menu-button-links button[aria-expanded="true"] {
+ padding: 4px;
+ border: 3px solid #034575;
+ background: #eee;
+ color: #222;
+ outline: none;
+ margin: 0;
+}
+
+.menu-button-links [role="menuitem"]:focus {
+ padding: 4px;
+ border: 2px solid #034575;
+ background: #034575;
+ color: #fff;
+ outline: none;
+ margin: 0;
+}
diff --git a/tests/menu-button-actions/reference/2024-8-28_1295/js/menu-button-actions-active-descendant.js b/tests/menu-button-actions/reference/2024-8-28_1295/js/menu-button-actions-active-descendant.js
new file mode 100644
index 000000000..a1165150d
--- /dev/null
+++ b/tests/menu-button-actions/reference/2024-8-28_1295/js/menu-button-actions-active-descendant.js
@@ -0,0 +1,349 @@
+/*
+ * This content is licensed according to the W3C Software License at
+ * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
+ *
+ * File: menu-button-actives-active-descendant.js
+ *
+ * Desc: Creates a menu button that opens a menu of actions using aria-activedescendants
+ */
+
+'use strict';
+
+class MenuButtonActionsActiveDescendant {
+ constructor(domNode, performMenuAction) {
+ this.domNode = domNode;
+ this.performMenuAction = performMenuAction;
+ this.buttonNode = domNode.querySelector('button');
+ this.menuNode = domNode.querySelector('[role="menu"]');
+ this.currentMenuitem = {};
+ this.menuitemNodes = [];
+ this.firstMenuitem = false;
+ this.lastMenuitem = false;
+ this.firstChars = [];
+
+ this.buttonNode.addEventListener(
+ 'keydown',
+ this.onButtonKeydown.bind(this)
+ );
+
+ this.buttonNode.addEventListener('click', this.onButtonClick.bind(this));
+
+ this.menuNode.addEventListener('keydown', this.onMenuKeydown.bind(this));
+
+ var nodes = domNode.querySelectorAll('[role="menuitem"]');
+
+ for (var i = 0; i < nodes.length; i++) {
+ var menuitem = nodes[i];
+ this.menuitemNodes.push(menuitem);
+ menuitem.tabIndex = -1;
+ this.firstChars.push(menuitem.textContent.trim()[0].toLowerCase());
+
+ menuitem.addEventListener('click', this.onMenuitemClick.bind(this));
+
+ menuitem.addEventListener(
+ 'mouseover',
+ this.onMenuitemMouseover.bind(this)
+ );
+
+ if (!this.firstMenuitem) {
+ this.firstMenuitem = menuitem;
+ }
+ this.lastMenuitem = menuitem;
+ }
+
+ domNode.addEventListener('focusin', this.onFocusin.bind(this));
+ domNode.addEventListener('focusout', this.onFocusout.bind(this));
+
+ window.addEventListener(
+ 'mousedown',
+ this.onBackgroundMousedown.bind(this),
+ true
+ );
+ }
+
+ setFocusToMenuitem(newMenuitem) {
+ for (var i = 0; i < this.menuitemNodes.length; i++) {
+ var menuitem = this.menuitemNodes[i];
+ if (menuitem === newMenuitem) {
+ this.currentMenuitem = newMenuitem;
+ menuitem.classList.add('focus');
+ this.menuNode.setAttribute('aria-activedescendant', newMenuitem.id);
+ } else {
+ menuitem.classList.remove('focus');
+ }
+ }
+ }
+
+ setFocusToFirstMenuitem() {
+ this.setFocusToMenuitem(this.firstMenuitem);
+ }
+
+ setFocusToLastMenuitem() {
+ this.setFocusToMenuitem(this.lastMenuitem);
+ }
+
+ setFocusToPreviousMenuitem() {
+ var newMenuitem, index;
+
+ if (this.currentMenuitem === this.firstMenuitem) {
+ newMenuitem = this.lastMenuitem;
+ } else {
+ index = this.menuitemNodes.indexOf(this.currentMenuitem);
+ newMenuitem = this.menuitemNodes[index - 1];
+ }
+
+ this.setFocusToMenuitem(newMenuitem);
+
+ return newMenuitem;
+ }
+
+ setFocusToNextMenuitem() {
+ var newMenuitem, index;
+
+ if (this.currentMenuitem === this.lastMenuitem) {
+ newMenuitem = this.firstMenuitem;
+ } else {
+ index = this.menuitemNodes.indexOf(this.currentMenuitem);
+ newMenuitem = this.menuitemNodes[index + 1];
+ }
+ this.setFocusToMenuitem(newMenuitem);
+
+ return newMenuitem;
+ }
+
+ setFocusByFirstCharacter(char) {
+ var start, index;
+
+ if (char.length > 1) {
+ return;
+ }
+
+ char = char.toLowerCase();
+
+ // Get start index for search based on position of currentItem
+ start = this.menuitemNodes.indexOf(this.currentMenuitem) + 1;
+ if (start >= this.menuitemNodes.length) {
+ start = 0;
+ }
+
+ // Check remaining slots in the menu
+ index = this.firstChars.indexOf(char, start);
+
+ // If not found in remaining slots, check from beginning
+ if (index === -1) {
+ index = this.firstChars.indexOf(char, 0);
+ }
+
+ // If match was found...
+ if (index > -1) {
+ this.setFocusToMenuitem(this.menuitemNodes[index]);
+ }
+ }
+
+ // Utilities
+
+ getIndexFirstChars(startIndex, char) {
+ for (var i = startIndex; i < this.firstChars.length; i++) {
+ if (char === this.firstChars[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ // Popup menu methods
+
+ openPopup() {
+ this.menuNode.style.display = 'block';
+ this.buttonNode.setAttribute('aria-expanded', 'true');
+ this.menuNode.focus();
+ this.setFocusToFirstMenuitem();
+ }
+
+ closePopup() {
+ if (this.isOpen()) {
+ this.buttonNode.setAttribute('aria-expanded', 'false');
+ this.menuNode.setAttribute('aria-activedescendant', '');
+ for (let i = 0; i < this.menuitemNodes.length; i++) {
+ this.menuitemNodes[i].classList.remove('focus');
+ }
+ this.menuNode.style.display = 'none';
+ this.buttonNode.focus();
+ }
+ }
+
+ isOpen() {
+ return this.buttonNode.getAttribute('aria-expanded') === 'true';
+ }
+
+ // Menu event handlers
+
+ onFocusin() {
+ this.domNode.classList.add('focus');
+ }
+
+ onFocusout() {
+ this.domNode.classList.remove('focus');
+ }
+
+ onButtonKeydown(event) {
+ var key = event.key,
+ flag = false;
+
+ switch (key) {
+ case ' ':
+ case 'Enter':
+ case 'ArrowDown':
+ case 'Down':
+ this.openPopup();
+ this.setFocusToFirstMenuitem();
+ flag = true;
+ break;
+
+ case 'Esc':
+ case 'Escape':
+ this.closePopup();
+ flag = true;
+ break;
+
+ case 'Up':
+ case 'ArrowUp':
+ this.openPopup();
+ this.setFocusToLastMenuitem();
+ flag = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if (flag) {
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ }
+
+ onButtonClick(event) {
+ if (this.isOpen()) {
+ this.closePopup();
+ } else {
+ this.openPopup();
+ }
+ event.stopPropagation();
+ event.preventDefault();
+ }
+
+ onMenuKeydown(event) {
+ var key = event.key,
+ flag = false;
+
+ function isPrintableCharacter(str) {
+ return str.length === 1 && str.match(/\S/);
+ }
+
+ if (event.ctrlKey || event.altKey || event.metaKey) {
+ return;
+ }
+
+ if (event.shiftKey) {
+ if (isPrintableCharacter(key)) {
+ this.setFocusByFirstCharacter(key);
+ flag = true;
+ }
+
+ if (event.key === 'Tab') {
+ this.closePopup();
+ flag = true;
+ }
+ } else {
+ switch (key) {
+ case ' ':
+ case 'Enter':
+ this.closePopup();
+ this.performMenuAction(this.currentMenuitem);
+ flag = true;
+ break;
+
+ case 'Esc':
+ case 'Escape':
+ this.closePopup();
+ flag = true;
+ break;
+
+ case 'Up':
+ case 'ArrowUp':
+ this.setFocusToPreviousMenuitem();
+ flag = true;
+ break;
+
+ case 'ArrowDown':
+ case 'Down':
+ this.setFocusToNextMenuitem();
+ flag = true;
+ break;
+
+ case 'Home':
+ case 'PageUp':
+ this.setFocusToFirstMenuitem();
+ flag = true;
+ break;
+
+ case 'End':
+ case 'PageDown':
+ this.setFocusToLastMenuitem();
+ flag = true;
+ break;
+
+ case 'Tab':
+ this.closePopup();
+ break;
+
+ default:
+ if (isPrintableCharacter(key)) {
+ this.setFocusByFirstCharacter(key);
+ flag = true;
+ }
+ break;
+ }
+ }
+
+ if (flag) {
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ }
+
+ onMenuitemMouseover(event) {
+ var tgt = event.currentTarget;
+ this.setFocusToMenuitem(tgt);
+ }
+
+ onMenuitemClick(event) {
+ var tgt = event.currentTarget;
+ this.closePopup();
+ this.performMenuAction(tgt);
+ }
+
+ onBackgroundMousedown(event) {
+ if (!this.domNode.contains(event.target)) {
+ if (this.isOpen()) {
+ this.closePopup();
+ }
+ }
+ }
+}
+
+// Initialize menu buttons
+
+window.addEventListener('load', function () {
+ document.getElementById('action_output').value = 'none';
+
+ function performMenuAction(node) {
+ document.getElementById('action_output').value = node.textContent.trim();
+ }
+
+ var menuButtons = document.querySelectorAll('.menu-button-actions');
+ for (var i = 0; i < menuButtons.length; i++) {
+ new MenuButtonActionsActiveDescendant(menuButtons[i], performMenuAction);
+ }
+});
diff --git a/tests/menu-button-actions/reference/2021-1-14_12348/js/menu-button-actions.js b/tests/menu-button-actions/reference/2024-8-28_1295/js/menu-button-actions.js
similarity index 99%
rename from tests/menu-button-actions/reference/2021-1-14_12348/js/menu-button-actions.js
rename to tests/menu-button-actions/reference/2024-8-28_1295/js/menu-button-actions.js
index 30bc755d9..62bbdb58a 100644
--- a/tests/menu-button-actions/reference/2021-1-14_12348/js/menu-button-actions.js
+++ b/tests/menu-button-actions/reference/2024-8-28_1295/js/menu-button-actions.js
@@ -156,7 +156,7 @@ class MenuButtonActions {
closePopup() {
if (this.isOpen()) {
- this.buttonNode.removeAttribute('aria-expanded');
+ this.buttonNode.setAttribute('aria-expanded', 'false');
this.menuNode.style.display = 'none';
}
}
diff --git a/tests/menu-button-actions/reference/2024-8-28_1295/js/menu-button-links.js b/tests/menu-button-actions/reference/2024-8-28_1295/js/menu-button-links.js
new file mode 100644
index 000000000..757aac226
--- /dev/null
+++ b/tests/menu-button-actions/reference/2024-8-28_1295/js/menu-button-links.js
@@ -0,0 +1,328 @@
+/*
+ * This content is licensed according to the W3C Software License at
+ * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
+ *
+ * File: menu-button-links.js
+ *
+ * Desc: Creates a menu button that opens a menu of links
+ */
+
+'use strict';
+
+class MenuButtonLinks {
+ constructor(domNode) {
+ this.domNode = domNode;
+ this.buttonNode = domNode.querySelector('button');
+ this.menuNode = domNode.querySelector('[role="menu"]');
+ this.menuitemNodes = [];
+ this.firstMenuitem = false;
+ this.lastMenuitem = false;
+ this.firstChars = [];
+
+ this.buttonNode.addEventListener(
+ 'keydown',
+ this.onButtonKeydown.bind(this)
+ );
+ this.buttonNode.addEventListener('click', this.onButtonClick.bind(this));
+
+ var nodes = domNode.querySelectorAll('[role="menuitem"]');
+
+ for (var i = 0; i < nodes.length; i++) {
+ var menuitem = nodes[i];
+ this.menuitemNodes.push(menuitem);
+ menuitem.tabIndex = -1;
+ this.firstChars.push(menuitem.textContent.trim()[0].toLowerCase());
+
+ menuitem.addEventListener('keydown', this.onMenuitemKeydown.bind(this));
+
+ menuitem.addEventListener(
+ 'mouseover',
+ this.onMenuitemMouseover.bind(this)
+ );
+
+ if (!this.firstMenuitem) {
+ this.firstMenuitem = menuitem;
+ }
+ this.lastMenuitem = menuitem;
+ }
+
+ domNode.addEventListener('focusin', this.onFocusin.bind(this));
+ domNode.addEventListener('focusout', this.onFocusout.bind(this));
+
+ window.addEventListener(
+ 'mousedown',
+ this.onBackgroundMousedown.bind(this),
+ true
+ );
+ }
+
+ setFocusToMenuitem(newMenuitem) {
+ this.menuitemNodes.forEach(function (item) {
+ if (item === newMenuitem) {
+ item.tabIndex = 0;
+ newMenuitem.focus();
+ } else {
+ item.tabIndex = -1;
+ }
+ });
+ }
+
+ setFocusToFirstMenuitem() {
+ this.setFocusToMenuitem(this.firstMenuitem);
+ }
+
+ setFocusToLastMenuitem() {
+ this.setFocusToMenuitem(this.lastMenuitem);
+ }
+
+ setFocusToPreviousMenuitem(currentMenuitem) {
+ var newMenuitem, index;
+
+ if (currentMenuitem === this.firstMenuitem) {
+ newMenuitem = this.lastMenuitem;
+ } else {
+ index = this.menuitemNodes.indexOf(currentMenuitem);
+ newMenuitem = this.menuitemNodes[index - 1];
+ }
+
+ this.setFocusToMenuitem(newMenuitem);
+
+ return newMenuitem;
+ }
+
+ setFocusToNextMenuitem(currentMenuitem) {
+ var newMenuitem, index;
+
+ if (currentMenuitem === this.lastMenuitem) {
+ newMenuitem = this.firstMenuitem;
+ } else {
+ index = this.menuitemNodes.indexOf(currentMenuitem);
+ newMenuitem = this.menuitemNodes[index + 1];
+ }
+ this.setFocusToMenuitem(newMenuitem);
+
+ return newMenuitem;
+ }
+
+ setFocusByFirstCharacter(currentMenuitem, char) {
+ var start, index;
+
+ if (char.length > 1) {
+ return;
+ }
+
+ char = char.toLowerCase();
+
+ // Get start index for search based on position of currentItem
+ start = this.menuitemNodes.indexOf(currentMenuitem) + 1;
+ if (start >= this.menuitemNodes.length) {
+ start = 0;
+ }
+
+ // Check remaining slots in the menu
+ index = this.firstChars.indexOf(char, start);
+
+ // If not found in remaining slots, check from beginning
+ if (index === -1) {
+ index = this.firstChars.indexOf(char, 0);
+ }
+
+ // If match was found...
+ if (index > -1) {
+ this.setFocusToMenuitem(this.menuitemNodes[index]);
+ }
+ }
+
+ // Utilities
+
+ getIndexFirstChars(startIndex, char) {
+ for (var i = startIndex; i < this.firstChars.length; i++) {
+ if (char === this.firstChars[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ // Popup menu methods
+
+ openPopup() {
+ this.menuNode.style.display = 'block';
+ this.buttonNode.setAttribute('aria-expanded', 'true');
+ }
+
+ closePopup() {
+ if (this.isOpen()) {
+ this.buttonNode.setAttribute('aria-expanded', 'false');
+ this.menuNode.style.display = 'none';
+ }
+ }
+
+ isOpen() {
+ return this.buttonNode.getAttribute('aria-expanded') === 'true';
+ }
+
+ // Menu event handlers
+
+ onFocusin() {
+ this.domNode.classList.add('focus');
+ }
+
+ onFocusout() {
+ this.domNode.classList.remove('focus');
+ }
+
+ onButtonKeydown(event) {
+ var key = event.key,
+ flag = false;
+
+ switch (key) {
+ case ' ':
+ case 'Enter':
+ case 'ArrowDown':
+ case 'Down':
+ this.openPopup();
+ this.setFocusToFirstMenuitem();
+ flag = true;
+ break;
+
+ case 'Esc':
+ case 'Escape':
+ this.closePopup();
+ this.buttonNode.focus();
+ flag = true;
+ break;
+
+ case 'Up':
+ case 'ArrowUp':
+ this.openPopup();
+ this.setFocusToLastMenuitem();
+ flag = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if (flag) {
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ }
+
+ onButtonClick(event) {
+ if (this.isOpen()) {
+ this.closePopup();
+ this.buttonNode.focus();
+ } else {
+ this.openPopup();
+ this.setFocusToFirstMenuitem();
+ }
+
+ event.stopPropagation();
+ event.preventDefault();
+ }
+
+ onMenuitemKeydown(event) {
+ var tgt = event.currentTarget,
+ key = event.key,
+ flag = false;
+
+ function isPrintableCharacter(str) {
+ return str.length === 1 && str.match(/\S/);
+ }
+
+ if (event.ctrlKey || event.altKey || event.metaKey) {
+ return;
+ }
+
+ if (event.shiftKey) {
+ if (isPrintableCharacter(key)) {
+ this.setFocusByFirstCharacter(tgt, key);
+ flag = true;
+ }
+
+ if (event.key === 'Tab') {
+ this.buttonNode.focus();
+ this.closePopup();
+ flag = true;
+ }
+ } else {
+ switch (key) {
+ case ' ':
+ window.location.href = tgt.href;
+ break;
+
+ case 'Esc':
+ case 'Escape':
+ this.closePopup();
+ this.buttonNode.focus();
+ flag = true;
+ break;
+
+ case 'Up':
+ case 'ArrowUp':
+ this.setFocusToPreviousMenuitem(tgt);
+ flag = true;
+ break;
+
+ case 'ArrowDown':
+ case 'Down':
+ this.setFocusToNextMenuitem(tgt);
+ flag = true;
+ break;
+
+ case 'Home':
+ case 'PageUp':
+ this.setFocusToFirstMenuitem();
+ flag = true;
+ break;
+
+ case 'End':
+ case 'PageDown':
+ this.setFocusToLastMenuitem();
+ flag = true;
+ break;
+
+ case 'Tab':
+ this.closePopup();
+ break;
+
+ default:
+ if (isPrintableCharacter(key)) {
+ this.setFocusByFirstCharacter(tgt, key);
+ flag = true;
+ }
+ break;
+ }
+ }
+
+ if (flag) {
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ }
+
+ onMenuitemMouseover(event) {
+ var tgt = event.currentTarget;
+ tgt.focus();
+ }
+
+ onBackgroundMousedown(event) {
+ if (!this.domNode.contains(event.target)) {
+ if (this.isOpen()) {
+ this.closePopup();
+ this.buttonNode.focus();
+ }
+ }
+ }
+}
+
+// Initialize menu buttons
+
+window.addEventListener('load', function () {
+ var menuButtons = document.querySelectorAll('.menu-button-links');
+ for (let i = 0; i < menuButtons.length; i++) {
+ new MenuButtonLinks(menuButtons[i]);
+ }
+});
diff --git a/tests/menu-button-actions/reference/2024-8-28_1295/menu-button-actions.html b/tests/menu-button-actions/reference/2024-8-28_1295/menu-button-actions.html
new file mode 100644
index 000000000..f0bd7bfb9
--- /dev/null
+++ b/tests/menu-button-actions/reference/2024-8-28_1295/menu-button-actions.html
@@ -0,0 +1,62 @@
+
+
+
+
+
+ Actions Menu Button Example Using element.focus()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Actions Menu Button Example Using element.focus()
+
+
+
+ This example demonstrates how the Menu Button Pattern can be used to create a button that opens an actions menu.
+ In this example, choosing an action from the menu will cause the chosen action to be displayed in the Last Action edit box.
+
+ This example demonstrates how the Menu Button Pattern can be used to create a button that opens an actions menu.
+ In this example, choosing an action from the menu will cause the chosen action to be displayed in the Last Action edit box.
+
+ This example demonstrates how the Menu Button Pattern can be used to create a button that opens an actions menu.
+ In this example, choosing an action from the menu will cause the chosen action to be displayed in the Last Action edit box.
+
+ This example demonstrates how the Menu Button Pattern can be used to create a button that opens an actions menu.
+ In this example, choosing an action from the menu will cause the chosen action to be displayed in the Last Action edit box.
+
+ This example demonstrates how the Menu Button Pattern can be used to create a button that opens an actions menu.
+ In this example, choosing an action from the menu will cause the chosen action to be displayed in the Last Action edit box.
+
+ This example demonstrates how the Menu Button Pattern can be used to create a button that opens an actions menu.
+ In this example, choosing an action from the menu will cause the chosen action to be displayed in the Last Action edit box.
+