@cerios/playwright-table 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ The MIT License (MIT)
2
+ Copyright © 2025 Cerios
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ <h1>
2
+ 🎭 Playwright Tables
3
+ <picture>
4
+ <source srcset="cerios-logo-seasalt.svg" media="(prefers-color-scheme: dark)">
5
+ <img src="cerios-logo-spacecadet.svg" alt="cerios logo">
6
+ </picture>
7
+ </h1>
8
+
9
+ ## Introduction
10
+
11
+ It is always hard to test HTML Tables. You will need multiple selectors/locators to get the data you need. This package will make it easy for you and parse it to a json based on the given headers and objects for each row of the table. Now you can assert the objects to your liking.
12
+
13
+ Given the following HTML
14
+
15
+ | id | name | yearOfBirth |
16
+ | :-: | :----: | :---------: |
17
+ | 1 | Ronald | 1987 |
18
+ | 2 | Cerios | 2022 |
19
+
20
+ The result JSON will become:
21
+
22
+ ```
23
+ [
24
+ {
25
+ id: 1,
26
+ name: "Ronald",
27
+ yearOfBirth: 1987
28
+ },
29
+ {
30
+ id: 2,
31
+ name: "Cerios",
32
+ yearOfBirth: 2022
33
+ },
34
+ ]
35
+ ```
36
+
37
+ ## Installation
38
+
39
+ First you need to install and get firmiliar with the amazing playwright testing library:
40
+ https://github.com/microsoft/playwright/blob/main/README.md
41
+
42
+ ```
43
+ npx i -D @cerios/playwright-tables
44
+ ```
45
+
46
+ ## Usage
47
+
48
+ There can be more tables on a webpage. So you first need to identify the unique locator that wraps you complete table element.
49
+
50
+ Create a new PlaywrightTable
51
+
52
+ ```
53
+ const table = new PlaywrightTable(page.locator("table"));
54
+ ```
55
+
56
+ Without extra options the defaults for header rows(thead>tr), header cells(thead), body rows(tbody/tr) and body cells(td) will be used.
57
+ Now you can call the following methods:
58
+
59
+ - getHeaderRows
60
+ - getMainHeaderRow (default last)
61
+ - getBodyRows
62
+ - getBodyCellLocator
63
+ - getBodyCellLocatorByRowConditions
64
+ - getAllBodyCellLocatorsByHeaderName
65
+ - getAllBodyCellLocatorsByHeaderIndex
66
+ - getJson
67
+ - waitForHeaderRows
68
+ - waitForBodyRows
69
+
70
+ More information will be provided soon. Check the unit tests for inspiration...
@@ -0,0 +1,91 @@
1
+ import { Locator } from '@playwright/test';
2
+
3
+ type Cell = string | boolean | number;
4
+ type BodyRow = Cell[];
5
+ type HeaderRow = string[];
6
+
7
+ declare enum CellContentType {
8
+ TextContent = "textContent",
9
+ InnerText = "innerText"
10
+ }
11
+
12
+ type HeaderRowOptions = {
13
+ cellContentType?: CellContentType;
14
+ emptyCellReplacement?: boolean;
15
+ duplicateSuffix?: boolean;
16
+ colspan?: {
17
+ enabled?: boolean;
18
+ suffix?: boolean;
19
+ };
20
+ };
21
+
22
+ declare class PlaywrightTable {
23
+ private readonly _tableLocator;
24
+ private readonly _options?;
25
+ private _headers;
26
+ private _rows;
27
+ private _bodyRowLocator;
28
+ private _bodyRowColumnSelector;
29
+ private _headerRowLocator;
30
+ private _headerColumnSelector;
31
+ constructor(_tableLocator: Locator, _options?: {
32
+ header?: {
33
+ setMainHeaderRow?: number;
34
+ rowSelector?: string;
35
+ columnSelector?: string;
36
+ };
37
+ row?: {
38
+ rowSelector?: string;
39
+ columnSelector?: string;
40
+ };
41
+ } | undefined);
42
+ getHeaderRows(options?: {
43
+ timeout?: number;
44
+ duplicateSuffix?: boolean;
45
+ headerRowOptions?: HeaderRowOptions;
46
+ }): Promise<HeaderRow[]>;
47
+ getMainHeaderRow(options?: {
48
+ timeout?: number;
49
+ duplicateSuffix?: boolean;
50
+ headerRowOptions?: HeaderRowOptions;
51
+ }): Promise<HeaderRow>;
52
+ getBodyRows(options?: {
53
+ timeout?: number;
54
+ }): Promise<BodyRow[]>;
55
+ getBodyCellLocator(rowNumber: number, headerPosition: number): Locator;
56
+ getBodyCellLocatorByRowConditions(conditions: Record<string, string>, targetHeader: string, options?: {
57
+ timeout?: number;
58
+ duplicateSuffix?: boolean;
59
+ colspanEnabled?: boolean;
60
+ }): Promise<Locator>;
61
+ getAllBodyCellLocatorsByHeaderName(header: string, options?: {
62
+ timeout?: number;
63
+ }): Promise<Locator[]>;
64
+ getAllBodyCellLocatorsByHeaderIndex(headerIndex: number): Promise<Locator[]>;
65
+ getJson(options?: {
66
+ timeout?: number;
67
+ }): Promise<any>;
68
+ waitForHeaderRows(options?: {
69
+ timeout?: number;
70
+ row?: {
71
+ amount?: number;
72
+ cell?: {
73
+ totalCount?: number;
74
+ contentCount?: number;
75
+ };
76
+ };
77
+ }): Promise<void>;
78
+ waitForBodyRows(options?: {
79
+ timeout?: number;
80
+ row?: {
81
+ amount?: number;
82
+ cell?: {
83
+ totalCount?: number;
84
+ contentCount?: number;
85
+ };
86
+ };
87
+ }): Promise<void>;
88
+ private load;
89
+ }
90
+
91
+ export { type BodyRow, type Cell, CellContentType, type HeaderRow, type HeaderRowOptions, PlaywrightTable };
@@ -0,0 +1,91 @@
1
+ import { Locator } from '@playwright/test';
2
+
3
+ type Cell = string | boolean | number;
4
+ type BodyRow = Cell[];
5
+ type HeaderRow = string[];
6
+
7
+ declare enum CellContentType {
8
+ TextContent = "textContent",
9
+ InnerText = "innerText"
10
+ }
11
+
12
+ type HeaderRowOptions = {
13
+ cellContentType?: CellContentType;
14
+ emptyCellReplacement?: boolean;
15
+ duplicateSuffix?: boolean;
16
+ colspan?: {
17
+ enabled?: boolean;
18
+ suffix?: boolean;
19
+ };
20
+ };
21
+
22
+ declare class PlaywrightTable {
23
+ private readonly _tableLocator;
24
+ private readonly _options?;
25
+ private _headers;
26
+ private _rows;
27
+ private _bodyRowLocator;
28
+ private _bodyRowColumnSelector;
29
+ private _headerRowLocator;
30
+ private _headerColumnSelector;
31
+ constructor(_tableLocator: Locator, _options?: {
32
+ header?: {
33
+ setMainHeaderRow?: number;
34
+ rowSelector?: string;
35
+ columnSelector?: string;
36
+ };
37
+ row?: {
38
+ rowSelector?: string;
39
+ columnSelector?: string;
40
+ };
41
+ } | undefined);
42
+ getHeaderRows(options?: {
43
+ timeout?: number;
44
+ duplicateSuffix?: boolean;
45
+ headerRowOptions?: HeaderRowOptions;
46
+ }): Promise<HeaderRow[]>;
47
+ getMainHeaderRow(options?: {
48
+ timeout?: number;
49
+ duplicateSuffix?: boolean;
50
+ headerRowOptions?: HeaderRowOptions;
51
+ }): Promise<HeaderRow>;
52
+ getBodyRows(options?: {
53
+ timeout?: number;
54
+ }): Promise<BodyRow[]>;
55
+ getBodyCellLocator(rowNumber: number, headerPosition: number): Locator;
56
+ getBodyCellLocatorByRowConditions(conditions: Record<string, string>, targetHeader: string, options?: {
57
+ timeout?: number;
58
+ duplicateSuffix?: boolean;
59
+ colspanEnabled?: boolean;
60
+ }): Promise<Locator>;
61
+ getAllBodyCellLocatorsByHeaderName(header: string, options?: {
62
+ timeout?: number;
63
+ }): Promise<Locator[]>;
64
+ getAllBodyCellLocatorsByHeaderIndex(headerIndex: number): Promise<Locator[]>;
65
+ getJson(options?: {
66
+ timeout?: number;
67
+ }): Promise<any>;
68
+ waitForHeaderRows(options?: {
69
+ timeout?: number;
70
+ row?: {
71
+ amount?: number;
72
+ cell?: {
73
+ totalCount?: number;
74
+ contentCount?: number;
75
+ };
76
+ };
77
+ }): Promise<void>;
78
+ waitForBodyRows(options?: {
79
+ timeout?: number;
80
+ row?: {
81
+ amount?: number;
82
+ cell?: {
83
+ totalCount?: number;
84
+ contentCount?: number;
85
+ };
86
+ };
87
+ }): Promise<void>;
88
+ private load;
89
+ }
90
+
91
+ export { type BodyRow, type Cell, CellContentType, type HeaderRow, type HeaderRowOptions, PlaywrightTable };
package/dist/index.js ADDED
@@ -0,0 +1,445 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ CellContentType: () => CellContentType,
24
+ PlaywrightTable: () => PlaywrightTable
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/playwright-table.ts
29
+ var import_test2 = require("@playwright/test");
30
+
31
+ // src/cell-content-type.ts
32
+ var CellContentType = /* @__PURE__ */ ((CellContentType2) => {
33
+ CellContentType2["TextContent"] = "textContent";
34
+ CellContentType2["InnerText"] = "innerText";
35
+ return CellContentType2;
36
+ })(CellContentType || {});
37
+
38
+ // src/table-utils.ts
39
+ var TableUtils = class {
40
+ static async getCellContent(cell, cellContentType) {
41
+ const content = cellContentType === "innerText" /* InnerText */ ? await cell.innerText() : await cell.textContent();
42
+ return (content == null ? void 0 : content.trim()) || "";
43
+ }
44
+ static async parseSpanAttributes(cell) {
45
+ return {
46
+ rowspan: parseInt(await cell.getAttribute("rowspan") || "1", 10),
47
+ colspan: parseInt(await cell.getAttribute("colspan") || "1", 10)
48
+ };
49
+ }
50
+ static castContent(value) {
51
+ const trimmedValue = value.trim();
52
+ if (trimmedValue === "") return "";
53
+ const lowerValue = trimmedValue.toLowerCase();
54
+ if (lowerValue === "true") return true;
55
+ if (lowerValue === "false") return false;
56
+ const num = Number(trimmedValue);
57
+ return isNaN(num) ? trimmedValue : num;
58
+ }
59
+ };
60
+
61
+ // src/table-body.ts
62
+ var TableBody = class {
63
+ static async getRows(rowLocator, columnsSelector, bodyRowsOptions) {
64
+ const rows = [];
65
+ const rowsCount = await rowLocator.count();
66
+ const spannedCells = {};
67
+ for (let rowIndex = 0; rowIndex < rowsCount; rowIndex++) {
68
+ const row = rowLocator.nth(rowIndex);
69
+ const columns = await this.extractColumns(
70
+ row,
71
+ columnsSelector,
72
+ rowIndex,
73
+ spannedCells,
74
+ bodyRowsOptions == null ? void 0 : bodyRowsOptions.cellContentType
75
+ );
76
+ rows.push(columns);
77
+ }
78
+ return rows;
79
+ }
80
+ static async extractColumns(row, columnsSelector, rowIndex, spannedCells, cellContentType) {
81
+ const columns = [];
82
+ const columnLocators = row.locator(columnsSelector);
83
+ const columnCount = await columnLocators.count();
84
+ for (let colIndex = 0; colIndex < columnCount; colIndex++) {
85
+ await this.processColumn(
86
+ columnLocators.nth(colIndex),
87
+ colIndex,
88
+ columns,
89
+ rowIndex,
90
+ spannedCells,
91
+ cellContentType
92
+ );
93
+ }
94
+ this.applySpannedCells(spannedCells, rowIndex, columns);
95
+ return columns;
96
+ }
97
+ static async processColumn(column, colIndex, columns, rowIndex, spannedCells, cellContentType = "innerText" /* InnerText */) {
98
+ const content = await TableUtils.getCellContent(column, cellContentType);
99
+ const castedContent = TableUtils.castContent(content);
100
+ const { rowspan, colspan } = await TableUtils.parseSpanAttributes(column);
101
+ for (let span = 0; span < colspan; span++) {
102
+ columns[colIndex + span] = castedContent;
103
+ }
104
+ if (rowspan > 1) {
105
+ this.storeSpannedCells(rowIndex, colIndex, rowspan, castedContent, spannedCells);
106
+ }
107
+ }
108
+ static storeSpannedCells(rowIndex, colIndex, rowspan, content, spannedCells) {
109
+ for (let span = 1; span < rowspan; span++) {
110
+ if (!spannedCells[rowIndex + span]) {
111
+ spannedCells[rowIndex + span] = [];
112
+ }
113
+ spannedCells[rowIndex + span][colIndex] = content;
114
+ }
115
+ }
116
+ static applySpannedCells(spannedCells, rowIndex, columns) {
117
+ if (spannedCells[rowIndex]) {
118
+ spannedCells[rowIndex].forEach((spannedContent, colIndex) => {
119
+ if (spannedContent !== void 0) {
120
+ columns[colIndex] = spannedContent;
121
+ }
122
+ });
123
+ }
124
+ }
125
+ };
126
+
127
+ // src/table-header.ts
128
+ var TableHeader = class {
129
+ static async getRows(headerRowLocator, columnsSelector, headerRowOptions) {
130
+ const options = this.getDefaultOptions(headerRowOptions);
131
+ const rows = await headerRowLocator.all();
132
+ const headerRows = [];
133
+ const rowSpans = /* @__PURE__ */ new Map();
134
+ for (const row of rows) {
135
+ const headerRow = await this.processRow(row, columnsSelector, rowSpans, options);
136
+ headerRows.push(headerRow);
137
+ }
138
+ this.applyColspanOptions(headerRows, options);
139
+ this.applyDuplicateSuffix(headerRows, options);
140
+ return headerRows;
141
+ }
142
+ static getDefaultOptions(options) {
143
+ var _a, _b, _c, _d, _e, _f, _g;
144
+ return {
145
+ cellContentType: (_a = options == null ? void 0 : options.cellContentType) != null ? _a : "innerText" /* InnerText */,
146
+ emptyCellReplacement: (_b = options == null ? void 0 : options.emptyCellReplacement) != null ? _b : false,
147
+ duplicateSuffix: (_c = options == null ? void 0 : options.duplicateSuffix) != null ? _c : false,
148
+ colspan: {
149
+ enabled: (_e = (_d = options == null ? void 0 : options.colspan) == null ? void 0 : _d.enabled) != null ? _e : false,
150
+ suffix: (_g = (_f = options == null ? void 0 : options.colspan) == null ? void 0 : _f.suffix) != null ? _g : false
151
+ }
152
+ };
153
+ }
154
+ static async processRow(row, columnsSelector, rowSpans, options) {
155
+ const headerRow = [];
156
+ const cells = await row.locator(columnsSelector).all();
157
+ let columnIndex = 0;
158
+ for (const cell of cells) {
159
+ columnIndex = await this.processCell(cell, headerRow, rowSpans, columnIndex, options);
160
+ }
161
+ this.addRemainingRowSpans(headerRow, rowSpans, columnIndex);
162
+ return headerRow;
163
+ }
164
+ static async processCell(cell, headerRow, rowSpans, columnIndex, options) {
165
+ while (rowSpans.has(columnIndex)) {
166
+ headerRow.push(rowSpans.get(columnIndex));
167
+ rowSpans.delete(columnIndex);
168
+ columnIndex++;
169
+ }
170
+ let text = await TableUtils.getCellContent(cell, options.cellContentType);
171
+ if (!text && options.emptyCellReplacement) {
172
+ text = "{{Empty}}";
173
+ }
174
+ const { colspan, rowspan } = await TableUtils.parseSpanAttributes(cell);
175
+ headerRow.push(text);
176
+ this.handleColspan(headerRow, text, colspan);
177
+ this.handleRowspan(rowSpans, text, columnIndex, colspan, rowspan);
178
+ return columnIndex + colspan;
179
+ }
180
+ static handleColspan(headerRow, text, colspan) {
181
+ for (let i = 1; i < colspan; i++) {
182
+ headerRow.push(`${text}__C${i}`);
183
+ }
184
+ }
185
+ static handleRowspan(rowSpans, text, columnIndex, colspan, rowspan) {
186
+ if (rowspan > 1) {
187
+ for (let i = 0; i < colspan; i++) {
188
+ rowSpans.set(columnIndex + i, text);
189
+ }
190
+ }
191
+ }
192
+ static addRemainingRowSpans(headerRow, rowSpans, columnIndex) {
193
+ while (rowSpans.has(columnIndex)) {
194
+ headerRow.push(rowSpans.get(columnIndex));
195
+ rowSpans.delete(columnIndex);
196
+ columnIndex++;
197
+ }
198
+ }
199
+ static applyColspanOptions(headerRows, options) {
200
+ if (!options.colspan.enabled) {
201
+ this.removeColspanCells(headerRows);
202
+ }
203
+ if (!options.colspan.suffix) {
204
+ this.removeColspanSuffix(headerRows);
205
+ }
206
+ }
207
+ static removeColspanCells(headerRows) {
208
+ for (const headerRow of headerRows) {
209
+ for (let i = 0; i < headerRow.length; i++) {
210
+ if (/__C\d/.test(headerRow[i])) {
211
+ headerRow.splice(i, 1);
212
+ i--;
213
+ }
214
+ }
215
+ }
216
+ }
217
+ static removeColspanSuffix(headerRows) {
218
+ for (const headerRow of headerRows) {
219
+ for (let i = 0; i < headerRow.length; i++) {
220
+ if (/__C\d/.test(headerRow[i])) {
221
+ headerRow[i] = headerRow[i].replace(/__C\d/, "");
222
+ }
223
+ }
224
+ }
225
+ }
226
+ static applyDuplicateSuffix(headerRows, options) {
227
+ if (!options.duplicateSuffix) return;
228
+ for (const headerRow of headerRows) {
229
+ const headerCountMap = /* @__PURE__ */ new Map();
230
+ for (let i = 0; i < headerRow.length; i++) {
231
+ const header = headerRow[i];
232
+ if (headerCountMap.has(header)) {
233
+ const count = headerCountMap.get(header);
234
+ headerRow[i] = `${header}__D${count}`;
235
+ headerCountMap.set(header, count + 1);
236
+ } else {
237
+ headerCountMap.set(header, 1);
238
+ }
239
+ }
240
+ }
241
+ }
242
+ };
243
+
244
+ // src/table-wait.ts
245
+ var import_test = require("@playwright/test");
246
+ var TableWait = class {
247
+ static async waitForRows(rowLocator, cellSelector, rowKind, options) {
248
+ const validateCellsWithContent = async () => {
249
+ const cells = await rowLocator.locator(cellSelector).all();
250
+ const cellsWithContent = (await Promise.all(
251
+ cells.map(async (cell) => {
252
+ const content = await cell.textContent();
253
+ return content !== null && content.trim() !== "" ? cell : null;
254
+ })
255
+ )).filter((cell) => cell !== null);
256
+ (0, import_test.expect)(cellsWithContent.length, `No ${rowKind} cells with content found`).toBeGreaterThan(0);
257
+ };
258
+ const validateRowAmount = (rows2, expectedAmount) => {
259
+ (0, import_test.expect)(rows2.length, `Expected ${expectedAmount} ${rowKind} rows, but found ${rows2.length}`).toBe(expectedAmount);
260
+ };
261
+ const validateCellCount = async (rows2, expectedCount) => {
262
+ const rowsWithMatchingCells = (await Promise.all(
263
+ rows2.map(async (row) => {
264
+ const cellCount = await row.locator(cellSelector).count();
265
+ return cellCount === expectedCount ? row : null;
266
+ })
267
+ )).filter((row) => row !== null);
268
+ (0, import_test.expect)(
269
+ rowsWithMatchingCells.length,
270
+ `Expected amount of ${expectedCount} ${rowKind} cells for row not found`
271
+ ).toBeGreaterThan(0);
272
+ };
273
+ const validateCellContentCount = async (rows2, expectedContentCount) => {
274
+ const rowsWithMatchingContent = (await Promise.all(
275
+ rows2.map(async (row) => {
276
+ const cells = await row.locator(cellSelector).all();
277
+ const cellsWithContent = (await Promise.all(
278
+ cells.map(async (cell) => {
279
+ const content = await cell.textContent();
280
+ return content !== null && content.trim() !== "" ? cell : null;
281
+ })
282
+ )).filter((cell) => cell !== null);
283
+ return cellsWithContent.length === expectedContentCount ? row : null;
284
+ })
285
+ )).filter((row) => row !== null);
286
+ (0, import_test.expect)(
287
+ rowsWithMatchingContent.length,
288
+ `Expected amount of ${expectedContentCount} ${rowKind} cells with content for row not found`
289
+ ).toBeGreaterThan(0);
290
+ };
291
+ const rows = await rowLocator.all();
292
+ if (options == null ? void 0 : options.row) {
293
+ if (options.row.amount) {
294
+ validateRowAmount(rows, options.row.amount);
295
+ } else {
296
+ (0, import_test.expect)(rows.length, `No ${rowKind} rows found`).toBeGreaterThan(0);
297
+ }
298
+ if (options.row.cell) {
299
+ if (options.row.cell.totalCount) {
300
+ await validateCellCount(rows, options.row.cell.totalCount);
301
+ }
302
+ if (options.row.cell.contentCount) {
303
+ await validateCellContentCount(rows, options.row.cell.contentCount);
304
+ } else {
305
+ await validateCellsWithContent();
306
+ }
307
+ } else {
308
+ await validateCellsWithContent();
309
+ }
310
+ } else {
311
+ await validateCellsWithContent();
312
+ }
313
+ }
314
+ };
315
+
316
+ // src/playwright-table.ts
317
+ var PlaywrightTable = class {
318
+ constructor(_tableLocator, _options) {
319
+ this._tableLocator = _tableLocator;
320
+ this._options = _options;
321
+ this._headers = [];
322
+ this._rows = [];
323
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
324
+ this._headerRowLocator = this._tableLocator.locator((_c = (_b = (_a = this._options) == null ? void 0 : _a.header) == null ? void 0 : _b.rowSelector) != null ? _c : "thead>tr");
325
+ this._headerColumnSelector = (_f = (_e = (_d = this._options) == null ? void 0 : _d.header) == null ? void 0 : _e.columnSelector) != null ? _f : "th";
326
+ this._bodyRowLocator = this._tableLocator.locator((_i = (_h = (_g = this._options) == null ? void 0 : _g.row) == null ? void 0 : _h.rowSelector) != null ? _i : "tbody>tr");
327
+ this._bodyRowColumnSelector = (_l = (_k = (_j = this._options) == null ? void 0 : _j.row) == null ? void 0 : _k.columnSelector) != null ? _l : "td";
328
+ }
329
+ async getHeaderRows(options) {
330
+ await this.load(options);
331
+ return this._headers;
332
+ }
333
+ async getMainHeaderRow(options) {
334
+ var _a, _b;
335
+ const headerRows = await this.getHeaderRows(options);
336
+ const headers = ((_b = (_a = this._options) == null ? void 0 : _a.header) == null ? void 0 : _b.setMainHeaderRow) ? headerRows[this._options.header.setMainHeaderRow] : headerRows[this._headers.length - 1];
337
+ return headers;
338
+ }
339
+ async getBodyRows(options) {
340
+ await this.load({ ...options, headerRowOptions: { colspan: { enabled: true } } });
341
+ return this._rows;
342
+ }
343
+ getBodyCellLocator(rowNumber, headerPosition) {
344
+ return this._bodyRowLocator.nth(rowNumber).locator(this._bodyRowColumnSelector).nth(headerPosition);
345
+ }
346
+ async getBodyCellLocatorByRowConditions(conditions, targetHeader, options) {
347
+ await this.load(options);
348
+ const headers = await this.getMainHeaderRow();
349
+ const targetHeaderIndex = headers.indexOf(targetHeader);
350
+ if (targetHeaderIndex === -1) {
351
+ throw new Error(`Header "${targetHeader}" not found.`);
352
+ }
353
+ for (let rowIndex = 0; rowIndex < this._rows.length; rowIndex++) {
354
+ const row = this._rows[rowIndex];
355
+ let matches = true;
356
+ for (const [header, value] of Object.entries(conditions)) {
357
+ const headerIndex = headers.indexOf(header);
358
+ if (headerIndex === -1) {
359
+ throw new Error(`Header "${header}" not found.`);
360
+ }
361
+ if (row[headerIndex] !== value) {
362
+ matches = false;
363
+ break;
364
+ }
365
+ }
366
+ if (matches) {
367
+ return this.getBodyCellLocator(rowIndex, targetHeaderIndex);
368
+ }
369
+ }
370
+ throw new Error(`No row found matching conditions: ${JSON.stringify(conditions)}`);
371
+ }
372
+ async getAllBodyCellLocatorsByHeaderName(header, options) {
373
+ await this.load(options);
374
+ const headers = await this.getMainHeaderRow();
375
+ const headerIndex = headers.indexOf(header);
376
+ if (headerIndex === -1) {
377
+ throw new Error(`Header "${header}" not found.`);
378
+ }
379
+ const locators = [];
380
+ for (let rowIndex = 0; rowIndex < this._rows.length; rowIndex++) {
381
+ const cellLocator = this.getBodyCellLocator(rowIndex, headerIndex);
382
+ locators.push(cellLocator);
383
+ }
384
+ return locators;
385
+ }
386
+ async getAllBodyCellLocatorsByHeaderIndex(headerIndex) {
387
+ await this.load();
388
+ const locators = [];
389
+ for (let rowIndex = 0; rowIndex < this._rows.length; rowIndex++) {
390
+ const cellLocator = this.getBodyCellLocator(rowIndex, headerIndex);
391
+ locators.push(cellLocator);
392
+ }
393
+ return locators;
394
+ }
395
+ async getJson(options) {
396
+ const headers = await this.getMainHeaderRow({
397
+ timeout: options == null ? void 0 : options.timeout,
398
+ duplicateSuffix: true,
399
+ headerRowOptions: {
400
+ colspan: { enabled: true, suffix: true },
401
+ duplicateSuffix: true,
402
+ emptyCellReplacement: true
403
+ }
404
+ });
405
+ return this._rows.map((row) => {
406
+ const rowObj = {};
407
+ headers.forEach((header, index) => {
408
+ rowObj[header] = row[index] || "";
409
+ });
410
+ return rowObj;
411
+ });
412
+ }
413
+ async waitForHeaderRows(options) {
414
+ await (0, import_test2.expect)(
415
+ async () => await TableWait.waitForRows(this._headerRowLocator, this._headerColumnSelector, "header" /* Header */, options)
416
+ ).toPass({
417
+ timeout: options == null ? void 0 : options.timeout
418
+ });
419
+ }
420
+ async waitForBodyRows(options) {
421
+ await (0, import_test2.expect)(
422
+ async () => await TableWait.waitForRows(this._bodyRowLocator, this._bodyRowColumnSelector, "body" /* Body */, options)
423
+ ).toPass({
424
+ timeout: options == null ? void 0 : options.timeout
425
+ });
426
+ }
427
+ async load(options) {
428
+ await (0, import_test2.expect)(async () => {
429
+ await TableWait.waitForRows(this._headerRowLocator, this._headerColumnSelector, "header" /* Header */);
430
+ await TableWait.waitForRows(this._bodyRowLocator, this._bodyRowColumnSelector, "body" /* Body */);
431
+ }).toPass({ timeout: options == null ? void 0 : options.timeout });
432
+ this._headers = await TableHeader.getRows(
433
+ this._headerRowLocator,
434
+ this._headerColumnSelector,
435
+ options == null ? void 0 : options.headerRowOptions
436
+ );
437
+ this._rows = await TableBody.getRows(this._bodyRowLocator, this._bodyRowColumnSelector);
438
+ }
439
+ };
440
+ // Annotate the CommonJS export names for ESM import in node:
441
+ 0 && (module.exports = {
442
+ CellContentType,
443
+ PlaywrightTable
444
+ });
445
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/playwright-table.ts","../src/cell-content-type.ts","../src/table-utils.ts","../src/table-body.ts","../src/table-header.ts","../src/table-wait.ts"],"sourcesContent":["export * from \"./playwright-table\";\r\nexport * from \"./row\";\r\nexport { HeaderRowOptions } from \"./table-header\";\r\nexport { CellContentType } from \"./cell-content-type\";\r\n","import { expect, Locator } from \"@playwright/test\";\r\nimport { TableBody } from \"./table-body\";\r\nimport { BodyRow, Cell, HeaderRow } from \"./row\";\r\nimport { HeaderRowOptions, TableHeader } from \"./table-header\";\r\nimport { RowKind, TableWait } from \"./table-wait\";\r\n\r\nexport class PlaywrightTable {\r\n\tprivate _headers: HeaderRow[] = [];\r\n\tprivate _rows: BodyRow[] = [];\r\n\tprivate _bodyRowLocator: Locator;\r\n\tprivate _bodyRowColumnSelector: string;\r\n\tprivate _headerRowLocator: Locator;\r\n\tprivate _headerColumnSelector: string;\r\n\r\n\tconstructor(\r\n\t\tprivate readonly _tableLocator: Locator,\r\n\t\tprivate readonly _options?: {\r\n\t\t\theader?: {\r\n\t\t\t\tsetMainHeaderRow?: number;\r\n\t\t\t\trowSelector?: string;\r\n\t\t\t\tcolumnSelector?: string;\r\n\t\t\t};\r\n\t\t\trow?: {\r\n\t\t\t\trowSelector?: string;\r\n\t\t\t\tcolumnSelector?: string;\r\n\t\t\t};\r\n\t\t}\r\n\t) {\r\n\t\tthis._headerRowLocator = this._tableLocator.locator(this._options?.header?.rowSelector ?? \"thead>tr\");\r\n\t\tthis._headerColumnSelector = this._options?.header?.columnSelector ?? \"th\";\r\n\t\tthis._bodyRowLocator = this._tableLocator.locator(this._options?.row?.rowSelector ?? \"tbody>tr\");\r\n\t\tthis._bodyRowColumnSelector = this._options?.row?.columnSelector ?? \"td\";\r\n\t}\r\n\r\n\tasync getHeaderRows(options?: {\r\n\t\ttimeout?: number;\r\n\t\tduplicateSuffix?: boolean;\r\n\t\theaderRowOptions?: HeaderRowOptions;\r\n\t}): Promise<HeaderRow[]> {\r\n\t\tawait this.load(options);\r\n\t\treturn this._headers;\r\n\t}\r\n\r\n\tasync getMainHeaderRow(options?: {\r\n\t\ttimeout?: number;\r\n\t\tduplicateSuffix?: boolean;\r\n\t\theaderRowOptions?: HeaderRowOptions;\r\n\t}): Promise<HeaderRow> {\r\n\t\tconst headerRows = await this.getHeaderRows(options);\r\n\t\tconst headers = this._options?.header?.setMainHeaderRow\r\n\t\t\t? headerRows[this._options.header.setMainHeaderRow]\r\n\t\t\t: headerRows[this._headers.length - 1];\r\n\t\treturn headers;\r\n\t}\r\n\r\n\tasync getBodyRows(options?: { timeout?: number }): Promise<BodyRow[]> {\r\n\t\tawait this.load({ ...options, headerRowOptions: { colspan: { enabled: true } } });\r\n\t\treturn this._rows;\r\n\t}\r\n\r\n\tgetBodyCellLocator(rowNumber: number, headerPosition: number): Locator {\r\n\t\treturn this._bodyRowLocator.nth(rowNumber).locator(this._bodyRowColumnSelector).nth(headerPosition);\r\n\t}\r\n\r\n\tasync getBodyCellLocatorByRowConditions(\r\n\t\tconditions: Record<string, string>,\r\n\t\ttargetHeader: string,\r\n\t\toptions?: { timeout?: number; duplicateSuffix?: boolean; colspanEnabled?: boolean }\r\n\t): Promise<Locator> {\r\n\t\tawait this.load(options);\r\n\t\tconst headers = await this.getMainHeaderRow();\r\n\r\n\t\tconst targetHeaderIndex = headers.indexOf(targetHeader);\r\n\t\tif (targetHeaderIndex === -1) {\r\n\t\t\tthrow new Error(`Header \"${targetHeader}\" not found.`);\r\n\t\t}\r\n\r\n\t\tfor (let rowIndex = 0; rowIndex < this._rows.length; rowIndex++) {\r\n\t\t\tconst row = this._rows[rowIndex];\r\n\t\t\tlet matches = true;\r\n\r\n\t\t\tfor (const [header, value] of Object.entries(conditions)) {\r\n\t\t\t\tconst headerIndex = headers.indexOf(header);\r\n\t\t\t\tif (headerIndex === -1) {\r\n\t\t\t\t\tthrow new Error(`Header \"${header}\" not found.`);\r\n\t\t\t\t}\r\n\t\t\t\tif (row[headerIndex] !== value) {\r\n\t\t\t\t\tmatches = false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (matches) {\r\n\t\t\t\treturn this.getBodyCellLocator(rowIndex, targetHeaderIndex);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthrow new Error(`No row found matching conditions: ${JSON.stringify(conditions)}`);\r\n\t}\r\n\r\n\tasync getAllBodyCellLocatorsByHeaderName(header: string, options?: { timeout?: number }): Promise<Locator[]> {\r\n\t\tawait this.load(options);\r\n\t\tconst headers = await this.getMainHeaderRow();\r\n\t\tconst headerIndex = headers.indexOf(header);\r\n\t\tif (headerIndex === -1) {\r\n\t\t\tthrow new Error(`Header \"${header}\" not found.`);\r\n\t\t}\r\n\t\tconst locators: Locator[] = [];\r\n\t\tfor (let rowIndex = 0; rowIndex < this._rows.length; rowIndex++) {\r\n\t\t\tconst cellLocator = this.getBodyCellLocator(rowIndex, headerIndex);\r\n\t\t\tlocators.push(cellLocator);\r\n\t\t}\r\n\t\treturn locators;\r\n\t}\r\n\r\n\tasync getAllBodyCellLocatorsByHeaderIndex(headerIndex: number): Promise<Locator[]> {\r\n\t\tawait this.load();\r\n\t\tconst locators: Locator[] = [];\r\n\t\tfor (let rowIndex = 0; rowIndex < this._rows.length; rowIndex++) {\r\n\t\t\tconst cellLocator = this.getBodyCellLocator(rowIndex, headerIndex);\r\n\t\t\tlocators.push(cellLocator);\r\n\t\t}\r\n\t\treturn locators;\r\n\t}\r\n\r\n\tasync getJson(options?: { timeout?: number }): Promise<any> {\r\n\t\tconst headers = await this.getMainHeaderRow({\r\n\t\t\ttimeout: options?.timeout,\r\n\t\t\tduplicateSuffix: true,\r\n\t\t\theaderRowOptions: {\r\n\t\t\t\tcolspan: { enabled: true, suffix: true },\r\n\t\t\t\tduplicateSuffix: true,\r\n\t\t\t\temptyCellReplacement: true,\r\n\t\t\t},\r\n\t\t});\r\n\t\treturn this._rows.map(row => {\r\n\t\t\tconst rowObj: Record<string, Cell> = {};\r\n\t\t\theaders.forEach((header, index) => {\r\n\t\t\t\trowObj[header] = row[index] || \"\";\r\n\t\t\t});\r\n\t\t\treturn rowObj;\r\n\t\t});\r\n\t}\r\n\r\n\tasync waitForHeaderRows(options?: {\r\n\t\ttimeout?: number;\r\n\t\trow?: {\r\n\t\t\tamount?: number;\r\n\t\t\tcell?: {\r\n\t\t\t\ttotalCount?: number;\r\n\t\t\t\tcontentCount?: number;\r\n\t\t\t};\r\n\t\t};\r\n\t}): Promise<void> {\r\n\t\tawait expect(\r\n\t\t\tasync () =>\r\n\t\t\t\tawait TableWait.waitForRows(this._headerRowLocator, this._headerColumnSelector, RowKind.Header, options)\r\n\t\t).toPass({\r\n\t\t\ttimeout: options?.timeout,\r\n\t\t});\r\n\t}\r\n\r\n\tasync waitForBodyRows(options?: {\r\n\t\ttimeout?: number;\r\n\t\trow?: {\r\n\t\t\tamount?: number;\r\n\t\t\tcell?: {\r\n\t\t\t\ttotalCount?: number;\r\n\t\t\t\tcontentCount?: number;\r\n\t\t\t};\r\n\t\t};\r\n\t}): Promise<void> {\r\n\t\tawait expect(\r\n\t\t\tasync () => await TableWait.waitForRows(this._bodyRowLocator, this._bodyRowColumnSelector, RowKind.Body, options)\r\n\t\t).toPass({\r\n\t\t\ttimeout: options?.timeout,\r\n\t\t});\r\n\t}\r\n\r\n\tprivate async load(options?: { timeout?: number; headerRowOptions?: HeaderRowOptions }): Promise<void> {\r\n\t\tawait expect(async () => {\r\n\t\t\tawait TableWait.waitForRows(this._headerRowLocator, this._headerColumnSelector, RowKind.Header);\r\n\t\t\tawait TableWait.waitForRows(this._bodyRowLocator, this._bodyRowColumnSelector, RowKind.Body);\r\n\t\t}).toPass({ timeout: options?.timeout });\r\n\r\n\t\tthis._headers = await TableHeader.getRows(\r\n\t\t\tthis._headerRowLocator,\r\n\t\t\tthis._headerColumnSelector,\r\n\t\t\toptions?.headerRowOptions\r\n\t\t);\r\n\t\tthis._rows = await TableBody.getRows(this._bodyRowLocator, this._bodyRowColumnSelector);\r\n\t}\r\n}\r\n","export enum CellContentType {\r\n\tTextContent = \"textContent\",\r\n\tInnerText = \"innerText\",\r\n}\r\n","import { Locator } from \"@playwright/test\";\r\nimport { CellContentType } from \"./cell-content-type\";\r\nimport { Cell } from \"./row\";\r\n\r\nexport abstract class TableUtils {\r\n\tstatic async getCellContent(cell: Locator, cellContentType: CellContentType): Promise<string> {\r\n\t\tconst content = cellContentType === CellContentType.InnerText ? await cell.innerText() : await cell.textContent();\r\n\t\treturn content?.trim() || \"\";\r\n\t}\r\n\r\n\tstatic async parseSpanAttributes(cell: Locator): Promise<{ rowspan: number; colspan: number }> {\r\n\t\treturn {\r\n\t\t\trowspan: parseInt((await cell.getAttribute(\"rowspan\")) || \"1\", 10),\r\n\t\t\tcolspan: parseInt((await cell.getAttribute(\"colspan\")) || \"1\", 10),\r\n\t\t};\r\n\t}\r\n\r\n\tstatic castContent(value: string): Cell {\r\n\t\tconst trimmedValue = value.trim();\r\n\r\n\t\tif (trimmedValue === \"\") return \"\";\r\n\r\n\t\tconst lowerValue = trimmedValue.toLowerCase();\r\n\r\n\t\tif (lowerValue === \"true\") return true;\r\n\t\tif (lowerValue === \"false\") return false;\r\n\r\n\t\tconst num = Number(trimmedValue);\r\n\t\treturn isNaN(num) ? trimmedValue : num;\r\n\t}\r\n}\r\n","import { Locator } from \"@playwright/test\";\r\nimport { BodyRow, Cell } from \"./row\";\r\nimport { CellContentType } from \"./cell-content-type\";\r\nimport { TableUtils } from \"./table-utils\";\r\n\r\nexport abstract class TableBody {\r\n\tstatic async getRows(\r\n\t\trowLocator: Locator,\r\n\t\tcolumnsSelector: string,\r\n\t\tbodyRowsOptions?: {\r\n\t\t\tcellContentType?: CellContentType;\r\n\t\t}\r\n\t): Promise<BodyRow[]> {\r\n\t\tconst rows: BodyRow[] = [];\r\n\t\tconst rowsCount = await rowLocator.count();\r\n\t\tconst spannedCells: Record<number, Cell[]> = {};\r\n\r\n\t\tfor (let rowIndex = 0; rowIndex < rowsCount; rowIndex++) {\r\n\t\t\tconst row = rowLocator.nth(rowIndex);\r\n\t\t\tconst columns = await this.extractColumns(\r\n\t\t\t\trow,\r\n\t\t\t\tcolumnsSelector,\r\n\t\t\t\trowIndex,\r\n\t\t\t\tspannedCells,\r\n\t\t\t\tbodyRowsOptions?.cellContentType\r\n\t\t\t);\r\n\t\t\trows.push(columns as BodyRow);\r\n\t\t}\r\n\r\n\t\treturn rows;\r\n\t}\r\n\r\n\tprivate static async extractColumns(\r\n\t\trow: Locator,\r\n\t\tcolumnsSelector: string,\r\n\t\trowIndex: number,\r\n\t\tspannedCells: Record<number, Cell[]>,\r\n\t\tcellContentType?: CellContentType\r\n\t): Promise<Cell[]> {\r\n\t\tconst columns: Cell[] = [];\r\n\t\tconst columnLocators = row.locator(columnsSelector);\r\n\t\tconst columnCount = await columnLocators.count();\r\n\r\n\t\tfor (let colIndex = 0; colIndex < columnCount; colIndex++) {\r\n\t\t\tawait this.processColumn(\r\n\t\t\t\tcolumnLocators.nth(colIndex),\r\n\t\t\t\tcolIndex,\r\n\t\t\t\tcolumns,\r\n\t\t\t\trowIndex,\r\n\t\t\t\tspannedCells,\r\n\t\t\t\tcellContentType\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tthis.applySpannedCells(spannedCells, rowIndex, columns);\r\n\r\n\t\treturn columns;\r\n\t}\r\n\r\n\tprivate static async processColumn(\r\n\t\tcolumn: Locator,\r\n\t\tcolIndex: number,\r\n\t\tcolumns: Cell[],\r\n\t\trowIndex: number,\r\n\t\tspannedCells: Record<number, Cell[]>,\r\n\t\tcellContentType: CellContentType = CellContentType.InnerText\r\n\t): Promise<void> {\r\n\t\tconst content = await TableUtils.getCellContent(column, cellContentType);\r\n\t\tconst castedContent = TableUtils.castContent(content);\r\n\r\n\t\tconst { rowspan, colspan } = await TableUtils.parseSpanAttributes(column);\r\n\r\n\t\tfor (let span = 0; span < colspan; span++) {\r\n\t\t\tcolumns[colIndex + span] = castedContent;\r\n\t\t}\r\n\r\n\t\tif (rowspan > 1) {\r\n\t\t\tthis.storeSpannedCells(rowIndex, colIndex, rowspan, castedContent, spannedCells);\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static storeSpannedCells(\r\n\t\trowIndex: number,\r\n\t\tcolIndex: number,\r\n\t\trowspan: number,\r\n\t\tcontent: Cell,\r\n\t\tspannedCells: Record<number, Cell[]>\r\n\t): void {\r\n\t\tfor (let span = 1; span < rowspan; span++) {\r\n\t\t\tif (!spannedCells[rowIndex + span]) {\r\n\t\t\t\tspannedCells[rowIndex + span] = [];\r\n\t\t\t}\r\n\t\t\tspannedCells[rowIndex + span][colIndex] = content;\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static applySpannedCells(spannedCells: Record<number, Cell[]>, rowIndex: number, columns: Cell[]): void {\r\n\t\tif (spannedCells[rowIndex]) {\r\n\t\t\tspannedCells[rowIndex].forEach((spannedContent, colIndex) => {\r\n\t\t\t\tif (spannedContent !== undefined) {\r\n\t\t\t\t\tcolumns[colIndex] = spannedContent;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n}\r\n","import { Locator } from \"@playwright/test\";\r\nimport { HeaderRow } from \"./row\";\r\nimport { CellContentType } from \"./cell-content-type\";\r\nimport { TableUtils } from \"./table-utils\";\r\n\r\nexport type HeaderRowOptions = {\r\n\tcellContentType?: CellContentType;\r\n\temptyCellReplacement?: boolean;\r\n\tduplicateSuffix?: boolean;\r\n\tcolspan?: { enabled?: boolean; suffix?: boolean };\r\n};\r\n\r\nexport abstract class TableHeader {\r\n\tstatic async getRows(\r\n\t\theaderRowLocator: Locator,\r\n\t\tcolumnsSelector: string,\r\n\t\theaderRowOptions?: HeaderRowOptions\r\n\t): Promise<HeaderRow[]> {\r\n\t\tconst options = this.getDefaultOptions(headerRowOptions);\r\n\t\tconst rows = await headerRowLocator.all();\r\n\t\tconst headerRows: HeaderRow[] = [];\r\n\t\tconst rowSpans: Map<number, string> = new Map();\r\n\r\n\t\tfor (const row of rows) {\r\n\t\t\tconst headerRow = await this.processRow(row, columnsSelector, rowSpans, options);\r\n\t\t\theaderRows.push(headerRow);\r\n\t\t}\r\n\r\n\t\tthis.applyColspanOptions(headerRows, options);\r\n\t\tthis.applyDuplicateSuffix(headerRows, options);\r\n\r\n\t\treturn headerRows;\r\n\t}\r\n\r\n\tprivate static getDefaultOptions(options?: HeaderRowOptions): Required<HeaderRowOptions> {\r\n\t\treturn {\r\n\t\t\tcellContentType: options?.cellContentType ?? CellContentType.InnerText,\r\n\t\t\temptyCellReplacement: options?.emptyCellReplacement ?? false,\r\n\t\t\tduplicateSuffix: options?.duplicateSuffix ?? false,\r\n\t\t\tcolspan: {\r\n\t\t\t\tenabled: options?.colspan?.enabled ?? false,\r\n\t\t\t\tsuffix: options?.colspan?.suffix ?? false,\r\n\t\t\t},\r\n\t\t};\r\n\t}\r\n\r\n\tprivate static async processRow(\r\n\t\trow: Locator,\r\n\t\tcolumnsSelector: string,\r\n\t\trowSpans: Map<number, string>,\r\n\t\toptions: Required<HeaderRowOptions>\r\n\t): Promise<HeaderRow> {\r\n\t\tconst headerRow: HeaderRow = [];\r\n\t\tconst cells = await row.locator(columnsSelector).all();\r\n\t\tlet columnIndex = 0;\r\n\r\n\t\tfor (const cell of cells) {\r\n\t\t\tcolumnIndex = await this.processCell(cell, headerRow, rowSpans, columnIndex, options);\r\n\t\t}\r\n\r\n\t\tthis.addRemainingRowSpans(headerRow, rowSpans, columnIndex);\r\n\t\treturn headerRow;\r\n\t}\r\n\r\n\tprivate static async processCell(\r\n\t\tcell: Locator,\r\n\t\theaderRow: HeaderRow,\r\n\t\trowSpans: Map<number, string>,\r\n\t\tcolumnIndex: number,\r\n\t\toptions: Required<HeaderRowOptions>\r\n\t): Promise<number> {\r\n\t\twhile (rowSpans.has(columnIndex)) {\r\n\t\t\theaderRow.push(rowSpans.get(columnIndex)!);\r\n\t\t\trowSpans.delete(columnIndex);\r\n\t\t\tcolumnIndex++;\r\n\t\t}\r\n\r\n\t\tlet text = await TableUtils.getCellContent(cell, options.cellContentType);\r\n\t\tif (!text && options.emptyCellReplacement) {\r\n\t\t\ttext = \"{{Empty}}\";\r\n\t\t}\r\n\r\n\t\tconst { colspan, rowspan } = await TableUtils.parseSpanAttributes(cell);\r\n\r\n\t\theaderRow.push(text);\r\n\t\tthis.handleColspan(headerRow, text, colspan);\r\n\t\tthis.handleRowspan(rowSpans, text, columnIndex, colspan, rowspan);\r\n\r\n\t\treturn columnIndex + colspan;\r\n\t}\r\n\r\n\tprivate static handleColspan(headerRow: HeaderRow, text: string, colspan: number): void {\r\n\t\tfor (let i = 1; i < colspan; i++) {\r\n\t\t\theaderRow.push(`${text}__C${i}`);\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static handleRowspan(\r\n\t\trowSpans: Map<number, string>,\r\n\t\ttext: string,\r\n\t\tcolumnIndex: number,\r\n\t\tcolspan: number,\r\n\t\trowspan: number\r\n\t): void {\r\n\t\tif (rowspan > 1) {\r\n\t\t\tfor (let i = 0; i < colspan; i++) {\r\n\t\t\t\trowSpans.set(columnIndex + i, text);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static addRemainingRowSpans(headerRow: HeaderRow, rowSpans: Map<number, string>, columnIndex: number): void {\r\n\t\twhile (rowSpans.has(columnIndex)) {\r\n\t\t\theaderRow.push(rowSpans.get(columnIndex)!);\r\n\t\t\trowSpans.delete(columnIndex);\r\n\t\t\tcolumnIndex++;\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static applyColspanOptions(headerRows: HeaderRow[], options: Required<HeaderRowOptions>): void {\r\n\t\tif (!options.colspan.enabled) {\r\n\t\t\tthis.removeColspanCells(headerRows);\r\n\t\t}\r\n\r\n\t\tif (!options.colspan.suffix) {\r\n\t\t\tthis.removeColspanSuffix(headerRows);\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static removeColspanCells(headerRows: HeaderRow[]): void {\r\n\t\tfor (const headerRow of headerRows) {\r\n\t\t\tfor (let i = 0; i < headerRow.length; i++) {\r\n\t\t\t\tif (/__C\\d/.test(headerRow[i])) {\r\n\t\t\t\t\theaderRow.splice(i, 1);\r\n\t\t\t\t\ti--;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static removeColspanSuffix(headerRows: HeaderRow[]): void {\r\n\t\tfor (const headerRow of headerRows) {\r\n\t\t\tfor (let i = 0; i < headerRow.length; i++) {\r\n\t\t\t\tif (/__C\\d/.test(headerRow[i])) {\r\n\t\t\t\t\theaderRow[i] = headerRow[i].replace(/__C\\d/, \"\");\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static applyDuplicateSuffix(headerRows: HeaderRow[], options: Required<HeaderRowOptions>): void {\r\n\t\tif (!options.duplicateSuffix) return;\r\n\r\n\t\tfor (const headerRow of headerRows) {\r\n\t\t\tconst headerCountMap: Map<string, number> = new Map();\r\n\t\t\tfor (let i = 0; i < headerRow.length; i++) {\r\n\t\t\t\tconst header = headerRow[i];\r\n\t\t\t\tif (headerCountMap.has(header)) {\r\n\t\t\t\t\tconst count = headerCountMap.get(header)!;\r\n\t\t\t\t\theaderRow[i] = `${header}__D${count}`;\r\n\t\t\t\t\theaderCountMap.set(header, count + 1);\r\n\t\t\t\t} else {\r\n\t\t\t\t\theaderCountMap.set(header, 1);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n","import { Locator, expect } from \"@playwright/test\";\r\n\r\nexport enum RowKind {\r\n\tHeader = \"header\",\r\n\tBody = \"body\",\r\n}\r\n\r\nexport abstract class TableWait {\r\n\tstatic async waitForRows(\r\n\t\trowLocator: Locator,\r\n\t\tcellSelector: string,\r\n\t\trowKind: RowKind,\r\n\t\toptions?: {\r\n\t\t\trow?: {\r\n\t\t\t\tamount?: number;\r\n\t\t\t\tcell?: {\r\n\t\t\t\t\ttotalCount?: number;\r\n\t\t\t\t\tcontentCount?: number;\r\n\t\t\t\t};\r\n\t\t\t};\r\n\t\t}\r\n\t): Promise<void> {\r\n\t\tconst validateCellsWithContent = async (): Promise<void> => {\r\n\t\t\tconst cells = await rowLocator.locator(cellSelector).all();\r\n\t\t\tconst cellsWithContent = (\r\n\t\t\t\tawait Promise.all(\r\n\t\t\t\t\tcells.map(async cell => {\r\n\t\t\t\t\t\tconst content = await cell.textContent();\r\n\t\t\t\t\t\treturn content !== null && content.trim() !== \"\" ? cell : null;\r\n\t\t\t\t\t})\r\n\t\t\t\t)\r\n\t\t\t).filter(cell => cell !== null);\r\n\t\t\texpect(cellsWithContent.length, `No ${rowKind} cells with content found`).toBeGreaterThan(0);\r\n\t\t};\r\n\r\n\t\tconst validateRowAmount = (rows: Locator[], expectedAmount: number): void => {\r\n\t\t\texpect(rows.length, `Expected ${expectedAmount} ${rowKind} rows, but found ${rows.length}`).toBe(expectedAmount);\r\n\t\t};\r\n\r\n\t\tconst validateCellCount = async (rows: Locator[], expectedCount: number): Promise<void> => {\r\n\t\t\tconst rowsWithMatchingCells = (\r\n\t\t\t\tawait Promise.all(\r\n\t\t\t\t\trows.map(async row => {\r\n\t\t\t\t\t\tconst cellCount = await row.locator(cellSelector).count();\r\n\t\t\t\t\t\treturn cellCount === expectedCount ? row : null;\r\n\t\t\t\t\t})\r\n\t\t\t\t)\r\n\t\t\t).filter(row => row !== null);\r\n\t\t\texpect(\r\n\t\t\t\trowsWithMatchingCells.length,\r\n\t\t\t\t`Expected amount of ${expectedCount} ${rowKind} cells for row not found`\r\n\t\t\t).toBeGreaterThan(0);\r\n\t\t};\r\n\r\n\t\tconst validateCellContentCount = async (rows: Locator[], expectedContentCount: number): Promise<void> => {\r\n\t\t\tconst rowsWithMatchingContent = (\r\n\t\t\t\tawait Promise.all(\r\n\t\t\t\t\trows.map(async row => {\r\n\t\t\t\t\t\tconst cells = await row.locator(cellSelector).all();\r\n\t\t\t\t\t\tconst cellsWithContent = (\r\n\t\t\t\t\t\t\tawait Promise.all(\r\n\t\t\t\t\t\t\t\tcells.map(async cell => {\r\n\t\t\t\t\t\t\t\t\tconst content = await cell.textContent();\r\n\t\t\t\t\t\t\t\t\treturn content !== null && content.trim() !== \"\" ? cell : null;\r\n\t\t\t\t\t\t\t\t})\r\n\t\t\t\t\t\t\t)\r\n\t\t\t\t\t\t).filter(cell => cell !== null);\r\n\t\t\t\t\t\treturn cellsWithContent.length === expectedContentCount ? row : null;\r\n\t\t\t\t\t})\r\n\t\t\t\t)\r\n\t\t\t).filter(row => row !== null);\r\n\t\t\texpect(\r\n\t\t\t\trowsWithMatchingContent.length,\r\n\t\t\t\t`Expected amount of ${expectedContentCount} ${rowKind} cells with content for row not found`\r\n\t\t\t).toBeGreaterThan(0);\r\n\t\t};\r\n\r\n\t\tconst rows = await rowLocator.all();\r\n\r\n\t\tif (options?.row) {\r\n\t\t\tif (options.row.amount) {\r\n\t\t\t\tvalidateRowAmount(rows, options.row.amount);\r\n\t\t\t} else {\r\n\t\t\t\texpect(rows.length, `No ${rowKind} rows found`).toBeGreaterThan(0);\r\n\t\t\t}\r\n\r\n\t\t\tif (options.row.cell) {\r\n\t\t\t\tif (options.row.cell.totalCount) {\r\n\t\t\t\t\tawait validateCellCount(rows, options.row.cell.totalCount);\r\n\t\t\t\t}\r\n\t\t\t\tif (options.row.cell.contentCount) {\r\n\t\t\t\t\tawait validateCellContentCount(rows, options.row.cell.contentCount);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tawait validateCellsWithContent();\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tawait validateCellsWithContent();\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tawait validateCellsWithContent();\r\n\t\t}\r\n\t}\r\n}\r\n"],"mappings":"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","names":["import_test","CellContentType","rows"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,417 @@
1
+ // src/playwright-table.ts
2
+ import { expect as expect2 } from "@playwright/test";
3
+
4
+ // src/cell-content-type.ts
5
+ var CellContentType = /* @__PURE__ */ ((CellContentType2) => {
6
+ CellContentType2["TextContent"] = "textContent";
7
+ CellContentType2["InnerText"] = "innerText";
8
+ return CellContentType2;
9
+ })(CellContentType || {});
10
+
11
+ // src/table-utils.ts
12
+ var TableUtils = class {
13
+ static async getCellContent(cell, cellContentType) {
14
+ const content = cellContentType === "innerText" /* InnerText */ ? await cell.innerText() : await cell.textContent();
15
+ return (content == null ? void 0 : content.trim()) || "";
16
+ }
17
+ static async parseSpanAttributes(cell) {
18
+ return {
19
+ rowspan: parseInt(await cell.getAttribute("rowspan") || "1", 10),
20
+ colspan: parseInt(await cell.getAttribute("colspan") || "1", 10)
21
+ };
22
+ }
23
+ static castContent(value) {
24
+ const trimmedValue = value.trim();
25
+ if (trimmedValue === "") return "";
26
+ const lowerValue = trimmedValue.toLowerCase();
27
+ if (lowerValue === "true") return true;
28
+ if (lowerValue === "false") return false;
29
+ const num = Number(trimmedValue);
30
+ return isNaN(num) ? trimmedValue : num;
31
+ }
32
+ };
33
+
34
+ // src/table-body.ts
35
+ var TableBody = class {
36
+ static async getRows(rowLocator, columnsSelector, bodyRowsOptions) {
37
+ const rows = [];
38
+ const rowsCount = await rowLocator.count();
39
+ const spannedCells = {};
40
+ for (let rowIndex = 0; rowIndex < rowsCount; rowIndex++) {
41
+ const row = rowLocator.nth(rowIndex);
42
+ const columns = await this.extractColumns(
43
+ row,
44
+ columnsSelector,
45
+ rowIndex,
46
+ spannedCells,
47
+ bodyRowsOptions == null ? void 0 : bodyRowsOptions.cellContentType
48
+ );
49
+ rows.push(columns);
50
+ }
51
+ return rows;
52
+ }
53
+ static async extractColumns(row, columnsSelector, rowIndex, spannedCells, cellContentType) {
54
+ const columns = [];
55
+ const columnLocators = row.locator(columnsSelector);
56
+ const columnCount = await columnLocators.count();
57
+ for (let colIndex = 0; colIndex < columnCount; colIndex++) {
58
+ await this.processColumn(
59
+ columnLocators.nth(colIndex),
60
+ colIndex,
61
+ columns,
62
+ rowIndex,
63
+ spannedCells,
64
+ cellContentType
65
+ );
66
+ }
67
+ this.applySpannedCells(spannedCells, rowIndex, columns);
68
+ return columns;
69
+ }
70
+ static async processColumn(column, colIndex, columns, rowIndex, spannedCells, cellContentType = "innerText" /* InnerText */) {
71
+ const content = await TableUtils.getCellContent(column, cellContentType);
72
+ const castedContent = TableUtils.castContent(content);
73
+ const { rowspan, colspan } = await TableUtils.parseSpanAttributes(column);
74
+ for (let span = 0; span < colspan; span++) {
75
+ columns[colIndex + span] = castedContent;
76
+ }
77
+ if (rowspan > 1) {
78
+ this.storeSpannedCells(rowIndex, colIndex, rowspan, castedContent, spannedCells);
79
+ }
80
+ }
81
+ static storeSpannedCells(rowIndex, colIndex, rowspan, content, spannedCells) {
82
+ for (let span = 1; span < rowspan; span++) {
83
+ if (!spannedCells[rowIndex + span]) {
84
+ spannedCells[rowIndex + span] = [];
85
+ }
86
+ spannedCells[rowIndex + span][colIndex] = content;
87
+ }
88
+ }
89
+ static applySpannedCells(spannedCells, rowIndex, columns) {
90
+ if (spannedCells[rowIndex]) {
91
+ spannedCells[rowIndex].forEach((spannedContent, colIndex) => {
92
+ if (spannedContent !== void 0) {
93
+ columns[colIndex] = spannedContent;
94
+ }
95
+ });
96
+ }
97
+ }
98
+ };
99
+
100
+ // src/table-header.ts
101
+ var TableHeader = class {
102
+ static async getRows(headerRowLocator, columnsSelector, headerRowOptions) {
103
+ const options = this.getDefaultOptions(headerRowOptions);
104
+ const rows = await headerRowLocator.all();
105
+ const headerRows = [];
106
+ const rowSpans = /* @__PURE__ */ new Map();
107
+ for (const row of rows) {
108
+ const headerRow = await this.processRow(row, columnsSelector, rowSpans, options);
109
+ headerRows.push(headerRow);
110
+ }
111
+ this.applyColspanOptions(headerRows, options);
112
+ this.applyDuplicateSuffix(headerRows, options);
113
+ return headerRows;
114
+ }
115
+ static getDefaultOptions(options) {
116
+ var _a, _b, _c, _d, _e, _f, _g;
117
+ return {
118
+ cellContentType: (_a = options == null ? void 0 : options.cellContentType) != null ? _a : "innerText" /* InnerText */,
119
+ emptyCellReplacement: (_b = options == null ? void 0 : options.emptyCellReplacement) != null ? _b : false,
120
+ duplicateSuffix: (_c = options == null ? void 0 : options.duplicateSuffix) != null ? _c : false,
121
+ colspan: {
122
+ enabled: (_e = (_d = options == null ? void 0 : options.colspan) == null ? void 0 : _d.enabled) != null ? _e : false,
123
+ suffix: (_g = (_f = options == null ? void 0 : options.colspan) == null ? void 0 : _f.suffix) != null ? _g : false
124
+ }
125
+ };
126
+ }
127
+ static async processRow(row, columnsSelector, rowSpans, options) {
128
+ const headerRow = [];
129
+ const cells = await row.locator(columnsSelector).all();
130
+ let columnIndex = 0;
131
+ for (const cell of cells) {
132
+ columnIndex = await this.processCell(cell, headerRow, rowSpans, columnIndex, options);
133
+ }
134
+ this.addRemainingRowSpans(headerRow, rowSpans, columnIndex);
135
+ return headerRow;
136
+ }
137
+ static async processCell(cell, headerRow, rowSpans, columnIndex, options) {
138
+ while (rowSpans.has(columnIndex)) {
139
+ headerRow.push(rowSpans.get(columnIndex));
140
+ rowSpans.delete(columnIndex);
141
+ columnIndex++;
142
+ }
143
+ let text = await TableUtils.getCellContent(cell, options.cellContentType);
144
+ if (!text && options.emptyCellReplacement) {
145
+ text = "{{Empty}}";
146
+ }
147
+ const { colspan, rowspan } = await TableUtils.parseSpanAttributes(cell);
148
+ headerRow.push(text);
149
+ this.handleColspan(headerRow, text, colspan);
150
+ this.handleRowspan(rowSpans, text, columnIndex, colspan, rowspan);
151
+ return columnIndex + colspan;
152
+ }
153
+ static handleColspan(headerRow, text, colspan) {
154
+ for (let i = 1; i < colspan; i++) {
155
+ headerRow.push(`${text}__C${i}`);
156
+ }
157
+ }
158
+ static handleRowspan(rowSpans, text, columnIndex, colspan, rowspan) {
159
+ if (rowspan > 1) {
160
+ for (let i = 0; i < colspan; i++) {
161
+ rowSpans.set(columnIndex + i, text);
162
+ }
163
+ }
164
+ }
165
+ static addRemainingRowSpans(headerRow, rowSpans, columnIndex) {
166
+ while (rowSpans.has(columnIndex)) {
167
+ headerRow.push(rowSpans.get(columnIndex));
168
+ rowSpans.delete(columnIndex);
169
+ columnIndex++;
170
+ }
171
+ }
172
+ static applyColspanOptions(headerRows, options) {
173
+ if (!options.colspan.enabled) {
174
+ this.removeColspanCells(headerRows);
175
+ }
176
+ if (!options.colspan.suffix) {
177
+ this.removeColspanSuffix(headerRows);
178
+ }
179
+ }
180
+ static removeColspanCells(headerRows) {
181
+ for (const headerRow of headerRows) {
182
+ for (let i = 0; i < headerRow.length; i++) {
183
+ if (/__C\d/.test(headerRow[i])) {
184
+ headerRow.splice(i, 1);
185
+ i--;
186
+ }
187
+ }
188
+ }
189
+ }
190
+ static removeColspanSuffix(headerRows) {
191
+ for (const headerRow of headerRows) {
192
+ for (let i = 0; i < headerRow.length; i++) {
193
+ if (/__C\d/.test(headerRow[i])) {
194
+ headerRow[i] = headerRow[i].replace(/__C\d/, "");
195
+ }
196
+ }
197
+ }
198
+ }
199
+ static applyDuplicateSuffix(headerRows, options) {
200
+ if (!options.duplicateSuffix) return;
201
+ for (const headerRow of headerRows) {
202
+ const headerCountMap = /* @__PURE__ */ new Map();
203
+ for (let i = 0; i < headerRow.length; i++) {
204
+ const header = headerRow[i];
205
+ if (headerCountMap.has(header)) {
206
+ const count = headerCountMap.get(header);
207
+ headerRow[i] = `${header}__D${count}`;
208
+ headerCountMap.set(header, count + 1);
209
+ } else {
210
+ headerCountMap.set(header, 1);
211
+ }
212
+ }
213
+ }
214
+ }
215
+ };
216
+
217
+ // src/table-wait.ts
218
+ import { expect } from "@playwright/test";
219
+ var TableWait = class {
220
+ static async waitForRows(rowLocator, cellSelector, rowKind, options) {
221
+ const validateCellsWithContent = async () => {
222
+ const cells = await rowLocator.locator(cellSelector).all();
223
+ const cellsWithContent = (await Promise.all(
224
+ cells.map(async (cell) => {
225
+ const content = await cell.textContent();
226
+ return content !== null && content.trim() !== "" ? cell : null;
227
+ })
228
+ )).filter((cell) => cell !== null);
229
+ expect(cellsWithContent.length, `No ${rowKind} cells with content found`).toBeGreaterThan(0);
230
+ };
231
+ const validateRowAmount = (rows2, expectedAmount) => {
232
+ expect(rows2.length, `Expected ${expectedAmount} ${rowKind} rows, but found ${rows2.length}`).toBe(expectedAmount);
233
+ };
234
+ const validateCellCount = async (rows2, expectedCount) => {
235
+ const rowsWithMatchingCells = (await Promise.all(
236
+ rows2.map(async (row) => {
237
+ const cellCount = await row.locator(cellSelector).count();
238
+ return cellCount === expectedCount ? row : null;
239
+ })
240
+ )).filter((row) => row !== null);
241
+ expect(
242
+ rowsWithMatchingCells.length,
243
+ `Expected amount of ${expectedCount} ${rowKind} cells for row not found`
244
+ ).toBeGreaterThan(0);
245
+ };
246
+ const validateCellContentCount = async (rows2, expectedContentCount) => {
247
+ const rowsWithMatchingContent = (await Promise.all(
248
+ rows2.map(async (row) => {
249
+ const cells = await row.locator(cellSelector).all();
250
+ const cellsWithContent = (await Promise.all(
251
+ cells.map(async (cell) => {
252
+ const content = await cell.textContent();
253
+ return content !== null && content.trim() !== "" ? cell : null;
254
+ })
255
+ )).filter((cell) => cell !== null);
256
+ return cellsWithContent.length === expectedContentCount ? row : null;
257
+ })
258
+ )).filter((row) => row !== null);
259
+ expect(
260
+ rowsWithMatchingContent.length,
261
+ `Expected amount of ${expectedContentCount} ${rowKind} cells with content for row not found`
262
+ ).toBeGreaterThan(0);
263
+ };
264
+ const rows = await rowLocator.all();
265
+ if (options == null ? void 0 : options.row) {
266
+ if (options.row.amount) {
267
+ validateRowAmount(rows, options.row.amount);
268
+ } else {
269
+ expect(rows.length, `No ${rowKind} rows found`).toBeGreaterThan(0);
270
+ }
271
+ if (options.row.cell) {
272
+ if (options.row.cell.totalCount) {
273
+ await validateCellCount(rows, options.row.cell.totalCount);
274
+ }
275
+ if (options.row.cell.contentCount) {
276
+ await validateCellContentCount(rows, options.row.cell.contentCount);
277
+ } else {
278
+ await validateCellsWithContent();
279
+ }
280
+ } else {
281
+ await validateCellsWithContent();
282
+ }
283
+ } else {
284
+ await validateCellsWithContent();
285
+ }
286
+ }
287
+ };
288
+
289
+ // src/playwright-table.ts
290
+ var PlaywrightTable = class {
291
+ constructor(_tableLocator, _options) {
292
+ this._tableLocator = _tableLocator;
293
+ this._options = _options;
294
+ this._headers = [];
295
+ this._rows = [];
296
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
297
+ this._headerRowLocator = this._tableLocator.locator((_c = (_b = (_a = this._options) == null ? void 0 : _a.header) == null ? void 0 : _b.rowSelector) != null ? _c : "thead>tr");
298
+ this._headerColumnSelector = (_f = (_e = (_d = this._options) == null ? void 0 : _d.header) == null ? void 0 : _e.columnSelector) != null ? _f : "th";
299
+ this._bodyRowLocator = this._tableLocator.locator((_i = (_h = (_g = this._options) == null ? void 0 : _g.row) == null ? void 0 : _h.rowSelector) != null ? _i : "tbody>tr");
300
+ this._bodyRowColumnSelector = (_l = (_k = (_j = this._options) == null ? void 0 : _j.row) == null ? void 0 : _k.columnSelector) != null ? _l : "td";
301
+ }
302
+ async getHeaderRows(options) {
303
+ await this.load(options);
304
+ return this._headers;
305
+ }
306
+ async getMainHeaderRow(options) {
307
+ var _a, _b;
308
+ const headerRows = await this.getHeaderRows(options);
309
+ const headers = ((_b = (_a = this._options) == null ? void 0 : _a.header) == null ? void 0 : _b.setMainHeaderRow) ? headerRows[this._options.header.setMainHeaderRow] : headerRows[this._headers.length - 1];
310
+ return headers;
311
+ }
312
+ async getBodyRows(options) {
313
+ await this.load({ ...options, headerRowOptions: { colspan: { enabled: true } } });
314
+ return this._rows;
315
+ }
316
+ getBodyCellLocator(rowNumber, headerPosition) {
317
+ return this._bodyRowLocator.nth(rowNumber).locator(this._bodyRowColumnSelector).nth(headerPosition);
318
+ }
319
+ async getBodyCellLocatorByRowConditions(conditions, targetHeader, options) {
320
+ await this.load(options);
321
+ const headers = await this.getMainHeaderRow();
322
+ const targetHeaderIndex = headers.indexOf(targetHeader);
323
+ if (targetHeaderIndex === -1) {
324
+ throw new Error(`Header "${targetHeader}" not found.`);
325
+ }
326
+ for (let rowIndex = 0; rowIndex < this._rows.length; rowIndex++) {
327
+ const row = this._rows[rowIndex];
328
+ let matches = true;
329
+ for (const [header, value] of Object.entries(conditions)) {
330
+ const headerIndex = headers.indexOf(header);
331
+ if (headerIndex === -1) {
332
+ throw new Error(`Header "${header}" not found.`);
333
+ }
334
+ if (row[headerIndex] !== value) {
335
+ matches = false;
336
+ break;
337
+ }
338
+ }
339
+ if (matches) {
340
+ return this.getBodyCellLocator(rowIndex, targetHeaderIndex);
341
+ }
342
+ }
343
+ throw new Error(`No row found matching conditions: ${JSON.stringify(conditions)}`);
344
+ }
345
+ async getAllBodyCellLocatorsByHeaderName(header, options) {
346
+ await this.load(options);
347
+ const headers = await this.getMainHeaderRow();
348
+ const headerIndex = headers.indexOf(header);
349
+ if (headerIndex === -1) {
350
+ throw new Error(`Header "${header}" not found.`);
351
+ }
352
+ const locators = [];
353
+ for (let rowIndex = 0; rowIndex < this._rows.length; rowIndex++) {
354
+ const cellLocator = this.getBodyCellLocator(rowIndex, headerIndex);
355
+ locators.push(cellLocator);
356
+ }
357
+ return locators;
358
+ }
359
+ async getAllBodyCellLocatorsByHeaderIndex(headerIndex) {
360
+ await this.load();
361
+ const locators = [];
362
+ for (let rowIndex = 0; rowIndex < this._rows.length; rowIndex++) {
363
+ const cellLocator = this.getBodyCellLocator(rowIndex, headerIndex);
364
+ locators.push(cellLocator);
365
+ }
366
+ return locators;
367
+ }
368
+ async getJson(options) {
369
+ const headers = await this.getMainHeaderRow({
370
+ timeout: options == null ? void 0 : options.timeout,
371
+ duplicateSuffix: true,
372
+ headerRowOptions: {
373
+ colspan: { enabled: true, suffix: true },
374
+ duplicateSuffix: true,
375
+ emptyCellReplacement: true
376
+ }
377
+ });
378
+ return this._rows.map((row) => {
379
+ const rowObj = {};
380
+ headers.forEach((header, index) => {
381
+ rowObj[header] = row[index] || "";
382
+ });
383
+ return rowObj;
384
+ });
385
+ }
386
+ async waitForHeaderRows(options) {
387
+ await expect2(
388
+ async () => await TableWait.waitForRows(this._headerRowLocator, this._headerColumnSelector, "header" /* Header */, options)
389
+ ).toPass({
390
+ timeout: options == null ? void 0 : options.timeout
391
+ });
392
+ }
393
+ async waitForBodyRows(options) {
394
+ await expect2(
395
+ async () => await TableWait.waitForRows(this._bodyRowLocator, this._bodyRowColumnSelector, "body" /* Body */, options)
396
+ ).toPass({
397
+ timeout: options == null ? void 0 : options.timeout
398
+ });
399
+ }
400
+ async load(options) {
401
+ await expect2(async () => {
402
+ await TableWait.waitForRows(this._headerRowLocator, this._headerColumnSelector, "header" /* Header */);
403
+ await TableWait.waitForRows(this._bodyRowLocator, this._bodyRowColumnSelector, "body" /* Body */);
404
+ }).toPass({ timeout: options == null ? void 0 : options.timeout });
405
+ this._headers = await TableHeader.getRows(
406
+ this._headerRowLocator,
407
+ this._headerColumnSelector,
408
+ options == null ? void 0 : options.headerRowOptions
409
+ );
410
+ this._rows = await TableBody.getRows(this._bodyRowLocator, this._bodyRowColumnSelector);
411
+ }
412
+ };
413
+ export {
414
+ CellContentType,
415
+ PlaywrightTable
416
+ };
417
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/playwright-table.ts","../src/cell-content-type.ts","../src/table-utils.ts","../src/table-body.ts","../src/table-header.ts","../src/table-wait.ts"],"sourcesContent":["import { expect, Locator } from \"@playwright/test\";\r\nimport { TableBody } from \"./table-body\";\r\nimport { BodyRow, Cell, HeaderRow } from \"./row\";\r\nimport { HeaderRowOptions, TableHeader } from \"./table-header\";\r\nimport { RowKind, TableWait } from \"./table-wait\";\r\n\r\nexport class PlaywrightTable {\r\n\tprivate _headers: HeaderRow[] = [];\r\n\tprivate _rows: BodyRow[] = [];\r\n\tprivate _bodyRowLocator: Locator;\r\n\tprivate _bodyRowColumnSelector: string;\r\n\tprivate _headerRowLocator: Locator;\r\n\tprivate _headerColumnSelector: string;\r\n\r\n\tconstructor(\r\n\t\tprivate readonly _tableLocator: Locator,\r\n\t\tprivate readonly _options?: {\r\n\t\t\theader?: {\r\n\t\t\t\tsetMainHeaderRow?: number;\r\n\t\t\t\trowSelector?: string;\r\n\t\t\t\tcolumnSelector?: string;\r\n\t\t\t};\r\n\t\t\trow?: {\r\n\t\t\t\trowSelector?: string;\r\n\t\t\t\tcolumnSelector?: string;\r\n\t\t\t};\r\n\t\t}\r\n\t) {\r\n\t\tthis._headerRowLocator = this._tableLocator.locator(this._options?.header?.rowSelector ?? \"thead>tr\");\r\n\t\tthis._headerColumnSelector = this._options?.header?.columnSelector ?? \"th\";\r\n\t\tthis._bodyRowLocator = this._tableLocator.locator(this._options?.row?.rowSelector ?? \"tbody>tr\");\r\n\t\tthis._bodyRowColumnSelector = this._options?.row?.columnSelector ?? \"td\";\r\n\t}\r\n\r\n\tasync getHeaderRows(options?: {\r\n\t\ttimeout?: number;\r\n\t\tduplicateSuffix?: boolean;\r\n\t\theaderRowOptions?: HeaderRowOptions;\r\n\t}): Promise<HeaderRow[]> {\r\n\t\tawait this.load(options);\r\n\t\treturn this._headers;\r\n\t}\r\n\r\n\tasync getMainHeaderRow(options?: {\r\n\t\ttimeout?: number;\r\n\t\tduplicateSuffix?: boolean;\r\n\t\theaderRowOptions?: HeaderRowOptions;\r\n\t}): Promise<HeaderRow> {\r\n\t\tconst headerRows = await this.getHeaderRows(options);\r\n\t\tconst headers = this._options?.header?.setMainHeaderRow\r\n\t\t\t? headerRows[this._options.header.setMainHeaderRow]\r\n\t\t\t: headerRows[this._headers.length - 1];\r\n\t\treturn headers;\r\n\t}\r\n\r\n\tasync getBodyRows(options?: { timeout?: number }): Promise<BodyRow[]> {\r\n\t\tawait this.load({ ...options, headerRowOptions: { colspan: { enabled: true } } });\r\n\t\treturn this._rows;\r\n\t}\r\n\r\n\tgetBodyCellLocator(rowNumber: number, headerPosition: number): Locator {\r\n\t\treturn this._bodyRowLocator.nth(rowNumber).locator(this._bodyRowColumnSelector).nth(headerPosition);\r\n\t}\r\n\r\n\tasync getBodyCellLocatorByRowConditions(\r\n\t\tconditions: Record<string, string>,\r\n\t\ttargetHeader: string,\r\n\t\toptions?: { timeout?: number; duplicateSuffix?: boolean; colspanEnabled?: boolean }\r\n\t): Promise<Locator> {\r\n\t\tawait this.load(options);\r\n\t\tconst headers = await this.getMainHeaderRow();\r\n\r\n\t\tconst targetHeaderIndex = headers.indexOf(targetHeader);\r\n\t\tif (targetHeaderIndex === -1) {\r\n\t\t\tthrow new Error(`Header \"${targetHeader}\" not found.`);\r\n\t\t}\r\n\r\n\t\tfor (let rowIndex = 0; rowIndex < this._rows.length; rowIndex++) {\r\n\t\t\tconst row = this._rows[rowIndex];\r\n\t\t\tlet matches = true;\r\n\r\n\t\t\tfor (const [header, value] of Object.entries(conditions)) {\r\n\t\t\t\tconst headerIndex = headers.indexOf(header);\r\n\t\t\t\tif (headerIndex === -1) {\r\n\t\t\t\t\tthrow new Error(`Header \"${header}\" not found.`);\r\n\t\t\t\t}\r\n\t\t\t\tif (row[headerIndex] !== value) {\r\n\t\t\t\t\tmatches = false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (matches) {\r\n\t\t\t\treturn this.getBodyCellLocator(rowIndex, targetHeaderIndex);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthrow new Error(`No row found matching conditions: ${JSON.stringify(conditions)}`);\r\n\t}\r\n\r\n\tasync getAllBodyCellLocatorsByHeaderName(header: string, options?: { timeout?: number }): Promise<Locator[]> {\r\n\t\tawait this.load(options);\r\n\t\tconst headers = await this.getMainHeaderRow();\r\n\t\tconst headerIndex = headers.indexOf(header);\r\n\t\tif (headerIndex === -1) {\r\n\t\t\tthrow new Error(`Header \"${header}\" not found.`);\r\n\t\t}\r\n\t\tconst locators: Locator[] = [];\r\n\t\tfor (let rowIndex = 0; rowIndex < this._rows.length; rowIndex++) {\r\n\t\t\tconst cellLocator = this.getBodyCellLocator(rowIndex, headerIndex);\r\n\t\t\tlocators.push(cellLocator);\r\n\t\t}\r\n\t\treturn locators;\r\n\t}\r\n\r\n\tasync getAllBodyCellLocatorsByHeaderIndex(headerIndex: number): Promise<Locator[]> {\r\n\t\tawait this.load();\r\n\t\tconst locators: Locator[] = [];\r\n\t\tfor (let rowIndex = 0; rowIndex < this._rows.length; rowIndex++) {\r\n\t\t\tconst cellLocator = this.getBodyCellLocator(rowIndex, headerIndex);\r\n\t\t\tlocators.push(cellLocator);\r\n\t\t}\r\n\t\treturn locators;\r\n\t}\r\n\r\n\tasync getJson(options?: { timeout?: number }): Promise<any> {\r\n\t\tconst headers = await this.getMainHeaderRow({\r\n\t\t\ttimeout: options?.timeout,\r\n\t\t\tduplicateSuffix: true,\r\n\t\t\theaderRowOptions: {\r\n\t\t\t\tcolspan: { enabled: true, suffix: true },\r\n\t\t\t\tduplicateSuffix: true,\r\n\t\t\t\temptyCellReplacement: true,\r\n\t\t\t},\r\n\t\t});\r\n\t\treturn this._rows.map(row => {\r\n\t\t\tconst rowObj: Record<string, Cell> = {};\r\n\t\t\theaders.forEach((header, index) => {\r\n\t\t\t\trowObj[header] = row[index] || \"\";\r\n\t\t\t});\r\n\t\t\treturn rowObj;\r\n\t\t});\r\n\t}\r\n\r\n\tasync waitForHeaderRows(options?: {\r\n\t\ttimeout?: number;\r\n\t\trow?: {\r\n\t\t\tamount?: number;\r\n\t\t\tcell?: {\r\n\t\t\t\ttotalCount?: number;\r\n\t\t\t\tcontentCount?: number;\r\n\t\t\t};\r\n\t\t};\r\n\t}): Promise<void> {\r\n\t\tawait expect(\r\n\t\t\tasync () =>\r\n\t\t\t\tawait TableWait.waitForRows(this._headerRowLocator, this._headerColumnSelector, RowKind.Header, options)\r\n\t\t).toPass({\r\n\t\t\ttimeout: options?.timeout,\r\n\t\t});\r\n\t}\r\n\r\n\tasync waitForBodyRows(options?: {\r\n\t\ttimeout?: number;\r\n\t\trow?: {\r\n\t\t\tamount?: number;\r\n\t\t\tcell?: {\r\n\t\t\t\ttotalCount?: number;\r\n\t\t\t\tcontentCount?: number;\r\n\t\t\t};\r\n\t\t};\r\n\t}): Promise<void> {\r\n\t\tawait expect(\r\n\t\t\tasync () => await TableWait.waitForRows(this._bodyRowLocator, this._bodyRowColumnSelector, RowKind.Body, options)\r\n\t\t).toPass({\r\n\t\t\ttimeout: options?.timeout,\r\n\t\t});\r\n\t}\r\n\r\n\tprivate async load(options?: { timeout?: number; headerRowOptions?: HeaderRowOptions }): Promise<void> {\r\n\t\tawait expect(async () => {\r\n\t\t\tawait TableWait.waitForRows(this._headerRowLocator, this._headerColumnSelector, RowKind.Header);\r\n\t\t\tawait TableWait.waitForRows(this._bodyRowLocator, this._bodyRowColumnSelector, RowKind.Body);\r\n\t\t}).toPass({ timeout: options?.timeout });\r\n\r\n\t\tthis._headers = await TableHeader.getRows(\r\n\t\t\tthis._headerRowLocator,\r\n\t\t\tthis._headerColumnSelector,\r\n\t\t\toptions?.headerRowOptions\r\n\t\t);\r\n\t\tthis._rows = await TableBody.getRows(this._bodyRowLocator, this._bodyRowColumnSelector);\r\n\t}\r\n}\r\n","export enum CellContentType {\r\n\tTextContent = \"textContent\",\r\n\tInnerText = \"innerText\",\r\n}\r\n","import { Locator } from \"@playwright/test\";\r\nimport { CellContentType } from \"./cell-content-type\";\r\nimport { Cell } from \"./row\";\r\n\r\nexport abstract class TableUtils {\r\n\tstatic async getCellContent(cell: Locator, cellContentType: CellContentType): Promise<string> {\r\n\t\tconst content = cellContentType === CellContentType.InnerText ? await cell.innerText() : await cell.textContent();\r\n\t\treturn content?.trim() || \"\";\r\n\t}\r\n\r\n\tstatic async parseSpanAttributes(cell: Locator): Promise<{ rowspan: number; colspan: number }> {\r\n\t\treturn {\r\n\t\t\trowspan: parseInt((await cell.getAttribute(\"rowspan\")) || \"1\", 10),\r\n\t\t\tcolspan: parseInt((await cell.getAttribute(\"colspan\")) || \"1\", 10),\r\n\t\t};\r\n\t}\r\n\r\n\tstatic castContent(value: string): Cell {\r\n\t\tconst trimmedValue = value.trim();\r\n\r\n\t\tif (trimmedValue === \"\") return \"\";\r\n\r\n\t\tconst lowerValue = trimmedValue.toLowerCase();\r\n\r\n\t\tif (lowerValue === \"true\") return true;\r\n\t\tif (lowerValue === \"false\") return false;\r\n\r\n\t\tconst num = Number(trimmedValue);\r\n\t\treturn isNaN(num) ? trimmedValue : num;\r\n\t}\r\n}\r\n","import { Locator } from \"@playwright/test\";\r\nimport { BodyRow, Cell } from \"./row\";\r\nimport { CellContentType } from \"./cell-content-type\";\r\nimport { TableUtils } from \"./table-utils\";\r\n\r\nexport abstract class TableBody {\r\n\tstatic async getRows(\r\n\t\trowLocator: Locator,\r\n\t\tcolumnsSelector: string,\r\n\t\tbodyRowsOptions?: {\r\n\t\t\tcellContentType?: CellContentType;\r\n\t\t}\r\n\t): Promise<BodyRow[]> {\r\n\t\tconst rows: BodyRow[] = [];\r\n\t\tconst rowsCount = await rowLocator.count();\r\n\t\tconst spannedCells: Record<number, Cell[]> = {};\r\n\r\n\t\tfor (let rowIndex = 0; rowIndex < rowsCount; rowIndex++) {\r\n\t\t\tconst row = rowLocator.nth(rowIndex);\r\n\t\t\tconst columns = await this.extractColumns(\r\n\t\t\t\trow,\r\n\t\t\t\tcolumnsSelector,\r\n\t\t\t\trowIndex,\r\n\t\t\t\tspannedCells,\r\n\t\t\t\tbodyRowsOptions?.cellContentType\r\n\t\t\t);\r\n\t\t\trows.push(columns as BodyRow);\r\n\t\t}\r\n\r\n\t\treturn rows;\r\n\t}\r\n\r\n\tprivate static async extractColumns(\r\n\t\trow: Locator,\r\n\t\tcolumnsSelector: string,\r\n\t\trowIndex: number,\r\n\t\tspannedCells: Record<number, Cell[]>,\r\n\t\tcellContentType?: CellContentType\r\n\t): Promise<Cell[]> {\r\n\t\tconst columns: Cell[] = [];\r\n\t\tconst columnLocators = row.locator(columnsSelector);\r\n\t\tconst columnCount = await columnLocators.count();\r\n\r\n\t\tfor (let colIndex = 0; colIndex < columnCount; colIndex++) {\r\n\t\t\tawait this.processColumn(\r\n\t\t\t\tcolumnLocators.nth(colIndex),\r\n\t\t\t\tcolIndex,\r\n\t\t\t\tcolumns,\r\n\t\t\t\trowIndex,\r\n\t\t\t\tspannedCells,\r\n\t\t\t\tcellContentType\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tthis.applySpannedCells(spannedCells, rowIndex, columns);\r\n\r\n\t\treturn columns;\r\n\t}\r\n\r\n\tprivate static async processColumn(\r\n\t\tcolumn: Locator,\r\n\t\tcolIndex: number,\r\n\t\tcolumns: Cell[],\r\n\t\trowIndex: number,\r\n\t\tspannedCells: Record<number, Cell[]>,\r\n\t\tcellContentType: CellContentType = CellContentType.InnerText\r\n\t): Promise<void> {\r\n\t\tconst content = await TableUtils.getCellContent(column, cellContentType);\r\n\t\tconst castedContent = TableUtils.castContent(content);\r\n\r\n\t\tconst { rowspan, colspan } = await TableUtils.parseSpanAttributes(column);\r\n\r\n\t\tfor (let span = 0; span < colspan; span++) {\r\n\t\t\tcolumns[colIndex + span] = castedContent;\r\n\t\t}\r\n\r\n\t\tif (rowspan > 1) {\r\n\t\t\tthis.storeSpannedCells(rowIndex, colIndex, rowspan, castedContent, spannedCells);\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static storeSpannedCells(\r\n\t\trowIndex: number,\r\n\t\tcolIndex: number,\r\n\t\trowspan: number,\r\n\t\tcontent: Cell,\r\n\t\tspannedCells: Record<number, Cell[]>\r\n\t): void {\r\n\t\tfor (let span = 1; span < rowspan; span++) {\r\n\t\t\tif (!spannedCells[rowIndex + span]) {\r\n\t\t\t\tspannedCells[rowIndex + span] = [];\r\n\t\t\t}\r\n\t\t\tspannedCells[rowIndex + span][colIndex] = content;\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static applySpannedCells(spannedCells: Record<number, Cell[]>, rowIndex: number, columns: Cell[]): void {\r\n\t\tif (spannedCells[rowIndex]) {\r\n\t\t\tspannedCells[rowIndex].forEach((spannedContent, colIndex) => {\r\n\t\t\t\tif (spannedContent !== undefined) {\r\n\t\t\t\t\tcolumns[colIndex] = spannedContent;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n}\r\n","import { Locator } from \"@playwright/test\";\r\nimport { HeaderRow } from \"./row\";\r\nimport { CellContentType } from \"./cell-content-type\";\r\nimport { TableUtils } from \"./table-utils\";\r\n\r\nexport type HeaderRowOptions = {\r\n\tcellContentType?: CellContentType;\r\n\temptyCellReplacement?: boolean;\r\n\tduplicateSuffix?: boolean;\r\n\tcolspan?: { enabled?: boolean; suffix?: boolean };\r\n};\r\n\r\nexport abstract class TableHeader {\r\n\tstatic async getRows(\r\n\t\theaderRowLocator: Locator,\r\n\t\tcolumnsSelector: string,\r\n\t\theaderRowOptions?: HeaderRowOptions\r\n\t): Promise<HeaderRow[]> {\r\n\t\tconst options = this.getDefaultOptions(headerRowOptions);\r\n\t\tconst rows = await headerRowLocator.all();\r\n\t\tconst headerRows: HeaderRow[] = [];\r\n\t\tconst rowSpans: Map<number, string> = new Map();\r\n\r\n\t\tfor (const row of rows) {\r\n\t\t\tconst headerRow = await this.processRow(row, columnsSelector, rowSpans, options);\r\n\t\t\theaderRows.push(headerRow);\r\n\t\t}\r\n\r\n\t\tthis.applyColspanOptions(headerRows, options);\r\n\t\tthis.applyDuplicateSuffix(headerRows, options);\r\n\r\n\t\treturn headerRows;\r\n\t}\r\n\r\n\tprivate static getDefaultOptions(options?: HeaderRowOptions): Required<HeaderRowOptions> {\r\n\t\treturn {\r\n\t\t\tcellContentType: options?.cellContentType ?? CellContentType.InnerText,\r\n\t\t\temptyCellReplacement: options?.emptyCellReplacement ?? false,\r\n\t\t\tduplicateSuffix: options?.duplicateSuffix ?? false,\r\n\t\t\tcolspan: {\r\n\t\t\t\tenabled: options?.colspan?.enabled ?? false,\r\n\t\t\t\tsuffix: options?.colspan?.suffix ?? false,\r\n\t\t\t},\r\n\t\t};\r\n\t}\r\n\r\n\tprivate static async processRow(\r\n\t\trow: Locator,\r\n\t\tcolumnsSelector: string,\r\n\t\trowSpans: Map<number, string>,\r\n\t\toptions: Required<HeaderRowOptions>\r\n\t): Promise<HeaderRow> {\r\n\t\tconst headerRow: HeaderRow = [];\r\n\t\tconst cells = await row.locator(columnsSelector).all();\r\n\t\tlet columnIndex = 0;\r\n\r\n\t\tfor (const cell of cells) {\r\n\t\t\tcolumnIndex = await this.processCell(cell, headerRow, rowSpans, columnIndex, options);\r\n\t\t}\r\n\r\n\t\tthis.addRemainingRowSpans(headerRow, rowSpans, columnIndex);\r\n\t\treturn headerRow;\r\n\t}\r\n\r\n\tprivate static async processCell(\r\n\t\tcell: Locator,\r\n\t\theaderRow: HeaderRow,\r\n\t\trowSpans: Map<number, string>,\r\n\t\tcolumnIndex: number,\r\n\t\toptions: Required<HeaderRowOptions>\r\n\t): Promise<number> {\r\n\t\twhile (rowSpans.has(columnIndex)) {\r\n\t\t\theaderRow.push(rowSpans.get(columnIndex)!);\r\n\t\t\trowSpans.delete(columnIndex);\r\n\t\t\tcolumnIndex++;\r\n\t\t}\r\n\r\n\t\tlet text = await TableUtils.getCellContent(cell, options.cellContentType);\r\n\t\tif (!text && options.emptyCellReplacement) {\r\n\t\t\ttext = \"{{Empty}}\";\r\n\t\t}\r\n\r\n\t\tconst { colspan, rowspan } = await TableUtils.parseSpanAttributes(cell);\r\n\r\n\t\theaderRow.push(text);\r\n\t\tthis.handleColspan(headerRow, text, colspan);\r\n\t\tthis.handleRowspan(rowSpans, text, columnIndex, colspan, rowspan);\r\n\r\n\t\treturn columnIndex + colspan;\r\n\t}\r\n\r\n\tprivate static handleColspan(headerRow: HeaderRow, text: string, colspan: number): void {\r\n\t\tfor (let i = 1; i < colspan; i++) {\r\n\t\t\theaderRow.push(`${text}__C${i}`);\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static handleRowspan(\r\n\t\trowSpans: Map<number, string>,\r\n\t\ttext: string,\r\n\t\tcolumnIndex: number,\r\n\t\tcolspan: number,\r\n\t\trowspan: number\r\n\t): void {\r\n\t\tif (rowspan > 1) {\r\n\t\t\tfor (let i = 0; i < colspan; i++) {\r\n\t\t\t\trowSpans.set(columnIndex + i, text);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static addRemainingRowSpans(headerRow: HeaderRow, rowSpans: Map<number, string>, columnIndex: number): void {\r\n\t\twhile (rowSpans.has(columnIndex)) {\r\n\t\t\theaderRow.push(rowSpans.get(columnIndex)!);\r\n\t\t\trowSpans.delete(columnIndex);\r\n\t\t\tcolumnIndex++;\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static applyColspanOptions(headerRows: HeaderRow[], options: Required<HeaderRowOptions>): void {\r\n\t\tif (!options.colspan.enabled) {\r\n\t\t\tthis.removeColspanCells(headerRows);\r\n\t\t}\r\n\r\n\t\tif (!options.colspan.suffix) {\r\n\t\t\tthis.removeColspanSuffix(headerRows);\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static removeColspanCells(headerRows: HeaderRow[]): void {\r\n\t\tfor (const headerRow of headerRows) {\r\n\t\t\tfor (let i = 0; i < headerRow.length; i++) {\r\n\t\t\t\tif (/__C\\d/.test(headerRow[i])) {\r\n\t\t\t\t\theaderRow.splice(i, 1);\r\n\t\t\t\t\ti--;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static removeColspanSuffix(headerRows: HeaderRow[]): void {\r\n\t\tfor (const headerRow of headerRows) {\r\n\t\t\tfor (let i = 0; i < headerRow.length; i++) {\r\n\t\t\t\tif (/__C\\d/.test(headerRow[i])) {\r\n\t\t\t\t\theaderRow[i] = headerRow[i].replace(/__C\\d/, \"\");\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static applyDuplicateSuffix(headerRows: HeaderRow[], options: Required<HeaderRowOptions>): void {\r\n\t\tif (!options.duplicateSuffix) return;\r\n\r\n\t\tfor (const headerRow of headerRows) {\r\n\t\t\tconst headerCountMap: Map<string, number> = new Map();\r\n\t\t\tfor (let i = 0; i < headerRow.length; i++) {\r\n\t\t\t\tconst header = headerRow[i];\r\n\t\t\t\tif (headerCountMap.has(header)) {\r\n\t\t\t\t\tconst count = headerCountMap.get(header)!;\r\n\t\t\t\t\theaderRow[i] = `${header}__D${count}`;\r\n\t\t\t\t\theaderCountMap.set(header, count + 1);\r\n\t\t\t\t} else {\r\n\t\t\t\t\theaderCountMap.set(header, 1);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n","import { Locator, expect } from \"@playwright/test\";\r\n\r\nexport enum RowKind {\r\n\tHeader = \"header\",\r\n\tBody = \"body\",\r\n}\r\n\r\nexport abstract class TableWait {\r\n\tstatic async waitForRows(\r\n\t\trowLocator: Locator,\r\n\t\tcellSelector: string,\r\n\t\trowKind: RowKind,\r\n\t\toptions?: {\r\n\t\t\trow?: {\r\n\t\t\t\tamount?: number;\r\n\t\t\t\tcell?: {\r\n\t\t\t\t\ttotalCount?: number;\r\n\t\t\t\t\tcontentCount?: number;\r\n\t\t\t\t};\r\n\t\t\t};\r\n\t\t}\r\n\t): Promise<void> {\r\n\t\tconst validateCellsWithContent = async (): Promise<void> => {\r\n\t\t\tconst cells = await rowLocator.locator(cellSelector).all();\r\n\t\t\tconst cellsWithContent = (\r\n\t\t\t\tawait Promise.all(\r\n\t\t\t\t\tcells.map(async cell => {\r\n\t\t\t\t\t\tconst content = await cell.textContent();\r\n\t\t\t\t\t\treturn content !== null && content.trim() !== \"\" ? cell : null;\r\n\t\t\t\t\t})\r\n\t\t\t\t)\r\n\t\t\t).filter(cell => cell !== null);\r\n\t\t\texpect(cellsWithContent.length, `No ${rowKind} cells with content found`).toBeGreaterThan(0);\r\n\t\t};\r\n\r\n\t\tconst validateRowAmount = (rows: Locator[], expectedAmount: number): void => {\r\n\t\t\texpect(rows.length, `Expected ${expectedAmount} ${rowKind} rows, but found ${rows.length}`).toBe(expectedAmount);\r\n\t\t};\r\n\r\n\t\tconst validateCellCount = async (rows: Locator[], expectedCount: number): Promise<void> => {\r\n\t\t\tconst rowsWithMatchingCells = (\r\n\t\t\t\tawait Promise.all(\r\n\t\t\t\t\trows.map(async row => {\r\n\t\t\t\t\t\tconst cellCount = await row.locator(cellSelector).count();\r\n\t\t\t\t\t\treturn cellCount === expectedCount ? row : null;\r\n\t\t\t\t\t})\r\n\t\t\t\t)\r\n\t\t\t).filter(row => row !== null);\r\n\t\t\texpect(\r\n\t\t\t\trowsWithMatchingCells.length,\r\n\t\t\t\t`Expected amount of ${expectedCount} ${rowKind} cells for row not found`\r\n\t\t\t).toBeGreaterThan(0);\r\n\t\t};\r\n\r\n\t\tconst validateCellContentCount = async (rows: Locator[], expectedContentCount: number): Promise<void> => {\r\n\t\t\tconst rowsWithMatchingContent = (\r\n\t\t\t\tawait Promise.all(\r\n\t\t\t\t\trows.map(async row => {\r\n\t\t\t\t\t\tconst cells = await row.locator(cellSelector).all();\r\n\t\t\t\t\t\tconst cellsWithContent = (\r\n\t\t\t\t\t\t\tawait Promise.all(\r\n\t\t\t\t\t\t\t\tcells.map(async cell => {\r\n\t\t\t\t\t\t\t\t\tconst content = await cell.textContent();\r\n\t\t\t\t\t\t\t\t\treturn content !== null && content.trim() !== \"\" ? cell : null;\r\n\t\t\t\t\t\t\t\t})\r\n\t\t\t\t\t\t\t)\r\n\t\t\t\t\t\t).filter(cell => cell !== null);\r\n\t\t\t\t\t\treturn cellsWithContent.length === expectedContentCount ? row : null;\r\n\t\t\t\t\t})\r\n\t\t\t\t)\r\n\t\t\t).filter(row => row !== null);\r\n\t\t\texpect(\r\n\t\t\t\trowsWithMatchingContent.length,\r\n\t\t\t\t`Expected amount of ${expectedContentCount} ${rowKind} cells with content for row not found`\r\n\t\t\t).toBeGreaterThan(0);\r\n\t\t};\r\n\r\n\t\tconst rows = await rowLocator.all();\r\n\r\n\t\tif (options?.row) {\r\n\t\t\tif (options.row.amount) {\r\n\t\t\t\tvalidateRowAmount(rows, options.row.amount);\r\n\t\t\t} else {\r\n\t\t\t\texpect(rows.length, `No ${rowKind} rows found`).toBeGreaterThan(0);\r\n\t\t\t}\r\n\r\n\t\t\tif (options.row.cell) {\r\n\t\t\t\tif (options.row.cell.totalCount) {\r\n\t\t\t\t\tawait validateCellCount(rows, options.row.cell.totalCount);\r\n\t\t\t\t}\r\n\t\t\t\tif (options.row.cell.contentCount) {\r\n\t\t\t\t\tawait validateCellContentCount(rows, options.row.cell.contentCount);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tawait validateCellsWithContent();\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tawait validateCellsWithContent();\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tawait validateCellsWithContent();\r\n\t\t}\r\n\t}\r\n}\r\n"],"mappings":"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","names":["expect","CellContentType","rows","expect"]}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@cerios/playwright-table",
3
+ "version": "1.0.0",
4
+ "author": "Ronald Veth - Cerios",
5
+ "description": "Easy Html Tables handler for Playwright",
6
+ "homepage": "https://www.cerios.nl/",
7
+ "license": "MIT",
8
+ "keywords": [
9
+ "playwright",
10
+ "html",
11
+ "table",
12
+ "testing"
13
+ ],
14
+ "scripts": {
15
+ "format": "prettier --write . --cache --ignore-path=.prettierignore",
16
+ "test": "playwright test",
17
+ "prepare": "husky",
18
+ "build": "tsup",
19
+ "serve": "serve tests/demo-html -p 3000",
20
+ "check-exports": "attw --pack .",
21
+ "changeset": "npx changeset",
22
+ "local-release": "changeset version && changeset publish"
23
+ },
24
+ "devDependencies": {
25
+ "@arethetypeswrong/cli": "^0.18.0",
26
+ "@changesets/cli": "^2.29.3",
27
+ "@playwright/test": "^1.51.1",
28
+ "husky": "^9.1.7",
29
+ "lint-staged": "^15.5.0",
30
+ "prettier": "^3.5.3",
31
+ "serve": "^14.2.4",
32
+ "ts-node": "^10.9.2",
33
+ "tsup": "^8.4.0",
34
+ "typescript": "^5.8.3"
35
+ },
36
+ "peerDependencies": {
37
+ "@playwright/test": "^1.51.1"
38
+ },
39
+ "main": "./dist/index.js",
40
+ "module": "./dist/index.mjs",
41
+ "types": "./dist/index.d.ts",
42
+ "files": [
43
+ "dist"
44
+ ],
45
+ "type": "commonjs",
46
+ "exports": {
47
+ "./package.json": "./package.json",
48
+ ".": {
49
+ "import": "./dist/index.mjs",
50
+ "default": "./dist/index.js"
51
+ }
52
+ }
53
+ }