Skip to content

Commit 7b1c2ea

Browse files
committed
feat(material/tabs/testing): polish harness API
1 parent aa2cbf7 commit 7b1c2ea

File tree

5 files changed

+46
-26
lines changed

5 files changed

+46
-26
lines changed

src/material/tabs/testing/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ ng_test_library(
2626
deps = [
2727
":testing",
2828
"//src/cdk/testing",
29+
"//src/cdk/private/testing",
2930
"//src/cdk/testing/testbed",
3031
"//src/material/tabs",
3132
"@npm//@angular/forms",

src/material/tabs/testing/shared.spec.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {expectAsyncError} from '@angular/cdk/private/testing';
12
import {HarnessLoader} from '@angular/cdk/testing';
23
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
34
import {Component} from '@angular/core';
@@ -51,6 +52,26 @@ export function runHarnessTests(
5152
expect(tabs.length).toBe(3);
5253
});
5354

55+
it('should be able to get filtered tabs', async () => {
56+
const tabGroup = await loader.getHarness(tabGroupHarness);
57+
const tabs = await tabGroup.getTabs({label: 'Third'});
58+
expect(tabs.length).toBe(1);
59+
expect(await tabs[0].getLabel()).toBe('Third');
60+
});
61+
62+
it('should be able to select tab from tab-group', async () => {
63+
const tabGroup = await loader.getHarness(tabGroupHarness);
64+
expect(await (await tabGroup.getSelectedTab()).getLabel()).toBe('First');
65+
await tabGroup.selectTab({label: 'Second'});
66+
expect(await (await tabGroup.getSelectedTab()).getLabel()).toBe('Second');
67+
});
68+
69+
it('should throw error when attempting to select invalid tab', async () => {
70+
const tabGroup = await loader.getHarness(tabGroupHarness);
71+
await expectAsyncError(() => tabGroup.selectTab({label: 'Fake'}),
72+
/Error: Cannot find mat-tab matching {"label":"Fake"}/);
73+
});
74+
5475
it('should be able to get label of tabs', async () => {
5576
const tabGroup = await loader.getHarness(tabGroupHarness);
5677
const tabs = await tabGroup.getTabs();
@@ -78,13 +99,9 @@ export function runHarnessTests(
7899
it('should be able to get content element of active tab', async () => {
79100
const tabGroup = await loader.getHarness(tabGroupHarness);
80101
const tabs = await tabGroup.getTabs();
81-
expect(await (await tabs[0].getContentElement()).text()).toBe('Content 1');
82-
});
83-
84-
it('should be able to get content element of active tab', async () => {
85-
const tabGroup = await loader.getHarness(tabGroupHarness);
86-
const tabs = await tabGroup.getTabs();
87-
expect(await (await tabs[0].getContentElement()).text()).toBe('Content 1');
102+
const contentSelector = await tabs[0].getSelectorForContent();
103+
const contentEl = document.querySelector(contentSelector) as HTMLElement;
104+
expect(contentEl.innerText.trim()).toBe('Content 1');
88105
});
89106

90107
it('should be able to get disabled state of tab', async () => {

src/material/tabs/testing/tab-group-harness.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

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

1313
/**
@@ -34,11 +34,9 @@ export class MatTabGroupHarness extends ComponentHarness {
3434
});
3535
}
3636

37-
private _tabs = this.locatorForAll(MatTabHarness);
38-
3937
/** Gets all tabs of the tab group. */
40-
async getTabs(): Promise<MatTabHarness[]> {
41-
return this._tabs();
38+
async getTabs(filter: TabHarnessFilters = {}): Promise<MatTabHarness[]> {
39+
return this.locatorForAll(MatTabHarness.with(filter))();
4240
}
4341

4442
/** Gets the selected tab of the tab group. */
@@ -52,4 +50,13 @@ export class MatTabGroupHarness extends ComponentHarness {
5250
}
5351
throw new Error('No selected tab could be found.');
5452
}
53+
54+
/** Selects a tab in this tab group. */
55+
async selectTab(filter: TabHarnessFilters = {}): Promise<void> {
56+
const tabs = await this.getTabs(filter);
57+
if (!tabs.length) {
58+
throw Error(`Cannot find mat-tab matching ${JSON.stringify(filter)}`);
59+
}
60+
await tabs[0].select();
61+
}
5562
}

src/material/tabs/testing/tab-harness-filters.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
*/
88
import {BaseHarnessFilters} from '@angular/cdk/testing';
99

10-
export interface TabHarnessFilters extends BaseHarnessFilters {}
10+
export interface TabHarnessFilters extends BaseHarnessFilters {
11+
label?: string | RegExp;
12+
}
1113

1214
export interface TabGroupHarnessFilters extends BaseHarnessFilters {
1315
selectedTabLabel?: string | RegExp;

src/material/tabs/testing/tab-harness.ts

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ export class MatTabHarness extends ComponentHarness {
2020
* Gets a `HarnessPredicate` that can be used to search for a tab with specific attributes.
2121
*/
2222
static with(options: TabHarnessFilters = {}): HarnessPredicate<MatTabHarness> {
23-
return new HarnessPredicate(MatTabHarness, options);
23+
return new HarnessPredicate(MatTabHarness, options)
24+
.addOption('label', options.label,
25+
(harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
2426
}
2527

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

43-
/**
44-
* Gets the content element of the given tab. Note that the element will be empty
45-
* until the tab is selected. This is an implementation detail of the tab-group
46-
* in order to avoid rendering of non-active tabs.
47-
*/
48-
async getContentElement(): Promise<TestElement> {
49-
return this._rootLocatorFactory.locatorFor(`#${await this._getContentId()}`)();
50-
}
51-
5245
/** Whether the tab is selected. */
5346
async isSelected(): Promise<boolean> {
5447
const hostEl = await this.host();
@@ -69,10 +62,10 @@ export class MatTabHarness extends ComponentHarness {
6962
await (await this.host()).click();
7063
}
7164

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

0 commit comments

Comments
 (0)