Skip to content

Commit 9e97a34

Browse files
authored
feat(toolbar/testing): Add a test harness for MatToolbar (#19976)
* toolbar harness base * add get rows as text * make getRows and getText private * add public api guard * refactor getRowsAsText * use MatToolbarSection instead of literal
1 parent dbbe2f2 commit 9e97a34

File tree

10 files changed

+299
-0
lines changed

10 files changed

+299
-0
lines changed

src/material/config.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ entryPoints = [
5858
"tabs",
5959
"tabs/testing",
6060
"toolbar",
61+
"toolbar/testing",
6162
"tooltip",
6263
"tooltip/testing",
6364
"tree",
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
load("//src/e2e-app:test_suite.bzl", "e2e_test_suite")
2+
load("//tools:defaults.bzl", "ng_e2e_test_library", "ng_test_library", "ng_web_test_suite", "ts_library")
3+
4+
package(default_visibility = ["//visibility:public"])
5+
6+
ts_library(
7+
name = "testing",
8+
srcs = glob(
9+
["**/*.ts"],
10+
exclude = ["**/*.spec.ts"],
11+
),
12+
module_name = "@angular/material/toolbar/testing",
13+
deps = [
14+
"//src/cdk/testing",
15+
],
16+
)
17+
18+
filegroup(
19+
name = "source-files",
20+
srcs = glob(["**/*.ts"]),
21+
)
22+
23+
ng_test_library(
24+
name = "harness_tests_lib",
25+
srcs = ["shared.spec.ts"],
26+
deps = [
27+
":testing",
28+
"//src/cdk/testing",
29+
"//src/cdk/testing/testbed",
30+
"//src/material/toolbar",
31+
"@npm//@angular/platform-browser",
32+
],
33+
)
34+
35+
ng_test_library(
36+
name = "unit_tests_lib",
37+
srcs = glob(
38+
["**/*.spec.ts"],
39+
exclude = [
40+
"**/*.e2e.spec.ts",
41+
"shared.spec.ts",
42+
],
43+
),
44+
deps = [
45+
":harness_tests_lib",
46+
":testing",
47+
"//src/material/toolbar",
48+
],
49+
)
50+
51+
ng_web_test_suite(
52+
name = "unit_tests",
53+
deps = [":unit_tests_lib"],
54+
)
55+
56+
ng_e2e_test_library(
57+
name = "e2e_test_sources",
58+
srcs = glob(["**/*.e2e.spec.ts"]),
59+
deps = [
60+
":testing",
61+
"//src/cdk/testing",
62+
"//src/cdk/testing/private/e2e",
63+
"//src/cdk/testing/protractor",
64+
],
65+
)
66+
67+
e2e_test_suite(
68+
name = "e2e_tests",
69+
deps = [
70+
":e2e_test_sources",
71+
"//src/cdk/testing/private/e2e",
72+
],
73+
)

src/material/toolbar/testing/index.ts

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 './toolbar-harness';
10+
export * from './toolbar-harness-filters';
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import {Component} from '@angular/core';
2+
import {ComponentHarness, HarnessLoader} from '@angular/cdk/testing';
3+
import {MatToolbarModule} from '@angular/material/toolbar';
4+
import {
5+
MatToolbarHarness,
6+
MatToolbarSection
7+
} from '@angular/material/toolbar/testing';
8+
import {ComponentFixture, TestBed} from '@angular/core/testing';
9+
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
10+
11+
/** Shared tests to run on both the original and MDC-based toolbars. */
12+
export function runHarnessTests(
13+
toolbarModule: typeof MatToolbarModule, toolbarHarness: typeof MatToolbarHarness) {
14+
let fixture: ComponentFixture<ToolbarHarnessTest>;
15+
let loader: HarnessLoader;
16+
17+
beforeEach(async () => {
18+
await TestBed.configureTestingModule({
19+
imports: [toolbarModule],
20+
declarations: [ToolbarHarnessTest],
21+
}).compileComponents();
22+
23+
fixture = TestBed.createComponent(ToolbarHarnessTest);
24+
fixture.detectChanges();
25+
loader = TestbedHarnessEnvironment.loader(fixture);
26+
});
27+
28+
it('should find all toolbars', async () => {
29+
const toolbars = await loader.getAllHarnesses(toolbarHarness);
30+
31+
expect(toolbars.length).toBe(2);
32+
});
33+
34+
it('should find toolbar with text', async () => {
35+
const toolbars = await loader.getAllHarnesses(toolbarHarness.with({text: 'My App'}));
36+
37+
expect(toolbars.length).toBe(1);
38+
expect(await toolbars[0].hasMultipleRows()).toBeFalse();
39+
});
40+
41+
it('should find toolbar with regex', async () => {
42+
const toolbars = await loader.getAllHarnesses(toolbarHarness.with({text: /Row/}));
43+
44+
expect(toolbars.length).toBe(1);
45+
expect(await toolbars[0].hasMultipleRows()).toBeTrue();
46+
});
47+
48+
it('should get toolbar text', async () => {
49+
const toolbars = await loader.getAllHarnesses(toolbarHarness);
50+
51+
expect(await toolbars[0].getRowsAsText()).toEqual(['My App']);
52+
expect(await toolbars[1].getRowsAsText()).toEqual([
53+
'Row 1',
54+
'Row 2 Button 1 Button 2'
55+
]);
56+
});
57+
58+
it('should get harness loaders for toolbar row', async () => {
59+
const toolbar = await loader.getHarness(toolbarHarness.with({text: /Button/}));
60+
const rowLoaders = await toolbar.getAllChildLoaders(MatToolbarSection.ROW);
61+
const row1 = rowLoaders[0] as HarnessLoader;
62+
const row1Subcomponents = await row1.getAllHarnesses(DummyHarness);
63+
const row2 = rowLoaders[1] as HarnessLoader;
64+
const row2Subcomponents = await row2.getAllHarnesses(DummyHarness);
65+
66+
expect(row1Subcomponents.length).toBe(1);
67+
expect(row2Subcomponents.length).toBe(3);
68+
});
69+
}
70+
71+
@Component({
72+
template: `
73+
<mat-toolbar><span>My App</span></mat-toolbar>
74+
<mat-toolbar>
75+
<mat-toolbar-row><span>Row 1</span></mat-toolbar-row>
76+
<mat-toolbar-row><span>Row 2</span>
77+
<button mat-button>
78+
Button 1
79+
</button>
80+
<button mat-button>
81+
Button 2
82+
</button>
83+
</mat-toolbar-row>
84+
</mat-toolbar>
85+
`
86+
})
87+
class ToolbarHarnessTest {
88+
}
89+
90+
export class DummyHarness extends ComponentHarness {
91+
static hostSelector = 'span, button';
92+
}
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 `MatToolbarHarness` instances. */
12+
export interface ToolbarHarnessFilters extends BaseHarnessFilters {
13+
/** Only find instances whose text matches the given value. */
14+
text?: string | RegExp;
15+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import {HarnessLoader} from '@angular/cdk/testing';
2+
import {browser} from 'protractor';
3+
import {ProtractorHarnessEnvironment} from '@angular/cdk/testing/protractor';
4+
import {MatToolbarHarness} from '@angular/material/toolbar/testing';
5+
6+
describe('toolbar harness', () => {
7+
let loader: HarnessLoader;
8+
9+
beforeEach(async () => await browser.get('/toolbar'));
10+
11+
beforeEach(() => {
12+
loader = ProtractorHarnessEnvironment.loader();
13+
});
14+
15+
it('should get toolbar text', async () => {
16+
const toolbar = await loader.getHarness(MatToolbarHarness);
17+
18+
expect(await toolbar.getRowsAsText())
19+
.toEqual(['Custom Toolbar', 'Second Line\nverified_user', 'Third Line\nfavorite\ndelete']);
20+
});
21+
22+
it('should have multiple rows', async () => {
23+
const toolbar = await loader.getHarness(MatToolbarHarness);
24+
25+
expect(await toolbar.hasMultipleRows()).toBe(true);
26+
});
27+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import {runHarnessTests} from '@angular/material/toolbar/testing/shared.spec';
2+
import {MatToolbarModule} from '@angular/material/toolbar';
3+
import {MatToolbarHarness} from '@angular/material/toolbar/testing';
4+
5+
describe('Non-MDC-based MatToolbarHarness', () => {
6+
runHarnessTests(MatToolbarModule, MatToolbarHarness);
7+
});
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
10+
import {ContentContainerComponentHarness, HarnessPredicate} from '@angular/cdk/testing';
11+
import {ToolbarHarnessFilters} from './toolbar-harness-filters';
12+
13+
/** Selectors for different sections of the mat-toolbar that contain user content. */
14+
export const enum MatToolbarSection {
15+
ROW = '.mat-toolbar-row'
16+
}
17+
18+
/** Harness for interacting with a standard mat-toolbar in tests. */
19+
export class MatToolbarHarness extends ContentContainerComponentHarness<MatToolbarSection> {
20+
static hostSelector = 'mat-toolbar';
21+
22+
private _getRows = this.locatorForAll(MatToolbarSection.ROW);
23+
24+
/**
25+
* Gets a `HarnessPredicate` that can be used to search for a `MatToolbarHarness` that meets
26+
* certain criteria.
27+
* @param options Options for filtering which card instances are considered a match.
28+
* @return a `HarnessPredicate` configured with the given options.
29+
*/
30+
static with(options: ToolbarHarnessFilters = {}): HarnessPredicate<MatToolbarHarness> {
31+
return new HarnessPredicate(MatToolbarHarness, options)
32+
.addOption('text', options.text,
33+
(harness, text) => HarnessPredicate.stringMatches(harness._getText(), text));
34+
}
35+
36+
/** Whether the toolbar has multiple rows. */
37+
async hasMultipleRows(): Promise<boolean> {
38+
return (await this.host()).hasClass('mat-toolbar-multiple-rows');
39+
}
40+
41+
/** Gets all of the toolbar's content as text. */
42+
private async _getText(): Promise<string> {
43+
return (await this.host()).text();
44+
}
45+
46+
/** Gets the text of each row in the toolbar. */
47+
async getRowsAsText(): Promise<string[]> {
48+
const rows = await this._getRows();
49+
return Promise.all(rows.length ? rows.map(r => r.text()) : [this._getText()]);
50+
}
51+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export declare class MatToolbarHarness extends ContentContainerComponentHarness<MatToolbarSection> {
2+
getRowsAsText(): Promise<string[]>;
3+
hasMultipleRows(): Promise<boolean>;
4+
static hostSelector: string;
5+
static with(options?: ToolbarHarnessFilters): HarnessPredicate<MatToolbarHarness>;
6+
}
7+
8+
export declare const enum MatToolbarSection {
9+
ROW = ".mat-toolbar-row"
10+
}
11+
12+
export interface ToolbarHarnessFilters extends BaseHarnessFilters {
13+
text?: string | RegExp;
14+
}

0 commit comments

Comments
 (0)