@@ -127,4 +127,164 @@ describe("OverflowMenu", () => {
127127 expect ( menu ) . toHaveStyle ( "--overflow-menu-options-after-width: 2rem" ) ;
128128 } ) ;
129129 } ) ;
130+
131+ test . each ( [
132+ [ "sm" , "bx--overflow-menu--sm" ] ,
133+ [ "xl" , "bx--overflow-menu--xl" ] ,
134+ ] as const ) ( "should support %s size" , ( size , expectedClass ) => {
135+ render ( OverflowMenu , { props : { size } } ) ;
136+
137+ const menuButton = screen . getByRole ( "button" ) ;
138+ expect ( menuButton ) . toHaveClass ( expectedClass ) ;
139+ } ) ;
140+
141+ it ( "should not apply size classes when size is undefined" , ( ) => {
142+ render ( OverflowMenu , { props : { size : undefined } } ) ;
143+
144+ const menuButton = screen . getByRole ( "button" ) ;
145+ expect ( menuButton ) . not . toHaveClass ( "bx--overflow-menu--sm" ) ;
146+ expect ( menuButton ) . not . toHaveClass ( "bx--overflow-menu--xl" ) ;
147+ } ) ;
148+
149+ it ( "applies light variant styling" , ( ) => {
150+ render ( OverflowMenu , { props : { light : true } } ) ;
151+
152+ const menuButton = screen . getByRole ( "button" ) ;
153+ expect ( menuButton ) . toHaveClass ( "bx--overflow-menu--light" ) ;
154+ } ) ;
155+
156+ it ( "applies flipped styling" , async ( ) => {
157+ render ( OverflowMenu , { props : { flipped : true } } ) ;
158+
159+ const menuButton = screen . getByRole ( "button" ) ;
160+ await user . click ( menuButton ) ;
161+
162+ const menu = screen . getByRole ( "menu" ) ;
163+ expect ( menu ) . toHaveClass ( "bx--overflow-menu--flip" ) ;
164+ } ) ;
165+
166+ it ( "applies direction attribute" , async ( ) => {
167+ render ( OverflowMenu , { props : { direction : "top" } } ) ;
168+
169+ const menuButton = screen . getByRole ( "button" ) ;
170+ await user . click ( menuButton ) ;
171+
172+ const menu = screen . getByRole ( "menu" ) ;
173+ expect ( menu ) . toHaveAttribute ( "data-floating-menu-direction" , "top" ) ;
174+ } ) ;
175+
176+ it ( "applies custom menu options class" , async ( ) => {
177+ render ( OverflowMenu , { props : { menuOptionsClass : "custom-class" } } ) ;
178+
179+ const menuButton = screen . getByRole ( "button" ) ;
180+ await user . click ( menuButton ) ;
181+
182+ const menu = screen . getByRole ( "menu" ) ;
183+ expect ( menu ) . toHaveClass ( "custom-class" ) ;
184+ } ) ;
185+
186+ it ( "applies custom icon class" , ( ) => {
187+ render ( OverflowMenu , { props : { iconClass : "custom-icon-class" } } ) ;
188+
189+ const icon = screen . getByRole ( "button" ) . querySelector ( "svg" ) ;
190+ expect ( icon ) . toHaveClass ( "custom-icon-class" ) ;
191+ } ) ;
192+
193+ it ( "uses custom icon description" , ( ) => {
194+ render ( OverflowMenu , { props : { iconDescription : "Custom description" } } ) ;
195+
196+ const icon = screen . getByRole ( "button" ) . querySelector ( "svg" ) ;
197+ expect ( icon ) . toHaveAttribute ( "aria-label" , "Custom description" ) ;
198+ } ) ;
199+
200+ it ( "uses custom id" , ( ) => {
201+ render ( OverflowMenu , { props : { id : "custom-id" } } ) ;
202+
203+ const menuButton = screen . getByRole ( "button" ) ;
204+ expect ( menuButton ) . toHaveAttribute ( "id" , "custom-id" ) ;
205+ } ) ;
206+
207+ it ( "applies danger styling to menu items" , async ( ) => {
208+ render ( OverflowMenu ) ;
209+
210+ const menuButton = screen . getByRole ( "button" ) ;
211+ await user . click ( menuButton ) ;
212+
213+ const menuItems = screen . getAllByRole ( "menuitem" ) ;
214+ const dangerItem = menuItems . find (
215+ ( item ) => item . textContent === "Delete service" ,
216+ ) ;
217+ expect ( dangerItem ?. parentElement ) . toHaveClass (
218+ "bx--overflow-menu-options__option--danger" ,
219+ ) ;
220+ } ) ;
221+
222+ it ( "handles link menu items correctly" , async ( ) => {
223+ render ( OverflowMenu ) ;
224+
225+ const menuButton = screen . getByRole ( "button" ) ;
226+ await user . click ( menuButton ) ;
227+
228+ const menuItems = screen . getAllByRole ( "menuitem" ) ;
229+ const linkItem = menuItems . find (
230+ ( item ) => item . textContent === "API documentation" ,
231+ ) ;
232+ expect ( linkItem ) . toHaveAttribute (
233+ "href" ,
234+ "https://cloud.ibm.com/docs/api-gateway/" ,
235+ ) ;
236+ } ) ;
237+
238+ it ( "returns focus to button after menu closes" , async ( ) => {
239+ render ( OverflowMenu ) ;
240+
241+ const menuButton = screen . getByRole ( "button" ) ;
242+ await user . click ( menuButton ) ;
243+
244+ const menuItems = screen . getAllByRole ( "menuitem" ) ;
245+ expect ( menuItems [ 0 ] ) . toHaveFocus ( ) ;
246+
247+ await user . keyboard ( "{Escape}" ) ;
248+ expect ( menuButton ) . toHaveFocus ( ) ;
249+ } ) ;
250+
251+ it ( "handles close event with item click" , async ( ) => {
252+ render ( OverflowMenu ) ;
253+
254+ const spy = vi . spyOn ( console , "log" ) ;
255+ const menuButton = screen . getByRole ( "button" ) ;
256+ await user . click ( menuButton ) ;
257+
258+ const menuItems = screen . getAllByRole ( "menuitem" ) ;
259+ await user . click ( menuItems [ 0 ] ) ;
260+
261+ expect ( spy ) . toHaveBeenCalledWith ( "close" , {
262+ index : 0 ,
263+ text : "Manage credentials" ,
264+ } ) ;
265+ } ) ;
266+
267+ it ( "handles close event with escape key" , async ( ) => {
268+ render ( OverflowMenu ) ;
269+
270+ const spy = vi . spyOn ( console , "log" ) ;
271+ const menuButton = screen . getByRole ( "button" ) ;
272+ await user . click ( menuButton ) ;
273+
274+ await user . keyboard ( "{Escape}" ) ;
275+
276+ expect ( spy ) . toHaveBeenCalledWith ( "close" , null ) ;
277+ } ) ;
278+
279+ it ( "handles close event with outside click" , async ( ) => {
280+ render ( OverflowMenu ) ;
281+
282+ const spy = vi . spyOn ( console , "log" ) ;
283+ const menuButton = screen . getByRole ( "button" ) ;
284+ await user . click ( menuButton ) ;
285+
286+ await user . click ( document . body ) ;
287+
288+ expect ( spy ) . toHaveBeenCalledWith ( "close" , null ) ;
289+ } ) ;
130290} ) ;
0 commit comments