Skip to content

Commit 5b6da05

Browse files
committed
(test): add e2e tests for autocomplete (#4491)
1 parent a779017 commit 5b6da05

File tree

8 files changed

+109
-4
lines changed

8 files changed

+109
-4
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import {browser, by, element} from 'protractor';
2+
import {screenshot} from '../screenshot';
3+
import {expectToExist} from '../util/index';
4+
5+
6+
describe('autocomplete', () => {
7+
const autocompletePanelSelector = '.mat-autocomplete-panel.mat-autocomplete-visible';
8+
let page: AutocompletePage;
9+
10+
beforeEach(() => page = new AutocompletePage());
11+
12+
it('should open the panel when the input is focused', async () => {
13+
expectToExist(autocompletePanelSelector, false);
14+
page.autocompleteInput().click();
15+
16+
expectToExist(autocompletePanelSelector);
17+
expect(await page.autocompletePanel().getText()).toEqual('One\nTwo\nThree\nFour');
18+
screenshot();
19+
});
20+
21+
it('should close the panel when an option is clicked', async () => {
22+
page.autocompleteInput().click();
23+
page.option('One').click();
24+
25+
expectToExist(autocompletePanelSelector, false);
26+
screenshot();
27+
});
28+
29+
it('should set the selected option text to the input', async () => {
30+
page.autocompleteInput().click();
31+
page.option('One').click();
32+
33+
expect(await page.getInputText()).toEqual('One');
34+
});
35+
36+
it('should trigger filtering with proper key', async () => {
37+
page.autocompleteInput().sendKeys('T');
38+
39+
expect(await page.autocompletePanel().getText()).toEqual('Two\nThree');
40+
screenshot();
41+
});
42+
});
43+
44+
class AutocompletePage {
45+
constructor() { browser.get('/autocomplete'); }
46+
autocompleteInput = () => element(by.id('autocomplete-input'));
47+
autocompletePanel = () => element(by.css('.mat-autocomplete-panel'));
48+
option = (text: string) => element(by.cssContainingText('mat-option', text));
49+
getInputText = () => this.autocompleteInput().getAttribute('value');
50+
}

src/cdk/accordion/public-api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
export {CdkAccordionItem} from './accordion-item';
9+
export {CdkAccordionItem} from './accordion-item';
1010
export {CdkAccordion} from './accordion';
1111
export * from './accordion-module';
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<section>
2+
<mat-form-field>
3+
<input id="autocomplete-input" matInput placeholder="Choose" [matAutocomplete]="auto" [formControl]="optionCtrl">
4+
</mat-form-field>
5+
6+
<mat-autocomplete #auto="matAutocomplete">
7+
<mat-option *ngFor="let option of filteredOptions | async" [value]="option">
8+
{{option}}
9+
</mat-option>
10+
</mat-autocomplete>
11+
</section>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import {FormControl} from '@angular/forms';
2+
import {Observable} from 'rxjs/Observable';
3+
import {startWith} from 'rxjs/operators/startWith';
4+
import {map} from 'rxjs/operators/map';
5+
import {
6+
Component,
7+
QueryList,
8+
ViewChild,
9+
ViewChildren
10+
} from '@angular/core';
11+
import {
12+
MatAutocompleteTrigger,
13+
MatOption
14+
} from '@angular/material';
15+
16+
17+
@Component({
18+
moduleId: module.id,
19+
selector: 'autocomplete-e2e',
20+
templateUrl: 'autocomplete-e2e.html',
21+
})
22+
export class AutocompleteE2E {
23+
optionCtrl = new FormControl();
24+
filteredOptions: Observable<string[]>;
25+
options = ['One', 'Two', 'Three', 'Four'];
26+
27+
@ViewChild(MatAutocompleteTrigger) trigger: MatAutocompleteTrigger;
28+
@ViewChildren(MatOption) matOptions: QueryList<MatOption>;
29+
30+
constructor() {
31+
this.filteredOptions = this.optionCtrl.valueChanges.pipe(
32+
startWith(null),
33+
map((val: string) => {
34+
return val ? this.options.filter(option => option.startsWith(val)) : this.options.slice();
35+
}));
36+
}
37+
}

src/e2e-app/e2e-app-module.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import {SlideToggleE2E} from './slide-toggle/slide-toggle-e2e';
1919
import {InputE2E} from './input/input-e2e';
2020
import {SidenavE2E} from './sidenav/sidenav-e2e';
2121
import {BlockScrollStrategyE2E} from './block-scroll-strategy/block-scroll-strategy-e2e';
22+
import {AutocompleteE2E} from './autocomplete/autocomplete-e2e';
2223
import {
24+
MatAutocompleteModule,
2325
MatButtonModule,
2426
MatCheckboxModule,
2527
MatDialogModule,
@@ -47,6 +49,7 @@ import {ReactiveFormsModule} from '@angular/forms';
4749
*/
4850
@NgModule({
4951
exports: [
52+
MatAutocompleteModule,
5053
MatButtonModule,
5154
MatCheckboxModule,
5255
MatDialogModule,
@@ -78,8 +81,10 @@ export class E2eMaterialModule {}
7881
ReactiveFormsModule
7982
],
8083
declarations: [
84+
AutocompleteE2E,
8185
BasicTabs,
8286
ButtonE2E,
87+
BlockScrollStrategyE2E,
8388
DialogE2E,
8489
E2EApp,
8590
FullscreenE2E,
@@ -95,8 +100,7 @@ export class E2eMaterialModule {}
95100
SimpleRadioButtons,
96101
SlideToggleE2E,
97102
TestDialog,
98-
TestDialogFullScreen,
99-
BlockScrollStrategyE2E
103+
TestDialogFullScreen
100104
],
101105
bootstrap: [E2EApp],
102106
providers: [

src/e2e-app/e2e-app/e2e-app.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<button (click)="showLinks = !showLinks">Toggle Navigation Links</button>
22

33
<mat-nav-list *ngIf="showLinks">
4+
<a mat-list-item [routerLink]="['autocomplete']">Autocomplete</a>
45
<a mat-list-item [routerLink]="['block-scroll-strategy']">Block scroll strategy</a>
56
<a mat-list-item [routerLink]="['button']">Button</a>
67
<a mat-list-item [routerLink]="['button-toggle']">Button Toggle</a>

src/e2e-app/e2e-app/routes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {FullscreenE2E} from '../fullscreen/fullscreen-e2e';
1515
import {InputE2E} from '../input/input-e2e';
1616
import {SidenavE2E} from '../sidenav/sidenav-e2e';
1717
import {BlockScrollStrategyE2E} from '../block-scroll-strategy/block-scroll-strategy-e2e';
18+
import {AutocompleteE2E} from '../autocomplete/autocomplete-e2e';
1819
import {
1920
CardFancyExample,
2021
ListOverviewExample,
@@ -26,6 +27,7 @@ import {
2627

2728
export const E2E_APP_ROUTES: Routes = [
2829
{path: '', component: Home},
30+
{path: 'autocomplete', component: AutocompleteE2E},
2931
{path: 'block-scroll-strategy', component: BlockScrollStrategyE2E},
3032
{path: 'button', component: ButtonE2E},
3133
{path: 'button-toggle', component: ButtonToggleOverviewExample},

src/lib/autocomplete/autocomplete-trigger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export function getMatAutocompleteMissingPanelError(): Error {
104104
'aria-autocomplete': 'list',
105105
'[attr.aria-activedescendant]': 'activeOption?.id',
106106
'[attr.aria-expanded]': 'panelOpen.toString()',
107-
'[attr.aria-owns]': 'autocomplete?.id',
107+
'[attr.aria-owns]': '(autocomplete && autocomplete._isOpen) ? autocomplete.id : null',
108108
// Note: we use `focusin`, as opposed to `focus`, in order to open the panel
109109
// a little earlier. This avoids issues where IE delays the focusing of the input.
110110
'(focusin)': '_handleFocus()',

0 commit comments

Comments
 (0)