diff --git a/src/cdk/a11y/key-manager/list-key-manager.spec.ts b/src/cdk/a11y/key-manager/list-key-manager.spec.ts index 774cd05779d4..f520db426b05 100644 --- a/src/cdk/a11y/key-manager/list-key-manager.spec.ts +++ b/src/cdk/a11y/key-manager/list-key-manager.spec.ts @@ -82,15 +82,28 @@ describe('Key managers', () => { spyOn(keyManager, 'setActiveItem').and.callThrough(); }); - it('should maintain the active item if the amount of items changes', () => { + it('should maintain the active item if the amount of items changes', fakeAsync(() => { expect(keyManager.activeItemIndex).toBe(0); expect(keyManager.activeItem!.getLabel()).toBe('one'); itemList.reset([new FakeFocusable('zero'), ...itemList.toArray()]); itemList.notifyOnChanges(); + tick(); expect(keyManager.activeItemIndex).toBe(1); expect(keyManager.activeItem!.getLabel()).toBe('one'); - }); + })); + + it('should keep the active item in sync if the active item is removed', fakeAsync(() => { + expect(keyManager.activeItemIndex).toBe(0); + expect(keyManager.activeItem!.getLabel()).toBe('one'); + + itemList.reset(itemList.toArray().slice(1)); + itemList.notifyOnChanges(); + tick(); + + expect(keyManager.activeItemIndex).toBe(0); + expect(keyManager.activeItem!.getLabel()).toBe('two'); + })); it('should start off the activeItem as null', () => { expect(new ListKeyManager([]).activeItem).toBeNull(); diff --git a/src/cdk/a11y/key-manager/list-key-manager.ts b/src/cdk/a11y/key-manager/list-key-manager.ts index 8f64379dcbe3..d8a94f91b5f7 100644 --- a/src/cdk/a11y/key-manager/list-key-manager.ts +++ b/src/cdk/a11y/key-manager/list-key-manager.ts @@ -70,8 +70,11 @@ export class ListKeyManager { const itemArray = newItems.toArray(); const newIndex = itemArray.indexOf(this._activeItem); - if (newIndex > -1 && newIndex !== this._activeItemIndex) { - this._activeItemIndex = newIndex; + if (newIndex !== this._activeItemIndex) { + // Timeout is required to avoid "changed after checked" errors. + setTimeout(() => { + this.updateActiveItem(newIndex > -1 ? newIndex : this._activeItemIndex); + }, 0); } } }); diff --git a/src/material-experimental/mdc-menu/menu.spec.ts b/src/material-experimental/mdc-menu/menu.spec.ts index 3143f9a86a3e..e5535fa5aa8e 100644 --- a/src/material-experimental/mdc-menu/menu.spec.ts +++ b/src/material-experimental/mdc-menu/menu.spec.ts @@ -1176,6 +1176,7 @@ describe('MDC-based MatMenu', () => { fixture.detectChanges(); tick(500); fixture.detectChanges(); + tick(); expect(fixture.componentInstance.items.length).toBe(0); })); @@ -1201,6 +1202,7 @@ describe('MDC-based MatMenu', () => { .toBe(true); tick(500); fixture.detectChanges(); + tick(); expect(trigger.menuOpen).withContext('Expected menu to be closed').toBe(false); })); diff --git a/src/material/menu/menu.spec.ts b/src/material/menu/menu.spec.ts index 1adb1fd42934..3d0ba55be20c 100644 --- a/src/material/menu/menu.spec.ts +++ b/src/material/menu/menu.spec.ts @@ -1171,6 +1171,7 @@ describe('MatMenu', () => { fixture.detectChanges(); tick(500); fixture.detectChanges(); + tick(); expect(fixture.componentInstance.items.length).toBe(0); })); @@ -1196,6 +1197,7 @@ describe('MatMenu', () => { .toBe(true); tick(500); fixture.detectChanges(); + tick(); expect(trigger.menuOpen).withContext('Expected menu to be closed').toBe(false); }));