diff --git a/src/material/button/testing/button-harness-filters.ts b/src/material/button/testing/button-harness-filters.ts index 4363961feb40..90966874566a 100644 --- a/src/material/button/testing/button-harness-filters.ts +++ b/src/material/button/testing/button-harness-filters.ts @@ -8,8 +8,14 @@ import {BaseHarnessFilters} from '@angular/cdk/testing'; +/** Possible button appearances. */ +export type ButtonVariant = 'basic' | 'raised' | 'flat' | 'icon' | 'stroked' | 'fab' | 'mini-fab'; + /** A set of criteria that can be used to filter a list of button harness instances. */ export interface ButtonHarnessFilters extends BaseHarnessFilters { /** Only find instances whose text matches the given value. */ text?: string | RegExp; + + /** Only find instances with a variant. */ + variant?: ButtonVariant; } diff --git a/src/material/button/testing/button-harness.ts b/src/material/button/testing/button-harness.ts index e4ac50c6ae8a..9978aaf5e773 100644 --- a/src/material/button/testing/button-harness.ts +++ b/src/material/button/testing/button-harness.ts @@ -12,7 +12,7 @@ import { HarnessPredicate, } from '@angular/cdk/testing'; import {coerceBooleanProperty} from '@angular/cdk/coercion'; -import {ButtonHarnessFilters} from './button-harness-filters'; +import {ButtonHarnessFilters, ButtonVariant} from './button-harness-filters'; /** Harness for interacting with a MDC-based mat-button in tests. */ export class MatButtonHarness extends ContentContainerComponentHarness { @@ -25,15 +25,20 @@ export class MatButtonHarness extends ContentContainerComponentHarness { * @param options Options for narrowing the search: * - `selector` finds a button whose host element matches the given selector. * - `text` finds a button with specific text content. + * - `variant` finds buttons matching a specific variant. * @return a `HarnessPredicate` configured with the given options. */ static with( this: ComponentHarnessConstructor, options: ButtonHarnessFilters = {}, ): HarnessPredicate { - return new HarnessPredicate(this, options).addOption('text', options.text, (harness, text) => - HarnessPredicate.stringMatches(harness.getText(), text), - ); + return new HarnessPredicate(this, options) + .addOption('text', options.text, (harness, text) => + HarnessPredicate.stringMatches(harness.getText(), text), + ) + .addOption('variant', options.variant, (harness, variant) => + HarnessPredicate.stringMatches(harness.getVariant(), variant), + ); } /** @@ -75,4 +80,25 @@ export class MatButtonHarness extends ContentContainerComponentHarness { async isFocused(): Promise { return (await this.host()).isFocused(); } + + /** Gets the variant of the button. */ + async getVariant(): Promise { + const host = await this.host(); + + if ((await host.getAttribute('mat-raised-button')) != null) { + return 'raised'; + } else if ((await host.getAttribute('mat-flat-button')) != null) { + return 'flat'; + } else if ((await host.getAttribute('mat-icon-button')) != null) { + return 'icon'; + } else if ((await host.getAttribute('mat-stroked-button')) != null) { + return 'stroked'; + } else if ((await host.getAttribute('mat-fab')) != null) { + return 'fab'; + } else if ((await host.getAttribute('mat-mini-fab')) != null) { + return 'mini-fab'; + } + + return 'basic'; + } } diff --git a/src/material/button/testing/shared.spec.ts b/src/material/button/testing/shared.spec.ts index 2a96d2045c3c..e7a516347a91 100644 --- a/src/material/button/testing/shared.spec.ts +++ b/src/material/button/testing/shared.spec.ts @@ -1,5 +1,5 @@ import {Platform, PlatformModule} from '@angular/cdk/platform'; -import {HarnessLoader} from '@angular/cdk/testing'; +import {HarnessLoader, parallel} from '@angular/cdk/testing'; import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; import {Component} from '@angular/core'; import {ComponentFixture, inject, TestBed} from '@angular/core/testing'; @@ -113,6 +113,34 @@ export function runHarnessTests( expect(await homeIcon.getName()).toBe('home'); expect(await favIcon.getName()).toBe('favorite'); }); + + it('should load all button harnesses', async () => { + const buttons = await loader.getAllHarnesses(buttonHarness); + const variants = await parallel(() => buttons.map(button => button.getVariant())); + + expect(variants).toEqual([ + 'basic', + 'flat', + 'raised', + 'stroked', + 'icon', + 'icon', + 'fab', + 'mini-fab', + 'basic', + 'flat', + 'raised', + 'stroked', + 'icon', + 'fab', + 'mini-fab', + ]); + }); + + it('should be able to filter buttons based on their variant', async () => { + const button = await loader.getHarness(buttonHarness.with({variant: 'flat'})); + expect(await button.getText()).toBe('Flat button'); + }); } @Component({ diff --git a/src/material/legacy-button/testing/button-harness.ts b/src/material/legacy-button/testing/button-harness.ts index c6f9df3eb210..6a54403743f1 100644 --- a/src/material/legacy-button/testing/button-harness.ts +++ b/src/material/legacy-button/testing/button-harness.ts @@ -8,7 +8,7 @@ import {ContentContainerComponentHarness, HarnessPredicate} from '@angular/cdk/testing'; import {coerceBooleanProperty} from '@angular/cdk/coercion'; -import {ButtonHarnessFilters} from '@angular/material/button/testing'; +import {ButtonHarnessFilters, ButtonVariant} from '@angular/material/button/testing'; /** * Harness for interacting with a standard mat-button in tests. @@ -28,11 +28,13 @@ export class MatLegacyButtonHarness extends ContentContainerComponentHarness { * @return a `HarnessPredicate` configured with the given options. */ static with(options: ButtonHarnessFilters = {}): HarnessPredicate { - return new HarnessPredicate(MatLegacyButtonHarness, options).addOption( - 'text', - options.text, - (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text), - ); + return new HarnessPredicate(MatLegacyButtonHarness, options) + .addOption('text', options.text, (harness, text) => + HarnessPredicate.stringMatches(harness.getText(), text), + ) + .addOption('variant', options.variant, (harness, variant) => + HarnessPredicate.stringMatches(harness.getVariant(), variant), + ); } /** @@ -74,4 +76,25 @@ export class MatLegacyButtonHarness extends ContentContainerComponentHarness { async isFocused(): Promise { return (await this.host()).isFocused(); } + + /** Gets the variant of the button. */ + async getVariant(): Promise { + const host = await this.host(); + + if ((await host.getAttribute('mat-raised-button')) != null) { + return 'raised'; + } else if ((await host.getAttribute('mat-flat-button')) != null) { + return 'flat'; + } else if ((await host.getAttribute('mat-icon-button')) != null) { + return 'icon'; + } else if ((await host.getAttribute('mat-stroked-button')) != null) { + return 'stroked'; + } else if ((await host.getAttribute('mat-fab')) != null) { + return 'fab'; + } else if ((await host.getAttribute('mat-mini-fab')) != null) { + return 'mini-fab'; + } + + return 'basic'; + } } diff --git a/src/material/legacy-button/testing/public-api.ts b/src/material/legacy-button/testing/public-api.ts index 7663152c7846..d9845ed2f440 100644 --- a/src/material/legacy-button/testing/public-api.ts +++ b/src/material/legacy-button/testing/public-api.ts @@ -7,4 +7,7 @@ */ export {MatLegacyButtonHarness} from './button-harness'; -export {ButtonHarnessFilters as LegacyButtonHarnessFilters} from '@angular/material/button/testing'; +export { + ButtonHarnessFilters as LegacyButtonHarnessFilters, + ButtonVariant as LegacyButtonVariant, +} from '@angular/material/button/testing'; diff --git a/tools/public_api_guard/material/button-testing.md b/tools/public_api_guard/material/button-testing.md index a29166dbe87c..595637c8a775 100644 --- a/tools/public_api_guard/material/button-testing.md +++ b/tools/public_api_guard/material/button-testing.md @@ -12,8 +12,12 @@ import { HarnessPredicate } from '@angular/cdk/testing'; // @public export interface ButtonHarnessFilters extends BaseHarnessFilters { text?: string | RegExp; + variant?: ButtonVariant; } +// @public +export type ButtonVariant = 'basic' | 'raised' | 'flat' | 'icon' | 'stroked' | 'fab' | 'mini-fab'; + // @public export class MatButtonHarness extends ContentContainerComponentHarness { blur(): Promise; @@ -22,6 +26,7 @@ export class MatButtonHarness extends ContentContainerComponentHarness { click(): Promise; focus(): Promise; getText(): Promise; + getVariant(): Promise; // (undocumented) static hostSelector: string; isDisabled(): Promise; diff --git a/tools/public_api_guard/material/legacy-button-testing.md b/tools/public_api_guard/material/legacy-button-testing.md index faafeb384494..740007ff2eec 100644 --- a/tools/public_api_guard/material/legacy-button-testing.md +++ b/tools/public_api_guard/material/legacy-button-testing.md @@ -7,9 +7,12 @@ import { ContentContainerComponentHarness } from '@angular/cdk/testing'; import { HarnessPredicate } from '@angular/cdk/testing'; import { ButtonHarnessFilters as LegacyButtonHarnessFilters } from '@angular/material/button/testing'; +import { ButtonVariant as LegacyButtonVariant } from '@angular/material/button/testing'; export { LegacyButtonHarnessFilters } +export { LegacyButtonVariant } + // @public @deprecated export class MatLegacyButtonHarness extends ContentContainerComponentHarness { blur(): Promise; @@ -18,6 +21,7 @@ export class MatLegacyButtonHarness extends ContentContainerComponentHarness { click(): Promise; focus(): Promise; getText(): Promise; + getVariant(): Promise; static hostSelector: string; isDisabled(): Promise; isFocused(): Promise;