Skip to content

Commit 357cfd3

Browse files
authored
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.
1 parent f573ce8 commit 357cfd3

File tree

11 files changed

+114
-166
lines changed

11 files changed

+114
-166
lines changed

Diff for: src/cdk/a11y/focus-trap/focus-trap.spec.ts

+22-34
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;

Diff for: src/cdk/overlay/overlay.spec.ts

-2
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,6 @@ describe('Overlay', () => {
955955
const overlayRef = overlay.create(config);
956956

957957
overlayRef.attach(componentPortal);
958-
await viewContainerFixture.whenStable();
959958

960959
const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
961960
expect(pane.classList)
@@ -968,7 +967,6 @@ describe('Overlay', () => {
968967
expect(pane.classList)
969968
.withContext('Expected class not to be removed immediately')
970969
.toContain('custom-panel-class');
971-
await viewContainerFixture.whenStable();
972970

973971
pane.children[0].remove();
974972
await new Promise(r => setTimeout(r));

Diff for: src/cdk/scrolling/virtual-scroll-viewport.spec.ts

+2-4
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
}));

Diff for: src/material/bottom-sheet/bottom-sheet.spec.ts

+10-16
Original file line numberDiff line numberDiff line change
@@ -650,24 +650,18 @@ describe('MatBottomSheet', () => {
650650
expect(focusTrapAnchors.length).toBeGreaterThan(0);
651651
}));
652652

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

662-
viewContainerFixture.detectChanges();
663-
await viewContainerFixture.whenStable();
664-
viewContainerFixture.detectChanges();
659+
viewContainerFixture.detectChanges();
665660

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

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

Diff for: src/material/chips/chip-grid.spec.ts

+36-42
Original file line numberDiff line numberDiff line change
@@ -935,20 +935,18 @@ describe('MatChipGrid', () => {
935935
flush();
936936
fixture.detectChanges();
937937

938-
fixture.whenStable().then(() => {
939-
expect(errorTestComponent.form.submitted)
940-
.withContext('Expected form to have been submitted')
941-
.toBe(true);
942-
expect(containerEl.classList)
943-
.withContext('Expected container to have the invalid CSS class.')
944-
.toContain('mat-form-field-invalid');
945-
expect(containerEl.querySelectorAll('mat-error').length)
946-
.withContext('Expected one error message to have been rendered.')
947-
.toBe(1);
948-
expect(chipGridEl.getAttribute('aria-invalid'))
949-
.withContext('Expected aria-invalid to be set to "true".')
950-
.toBe('true');
951-
});
938+
expect(errorTestComponent.form.submitted)
939+
.withContext('Expected form to have been submitted')
940+
.toBe(true);
941+
expect(containerEl.classList)
942+
.withContext('Expected container to have the invalid CSS class.')
943+
.toContain('mat-form-field-invalid');
944+
expect(containerEl.querySelectorAll('mat-error').length)
945+
.withContext('Expected one error message to have been rendered.')
946+
.toBe(1);
947+
expect(chipGridEl.getAttribute('aria-invalid'))
948+
.withContext('Expected aria-invalid to be set to "true".')
949+
.toBe('true');
952950
flush();
953951
}));
954952

@@ -957,36 +955,32 @@ describe('MatChipGrid', () => {
957955
flush();
958956
fixture.detectChanges();
959957

960-
fixture.whenStable().then(() => {
961-
expect(containerEl.classList)
962-
.withContext('Expected container to have the invalid CSS class.')
963-
.toContain('mat-form-field-invalid');
964-
expect(containerEl.querySelectorAll('mat-error').length)
965-
.withContext('Expected one error message to have been rendered.')
966-
.toBe(1);
967-
expect(containerEl.querySelectorAll('mat-hint').length)
968-
.withContext('Expected no hints to be shown.')
969-
.toBe(0);
970-
971-
errorTestComponent.formControl.setValue('something');
972-
flush();
973-
fixture.detectChanges();
958+
expect(containerEl.classList)
959+
.withContext('Expected container to have the invalid CSS class.')
960+
.toContain('mat-form-field-invalid');
961+
expect(containerEl.querySelectorAll('mat-error').length)
962+
.withContext('Expected one error message to have been rendered.')
963+
.toBe(1);
964+
expect(containerEl.querySelectorAll('mat-hint').length)
965+
.withContext('Expected no hints to be shown.')
966+
.toBe(0);
974967

975-
fixture.whenStable().then(() => {
976-
expect(containerEl.classList).not.toContain(
977-
'mat-form-field-invalid',
978-
'Expected container not to have the invalid class when valid.',
979-
);
980-
expect(containerEl.querySelectorAll('mat-error').length)
981-
.withContext('Expected no error messages when the input is valid.')
982-
.toBe(0);
983-
expect(containerEl.querySelectorAll('mat-hint').length)
984-
.withContext('Expected one hint to be shown once the input is valid.')
985-
.toBe(1);
986-
});
968+
errorTestComponent.formControl.setValue('something');
969+
flush();
970+
fixture.detectChanges();
987971

988-
flush();
989-
});
972+
expect(containerEl.classList).not.toContain(
973+
'mat-form-field-invalid',
974+
'Expected container not to have the invalid class when valid.',
975+
);
976+
expect(containerEl.querySelectorAll('mat-error').length)
977+
.withContext('Expected no error messages when the input is valid.')
978+
.toBe(0);
979+
expect(containerEl.querySelectorAll('mat-hint').length)
980+
.withContext('Expected one hint to be shown once the input is valid.')
981+
.toBe(1);
982+
983+
flush();
990984
}));
991985

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

Diff for: src/material/datepicker/datepicker.spec.ts

+22-33
Original file line numberDiff line numberDiff line change
@@ -389,34 +389,28 @@ describe('MatDatepicker', () => {
389389
}),
390390
);
391391

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

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

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

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

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

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

899888
afterEach(fakeAsync(() => {

Diff for: src/material/dialog/testing/dialog-opener.spec.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@ describe('MatTestDialogOpener', () => {
1717
);
1818
});
1919

20-
it('should pass data to the component', async () => {
20+
it('should pass data to the component', () => {
2121
const config = {data: 'test'};
2222
const fixture = TestBed.createComponent(
2323
MatTestDialogOpener.withComponent(ExampleComponent, config),
2424
);
2525
fixture.detectChanges();
26-
await fixture.whenStable();
2726
const dialogContainer = document.querySelector('mat-dialog-container');
2827
expect(dialogContainer!.innerHTML).toContain('Data: test');
2928
});

Diff for: src/material/menu/menu.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1261,13 +1261,13 @@ describe('MatMenu', () => {
12611261
expect(destroyCount).withContext('Expected ngOnDestroy to have been called').toBe(2);
12621262
}));
12631263

1264-
it('should focus the first menu item when opening a lazy menu via keyboard', async () => {
1264+
it('should focus the first menu item when opening a lazy menu via keyboard', () => {
12651265
const fixture = createComponent(SimpleLazyMenu);
1266-
fixture.autoDetectChanges();
1266+
fixture.detectChanges();
12671267

12681268
// A click without a mousedown before it is considered a keyboard open.
12691269
fixture.componentInstance.triggerEl.nativeElement.click();
1270-
await fixture.whenStable();
1270+
fixture.detectChanges();
12711271

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

0 commit comments

Comments
 (0)