Skip to content

fix(material-experimental): use harnesses for mat-option #17009

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/material-experimental/select/testing/option-harness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {ComponentHarness, HarnessPredicate, BaseHarnessFilters} from '@angular/cdk/testing';

// TODO(crisbeto): combine these with the ones in `mat-autocomplete`
// and expand to cover all states once we have experimental/core.

export interface OptionHarnessFilters extends BaseHarnessFilters {
text?: string;
}

export interface OptionGroupHarnessFilters extends BaseHarnessFilters {
labelText?: string;
}

/**
* Harness for interacting with a the `mat-option` for a `mat-select` in tests.
* @dynamic
*/
export class MatSelectOptionHarness extends ComponentHarness {
// TODO(crisbeto): things to add here when adding a common option harness:
// - isDisabled
// - isSelected
// - isActive
// - isMultiple

static with(options: OptionHarnessFilters = {}) {
return new HarnessPredicate(MatSelectOptionHarness, options)
.addOption('text', options.text,
async (harness, title) =>
HarnessPredicate.stringMatches(await harness.getText(), title));
}

static hostSelector = '.mat-select-panel .mat-option';

/** Clicks the option. */
async click(): Promise<void> {
return (await this.host()).click();
}

/** Gets a promise for the option's label text. */
async getText(): Promise<string> {
return (await this.host()).text();
}
}

/**
* Harness for interacting with a the `mat-optgroup` for a `mat-select` in tests.
* @dynamic
*/
export class MatSelectOptionGroupHarness extends ComponentHarness {
private _label = this.locatorFor('.mat-optgroup-label');
static hostSelector = '.mat-select-panel .mat-optgroup';

static with(options: OptionGroupHarnessFilters = {}) {
return new HarnessPredicate(MatSelectOptionGroupHarness, options)
.addOption('labelText', options.labelText,
async (harness, title) =>
HarnessPredicate.stringMatches(await harness.getLabelText(), title));
}

/** Gets a promise for the option group's label text. */
async getLabelText(): Promise<string> {
return (await this._label()).text();
}
}

9 changes: 5 additions & 4 deletions src/material-experimental/select/testing/select-harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

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

/** Selector for the select panel. */
const PANEL_SELECTOR = '.mat-select-panel';
Expand All @@ -21,8 +22,8 @@ export class MatSelectHarness extends ComponentHarness {
private _panel = this._documentRootLocator.locatorFor(PANEL_SELECTOR);
private _backdrop = this._documentRootLocator.locatorFor('.cdk-overlay-backdrop');
private _optionalPanel = this._documentRootLocator.locatorForOptional(PANEL_SELECTOR);
private _options = this._documentRootLocator.locatorForAll(`${PANEL_SELECTOR} .mat-option`);
private _groups = this._documentRootLocator.locatorForAll(`${PANEL_SELECTOR} .mat-optgroup`);
private _options = this._documentRootLocator.locatorForAll(MatSelectOptionHarness);
private _groups = this._documentRootLocator.locatorForAll(MatSelectOptionGroupHarness);
private _trigger = this.locatorFor('.mat-select-trigger');
private _value = this.locatorFor('.mat-select-value');

Expand Down Expand Up @@ -85,12 +86,12 @@ export class MatSelectHarness extends ComponentHarness {
}

/** Gets the options inside the select panel. */
async getOptions(): Promise<TestElement[]> {
async getOptions(): Promise<MatSelectOptionHarness[]> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we want to make this optionally take a HarnessPredicate? I seem to remember discussing that at some point. So we can search for a specific option more easily

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what that would look like. Here's what I got to compile, but it feels a little weird so I don't know if it's correct:

async getOptions(predicate?: HarnessPredicate<MatSelectOptionHarness>): Promise<MatSelectOptionHarness[]> {
  return this._documentRootLocator.locatorForAll(predicate || MatSelectOptionHarness)();
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I think I meant OptionHarnessFilters not HarnessPredicate. That way people can do getOptions({text: 'Option 1'}). Under the hood that would use a harness predicate: ...locatorForAll(MatSelectOptions.with(options)). My bad for not explaining that right

return this._options();
}

/** Gets the groups of options inside the panel. */
async getOptionGroups(): Promise<TestElement[]> {
async getOptionGroups(): Promise<MatSelectOptionGroupHarness[]> {
return this._groups();
}

Expand Down
2 changes: 1 addition & 1 deletion src/material-experimental/select/testing/shared.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export function runHarnessTests(
const options = await select.getOptions();

expect(options.length).toBe(11);
expect(await options[5].text()).toBe('New York');
expect(await options[5].getText()).toBe('New York');
});

it('should be able to get the select panel groups', async () => {
Expand Down
9 changes: 5 additions & 4 deletions src/material/autocomplete/testing/autocomplete-harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import {ComponentHarness, HarnessPredicate, TestElement} from '@angular/cdk/testing';
import {coerceBooleanProperty} from '@angular/cdk/coercion';
import {AutocompleteHarnessFilters} from './autocomplete-harness-filters';
import {MatAutocompleteOptionHarness, MatAutocompleteOptionGroupHarness} from './option-harness';

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

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

Expand Down Expand Up @@ -73,12 +74,12 @@ export class MatAutocompleteHarness extends ComponentHarness {
}

/** Gets the options inside the autocomplete panel. */
async getOptions(): Promise<TestElement[]> {
async getOptions(): Promise<MatAutocompleteOptionHarness[]> {
return this._options();
}

/** Gets the groups of options inside the panel. */
async getOptionGroups(): Promise<TestElement[]> {
async getOptionGroups(): Promise<MatAutocompleteOptionGroupHarness[]> {
return this._groups();
}

Expand Down
67 changes: 67 additions & 0 deletions src/material/autocomplete/testing/option-harness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {ComponentHarness, HarnessPredicate, BaseHarnessFilters} from '@angular/cdk/testing';

// TODO(crisbeto): combine these with the ones in `mat-select`
// and expand to cover all states once we have experimental/core.

export interface OptionHarnessFilters extends BaseHarnessFilters {
text?: string;
}

export interface OptionGroupHarnessFilters extends BaseHarnessFilters {
labelText?: string;
}

/**
* Harness for interacting with a the `mat-option` for a `mat-autocomplete` in tests.
* @dynamic
*/
export class MatAutocompleteOptionHarness extends ComponentHarness {
static hostSelector = '.mat-autocomplete-panel .mat-option';

static with(options: OptionHarnessFilters = {}) {
return new HarnessPredicate(MatAutocompleteOptionHarness, options)
.addOption('text', options.text,
async (harness, title) =>
HarnessPredicate.stringMatches(await harness.getText(), title));
}

/** Clicks the option. */
async click(): Promise<void> {
return (await this.host()).click();
}

/** Gets a promise for the option's label text. */
async getText(): Promise<string> {
return (await this.host()).text();
}
}

/**
* Harness for interacting with a the `mat-optgroup` for a `mat-autocomplete` in tests.
* @dynamic
*/
export class MatAutocompleteOptionGroupHarness extends ComponentHarness {
private _label = this.locatorFor('.mat-optgroup-label');
static hostSelector = '.mat-autocomplete-panel .mat-optgroup';

static with(options: OptionGroupHarnessFilters = {}) {
return new HarnessPredicate(MatAutocompleteOptionGroupHarness, options)
.addOption('labelText', options.labelText,
async (harness, title) =>
HarnessPredicate.stringMatches(await harness.getLabelText(), title));
}

/** Gets a promise for the option group's label text. */
async getLabelText(): Promise<string> {
return (await this._label()).text();
}
}

2 changes: 1 addition & 1 deletion src/material/autocomplete/testing/shared.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export function runHarnessTests(
const options = await input.getOptions();

expect(options.length).toBe(11);
expect(await options[5].text()).toBe('New York');
expect(await options[5].getText()).toBe('New York');
});

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