diff --git a/src/material/snack-bar/snack-bar-container.ts b/src/material/snack-bar/snack-bar-container.ts index 7fef7067c7a8..6913ba1280a7 100644 --- a/src/material/snack-bar/snack-bar-container.ts +++ b/src/material/snack-bar/snack-bar-container.ts @@ -152,6 +152,12 @@ export class MatSnackBarContainer extends BasePortalOutlet implements OnDestroy // where multiple snack bars are opened in quick succession (e.g. two consecutive calls to // `MatSnackBar.open`). this._animationState = 'hidden'; + + // Mark this element with an 'exit' attribute to indicate that the snackbar has + // been dismissed and will soon be removed from the DOM. This is used by the snackbar + // test harness. + this._elementRef.nativeElement.setAttribute('mat-exit', ''); + return this._onExit; } diff --git a/src/material/snack-bar/snack-bar.spec.ts b/src/material/snack-bar/snack-bar.spec.ts index f1d4e5c2ec38..d71d28222f02 100644 --- a/src/material/snack-bar/snack-bar.spec.ts +++ b/src/material/snack-bar/snack-bar.spec.ts @@ -177,6 +177,10 @@ describe('MatSnackBar', () => { snackBarRef.afterDismissed().subscribe({complete: dismissCompleteSpy}); snackBarRef.dismiss(); + const messageElement = overlayContainerElement.querySelector('snack-bar-container')!; + expect (messageElement.hasAttribute('mat-exit')) + .toBe(true, 'Expected the snackbar container to have the "exit" attribute upon dismiss'); + viewContainerFixture.detectChanges(); // Run through animations for dismissal flush(); diff --git a/src/material/snack-bar/testing/shared.spec.ts b/src/material/snack-bar/testing/shared.spec.ts index b7445e854bcb..7dc828e78d73 100644 --- a/src/material/snack-bar/testing/shared.spec.ts +++ b/src/material/snack-bar/testing/shared.spec.ts @@ -128,8 +128,13 @@ export function runHarnessTests( let actionCount = 0; snackBarRef.onAction().subscribe(() => actionCount++); + expect(await snackBar.isDismissed()) + .toBe(false, 'The snackbar should be present in the DOM before dismiss'); + await snackBar.dismissWithAction(); expect(actionCount).toBe(1); + expect(await snackBar.isDismissed()) + .toBe(true, 'The snackbar should be absent from the DOM after dismiss'); fixture.componentInstance.openSimple('No action'); snackBar = await loader.getHarness(snackBarHarness); diff --git a/src/material/snack-bar/testing/snack-bar-harness.ts b/src/material/snack-bar/testing/snack-bar-harness.ts index e90eedf3095f..a0dbe6d2fcee 100644 --- a/src/material/snack-bar/testing/snack-bar-harness.ts +++ b/src/material/snack-bar/testing/snack-bar-harness.ts @@ -74,13 +74,29 @@ export class MatSnackBarHarness extends ComponentHarness { return (await this._simpleSnackBarMessage()).text(); } + /** Gets whether the snack-bar has been dismissed. */ + async isDismissed(): Promise { + // We consider the snackbar dismissed if it's not in the DOM. We can assert that the + // element isn't in the DOM by seeing that its width and height are zero. + + const host = await this.host(); + const [exit, dimensions] = await Promise.all([ + // The snackbar container is marked with the "exit" attribute after it has been dismissed + // but before the animation has finished (after which it's removed from the DOM). + host.getAttribute('mat-exit'), + host.getDimensions(), + ]); + + return exit != null || (!!dimensions && dimensions.height === 0 && dimensions.width === 0); + } + /** * Asserts that the current snack-bar does not use custom content. Promise rejects if * custom content is used. */ private async _assertSimpleSnackBar(): Promise { if (!await this._isSimpleSnackBar()) { - throw new Error('Method cannot be used for snack-bar with custom content.'); + throw Error('Method cannot be used for snack-bar with custom content.'); } } @@ -91,7 +107,7 @@ export class MatSnackBarHarness extends ComponentHarness { private async _assertSimpleSnackBarWithAction(): Promise { await this._assertSimpleSnackBar(); if (!await this.hasAction()) { - throw new Error('Method cannot be used for standard snack-bar without action.'); + throw Error('Method cannot be used for standard snack-bar without action.'); } } diff --git a/tools/public_api_guard/material/snack-bar/testing.d.ts b/tools/public_api_guard/material/snack-bar/testing.d.ts index 6a51a6fc5838..89ab70c8bc4d 100644 --- a/tools/public_api_guard/material/snack-bar/testing.d.ts +++ b/tools/public_api_guard/material/snack-bar/testing.d.ts @@ -4,6 +4,7 @@ export declare class MatSnackBarHarness extends ComponentHarness { getMessage(): Promise; getRole(): Promise<'alert' | 'status' | null>; hasAction(): Promise; + isDismissed(): Promise; static hostSelector: string; static with(options?: SnackBarHarnessFilters): HarnessPredicate; }