Skip to content

Commit e584766

Browse files
committed
test(multiple): rework whenStable usages (#30878)
We have some really old tests that were depending on `fixture.whenStable` even though they don't need to. These changes clean them up. (cherry picked from commit 357cfd3)
1 parent 815a07b commit e584766

File tree

11 files changed

+114
-166
lines changed

11 files changed

+114
-166
lines changed

src/cdk/a11y/focus-trap/focus-trap.spec.ts

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
ViewChild,
77
ViewContainerRef,
88
ViewEncapsulation,
9-
inject as inject_1,
9+
inject,
1010
} from '@angular/core';
1111
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
1212
import {By} from '@angular/platform-browser';
@@ -217,16 +217,13 @@ describe('FocusTrap', () => {
217217
fixture.componentInstance.showTrappedRegion = true;
218218
fixture.changeDetectorRef.markForCheck();
219219
fixture.detectChanges();
220+
expect(getActiveElement().id).toBe('auto-capture-target');
220221

221-
fixture.whenStable().then(() => {
222-
expect(getActiveElement().id).toBe('auto-capture-target');
223-
224-
fixture.componentInstance.showTrappedRegion = false;
225-
fixture.changeDetectorRef.markForCheck();
226-
fixture.detectChanges();
222+
fixture.componentInstance.showTrappedRegion = false;
223+
fixture.changeDetectorRef.markForCheck();
224+
fixture.detectChanges();
227225

228-
expect(getActiveElement()).toBe(buttonOutsideTrappedRegion);
229-
});
226+
expect(getActiveElement()).toBe(buttonOutsideTrappedRegion);
230227
}));
231228

232229
it('should capture focus if auto capture is enabled later on', waitForAsync(() => {
@@ -243,16 +240,13 @@ describe('FocusTrap', () => {
243240
fixture.componentInstance.autoCaptureEnabled = true;
244241
fixture.changeDetectorRef.markForCheck();
245242
fixture.detectChanges();
243+
expect(getActiveElement().id).toBe('auto-capture-target');
246244

247-
fixture.whenStable().then(() => {
248-
expect(getActiveElement().id).toBe('auto-capture-target');
249-
250-
fixture.componentInstance.showTrappedRegion = false;
251-
fixture.changeDetectorRef.markForCheck();
252-
fixture.detectChanges();
245+
fixture.componentInstance.showTrappedRegion = false;
246+
fixture.changeDetectorRef.markForCheck();
247+
fixture.detectChanges();
253248

254-
expect(getActiveElement()).toBe(buttonOutsideTrappedRegion);
255-
});
249+
expect(getActiveElement()).toBe(buttonOutsideTrappedRegion);
256250
}));
257251

258252
it('should automatically capture and return focus on init / destroy inside the shadow DOM', waitForAsync(() => {
@@ -270,16 +264,13 @@ describe('FocusTrap', () => {
270264
fixture.componentInstance.showTrappedRegion = true;
271265
fixture.changeDetectorRef.markForCheck();
272266
fixture.detectChanges();
267+
expect(getActiveElement().id).toBe('auto-capture-target');
273268

274-
fixture.whenStable().then(() => {
275-
expect(getActiveElement().id).toBe('auto-capture-target');
276-
277-
fixture.componentInstance.showTrappedRegion = false;
278-
fixture.changeDetectorRef.markForCheck();
279-
fixture.detectChanges();
269+
fixture.componentInstance.showTrappedRegion = false;
270+
fixture.changeDetectorRef.markForCheck();
271+
fixture.detectChanges();
280272

281-
expect(getActiveElement()).toBe(buttonOutsideTrappedRegion);
282-
});
273+
expect(getActiveElement()).toBe(buttonOutsideTrappedRegion);
283274
}));
284275

285276
it('should capture focus if auto capture is enabled later on inside the shadow DOM', waitForAsync(() => {
@@ -300,16 +291,13 @@ describe('FocusTrap', () => {
300291
fixture.componentInstance.autoCaptureEnabled = true;
301292
fixture.changeDetectorRef.markForCheck();
302293
fixture.detectChanges();
294+
expect(getActiveElement().id).toBe('auto-capture-target');
303295

304-
fixture.whenStable().then(() => {
305-
expect(getActiveElement().id).toBe('auto-capture-target');
306-
307-
fixture.componentInstance.showTrappedRegion = false;
308-
fixture.changeDetectorRef.markForCheck();
309-
fixture.detectChanges();
296+
fixture.componentInstance.showTrappedRegion = false;
297+
fixture.changeDetectorRef.markForCheck();
298+
fixture.detectChanges();
310299

311-
expect(getActiveElement()).toBe(buttonOutsideTrappedRegion);
312-
});
300+
expect(getActiveElement()).toBe(buttonOutsideTrappedRegion);
313301
}));
314302
});
315303

@@ -473,7 +461,7 @@ class FocusTrapWithoutFocusableElements {
473461
imports: [A11yModule, PortalModule],
474462
})
475463
class FocusTrapInsidePortal {
476-
viewContainerRef = inject_1(ViewContainerRef);
464+
viewContainerRef = inject(ViewContainerRef);
477465

478466
@ViewChild('template') template: TemplateRef<any>;
479467
@ViewChild(CdkPortalOutlet) portalOutlet: CdkPortalOutlet;

src/cdk/overlay/overlay.spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,6 @@ describe('Overlay', () => {
950950
const overlayRef = overlay.create(config);
951951

952952
overlayRef.attach(componentPortal);
953-
await viewContainerFixture.whenStable();
954953

955954
const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
956955
expect(pane.classList)
@@ -961,7 +960,6 @@ describe('Overlay', () => {
961960
expect(pane.classList)
962961
.withContext('Expected class not to be removed immediately')
963962
.toContain('custom-panel-class');
964-
await viewContainerFixture.whenStable();
965963

966964
expect(pane.classList)
967965
.not.withContext('Expected class to be removed on stable')

src/cdk/scrolling/virtual-scroll-viewport.spec.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,15 +237,14 @@ describe('CdkVirtualScrollViewport', () => {
237237
expect(viewport.getOffsetToRenderedContentStart()).toBe(10);
238238
}));
239239

240-
it('should set content offset to bottom of content', fakeAsync(async () => {
240+
it('should set content offset to bottom of content', fakeAsync(() => {
241241
finishInit(fixture);
242242
const contentSize = viewport.measureRenderedContentSize();
243243

244244
expect(contentSize).toBeGreaterThan(0);
245245

246246
viewport.setRenderedContentOffset(contentSize + 10, 'to-end');
247247
flush();
248-
await fixture.whenStable();
249248

250249
expect(viewport.getOffsetToRenderedContentStart()).toBe(10);
251250
}));
@@ -1066,15 +1065,14 @@ describe('CdkVirtualScrollViewport', () => {
10661065
.toBe(0);
10671066
}));
10681067

1069-
it('should set content offset to bottom of content', fakeAsync(async () => {
1068+
it('should set content offset to bottom of content', fakeAsync(() => {
10701069
finishInit(fixture);
10711070
const contentSize = viewport.measureRenderedContentSize();
10721071

10731072
expect(contentSize).toBeGreaterThan(0);
10741073

10751074
viewport.setRenderedContentOffset(contentSize + 10, 'to-end');
10761075
flush();
1077-
await fixture.whenStable();
10781076

10791077
expect(viewport.getOffsetToRenderedContentStart()).toBe(0);
10801078
}));

src/material/bottom-sheet/bottom-sheet.spec.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -648,24 +648,18 @@ describe('MatBottomSheet', () => {
648648
expect(focusTrapAnchors.length).toBeGreaterThan(0);
649649
}));
650650

651-
it(
652-
'should focus the first tabbable element of the bottom sheet on open when' +
653-
'autoFocus is set to "first-tabbable"',
654-
async () => {
655-
bottomSheet.open(PizzaMsg, {
656-
viewContainerRef: testViewContainerRef,
657-
autoFocus: 'first-tabbable',
658-
});
651+
it('should focus the first tabbable element of the bottom sheet on open when autoFocus is set to "first-tabbable"', () => {
652+
bottomSheet.open(PizzaMsg, {
653+
viewContainerRef: testViewContainerRef,
654+
autoFocus: 'first-tabbable',
655+
});
659656

660-
viewContainerFixture.detectChanges();
661-
await viewContainerFixture.whenStable();
662-
viewContainerFixture.detectChanges();
657+
viewContainerFixture.detectChanges();
663658

664-
expect(document.activeElement!.tagName)
665-
.withContext('Expected first tabbable element (input) in the dialog to be focused.')
666-
.toBe('INPUT');
667-
},
668-
);
659+
expect(document.activeElement!.tagName)
660+
.withContext('Expected first tabbable element (input) in the dialog to be focused.')
661+
.toBe('INPUT');
662+
});
669663

670664
it('should focus the bottom sheet element on open when autoFocus is set to "dialog"', fakeAsync(() => {
671665
bottomSheet.open(PizzaMsg, {

src/material/chips/chip-grid.spec.ts

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -925,20 +925,18 @@ describe('MatChipGrid', () => {
925925
flush();
926926
fixture.detectChanges();
927927

928-
fixture.whenStable().then(() => {
929-
expect(errorTestComponent.form.submitted)
930-
.withContext('Expected form to have been submitted')
931-
.toBe(true);
932-
expect(containerEl.classList)
933-
.withContext('Expected container to have the invalid CSS class.')
934-
.toContain('mat-form-field-invalid');
935-
expect(containerEl.querySelectorAll('mat-error').length)
936-
.withContext('Expected one error message to have been rendered.')
937-
.toBe(1);
938-
expect(chipGridEl.getAttribute('aria-invalid'))
939-
.withContext('Expected aria-invalid to be set to "true".')
940-
.toBe('true');
941-
});
928+
expect(errorTestComponent.form.submitted)
929+
.withContext('Expected form to have been submitted')
930+
.toBe(true);
931+
expect(containerEl.classList)
932+
.withContext('Expected container to have the invalid CSS class.')
933+
.toContain('mat-form-field-invalid');
934+
expect(containerEl.querySelectorAll('mat-error').length)
935+
.withContext('Expected one error message to have been rendered.')
936+
.toBe(1);
937+
expect(chipGridEl.getAttribute('aria-invalid'))
938+
.withContext('Expected aria-invalid to be set to "true".')
939+
.toBe('true');
942940
flush();
943941
}));
944942

@@ -947,36 +945,32 @@ describe('MatChipGrid', () => {
947945
flush();
948946
fixture.detectChanges();
949947

950-
fixture.whenStable().then(() => {
951-
expect(containerEl.classList)
952-
.withContext('Expected container to have the invalid CSS class.')
953-
.toContain('mat-form-field-invalid');
954-
expect(containerEl.querySelectorAll('mat-error').length)
955-
.withContext('Expected one error message to have been rendered.')
956-
.toBe(1);
957-
expect(containerEl.querySelectorAll('mat-hint').length)
958-
.withContext('Expected no hints to be shown.')
959-
.toBe(0);
960-
961-
errorTestComponent.formControl.setValue('something');
962-
flush();
963-
fixture.detectChanges();
948+
expect(containerEl.classList)
949+
.withContext('Expected container to have the invalid CSS class.')
950+
.toContain('mat-form-field-invalid');
951+
expect(containerEl.querySelectorAll('mat-error').length)
952+
.withContext('Expected one error message to have been rendered.')
953+
.toBe(1);
954+
expect(containerEl.querySelectorAll('mat-hint').length)
955+
.withContext('Expected no hints to be shown.')
956+
.toBe(0);
964957

965-
fixture.whenStable().then(() => {
966-
expect(containerEl.classList).not.toContain(
967-
'mat-form-field-invalid',
968-
'Expected container not to have the invalid class when valid.',
969-
);
970-
expect(containerEl.querySelectorAll('mat-error').length)
971-
.withContext('Expected no error messages when the input is valid.')
972-
.toBe(0);
973-
expect(containerEl.querySelectorAll('mat-hint').length)
974-
.withContext('Expected one hint to be shown once the input is valid.')
975-
.toBe(1);
976-
});
958+
errorTestComponent.formControl.setValue('something');
959+
flush();
960+
fixture.detectChanges();
977961

978-
flush();
979-
});
962+
expect(containerEl.classList).not.toContain(
963+
'mat-form-field-invalid',
964+
'Expected container not to have the invalid class when valid.',
965+
);
966+
expect(containerEl.querySelectorAll('mat-error').length)
967+
.withContext('Expected no error messages when the input is valid.')
968+
.toBe(0);
969+
expect(containerEl.querySelectorAll('mat-hint').length)
970+
.withContext('Expected one hint to be shown once the input is valid.')
971+
.toBe(1);
972+
973+
flush();
980974
}));
981975

982976
it('should set the proper aria-live attribute on the error messages', () => {

src/material/datepicker/datepicker.spec.ts

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -388,34 +388,28 @@ describe('MatDatepicker', () => {
388388
}),
389389
);
390390

391-
it(
392-
'pressing enter on the currently selected date should close the calendar without ' +
393-
'firing selectedChanged',
394-
fakeAsync(() => {
395-
const spy = jasmine.createSpy('selectionChanged spy');
396-
const selectedSubscription = model.selectionChanged.subscribe(spy);
391+
it('pressing enter on the currently selected date should close the calendar without firing selectedChanged', fakeAsync(() => {
392+
const spy = jasmine.createSpy('selectionChanged spy');
393+
const selectedSubscription = model.selectionChanged.subscribe(spy);
397394

398-
testComponent.datepicker.open();
399-
fixture.detectChanges();
400-
tick();
401-
flush();
395+
testComponent.datepicker.open();
396+
fixture.detectChanges();
397+
tick();
398+
flush();
402399

403-
let calendarBodyEl = document.querySelector('.mat-calendar-body') as HTMLElement;
404-
expect(calendarBodyEl).not.toBeNull();
405-
expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 1));
400+
let calendarBodyEl = document.querySelector('.mat-calendar-body') as HTMLElement;
401+
expect(calendarBodyEl).not.toBeNull();
402+
expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 1));
406403

407-
dispatchKeyboardEvent(calendarBodyEl, 'keydown', ENTER);
408-
fixture.detectChanges();
409-
flush();
404+
dispatchKeyboardEvent(calendarBodyEl, 'keydown', ENTER);
405+
fixture.detectChanges();
406+
flush();
410407

411-
fixture.whenStable().then(() => {
412-
expect(spy).not.toHaveBeenCalled();
413-
expect(document.querySelector('.mat-datepicker-dialog')).toBeNull();
414-
expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 1));
415-
selectedSubscription.unsubscribe();
416-
});
417-
}),
418-
);
408+
expect(spy).not.toHaveBeenCalled();
409+
expect(document.querySelector('.mat-datepicker-dialog')).toBeNull();
410+
expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 1));
411+
selectedSubscription.unsubscribe();
412+
}));
419413

420414
it('startAt should fallback to input value', () => {
421415
expect(testComponent.datepicker.startAt).toEqual(new Date(2020, JAN, 1));
@@ -884,15 +878,10 @@ describe('MatDatepicker', () => {
884878
beforeEach(fakeAsync(() => {
885879
fixture = createComponent(DatepickerWithNgModel, [MatNativeDateModule]);
886880
fixture.detectChanges();
887-
888-
fixture.whenStable().then(() => {
889-
fixture.detectChanges();
890-
891-
testComponent = fixture.componentInstance;
892-
model = fixture.debugElement
893-
.query(By.directive(MatDatepicker))
894-
.injector.get(MatDateSelectionModel);
895-
});
881+
testComponent = fixture.componentInstance;
882+
model = fixture.debugElement
883+
.query(By.directive(MatDatepicker))
884+
.injector.get(MatDateSelectionModel);
896885
}));
897886

898887
afterEach(fakeAsync(() => {

src/material/dialog/testing/dialog-opener.spec.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,12 @@ describe('MatTestDialogOpener', () => {
2424
);
2525
});
2626

27-
it('should pass data to the component', async () => {
27+
it('should pass data to the component', () => {
2828
const config = {data: 'test'};
2929
const fixture = TestBed.createComponent(
3030
MatTestDialogOpener.withComponent(ExampleComponent, config),
3131
);
3232
fixture.detectChanges();
33-
await fixture.whenStable();
3433
const dialogContainer = document.querySelector('mat-dialog-container');
3534
expect(dialogContainer!.innerHTML).toContain('Data: test');
3635
});

src/material/menu/menu.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,13 +1255,13 @@ describe('MatMenu', () => {
12551255
expect(destroyCount).withContext('Expected ngOnDestroy to have been called').toBe(2);
12561256
}));
12571257

1258-
it('should focus the first menu item when opening a lazy menu via keyboard', async () => {
1258+
it('should focus the first menu item when opening a lazy menu via keyboard', () => {
12591259
const fixture = createComponent(SimpleLazyMenu);
1260-
fixture.autoDetectChanges();
1260+
fixture.detectChanges();
12611261

12621262
// A click without a mousedown before it is considered a keyboard open.
12631263
fixture.componentInstance.triggerEl.nativeElement.click();
1264-
await fixture.whenStable();
1264+
fixture.detectChanges();
12651265

12661266
const item = document.querySelector('.mat-mdc-menu-panel [mat-menu-item]')!;
12671267

0 commit comments

Comments
 (0)