diff --git a/src/cdk-experimental/selection/selection.spec.ts b/src/cdk-experimental/selection/selection.spec.ts index 821e57e784ee..8fe14dc688cc 100644 --- a/src/cdk-experimental/selection/selection.spec.ts +++ b/src/cdk-experimental/selection/selection.spec.ts @@ -308,11 +308,12 @@ describe('cdkSelectionColumn', () => { }); })); - beforeEach(() => { + beforeEach(fakeAsync(() => { fixture = TestBed.createComponent(MultiSelectTableWithSelectionColumn); component = fixture.componentInstance; fixture.detectChanges(); - }); + flush(); + })); it('should show check boxes', () => { const checkboxes = @@ -585,6 +586,7 @@ class MultiSelectTableWithSelectionColumn { this.getSelectAll().click(); flush(); this._cdr.detectChanges(); + flush(); } clickSelectionToggle(index: number) { @@ -596,6 +598,7 @@ class MultiSelectTableWithSelectionColumn { toggle.click(); flush(); this._cdr.detectChanges(); + flush(); } constructor( @@ -648,6 +651,7 @@ class SingleSelectTableWithSelectionColumn { toggle.click(); flush(); this._cdr.detectChanges(); + flush(); } constructor( diff --git a/src/cdk/bidi/directionality.spec.ts b/src/cdk/bidi/directionality.spec.ts index 41330a27b495..03a64b684547 100644 --- a/src/cdk/bidi/directionality.spec.ts +++ b/src/cdk/bidi/directionality.spec.ts @@ -1,4 +1,4 @@ -import {waitForAsync, fakeAsync, TestBed} from '@angular/core/testing'; +import {waitForAsync, fakeAsync, TestBed, flush} from '@angular/core/testing'; import {Component, ViewChild, signal} from '@angular/core'; import {By} from '@angular/platform-browser'; import {BidiModule, Directionality, Dir, Direction, DIR_DOCUMENT} from './index'; @@ -121,6 +121,7 @@ describe('Directionality', () => { fixture.destroy(); expect(spy).toHaveBeenCalled(); subscription.unsubscribe(); + flush(); })); it('should default to ltr if an invalid value is passed in', () => { diff --git a/src/cdk/overlay/dispatchers/overlay-outside-click-dispatcher.spec.ts b/src/cdk/overlay/dispatchers/overlay-outside-click-dispatcher.spec.ts index 1d68d7806803..b738ab16194e 100644 --- a/src/cdk/overlay/dispatchers/overlay-outside-click-dispatcher.spec.ts +++ b/src/cdk/overlay/dispatchers/overlay-outside-click-dispatcher.spec.ts @@ -1,4 +1,4 @@ -import {TestBed, inject, fakeAsync} from '@angular/core/testing'; +import {TestBed, inject} from '@angular/core/testing'; import {ApplicationRef, Component, afterRender} from '@angular/core'; import {dispatchFakeEvent, dispatchMouseEvent} from '../../testing/private'; import {OverlayModule, Overlay} from '../index'; @@ -305,39 +305,35 @@ describe('OverlayOutsideClickDispatcher', () => { overlayRef.dispose(); }); - it( - 'should not throw an error when closing out related components via the ' + - 'outsidePointerEvents emitter on background click', - fakeAsync(() => { - const firstOverlayRef = overlay.create(); - firstOverlayRef.attach(new ComponentPortal(TestComponent)); - const secondOverlayRef = overlay.create(); - secondOverlayRef.attach(new ComponentPortal(TestComponent)); - const thirdOverlayRef = overlay.create(); - thirdOverlayRef.attach(new ComponentPortal(TestComponent)); - - const spy = jasmine.createSpy('background click handler spy').and.callFake(() => { - // we close out both overlays from a single outside click event - firstOverlayRef.detach(); - thirdOverlayRef.detach(); - }); - firstOverlayRef.outsidePointerEvents().subscribe(spy); - secondOverlayRef.outsidePointerEvents().subscribe(spy); - thirdOverlayRef.outsidePointerEvents().subscribe(spy); + it('should not throw an error when closing out related components via the outsidePointerEvents emitter on background click', () => { + const firstOverlayRef = overlay.create(); + firstOverlayRef.attach(new ComponentPortal(TestComponent)); + const secondOverlayRef = overlay.create(); + secondOverlayRef.attach(new ComponentPortal(TestComponent)); + const thirdOverlayRef = overlay.create(); + thirdOverlayRef.attach(new ComponentPortal(TestComponent)); + + const spy = jasmine.createSpy('background click handler spy').and.callFake(() => { + // we close out both overlays from a single outside click event + firstOverlayRef.detach(); + thirdOverlayRef.detach(); + }); + firstOverlayRef.outsidePointerEvents().subscribe(spy); + secondOverlayRef.outsidePointerEvents().subscribe(spy); + thirdOverlayRef.outsidePointerEvents().subscribe(spy); - const backgroundElement = document.createElement('div'); - document.body.appendChild(backgroundElement); + const backgroundElement = document.createElement('div'); + document.body.appendChild(backgroundElement); - expect(() => backgroundElement.click()).not.toThrowError(); + expect(() => backgroundElement.click()).not.toThrowError(); - expect(spy).toHaveBeenCalled(); + expect(spy).toHaveBeenCalled(); - backgroundElement.remove(); - firstOverlayRef.dispose(); - secondOverlayRef.dispose(); - thirdOverlayRef.dispose(); - }), - ); + backgroundElement.remove(); + firstOverlayRef.dispose(); + secondOverlayRef.dispose(); + thirdOverlayRef.dispose(); + }); describe('change detection behavior', () => { it('should not run change detection if there is no portal attached to the overlay', () => { diff --git a/src/cdk/overlay/overlay.spec.ts b/src/cdk/overlay/overlay.spec.ts index 77048fdc5dc0..8acf58d68314 100644 --- a/src/cdk/overlay/overlay.spec.ts +++ b/src/cdk/overlay/overlay.spec.ts @@ -528,6 +528,7 @@ describe('Overlay', () => { tick(); overlayRef.attach(componentPortal); + tick(); expect(overlayPresentInDom) .withContext('Expected host element to be attached to the DOM.') diff --git a/src/cdk/scrolling/virtual-scroll-viewport.spec.ts b/src/cdk/scrolling/virtual-scroll-viewport.spec.ts index c3233c3eafef..de6e7072ac02 100644 --- a/src/cdk/scrolling/virtual-scroll-viewport.spec.ts +++ b/src/cdk/scrolling/virtual-scroll-viewport.spec.ts @@ -83,6 +83,7 @@ describe('CdkVirtualScrollViewport', () => { flush(); viewport.checkViewportSize(); expect(viewport.getViewportSize()).toBe(500); + flush(); })); it('should update the viewport size when the page viewport changes', fakeAsync(() => { @@ -112,12 +113,14 @@ describe('CdkVirtualScrollViewport', () => { fixture.componentInstance.items = [0, 1]; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); + flush(); expect(viewport.getRenderedRange()).toEqual({start: 0, end: 2}); fixture.componentInstance.items = []; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); + flush(); expect(viewport.getRenderedRange()).toEqual({start: 0, end: 0}); })); diff --git a/src/material-experimental/column-resize/column-resize.spec.ts b/src/material-experimental/column-resize/column-resize.spec.ts index 2ea243f4ee93..b109a924e0d0 100644 --- a/src/material-experimental/column-resize/column-resize.spec.ts +++ b/src/material-experimental/column-resize/column-resize.spec.ts @@ -2,7 +2,7 @@ import {BidiModule} from '@angular/cdk/bidi'; import {DataSource} from '@angular/cdk/collections'; import {ESCAPE} from '@angular/cdk/keycodes'; import {ChangeDetectionStrategy, Component, Directive, ElementRef, ViewChild} from '@angular/core'; -import {ComponentFixture, TestBed, fakeAsync, flushMicrotasks} from '@angular/core/testing'; +import {ComponentFixture, TestBed, fakeAsync, flush} from '@angular/core/testing'; import {MatTableModule} from '@angular/material/table'; import {BehaviorSubject} from 'rxjs'; import {dispatchKeyboardEvent} from '../../cdk/testing/private'; @@ -379,7 +379,7 @@ describe('Material Popover Edit', () => { fixture = TestBed.createComponent(componentClass); component = fixture.componentInstance; fixture.detectChanges(); - flushMicrotasks(); + flush(); })); it('shows resize handle overlays on header row hover and while a resize handle is in use', fakeAsync(() => { @@ -427,7 +427,7 @@ describe('Material Popover Edit', () => { component.completeResizeWithMouseInProgress(0); component.endHoverState(); fixture.detectChanges(); - flushMicrotasks(); + flush(); expect(component.getOverlayThumbElement(0)).toBeUndefined(); })); @@ -445,7 +445,7 @@ describe('Material Popover Edit', () => { const initialThumbPosition = component.getOverlayThumbPosition(1); component.updateResizeWithMouseInProgress(5); fixture.detectChanges(); - flushMicrotasks(); + flush(); let thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition; let columnPositionDelta = component.getColumnOriginPosition(1) - initialColumnPosition; @@ -463,7 +463,7 @@ describe('Material Popover Edit', () => { component.updateResizeWithMouseInProgress(1); fixture.detectChanges(); - flushMicrotasks(); + flush(); thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition; columnPositionDelta = component.getColumnOriginPosition(1) - initialColumnPosition; @@ -473,7 +473,7 @@ describe('Material Popover Edit', () => { (expect(component.getColumnWidth(1)) as any).isApproximately(initialColumnWidth + 1); component.completeResizeWithMouseInProgress(1); - flushMicrotasks(); + flush(); (expect(component.getColumnWidth(1)) as any).isApproximately(initialColumnWidth + 1); @@ -509,7 +509,7 @@ describe('Material Popover Edit', () => { component.updateResizeWithMouseInProgress(5); fixture.detectChanges(); - flushMicrotasks(); + flush(); let thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition; let columnPositionDelta = component.getColumnOriginPosition(1) - initialColumnPosition; @@ -521,7 +521,7 @@ describe('Material Popover Edit', () => { // (expect(component.getTableWidth()) as any).isApproximately(initialTableWidth + 5); dispatchKeyboardEvent(document, 'keyup', ESCAPE); - flushMicrotasks(); + flush(); (expect(component.getColumnWidth(1)) as any).isApproximately(initialColumnWidth); (expect(component.getTableWidth()) as any).isApproximately(initialTableWidth); @@ -545,7 +545,7 @@ describe('Material Popover Edit', () => { component.resizeColumnWithMouse(1, 5); fixture.detectChanges(); - flushMicrotasks(); + flush(); expect(resize).toEqual({columnId: 'name', size: initialColumnWidth + 5} as any); @@ -564,10 +564,10 @@ describe('Material Popover Edit', () => { component.beginColumnResizeWithMouse(0); component.updateResizeWithMouseInProgress(5); - flushMicrotasks(); + flush(); dispatchKeyboardEvent(document, 'keyup', ESCAPE); - flushMicrotasks(); + flush(); component.endHoverState(); fixture.detectChanges(); @@ -580,7 +580,7 @@ describe('Material Popover Edit', () => { (expect(component.getColumnWidth(1)) as any).not.isApproximately(173); component.columnResize.columnResizeNotifier.resize('name', 173); - flushMicrotasks(); + flush(); (expect(component.getColumnWidth(1)) as any).isApproximately(173); })); diff --git a/src/material/autocomplete/autocomplete.spec.ts b/src/material/autocomplete/autocomplete.spec.ts index edb70b151dee..975c4e7eecff 100644 --- a/src/material/autocomplete/autocomplete.spec.ts +++ b/src/material/autocomplete/autocomplete.spec.ts @@ -356,6 +356,7 @@ describe('MatAutocomplete', () => { ) as NodeListOf; options[1].click(); fixture.detectChanges(); + flush(); expect(fixture.componentInstance.formField.floatLabel) .withContext('Expected label to stay in static state after close.') @@ -379,6 +380,7 @@ describe('MatAutocomplete', () => { ) as NodeListOf; options[1].click(); fixture.detectChanges(); + flush(); expect(fixture.componentInstance.formField.floatLabel) .withContext('Expected label to stay elevated after close.') @@ -1182,6 +1184,7 @@ describe('MatAutocomplete', () => { fixture.componentInstance.trigger._handleKeydown(ENTER_EVENT); fixture.detectChanges(); + flush(); expect(input.value) .withContext(`Expected text field to fill with selected value on ENTER.`) .toContain('Alabama'); @@ -1192,6 +1195,7 @@ describe('MatAutocomplete', () => { flush(); fixture.componentInstance.trigger._handleKeydown(ENTER_EVENT); + flush(); expect(ENTER_EVENT.defaultPrevented) .withContext('Expected the default action to have been prevented.') @@ -1257,6 +1261,7 @@ describe('MatAutocomplete', () => { flush(); fixture.componentInstance.trigger._handleKeydown(ENTER_EVENT); fixture.detectChanges(); + flush(); expect(fixture.componentInstance.stateCtrl.dirty) .withContext(`Expected control to become dirty when option was selected by ENTER.`) @@ -1444,6 +1449,7 @@ describe('MatAutocomplete', () => { dispatchKeyboardEvent(document.body, 'keydown', ESCAPE); fixture.detectChanges(); + flush(); expect(document.activeElement) .withContext('Expected input to continue to be focused.') @@ -1451,12 +1457,12 @@ describe('MatAutocomplete', () => { expect(trigger.panelOpen).withContext('Expected panel to be closed.').toBe(false); })); - it('should prevent the default action when pressing escape', fakeAsync(() => { + it('should prevent the default action when pressing escape', () => { const escapeEvent = dispatchKeyboardEvent(input, 'keydown', ESCAPE); fixture.detectChanges(); expect(escapeEvent.defaultPrevented).toBe(true); - })); + }); it('should not close the panel when pressing escape with a modifier', fakeAsync(() => { const trigger = fixture.componentInstance.trigger; @@ -1494,6 +1500,7 @@ describe('MatAutocomplete', () => { dispatchEvent(document.body, upArrowEvent); fixture.detectChanges(); + flush(); expect(document.activeElement) .withContext('Expected input to continue to be focused.') @@ -2976,7 +2983,7 @@ describe('MatAutocomplete', () => { }); describe('with panel classes in the default options', () => { - it('should apply them if provided as string', fakeAsync(() => { + it('should apply them if provided as string', () => { const fixture = createComponent(SimpleAutocomplete, [ {provide: MAT_AUTOCOMPLETE_DEFAULT_OPTIONS, useValue: {overlayPanelClass: 'default1'}}, ]); @@ -2987,9 +2994,9 @@ describe('MatAutocomplete', () => { const panelClassList = overlayContainerElement.querySelector('.cdk-overlay-pane')!.classList; expect(panelClassList).toContain('default1'); - })); + }); - it('should apply them if provided as array', fakeAsync(() => { + it('should apply them if provided as array', () => { const fixture = createComponent(SimpleAutocomplete, [ { provide: MAT_AUTOCOMPLETE_DEFAULT_OPTIONS, @@ -3004,7 +3011,7 @@ describe('MatAutocomplete', () => { const panelClassList = overlayContainerElement.querySelector('.cdk-overlay-pane')!.classList; expect(panelClassList).toContain('default1'); expect(panelClassList).toContain('default2'); - })); + }); }); describe('misc', () => { @@ -3170,7 +3177,7 @@ describe('MatAutocomplete', () => { expect(trigger.panelOpen).withContext('Expected panel to be closed.').toBe(false); })); - it('should handle autocomplete being attached to number inputs', fakeAsync(() => { + it('should handle autocomplete being attached to number inputs', () => { const fixture = createComponent(AutocompleteWithNumberInputAndNgModel); fixture.detectChanges(); const input = fixture.debugElement.query(By.css('input'))!.nativeElement; @@ -3179,9 +3186,9 @@ describe('MatAutocomplete', () => { fixture.detectChanges(); expect(fixture.componentInstance.selectedValue).toBe(1337); - })); + }); - it('should not focus the option when DOWN key is pressed', fakeAsync(() => { + it('should not focus the option when DOWN key is pressed', () => { const fixture = createComponent(SimpleAutocomplete); const input = fixture.debugElement.query(By.css('input'))!.nativeElement; fixture.detectChanges(); @@ -3194,7 +3201,7 @@ describe('MatAutocomplete', () => { // Note: for some reason the error here gets logged using console.error, rather than being // thrown, hence why we use a spy to assert against it, rather than `.not.toThrow`. expect(spy).not.toHaveBeenCalled(); - })); + }); }); describe('automatically selecting the active option', () => { @@ -3584,32 +3591,27 @@ describe('MatAutocomplete', () => { expect(Math.ceil(parseFloat(overlayPane.style.width as string))).toBe(400); }); - it( - 'should show the panel when the options are initialized later within a component with ' + - 'OnPush change detection', - fakeAsync(() => { - let fixture = createComponent(AutocompleteWithOnPushDelay); - - fixture.detectChanges(); - dispatchFakeEvent(fixture.debugElement.query(By.css('input'))!.nativeElement, 'focusin'); - tick(1000); + it('should show the panel when the options are initialized later within a component with OnPush change detection', fakeAsync(() => { + let fixture = createComponent(AutocompleteWithOnPushDelay); + fixture.detectChanges(); + flush(); + dispatchFakeEvent(fixture.debugElement.query(By.css('input'))!.nativeElement, 'focusin'); + tick(1000); - fixture.detectChanges(); - tick(); + fixture.detectChanges(); + tick(); - Promise.resolve().then(() => { - let panel = overlayContainerElement.querySelector( - '.mat-mdc-autocomplete-panel', - ) as HTMLElement; - let visibleClass = 'mat-mdc-autocomplete-visible'; + Promise.resolve().then(() => { + let panel = overlayContainerElement.querySelector( + '.mat-mdc-autocomplete-panel', + ) as HTMLElement; + let visibleClass = 'mat-mdc-autocomplete-visible'; - fixture.detectChanges(); - expect(panel.classList) - .withContext(`Expected panel to be visible.`) - .toContain(visibleClass); - }); - }), - ); + fixture.changeDetectorRef.markForCheck(); + fixture.detectChanges(); + expect(panel.classList).withContext(`Expected panel to be visible.`).toContain(visibleClass); + }); + })); it('should emit an event when an option is selected', waitForAsync(async () => { let fixture = createComponent(AutocompleteWithSelectEvent); @@ -3883,12 +3885,12 @@ describe('MatAutocomplete', () => { describe('when used inside a modal', () => { let fixture: ComponentFixture; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(AutocompleteInsideAModal); fixture.detectChanges(); - })); + }); - it('should add the id of the autocomplete panel to the aria-owns of the modal', fakeAsync(() => { + it('should add the id of the autocomplete panel to the aria-owns of the modal', () => { fixture.componentInstance.trigger.openPanel(); fixture.detectChanges(); @@ -3898,9 +3900,9 @@ describe('MatAutocomplete', () => { expect(modalElement.getAttribute('aria-owns')?.split(' ')) .withContext('expecting modal to own the autocommplete panel') .toContain(panelId); - })); + }); - it('should remove the aria-owns attribute of the modal when the autocomplete panel closes', fakeAsync(() => { + it('should remove the aria-owns attribute of the modal when the autocomplete panel closes', () => { fixture.componentInstance.trigger.openPanel(); fixture.componentInstance.trigger.closePanel(); fixture.detectChanges(); @@ -3908,9 +3910,9 @@ describe('MatAutocomplete', () => { const modalElement = fixture.componentInstance.modal.nativeElement; expect(modalElement.getAttribute('aria-owns')).toBeFalsy(); - })); + }); - it('should readd the aria-owns attribute of the modal when the autocomplete panel opens again', fakeAsync(() => { + it('should readd the aria-owns attribute of the modal when the autocomplete panel opens again', () => { fixture.componentInstance.trigger.openPanel(); fixture.componentInstance.trigger.closePanel(); fixture.componentInstance.trigger.openPanel(); @@ -3922,7 +3924,7 @@ describe('MatAutocomplete', () => { expect(modalElement.getAttribute('aria-owns')?.split(' ')) .withContext('expecting modal to own the autocommplete panel') .toContain(panelId); - })); + }); }); }); diff --git a/src/material/bottom-sheet/bottom-sheet.spec.ts b/src/material/bottom-sheet/bottom-sheet.spec.ts index 6ff758e2fa96..3eb25e436bea 100644 --- a/src/material/bottom-sheet/bottom-sheet.spec.ts +++ b/src/material/bottom-sheet/bottom-sheet.spec.ts @@ -133,7 +133,7 @@ describe('MatBottomSheet', () => { // callback should not be called before animation is complete expect(spy).not.toHaveBeenCalled(); - flushMicrotasks(); + flush(); expect(spy).toHaveBeenCalled(); })); @@ -242,6 +242,7 @@ describe('MatBottomSheet', () => { bottomSheetRef.keydownEvents().subscribe(spy); viewContainerFixture.detectChanges(); + flush(); const backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement; const container = overlayContainerElement.querySelector( @@ -459,7 +460,7 @@ describe('MatBottomSheet', () => { expect(overlayContainerElement.querySelector('mat-bottom-sheet-container')).toBeTruthy(); })); - it('should be able to attach a custom scroll strategy', fakeAsync(() => { + it('should be able to attach a custom scroll strategy', () => { const scrollStrategy: ScrollStrategy = { attach: () => {}, enable: jasmine.createSpy('scroll strategy enable spy'), @@ -468,7 +469,7 @@ describe('MatBottomSheet', () => { bottomSheet.open(PizzaMsg, {scrollStrategy}); expect(scrollStrategy.enable).toHaveBeenCalled(); - })); + }); describe('passing in data', () => { it('should be able to pass in data', () => { @@ -624,7 +625,7 @@ describe('MatBottomSheet', () => { }); viewContainerFixture.detectChanges(); - flushMicrotasks(); + flush(); const focusTrapAnchors = overlayContainerElement.querySelectorAll('.cdk-focus-trap-anchor'); diff --git a/src/material/button-toggle/button-toggle.spec.ts b/src/material/button-toggle/button-toggle.spec.ts index e30088d97a6a..bb9e65895be7 100644 --- a/src/material/button-toggle/button-toggle.spec.ts +++ b/src/material/button-toggle/button-toggle.spec.ts @@ -84,7 +84,7 @@ describe('MatButtonToggle with forms', () => { let groupNgModel: NgModel; let innerButtons: HTMLElement[]; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = TestBed.createComponent(ButtonToggleGroupWithNgModel); fixture.detectChanges(); testComponent = fixture.debugElement.componentInstance; @@ -100,7 +100,7 @@ describe('MatButtonToggle with forms', () => { ); fixture.detectChanges(); - })); + }); it('should update the model before firing change event', fakeAsync(() => { expect(testComponent.modelValue).toBeUndefined(); @@ -134,6 +134,7 @@ describe('MatButtonToggle with forms', () => { .toBe(true); fixture.componentInstance.groupName = 'changed-name'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(groupInstance.name).toBe('changed-name'); @@ -147,6 +148,7 @@ describe('MatButtonToggle with forms', () => { expect(firstButton.getAttribute('name')).toBe(fixture.componentInstance.groupName); fixture.componentInstance.options[0].name = 'changed-name'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(firstButton.getAttribute('name')).toBe(fixture.componentInstance.groupName); }); @@ -213,6 +215,7 @@ describe('MatButtonToggle with forms', () => { const groupElement = groupDebugElement.nativeElement; testComponent.disableRipple = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(groupElement.querySelectorAll('.mat-ripple-element').length).toBe(0); diff --git a/src/material/checkbox/checkbox.spec.ts b/src/material/checkbox/checkbox.spec.ts index 8e0db10bb996..9c029d2bc8e2 100644 --- a/src/material/checkbox/checkbox.spec.ts +++ b/src/material/checkbox/checkbox.spec.ts @@ -264,14 +264,14 @@ describe('MatCheckbox', () => { expect(inputElement.disabled).toBe(false); })); - it('should not toggle `checked` state upon interation while disabled', fakeAsync(() => { + it('should not toggle `checked` state upon interation while disabled', () => { testComponent.isDisabled = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); checkboxNativeElement.click(); expect(checkboxInstance.checked).toBe(false); - })); + }); it('should overwrite indeterminate state when clicked', fakeAsync(() => { testComponent.isIndeterminate = true; @@ -926,7 +926,7 @@ describe('MatCheckbox', () => { // also turn touched. dispatchFakeEvent(inputElement, 'blur'); fixture.detectChanges(); - flushMicrotasks(); + flush(); expect(ngModel.pristine).toBe(false); expect(ngModel.touched).toBe(true); @@ -968,7 +968,7 @@ describe('MatCheckbox', () => { fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flushMicrotasks(); + flush(); }).not.toThrow(); })); diff --git a/src/material/datepicker/datepicker.spec.ts b/src/material/datepicker/datepicker.spec.ts index fef4abbe8081..749f944e990f 100644 --- a/src/material/datepicker/datepicker.spec.ts +++ b/src/material/datepicker/datepicker.spec.ts @@ -1366,6 +1366,7 @@ describe('MatDatepicker', () => { fixture.componentInstance.datepicker.close(); fixture.detectChanges(); + flush(); expect(document.activeElement) .not.withContext('Expected focus not to be restored to toggle.') @@ -1582,6 +1583,7 @@ describe('MatDatepicker', () => { beforeEach(fakeAsync(() => { fixture = createComponent(DatepickerWithMinAndMaxValidation, [MatNativeDateModule]); fixture.detectChanges(); + flush(); testComponent = fixture.componentInstance; })); @@ -1744,12 +1746,12 @@ describe('MatDatepicker', () => { let fixture: ComponentFixture; let testComponent: DatepickerWithFilterAndValidation; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerWithFilterAndValidation, [MatNativeDateModule]); fixture.detectChanges(); testComponent = fixture.componentInstance; - })); + }); afterEach(fakeAsync(() => { testComponent.datepicker.close(); @@ -1966,6 +1968,7 @@ describe('MatDatepicker', () => { beforeEach(fakeAsync(() => { fixture = createComponent(DatepickerWithISOStrings, [MatNativeDateModule]); + flush(); testComponent = fixture.componentInstance; })); @@ -1993,6 +1996,7 @@ describe('MatDatepicker', () => { beforeEach(fakeAsync(() => { fixture = createComponent(DatepickerWithEvents, [MatNativeDateModule]); fixture.detectChanges(); + flush(); testComponent = fixture.componentInstance; })); @@ -2318,7 +2322,7 @@ describe('MatDatepicker', () => { let testComponent: DatepickerWithi18n; let input: HTMLInputElement; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent( DatepickerWithi18n, [MatNativeDateModule, NativeDateModule], @@ -2327,7 +2331,7 @@ describe('MatDatepicker', () => { fixture.detectChanges(); testComponent = fixture.componentInstance; input = fixture.nativeElement.querySelector('input') as HTMLInputElement; - })); + }); it('should have the correct input value even when inverted date format', fakeAsync(() => { if (typeof Intl === 'undefined') { diff --git a/src/material/dialog/dialog.spec.ts b/src/material/dialog/dialog.spec.ts index 953fa5927701..1e64f0005486 100644 --- a/src/material/dialog/dialog.spec.ts +++ b/src/material/dialog/dialog.spec.ts @@ -1243,7 +1243,7 @@ describe('MatDialog', () => { }); viewContainerFixture.detectChanges(); - flushMicrotasks(); + flush(); expect( overlayContainerElement.querySelectorAll('.cdk-focus-trap-anchor').length, diff --git a/src/material/divider/divider.spec.ts b/src/material/divider/divider.spec.ts index c5e7b0057551..3bb8c08c8aee 100644 --- a/src/material/divider/divider.spec.ts +++ b/src/material/divider/divider.spec.ts @@ -1,4 +1,4 @@ -import {fakeAsync, ComponentFixture, TestBed} from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import {Component} from '@angular/core'; import {By} from '@angular/platform-browser'; import {MatDividerModule} from './divider-module'; @@ -6,13 +6,13 @@ import {MatDividerModule} from './divider-module'; describe('MatDivider', () => { let fixture: ComponentFixture; - beforeEach(fakeAsync(() => { + beforeEach(() => { TestBed.configureTestingModule({ imports: [MatDividerModule, MatDividerTestComponent], }); fixture = TestBed.createComponent(MatDividerTestComponent); - })); + }); it('should apply vertical class to vertical divider', () => { fixture.componentInstance.vertical = true; diff --git a/src/material/expansion/expansion.spec.ts b/src/material/expansion/expansion.spec.ts index 157507f935f9..4196816877fe 100644 --- a/src/material/expansion/expansion.spec.ts +++ b/src/material/expansion/expansion.spec.ts @@ -55,16 +55,16 @@ describe('MatExpansionPanel', () => { expect(headerEl.classList).toContain('mat-expanded'); })); - it('should add strong focus indication', fakeAsync(() => { + it('should add strong focus indication', () => { const fixture = TestBed.createComponent(PanelWithContent); fixture.detectChanges(); expect(fixture.nativeElement.querySelector('.mat-expansion-panel-header').classList).toContain( 'mat-focus-indicator', ); - })); + }); - it('should be able to render panel content lazily', fakeAsync(() => { + it('should be able to render panel content lazily', () => { const fixture = TestBed.createComponent(LazyPanelWithContent); const content = fixture.debugElement.query( By.css('.mat-expansion-panel-content'), @@ -82,9 +82,9 @@ describe('MatExpansionPanel', () => { expect(content.textContent.trim()) .withContext('Expected content to be rendered.') .toContain('Some content'); - })); + }); - it('should render the content for a lazy-loaded panel that is opened on init', fakeAsync(() => { + it('should render the content for a lazy-loaded panel that is opened on init', () => { const fixture = TestBed.createComponent(LazyPanelOpenOnLoad); const content = fixture.debugElement.query( By.css('.mat-expansion-panel-content'), @@ -94,9 +94,9 @@ describe('MatExpansionPanel', () => { expect(content.textContent.trim()) .withContext('Expected content to be rendered.') .toContain('Some content'); - })); + }); - it('should not render lazy content from a child panel inside the parent', fakeAsync(() => { + it('should not render lazy content from a child panel inside the parent', () => { const fixture = TestBed.createComponent(NestedLazyPanelWithContent); fixture.componentInstance.parentExpanded = true; fixture.changeDetectorRef.markForCheck(); @@ -126,7 +126,7 @@ describe('MatExpansionPanel', () => { 'Child content', 'Expected child content element to be rendered.', ); - })); + }); it('emit correct events for change in panel expanded state', () => { const fixture = TestBed.createComponent(PanelWithContent); @@ -449,13 +449,13 @@ describe('MatExpansionPanel', () => { expect(header.nativeElement.style.height).toBe('10px'); }); - it('should be able to set a custom tabindex on the header', fakeAsync(() => { + it('should be able to set a custom tabindex on the header', () => { const fixture = TestBed.createComponent(PanelWithHeaderTabindex); const headerEl = fixture.nativeElement.querySelector('.mat-expansion-panel-header'); fixture.detectChanges(); expect(headerEl.getAttribute('tabindex')).toBe('7'); - })); + }); describe('disabled state', () => { let fixture: ComponentFixture; diff --git a/src/material/input/input.spec.ts b/src/material/input/input.spec.ts index b39f6eeb74f1..13c2b1d4f45c 100644 --- a/src/material/input/input.spec.ts +++ b/src/material/input/input.spec.ts @@ -1099,6 +1099,7 @@ describe('MatMdcInput with forms', () => { dispatchFakeEvent(inputEl, 'focus'); dispatchFakeEvent(inputEl, 'blur'); + flush(); expect(wrapperEl.classList).toContain('mdc-text-field--invalid'); })); @@ -1369,7 +1370,7 @@ describe('MatMdcInput with forms', () => { })); }); - it('should update the value when using FormControl.setValue', fakeAsync(() => { + it('should update the value when using FormControl.setValue', () => { let fixture = createComponent(MatInputWithFormControl); fixture.detectChanges(); @@ -1382,7 +1383,7 @@ describe('MatMdcInput with forms', () => { fixture.componentInstance.formControl.setValue('something'); expect(input.value).toBe('something'); - })); + }); it('should display disabled styles when using FormControl.disable()', fakeAsync(() => { const fixture = createComponent(MatInputWithFormControl); diff --git a/src/material/menu/menu.spec.ts b/src/material/menu/menu.spec.ts index 8de903786e8d..0ac3065cdaa0 100644 --- a/src/material/menu/menu.spec.ts +++ b/src/material/menu/menu.spec.ts @@ -501,7 +501,7 @@ describe('MatMenu', () => { expect(event.defaultPrevented).toBe(false); })); - it('should open a custom menu', fakeAsync(() => { + it('should open a custom menu', () => { const fixture = createComponent(CustomMenu, [], [CustomMenuPanel]); fixture.detectChanges(); expect(overlayContainerElement.textContent).toBe(''); @@ -512,7 +512,7 @@ describe('MatMenu', () => { expect(overlayContainerElement.textContent).toContain('Custom Menu header'); expect(overlayContainerElement.textContent).toContain('Custom Content'); }).not.toThrowError(); - })); + }); it('should set the panel direction based on the trigger direction', fakeAsync(() => { const fixture = createComponent( @@ -609,6 +609,7 @@ describe('MatMenu', () => { expect(panel.classList).toContain('mat-elevation-z2'); fixture.componentInstance.panelClass = 'custom-two'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(panel.classList).not.toContain('custom-one'); @@ -719,16 +720,16 @@ describe('MatMenu', () => { expect(secondMenuItemDebugEl.nativeElement.classList).toContain('cdk-mouse-focused'); })); - it('should not throw an error on destroy', fakeAsync(() => { + it('should not throw an error on destroy', () => { const fixture = createComponent(SimpleMenu, [], [FakeIcon]); expect(fixture.destroy.bind(fixture)).not.toThrow(); - })); + }); - it('should be able to extract the menu item text', fakeAsync(() => { + it('should be able to extract the menu item text', () => { const fixture = createComponent(SimpleMenu, [], [FakeIcon]); fixture.detectChanges(); expect(fixture.componentInstance.items.first.getLabel()).toBe('Item'); - })); + }); it('should filter out icon nodes when figuring out the label', fakeAsync(() => { const fixture = createComponent(SimpleMenu, [], [FakeIcon]); @@ -1047,39 +1048,34 @@ describe('MatMenu', () => { flush(); })); - it( - 'should respect the DOM order, rather than insertion order, when moving focus using ' + - 'the arrow keys', - fakeAsync(() => { - let fixture = createComponent(SimpleMenuWithRepeater); + it('should respect the DOM order, rather than insertion order, when moving focus using the arrow keys', fakeAsync(() => { + let fixture = createComponent(SimpleMenuWithRepeater); - fixture.detectChanges(); - fixture.componentInstance.trigger.openMenu(); - fixture.detectChanges(); - tick(500); + fixture.detectChanges(); + fixture.componentInstance.trigger.openMenu(); + fixture.detectChanges(); + tick(500); - let menuPanel = document.querySelector('.mat-mdc-menu-panel')!; - let items = menuPanel.querySelectorAll('.mat-mdc-menu-panel [mat-menu-item]'); + let menuPanel = document.querySelector('.mat-mdc-menu-panel')!; + let items = menuPanel.querySelectorAll('.mat-mdc-menu-panel [mat-menu-item]'); - expect(document.activeElement) - .withContext('Expected first item to be focused on open') - .toBe(items[0]); + expect(document.activeElement) + .withContext('Expected first item to be focused on open') + .toBe(items[0]); - // Add a new item after the first one. - fixture.componentInstance.items.splice(1, 0, {label: 'Calzone', disabled: false}); - fixture.detectChanges(); + // Add a new item after the first one. + fixture.componentInstance.items.splice(1, 0, {label: 'Calzone', disabled: false}); + fixture.changeDetectorRef.markForCheck(); + fixture.detectChanges(); - items = menuPanel.querySelectorAll('.mat-mdc-menu-panel [mat-menu-item]'); - dispatchKeyboardEvent(menuPanel, 'keydown', DOWN_ARROW); - fixture.detectChanges(); - tick(); + items = menuPanel.querySelectorAll('.mat-mdc-menu-panel [mat-menu-item]'); + dispatchKeyboardEvent(menuPanel, 'keydown', DOWN_ARROW); + fixture.detectChanges(); + tick(); - expect(document.activeElement) - .withContext('Expected second item to be focused') - .toBe(items[1]); - flush(); - }), - ); + expect(document.activeElement).withContext('Expected second item to be focused').toBe(items[1]); + flush(); + })); it('should sync the focus order when an item is focused programmatically', fakeAsync(() => { const fixture = createComponent(SimpleMenuWithRepeater); @@ -1362,6 +1358,7 @@ describe('MatMenu', () => { expect(panel.classList).not.toContain('mat-menu-after'); fixture.componentInstance.xPosition = 'after'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(panel.classList).toContain('mat-menu-after'); @@ -1379,6 +1376,7 @@ describe('MatMenu', () => { expect(panel.classList).not.toContain('mat-menu-below'); fixture.componentInstance.yPosition = 'below'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(panel.classList).toContain('mat-menu-below'); @@ -1444,9 +1442,9 @@ describe('MatMenu', () => { .toBe(Math.floor(trigger.getBoundingClientRect().bottom)); })); - it('should not throw if a menu reposition is requested while the menu is closed', fakeAsync(() => { + it('should not throw if a menu reposition is requested while the menu is closed', () => { expect(() => fixture.componentInstance.trigger.updatePosition()).not.toThrow(); - })); + }); }); describe('fallback positions', () => { @@ -1954,6 +1952,7 @@ describe('MatMenu', () => { .toBe(2); items[1].componentInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); // Invoke the handler directly since the fake events are flaky on disabled elements. @@ -1979,6 +1978,7 @@ describe('MatMenu', () => { const item = fixture.debugElement.query(By.directive(MatMenuItem))!; item.componentInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); // Invoke the handler directly since the fake events are flaky on disabled elements. @@ -2498,6 +2498,7 @@ describe('MatMenu', () => { .toBe(1); instance.showLazy = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); const lazyTrigger = overlay.querySelector('#lazy-trigger')!; diff --git a/src/material/select/select.spec.ts b/src/material/select/select.spec.ts index 14374e689edb..c0a5dc64cec7 100644 --- a/src/material/select/select.spec.ts +++ b/src/material/select/select.spec.ts @@ -135,17 +135,17 @@ describe('MatSelect', () => { let fixture: ComponentFixture; let select: HTMLElement; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = TestBed.createComponent(BasicSelect); fixture.detectChanges(); select = fixture.debugElement.query(By.css('mat-select'))!.nativeElement; - })); + }); - it('should set the role of the select to combobox', fakeAsync(() => { + it('should set the role of the select to combobox', () => { expect(select.getAttribute('role')).toEqual('combobox'); expect(select.getAttribute('aria-autocomplete')).toBe('none'); expect(select.getAttribute('aria-haspopup')).toBe('listbox'); - })); + }); it('should point the aria-controls attribute to the listbox', fakeAsync(() => { expect(select.hasAttribute('aria-controls')).toBe(false); @@ -169,16 +169,16 @@ describe('MatSelect', () => { expect(select.getAttribute('aria-expanded')).toBe('true'); })); - it('should support setting a custom aria-label', fakeAsync(() => { + it('should support setting a custom aria-label', () => { fixture.componentInstance.ariaLabel = 'Custom Label'; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(select.getAttribute('aria-label')).toEqual('Custom Label'); expect(select.hasAttribute('aria-labelledby')).toBeFalsy(); - })); + }); - it('should be able to add an extra aria-labelledby on top of the default', fakeAsync(() => { + it('should be able to add an extra aria-labelledby on top of the default', () => { fixture.componentInstance.ariaLabelledby = 'myLabelId'; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); @@ -187,15 +187,15 @@ describe('MatSelect', () => { const valueId = fixture.nativeElement.querySelector('.mat-mdc-select-value').id; expect(select.getAttribute('aria-labelledby')).toBe(`${labelId} ${valueId} myLabelId`); - })); + }); - it('should set aria-labelledby to the value and label IDs', fakeAsync(() => { + it('should set aria-labelledby to the value and label IDs', () => { fixture.detectChanges(); const labelId = fixture.nativeElement.querySelector('label').id; const valueId = fixture.nativeElement.querySelector('.mat-mdc-select-value').id; expect(select.getAttribute('aria-labelledby')).toBe(`${labelId} ${valueId}`); - })); + }); it('should trim the trigger aria-labelledby when there is no label', fakeAsync(() => { fixture.componentInstance.hasLabel = false; @@ -209,11 +209,11 @@ describe('MatSelect', () => { expect(select.getAttribute('aria-labelledby')).toBe(`${valueId}`); })); - it('should set the tabindex of the select to 0 by default', fakeAsync(() => { + it('should set the tabindex of the select to 0 by default', () => { expect(select.getAttribute('tabindex')).toEqual('0'); - })); + }); - it('should set `aria-describedby` to the id of the mat-hint', fakeAsync(() => { + it('should set `aria-describedby` to the id of the mat-hint', () => { expect(select.getAttribute('aria-describedby')).toBeNull(); fixture.componentInstance.hint = 'test'; @@ -222,24 +222,24 @@ describe('MatSelect', () => { const hint = fixture.debugElement.query(By.css('mat-hint')).nativeElement; expect(select.getAttribute('aria-describedby')).toBe(hint.getAttribute('id')); expect(select.getAttribute('aria-describedby')).toMatch(/^mat-mdc-hint-\d+$/); - })); + }); - it('should support user binding to `aria-describedby`', fakeAsync(() => { + it('should support user binding to `aria-describedby`', () => { fixture.componentInstance.ariaDescribedBy = 'test'; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(select.getAttribute('aria-describedby')).toBe('test'); - })); + }); - it('should be able to override the tabindex', fakeAsync(() => { + it('should be able to override the tabindex', () => { fixture.componentInstance.tabIndexOverride = 3; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(select.getAttribute('tabindex')).toBe('3'); - })); + }); - it('should set aria-required for required selects', fakeAsync(() => { + it('should set aria-required for required selects', () => { expect(select.getAttribute('aria-required')) .withContext(`Expected aria-required attr to be false for normal selects.`) .toEqual('false'); @@ -251,9 +251,9 @@ describe('MatSelect', () => { expect(select.getAttribute('aria-required')) .withContext(`Expected aria-required attr to be true for required selects.`) .toEqual('true'); - })); + }); - it('should set the mat-select-required class for required selects', fakeAsync(() => { + it('should set the mat-select-required class for required selects', () => { expect(select.classList).not.toContain( 'mat-mdc-select-required', `Expected the mat-mdc-select-required class not to be set.`, @@ -266,9 +266,9 @@ describe('MatSelect', () => { expect(select.classList) .withContext(`Expected the mat-mdc-select-required class to be set.`) .toContain('mat-mdc-select-required'); - })); + }); - it('should set aria-invalid for selects that are invalid and touched', fakeAsync(() => { + it('should set aria-invalid for selects that are invalid and touched', () => { expect(select.getAttribute('aria-invalid')) .withContext(`Expected aria-invalid attr to be false for valid selects.`) .toEqual('false'); @@ -282,18 +282,18 @@ describe('MatSelect', () => { expect(select.getAttribute('aria-invalid')) .withContext(`Expected aria-invalid attr to be true for invalid selects.`) .toEqual('true'); - })); + }); - it('should set aria-disabled for disabled selects', fakeAsync(() => { + it('should set aria-disabled for disabled selects', () => { expect(select.getAttribute('aria-disabled')).toEqual('false'); fixture.componentInstance.control.disable(); fixture.detectChanges(); expect(select.getAttribute('aria-disabled')).toEqual('true'); - })); + }); - it('should set the tabindex of the select to -1 if disabled', fakeAsync(() => { + it('should set the tabindex of the select to -1 if disabled', () => { fixture.componentInstance.control.disable(); fixture.detectChanges(); expect(select.getAttribute('tabindex')).toEqual('-1'); @@ -301,7 +301,7 @@ describe('MatSelect', () => { fixture.componentInstance.control.enable(); fixture.detectChanges(); expect(select.getAttribute('tabindex')).toEqual('0'); - })); + }); it('should set `aria-labelledby` to the value ID if there is no form field', () => { fixture.destroy(); @@ -353,44 +353,40 @@ describe('MatSelect', () => { flush(); })); - it( - 'should go back to first option if value is reset after interacting using the' + - 'arrow keys on a closed select', - fakeAsync(() => { - const formControl = fixture.componentInstance.control; - const options = fixture.componentInstance.options.toArray(); + it('should go back to first option if value is reset after interacting using the arrow keys on a closed select', fakeAsync(() => { + const formControl = fixture.componentInstance.control; + const options = fixture.componentInstance.options.toArray(); - expect(formControl.value).withContext('Expected no initial value.').toBeFalsy(); + expect(formControl.value).withContext('Expected no initial value.').toBeFalsy(); - dispatchKeyboardEvent(select, 'keydown', DOWN_ARROW); - flush(); + dispatchKeyboardEvent(select, 'keydown', DOWN_ARROW); + flush(); - expect(options[0].selected) - .withContext('Expected first option to be selected.') - .toBe(true); - expect(formControl.value) - .withContext('Expected value from first option to have been set on the model.') - .toBe(options[0].value); + expect(options[0].selected) + .withContext('Expected first option to be selected.') + .toBe(true); + expect(formControl.value) + .withContext('Expected value from first option to have been set on the model.') + .toBe(options[0].value); - formControl.reset(); - fixture.detectChanges(); + formControl.reset(); + fixture.detectChanges(); - expect(options[0].selected) - .withContext('Expected first option to be deselected.') - .toBe(false); - expect(formControl.value).withContext('Expected value to be reset.').toBeFalsy(); + expect(options[0].selected) + .withContext('Expected first option to be deselected.') + .toBe(false); + expect(formControl.value).withContext('Expected value to be reset.').toBeFalsy(); - dispatchKeyboardEvent(select, 'keydown', DOWN_ARROW); - flush(); - - expect(options[0].selected) - .withContext('Expected first option to be selected again.') - .toBe(true); - expect(formControl.value) - .withContext('Expected value from first option to have been set on the model again.') - .toBe(options[0].value); - }), - ); + dispatchKeyboardEvent(select, 'keydown', DOWN_ARROW); + flush(); + + expect(options[0].selected) + .withContext('Expected first option to be selected again.') + .toBe(true); + expect(formControl.value) + .withContext('Expected value from first option to have been set on the model again.') + .toBe(options[0].value); + })); it('should select first/last options via the HOME/END keys on a closed select', fakeAsync(() => { const formControl = fixture.componentInstance.control; @@ -544,7 +540,7 @@ describe('MatSelect', () => { flush(); })); - it('should open a single-selection select using ALT + DOWN_ARROW', fakeAsync(() => { + it('should open a single-selection select using ALT + DOWN_ARROW', () => { const {control: formControl, select: selectInstance} = fixture.componentInstance; expect(selectInstance.panelOpen).withContext('Expected select to be closed.').toBe(false); @@ -556,9 +552,9 @@ describe('MatSelect', () => { expect(selectInstance.panelOpen).withContext('Expected select to be open.').toBe(true); expect(formControl.value).withContext('Expected value not to have changed.').toBeFalsy(); - })); + }); - it('should open a single-selection select using ALT + UP_ARROW', fakeAsync(() => { + it('should open a single-selection select using ALT + UP_ARROW', () => { const {control: formControl, select: selectInstance} = fixture.componentInstance; expect(selectInstance.panelOpen).withContext('Expected select to be closed.').toBe(false); @@ -570,9 +566,9 @@ describe('MatSelect', () => { expect(selectInstance.panelOpen).withContext('Expected select to be open.').toBe(true); expect(formControl.value).withContext('Expected value not to have changed.').toBeFalsy(); - })); + }); - it('should close when pressing ALT + DOWN_ARROW', fakeAsync(() => { + it('should close when pressing ALT + DOWN_ARROW', () => { const {select: selectInstance} = fixture.componentInstance; selectInstance.open(); @@ -588,9 +584,9 @@ describe('MatSelect', () => { expect(event.defaultPrevented) .withContext('Expected default action to be prevented.') .toBe(true); - })); + }); - it('should close when pressing ALT + UP_ARROW', fakeAsync(() => { + it('should close when pressing ALT + UP_ARROW', () => { const {select: selectInstance} = fixture.componentInstance; selectInstance.open(); @@ -606,7 +602,7 @@ describe('MatSelect', () => { expect(event.defaultPrevented) .withContext('Expected default action to be prevented.') .toBe(true); - })); + }); it('should be able to select options by typing on a closed select', fakeAsync(() => { const formControl = fixture.componentInstance.control; @@ -708,7 +704,7 @@ describe('MatSelect', () => { expect(formControl.value).withContext('Expected no value to be assigned.').toBeFalsy(); })); - it('should open the panel when pressing a vertical arrow key on a closed multiple select', fakeAsync(() => { + it('should open the panel when pressing a vertical arrow key on a closed multiple select', () => { fixture.destroy(); const multiFixture = TestBed.createComponent(MultiSelect); @@ -730,9 +726,9 @@ describe('MatSelect', () => { expect(event.defaultPrevented) .withContext('Expected default to be prevented.') .toBe(true); - })); + }); - it('should open the panel when pressing a horizontal arrow key on closed multiple select', fakeAsync(() => { + it('should open the panel when pressing a horizontal arrow key on closed multiple select', () => { fixture.destroy(); const multiFixture = TestBed.createComponent(MultiSelect); @@ -754,9 +750,9 @@ describe('MatSelect', () => { expect(event.defaultPrevented) .withContext('Expected default to be prevented.') .toBe(true); - })); + }); - it('should do nothing when typing on a closed multi-select', fakeAsync(() => { + it('should do nothing when typing on a closed multi-select', () => { fixture.destroy(); const multiFixture = TestBed.createComponent(MultiSelect); @@ -777,9 +773,9 @@ describe('MatSelect', () => { expect(instance.control.value) .withContext('Expected value to stay the same.') .toBe(initialValue); - })); + }); - it('should do nothing if the key manager did not change the active item', fakeAsync(() => { + it('should do nothing if the key manager did not change the active item', () => { const formControl = fixture.componentInstance.control; expect(formControl.value) @@ -795,7 +791,7 @@ describe('MatSelect', () => { expect(formControl.pristine) .withContext('Expected form control to stay clean.') .toBe(true); - })); + }); it('should continue from the selected option when the value is set programmatically', fakeAsync(() => { const formControl = fixture.componentInstance.control; @@ -810,48 +806,44 @@ describe('MatSelect', () => { flush(); })); - it( - 'should not shift focus when the selected options are updated programmatically ' + - 'in a multi select', - fakeAsync(() => { - fixture.destroy(); + it('should not shift focus when the selected options are updated programmatically in a multi select', () => { + fixture.destroy(); - const multiFixture = TestBed.createComponent(MultiSelect); + const multiFixture = TestBed.createComponent(MultiSelect); - multiFixture.detectChanges(); - select = multiFixture.debugElement.query(By.css('mat-select'))!.nativeElement; - multiFixture.componentInstance.select.open(); - multiFixture.detectChanges(); + multiFixture.detectChanges(); + select = multiFixture.debugElement.query(By.css('mat-select'))!.nativeElement; + multiFixture.componentInstance.select.open(); + multiFixture.detectChanges(); - const options = overlayContainerElement.querySelectorAll( - 'mat-option', - ) as NodeListOf; + const options = overlayContainerElement.querySelectorAll( + 'mat-option', + ) as NodeListOf; - select.focus(); - multiFixture.detectChanges(); - multiFixture.componentInstance.select._keyManager.setActiveItem(3); - multiFixture.detectChanges(); + select.focus(); + multiFixture.detectChanges(); + multiFixture.componentInstance.select._keyManager.setActiveItem(3); + multiFixture.detectChanges(); - expect(document.activeElement) - .withContext('Expected select to have DOM focus.') - .toBe(select); - expect(select.getAttribute('aria-activedescendant')) - .withContext('Expected fourth option to be activated.') - .toBe(options[3].id); + expect(document.activeElement) + .withContext('Expected select to have DOM focus.') + .toBe(select); + expect(select.getAttribute('aria-activedescendant')) + .withContext('Expected fourth option to be activated.') + .toBe(options[3].id); - multiFixture.componentInstance.control.setValue(['steak-0', 'sushi-7']); - multiFixture.detectChanges(); + multiFixture.componentInstance.control.setValue(['steak-0', 'sushi-7']); + multiFixture.detectChanges(); - expect(document.activeElement) - .withContext('Expected select to have DOM focus.') - .toBe(select); - expect(select.getAttribute('aria-activedescendant')) - .withContext('Expected fourth optino to remain activated.') - .toBe(options[3].id); - }), - ); + expect(document.activeElement) + .withContext('Expected select to have DOM focus.') + .toBe(select); + expect(select.getAttribute('aria-activedescendant')) + .withContext('Expected fourth optino to remain activated.') + .toBe(options[3].id); + }); - it('should not cycle through the options if the control is disabled', fakeAsync(() => { + it('should not cycle through the options if the control is disabled', () => { const formControl = fixture.componentInstance.control; formControl.setValue('eggs-5'); @@ -862,9 +854,9 @@ describe('MatSelect', () => { expect(formControl.value) .withContext('Expected value to remain unchaged.') .toBe('eggs-5'); - })); + }); - it('should not wrap selection after reaching the end of the options', fakeAsync(() => { + it('should not wrap selection after reaching the end of the options', () => { const lastOption = fixture.componentInstance.options.last; fixture.componentInstance.options.forEach(() => { @@ -880,11 +872,9 @@ describe('MatSelect', () => { expect(lastOption.selected) .withContext('Expected last option to stay selected.') .toBe(true); + }); - flush(); - })); - - it('should not open a multiple select when tabbing through', fakeAsync(() => { + it('should not open a multiple select when tabbing through', () => { fixture.destroy(); const multiFixture = TestBed.createComponent(MultiSelect); @@ -901,7 +891,7 @@ describe('MatSelect', () => { expect(multiFixture.componentInstance.select.panelOpen) .withContext('Expected panel to stay closed.') .toBe(false); - })); + }); it('should toggle the next option when pressing shift + DOWN_ARROW on a multi-select', fakeAsync(() => { fixture.destroy(); @@ -961,22 +951,22 @@ describe('MatSelect', () => { expect(multiFixture.componentInstance.select.value).toEqual(['sandwich-3', 'chips-4']); })); - it('should prevent the default action when pressing space', fakeAsync(() => { + it('should prevent the default action when pressing space', () => { const event = dispatchKeyboardEvent(select, 'keydown', SPACE); expect(event.defaultPrevented).toBe(true); - })); + }); - it('should prevent the default action when pressing enter', fakeAsync(() => { + it('should prevent the default action when pressing enter', () => { const event = dispatchKeyboardEvent(select, 'keydown', ENTER); expect(event.defaultPrevented).toBe(true); - })); + }); - it('should not prevent the default actions on selection keys when pressing a modifier', fakeAsync(() => { + it('should not prevent the default actions on selection keys when pressing a modifier', () => { [ENTER, SPACE].forEach(key => { const event = createKeyboardEvent('keydown', key, undefined, {shift: true}); expect(event.defaultPrevented).toBe(false); }); - })); + }); it('should consider the selection a result of a user action when closed', fakeAsync(() => { const option = fixture.componentInstance.options.first; @@ -992,7 +982,7 @@ describe('MatSelect', () => { flush(); })); - it('should be able to focus the select trigger', fakeAsync(() => { + it('should be able to focus the select trigger', () => { document.body.focus(); // ensure that focus isn't on the trigger already fixture.componentInstance.select.focus(); @@ -1000,7 +990,7 @@ describe('MatSelect', () => { expect(document.activeElement) .withContext('Expected select element to be focused.') .toBe(select); - })); + }); it('should set `aria-multiselectable` to true on the listbox inside multi select', fakeAsync(() => { fixture.destroy(); @@ -1097,7 +1087,7 @@ describe('MatSelect', () => { expect(host.getAttribute('aria-activedescendant')).toBe(options[0].id); })); - it('should restore focus to the trigger after selecting an option in multi-select mode', fakeAsync(() => { + it('should restore focus to the trigger after selecting an option in multi-select mode', () => { fixture.destroy(); const multiFixture = TestBed.createComponent(MultiSelect); @@ -1119,7 +1109,7 @@ describe('MatSelect', () => { expect(document.activeElement) .withContext('Expected trigger to be focused.') .toBe(select); - })); + }); it('should set a role of listbox on the select panel', fakeAsync(() => { fixture.componentInstance.select.open(); @@ -1181,12 +1171,12 @@ describe('MatSelect', () => { describe('for select inside a modal', () => { let fixture: ComponentFixture; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = TestBed.createComponent(SelectInsideAModal); fixture.detectChanges(); - })); + }); - it('should add the id of the select panel to the aria-owns of the modal', fakeAsync(() => { + it('should add the id of the select panel to the aria-owns of the modal', () => { fixture.componentInstance.select.open(); fixture.detectChanges(); @@ -1196,7 +1186,7 @@ describe('MatSelect', () => { expect(modalElement.getAttribute('aria-owns')?.split(' ')) .withContext('expecting modal to own the select panel') .toContain(panelId); - })); + }); }); describe('for options', () => { @@ -1204,7 +1194,7 @@ describe('MatSelect', () => { let trigger: HTMLElement; let options: HTMLElement[]; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = TestBed.createComponent(BasicSelect); fixture.detectChanges(); trigger = fixture.debugElement.query(By.css('.mat-mdc-select-trigger'))!.nativeElement; @@ -1212,7 +1202,7 @@ describe('MatSelect', () => { fixture.detectChanges(); options = Array.from(overlayContainerElement.querySelectorAll('mat-option')); - })); + }); it('should set the role of mat-option to option', fakeAsync(() => { expect(options[0].getAttribute('role')).toEqual('option'); @@ -1348,6 +1338,7 @@ describe('MatSelect', () => { fixture.componentInstance.select.open(); fixture.detectChanges(); + flush(); activeOptions = options.filter(option => { return option.classList.contains('mat-mdc-option-active'); @@ -1416,7 +1407,7 @@ describe('MatSelect', () => { let trigger: HTMLElement; let groups: NodeListOf; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = TestBed.createComponent(SelectWithGroups); fixture.detectChanges(); trigger = fixture.debugElement.query(By.css('.mat-mdc-select-trigger'))!.nativeElement; @@ -1425,7 +1416,7 @@ describe('MatSelect', () => { groups = overlayContainerElement.querySelectorAll( 'mat-optgroup', ) as NodeListOf; - })); + }); it('should set the appropriate role', fakeAsync(() => { expect(groups[0].getAttribute('role')).toBe('group'); @@ -1454,12 +1445,12 @@ describe('MatSelect', () => { let formField: HTMLElement; let trigger: HTMLElement; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = TestBed.createComponent(BasicSelect); fixture.detectChanges(); formField = fixture.debugElement.query(By.css('.mat-mdc-form-field'))!.nativeElement; trigger = formField.querySelector('.mat-mdc-select-trigger') as HTMLElement; - })); + }); it('should not throw when attempting to open too early', () => { // Create component and then immediately open without running change detection @@ -1580,7 +1571,7 @@ describe('MatSelect', () => { expect(pane.style.width).toBeFalsy(); })); - it('should not attempt to open a select that does not have any options', fakeAsync(() => { + it('should not attempt to open a select that does not have any options', () => { fixture.componentInstance.foods = []; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); @@ -1589,7 +1580,7 @@ describe('MatSelect', () => { fixture.detectChanges(); expect(fixture.componentInstance.select.panelOpen).toBe(false); - })); + }); it('should close the panel when tabbing out', fakeAsync(() => { trigger.click(); @@ -1700,7 +1691,7 @@ describe('MatSelect', () => { expect(event.defaultPrevented).toBe(true); })); - it('should be able to set extra classes on the panel', fakeAsync(() => { + it('should be able to set extra classes on the panel', () => { trigger.click(); fixture.detectChanges(); @@ -1708,9 +1699,9 @@ describe('MatSelect', () => { expect(panel.classList).toContain('custom-one'); expect(panel.classList).toContain('custom-two'); - })); + }); - it('should update disableRipple properly on each option', fakeAsync(() => { + it('should update disableRipple properly on each option', () => { const options = fixture.componentInstance.options.toArray(); expect(options.every(option => option.disableRipple === false)) @@ -1724,7 +1715,7 @@ describe('MatSelect', () => { expect(options.every(option => option.disableRipple === true)) .withContext('Expected all options to have disableRipple set to true.') .toBeTruthy(); - })); + }); it('should not show ripples if they were disabled', fakeAsync(() => { fixture.componentInstance.disableRipple = true; @@ -1743,7 +1734,7 @@ describe('MatSelect', () => { expect(option.querySelectorAll('.mat-ripple-element').length).toBe(0); })); - it('should be able to render options inside groups with an ng-container', fakeAsync(() => { + it('should be able to render options inside groups with an ng-container', () => { fixture.destroy(); const groupFixture = TestBed.createComponent(SelectWithGroupsAndNgContainer); @@ -1755,31 +1746,27 @@ describe('MatSelect', () => { expect(document.querySelectorAll('.cdk-overlay-container mat-option').length) .withContext('Expected at least one option to be rendered.') .toBeGreaterThan(0); - })); + }); - it( - 'should not consider itself as blurred if the trigger loses focus while the ' + - 'panel is still open', - fakeAsync(() => { - const selectElement = fixture.nativeElement.querySelector('.mat-mdc-select'); - const selectInstance = fixture.componentInstance.select; + it('should not consider itself as blurred if the trigger loses focus while the panel is still open', fakeAsync(() => { + const selectElement = fixture.nativeElement.querySelector('.mat-mdc-select'); + const selectInstance = fixture.componentInstance.select; - dispatchFakeEvent(selectElement, 'focus'); - fixture.detectChanges(); + dispatchFakeEvent(selectElement, 'focus'); + fixture.detectChanges(); - expect(selectInstance.focused).withContext('Expected select to be focused.').toBe(true); + expect(selectInstance.focused).withContext('Expected select to be focused.').toBe(true); - selectInstance.open(); - fixture.detectChanges(); - flush(); - dispatchFakeEvent(selectElement, 'blur'); - fixture.detectChanges(); + selectInstance.open(); + fixture.detectChanges(); + flush(); + dispatchFakeEvent(selectElement, 'blur'); + fixture.detectChanges(); - expect(selectInstance.focused) - .withContext('Expected select element to remain focused.') - .toBe(true); - }), - ); + expect(selectInstance.focused) + .withContext('Expected select element to remain focused.') + .toBe(true); + })); }); describe('selection logic', () => { @@ -1788,19 +1775,19 @@ describe('MatSelect', () => { let formField: HTMLElement; let label: HTMLLabelElement; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = TestBed.createComponent(BasicSelect); fixture.detectChanges(); trigger = fixture.debugElement.query(By.css('.mat-mdc-select-trigger'))!.nativeElement; formField = fixture.debugElement.query(By.css('.mat-mdc-form-field'))!.nativeElement; label = formField.querySelector('label')!; - })); + }); - it('should not float label if no option is selected', fakeAsync(() => { + it('should not float label if no option is selected', () => { expect(label.classList.contains('mat-form-field-should-float')) .withContext('Label should not be floating') .toBe(false); - })); + }); it('should focus the first option if no option is selected', fakeAsync(() => { trigger.click(); @@ -2025,7 +2012,7 @@ describe('MatSelect', () => { expect(trigger.textContent!.trim()).toBe('PIZZA'); })); - it('should not select disabled options', fakeAsync(() => { + it('should not select disabled options', () => { trigger.click(); fixture.detectChanges(); @@ -2038,9 +2025,9 @@ describe('MatSelect', () => { expect(fixture.componentInstance.select.panelOpen).toBe(true); expect(options[2].classList).not.toContain('mdc-list-item--selected'); expect(fixture.componentInstance.select.selected).toBeUndefined(); - })); + }); - it('should not select options inside a disabled group', fakeAsync(() => { + it('should not select options inside a disabled group', () => { fixture.destroy(); const groupFixture = TestBed.createComponent(SelectWithGroups); @@ -2057,7 +2044,7 @@ describe('MatSelect', () => { expect(groupFixture.componentInstance.select.panelOpen).toBe(true); expect(options[0].classList).not.toContain('mdc-list-item--selected'); expect(groupFixture.componentInstance.select.selected).toBeUndefined(); - })); + }); it('should not throw if triggerValue accessed with no selected value', fakeAsync(() => { expect(() => fixture.componentInstance.select.triggerValue).not.toThrow(); @@ -2159,11 +2146,11 @@ describe('MatSelect', () => { let fixture: ComponentFixture; let trigger: HTMLElement; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = TestBed.createComponent(BasicSelect); fixture.detectChanges(); trigger = fixture.debugElement.query(By.css('.mat-mdc-select-trigger'))!.nativeElement; - })); + }); it('should take an initial view value with reactive forms', fakeAsync(() => { fixture.componentInstance.control = new FormControl('pizza-1'); @@ -2339,7 +2326,7 @@ describe('MatSelect', () => { .toBe(true); })); - it('should not set touched when a disabled select is touched', fakeAsync(() => { + it('should not set touched when a disabled select is touched', () => { expect(fixture.componentInstance.control.touched) .withContext('Expected the control to start off as untouched.') .toBe(false); @@ -2350,7 +2337,7 @@ describe('MatSelect', () => { expect(fixture.componentInstance.control.touched) .withContext('Expected the control to stay untouched.') .toBe(false); - })); + }); it('should set the control to dirty when the select value changes in DOM', fakeAsync(() => { expect(fixture.componentInstance.control.dirty) @@ -2371,7 +2358,7 @@ describe('MatSelect', () => { .toEqual(true); })); - it('should not set the control to dirty when the value changes programmatically', fakeAsync(() => { + it('should not set the control to dirty when the value changes programmatically', () => { expect(fixture.componentInstance.control.dirty) .withContext(`Expected control to start out pristine.`) .toEqual(false); @@ -2381,7 +2368,7 @@ describe('MatSelect', () => { expect(fixture.componentInstance.control.dirty) .withContext(`Expected control to stay pristine after programmatic change.`) .toEqual(false); - })); + }); it('should set an asterisk after the label if control is required', fakeAsync(() => { const label = fixture.nativeElement.querySelector('.mat-mdc-form-field label'); @@ -2426,6 +2413,7 @@ describe('MatSelect', () => { trigger.click(); fixture.detectChanges(); + flush(); expect(overlayContainerElement.textContent) .withContext(`Expected select panel to stay closed.`) @@ -2442,6 +2430,7 @@ describe('MatSelect', () => { trigger.click(); fixture.detectChanges(); + flush(); expect(overlayContainerElement.textContent) .withContext(`Expected select panel to open normally on re-enabled control`) @@ -2451,22 +2440,18 @@ describe('MatSelect', () => { .toBe(true); })); - it( - 'should keep the disabled state in sync if the form group is swapped and ' + - 'disabled at the same time', - fakeAsync(() => { - const fixture = TestBed.createComponent(SelectInsideDynamicFormGroup); - fixture.detectChanges(); - const instance = fixture.componentInstance; + it('should keep the disabled state in sync if the form group is swapped and disabled at the same time', () => { + const fixture = TestBed.createComponent(SelectInsideDynamicFormGroup); + fixture.detectChanges(); + const instance = fixture.componentInstance; - expect(instance.select.disabled).toBe(false); + expect(instance.select.disabled).toBe(false); - instance.assignGroup(true); - fixture.detectChanges(); + instance.assignGroup(true); + fixture.detectChanges(); - expect(instance.select.disabled).toBe(true); - }), - ); + expect(instance.select.disabled).toBe(true); + }); }); describe('keyboard scrolling', () => { @@ -2494,7 +2479,7 @@ describe('MatSelect', () => { panel = overlayContainerElement.querySelector('.mat-mdc-select-panel')! as HTMLElement; })); - it('should not scroll to options that are completely in the view', fakeAsync(() => { + it('should not scroll to options that are completely in the view', () => { const initialScrollPosition = panel.scrollTop; [1, 2, 3].forEach(() => { @@ -2504,18 +2489,18 @@ describe('MatSelect', () => { expect(panel.scrollTop) .withContext('Expected scroll position not to change') .toBe(initialScrollPosition); - })); + }); - it('should scroll down to the active option', fakeAsync(() => { + it('should scroll down to the active option', () => { for (let i = 0; i < 15; i++) { dispatchKeyboardEvent(host, 'keydown', DOWN_ARROW); } // +