Skip to content

Commit b3348e9

Browse files
committed
fix(material-experimental): use harnesses for mat-option
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 7f6972f commit b3348e9

File tree

6 files changed

+130
-10
lines changed

6 files changed

+130
-10
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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+
/**
19+
* Harness for interacting with a the `mat-option` for a `mat-select` in tests.
20+
* @dynamic
21+
*/
22+
export class MatSelectOptionHarness extends ComponentHarness {
23+
// TODO(crisbeto): things to add here when adding a common option harness:
24+
// - isDisabled
25+
// - isSelected
26+
// - isActive
27+
// - isMultiple
28+
29+
static with(options: OptionHarnessFilters = {}) {
30+
return new HarnessPredicate(MatSelectOptionHarness, options)
31+
.addOption('text', options.text,
32+
async (harness, title) =>
33+
HarnessPredicate.stringMatches(await harness.getText(), title));
34+
}
35+
36+
static hostSelector = '.mat-select-panel .mat-option';
37+
38+
/** Clicks the option. */
39+
async click(): Promise<void> {
40+
return (await this.host()).click();
41+
}
42+
43+
/** Gets a promise for the option's label text. */
44+
async getText(): Promise<string> {
45+
return (await this.host()).text();
46+
}
47+
}
48+
49+
/**
50+
* Harness for interacting with a the `mat-optgroup` for a `mat-select` in tests.
51+
* @dynamic
52+
*/
53+
export class MatSelectOptionGroupHarness extends ComponentHarness {
54+
private _label = this.locatorFor('.mat-optgroup-label');
55+
static hostSelector = '.mat-select-panel .mat-optgroup';
56+
57+
/** Gets a promise for the option group's label text. */
58+
async getLabelText(): Promise<string> {
59+
return (await this._label()).text();
60+
}
61+
}
62+

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

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

99
import {ComponentHarness, HarnessPredicate, TestElement} from '@angular/cdk/testing';
1010
import {SelectHarnessFilters} from './select-harness-filters';
11+
import {MatSelectOptionHarness, MatSelectOptionGroupHarness} from './option-harness';
1112

1213
/** Selector for the select panel. */
1314
const PANEL_SELECTOR = '.mat-select-panel';
@@ -21,8 +22,8 @@ export class MatSelectHarness extends ComponentHarness {
2122
private _panel = this._documentRootLocator.locatorFor(PANEL_SELECTOR);
2223
private _backdrop = this._documentRootLocator.locatorFor('.cdk-overlay-backdrop');
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(MatSelectOptionHarness);
26+
private _groups = this._documentRootLocator.locatorForAll(MatSelectOptionGroupHarness);
2627
private _trigger = this.locatorFor('.mat-select-trigger');
2728
private _value = this.locatorFor('.mat-select-value');
2829

@@ -85,12 +86,12 @@ export class MatSelectHarness extends ComponentHarness {
8586
}
8687

8788
/** Gets the options inside the select panel. */
88-
async getOptions(): Promise<TestElement[]> {
89+
async getOptions(): Promise<MatSelectOptionHarness[]> {
8990
return this._options();
9091
}
9192

9293
/** Gets the groups of options inside the panel. */
93-
async getOptionGroups(): Promise<TestElement[]> {
94+
async getOptionGroups(): Promise<MatSelectOptionGroupHarness[]> {
9495
return this._groups();
9596
}
9697

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: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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+
/**
19+
* Harness for interacting with a the `mat-option` for a `mat-autocomplete` in tests.
20+
* @dynamic
21+
*/
22+
export class MatAutocompleteOptionHarness extends ComponentHarness {
23+
static hostSelector = '.mat-autocomplete-panel .mat-option';
24+
25+
static with(options: OptionHarnessFilters = {}) {
26+
return new HarnessPredicate(MatAutocompleteOptionHarness, options)
27+
.addOption('text', options.text,
28+
async (harness, title) =>
29+
HarnessPredicate.stringMatches(await harness.getText(), title));
30+
}
31+
32+
/** Clicks the option. */
33+
async click(): Promise<void> {
34+
return (await this.host()).click();
35+
}
36+
37+
/** Gets a promise for the option's label text. */
38+
async getText(): Promise<string> {
39+
return (await this.host()).text();
40+
}
41+
}
42+
43+
/**
44+
* Harness for interacting with a the `mat-optgroup` for a `mat-autocomplete` in tests.
45+
* @dynamic
46+
*/
47+
export class MatAutocompleteOptionGroupHarness extends ComponentHarness {
48+
private _label = this.locatorFor('.mat-optgroup-label');
49+
static hostSelector = '.mat-autocomplete-panel .mat-optgroup';
50+
51+
/** Gets a promise for the option group's label text. */
52+
async getLabelText(): Promise<string> {
53+
return (await this._label()).text();
54+
}
55+
}
56+

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)