mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(dialog): switch to fakeAsync tests (#8564)
Refactors all the `async` dialog tests to run in the `fakeAsync` zone, making them faster and more reliable (10sec runtime down to ~2.7sec).
This commit is contained in:
committed by
Jeremy Elbourn
parent
623be22e58
commit
1fd833af41
@@ -1,11 +1,11 @@
|
||||
import {
|
||||
async,
|
||||
ComponentFixture,
|
||||
fakeAsync,
|
||||
flushMicrotasks,
|
||||
inject,
|
||||
TestBed,
|
||||
tick,
|
||||
flush,
|
||||
} from '@angular/core/testing';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
@@ -38,7 +38,7 @@ describe('MatDialog', () => {
|
||||
let viewContainerFixture: ComponentFixture<ComponentWithChildViewContainer>;
|
||||
let mockLocation: SpyLocation;
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [MatDialogModule, DialogTestModule],
|
||||
providers: [
|
||||
@@ -165,21 +165,20 @@ describe('MatDialog', () => {
|
||||
expect(dialogContainerElement.getAttribute('aria-describedby')).toBe('description-element');
|
||||
});
|
||||
|
||||
it('should close a dialog and get back a result', async(() => {
|
||||
it('should close a dialog and get back a result', fakeAsync(() => {
|
||||
let dialogRef = dialog.open(PizzaMsg, { viewContainerRef: testViewContainerRef });
|
||||
let afterCloseCallback = jasmine.createSpy('afterClose callback');
|
||||
|
||||
dialogRef.afterClosed().subscribe(afterCloseCallback);
|
||||
dialogRef.close('Charmander');
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(afterCloseCallback).toHaveBeenCalledWith('Charmander');
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeNull();
|
||||
});
|
||||
expect(afterCloseCallback).toHaveBeenCalledWith('Charmander');
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeNull();
|
||||
}));
|
||||
|
||||
it('should close a dialog and get back a result before it is closed', async(() => {
|
||||
it('should close a dialog and get back a result before it is closed', fakeAsync(() => {
|
||||
const dialogRef = dialog.open(PizzaMsg, {viewContainerRef: testViewContainerRef});
|
||||
|
||||
// beforeClose should emit before dialog container is destroyed
|
||||
@@ -191,24 +190,22 @@ describe('MatDialog', () => {
|
||||
dialogRef.beforeClose().subscribe(beforeCloseHandler);
|
||||
dialogRef.close('Bulbasaurus');
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(beforeCloseHandler).toHaveBeenCalledWith('Bulbasaurus');
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeNull();
|
||||
});
|
||||
expect(beforeCloseHandler).toHaveBeenCalledWith('Bulbasaurus');
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeNull();
|
||||
}));
|
||||
|
||||
it('should close a dialog via the escape key', async(() => {
|
||||
it('should close a dialog via the escape key', fakeAsync(() => {
|
||||
dialog.open(PizzaMsg, {
|
||||
viewContainerRef: testViewContainerRef
|
||||
});
|
||||
|
||||
dispatchKeyboardEvent(document.body, 'keydown', ESCAPE);
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeNull();
|
||||
});
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeNull();
|
||||
}));
|
||||
|
||||
it('should close from a ViewContainerRef with OnPush change detection', fakeAsync(() => {
|
||||
@@ -236,7 +233,7 @@ describe('MatDialog', () => {
|
||||
.toBe(0, 'Expected no open dialogs.');
|
||||
}));
|
||||
|
||||
it('should close when clicking on the overlay backdrop', async(() => {
|
||||
it('should close when clicking on the overlay backdrop', fakeAsync(() => {
|
||||
dialog.open(PizzaMsg, {
|
||||
viewContainerRef: testViewContainerRef
|
||||
});
|
||||
@@ -247,13 +244,12 @@ describe('MatDialog', () => {
|
||||
|
||||
backdrop.click();
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeFalsy();
|
||||
});
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeFalsy();
|
||||
}));
|
||||
|
||||
it('should emit the backdropClick stream when clicking on the overlay backdrop', async(() => {
|
||||
it('should emit the backdropClick stream when clicking on the overlay backdrop', fakeAsync(() => {
|
||||
const dialogRef = dialog.open(PizzaMsg, {
|
||||
viewContainerRef: testViewContainerRef
|
||||
});
|
||||
@@ -269,15 +265,14 @@ describe('MatDialog', () => {
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
// Additional clicks after the dialog has closed should not be emitted
|
||||
backdrop.click();
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
// Additional clicks after the dialog has closed should not be emitted
|
||||
backdrop.click();
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
}));
|
||||
|
||||
it('should emit the keyboardEvent stream when key events target the overlay', async(() => {
|
||||
it('should emit the keyboardEvent stream when key events target the overlay', fakeAsync(() => {
|
||||
const dialogRef = dialog.open(PizzaMsg, {viewContainerRef: testViewContainerRef});
|
||||
|
||||
const spy = jasmine.createSpy('keyboardEvent spy');
|
||||
@@ -302,7 +297,7 @@ describe('MatDialog', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should notify the observers if all open dialogs have finished closing', async(() => {
|
||||
it('should notify the observers if all open dialogs have finished closing', fakeAsync(() => {
|
||||
const ref1 = dialog.open(PizzaMsg, { viewContainerRef: testViewContainerRef });
|
||||
const ref2 = dialog.open(ContentElementDialog, { viewContainerRef: testViewContainerRef });
|
||||
const spy = jasmine.createSpy('afterAllClosed spy');
|
||||
@@ -311,14 +306,14 @@ describe('MatDialog', () => {
|
||||
|
||||
ref1.close();
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
|
||||
ref2.close();
|
||||
viewContainerFixture.detectChanges();
|
||||
viewContainerFixture.whenStable().then(() => expect(spy).toHaveBeenCalled());
|
||||
});
|
||||
ref2.close();
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should emit the afterAllClosed stream on subscribe if there are no open dialogs', () => {
|
||||
@@ -522,7 +517,7 @@ describe('MatDialog', () => {
|
||||
expect(dialogRef.componentInstance.directionality.value).toBe('rtl');
|
||||
});
|
||||
|
||||
it('should close all of the dialogs', async(() => {
|
||||
it('should close all of the dialogs', fakeAsync(() => {
|
||||
dialog.open(PizzaMsg);
|
||||
dialog.open(PizzaMsg);
|
||||
dialog.open(PizzaMsg);
|
||||
@@ -531,10 +526,9 @@ describe('MatDialog', () => {
|
||||
|
||||
dialog.closeAll();
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(overlayContainerElement.querySelectorAll('mat-dialog-container').length).toBe(0);
|
||||
});
|
||||
expect(overlayContainerElement.querySelectorAll('mat-dialog-container').length).toBe(0);
|
||||
}));
|
||||
|
||||
it('should set the proper animation states', () => {
|
||||
@@ -549,7 +543,7 @@ describe('MatDialog', () => {
|
||||
expect(dialogContainer._state).toBe('exit');
|
||||
});
|
||||
|
||||
it('should close all dialogs when the user goes forwards/backwards in history', async(() => {
|
||||
it('should close all dialogs when the user goes forwards/backwards in history', fakeAsync(() => {
|
||||
dialog.open(PizzaMsg);
|
||||
dialog.open(PizzaMsg);
|
||||
|
||||
@@ -557,13 +551,12 @@ describe('MatDialog', () => {
|
||||
|
||||
mockLocation.simulateUrlPop('');
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(overlayContainerElement.querySelectorAll('mat-dialog-container').length).toBe(0);
|
||||
});
|
||||
expect(overlayContainerElement.querySelectorAll('mat-dialog-container').length).toBe(0);
|
||||
}));
|
||||
|
||||
it('should close all open dialogs when the location hash changes', async(() => {
|
||||
it('should close all open dialogs when the location hash changes', fakeAsync(() => {
|
||||
dialog.open(PizzaMsg);
|
||||
dialog.open(PizzaMsg);
|
||||
|
||||
@@ -571,10 +564,9 @@ describe('MatDialog', () => {
|
||||
|
||||
mockLocation.simulateHashChange('');
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(overlayContainerElement.querySelectorAll('mat-dialog-container').length).toBe(0);
|
||||
});
|
||||
expect(overlayContainerElement.querySelectorAll('mat-dialog-container').length).toBe(0);
|
||||
}));
|
||||
|
||||
it('should have the componentInstance available in the afterClosed callback', fakeAsync(() => {
|
||||
@@ -623,17 +615,16 @@ describe('MatDialog', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should not keep a reference to the component after the dialog is closed', async(() => {
|
||||
it('should not keep a reference to the component after the dialog is closed', fakeAsync(() => {
|
||||
let dialogRef = dialog.open(PizzaMsg);
|
||||
|
||||
expect(dialogRef.componentInstance).toBeTruthy();
|
||||
|
||||
dialogRef.close();
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(dialogRef.componentInstance).toBeFalsy('Expected reference to have been cleared.');
|
||||
});
|
||||
expect(dialogRef.componentInstance).toBeFalsy('Expected reference to have been cleared.');
|
||||
}));
|
||||
|
||||
it('should assign a unique id to each dialog', () => {
|
||||
@@ -687,7 +678,7 @@ describe('MatDialog', () => {
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should allow for the disableClose option to be updated while open', async(() => {
|
||||
it('should allow for the disableClose option to be updated while open', fakeAsync(() => {
|
||||
let dialogRef = dialog.open(PizzaMsg, {
|
||||
disableClose: true,
|
||||
viewContainerRef: testViewContainerRef
|
||||
@@ -702,11 +693,10 @@ describe('MatDialog', () => {
|
||||
|
||||
dialogRef.disableClose = false;
|
||||
backdrop.click();
|
||||
|
||||
viewContainerFixture.detectChanges();
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeFalsy();
|
||||
});
|
||||
flush();
|
||||
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeFalsy();
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -877,20 +867,20 @@ describe('MatDialog', () => {
|
||||
describe('dialog content elements', () => {
|
||||
let dialogRef: MatDialogRef<ContentElementDialog>;
|
||||
|
||||
beforeEach(() => {
|
||||
dialogRef = dialog.open(ContentElementDialog);
|
||||
beforeEach(fakeAsync(() => {
|
||||
dialogRef = dialog.open(ContentElementDialog, {viewContainerRef: testViewContainerRef});
|
||||
viewContainerFixture.detectChanges();
|
||||
});
|
||||
flush();
|
||||
}));
|
||||
|
||||
it('should close the dialog when clicking on the close button', async(() => {
|
||||
it('should close the dialog when clicking on the close button', fakeAsync(() => {
|
||||
expect(overlayContainerElement.querySelectorAll('.mat-dialog-container').length).toBe(1);
|
||||
|
||||
(overlayContainerElement.querySelector('button[mat-dialog-close]') as HTMLElement).click();
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(overlayContainerElement.querySelectorAll('.mat-dialog-container').length).toBe(0);
|
||||
});
|
||||
expect(overlayContainerElement.querySelectorAll('.mat-dialog-container').length).toBe(0);
|
||||
}));
|
||||
|
||||
it('should not close the dialog if [mat-dialog-close] is applied on a non-button node', () => {
|
||||
@@ -901,15 +891,14 @@ describe('MatDialog', () => {
|
||||
expect(overlayContainerElement.querySelectorAll('.mat-dialog-container').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should allow for a user-specified aria-label on the close button', async(() => {
|
||||
it('should allow for a user-specified aria-label on the close button', fakeAsync(() => {
|
||||
let button = overlayContainerElement.querySelector('button[mat-dialog-close]')!;
|
||||
|
||||
dialogRef.componentInstance.closeButtonAriaLabel = 'Best close button ever';
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(button.getAttribute('aria-label')).toBe('Best close button ever');
|
||||
});
|
||||
expect(button.getAttribute('aria-label')).toBe('Best close button ever');
|
||||
}));
|
||||
|
||||
it('should override the "type" attribute of the close button', () => {
|
||||
@@ -918,27 +907,28 @@ describe('MatDialog', () => {
|
||||
expect(button.getAttribute('type')).toBe('button');
|
||||
});
|
||||
|
||||
it('should return the [mat-dialog-close] result when clicking the close button', async(() => {
|
||||
let afterCloseCallback = jasmine.createSpy('afterClose callback');
|
||||
dialogRef.afterClosed().subscribe(afterCloseCallback);
|
||||
it('should return the [mat-dialog-close] result when clicking the close button',
|
||||
fakeAsync(() => {
|
||||
let afterCloseCallback = jasmine.createSpy('afterClose callback');
|
||||
dialogRef.afterClosed().subscribe(afterCloseCallback);
|
||||
|
||||
(overlayContainerElement.querySelector('button.close-with-true') as HTMLElement).click();
|
||||
viewContainerFixture.detectChanges();
|
||||
(overlayContainerElement.querySelector('button.close-with-true') as HTMLElement).click();
|
||||
viewContainerFixture.detectChanges();
|
||||
flush();
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(afterCloseCallback).toHaveBeenCalledWith(true);
|
||||
});
|
||||
}));
|
||||
}));
|
||||
|
||||
it('should set the aria-labelledby attribute to the id of the title', async(() => {
|
||||
it('should set the aria-labelledby attribute to the id of the title', fakeAsync(() => {
|
||||
let title = overlayContainerElement.querySelector('[mat-dialog-title]')!;
|
||||
let container = overlayContainerElement.querySelector('mat-dialog-container')!;
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(title.id).toBeTruthy('Expected title element to have an id.');
|
||||
expect(container.getAttribute('aria-labelledby'))
|
||||
.toBe(title.id, 'Expected the aria-labelledby to match the title id.');
|
||||
});
|
||||
flush();
|
||||
viewContainerFixture.detectChanges();
|
||||
|
||||
expect(title.id).toBeTruthy('Expected title element to have an id.');
|
||||
expect(container.getAttribute('aria-labelledby'))
|
||||
.toBe(title.id, 'Expected the aria-labelledby to match the title id.');
|
||||
}));
|
||||
|
||||
});
|
||||
@@ -976,7 +966,7 @@ describe('MatDialog with a parent MatDialog', () => {
|
||||
let overlayContainerElement: HTMLElement;
|
||||
let fixture: ComponentFixture<ComponentThatProvidesMatDialog>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [MatDialogModule, DialogTestModule],
|
||||
declarations: [ComponentThatProvidesMatDialog],
|
||||
@@ -1005,24 +995,24 @@ describe('MatDialog with a parent MatDialog', () => {
|
||||
});
|
||||
|
||||
it('should close dialogs opened by a parent when calling closeAll on a child MatDialog',
|
||||
async(() => {
|
||||
fakeAsync(() => {
|
||||
parentDialog.open(PizzaMsg);
|
||||
fixture.detectChanges();
|
||||
flush();
|
||||
|
||||
expect(overlayContainerElement.textContent)
|
||||
.toContain('Pizza', 'Expected a dialog to be opened');
|
||||
|
||||
childDialog.closeAll();
|
||||
fixture.detectChanges();
|
||||
flush();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
expect(overlayContainerElement.textContent!.trim())
|
||||
.toBe('', 'Expected closeAll on child MatDialog to close dialog opened by parent');
|
||||
});
|
||||
expect(overlayContainerElement.textContent!.trim())
|
||||
.toBe('', 'Expected closeAll on child MatDialog to close dialog opened by parent');
|
||||
}));
|
||||
|
||||
it('should close dialogs opened by a child when calling closeAll on a parent MatDialog',
|
||||
async(() => {
|
||||
fakeAsync(() => {
|
||||
childDialog.open(PizzaMsg);
|
||||
fixture.detectChanges();
|
||||
|
||||
@@ -1031,22 +1021,20 @@ describe('MatDialog with a parent MatDialog', () => {
|
||||
|
||||
parentDialog.closeAll();
|
||||
fixture.detectChanges();
|
||||
flush();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
expect(overlayContainerElement.textContent!.trim())
|
||||
.toBe('', 'Expected closeAll on parent MatDialog to close dialog opened by child');
|
||||
});
|
||||
expect(overlayContainerElement.textContent!.trim())
|
||||
.toBe('', 'Expected closeAll on parent MatDialog to close dialog opened by child');
|
||||
}));
|
||||
|
||||
it('should close the top dialog via the escape key', async(() => {
|
||||
it('should close the top dialog via the escape key', fakeAsync(() => {
|
||||
childDialog.open(PizzaMsg);
|
||||
|
||||
dispatchKeyboardEvent(document.body, 'keydown', ESCAPE);
|
||||
fixture.detectChanges();
|
||||
flush();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeNull();
|
||||
});
|
||||
expect(overlayContainerElement.querySelector('mat-dialog-container')).toBeNull();
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user