File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -822,6 +822,23 @@ describe('Listbox', () => {
822822 expect ( listboxInstance . value ( ) ) . toEqual ( [ ] ) ;
823823 } ) ;
824824 } ) ;
825+
826+ describe ( 'item mutations and focus stability' , ( ) => {
827+ it ( 'should recover focus by shifting to the default state if the active option is removed' , async ( ) => {
828+ setupListbox ( { focusMode : 'activedescendant' } ) ;
829+ click ( 2 ) ;
830+ expect ( listboxElement . getAttribute ( 'aria-activedescendant' ) ) . toBe ( optionElements [ 2 ] . id ) ;
831+
832+ const testComponent = fixture . componentInstance as ListboxExample ;
833+ const updatedOptions = testComponent . options ( ) . filter ( o => o . value !== 2 ) ;
834+ testComponent . options . set ( updatedOptions ) ;
835+ fixture . detectChanges ( ) ;
836+ await waitForMicrotasks ( ) ;
837+ defineTestVariables ( fixture ) ;
838+
839+ expect ( listboxElement . getAttribute ( 'aria-activedescendant' ) ) . toBe ( optionElements [ 0 ] . id ) ;
840+ } ) ;
841+ } ) ;
825842} ) ;
826843
827844interface TestOption {
Original file line number Diff line number Diff line change @@ -182,8 +182,9 @@ export class Listbox<V> implements OnDestroy {
182182 const items = inputs . items ( ) ;
183183 const activeItem = untracked ( ( ) => inputs . activeItem ( ) ) ;
184184
185- if ( ! items . some ( i => i === activeItem ) && activeItem ) {
185+ if ( activeItem && ! items . some ( i => i === activeItem ) ) {
186186 this . _pattern . listBehavior . unfocus ( ) ;
187+ this . _pattern . setDefaultState ( ) ;
187188 }
188189 } ,
189190 } ) ;
Original file line number Diff line number Diff line change @@ -1556,6 +1556,25 @@ describe('Tree', () => {
15561556 } ) ;
15571557 }
15581558 } ) ;
1559+
1560+ describe ( 'item mutations and focus stability' , ( ) => {
1561+ it ( 'should recover focus by shifting to the default state if the active item is removed' , async ( ) => {
1562+ setupTestTree ( ) ;
1563+ updateTree ( { focusMode : 'activedescendant' } ) ;
1564+
1565+ const vegetablesEl = getTreeItemElementByValue ( 'vegetables' ) ! ;
1566+ click ( vegetablesEl ) ;
1567+ expect ( getFocusedTreeItemValue ( ) ) . toBe ( 'vegetables' ) ;
1568+
1569+ const updatedNodes = testComponent . nodes ( ) . filter ( n => n . value !== 'vegetables' ) ;
1570+ testComponent . nodes . set ( updatedNodes ) ;
1571+ fixture . detectChanges ( ) ;
1572+ await waitForMicrotasks ( ) ;
1573+ defineTestVariables ( ) ;
1574+
1575+ expect ( getFocusedTreeItemValue ( ) ) . toBe ( 'fruits' ) ;
1576+ } ) ;
1577+ } ) ;
15591578} ) ;
15601579
15611580interface TestTreeNode < V = string > {
Original file line number Diff line number Diff line change @@ -192,8 +192,9 @@ export class Tree<V> implements OnDestroy {
192192 const items = inputs . items ( ) ;
193193 const activeItem = untracked ( ( ) => inputs . activeItem ( ) ) ;
194194
195- if ( ! items . some ( i => i === activeItem ) && activeItem ) {
195+ if ( activeItem && ! items . some ( i => i === activeItem ) ) {
196196 this . _pattern . treeBehavior . unfocus ( ) ;
197+ this . _pattern . setDefaultState ( ) ;
197198 }
198199 } ,
199200 } ) ;
You can’t perform that action at this time.
0 commit comments