Skip to content

Commit f2475cd

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 0632026 commit f2475cd

File tree

5 files changed

+67
-56
lines changed

5 files changed

+67
-56
lines changed

src/material/table/testing/cell-harness.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing';
9+
import {
10+
ComponentHarness,
11+
HarnessPredicate,
12+
ComponentHarnessConstructor,
13+
} from '@angular/cdk/testing';
1014
import {CellHarnessFilters} from './table-harness-filters';
1115

1216
/** Harness for interacting with a standard Angular Material table cell. */
@@ -17,9 +21,7 @@ export class MatCellHarness extends ComponentHarness {
1721
* Gets a `HarnessPredicate` that can be used to search for a cell with specific attributes.
1822
*/
1923
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));
24+
return getCellPredicate(MatCellHarness, options);
2325
}
2426

2527
/** Gets a promise for the cell's text. */
@@ -53,9 +55,7 @@ export class MatHeaderCellHarness extends MatCellHarness {
5355
* Gets a `HarnessPredicate` that can be used to search for a header cell with specific attributes
5456
*/
5557
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));
58+
return getCellPredicate(MatHeaderCellHarness, options);
5959
}
6060
}
6161

@@ -67,8 +67,15 @@ export class MatFooterCellHarness extends MatCellHarness {
6767
* Gets a `HarnessPredicate` that can be used to search for a footer cell with specific attributes
6868
*/
6969
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));
70+
return getCellPredicate(MatFooterCellHarness, options);
7371
}
7472
}
73+
74+
75+
function getCellPredicate<T extends MatCellHarness>(
76+
type: ComponentHarnessConstructor<T>,
77+
options: CellHarnessFilters): HarnessPredicate<T> {
78+
return new HarnessPredicate(type, options)
79+
.addOption('text', options.text,
80+
(harness, text) => HarnessPredicate.stringMatches(harness.getText(), text));
81+
}

src/material/table/testing/row-harness.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing';
1010
import {RowHarnessFilters, CellHarnessFilters} from './table-harness-filters';
1111
import {MatCellHarness, MatHeaderCellHarness, MatFooterCellHarness} from './cell-harness';
1212

13-
/** Data extracted from the cells in a table row. */
14-
export type MatRowHarnessData = {
13+
/** Text extracted from the cells in a table row. */
14+
export type MatRowHarnessText = {
1515
columnName: string;
1616
text: string;
1717
}[];
@@ -32,8 +32,8 @@ export class MatRowHarness extends ComponentHarness {
3232
return this.locatorForAll(MatCellHarness.with(filter))();
3333
}
3434

35-
/** Gets the data of the cells in the footer row. */
36-
async getData(filter: CellHarnessFilters = {}): Promise<MatRowHarnessData> {
35+
/** Gets the text of the cells in the footer row. */
36+
async getText(filter: CellHarnessFilters = {}): Promise<MatRowHarnessText> {
3737
return getCellData(await this.getCells(filter));
3838
}
3939
}
@@ -54,8 +54,8 @@ export class MatHeaderRowHarness extends ComponentHarness {
5454
return this.locatorForAll(MatHeaderCellHarness.with(filter))();
5555
}
5656

57-
/** Gets the data of the cells in the footer row. */
58-
async getData(filter: CellHarnessFilters = {}): Promise<MatRowHarnessData> {
57+
/** Gets the text of the cells in the footer row. */
58+
async getText(filter: CellHarnessFilters = {}): Promise<MatRowHarnessText> {
5959
return getCellData(await this.getCells(filter));
6060
}
6161
}
@@ -77,16 +77,16 @@ export class MatFooterRowHarness extends ComponentHarness {
7777
return this.locatorForAll(MatFooterCellHarness.with(filter))();
7878
}
7979

80-
/** Gets the data of the cells in the footer row. */
81-
async getData(filter: CellHarnessFilters = {}): Promise<MatRowHarnessData> {
80+
/** Gets the text of the cells in the footer row. */
81+
async getText(filter: CellHarnessFilters = {}): Promise<MatRowHarnessText> {
8282
return getCellData(await this.getCells(filter));
8383
}
8484
}
8585

8686
/** 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-
})));
87+
async function getCellData(cells: MatCellHarness[]): Promise<MatRowHarnessText> {
88+
return Promise.all(cells.map(async cell => {
89+
const [text, columnName] = await Promise.all([cell.getText(), cell.getColumnName()]);
90+
return {text, columnName};
91+
}));
9292
}

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ export function runHarnessTests(
8787
expect(cellTexts).toEqual(['Hydrogen', 'H']);
8888
});
8989

90-
it('should be able to get the table data organized by columns', async () => {
90+
it('should be able to get the table text organized by columns', async () => {
9191
const table = await loader.getHarness(tableHarness);
92-
const data = await table.getColumnsData();
92+
const text = await table.getColumnsText();
9393

94-
expect(data).toEqual({
94+
expect(text).toEqual({
9595
position: {
9696
headerText: 'No.',
9797
footerText: 'Number of the element',
@@ -121,11 +121,11 @@ export function runHarnessTests(
121121
});
122122
});
123123

124-
it('should be able to get the table data organized by rows', async () => {
124+
it('should be able to get the table text organized by rows', async () => {
125125
const table = await loader.getHarness(tableHarness);
126-
const data = await table.getRowsData();
126+
const text = await table.getRowsText();
127127

128-
expect(data).toEqual([
128+
expect(text).toEqual([
129129
[
130130
{text: '1', columnName: 'position'},
131131
{text: 'Hydrogen', columnName: 'name'},

src/material/table/testing/table-harness.ts

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {TableHarnessFilters, RowHarnessFilters} from './table-harness-filters';
1111
import {MatRowHarness, MatHeaderRowHarness, MatFooterRowHarness} from './row-harness';
1212

1313
/** Data extracted from a table organized by columns. */
14-
export interface MatTableHarnessColumnsData {
14+
export interface MatTableHarnessColumnsText {
1515
[columnName: string]: {
1616
text: string[];
1717
headerText: string;
@@ -20,7 +20,7 @@ export interface MatTableHarnessColumnsData {
2020
}
2121

2222
/** Data extracted from a table organized by rows. */
23-
export type MatTableHarnessRowsData = {
23+
export type MatTableHarnessRowsText = {
2424
columnName: string;
2525
text: string;
2626
}[][];
@@ -54,41 +54,45 @@ export class MatTableHarness extends ComponentHarness {
5454
return this.locatorForAll(MatFooterRowHarness.with(filter))();
5555
}
5656

57-
/** Gets the data inside the entire table organized by rows. */
58-
async getRowsData(): Promise<MatTableHarnessRowsData> {
57+
/** Gets the text inside the entire table organized by rows. */
58+
async getRowsText(): Promise<MatTableHarnessRowsText> {
5959
const rows = await this.getRows();
60-
return Promise.all(rows.map(row => row.getData()));
60+
return Promise.all(rows.map(row => row.getText()));
6161
}
6262

63-
/** Gets the data inside the entire table organized by columns. */
64-
async getColumnsData(): Promise<MatTableHarnessColumnsData> {
65-
// Tables can have multiple header rows, but we consider the first one as the "main" row.
66-
const headerRow = (await this.getHeaderRows())[0];
67-
const footerRow = (await this.getFooterRows())[0];
68-
const dataRows = await this.getRows();
63+
/** Gets the text inside the entire table organized by columns. */
64+
async getColumnsText(): Promise<MatTableHarnessColumnsText> {
65+
const [headerRow, footerRow, dataRows] = await Promise.all([
66+
// Tables can have multiple header rows, but we consider the first one as the "main" row.
67+
this.getHeaderRows().then(rows => rows[0]),
68+
this.getFooterRows().then(rows => rows[0]),
69+
this.getRows()
70+
]);
6971

70-
const headerData = headerRow ? await headerRow.getData() : [];
71-
const footerData = footerRow ? await footerRow.getData() : [];
72-
const rowsData = await Promise.all(dataRows.map(row => row.getData()));
73-
const data: MatTableHarnessColumnsData = {};
72+
const text: MatTableHarnessColumnsText = {};
73+
const [headerData, footerData, rowsData] = await Promise.all([
74+
headerRow ? headerRow.getText() : [],
75+
footerRow ? footerRow.getText() : [],
76+
Promise.all(dataRows.map(row => row.getText())),
77+
]);
7478

7579
rowsData.forEach(cells => {
7680
cells.forEach(cell => {
77-
if (!data[cell.columnName]) {
81+
if (!text[cell.columnName]) {
7882
const headerCell = headerData.find(header => header.columnName === cell.columnName);
7983
const footerCell = footerData.find(footer => footer.columnName === cell.columnName);
8084

81-
data[cell.columnName] = {
85+
text[cell.columnName] = {
8286
headerText: headerCell ? headerCell.text : '',
8387
footerText: footerCell ? footerCell.text : '',
8488
text: []
8589
};
8690
}
8791

88-
data[cell.columnName].text.push(cell.text);
92+
text[cell.columnName].text.push(cell.text);
8993
});
9094
});
9195

92-
return data;
96+
return text;
9397
}
9498
}

tools/public_api_guard/material/table/testing.d.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export declare class MatFooterCellHarness extends MatCellHarness {
1616

1717
export declare class MatFooterRowHarness extends ComponentHarness {
1818
getCells(filter?: CellHarnessFilters): Promise<MatFooterCellHarness[]>;
19-
getData(filter?: CellHarnessFilters): Promise<MatRowHarnessData>;
19+
getText(filter?: CellHarnessFilters): Promise<MatRowHarnessText>;
2020
static hostSelector: string;
2121
static with(options?: RowHarnessFilters): HarnessPredicate<MatFooterRowHarness>;
2222
}
@@ -28,42 +28,42 @@ export declare class MatHeaderCellHarness extends MatCellHarness {
2828

2929
export declare class MatHeaderRowHarness extends ComponentHarness {
3030
getCells(filter?: CellHarnessFilters): Promise<MatHeaderCellHarness[]>;
31-
getData(filter?: CellHarnessFilters): Promise<MatRowHarnessData>;
31+
getText(filter?: CellHarnessFilters): Promise<MatRowHarnessText>;
3232
static hostSelector: string;
3333
static with(options?: RowHarnessFilters): HarnessPredicate<MatHeaderRowHarness>;
3434
}
3535

3636
export declare class MatRowHarness extends ComponentHarness {
3737
getCells(filter?: CellHarnessFilters): Promise<MatCellHarness[]>;
38-
getData(filter?: CellHarnessFilters): Promise<MatRowHarnessData>;
38+
getText(filter?: CellHarnessFilters): Promise<MatRowHarnessText>;
3939
static hostSelector: string;
4040
static with(options?: RowHarnessFilters): HarnessPredicate<MatRowHarness>;
4141
}
4242

43-
export declare type MatRowHarnessData = {
43+
export declare type MatRowHarnessText = {
4444
columnName: string;
4545
text: string;
4646
}[];
4747

4848
export declare class MatTableHarness extends ComponentHarness {
49-
getColumnsData(): Promise<MatTableHarnessColumnsData>;
49+
getColumnsText(): Promise<MatTableHarnessColumnsText>;
5050
getFooterRows(filter?: RowHarnessFilters): Promise<MatFooterRowHarness[]>;
5151
getHeaderRows(filter?: RowHarnessFilters): Promise<MatHeaderRowHarness[]>;
5252
getRows(filter?: RowHarnessFilters): Promise<MatRowHarness[]>;
53-
getRowsData(): Promise<MatTableHarnessRowsData>;
53+
getRowsText(): Promise<MatTableHarnessRowsText>;
5454
static hostSelector: string;
5555
static with(options?: TableHarnessFilters): HarnessPredicate<MatTableHarness>;
5656
}
5757

58-
export interface MatTableHarnessColumnsData {
58+
export interface MatTableHarnessColumnsText {
5959
[columnName: string]: {
6060
text: string[];
6161
headerText: string;
6262
footerText: string;
6363
};
6464
}
6565

66-
export declare type MatTableHarnessRowsData = {
66+
export declare type MatTableHarnessRowsText = {
6767
columnName: string;
6868
text: string;
6969
}[][];

0 commit comments

Comments
 (0)