Skip to content

Commit a30094b

Browse files
crisbetoandrewseguin
authored andcommitted
feat(table): add test harness (#17799)
* feat(table): add test harness Adds a test harness for `MatTable`, as well as the related row and cell directives. * feat(table): add test harness Adds a test harness for `MatTable`, as well as the related row and cell directives.
1 parent abe9e9c commit a30094b

File tree

12 files changed

+655
-0
lines changed

12 files changed

+655
-0
lines changed

src/material/config.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ entryPoints = [
5151
"sort/testing",
5252
"stepper",
5353
"table",
54+
"table/testing",
5455
"tabs",
5556
"tabs/testing",
5657
"toolbar",
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
load("//tools:defaults.bzl", "ng_test_library", "ng_web_test_suite", "ts_library")
4+
5+
ts_library(
6+
name = "testing",
7+
srcs = glob(
8+
["**/*.ts"],
9+
exclude = ["**/*.spec.ts"],
10+
),
11+
module_name = "@angular/material/table/testing",
12+
deps = [
13+
"//src/cdk/testing",
14+
],
15+
)
16+
17+
filegroup(
18+
name = "source-files",
19+
srcs = glob(["**/*.ts"]),
20+
)
21+
22+
ng_test_library(
23+
name = "harness_tests_lib",
24+
srcs = ["shared.spec.ts"],
25+
deps = [
26+
":testing",
27+
"//src/cdk/testing",
28+
"//src/cdk/testing/testbed",
29+
"//src/material/table",
30+
],
31+
)
32+
33+
ng_test_library(
34+
name = "unit_tests_lib",
35+
srcs = glob(
36+
["**/*.spec.ts"],
37+
exclude = ["shared.spec.ts"],
38+
),
39+
deps = [
40+
":harness_tests_lib",
41+
":testing",
42+
"//src/material/table",
43+
],
44+
)
45+
46+
ng_web_test_suite(
47+
name = "unit_tests",
48+
deps = [":unit_tests_lib"],
49+
)
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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 {
10+
ComponentHarness,
11+
HarnessPredicate,
12+
ComponentHarnessConstructor,
13+
} from '@angular/cdk/testing';
14+
import {CellHarnessFilters} from './table-harness-filters';
15+
16+
/** Harness for interacting with a standard Angular Material table cell. */
17+
export class MatCellHarness extends ComponentHarness {
18+
/** The selector for the host element of a `MatCellHarness` instance. */
19+
static hostSelector = '.mat-cell';
20+
21+
/**
22+
* Gets a `HarnessPredicate` that can be used to search for a table cell with specific attributes.
23+
* @param options Options for narrowing the search
24+
* @return a `HarnessPredicate` configured with the given options.
25+
*/
26+
static with(options: CellHarnessFilters = {}): HarnessPredicate<MatCellHarness> {
27+
return getCellPredicate(MatCellHarness, options);
28+
}
29+
30+
/** Gets the cell's text. */
31+
async getText(): Promise<string> {
32+
return (await this.host()).text();
33+
}
34+
35+
/** Gets the name of the column that the cell belongs to. */
36+
async getColumnName(): Promise<string> {
37+
const host = await this.host();
38+
const classAttribute = await host.getAttribute('class');
39+
40+
if (classAttribute) {
41+
const prefix = 'mat-column-';
42+
const name = classAttribute.split(' ').map(c => c.trim()).find(c => c.startsWith(prefix));
43+
44+
if (name) {
45+
return name.split(prefix)[1];
46+
}
47+
}
48+
49+
throw Error('Could not determine column name of cell.');
50+
}
51+
}
52+
53+
/** Harness for interacting with a standard Angular Material table header cell. */
54+
export class MatHeaderCellHarness extends MatCellHarness {
55+
/** The selector for the host element of a `MatHeaderCellHarness` instance. */
56+
static hostSelector = '.mat-header-cell';
57+
58+
/**
59+
* Gets a `HarnessPredicate` that can be used to search for
60+
* a table header cell with specific attributes.
61+
* @param options Options for narrowing the search
62+
* @return a `HarnessPredicate` configured with the given options.
63+
*/
64+
static with(options: CellHarnessFilters = {}): HarnessPredicate<MatHeaderCellHarness> {
65+
return getCellPredicate(MatHeaderCellHarness, options);
66+
}
67+
}
68+
69+
/** Harness for interacting with a standard Angular Material table footer cell. */
70+
export class MatFooterCellHarness extends MatCellHarness {
71+
/** The selector for the host element of a `MatFooterCellHarness` instance. */
72+
static hostSelector = '.mat-footer-cell';
73+
74+
/**
75+
* Gets a `HarnessPredicate` that can be used to search for
76+
* a table footer cell with specific attributes.
77+
* @param options Options for narrowing the search
78+
* @return a `HarnessPredicate` configured with the given options.
79+
*/
80+
static with(options: CellHarnessFilters = {}): HarnessPredicate<MatFooterCellHarness> {
81+
return getCellPredicate(MatFooterCellHarness, options);
82+
}
83+
}
84+
85+
86+
function getCellPredicate<T extends MatCellHarness>(
87+
type: ComponentHarnessConstructor<T>,
88+
options: CellHarnessFilters): HarnessPredicate<T> {
89+
return new HarnessPredicate(type, options)
90+
.addOption('text', options.text,
91+
(harness, text) => HarnessPredicate.stringMatches(harness.getText(), text));
92+
}

src/material/table/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: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
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 './table-harness';
10+
export * from './row-harness';
11+
export * from './cell-harness';
12+
export * from './table-harness-filters';
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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 {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing';
10+
import {RowHarnessFilters, CellHarnessFilters} from './table-harness-filters';
11+
import {MatCellHarness, MatHeaderCellHarness, MatFooterCellHarness} from './cell-harness';
12+
13+
/** Harness for interacting with a standard Angular Material table row. */
14+
export class MatRowHarness extends ComponentHarness {
15+
/** The selector for the host element of a `MatRowHarness` instance. */
16+
static hostSelector = '.mat-row';
17+
18+
/**
19+
* Gets a `HarnessPredicate` that can be used to search for a table row with specific attributes.
20+
* @param options Options for narrowing the search
21+
* @return a `HarnessPredicate` configured with the given options.
22+
*/
23+
static with(options: RowHarnessFilters = {}): HarnessPredicate<MatRowHarness> {
24+
return new HarnessPredicate(MatRowHarness, options);
25+
}
26+
27+
/** Gets a list of `MatCellHarness` for all cells in the row. */
28+
async getCells(filter: CellHarnessFilters = {}): Promise<MatCellHarness[]> {
29+
return this.locatorForAll(MatCellHarness.with(filter))();
30+
}
31+
32+
/** Gets the text of the cells in the row. */
33+
async getCellTextByIndex(filter: CellHarnessFilters = {}): Promise<string[]> {
34+
return getCellTextByIndex(this, filter);
35+
}
36+
}
37+
38+
/** Harness for interacting with a standard Angular Material table header row. */
39+
export class MatHeaderRowHarness extends ComponentHarness {
40+
/** The selector for the host element of a `MatHeaderRowHarness` instance. */
41+
static hostSelector = '.mat-header-row';
42+
43+
/**
44+
* Gets a `HarnessPredicate` that can be used to search for
45+
* a table header row with specific attributes.
46+
* @param options Options for narrowing the search
47+
* @return a `HarnessPredicate` configured with the given options.
48+
*/
49+
static with(options: RowHarnessFilters = {}): HarnessPredicate<MatHeaderRowHarness> {
50+
return new HarnessPredicate(MatHeaderRowHarness, options);
51+
}
52+
53+
/** Gets a list of `MatHeaderCellHarness` for all cells in the row. */
54+
async getCells(filter: CellHarnessFilters = {}): Promise<MatHeaderCellHarness[]> {
55+
return this.locatorForAll(MatHeaderCellHarness.with(filter))();
56+
}
57+
58+
/** Gets the text of the cells in the header row. */
59+
async getCellTextByIndex(filter: CellHarnessFilters = {}): Promise<string[]> {
60+
return getCellTextByIndex(this, filter);
61+
}
62+
}
63+
64+
65+
/** Harness for interacting with a standard Angular Material table footer row. */
66+
export class MatFooterRowHarness extends ComponentHarness {
67+
/** The selector for the host element of a `MatFooterRowHarness` instance. */
68+
static hostSelector = '.mat-footer-row';
69+
70+
/**
71+
* Gets a `HarnessPredicate` that can be used to search for
72+
* a table footer row cell with specific attributes.
73+
* @param options Options for narrowing the search
74+
* @return a `HarnessPredicate` configured with the given options.
75+
*/
76+
static with(options: RowHarnessFilters = {}): HarnessPredicate<MatFooterRowHarness> {
77+
return new HarnessPredicate(MatFooterRowHarness, options);
78+
}
79+
80+
/** Gets a list of `MatFooterCellHarness` for all cells in the row. */
81+
async getCells(filter: CellHarnessFilters = {}): Promise<MatFooterCellHarness[]> {
82+
return this.locatorForAll(MatFooterCellHarness.with(filter))();
83+
}
84+
85+
/** Gets the text of the cells in the footer row. */
86+
async getCellTextByIndex(filter: CellHarnessFilters = {}): Promise<string[]> {
87+
return getCellTextByIndex(this, filter);
88+
}
89+
}
90+
91+
async function getCellTextByIndex(harness: {
92+
getCells: (filter?: CellHarnessFilters) => Promise<MatCellHarness[]>
93+
}, filter: CellHarnessFilters): Promise<string[]> {
94+
const cells = await harness.getCells(filter);
95+
return Promise.all(cells.map(cell => cell.getText()));
96+
}

0 commit comments

Comments
 (0)