@@ -42,7 +42,7 @@ jest.mock("@/customization/hooks/use-custom-navigate", () => ({
4242} ) ) ;
4343jest . mock ( "@/stores/flowsManagerStore" , ( ) => ( {
4444 __esModule : true ,
45- default : ( sel ) =>
45+ default : ( sel : ( s : object ) => unknown ) =>
4646 sel ( {
4747 autoSaving : false ,
4848 saveLoading : false ,
@@ -51,11 +51,11 @@ jest.mock("@/stores/flowsManagerStore", () => ({
5151} ) ) ;
5252jest . mock ( "@/stores/alertStore" , ( ) => ( {
5353 __esModule : true ,
54- default : ( sel ) => sel ( { setSuccessData : jest . fn ( ) } ) ,
54+ default : ( sel : ( s : object ) => unknown ) => sel ( { setSuccessData : jest . fn ( ) } ) ,
5555} ) ) ;
5656jest . mock ( "@/stores/flowStore" , ( ) => ( {
5757 __esModule : true ,
58- default : ( sel ) =>
58+ default : jest . fn ( ( sel : ( s : object ) => unknown ) =>
5959 sel ( {
6060 onFlowPage : true ,
6161 isBuilding : false ,
@@ -68,19 +68,44 @@ jest.mock("@/stores/flowStore", () => ({
6868 locked : false ,
6969 } ,
7070 } ) ,
71+ ) ,
7172} ) ) ;
7273jest . mock ( "@/stores/shortcuts" , ( ) => ( {
7374 __esModule : true ,
74- useShortcutsStore : ( sel ) => sel ( { changesSave : "mod+s" } ) ,
75+ useShortcutsStore : ( sel : ( s : object ) => unknown ) =>
76+ sel ( { changesSave : "mod+s" } ) ,
7577} ) ) ;
7678
7779// Avoid pulling utils that depend on darkStore
7880jest . mock ( "@/utils/utils" , ( ) => ( {
7981 __esModule : true ,
80- cn : ( ...args ) => args . filter ( Boolean ) . join ( " " ) ,
82+ cn : ( ...args : unknown [ ] ) => ( args . filter ( Boolean ) as string [ ] ) . join ( " " ) ,
8183 getNumberFromString : ( ) => 0 ,
8284} ) ) ;
8385
86+ jest . mock ( "@/components/ui/popover" , ( ) => ( {
87+ Popover : ( { children } : { children : React . ReactNode } ) => < > { children } </ > ,
88+ PopoverAnchor : ( { children } : { children : React . ReactNode } ) => (
89+ < > { children } </ >
90+ ) ,
91+ PopoverTrigger : ( { children } : { children : React . ReactNode } ) => (
92+ < > { children } </ >
93+ ) ,
94+ PopoverContent : ( {
95+ children,
96+ "aria-label" : ariaLabel ,
97+ } : {
98+ children : React . ReactNode ;
99+ "aria-label" ?: string ;
100+ } ) => (
101+ < div data-testid = "popover-content" aria-label = { ariaLabel } >
102+ { children }
103+ </ div >
104+ ) ,
105+ } ) ) ;
106+
107+ import React from "react" ;
108+
84109// styleUtils imports lucide dynamic icons; stub to avoid resolution
85110jest . mock ( "lucide-react/dynamicIconImports" , ( ) => ( { } ) , { virtual : true } ) ;
86111
@@ -101,4 +126,64 @@ describe("FlowMenu MenuBar", () => {
101126 fireEvent . click ( screen . getByTestId ( "save-flow-button" ) ) ;
102127 expect ( mockSave ) . toHaveBeenCalled ( ) ;
103128 } ) ;
129+
130+ describe ( "Accessibility — aria labels" , ( ) => {
131+ const flowStoreMock = jest . requireMock ( "@/stores/flowStore" ) ;
132+
133+ afterEach ( ( ) => {
134+ flowStoreMock . default . mockReset ( ) ;
135+ flowStoreMock . default . mockImplementation ( ( sel : ( s : object ) => unknown ) =>
136+ sel ( {
137+ onFlowPage : true ,
138+ isBuilding : false ,
139+ currentFlow : {
140+ id : "1" ,
141+ name : "Flow" ,
142+ folder_id : "f1" ,
143+ icon : "Workflow" ,
144+ gradient : "0" ,
145+ locked : false ,
146+ } ,
147+ } ) ,
148+ ) ;
149+ } ) ;
150+
151+ it ( "menu_bar_display is a button element for keyboard and screen reader access" , ( ) => {
152+ render ( < MenuBar /> ) ;
153+ const trigger = screen . getByTestId ( "menu_bar_display" ) ;
154+ expect ( trigger . tagName ) . toBe ( "BUTTON" ) ;
155+ } ) ;
156+
157+ it ( "menu_bar_display button has aria-label matching the flow name" , ( ) => {
158+ render ( < MenuBar /> ) ;
159+ const trigger = screen . getByTestId ( "menu_bar_display" ) ;
160+ expect ( trigger ) . toHaveAttribute ( "aria-label" , "Flow" ) ;
161+ } ) ;
162+
163+ it ( "menu_bar_display aria-label falls back to untitled flow when name is absent" , ( ) => {
164+ flowStoreMock . default . mockImplementation ( ( sel : ( s : object ) => unknown ) =>
165+ sel ( {
166+ onFlowPage : true ,
167+ isBuilding : false ,
168+ currentFlow : {
169+ id : "1" ,
170+ name : undefined ,
171+ folder_id : "f1" ,
172+ icon : "Workflow" ,
173+ gradient : "0" ,
174+ locked : false ,
175+ } ,
176+ } ) ,
177+ ) ;
178+ render ( < MenuBar /> ) ;
179+ const trigger = screen . getByTestId ( "menu_bar_display" ) ;
180+ expect ( trigger ) . toHaveAttribute ( "aria-label" , "Untitled Flow" ) ;
181+ } ) ;
182+
183+ it ( "popover content has an aria-label of 'Flow settings' for screen readers" , ( ) => {
184+ render ( < MenuBar /> ) ;
185+ const content = screen . getByTestId ( "popover-content" ) ;
186+ expect ( content ) . toHaveAttribute ( "aria-label" , "Flow settings" ) ;
187+ } ) ;
188+ } ) ;
104189} ) ;
0 commit comments