Skip to content

Commit 63653bb

Browse files
committed
feat(table): add test harness
Adds a test harness for `MatTable`, as well as the related row and cell directives.
1 parent 527f1b5 commit 63653bb

File tree

12 files changed

+673
-0
lines changed

12 files changed

+673
-0
lines changed

src/material/config.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ entryPoints = [
4949
"sort/testing",
5050
"stepper",
5151
"table",
52+
"table/testing",
5253
"tabs",
5354
"tabs/testing",
5455
"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: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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 {CellHarnessFilters} from './table-harness-filters';
11+
12+
/** Harness for interacting with a standard Angular Material table cell. */
13+
export class MatCellHarness extends ComponentHarness {
14+
static hostSelector = '.mat-cell';
15+
16+
/**
17+
* Gets a `HarnessPredicate` that can be used to search for a cell with specific attributes.
18+
*/
19+
static with(options: CellHarnessFilters = {}): HarnessPredicate<MatCellHarness> {
20+
return new HarnessPredicate(MatCellHarness, options)
21+
.addOption('text', options.text,
22+
(harness, text) => HarnessPredicate.stringMatches(harness.getText(), text));
23+
}
24+
25+
/** Gets a promise for the cell's text. */
26+
async getText(): Promise<string> {
27+
return (await this.host()).text();
28+
}
29+
30+
/** Gets the name of the column. */
31+
async getColumnName(): Promise<string> {
32+
const host = await this.host();
33+
const classAttribute = await host.getAttribute('class');
34+
35+
if (classAttribute) {
36+
const prefix = 'mat-column-';
37+
const name = classAttribute.split(' ').map(c => c.trim()).find(c => c.startsWith(prefix));
38+
39+
if (name) {
40+
return name.split(prefix)[1];
41+
}
42+
}
43+
44+
throw Error('Could not determine column name of cell.');
45+
}
46+
}
47+
48+
/** Harness for interacting with a standard Angular Material table header cell. */
49+
export class MatHeaderCellHarness extends MatCellHarness {
50+
static hostSelector = '.mat-header-cell';
51+
52+
/**
53+
* Gets a `HarnessPredicate` that can be used to search for a header cell with specific attributes
54+
*/
55+
static with(options: CellHarnessFilters = {}): HarnessPredicate<MatHeaderCellHarness> {
56+
return new HarnessPredicate(MatHeaderCellHarness, options)
57+
.addOption('text', options.text,
58+
(harness, text) => HarnessPredicate.stringMatches(harness.getText(), text));
59+
}
60+
}
61+
62+
/** Harness for interacting with a standard Angular Material table footer cell. */
63+
export class MatFooterCellHarness extends MatCellHarness {
64+
static hostSelector = '.mat-footer-cell';
65+
66+
/**
67+
* Gets a `HarnessPredicate` that can be used to search for a footer cell with specific attributes
68+
*/
69+
static with(options: CellHarnessFilters = {}): HarnessPredicate<MatFooterCellHarness> {
70+
return new HarnessPredicate(MatFooterCellHarness, options)
71+
.addOption('text', options.text,
72+
(harness, text) => HarnessPredicate.stringMatches(harness.getText(), text));
73+
}
74+
}

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

0 commit comments

Comments
 (0)