From 2544a223e79d553fe8be12bd2a61bd5a5d640074 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sun, 17 May 2026 11:45:50 +0200 Subject: [PATCH] refactor(material/timepicker): switch tests away from fakeAsync Reworks the timepicker tests to no longer use `fakeAsync`. --- src/material/timepicker/timepicker.spec.ts | 97 +++++++++++----------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/src/material/timepicker/timepicker.spec.ts b/src/material/timepicker/timepicker.spec.ts index baa908fd5d3a..0907f469f291 100644 --- a/src/material/timepicker/timepicker.spec.ts +++ b/src/material/timepicker/timepicker.spec.ts @@ -7,7 +7,7 @@ import { ViewEncapsulation, ChangeDetectionStrategy, } from '@angular/core'; -import {ComponentFixture, fakeAsync, flush, TestBed} from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import {DateAdapter, MATERIAL_ANIMATIONS, provideNativeDateAdapter} from '../core'; import { clearElement, @@ -45,7 +45,7 @@ describe('MatTimepicker', () => { beforeEach(() => configureTestingModule()); describe('value selection', () => { - it('should only change the time part of the selected date', fakeAsync(() => { + it('should only change the time part of the selected date', async () => { const fixture = TestBed.createComponent(StandaloneTimepicker); fixture.componentInstance.value.set(new Date(2024, 0, 15, 0, 0, 0)); fixture.detectChanges(); @@ -54,7 +54,7 @@ describe('MatTimepicker', () => { getOptions()[3].click(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); const value = fixture.componentInstance.input.value()!; expect(value).toBeTruthy(); @@ -64,9 +64,9 @@ describe('MatTimepicker', () => { expect(adapter.getHours(value)).toBe(1); expect(adapter.getMinutes(value)).toBe(30); expect(adapter.getSeconds(value)).toBe(0); - })); + }); - it('should accept the selected value and close the panel when clicking an option', fakeAsync(() => { + it('should accept the selected value and close the panel when clicking an option', async () => { const fixture = TestBed.createComponent(StandaloneTimepicker); const input = getInput(fixture); fixture.detectChanges(); @@ -79,7 +79,7 @@ describe('MatTimepicker', () => { getOptions()[1].click(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); expect(getPanel()).toBeFalsy(); expect(input.value).toBe('12:30 AM'); @@ -91,9 +91,9 @@ describe('MatTimepicker', () => { value: jasmine.any(Date), }), ); - })); + }); - it('should support two-way binding on the `value` input', fakeAsync(() => { + it('should support two-way binding on the `value` input', async () => { const fixture = TestBed.createComponent(TimepickerTwoWayBinding); const input = getInput(fixture); fixture.detectChanges(); @@ -115,14 +115,14 @@ describe('MatTimepicker', () => { // Propagation from host down to input fixture.componentInstance.value.set(createTime(13, 37)); fixture.detectChanges(); - flush(); + await fixture.whenStable(); value = inputInstance.value()!; expect(adapter.getHours(value)).toBe(13); expect(adapter.getMinutes(value)).toBe(37); expectSameTime(fixture.componentInstance.value(), value); - })); + }); - it('should emit the `selected` event if the option being clicked was selected already', fakeAsync(() => { + it('should emit the `selected` event if the option being clicked was selected already', async () => { const fixture = TestBed.createComponent(StandaloneTimepicker); fixture.componentInstance.value.set(new Date(2024, 0, 15, 2, 30, 0)); fixture.detectChanges(); @@ -132,7 +132,7 @@ describe('MatTimepicker', () => { getOptions()[getActiveOptionIndex()].click(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); expect(getPanel()).toBeFalsy(); expect(fixture.componentInstance.selectedSpy).toHaveBeenCalledTimes(1); @@ -142,7 +142,7 @@ describe('MatTimepicker', () => { value: jasmine.any(Date), }), ); - })); + }); }); describe('input behavior', () => { @@ -343,7 +343,7 @@ describe('MatTimepicker', () => { expect(getPanel()).toBeFalsy(); }); - it('should close the timepicker when clicking outside', fakeAsync(() => { + it('should close the timepicker when clicking outside', async () => { const fixture = TestBed.createComponent(StandaloneTimepicker); fixture.detectChanges(); getInput(fixture).click(); @@ -351,11 +351,11 @@ describe('MatTimepicker', () => { expect(getPanel()).toBeTruthy(); document.body.click(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); expect(getPanel()).toBeFalsy(); - })); + }); - it('should close the timepicker when tabbing away from the input', fakeAsync(() => { + it('should close the timepicker when tabbing away from the input', async () => { const fixture = TestBed.createComponent(StandaloneTimepicker); fixture.detectChanges(); getInput(fixture).click(); @@ -363,11 +363,11 @@ describe('MatTimepicker', () => { expect(getPanel()).toBeTruthy(); dispatchKeyboardEvent(getInput(fixture), 'keydown', TAB); fixture.detectChanges(); - flush(); + await fixture.whenStable(); expect(getPanel()).toBeFalsy(); - })); + }); - it('should close the timepicker when pressing escape', fakeAsync(() => { + it('should close the timepicker when pressing escape', async () => { const fixture = TestBed.createComponent(StandaloneTimepicker); fixture.detectChanges(); getInput(fixture).click(); @@ -375,12 +375,12 @@ describe('MatTimepicker', () => { expect(getPanel()).toBeTruthy(); const event = dispatchKeyboardEvent(document.body, 'keydown', ESCAPE); fixture.detectChanges(); - flush(); + await fixture.whenStable(); expect(getPanel()).toBeFalsy(); expect(event.defaultPrevented).toBe(true); - })); + }); - it('should emit events on open/close', fakeAsync(() => { + it('should emit events on open/close', async () => { const fixture = TestBed.createComponent(StandaloneTimepicker); fixture.detectChanges(); const {openedSpy, closedSpy} = fixture.componentInstance; @@ -394,10 +394,10 @@ describe('MatTimepicker', () => { document.body.click(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); expect(openedSpy).toHaveBeenCalledTimes(1); expect(closedSpy).toHaveBeenCalledTimes(1); - })); + }); it('should clean up the overlay if it is open on destroy', () => { const fixture = TestBed.createComponent(StandaloneTimepicker); @@ -409,7 +409,7 @@ describe('MatTimepicker', () => { expect(getPanel()).toBeFalsy(); }); - it('should be able to open and close the panel programmatically', fakeAsync(() => { + it('should be able to open and close the panel programmatically', async () => { const fixture = TestBed.createComponent(StandaloneTimepicker); fixture.detectChanges(); fixture.componentInstance.timepicker.open(); @@ -417,9 +417,9 @@ describe('MatTimepicker', () => { expect(getPanel()).toBeTruthy(); fixture.componentInstance.timepicker.close(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); expect(getPanel()).toBeFalsy(); - })); + }); it('should focus the input when opened programmatically', () => { const fixture = TestBed.createComponent(StandaloneTimepicker); @@ -431,7 +431,7 @@ describe('MatTimepicker', () => { expect(document.activeElement).toBe(input); }); - it('should expose the current open state', fakeAsync(() => { + it('should expose the current open state', async () => { const fixture = TestBed.createComponent(StandaloneTimepicker); fixture.detectChanges(); const timepicker = fixture.componentInstance.timepicker; @@ -441,12 +441,12 @@ describe('MatTimepicker', () => { expect(timepicker.isOpen()).toBe(true); timepicker.close(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); expect(timepicker.isOpen()).toBe(false); - })); + }); // Note: this will be a type checking error, but we check it just in case for JIT mode. - it('should do nothing if trying to open a timepicker without an input', fakeAsync(() => { + it('should do nothing if trying to open a timepicker without an input', async () => { const fixture = TestBed.createComponent(TimepickerWithoutInput); fixture.detectChanges(); fixture.componentInstance.timepicker.open(); @@ -456,11 +456,10 @@ describe('MatTimepicker', () => { expect(() => { fixture.componentInstance.timepicker.close(); fixture.detectChanges(); - flush(); }).not.toThrow(); - })); + }); - it('should be able to reopen the panel when closed by a scroll strategy', fakeAsync(() => { + it('should be able to reopen the panel when closed by a scroll strategy', async () => { const scrolledSubject = new Subject(); TestBed.resetTestingModule(); @@ -482,12 +481,12 @@ describe('MatTimepicker', () => { expect(getPanel()).toBeTruthy(); scrolledSubject.next(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); expect(getPanel()).toBeFalsy(); fixture.componentInstance.timepicker.open(); fixture.detectChanges(); expect(getPanel()).toBeTruthy(); - })); + }); it('should be able to opt out of opening on click', () => { const fixture = TestBed.createComponent(StandaloneTimepicker); @@ -822,7 +821,7 @@ describe('MatTimepicker', () => { expect(event.defaultPrevented).toBe(true); }); - it('should select the active option and close when pressing enter', fakeAsync(() => { + it('should select the active option and close when pressing enter', async () => { const fixture = TestBed.createComponent(StandaloneTimepicker); const input = getInput(fixture); fixture.detectChanges(); @@ -842,7 +841,7 @@ describe('MatTimepicker', () => { const event = dispatchKeyboardEvent(input, 'keydown', ENTER); fixture.detectChanges(); - flush(); + await fixture.whenStable(); expect(input.value).toBe('1:30 AM'); expectSameTime(fixture.componentInstance.input.value(), createTime(1, 30)); @@ -855,7 +854,7 @@ describe('MatTimepicker', () => { value: jasmine.any(Date), }), ); - })); + }); it('should not navigate using the left/right arrow keys', () => { const fixture = TestBed.createComponent(StandaloneTimepicker); @@ -1040,7 +1039,7 @@ describe('MatTimepicker', () => { expect(fixture.componentInstance.control.touched).toBe(true); }); - it('should mark the control as touched when the panel is closed', fakeAsync(() => { + it('should mark the control as touched when the panel is closed', async () => { const fixture = TestBed.createComponent(TimepickerWithForms); fixture.detectChanges(); expect(fixture.componentInstance.control.touched).toBe(false); @@ -1051,9 +1050,9 @@ describe('MatTimepicker', () => { document.body.click(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); expect(fixture.componentInstance.control.touched).toBe(true); - })); + }); it('should not set the `required` error if there is no valid value in the input', () => { const fixture = TestBed.createComponent(TimepickerWithForms); @@ -1071,7 +1070,7 @@ describe('MatTimepicker', () => { expect(control.errors?.['required']).toBeFalsy(); }); - it('should set an error if the user enters an invalid time string', fakeAsync(() => { + it('should set an error if the user enters an invalid time string', () => { const fixture = TestBed.createComponent(TimepickerWithForms); const control = fixture.componentInstance.control; const input = getInput(fixture); @@ -1115,9 +1114,9 @@ describe('MatTimepicker', () => { fixture.detectChanges(); expect(control.errors?.['matTimepickerParse']).toBeFalsy(); expectSameTime(control.value, createTime(12, 10)); - })); + }); - it('should set an error if the user enters a time earlier than the minimum', fakeAsync(() => { + it('should set an error if the user enters a time earlier than the minimum', async () => { const fixture = TestBed.createComponent(TimepickerWithForms); const control = fixture.componentInstance.control; const input = getInput(fixture); @@ -1138,9 +1137,9 @@ describe('MatTimepicker', () => { fixture.componentInstance.min.set(createTime(11, 0)); fixture.detectChanges(); expect(control.errors?.['matTimepickerMin']).toBeFalsy(); - })); + }); - it('should set an error if the user enters a time later than the maximum', fakeAsync(() => { + it('should set an error if the user enters a time later than the maximum', async () => { const fixture = TestBed.createComponent(TimepickerWithForms); const control = fixture.componentInstance.control; const input = getInput(fixture); @@ -1161,7 +1160,7 @@ describe('MatTimepicker', () => { fixture.componentInstance.max.set(createTime(13, 0)); fixture.detectChanges(); expect(control.errors?.['matTimepickerMax']).toBeFalsy(); - })); + }); it('should mark the input as disabled when the form control is disabled', () => { const fixture = TestBed.createComponent(TimepickerWithForms);