Skip to content

Commit f084f13

Browse files
crisbetoandrewseguin
authored andcommitted
fix(material-experimental): use harnesses for mat-option (#17009)
Follow-up from #16620 and #16710. Adds a dedicated harness for `mat-option` and `mat-optgroup`. Note that some of the code is duplicated. This is because we don't have a shared place where to put the harness so that `mat-autocomplete` and `mat-select` don't have to depend on each other. I've intentionally kept the harnesses to only the methods we need, but once we have `experimental/core`, I'll combine them and implement all of the states that are supported by `mat-option`.
1 parent 9bd73d3 commit f084f13

File tree

6 files changed

+152
-10
lines changed

6 files changed

+152
-10
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {ComponentHarness, HarnessPredicate, BaseHarnessFilters} from '@angular/cdk/testing';
10+
11+
// TODO(crisbeto): combine these with the ones in `mat-autocomplete`
12+
// and expand to cover all states once we have experimental/core.
13+
14+
export interface OptionHarnessFilters extends BaseHarnessFilters {
15+
text?: string;
16+
}
17+
18+
export interface OptionGroupHarnessFilters extends BaseHarnessFilters {
19+
labelText?: string;
20+
}
21+
22+
/**
23+
* Harness for interacting with a the `mat-option` for a `mat-select` in tests.
24+
* @dynamic
25+
*/
26+
export class MatSelectOptionHarness extends ComponentHarness {
27+
// TODO(crisbeto): things to add here when adding a common option harness:
28+
// - isDisabled
29+
// - isSelected
30+
// - isActive
31+
// - isMultiple
32+
33+
static with(options: OptionHarnessFilters = {}) {
34+
return new HarnessPredicate(MatSelectOptionHarness, options)
35+
.addOption('text', options.text,
36+
async (harness, title) =>
37+
HarnessPredicate.stringMatches(await harness.getText(), title));
38+
}
39+
40+
static hostSelector = '.mat-select-panel .mat-option';
41+
42+
/** Clicks the option. */
43+
async click(): Promise<void> {
44+
return (await this.host()).click();
45+
}
46+
47+
/** Gets a promise for the option's label text. */
48+
async getText(): Promise<string> {
49+
return (await this.host()).text();
50+
}
51+
}
52+
53+
/**
54+
* Harness for interacting with a the `mat-optgroup` for a `mat-select` in tests.
55+
* @dynamic
56+
*/
57+
export class MatSelectOptionGroupHarness extends ComponentHarness {
58+
private _label = this.locatorFor('.mat-optgroup-label');
59+
static hostSelector = '.mat-select-panel .mat-optgroup';
60+
61+
static with(options: OptionGroupHarnessFilters = {}) {
62+
return new HarnessPredicate(MatSelectOptionGroupHarness, options)
63+
.addOption('labelText', options.labelText,
64+
async (harness, title) =>
65+
HarnessPredicate.stringMatches(await harness.getLabelText(), title));
66+
}
67+
68+
/** Gets a promise for the option group's label text. */
69+
async getLabelText(): Promise<string> {
70+
return (await this._label()).text();
71+
}
72+
}
73+

src/material-experimental/select/testing/select-harness.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
MatFormFieldControlHarness
1212
} from '@angular/material-experimental/form-field/testing/control';
1313
import {SelectHarnessFilters} from './select-harness-filters';
14+
import {MatSelectOptionHarness, MatSelectOptionGroupHarness} from './option-harness';
1415

1516
/** Selector for the select panel. */
1617
const PANEL_SELECTOR = '.mat-select-panel';
@@ -24,8 +25,8 @@ export class MatSelectHarness extends MatFormFieldControlHarness {
2425
private _panel = this._documentRootLocator.locatorFor(PANEL_SELECTOR);
2526
private _backdrop = this._documentRootLocator.locatorFor('.cdk-overlay-backdrop');
2627
private _optionalPanel = this._documentRootLocator.locatorForOptional(PANEL_SELECTOR);
27-
private _options = this._documentRootLocator.locatorForAll(`${PANEL_SELECTOR} .mat-option`);
28-
private _groups = this._documentRootLocator.locatorForAll(`${PANEL_SELECTOR} .mat-optgroup`);
28+
private _options = this._documentRootLocator.locatorForAll(MatSelectOptionHarness);
29+
private _groups = this._documentRootLocator.locatorForAll(MatSelectOptionGroupHarness);
2930
private _trigger = this.locatorFor('.mat-select-trigger');
3031
private _value = this.locatorFor('.mat-select-value');
3132

@@ -88,12 +89,12 @@ export class MatSelectHarness extends MatFormFieldControlHarness {
8889
}
8990

9091
/** Gets the options inside the select panel. */
91-
async getOptions(): Promise<TestElement[]> {
92+
async getOptions(): Promise<MatSelectOptionHarness[]> {
9293
return this._options();
9394
}
9495

9596
/** Gets the groups of options inside the panel. */
96-
async getOptionGroups(): Promise<TestElement[]> {
97+
async getOptionGroups(): Promise<MatSelectOptionGroupHarness[]> {
9798
return this._groups();
9899
}
99100

src/material-experimental/select/testing/shared.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ export function runHarnessTests(
138138
const options = await select.getOptions();
139139

140140
expect(options.length).toBe(11);
141-
expect(await options[5].text()).toBe('New York');
141+
expect(await options[5].getText()).toBe('New York');
142142
});
143143

144144
it('should be able to get the select panel groups', async () => {

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import {ComponentHarness, HarnessPredicate, TestElement} from '@angular/cdk/testing';
1010
import {coerceBooleanProperty} from '@angular/cdk/coercion';
1111
import {AutocompleteHarnessFilters} from './autocomplete-harness-filters';
12+
import {MatAutocompleteOptionHarness, MatAutocompleteOptionGroupHarness} from './option-harness';
1213

1314
/** Selector for the autocomplete panel. */
1415
const PANEL_SELECTOR = '.mat-autocomplete-panel';
@@ -21,8 +22,8 @@ export class MatAutocompleteHarness extends ComponentHarness {
2122
private _documentRootLocator = this.documentRootLocatorFactory();
2223
private _panel = this._documentRootLocator.locatorFor(PANEL_SELECTOR);
2324
private _optionalPanel = this._documentRootLocator.locatorForOptional(PANEL_SELECTOR);
24-
private _options = this._documentRootLocator.locatorForAll(`${PANEL_SELECTOR} .mat-option`);
25-
private _groups = this._documentRootLocator.locatorForAll(`${PANEL_SELECTOR} .mat-optgroup`);
25+
private _options = this._documentRootLocator.locatorForAll(MatAutocompleteOptionHarness);
26+
private _groups = this._documentRootLocator.locatorForAll(MatAutocompleteOptionGroupHarness);
2627

2728
static hostSelector = '.mat-autocomplete-trigger';
2829

@@ -73,12 +74,12 @@ export class MatAutocompleteHarness extends ComponentHarness {
7374
}
7475

7576
/** Gets the options inside the autocomplete panel. */
76-
async getOptions(): Promise<TestElement[]> {
77+
async getOptions(): Promise<MatAutocompleteOptionHarness[]> {
7778
return this._options();
7879
}
7980

8081
/** Gets the groups of options inside the panel. */
81-
async getOptionGroups(): Promise<TestElement[]> {
82+
async getOptionGroups(): Promise<MatAutocompleteOptionGroupHarness[]> {
8283
return this._groups();
8384
}
8485

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {ComponentHarness, HarnessPredicate, BaseHarnessFilters} from '@angular/cdk/testing';
10+
11+
// TODO(crisbeto): combine these with the ones in `mat-select`
12+
// and expand to cover all states once we have experimental/core.
13+
14+
export interface OptionHarnessFilters extends BaseHarnessFilters {
15+
text?: string;
16+
}
17+
18+
export interface OptionGroupHarnessFilters extends BaseHarnessFilters {
19+
labelText?: string;
20+
}
21+
22+
/**
23+
* Harness for interacting with a the `mat-option` for a `mat-autocomplete` in tests.
24+
* @dynamic
25+
*/
26+
export class MatAutocompleteOptionHarness extends ComponentHarness {
27+
static hostSelector = '.mat-autocomplete-panel .mat-option';
28+
29+
static with(options: OptionHarnessFilters = {}) {
30+
return new HarnessPredicate(MatAutocompleteOptionHarness, options)
31+
.addOption('text', options.text,
32+
async (harness, title) =>
33+
HarnessPredicate.stringMatches(await harness.getText(), title));
34+
}
35+
36+
/** Clicks the option. */
37+
async click(): Promise<void> {
38+
return (await this.host()).click();
39+
}
40+
41+
/** Gets a promise for the option's label text. */
42+
async getText(): Promise<string> {
43+
return (await this.host()).text();
44+
}
45+
}
46+
47+
/**
48+
* Harness for interacting with a the `mat-optgroup` for a `mat-autocomplete` in tests.
49+
* @dynamic
50+
*/
51+
export class MatAutocompleteOptionGroupHarness extends ComponentHarness {
52+
private _label = this.locatorFor('.mat-optgroup-label');
53+
static hostSelector = '.mat-autocomplete-panel .mat-optgroup';
54+
55+
static with(options: OptionGroupHarnessFilters = {}) {
56+
return new HarnessPredicate(MatAutocompleteOptionGroupHarness, options)
57+
.addOption('labelText', options.labelText,
58+
async (harness, title) =>
59+
HarnessPredicate.stringMatches(await harness.getLabelText(), title));
60+
}
61+
62+
/** Gets a promise for the option group's label text. */
63+
async getLabelText(): Promise<string> {
64+
return (await this._label()).text();
65+
}
66+
}
67+

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export function runHarnessTests(
8282
const options = await input.getOptions();
8383

8484
expect(options.length).toBe(11);
85-
expect(await options[5].text()).toBe('New York');
85+
expect(await options[5].getText()).toBe('New York');
8686
});
8787

8888
it('should be able to get the autocomplete panel groups', async () => {

0 commit comments

Comments
 (0)