@@ -683,44 +683,56 @@ export const EditMultilevelTaxonomy: StoryObj<typeof MetadataSidebarRedesign> =
683683
684684 await waitForLoadingToComplete ( canvas ) ;
685685
686- const editButton = await waitFor ( ( ) => canvas . getByRole ( 'button' , { name : 'Edit My Taxonomy' } ) ) ;
687-
686+ const editButton = await canvas . findByRole ( 'button' , { name : 'Edit My Taxonomy' } ) ;
688687 await userEvent . click ( editButton ) ;
689688
690- const multilevelInput = canvas . getByRole ( 'combobox' ) ;
691- const optionChip = canvas . getByRole ( 'button' , { name : 'London' } ) ;
692-
689+ const multilevelInput = await canvas . findByRole ( 'combobox' ) ;
690+ const optionChip = await canvas . findByRole ( 'button' , { name : 'London' } ) ;
693691 expect ( multilevelInput ) . toBeInTheDocument ( ) ;
694692 expect ( optionChip ) . toBeInTheDocument ( ) ;
695693
696694 await userEvent . click ( multilevelInput ) ;
697695
698- const listbox = await waitFor ( ( ) => canvas . getByRole ( 'listbox' ) ) ;
699- expect ( listbox ) . toBeInTheDocument ( ) ;
700-
701- let expandButtons = await waitFor ( ( ) => canvas . getAllByRole ( 'button' , { name : 'Expand branch' } ) ) ;
702-
703- await userEvent . click ( expandButtons [ 1 ] ) ;
704-
705- const hokkaidoOption = await waitFor ( ( ) => canvas . getByText ( 'Hokkaido' ) ) ;
706- expect ( hokkaidoOption ) . toBeInTheDocument ( ) ;
707-
708- expandButtons = await waitFor ( ( ) => screen . getAllByRole ( 'button' , { name : 'Expand branch' } ) ) ;
709-
710- await userEvent . click ( expandButtons [ 2 ] ) ;
711-
712- const sapporoOption = await waitFor ( ( ) => canvas . getByRole ( 'treeitem' , { name : 'Sapporo' } ) ) ;
713-
714- expect ( sapporoOption ) . toBeInTheDocument ( ) ;
715- expect ( sapporoOption ) . toHaveAttribute ( 'aria-selected' , 'false' ) ;
716-
717- await userEvent . click ( sapporoOption ) ;
718-
719- const sapporoSelection = await waitFor ( ( ) => canvas . getByRole ( 'gridcell' , { name : 'Sapporo' } ) ) ;
720-
721- expect ( sapporoOption ) . toBeInTheDocument ( ) ;
722- expect ( sapporoOption ) . toHaveAttribute ( 'aria-selected' , 'true' ) ;
723- expect ( sapporoSelection ) . toBeInTheDocument ( ) ;
696+ // Scope subsequent queries to the listbox to avoid race conditions with other UI
697+ const listbox = await canvas . findByRole ( 'listbox' ) ;
698+ const listboxCanvas = within ( listbox ) ;
699+
700+ // Deterministically expand branches by label to avoid index-based flakiness.
701+ // Tree nodes can lazy-load and reorder expander buttons across renders, so
702+ // clicking expanders by index is unstable. We locate the branch by its label,
703+ // click that branch's own expander, and then await a specific child label to
704+ // appear rather than relying solely on aria-expanded (which can lag or be
705+ // set on a different wrapper depending on render timing).
706+ const expandBranch = async ( label : string , expectedChildLabel : string ) => {
707+ const labelEl = await listboxCanvas . findByText ( label ) ;
708+ const treeitem = labelEl . closest ( '[role="treeitem"]' ) as HTMLElement | null ;
709+ expect ( treeitem ) . not . toBeNull ( ) ;
710+ const isExpanded = treeitem ?. getAttribute ( 'aria-expanded' ) === 'true' ;
711+ if ( ! isExpanded ) {
712+ const expander = within ( treeitem as HTMLElement ) . getByRole ( 'button' , { name : 'Expand branch' } ) ;
713+ await userEvent . click ( expander ) ;
714+ }
715+ // Wait for a known child to render to confirm expansion completed
716+ await listboxCanvas . findByText ( expectedChildLabel ) ;
717+ } ;
718+
719+ await expandBranch ( 'Japan' , 'Hokkaido' ) ;
720+ await expandBranch ( 'Hokkaido' , 'Sapporo' ) ;
721+
722+ // Re-scope to the active listbox before selecting the leaf.
723+ // Expanding branches can trigger a tree re-render that unmounts the previous
724+ // popup content. Re-querying the listbox here ensures we don't act on a stale
725+ // element reference and avoids intermittent "element not in the document" errors.
726+ const activeListbox = await canvas . findByRole ( 'listbox' ) ;
727+ const activeListboxCanvas = within ( activeListbox ) ;
728+ await userEvent . click ( await activeListboxCanvas . findByRole ( 'treeitem' , { name : 'Sapporo' } ) ) ;
729+
730+ // Wait for the combobox to collapse after selection
731+ await waitFor ( ( ) => expect ( multilevelInput ) . toHaveAttribute ( 'aria-expanded' , 'false' ) ) ;
732+
733+ const chipsGrid = await canvas . findByRole ( 'grid' ) ;
734+ const sapporoChip = within ( chipsGrid ) . getByRole ( 'button' , { name : 'Sapporo' } ) ;
735+ expect ( sapporoChip ) . toBeInTheDocument ( ) ;
724736 } ,
725737} ;
726738
0 commit comments