diff --git a/src/material/config.bzl b/src/material/config.bzl index d266e25bf9a7..600eed672c95 100644 --- a/src/material/config.bzl +++ b/src/material/config.bzl @@ -49,6 +49,7 @@ entryPoints = [ "sort/testing", "stepper", "table", + "table/testing", "tabs", "tabs/testing", "toolbar", diff --git a/src/material/table/testing/BUILD.bazel b/src/material/table/testing/BUILD.bazel new file mode 100644 index 000000000000..07d382859971 --- /dev/null +++ b/src/material/table/testing/BUILD.bazel @@ -0,0 +1,49 @@ +package(default_visibility = ["//visibility:public"]) + +load("//tools:defaults.bzl", "ng_test_library", "ng_web_test_suite", "ts_library") + +ts_library( + name = "testing", + srcs = glob( + ["**/*.ts"], + exclude = ["**/*.spec.ts"], + ), + module_name = "@angular/material/table/testing", + deps = [ + "//src/cdk/testing", + ], +) + +filegroup( + name = "source-files", + srcs = glob(["**/*.ts"]), +) + +ng_test_library( + name = "harness_tests_lib", + srcs = ["shared.spec.ts"], + deps = [ + ":testing", + "//src/cdk/testing", + "//src/cdk/testing/testbed", + "//src/material/table", + ], +) + +ng_test_library( + name = "unit_tests_lib", + srcs = glob( + ["**/*.spec.ts"], + exclude = ["shared.spec.ts"], + ), + deps = [ + ":harness_tests_lib", + ":testing", + "//src/material/table", + ], +) + +ng_web_test_suite( + name = "unit_tests", + deps = [":unit_tests_lib"], +) diff --git a/src/material/table/testing/cell-harness.ts b/src/material/table/testing/cell-harness.ts new file mode 100644 index 000000000000..a446eadf0c1e --- /dev/null +++ b/src/material/table/testing/cell-harness.ts @@ -0,0 +1,92 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import { + ComponentHarness, + HarnessPredicate, + ComponentHarnessConstructor, +} from '@angular/cdk/testing'; +import {CellHarnessFilters} from './table-harness-filters'; + +/** Harness for interacting with a standard Angular Material table cell. */ +export class MatCellHarness extends ComponentHarness { + /** The selector for the host element of a `MatCellHarness` instance. */ + static hostSelector = '.mat-cell'; + + /** + * Gets a `HarnessPredicate` that can be used to search for a table cell with specific attributes. + * @param options Options for narrowing the search + * @return a `HarnessPredicate` configured with the given options. + */ + static with(options: CellHarnessFilters = {}): HarnessPredicate { + return getCellPredicate(MatCellHarness, options); + } + + /** Gets the cell's text. */ + async getText(): Promise { + return (await this.host()).text(); + } + + /** Gets the name of the column that the cell belongs to. */ + async getColumnName(): Promise { + const host = await this.host(); + const classAttribute = await host.getAttribute('class'); + + if (classAttribute) { + const prefix = 'mat-column-'; + const name = classAttribute.split(' ').map(c => c.trim()).find(c => c.startsWith(prefix)); + + if (name) { + return name.split(prefix)[1]; + } + } + + throw Error('Could not determine column name of cell.'); + } +} + +/** Harness for interacting with a standard Angular Material table header cell. */ +export class MatHeaderCellHarness extends MatCellHarness { + /** The selector for the host element of a `MatHeaderCellHarness` instance. */ + static hostSelector = '.mat-header-cell'; + + /** + * Gets a `HarnessPredicate` that can be used to search for + * a table header cell with specific attributes. + * @param options Options for narrowing the search + * @return a `HarnessPredicate` configured with the given options. + */ + static with(options: CellHarnessFilters = {}): HarnessPredicate { + return getCellPredicate(MatHeaderCellHarness, options); + } +} + +/** Harness for interacting with a standard Angular Material table footer cell. */ +export class MatFooterCellHarness extends MatCellHarness { + /** The selector for the host element of a `MatFooterCellHarness` instance. */ + static hostSelector = '.mat-footer-cell'; + + /** + * Gets a `HarnessPredicate` that can be used to search for + * a table footer cell with specific attributes. + * @param options Options for narrowing the search + * @return a `HarnessPredicate` configured with the given options. + */ + static with(options: CellHarnessFilters = {}): HarnessPredicate { + return getCellPredicate(MatFooterCellHarness, options); + } +} + + +function getCellPredicate( + type: ComponentHarnessConstructor, + options: CellHarnessFilters): HarnessPredicate { + return new HarnessPredicate(type, options) + .addOption('text', options.text, + (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text)); +} diff --git a/src/material/table/testing/index.ts b/src/material/table/testing/index.ts new file mode 100644 index 000000000000..676ca90f1ffa --- /dev/null +++ b/src/material/table/testing/index.ts @@ -0,0 +1,9 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +export * from './public-api'; diff --git a/src/material/table/testing/public-api.ts b/src/material/table/testing/public-api.ts new file mode 100644 index 000000000000..1a5ecd8070f2 --- /dev/null +++ b/src/material/table/testing/public-api.ts @@ -0,0 +1,12 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +export * from './table-harness'; +export * from './row-harness'; +export * from './cell-harness'; +export * from './table-harness-filters'; diff --git a/src/material/table/testing/row-harness.ts b/src/material/table/testing/row-harness.ts new file mode 100644 index 000000000000..88c03f6d1f7f --- /dev/null +++ b/src/material/table/testing/row-harness.ts @@ -0,0 +1,96 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing'; +import {RowHarnessFilters, CellHarnessFilters} from './table-harness-filters'; +import {MatCellHarness, MatHeaderCellHarness, MatFooterCellHarness} from './cell-harness'; + +/** Harness for interacting with a standard Angular Material table row. */ +export class MatRowHarness extends ComponentHarness { + /** The selector for the host element of a `MatRowHarness` instance. */ + static hostSelector = '.mat-row'; + + /** + * Gets a `HarnessPredicate` that can be used to search for a table row with specific attributes. + * @param options Options for narrowing the search + * @return a `HarnessPredicate` configured with the given options. + */ + static with(options: RowHarnessFilters = {}): HarnessPredicate { + return new HarnessPredicate(MatRowHarness, options); + } + + /** Gets a list of `MatCellHarness` for all cells in the row. */ + async getCells(filter: CellHarnessFilters = {}): Promise { + return this.locatorForAll(MatCellHarness.with(filter))(); + } + + /** Gets the text of the cells in the row. */ + async getCellTextByIndex(filter: CellHarnessFilters = {}): Promise { + return getCellTextByIndex(this, filter); + } +} + +/** Harness for interacting with a standard Angular Material table header row. */ +export class MatHeaderRowHarness extends ComponentHarness { + /** The selector for the host element of a `MatHeaderRowHarness` instance. */ + static hostSelector = '.mat-header-row'; + + /** + * Gets a `HarnessPredicate` that can be used to search for + * a table header row with specific attributes. + * @param options Options for narrowing the search + * @return a `HarnessPredicate` configured with the given options. + */ + static with(options: RowHarnessFilters = {}): HarnessPredicate { + return new HarnessPredicate(MatHeaderRowHarness, options); + } + + /** Gets a list of `MatHeaderCellHarness` for all cells in the row. */ + async getCells(filter: CellHarnessFilters = {}): Promise { + return this.locatorForAll(MatHeaderCellHarness.with(filter))(); + } + + /** Gets the text of the cells in the header row. */ + async getCellTextByIndex(filter: CellHarnessFilters = {}): Promise { + return getCellTextByIndex(this, filter); + } +} + + +/** Harness for interacting with a standard Angular Material table footer row. */ +export class MatFooterRowHarness extends ComponentHarness { + /** The selector for the host element of a `MatFooterRowHarness` instance. */ + static hostSelector = '.mat-footer-row'; + + /** + * Gets a `HarnessPredicate` that can be used to search for + * a table footer row cell with specific attributes. + * @param options Options for narrowing the search + * @return a `HarnessPredicate` configured with the given options. + */ + static with(options: RowHarnessFilters = {}): HarnessPredicate { + return new HarnessPredicate(MatFooterRowHarness, options); + } + + /** Gets a list of `MatFooterCellHarness` for all cells in the row. */ + async getCells(filter: CellHarnessFilters = {}): Promise { + return this.locatorForAll(MatFooterCellHarness.with(filter))(); + } + + /** Gets the text of the cells in the footer row. */ + async getCellTextByIndex(filter: CellHarnessFilters = {}): Promise { + return getCellTextByIndex(this, filter); + } +} + +async function getCellTextByIndex(harness: { + getCells: (filter?: CellHarnessFilters) => Promise +}, filter: CellHarnessFilters): Promise { + const cells = await harness.getCells(filter); + return Promise.all(cells.map(cell => cell.getText())); +} diff --git a/src/material/table/testing/shared.spec.ts b/src/material/table/testing/shared.spec.ts new file mode 100644 index 000000000000..8ac81fa76787 --- /dev/null +++ b/src/material/table/testing/shared.spec.ts @@ -0,0 +1,190 @@ +import {HarnessLoader} from '@angular/cdk/testing'; +import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; +import {Component} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatTableModule} from '@angular/material/table'; +import {MatTableHarness} from './table-harness'; + +/** Shared tests to run on both the original and MDC-based table. */ +export function runHarnessTests( + tableModule: typeof MatTableModule, + tableHarness: typeof MatTableHarness) { + let fixture: ComponentFixture; + let loader: HarnessLoader; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [tableModule], + declarations: [TableHarnessTest], + }).compileComponents(); + + fixture = TestBed.createComponent(TableHarnessTest); + fixture.detectChanges(); + loader = TestbedHarnessEnvironment.loader(fixture); + }); + + it('should load harness for a table', async () => { + const tables = await loader.getAllHarnesses(tableHarness); + expect(tables.length).toBe(1); + }); + + it('should get the different kinds of rows in the table', async () => { + const table = await loader.getHarness(tableHarness); + const headerRows = await table.getHeaderRows(); + const footerRows = await table.getFooterRows(); + const rows = await table.getRows(); + expect(headerRows.length).toBe(1); + expect(footerRows.length).toBe(1); + expect(rows.length).toBe(10); + }); + + it('should get cells inside a row', async () => { + const table = await loader.getHarness(tableHarness); + const headerRows = await table.getHeaderRows(); + const footerRows = await table.getFooterRows(); + const rows = await table.getRows(); + const headerCells = (await Promise.all(headerRows.map(row => row.getCells()))) + .map(row => row.length); + const footerCells = (await Promise.all(footerRows.map(row => row.getCells()))) + .map(row => row.length); + const cells = (await Promise.all(rows.map(row => row.getCells()))) + .map(row => row.length); + + expect(headerCells).toEqual([4]); + expect(cells).toEqual([4, 4, 4, 4, 4, 4, 4, 4, 4, 4]); + expect(footerCells).toEqual([4]); + }); + + it('should be able to get the text of a cell', async () => { + const table = await loader.getHarness(tableHarness); + const secondRow = (await table.getRows())[1]; + const cells = await secondRow.getCells(); + const cellTexts = await Promise.all(cells.map(cell => cell.getText())); + expect(cellTexts).toEqual(['2', 'Helium', '4.0026', 'He']); + }); + + it('should be able to get the column name of a cell', async () => { + const table = await loader.getHarness(tableHarness); + const fifthRow = (await table.getRows())[1]; + const cells = await fifthRow.getCells(); + const cellColumnNames = await Promise.all(cells.map(cell => cell.getColumnName())); + expect(cellColumnNames).toEqual(['position', 'name', 'weight', 'symbol']); + }); + + it('should be able to filter cells by text', async () => { + const table = await loader.getHarness(tableHarness); + const firstRow = (await table.getRows())[0]; + const cells = await firstRow.getCells({text: '1.0079'}); + const cellTexts = await Promise.all(cells.map(cell => cell.getText())); + expect(cellTexts).toEqual(['1.0079']); + }); + + it('should be able to filter cells by regex', async () => { + const table = await loader.getHarness(tableHarness); + const firstRow = (await table.getRows())[0]; + const cells = await firstRow.getCells({text: /^H/}); + const cellTexts = await Promise.all(cells.map(cell => cell.getText())); + expect(cellTexts).toEqual(['Hydrogen', 'H']); + }); + + it('should be able to get the table text organized by columns', async () => { + const table = await loader.getHarness(tableHarness); + const text = await table.getCellTextByColumnName(); + + expect(text).toEqual({ + position: { + headerText: ['No.'], + footerText: ['Number of the element'], + text: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] + }, + name: { + headerText: ['Name'], + footerText: ['Name of the element'], + text: [ + 'Hydrogen', 'Helium', 'Lithium', 'Beryllium', 'Boron', + 'Carbon', 'Nitrogen', 'Oxygen', 'Fluorine', 'Neon' + ] + }, + weight: { + headerText: ['Weight'], + footerText: ['Weight of the element'], + text: [ + '1.0079', '4.0026', '6.941', '9.0122', '10.811', + '12.0107', '14.0067', '15.9994', '18.9984', '20.1797' + ] + }, + symbol: { + headerText: ['Symbol'], + footerText: ['Symbol of the element'], + text: ['H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne'] + } + }); + }); + + it('should be able to get the table text organized by rows', async () => { + const table = await loader.getHarness(tableHarness); + const text = await table.getCellTextByIndex(); + + expect(text).toEqual([ + ['1', 'Hydrogen', '1.0079', 'H'], + ['2', 'Helium', '4.0026', 'He'], + ['3', 'Lithium', '6.941', 'Li'], + ['4', 'Beryllium', '9.0122', 'Be'], + ['5', 'Boron', '10.811', 'B'], + ['6', 'Carbon', '12.0107', 'C'], + ['7', 'Nitrogen', '14.0067', 'N'], + ['8', 'Oxygen', '15.9994', 'O'], + ['9', 'Fluorine', '18.9984', 'F'], + ['10', 'Neon', '20.1797', 'Ne'] + ]); + }); +} + +@Component({ + template: ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
No.{{element.position}}Number of the elementName{{element.name}}Name of the elementWeight{{element.weight}}Weight of the elementSymbol{{element.symbol}}Symbol of the element
+ ` +}) +class TableHarnessTest { + displayedColumns: string[] = ['position', 'name', 'weight', 'symbol']; + dataSource = [ + {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'}, + {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'}, + {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'}, + {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'}, + {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'}, + {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'}, + {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'}, + {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'}, + {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'}, + {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'}, + ]; +} diff --git a/src/material/table/testing/table-harness-filters.ts b/src/material/table/testing/table-harness-filters.ts new file mode 100644 index 000000000000..78a16d701087 --- /dev/null +++ b/src/material/table/testing/table-harness-filters.ts @@ -0,0 +1,22 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import {BaseHarnessFilters} from '@angular/cdk/testing'; + +/** A set of criteria that can be used to filter a list of cell harness instances. */ +export interface CellHarnessFilters extends BaseHarnessFilters { + /** Only find instances whose text matches the given value. */ + text?: string | RegExp; +} + +/** A set of criteria that can be used to filter a list of row harness instances. */ +export interface RowHarnessFilters extends BaseHarnessFilters { +} + +/** A set of criteria that can be used to filter a list of table harness instances. */ +export interface TableHarnessFilters extends BaseHarnessFilters { +} diff --git a/src/material/table/testing/table-harness.spec.ts b/src/material/table/testing/table-harness.spec.ts new file mode 100644 index 000000000000..3c48afddbf06 --- /dev/null +++ b/src/material/table/testing/table-harness.spec.ts @@ -0,0 +1,7 @@ +import {MatTableModule} from '@angular/material/table'; +import {runHarnessTests} from '@angular/material/table/testing/shared.spec'; +import {MatTableHarness} from './table-harness'; + +describe('Non-MDC-based MatTableHarness', () => { + runHarnessTests(MatTableModule, MatTableHarness); +}); diff --git a/src/material/table/testing/table-harness.ts b/src/material/table/testing/table-harness.ts new file mode 100644 index 000000000000..dcd5ff64f16c --- /dev/null +++ b/src/material/table/testing/table-harness.ts @@ -0,0 +1,110 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing'; +import {TableHarnessFilters, RowHarnessFilters} from './table-harness-filters'; +import {MatRowHarness, MatHeaderRowHarness, MatFooterRowHarness} from './row-harness'; + +/** Text extracted from a table organized by columns. */ +export interface MatTableHarnessColumnsText { + [columnName: string]: { + text: string[]; + headerText: string[]; + footerText: string[]; + }; +} + +/** Harness for interacting with a standard mat-table in tests. */ +export class MatTableHarness extends ComponentHarness { + /** The selector for the host element of a `MatTableHarness` instance. */ + static hostSelector = '.mat-table'; + + /** + * Gets a `HarnessPredicate` that can be used to search for a table with specific attributes. + * @param options Options for narrowing the search + * @return a `HarnessPredicate` configured with the given options. + */ + static with(options: TableHarnessFilters = {}): HarnessPredicate { + return new HarnessPredicate(MatTableHarness, options); + } + + /** Gets all of the header rows in a table. */ + async getHeaderRows(filter: RowHarnessFilters = {}): Promise { + return this.locatorForAll(MatHeaderRowHarness.with(filter))(); + } + + /** Gets all of the regular data rows in a table. */ + async getRows(filter: RowHarnessFilters = {}): Promise { + return this.locatorForAll(MatRowHarness.with(filter))(); + } + + /** Gets all of the footer rows in a table. */ + async getFooterRows(filter: RowHarnessFilters = {}): Promise { + return this.locatorForAll(MatFooterRowHarness.with(filter))(); + } + + /** Gets the text inside the entire table organized by rows. */ + async getCellTextByIndex(): Promise { + const rows = await this.getRows(); + return Promise.all(rows.map(row => row.getCellTextByIndex())); + } + + /** Gets the text inside the entire table organized by columns. */ + async getCellTextByColumnName(): Promise { + const [headerRows, footerRows, dataRows] = await Promise.all([ + this.getHeaderRows(), + this.getFooterRows(), + this.getRows() + ]); + + const text: MatTableHarnessColumnsText = {}; + const [headerData, footerData, rowsData] = await Promise.all([ + Promise.all(headerRows.map(row => getRowData(row))), + Promise.all(footerRows.map(row => getRowData(row))), + Promise.all(dataRows.map(row => getRowData(row))), + ]); + + rowsData.forEach(cells => { + cells.forEach(([columnName, cellText]) => { + if (!text[columnName]) { + text[columnName] = { + headerText: getCellTextsByColumn(headerData, columnName), + footerText: getCellTextsByColumn(footerData, columnName), + text: [] + }; + } + + text[columnName].text.push(cellText); + }); + }); + + return text; + } +} + +/** Utility to extract the column names and text from all of the cells in a row. */ +async function getRowData(row: MatRowHarness | MatHeaderRowHarness | MatFooterRowHarness) { + const cells = await row.getCells(); + return Promise.all(cells.map(cell => Promise.all([cell.getColumnName(), cell.getText()]))); +} + + +/** Extracts the text of cells only under a particular column. */ +function getCellTextsByColumn(rowsData: [string, string][][], column: string): string[] { + const columnTexts: string[] = []; + + rowsData.forEach(cells => { + cells.forEach(([columnName, cellText]) => { + if (columnName === column) { + columnTexts.push(cellText); + } + }); + }); + + return columnTexts; +} diff --git a/test/karma-system-config.js b/test/karma-system-config.js index d8359d3344e4..728a02f6256f 100644 --- a/test/karma-system-config.js +++ b/test/karma-system-config.js @@ -163,6 +163,8 @@ System.config({ '@angular/material/sort/testing/shared.spec': 'dist/packages/material/sort/testing/shared.spec.js', '@angular/material/stepper': 'dist/packages/material/stepper/index.js', '@angular/material/table': 'dist/packages/material/table/index.js', + '@angular/material/table/testing': 'dist/packages/material/table/testing/index.js', + '@angular/material/table/testing/shared.spec': 'dist/packages/material/table/testing/shared.spec.js', '@angular/material/tabs': 'dist/packages/material/tabs/index.js', '@angular/material/tabs/testing': 'dist/packages/material/tabs/testing/index.js', '@angular/material/tabs/testing/shared.spec': 'dist/packages/material/tabs/testing/shared.spec.js', diff --git a/tools/public_api_guard/material/table/testing.d.ts b/tools/public_api_guard/material/table/testing.d.ts new file mode 100644 index 000000000000..de7736e82333 --- /dev/null +++ b/tools/public_api_guard/material/table/testing.d.ts @@ -0,0 +1,65 @@ +export interface CellHarnessFilters extends BaseHarnessFilters { + text?: string | RegExp; +} + +export declare class MatCellHarness extends ComponentHarness { + getColumnName(): Promise; + getText(): Promise; + static hostSelector: string; + static with(options?: CellHarnessFilters): HarnessPredicate; +} + +export declare class MatFooterCellHarness extends MatCellHarness { + static hostSelector: string; + static with(options?: CellHarnessFilters): HarnessPredicate; +} + +export declare class MatFooterRowHarness extends ComponentHarness { + getCellTextByIndex(filter?: CellHarnessFilters): Promise; + getCells(filter?: CellHarnessFilters): Promise; + static hostSelector: string; + static with(options?: RowHarnessFilters): HarnessPredicate; +} + +export declare class MatHeaderCellHarness extends MatCellHarness { + static hostSelector: string; + static with(options?: CellHarnessFilters): HarnessPredicate; +} + +export declare class MatHeaderRowHarness extends ComponentHarness { + getCellTextByIndex(filter?: CellHarnessFilters): Promise; + getCells(filter?: CellHarnessFilters): Promise; + static hostSelector: string; + static with(options?: RowHarnessFilters): HarnessPredicate; +} + +export declare class MatRowHarness extends ComponentHarness { + getCellTextByIndex(filter?: CellHarnessFilters): Promise; + getCells(filter?: CellHarnessFilters): Promise; + static hostSelector: string; + static with(options?: RowHarnessFilters): HarnessPredicate; +} + +export declare class MatTableHarness extends ComponentHarness { + getCellTextByColumnName(): Promise; + getCellTextByIndex(): Promise; + getFooterRows(filter?: RowHarnessFilters): Promise; + getHeaderRows(filter?: RowHarnessFilters): Promise; + getRows(filter?: RowHarnessFilters): Promise; + static hostSelector: string; + static with(options?: TableHarnessFilters): HarnessPredicate; +} + +export interface MatTableHarnessColumnsText { + [columnName: string]: { + text: string[]; + headerText: string[]; + footerText: string[]; + }; +} + +export interface RowHarnessFilters extends BaseHarnessFilters { +} + +export interface TableHarnessFilters extends BaseHarnessFilters { +}