Skip to content

Commit 9f695f2

Browse files
crisbetowagnermaciel
authored andcommitted
feat(material-experimental/mdc-autocomplete): add test harnesses
Adds test harnesses for the MDC-based autocomplete module. Also fixes one class that wasn't renamed to match the MDC naming scheme.
1 parent 2d4cab2 commit 9f695f2

File tree

8 files changed

+194
-1
lines changed

8 files changed

+194
-1
lines changed

src/material-experimental/config.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
entryPoints = [
22
"column-resize",
33
"mdc-autocomplete",
4+
"mdc-autocomplete/testing",
45
"mdc-button",
56
"mdc-button/testing",
67
"mdc-card",

src/material-experimental/mdc-autocomplete/autocomplete-trigger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const MAT_AUTOCOMPLETE_VALUE_ACCESSOR: any = {
2424
@Directive({
2525
selector: `input[matAutocomplete], textarea[matAutocomplete]`,
2626
host: {
27-
'class': 'mat-autocomplete-trigger',
27+
'class': 'mat-mdc-autocomplete-trigger',
2828
'[attr.autocomplete]': 'autocompleteAttribute',
2929
'[attr.role]': 'autocompleteDisabled ? null : "combobox"',
3030
'[attr.aria-autocomplete]': 'autocompleteDisabled ? null : "list"',
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
load("//tools:defaults.bzl", "ng_test_library", "ng_web_test_suite", "ts_library")
2+
3+
package(default_visibility = ["//visibility:public"])
4+
5+
ts_library(
6+
name = "testing",
7+
srcs = glob(
8+
["**/*.ts"],
9+
exclude = ["**/*.spec.ts"],
10+
),
11+
module_name = "@angular/material-experimental/mdc-autocomplete/testing",
12+
deps = [
13+
"//src/cdk/coercion",
14+
"//src/cdk/testing",
15+
"//src/material-experimental/mdc-core/testing",
16+
],
17+
)
18+
19+
filegroup(
20+
name = "source-files",
21+
srcs = glob(["**/*.ts"]),
22+
)
23+
24+
ng_test_library(
25+
name = "unit_tests_lib",
26+
srcs = glob(["**/*.spec.ts"]),
27+
deps = [
28+
":testing",
29+
"//src/material-experimental/mdc-autocomplete",
30+
"//src/material/autocomplete/testing:harness_tests_lib",
31+
],
32+
)
33+
34+
ng_web_test_suite(
35+
name = "unit_tests",
36+
deps = [":unit_tests_lib"],
37+
)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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 {BaseHarnessFilters} from '@angular/cdk/testing';
10+
11+
/** A set of criteria that can be used to filter a list of `MatAutocompleteHarness` instances. */
12+
export interface AutocompleteHarnessFilters extends BaseHarnessFilters {
13+
/** Only find instances whose associated input element matches the given value. */
14+
value?: string | RegExp;
15+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import {MatAutocompleteModule} from '@angular/material-experimental/mdc-autocomplete';
2+
import {runHarnessTests} from '@angular/material/autocomplete/testing/shared.spec';
3+
import {MatAutocompleteHarness} from './autocomplete-harness';
4+
5+
describe('MDC-based MatAutocompleteHarness', () => {
6+
runHarnessTests(MatAutocompleteModule, MatAutocompleteHarness as any);
7+
});
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
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 {coerceBooleanProperty} from '@angular/cdk/coercion';
10+
import {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing';
11+
import {
12+
MatOptgroupHarness,
13+
MatOptionHarness,
14+
OptgroupHarnessFilters,
15+
OptionHarnessFilters
16+
} from '@angular/material-experimental/mdc-core/testing';
17+
import {AutocompleteHarnessFilters} from './autocomplete-harness-filters';
18+
19+
/** Harness for interacting with an MDC-based mat-autocomplete in tests. */
20+
export class MatAutocompleteHarness extends ComponentHarness {
21+
private _documentRootLocator = this.documentRootLocatorFactory();
22+
23+
/** The selector for the host element of a `MatAutocomplete` instance. */
24+
static hostSelector = '.mat-mdc-autocomplete-trigger';
25+
26+
/**
27+
* Gets a `HarnessPredicate` that can be used to search for a `MatAutocompleteHarness` that meets
28+
* certain criteria.
29+
* @param options Options for filtering which autocomplete instances are considered a match.
30+
* @return a `HarnessPredicate` configured with the given options.
31+
*/
32+
static with(options: AutocompleteHarnessFilters = {}): HarnessPredicate<MatAutocompleteHarness> {
33+
return new HarnessPredicate(MatAutocompleteHarness, options)
34+
.addOption('value', options.value,
35+
(harness, value) => HarnessPredicate.stringMatches(harness.getValue(), value));
36+
}
37+
38+
/** Gets the value of the autocomplete input. */
39+
async getValue(): Promise<string> {
40+
return (await this.host()).getProperty('value');
41+
}
42+
43+
/** Whether the autocomplete input is disabled. */
44+
async isDisabled(): Promise<boolean> {
45+
const disabled = (await this.host()).getAttribute('disabled');
46+
return coerceBooleanProperty(await disabled);
47+
}
48+
49+
/** Focuses the autocomplete input. */
50+
async focus(): Promise<void> {
51+
return (await this.host()).focus();
52+
}
53+
54+
/** Blurs the autocomplete input. */
55+
async blur(): Promise<void> {
56+
return (await this.host()).blur();
57+
}
58+
59+
/** Whether the autocomplete input is focused. */
60+
async isFocused(): Promise<boolean> {
61+
return (await this.host()).isFocused();
62+
}
63+
64+
/** Enters text into the autocomplete. */
65+
async enterText(value: string): Promise<void> {
66+
return (await this.host()).sendKeys(value);
67+
}
68+
69+
/** Gets the options inside the autocomplete panel. */
70+
async getOptions(filters: Omit<OptionHarnessFilters, 'ancestor'> = {}):
71+
Promise<MatOptionHarness[]> {
72+
return this._documentRootLocator.locatorForAll(MatOptionHarness.with({
73+
...filters,
74+
ancestor: await this._getPanelSelector()
75+
}))();
76+
}
77+
78+
/** Gets the option groups inside the autocomplete panel. */
79+
async getOptionGroups(filters: Omit<OptgroupHarnessFilters, 'ancestor'> = {}):
80+
Promise<MatOptgroupHarness[]> {
81+
return this._documentRootLocator.locatorForAll(MatOptgroupHarness.with({
82+
...filters,
83+
ancestor: await this._getPanelSelector()
84+
}))();
85+
}
86+
87+
/** Selects the first option matching the given filters. */
88+
async selectOption(filters: OptionHarnessFilters): Promise<void> {
89+
await this.focus(); // Focus the input to make sure the autocomplete panel is shown.
90+
const options = await this.getOptions(filters);
91+
if (!options.length) {
92+
throw Error(`Could not find a mat-option matching ${JSON.stringify(filters)}`);
93+
}
94+
await options[0].click();
95+
}
96+
97+
/** Whether the autocomplete is open. */
98+
async isOpen(): Promise<boolean> {
99+
const panel = await this._getPanel();
100+
return !!panel && await panel.hasClass('mat-mdc-autocomplete-visible');
101+
}
102+
103+
/** Gets the panel associated with this autocomplete trigger. */
104+
private async _getPanel() {
105+
// Technically this is static, but it needs to be in a
106+
// function, because the autocomplete's panel ID can changed.
107+
return this._documentRootLocator.locatorForOptional(await this._getPanelSelector())();
108+
}
109+
110+
/** Gets the selector that can be used to find the autocomplete trigger's panel. */
111+
private async _getPanelSelector(): Promise<string> {
112+
return `#${(await (await this.host()).getAttribute('aria-owns'))}`;
113+
}
114+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
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+
export * from './public-api';
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
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+
export * from './autocomplete-harness';
10+
export * from './autocomplete-harness-filters';

0 commit comments

Comments
 (0)