Skip to content

Commit

Permalink
feat(material/tabs/testing): polish harness API
Browse files Browse the repository at this point in the history
  • Loading branch information
mmalerba committed Oct 15, 2019
1 parent aa2cbf7 commit 7b1c2ea
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 26 deletions.
1 change: 1 addition & 0 deletions src/material/tabs/testing/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ ng_test_library(
deps = [
":testing",
"//src/cdk/testing",
"//src/cdk/private/testing",
"//src/cdk/testing/testbed",
"//src/material/tabs",
"@npm//@angular/forms",
Expand Down
31 changes: 24 additions & 7 deletions src/material/tabs/testing/shared.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {expectAsyncError} from '@angular/cdk/private/testing';
import {HarnessLoader} from '@angular/cdk/testing';
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {Component} from '@angular/core';
Expand Down Expand Up @@ -51,6 +52,26 @@ export function runHarnessTests(
expect(tabs.length).toBe(3);
});

it('should be able to get filtered tabs', async () => {
const tabGroup = await loader.getHarness(tabGroupHarness);
const tabs = await tabGroup.getTabs({label: 'Third'});
expect(tabs.length).toBe(1);
expect(await tabs[0].getLabel()).toBe('Third');
});

it('should be able to select tab from tab-group', async () => {
const tabGroup = await loader.getHarness(tabGroupHarness);
expect(await (await tabGroup.getSelectedTab()).getLabel()).toBe('First');
await tabGroup.selectTab({label: 'Second'});
expect(await (await tabGroup.getSelectedTab()).getLabel()).toBe('Second');
});

it('should throw error when attempting to select invalid tab', async () => {
const tabGroup = await loader.getHarness(tabGroupHarness);
await expectAsyncError(() => tabGroup.selectTab({label: 'Fake'}),
/Error: Cannot find mat-tab matching {"label":"Fake"}/);
});

it('should be able to get label of tabs', async () => {
const tabGroup = await loader.getHarness(tabGroupHarness);
const tabs = await tabGroup.getTabs();
Expand Down Expand Up @@ -78,13 +99,9 @@ export function runHarnessTests(
it('should be able to get content element of active tab', async () => {
const tabGroup = await loader.getHarness(tabGroupHarness);
const tabs = await tabGroup.getTabs();
expect(await (await tabs[0].getContentElement()).text()).toBe('Content 1');
});

it('should be able to get content element of active tab', async () => {
const tabGroup = await loader.getHarness(tabGroupHarness);
const tabs = await tabGroup.getTabs();
expect(await (await tabs[0].getContentElement()).text()).toBe('Content 1');
const contentSelector = await tabs[0].getSelectorForContent();
const contentEl = document.querySelector(contentSelector) as HTMLElement;
expect(contentEl.innerText.trim()).toBe('Content 1');
});

it('should be able to get disabled state of tab', async () => {
Expand Down
17 changes: 12 additions & 5 deletions src/material/tabs/testing/tab-group-harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing';
import {TabGroupHarnessFilters} from './tab-harness-filters';
import {TabGroupHarnessFilters, TabHarnessFilters} from './tab-harness-filters';
import {MatTabHarness} from './tab-harness';

/**
Expand All @@ -34,11 +34,9 @@ export class MatTabGroupHarness extends ComponentHarness {
});
}

private _tabs = this.locatorForAll(MatTabHarness);

/** Gets all tabs of the tab group. */
async getTabs(): Promise<MatTabHarness[]> {
return this._tabs();
async getTabs(filter: TabHarnessFilters = {}): Promise<MatTabHarness[]> {
return this.locatorForAll(MatTabHarness.with(filter))();
}

/** Gets the selected tab of the tab group. */
Expand All @@ -52,4 +50,13 @@ export class MatTabGroupHarness extends ComponentHarness {
}
throw new Error('No selected tab could be found.');
}

/** Selects a tab in this tab group. */
async selectTab(filter: TabHarnessFilters = {}): Promise<void> {
const tabs = await this.getTabs(filter);
if (!tabs.length) {
throw Error(`Cannot find mat-tab matching ${JSON.stringify(filter)}`);
}
await tabs[0].select();
}
}
4 changes: 3 additions & 1 deletion src/material/tabs/testing/tab-harness-filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
*/
import {BaseHarnessFilters} from '@angular/cdk/testing';

export interface TabHarnessFilters extends BaseHarnessFilters {}
export interface TabHarnessFilters extends BaseHarnessFilters {
label?: string | RegExp;
}

export interface TabGroupHarnessFilters extends BaseHarnessFilters {
selectedTabLabel?: string | RegExp;
Expand Down
19 changes: 6 additions & 13 deletions src/material/tabs/testing/tab-harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export class MatTabHarness extends ComponentHarness {
* Gets a `HarnessPredicate` that can be used to search for a tab with specific attributes.
*/
static with(options: TabHarnessFilters = {}): HarnessPredicate<MatTabHarness> {
return new HarnessPredicate(MatTabHarness, options);
return new HarnessPredicate(MatTabHarness, options)
.addOption('label', options.label,
(harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
}

private _rootLocatorFactory = this.documentRootLocatorFactory();
Expand All @@ -40,15 +42,6 @@ export class MatTabHarness extends ComponentHarness {
return (await this.host()).getAttribute('aria-labelledby');
}

/**
* Gets the content element of the given tab. Note that the element will be empty
* until the tab is selected. This is an implementation detail of the tab-group
* in order to avoid rendering of non-active tabs.
*/
async getContentElement(): Promise<TestElement> {
return this._rootLocatorFactory.locatorFor(`#${await this._getContentId()}`)();
}

/** Whether the tab is selected. */
async isSelected(): Promise<boolean> {
const hostEl = await this.host();
Expand All @@ -69,10 +62,10 @@ export class MatTabHarness extends ComponentHarness {
await (await this.host()).click();
}

/** Gets the element id for the content of the current tab. */
private async _getContentId(): Promise<string> {
/** Gets a selector that can be used to locate the tab's content element. */
async getSelectorForContent(): Promise<string> {
const hostEl = await this.host();
// Tabs never have an empty "aria-controls" attribute.
return (await hostEl.getAttribute('aria-controls'))!;
return '#' + await hostEl.getAttribute('aria-controls');
}
}

0 comments on commit 7b1c2ea

Please sign in to comment.