diff --git a/src/cdk-experimental/table-scroll-container/table-scroll-container.spec.ts b/src/cdk-experimental/table-scroll-container/table-scroll-container.spec.ts index 4b582253e285..8134cdc0f3ea 100644 --- a/src/cdk-experimental/table-scroll-container/table-scroll-container.spec.ts +++ b/src/cdk-experimental/table-scroll-container/table-scroll-container.spec.ts @@ -1,6 +1,6 @@ import {CollectionViewer, DataSource} from '@angular/cdk/collections'; import {Component, Type, ViewChild} from '@angular/core'; -import {ComponentFixture, fakeAsync, flushMicrotasks, TestBed} from '@angular/core/testing'; +import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; import {BehaviorSubject, combineLatest} from 'rxjs'; import {map} from 'rxjs/operators'; import {CdkTable, CdkTableModule} from '@angular/cdk/table'; @@ -48,10 +48,10 @@ describe('CdkTableScrollContainer', () => { dataRows = getRows(tableElement); }); - it('sets scrollbar track margin for sticky headers', fakeAsync(() => { + it('sets scrollbar track margin for sticky headers', waitForAsync(async () => { component.stickyHeaders = ['header-1', 'header-3']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); if (platform.FIREFOX) { // ::-webkit-scrollbar-track is not recognized by Firefox. @@ -66,7 +66,7 @@ describe('CdkTableScrollContainer', () => { component.stickyHeaders = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expect(scrollerStyle.getPropertyValue('margin-top')).toBe('0px'); expect(scrollerStyle.getPropertyValue('margin-right')).toBe('0px'); @@ -74,10 +74,10 @@ describe('CdkTableScrollContainer', () => { expect(scrollerStyle.getPropertyValue('margin-left')).toBe('0px'); })); - it('sets scrollbar track margin for sticky footers', fakeAsync(() => { + it('sets scrollbar track margin for sticky footers', waitForAsync(async () => { component.stickyFooters = ['footer-1', 'footer-3']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); if (platform.FIREFOX) { // ::-webkit-scrollbar-track is not recognized by Firefox. @@ -92,7 +92,7 @@ describe('CdkTableScrollContainer', () => { component.stickyFooters = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expect(scrollerStyle.getPropertyValue('margin-top')).toBe('0px'); expect(scrollerStyle.getPropertyValue('margin-right')).toBe('0px'); @@ -100,10 +100,10 @@ describe('CdkTableScrollContainer', () => { expect(scrollerStyle.getPropertyValue('margin-left')).toBe('0px'); })); - it('sets scrollbar track margin for sticky start columns', fakeAsync(() => { + it('sets scrollbar track margin for sticky start columns', waitForAsync(async () => { component.stickyStartColumns = ['column-1', 'column-3']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); if (platform.FIREFOX) { // ::-webkit-scrollbar-track is not recognized by Firefox. @@ -120,7 +120,7 @@ describe('CdkTableScrollContainer', () => { component.stickyStartColumns = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expect(scrollerStyle.getPropertyValue('margin-top')).toBe('0px'); expect(scrollerStyle.getPropertyValue('margin-right')).toBe('0px'); @@ -128,10 +128,10 @@ describe('CdkTableScrollContainer', () => { expect(scrollerStyle.getPropertyValue('margin-left')).toBe('0px'); })); - it('sets scrollbar track margin for sticky end columns', fakeAsync(() => { + it('sets scrollbar track margin for sticky end columns', waitForAsync(async () => { component.stickyEndColumns = ['column-4', 'column-6']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); if (platform.FIREFOX) { // ::-webkit-scrollbar-track is not recognized by Firefox. @@ -148,7 +148,7 @@ describe('CdkTableScrollContainer', () => { component.stickyEndColumns = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expect(scrollerStyle.getPropertyValue('margin-top')).toBe('0px'); expect(scrollerStyle.getPropertyValue('margin-right')).toBe('0px'); @@ -156,13 +156,13 @@ describe('CdkTableScrollContainer', () => { expect(scrollerStyle.getPropertyValue('margin-left')).toBe('0px'); })); - it('sets scrollbar track margin for a combination of sticky rows and columns', fakeAsync(() => { + it('sets scrollbar track margin for a combination of sticky rows and columns', waitForAsync(async () => { component.stickyHeaders = ['header-1']; component.stickyFooters = ['footer-3']; component.stickyStartColumns = ['column-1']; component.stickyEndColumns = ['column-6']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); if (platform.FIREFOX) { // ::-webkit-scrollbar-track is not recognized by Firefox. @@ -184,7 +184,7 @@ describe('CdkTableScrollContainer', () => { component.stickyStartColumns = []; component.stickyEndColumns = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expect(scrollerStyle.getPropertyValue('margin-top')).toBe('0px'); expect(scrollerStyle.getPropertyValue('margin-right')).toBe('0px'); diff --git a/src/cdk/table/coalesced-style-scheduler.ts b/src/cdk/table/coalesced-style-scheduler.ts index 333dc9cfb26e..ba20be4549cb 100644 --- a/src/cdk/table/coalesced-style-scheduler.ts +++ b/src/cdk/table/coalesced-style-scheduler.ts @@ -15,8 +15,7 @@ import { inject, Injector, } from '@angular/core'; -import {from, Subject} from 'rxjs'; -import {take, takeUntil} from 'rxjs/operators'; +import {Subject} from 'rxjs'; /** * @docs-private @@ -42,7 +41,7 @@ export const _COALESCED_STYLE_SCHEDULER = new InjectionToken<_CoalescedStyleSche export class _CoalescedStyleScheduler implements OnDestroy { private _currentSchedule: _Schedule | null = null; private readonly _destroyed = new Subject(); - + private _isDestroyed = false; private _injector = inject(Injector); constructor(private readonly _ngZone: NgZone) {} @@ -70,6 +69,7 @@ export class _CoalescedStyleScheduler implements OnDestroy { ngOnDestroy() { this._destroyed.next(); this._destroyed.complete(); + this._isDestroyed = true; } private _createScheduleIfNeeded() { @@ -80,7 +80,11 @@ export class _CoalescedStyleScheduler implements OnDestroy { this._currentSchedule = new _Schedule(); this._ngZone.run(() => - queueMicrotask(() => + queueMicrotask(() => { + if (this._isDestroyed) { + return; + } + afterNextRender( () => { while (this._currentSchedule!.tasks.length || this._currentSchedule!.endTasks.length) { @@ -101,8 +105,8 @@ export class _CoalescedStyleScheduler implements OnDestroy { this._currentSchedule = null; }, {injector: this._injector}, - ), - ), + ); + }), ); } } diff --git a/src/cdk/table/table.spec.ts b/src/cdk/table/table.spec.ts index 4fa833885d3f..65013c0cb9fb 100644 --- a/src/cdk/table/table.spec.ts +++ b/src/cdk/table/table.spec.ts @@ -11,7 +11,7 @@ import { AfterViewInit, ChangeDetectionStrategy, } from '@angular/core'; -import {ComponentFixture, fakeAsync, flush, flushMicrotasks, TestBed} from '@angular/core/testing'; +import {ComponentFixture, fakeAsync, flush, TestBed, waitForAsync} from '@angular/core/testing'; import {BehaviorSubject, combineLatest, Observable, of as observableOf} from 'rxjs'; import {map} from 'rxjs/operators'; import {CdkColumnDef} from './cell'; @@ -966,10 +966,10 @@ describe('CdkTable', () => { dataRows = getRows(tableElement); }); - it('should stick and unstick headers', fakeAsync(() => { + it('should stick and unstick headers', waitForAsync(async () => { component.stickyHeaders = ['header-1', 'header-3']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expectStickyStyles(headerRows[0], '100', {top: '0px'}); expectStickyBorderClass(headerRows[0]); @@ -997,7 +997,7 @@ describe('CdkTable', () => { component.stickyHeaders = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expectNoStickyStyles(headerRows); expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({ sizes: [], @@ -1013,10 +1013,10 @@ describe('CdkTable', () => { expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []}); })); - it('should stick and unstick footers', fakeAsync(() => { + it('should stick and unstick footers', waitForAsync(async () => { component.stickyFooters = ['footer-1', 'footer-3']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expectStickyStyles(footerRows[0], '10', { bottom: footerRows[1].getBoundingClientRect().height + 'px', @@ -1044,7 +1044,7 @@ describe('CdkTable', () => { component.stickyFooters = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expectNoStickyStyles(footerRows); expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({ sizes: [], @@ -1060,20 +1060,20 @@ describe('CdkTable', () => { expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []}); })); - it('should stick the correct footer row', fakeAsync(() => { + it('should stick the correct footer row', waitForAsync(async () => { component.stickyFooters = ['footer-3']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expectStickyStyles(footerRows[2], '10', {bottom: '0px'}); expectStickyBorderClass(footerRows[2], {bottom: true}); expectNoStickyStyles([footerRows[0], footerRows[1]]); })); - it('should stick and unstick left columns', fakeAsync(() => { + it('should stick and unstick left columns', waitForAsync(async () => { component.stickyStartColumns = ['column-1', 'column-3']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); headerRows.forEach(row => { let cells = getHeaderCells(row); @@ -1120,7 +1120,7 @@ describe('CdkTable', () => { component.stickyStartColumns = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); headerRows.forEach(row => expectNoStickyStyles(getHeaderCells(row))); dataRows.forEach(row => expectNoStickyStyles(getCells(row))); footerRows.forEach(row => expectNoStickyStyles(getFooterCells(row))); @@ -1138,10 +1138,10 @@ describe('CdkTable', () => { expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []}); })); - it('should stick and unstick right columns', fakeAsync(() => { + it('should stick and unstick right columns', waitForAsync(async () => { component.stickyEndColumns = ['column-4', 'column-6']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); headerRows.forEach(row => { let cells = getHeaderCells(row); @@ -1188,7 +1188,7 @@ describe('CdkTable', () => { component.stickyEndColumns = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); headerRows.forEach(row => expectNoStickyStyles(getHeaderCells(row))); dataRows.forEach(row => expectNoStickyStyles(getCells(row))); footerRows.forEach(row => expectNoStickyStyles(getFooterCells(row))); @@ -1206,12 +1206,12 @@ describe('CdkTable', () => { expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []}); })); - it('should reverse directions for sticky columns in rtl', fakeAsync(() => { + it('should reverse directions for sticky columns in rtl', waitForAsync(async () => { component.dir = 'rtl'; component.stickyStartColumns = ['column-1', 'column-2']; component.stickyEndColumns = ['column-5', 'column-6']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); const firstColumnWidth = getHeaderCells(headerRows[0])[0].getBoundingClientRect().width; const lastColumnWidth = getHeaderCells(headerRows[0])[5].getBoundingClientRect().width; @@ -1249,13 +1249,13 @@ describe('CdkTable', () => { expectStickyBorderClass(footerCells[5]); })); - it('should stick and unstick combination of sticky header, footer, and columns', fakeAsync(() => { + it('should stick and unstick combination of sticky header, footer, and columns', waitForAsync(async () => { component.stickyHeaders = ['header-1']; component.stickyFooters = ['footer-3']; component.stickyStartColumns = ['column-1']; component.stickyEndColumns = ['column-6']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); let headerCells = getHeaderCells(headerRows[0]); expectStickyStyles(headerRows[0], '100', {top: '0px'}); @@ -1308,7 +1308,7 @@ describe('CdkTable', () => { component.stickyStartColumns = []; component.stickyEndColumns = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); headerRows.forEach(row => expectNoStickyStyles([row, ...getHeaderCells(row)])); dataRows.forEach(row => expectNoStickyStyles([row, ...getCells(row)])); @@ -1342,10 +1342,10 @@ describe('CdkTable', () => { dataRows = getRows(tableElement); }); - it('should stick and unstick headers', fakeAsync(() => { + it('should stick and unstick headers', waitForAsync(async () => { component.stickyHeaders = ['header-1', 'header-3']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); getHeaderCells(headerRows[0]).forEach(cell => { expectStickyStyles(cell, '100', {top: '0px'}); @@ -1377,7 +1377,7 @@ describe('CdkTable', () => { component.stickyHeaders = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expectNoStickyStyles(headerRows); // No sticky styles on rows for native table headerRows.forEach(row => expectNoStickyStyles(getHeaderCells(row))); expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({ @@ -1394,10 +1394,10 @@ describe('CdkTable', () => { expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []}); })); - it('should stick and unstick footers', fakeAsync(() => { + it('should stick and unstick footers', waitForAsync(async () => { component.stickyFooters = ['footer-1', 'footer-3']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); getFooterCells(footerRows[2]).forEach(cell => { expectStickyStyles(cell, '10', {bottom: '0px'}); @@ -1429,7 +1429,7 @@ describe('CdkTable', () => { component.stickyFooters = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expectNoStickyStyles(footerRows); // No sticky styles on rows for native table footerRows.forEach(row => expectNoStickyStyles(getFooterCells(row))); expect(component.mostRecentStickyHeaderRowsUpdate).toEqual({ @@ -1446,29 +1446,29 @@ describe('CdkTable', () => { expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []}); })); - it('should stick tfoot when all rows are stuck', fakeAsync(() => { + it('should stick tfoot when all rows are stuck', waitForAsync(async () => { const tfoot = tableElement.querySelector('tfoot'); component.stickyFooters = ['footer-1']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expectNoStickyStyles([tfoot]); component.stickyFooters = ['footer-1', 'footer-2', 'footer-3']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expectStickyStyles(tfoot, '10', {bottom: '0px'}); expectStickyBorderClass(tfoot); component.stickyFooters = ['footer-1', 'footer-2']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); expectNoStickyStyles([tfoot]); })); - it('should stick and unstick left columns', fakeAsync(() => { + it('should stick and unstick left columns', waitForAsync(async () => { component.stickyStartColumns = ['column-1', 'column-3']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); headerRows.forEach(row => { let cells = getHeaderCells(row); @@ -1515,7 +1515,7 @@ describe('CdkTable', () => { component.stickyStartColumns = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); headerRows.forEach(row => expectNoStickyStyles(getHeaderCells(row))); dataRows.forEach(row => expectNoStickyStyles(getCells(row))); footerRows.forEach(row => expectNoStickyStyles(getFooterCells(row))); @@ -1533,10 +1533,10 @@ describe('CdkTable', () => { expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []}); })); - it('should stick and unstick right columns', fakeAsync(() => { + it('should stick and unstick right columns', waitForAsync(async () => { component.stickyEndColumns = ['column-4', 'column-6']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); headerRows.forEach(row => { let cells = getHeaderCells(row); @@ -1583,7 +1583,7 @@ describe('CdkTable', () => { component.stickyEndColumns = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); headerRows.forEach(row => expectNoStickyStyles(getHeaderCells(row))); dataRows.forEach(row => expectNoStickyStyles(getCells(row))); footerRows.forEach(row => expectNoStickyStyles(getFooterCells(row))); @@ -1601,13 +1601,13 @@ describe('CdkTable', () => { expect(component.mostRecentStickyEndColumnsUpdate).toEqual({sizes: []}); })); - it('should stick and unstick combination of sticky header, footer, and columns', fakeAsync(() => { + it('should stick and unstick combination of sticky header, footer, and columns', waitForAsync(async () => { component.stickyHeaders = ['header-1']; component.stickyFooters = ['footer-3']; component.stickyStartColumns = ['column-1']; component.stickyEndColumns = ['column-6']; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); const headerCells = getHeaderCells(headerRows[0]); expectStickyStyles(headerCells[0], '101', {top: '0px', left: '0px'}); @@ -1670,7 +1670,7 @@ describe('CdkTable', () => { component.stickyStartColumns = []; component.stickyEndColumns = []; fixture.detectChanges(); - flushMicrotasks(); + await new Promise(r => setTimeout(r)); headerRows.forEach(row => expectNoStickyStyles([row, ...getHeaderCells(row)])); dataRows.forEach(row => expectNoStickyStyles([row, ...getCells(row)])); diff --git a/src/material-experimental/column-resize/column-resize.spec.ts b/src/material-experimental/column-resize/column-resize.spec.ts index 45f6dbe16413..a67dcf04c26f 100644 --- a/src/material-experimental/column-resize/column-resize.spec.ts +++ b/src/material-experimental/column-resize/column-resize.spec.ts @@ -1,13 +1,14 @@ -import {Component, Directive, ElementRef, ViewChild, ChangeDetectionStrategy} from '@angular/core'; -import {ComponentFixture, TestBed, fakeAsync, flushMicrotasks} from '@angular/core/testing'; import {BidiModule} from '@angular/cdk/bidi'; import {DataSource} from '@angular/cdk/collections'; -import {dispatchKeyboardEvent} from '../../cdk/testing/private'; 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 {MatTableModule} from '@angular/material/table'; import {BehaviorSubject} from 'rxjs'; +import {dispatchKeyboardEvent} from '../../cdk/testing/private'; import {ColumnSize} from '@angular/cdk-experimental/column-resize'; +import {AbstractMatColumnResize} from './column-resize-directives/common'; import { MatColumnResize, MatColumnResizeFlex, @@ -16,7 +17,6 @@ import { MatDefaultEnabledColumnResizeFlex, MatDefaultEnabledColumnResizeModule, } from './index'; -import {AbstractMatColumnResize} from './column-resize-directives/common'; function getDefaultEnabledDirectiveStrings() { return { @@ -444,6 +444,7 @@ describe('Material Popover Edit', () => { const initialThumbPosition = component.getOverlayThumbPosition(1); component.updateResizeWithMouseInProgress(5); + fixture.detectChanges(); flushMicrotasks(); let thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition; @@ -461,6 +462,7 @@ describe('Material Popover Edit', () => { (expect(component.getColumnWidth(1)) as any).isApproximately(initialColumnWidth + 5); component.updateResizeWithMouseInProgress(1); + fixture.detectChanges(); flushMicrotasks(); thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition; @@ -506,6 +508,7 @@ describe('Material Popover Edit', () => { const initialThumbPosition = component.getOverlayThumbPosition(1); component.updateResizeWithMouseInProgress(5); + fixture.detectChanges(); flushMicrotasks(); let thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition; @@ -541,7 +544,7 @@ describe('Material Popover Edit', () => { expect(resize).toBe(null); component.resizeColumnWithMouse(1, 5); - flushMicrotasks(); + fixture.detectChanges(); expect(resize).toEqual({columnId: 'name', size: initialColumnWidth + 5} as any);