Skip to content

Commit 87e17aa

Browse files
authored
feat(material/button): add variant to button harness (#25770)
Adds the ability to get the variant of a button harness and to filter by it. Fixes #25755.
1 parent 72547a4 commit 87e17aa

File tree

7 files changed

+107
-12
lines changed

7 files changed

+107
-12
lines changed

src/material/button/testing/button-harness-filters.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@
88

99
import {BaseHarnessFilters} from '@angular/cdk/testing';
1010

11+
/** Possible button appearances. */
12+
export type ButtonVariant = 'basic' | 'raised' | 'flat' | 'icon' | 'stroked' | 'fab' | 'mini-fab';
13+
1114
/** A set of criteria that can be used to filter a list of button harness instances. */
1215
export interface ButtonHarnessFilters extends BaseHarnessFilters {
1316
/** Only find instances whose text matches the given value. */
1417
text?: string | RegExp;
18+
19+
/** Only find instances with a variant. */
20+
variant?: ButtonVariant;
1521
}

src/material/button/testing/button-harness.ts

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
HarnessPredicate,
1313
} from '@angular/cdk/testing';
1414
import {coerceBooleanProperty} from '@angular/cdk/coercion';
15-
import {ButtonHarnessFilters} from './button-harness-filters';
15+
import {ButtonHarnessFilters, ButtonVariant} from './button-harness-filters';
1616

1717
/** Harness for interacting with a MDC-based mat-button in tests. */
1818
export class MatButtonHarness extends ContentContainerComponentHarness {
@@ -25,15 +25,20 @@ export class MatButtonHarness extends ContentContainerComponentHarness {
2525
* @param options Options for narrowing the search:
2626
* - `selector` finds a button whose host element matches the given selector.
2727
* - `text` finds a button with specific text content.
28+
* - `variant` finds buttons matching a specific variant.
2829
* @return a `HarnessPredicate` configured with the given options.
2930
*/
3031
static with<T extends MatButtonHarness>(
3132
this: ComponentHarnessConstructor<T>,
3233
options: ButtonHarnessFilters = {},
3334
): HarnessPredicate<T> {
34-
return new HarnessPredicate(this, options).addOption('text', options.text, (harness, text) =>
35-
HarnessPredicate.stringMatches(harness.getText(), text),
36-
);
35+
return new HarnessPredicate(this, options)
36+
.addOption('text', options.text, (harness, text) =>
37+
HarnessPredicate.stringMatches(harness.getText(), text),
38+
)
39+
.addOption('variant', options.variant, (harness, variant) =>
40+
HarnessPredicate.stringMatches(harness.getVariant(), variant),
41+
);
3742
}
3843

3944
/**
@@ -75,4 +80,25 @@ export class MatButtonHarness extends ContentContainerComponentHarness {
7580
async isFocused(): Promise<boolean> {
7681
return (await this.host()).isFocused();
7782
}
83+
84+
/** Gets the variant of the button. */
85+
async getVariant(): Promise<ButtonVariant> {
86+
const host = await this.host();
87+
88+
if ((await host.getAttribute('mat-raised-button')) != null) {
89+
return 'raised';
90+
} else if ((await host.getAttribute('mat-flat-button')) != null) {
91+
return 'flat';
92+
} else if ((await host.getAttribute('mat-icon-button')) != null) {
93+
return 'icon';
94+
} else if ((await host.getAttribute('mat-stroked-button')) != null) {
95+
return 'stroked';
96+
} else if ((await host.getAttribute('mat-fab')) != null) {
97+
return 'fab';
98+
} else if ((await host.getAttribute('mat-mini-fab')) != null) {
99+
return 'mini-fab';
100+
}
101+
102+
return 'basic';
103+
}
78104
}

src/material/button/testing/shared.spec.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Platform, PlatformModule} from '@angular/cdk/platform';
2-
import {HarnessLoader} from '@angular/cdk/testing';
2+
import {HarnessLoader, parallel} from '@angular/cdk/testing';
33
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
44
import {Component} from '@angular/core';
55
import {ComponentFixture, inject, TestBed} from '@angular/core/testing';
@@ -113,6 +113,34 @@ export function runHarnessTests(
113113
expect(await homeIcon.getName()).toBe('home');
114114
expect(await favIcon.getName()).toBe('favorite');
115115
});
116+
117+
it('should load all button harnesses', async () => {
118+
const buttons = await loader.getAllHarnesses(buttonHarness);
119+
const variants = await parallel(() => buttons.map(button => button.getVariant()));
120+
121+
expect(variants).toEqual([
122+
'basic',
123+
'flat',
124+
'raised',
125+
'stroked',
126+
'icon',
127+
'icon',
128+
'fab',
129+
'mini-fab',
130+
'basic',
131+
'flat',
132+
'raised',
133+
'stroked',
134+
'icon',
135+
'fab',
136+
'mini-fab',
137+
]);
138+
});
139+
140+
it('should be able to filter buttons based on their variant', async () => {
141+
const button = await loader.getHarness(buttonHarness.with({variant: 'flat'}));
142+
expect(await button.getText()).toBe('Flat button');
143+
});
116144
}
117145

118146
@Component({

src/material/legacy-button/testing/button-harness.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import {ContentContainerComponentHarness, HarnessPredicate} from '@angular/cdk/testing';
1010
import {coerceBooleanProperty} from '@angular/cdk/coercion';
11-
import {ButtonHarnessFilters} from '@angular/material/button/testing';
11+
import {ButtonHarnessFilters, ButtonVariant} from '@angular/material/button/testing';
1212

1313
/**
1414
* Harness for interacting with a standard mat-button in tests.
@@ -28,11 +28,13 @@ export class MatLegacyButtonHarness extends ContentContainerComponentHarness {
2828
* @return a `HarnessPredicate` configured with the given options.
2929
*/
3030
static with(options: ButtonHarnessFilters = {}): HarnessPredicate<MatLegacyButtonHarness> {
31-
return new HarnessPredicate(MatLegacyButtonHarness, options).addOption(
32-
'text',
33-
options.text,
34-
(harness, text) => HarnessPredicate.stringMatches(harness.getText(), text),
35-
);
31+
return new HarnessPredicate(MatLegacyButtonHarness, options)
32+
.addOption('text', options.text, (harness, text) =>
33+
HarnessPredicate.stringMatches(harness.getText(), text),
34+
)
35+
.addOption('variant', options.variant, (harness, variant) =>
36+
HarnessPredicate.stringMatches(harness.getVariant(), variant),
37+
);
3638
}
3739

3840
/**
@@ -74,4 +76,25 @@ export class MatLegacyButtonHarness extends ContentContainerComponentHarness {
7476
async isFocused(): Promise<boolean> {
7577
return (await this.host()).isFocused();
7678
}
79+
80+
/** Gets the variant of the button. */
81+
async getVariant(): Promise<ButtonVariant> {
82+
const host = await this.host();
83+
84+
if ((await host.getAttribute('mat-raised-button')) != null) {
85+
return 'raised';
86+
} else if ((await host.getAttribute('mat-flat-button')) != null) {
87+
return 'flat';
88+
} else if ((await host.getAttribute('mat-icon-button')) != null) {
89+
return 'icon';
90+
} else if ((await host.getAttribute('mat-stroked-button')) != null) {
91+
return 'stroked';
92+
} else if ((await host.getAttribute('mat-fab')) != null) {
93+
return 'fab';
94+
} else if ((await host.getAttribute('mat-mini-fab')) != null) {
95+
return 'mini-fab';
96+
}
97+
98+
return 'basic';
99+
}
77100
}

src/material/legacy-button/testing/public-api.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,7 @@
77
*/
88

99
export {MatLegacyButtonHarness} from './button-harness';
10-
export {ButtonHarnessFilters as LegacyButtonHarnessFilters} from '@angular/material/button/testing';
10+
export {
11+
ButtonHarnessFilters as LegacyButtonHarnessFilters,
12+
ButtonVariant as LegacyButtonVariant,
13+
} from '@angular/material/button/testing';

tools/public_api_guard/material/button-testing.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@ import { HarnessPredicate } from '@angular/cdk/testing';
1212
// @public
1313
export interface ButtonHarnessFilters extends BaseHarnessFilters {
1414
text?: string | RegExp;
15+
variant?: ButtonVariant;
1516
}
1617

18+
// @public
19+
export type ButtonVariant = 'basic' | 'raised' | 'flat' | 'icon' | 'stroked' | 'fab' | 'mini-fab';
20+
1721
// @public
1822
export class MatButtonHarness extends ContentContainerComponentHarness {
1923
blur(): Promise<void>;
@@ -22,6 +26,7 @@ export class MatButtonHarness extends ContentContainerComponentHarness {
2226
click(): Promise<void>;
2327
focus(): Promise<void>;
2428
getText(): Promise<string>;
29+
getVariant(): Promise<ButtonVariant>;
2530
// (undocumented)
2631
static hostSelector: string;
2732
isDisabled(): Promise<boolean>;

tools/public_api_guard/material/legacy-button-testing.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
import { ContentContainerComponentHarness } from '@angular/cdk/testing';
88
import { HarnessPredicate } from '@angular/cdk/testing';
99
import { ButtonHarnessFilters as LegacyButtonHarnessFilters } from '@angular/material/button/testing';
10+
import { ButtonVariant as LegacyButtonVariant } from '@angular/material/button/testing';
1011

1112
export { LegacyButtonHarnessFilters }
1213

14+
export { LegacyButtonVariant }
15+
1316
// @public @deprecated
1417
export class MatLegacyButtonHarness extends ContentContainerComponentHarness {
1518
blur(): Promise<void>;
@@ -18,6 +21,7 @@ export class MatLegacyButtonHarness extends ContentContainerComponentHarness {
1821
click(): Promise<void>;
1922
focus(): Promise<void>;
2023
getText(): Promise<string>;
24+
getVariant(): Promise<LegacyButtonVariant>;
2125
static hostSelector: string;
2226
isDisabled(): Promise<boolean>;
2327
isFocused(): Promise<boolean>;

0 commit comments

Comments
 (0)