@rickcedwhat/playwright-smart-table 6.1.0 → 6.1.1
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/dist/{examples/glide-strategies → strategies/glide}/columns.d.ts +1 -1
- package/dist/{examples/glide-strategies → strategies/glide}/headers.d.ts +1 -1
- package/dist/{src/strategies → strategies}/glide.js +2 -2
- package/dist/strategies/index.d.ts +29 -2
- package/dist/strategies/index.js +6 -0
- package/dist/strategies/pagination.d.ts +26 -4
- package/dist/strategies/pagination.js +52 -23
- package/dist/typeContext.d.ts +1 -1
- package/dist/typeContext.js +28 -4
- package/dist/types.d.ts +33 -2
- package/dist/useTable.d.ts +28 -3
- package/dist/useTable.js +92 -36
- package/package.json +1 -1
- package/dist/src/filterEngine.d.ts +0 -11
- package/dist/src/filterEngine.js +0 -39
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.js +0 -18
- package/dist/src/smartRow.d.ts +0 -7
- package/dist/src/smartRow.js +0 -160
- package/dist/src/strategies/columns.d.ts +0 -18
- package/dist/src/strategies/columns.js +0 -21
- package/dist/src/strategies/fill.d.ts +0 -7
- package/dist/src/strategies/fill.js +0 -88
- package/dist/src/strategies/headers.d.ts +0 -13
- package/dist/src/strategies/headers.js +0 -30
- package/dist/src/strategies/index.d.ts +0 -54
- package/dist/src/strategies/index.js +0 -43
- package/dist/src/strategies/pagination.d.ts +0 -33
- package/dist/src/strategies/pagination.js +0 -79
- package/dist/src/strategies/resolution.d.ts +0 -22
- package/dist/src/strategies/resolution.js +0 -30
- package/dist/src/strategies/sorting.d.ts +0 -12
- package/dist/src/strategies/sorting.js +0 -68
- package/dist/src/strategies/validation.d.ts +0 -22
- package/dist/src/strategies/validation.js +0 -54
- package/dist/src/strategies/virtualizedPagination.d.ts +0 -32
- package/dist/src/strategies/virtualizedPagination.js +0 -80
- package/dist/src/typeContext.d.ts +0 -6
- package/dist/src/typeContext.js +0 -465
- package/dist/src/types.d.ts +0 -458
- package/dist/src/types.js +0 -2
- package/dist/src/useTable.d.ts +0 -44
- package/dist/src/useTable.js +0 -641
- package/dist/src/utils/debugUtils.d.ts +0 -17
- package/dist/src/utils/debugUtils.js +0 -62
- package/dist/src/utils/smartRowArray.d.ts +0 -14
- package/dist/src/utils/smartRowArray.js +0 -22
- package/dist/src/utils/stringUtils.d.ts +0 -22
- package/dist/src/utils/stringUtils.js +0 -73
- package/dist/src/utils.d.ts +0 -7
- package/dist/src/utils.js +0 -29
- package/dist/utils/traceUtils.d.ts +0 -11
- package/dist/utils/traceUtils.js +0 -47
- /package/dist/{src/plugins.d.ts → plugins.d.ts} +0 -0
- /package/dist/{src/plugins.js → plugins.js} +0 -0
- /package/dist/{src/strategies → strategies}/dedupe.d.ts +0 -0
- /package/dist/{src/strategies → strategies}/dedupe.js +0 -0
- /package/dist/{examples/glide-strategies → strategies/glide}/columns.js +0 -0
- /package/dist/{examples/glide-strategies → strategies/glide}/headers.js +0 -0
- /package/dist/{src/strategies → strategies}/glide.d.ts +0 -0
- /package/dist/{src/strategies → strategies}/loading.d.ts +0 -0
- /package/dist/{src/strategies → strategies}/loading.js +0 -0
- /package/dist/{src/strategies → strategies}/rdg.d.ts +0 -0
- /package/dist/{src/strategies → strategies}/rdg.js +0 -0
- /package/dist/{src/strategies → strategies}/stabilization.d.ts +0 -0
- /package/dist/{src/strategies → strategies}/stabilization.js +0 -0
package/dist/useTable.js
CHANGED
|
@@ -9,10 +9,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.Strategies = exports.ResolutionStrategies = exports.CellNavigationStrategies = exports.HeaderStrategies = exports.FillStrategies = exports.SortingStrategies = exports.PaginationStrategies = exports.useTable = void 0;
|
|
12
|
+
exports.Strategies = exports.ResolutionStrategies = exports.CellNavigationStrategies = exports.HeaderStrategies = exports.FillStrategies = exports.DedupeStrategies = exports.SortingStrategies = exports.LoadingStrategies = exports.PaginationStrategies = exports.useTable = void 0;
|
|
13
13
|
const typeContext_1 = require("./typeContext");
|
|
14
14
|
const sorting_1 = require("./strategies/sorting");
|
|
15
15
|
const pagination_1 = require("./strategies/pagination");
|
|
16
|
+
const dedupe_1 = require("./strategies/dedupe");
|
|
17
|
+
const loading_1 = require("./strategies/loading");
|
|
16
18
|
const fill_1 = require("./strategies/fill");
|
|
17
19
|
Object.defineProperty(exports, "FillStrategies", { enumerable: true, get: function () { return fill_1.FillStrategies; } });
|
|
18
20
|
const headers_1 = require("./strategies/headers");
|
|
@@ -42,7 +44,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
42
44
|
cellNavigation: columns_1.CellNavigationStrategies.default,
|
|
43
45
|
pagination: () => __awaiter(void 0, void 0, void 0, function* () { return false; }),
|
|
44
46
|
};
|
|
45
|
-
const config = Object.assign(Object.assign({ rowSelector: "tbody tr", headerSelector: "thead th", cellSelector: "td", maxPages: 1, headerTransformer: ({ text
|
|
47
|
+
const config = Object.assign(Object.assign({ rowSelector: "tbody tr", headerSelector: "thead th", cellSelector: "td", maxPages: 1, headerTransformer: ({ text }) => text, autoScroll: true, onReset: () => __awaiter(void 0, void 0, void 0, function* () { }) }, configOptions), { strategies: Object.assign(Object.assign({}, defaultStrategies), configOptions.strategies) });
|
|
46
48
|
const resolve = (item, parent) => {
|
|
47
49
|
if (typeof item === 'string')
|
|
48
50
|
return parent.locator(item);
|
|
@@ -73,7 +75,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
73
75
|
suggestion = `. Available columns: ${availableColumns.map(c => `"${c}"`).join(', ')}`;
|
|
74
76
|
}
|
|
75
77
|
else if (availableColumns.length > 0) {
|
|
76
|
-
suggestion = `. Available columns (first
|
|
78
|
+
suggestion = `. Available columns (first 10 of ${availableColumns.length}): ${availableColumns.slice(0, 10).map(c => `"${c}"`).join(', ')}, ...`;
|
|
77
79
|
}
|
|
78
80
|
const contextMsg = context ? ` (${context})` : '';
|
|
79
81
|
return new Error(`Column "${colName}" not found${contextMsg}${suggestion}`);
|
|
@@ -102,17 +104,21 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
102
104
|
resolve: resolve
|
|
103
105
|
};
|
|
104
106
|
const rawHeaders = yield strategy(context);
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
+
const seenHeaders = new Set();
|
|
108
|
+
const entries = [];
|
|
109
|
+
for (let i = 0; i < rawHeaders.length; i++) {
|
|
110
|
+
let text = rawHeaders[i].trim() || `__col_${i}`;
|
|
107
111
|
if (config.headerTransformer) {
|
|
108
112
|
text = yield config.headerTransformer({
|
|
109
113
|
text,
|
|
110
114
|
index: i,
|
|
111
|
-
locator: rootLocator.locator(config.headerSelector).nth(i)
|
|
115
|
+
locator: rootLocator.locator(config.headerSelector).nth(i),
|
|
116
|
+
seenHeaders
|
|
112
117
|
});
|
|
113
118
|
}
|
|
114
|
-
|
|
115
|
-
|
|
119
|
+
entries.push([text, i]);
|
|
120
|
+
seenHeaders.add(text);
|
|
121
|
+
}
|
|
116
122
|
// Validation: Check for empty table
|
|
117
123
|
if (entries.length === 0) {
|
|
118
124
|
throw new Error(`Initialization Error: No columns found using selector "${config.headerSelector}". Check your selector or ensure the table is visible.`);
|
|
@@ -143,12 +149,21 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
143
149
|
return (0, smartRow_1.createSmartRow)(rowLocator, map, rowIndex, config, rootLocator, resolve, finalTable);
|
|
144
150
|
};
|
|
145
151
|
const _findRowLocator = (filters_1, ...args_1) => __awaiter(void 0, [filters_1, ...args_1], void 0, function* (filters, options = {}) {
|
|
146
|
-
var _a;
|
|
152
|
+
var _a, _b;
|
|
147
153
|
const map = yield _getMap();
|
|
148
154
|
const effectiveMaxPages = (_a = options.maxPages) !== null && _a !== void 0 ? _a : config.maxPages;
|
|
149
155
|
let currentPage = 1;
|
|
150
156
|
log(`Looking for row: ${JSON.stringify(filters)} (MaxPages: ${effectiveMaxPages})`);
|
|
151
157
|
while (true) {
|
|
158
|
+
// Check for table loading
|
|
159
|
+
if ((_b = config.strategies.loading) === null || _b === void 0 ? void 0 : _b.isTableLoading) {
|
|
160
|
+
const isLoading = yield config.strategies.loading.isTableLoading({ root: rootLocator, config, page: rootLocator.page(), resolve });
|
|
161
|
+
if (isLoading) {
|
|
162
|
+
log('Table is loading... waiting');
|
|
163
|
+
yield rootLocator.page().waitForTimeout(200);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
152
167
|
const allRows = resolve(config.rowSelector, rootLocator);
|
|
153
168
|
// Use FilterEngine
|
|
154
169
|
const matchedRows = filterEngine.applyFilters(allRows, filters, map, options.exact || false, rootLocator.page());
|
|
@@ -167,7 +182,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
167
182
|
}
|
|
168
183
|
catch (e) { }
|
|
169
184
|
const sampleMsg = sampleData.length > 0 ? `\nSample matching rows:\n${sampleData.map((d, i) => ` ${i + 1}. ${d}`).join('\n')}` : '';
|
|
170
|
-
throw new Error(`
|
|
185
|
+
throw new Error(`Ambiguous Row: Found ${count} rows matching ${JSON.stringify(filters)} on page ${currentPage}. ` +
|
|
171
186
|
`Expected exactly one match. Try adding more filters to make your query unique.${sampleMsg}`);
|
|
172
187
|
}
|
|
173
188
|
if (count === 1)
|
|
@@ -267,13 +282,11 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
267
282
|
});
|
|
268
283
|
}),
|
|
269
284
|
getHeaders: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
270
|
-
|
|
271
|
-
throw new Error('Table not initialized. Call await table.init() first, or use async methods like table.findRow() or table.getRows() which auto-initialize.');
|
|
285
|
+
yield _ensureInitialized();
|
|
272
286
|
return Array.from(_headerMap.keys());
|
|
273
287
|
}),
|
|
274
288
|
getHeaderCell: (columnName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
275
|
-
|
|
276
|
-
throw new Error('Table not initialized. Call await table.init() first.');
|
|
289
|
+
yield _ensureInitialized();
|
|
277
290
|
const idx = _headerMap.get(columnName);
|
|
278
291
|
if (idx === undefined)
|
|
279
292
|
throw _createColumnError(columnName, _headerMap, 'header cell');
|
|
@@ -336,9 +349,8 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
336
349
|
getRowByIndex: (index, options = {}) => {
|
|
337
350
|
if (!_isInitialized || !_headerMap)
|
|
338
351
|
throw new Error('Table not initialized. Call await table.init() first, or use async methods like table.findRow() or table.getRows() which auto-initialize.');
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
return _makeSmart(rowLocator, _headerMap, rowIndex);
|
|
352
|
+
const rowLocator = resolve(config.rowSelector, rootLocator).nth(index);
|
|
353
|
+
return _makeSmart(rowLocator, _headerMap, index);
|
|
342
354
|
},
|
|
343
355
|
findRow: (filters, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
344
356
|
(0, debugUtils_1.logDebug)(config, 'info', 'Searching for row', filters);
|
|
@@ -356,17 +368,28 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
356
368
|
return _makeSmart(row, _headerMap, 0);
|
|
357
369
|
}),
|
|
358
370
|
getRows: (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
371
|
+
var _a;
|
|
359
372
|
yield _ensureInitialized();
|
|
360
373
|
let rowLocators = resolve(config.rowSelector, rootLocator);
|
|
361
374
|
if (options === null || options === void 0 ? void 0 : options.filter) {
|
|
362
375
|
rowLocators = filterEngine.applyFilters(rowLocators, options.filter, _headerMap, options.exact || false, rootLocator.page());
|
|
363
376
|
}
|
|
364
|
-
const
|
|
365
|
-
const smartRows =
|
|
377
|
+
const allRowLocs = yield rowLocators.all();
|
|
378
|
+
const smartRows = [];
|
|
379
|
+
const isRowLoading = (_a = config.strategies.loading) === null || _a === void 0 ? void 0 : _a.isRowLoading;
|
|
380
|
+
for (let i = 0; i < allRowLocs.length; i++) {
|
|
381
|
+
const smartRow = _makeSmart(allRowLocs[i], _headerMap, i);
|
|
382
|
+
if (isRowLoading) {
|
|
383
|
+
const loading = yield isRowLoading(smartRow);
|
|
384
|
+
if (loading)
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
smartRows.push(smartRow);
|
|
388
|
+
}
|
|
366
389
|
return (0, smartRowArray_1.createSmartRowArray)(smartRows);
|
|
367
390
|
}),
|
|
368
391
|
findRows: (filters, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
369
|
-
var _a, _b, _c, _d;
|
|
392
|
+
var _a, _b, _c, _d, _e;
|
|
370
393
|
yield _ensureInitialized();
|
|
371
394
|
const allRows = [];
|
|
372
395
|
const effectiveMaxPages = (_b = (_a = options === null || options === void 0 ? void 0 : options.maxPages) !== null && _a !== void 0 ? _a : config.maxPages) !== null && _b !== void 0 ? _b : Infinity;
|
|
@@ -374,8 +397,14 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
374
397
|
// Collect rows from current page
|
|
375
398
|
let rowLocators = resolve(config.rowSelector, rootLocator);
|
|
376
399
|
rowLocators = filterEngine.applyFilters(rowLocators, filters, _headerMap, (_c = options === null || options === void 0 ? void 0 : options.exact) !== null && _c !== void 0 ? _c : false, rootLocator.page());
|
|
377
|
-
let
|
|
378
|
-
|
|
400
|
+
let currentRows = yield rowLocators.all();
|
|
401
|
+
const isRowLoading = (_d = config.strategies.loading) === null || _d === void 0 ? void 0 : _d.isRowLoading;
|
|
402
|
+
for (let i = 0; i < currentRows.length; i++) {
|
|
403
|
+
const smartRow = _makeSmart(currentRows[i], _headerMap, i);
|
|
404
|
+
if (isRowLoading && (yield isRowLoading(smartRow)))
|
|
405
|
+
continue;
|
|
406
|
+
allRows.push(smartRow);
|
|
407
|
+
}
|
|
379
408
|
// Paginate and collect more rows
|
|
380
409
|
while (pageCount < effectiveMaxPages && config.strategies.pagination) {
|
|
381
410
|
const paginationResult = yield config.strategies.pagination({
|
|
@@ -391,9 +420,14 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
391
420
|
_hasPaginated = true;
|
|
392
421
|
// Collect rows from new page
|
|
393
422
|
rowLocators = resolve(config.rowSelector, rootLocator);
|
|
394
|
-
rowLocators = filterEngine.applyFilters(rowLocators, filters, _headerMap, (
|
|
395
|
-
|
|
396
|
-
|
|
423
|
+
rowLocators = filterEngine.applyFilters(rowLocators, filters, _headerMap, (_e = options === null || options === void 0 ? void 0 : options.exact) !== null && _e !== void 0 ? _e : false, rootLocator.page());
|
|
424
|
+
const newRows = yield rowLocators.all();
|
|
425
|
+
for (let i = 0; i < newRows.length; i++) {
|
|
426
|
+
const smartRow = _makeSmart(newRows[i], _headerMap, i);
|
|
427
|
+
if (isRowLoading && (yield isRowLoading(smartRow)))
|
|
428
|
+
continue;
|
|
429
|
+
allRows.push(smartRow);
|
|
430
|
+
}
|
|
397
431
|
}
|
|
398
432
|
if (options === null || options === void 0 ? void 0 : options.asJSON) {
|
|
399
433
|
return Promise.all(allRows.map(r => r.toJSON()));
|
|
@@ -421,7 +455,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
421
455
|
})
|
|
422
456
|
},
|
|
423
457
|
iterateThroughTable: (callback, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
424
|
-
var _a, _b, _c, _d;
|
|
458
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
425
459
|
yield _ensureInitialized();
|
|
426
460
|
const paginationStrategy = (_a = options === null || options === void 0 ? void 0 : options.pagination) !== null && _a !== void 0 ? _a : config.strategies.pagination;
|
|
427
461
|
const hasPaginationInOptions = (options === null || options === void 0 ? void 0 : options.pagination) !== undefined;
|
|
@@ -451,6 +485,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
451
485
|
const effectiveMaxIterations = (_d = options === null || options === void 0 ? void 0 : options.maxIterations) !== null && _d !== void 0 ? _d : config.maxPages;
|
|
452
486
|
const batchSize = options === null || options === void 0 ? void 0 : options.batchSize;
|
|
453
487
|
const isBatching = batchSize !== undefined && batchSize > 1;
|
|
488
|
+
const autoFlatten = (_e = options === null || options === void 0 ? void 0 : options.autoFlatten) !== null && _e !== void 0 ? _e : false;
|
|
454
489
|
let index = 0;
|
|
455
490
|
let paginationResult = true;
|
|
456
491
|
let seenKeys = null;
|
|
@@ -459,19 +494,28 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
459
494
|
log(`Starting iterateThroughTable (maxIterations: ${effectiveMaxIterations}, batchSize: ${batchSize !== null && batchSize !== void 0 ? batchSize : 'none'})`);
|
|
460
495
|
while (index < effectiveMaxIterations) {
|
|
461
496
|
const rowLocators = yield resolve(config.rowSelector, rootLocator).all();
|
|
462
|
-
|
|
463
|
-
|
|
497
|
+
const smartRowsArray = [];
|
|
498
|
+
const isRowLoading = (_f = config.strategies.loading) === null || _f === void 0 ? void 0 : _f.isRowLoading;
|
|
499
|
+
for (let i = 0; i < rowLocators.length; i++) {
|
|
500
|
+
const smartRow = _makeSmart(rowLocators[i], _headerMap, i);
|
|
501
|
+
if (isRowLoading && (yield isRowLoading(smartRow)))
|
|
502
|
+
continue;
|
|
503
|
+
smartRowsArray.push(smartRow);
|
|
504
|
+
}
|
|
505
|
+
let rows = (0, smartRowArray_1.createSmartRowArray)(smartRowsArray);
|
|
506
|
+
const dedupeStrategy = (_g = options === null || options === void 0 ? void 0 : options.dedupeStrategy) !== null && _g !== void 0 ? _g : config.strategies.dedupe;
|
|
507
|
+
if (dedupeStrategy && rows.length > 0) {
|
|
464
508
|
if (!seenKeys)
|
|
465
509
|
seenKeys = new Set();
|
|
466
510
|
const deduplicated = [];
|
|
467
511
|
for (const row of rows) {
|
|
468
|
-
const key = yield
|
|
512
|
+
const key = yield dedupeStrategy(row);
|
|
469
513
|
if (!seenKeys.has(key)) {
|
|
470
514
|
seenKeys.add(key);
|
|
471
515
|
deduplicated.push(row);
|
|
472
516
|
}
|
|
473
517
|
}
|
|
474
|
-
rows = deduplicated;
|
|
518
|
+
rows = (0, smartRowArray_1.createSmartRowArray)(deduplicated);
|
|
475
519
|
log(`Deduplicated ${rowLocators.length} rows to ${rows.length} unique rows (total seen: ${seenKeys.size})`);
|
|
476
520
|
}
|
|
477
521
|
// Add rows to batch if batching is enabled
|
|
@@ -500,12 +544,17 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
500
544
|
index: callbackIndex,
|
|
501
545
|
isFirst,
|
|
502
546
|
isLast,
|
|
503
|
-
rows: callbackRows,
|
|
547
|
+
rows: (0, smartRowArray_1.createSmartRowArray)(callbackRows),
|
|
504
548
|
allData,
|
|
505
549
|
table: restrictedTable,
|
|
506
550
|
batchInfo
|
|
507
551
|
});
|
|
508
|
-
|
|
552
|
+
if (autoFlatten && Array.isArray(returnValue)) {
|
|
553
|
+
allData.push(...returnValue);
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
allData.push(returnValue);
|
|
557
|
+
}
|
|
509
558
|
// Determine if this is truly the last iteration
|
|
510
559
|
let finalIsLast = isLastDueToMax;
|
|
511
560
|
if (!isLastIteration) {
|
|
@@ -551,12 +600,17 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
551
600
|
index: callbackIndex,
|
|
552
601
|
isFirst,
|
|
553
602
|
isLast,
|
|
554
|
-
rows: batchRows,
|
|
603
|
+
rows: (0, smartRowArray_1.createSmartRowArray)(batchRows),
|
|
555
604
|
allData,
|
|
556
605
|
table: restrictedTable,
|
|
557
606
|
batchInfo
|
|
558
607
|
});
|
|
559
|
-
|
|
608
|
+
if (autoFlatten && Array.isArray(returnValue)) {
|
|
609
|
+
allData.push(...returnValue);
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
allData.push(returnValue);
|
|
613
|
+
}
|
|
560
614
|
if (options === null || options === void 0 ? void 0 : options.afterLast) {
|
|
561
615
|
yield options.afterLast({ index: callbackIndex, rows: batchRows, allData });
|
|
562
616
|
}
|
|
@@ -573,7 +627,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
573
627
|
generateConfigPrompt: (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
574
628
|
const html = yield _getCleanHtml(rootLocator);
|
|
575
629
|
const separator = "=".repeat(50);
|
|
576
|
-
const content = `\n${separator}\n🤖 COPY INTO GEMINI/ChatGPT 🤖\n${separator}\nI am using 'playwright-smart-table'.\nTarget Table Locator: ${rootLocator.toString()}\nGenerate config for
|
|
630
|
+
const content = `\n${separator} \n🤖 COPY INTO GEMINI / ChatGPT 🤖\n${separator} \nI am using 'playwright-smart-table'.\nTarget Table Locator: ${rootLocator.toString()} \nGenerate config for: \n\`\`\`html\n${html.substring(0, 10000)} ...\n\`\`\`\n${separator}\n`;
|
|
577
631
|
yield _handlePrompt('Smart Table Config', content, options);
|
|
578
632
|
}),
|
|
579
633
|
};
|
|
@@ -581,5 +635,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
581
635
|
return result;
|
|
582
636
|
};
|
|
583
637
|
exports.useTable = useTable;
|
|
584
|
-
exports.PaginationStrategies = pagination_1.PaginationStrategies;
|
|
638
|
+
exports.PaginationStrategies = Object.assign({}, pagination_1.PaginationStrategies);
|
|
639
|
+
exports.LoadingStrategies = loading_1.LoadingStrategies;
|
|
585
640
|
exports.SortingStrategies = sorting_1.SortingStrategies;
|
|
641
|
+
exports.DedupeStrategies = dedupe_1.DedupeStrategies;
|
package/package.json
CHANGED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Locator, Page } from "@playwright/test";
|
|
2
|
-
import { FinalTableConfig } from "./types";
|
|
3
|
-
export declare class FilterEngine {
|
|
4
|
-
private config;
|
|
5
|
-
private resolve;
|
|
6
|
-
constructor(config: FinalTableConfig, resolve: (selector: any, parent: Locator | Page) => Locator);
|
|
7
|
-
/**
|
|
8
|
-
* Applies filters to a set of rows.
|
|
9
|
-
*/
|
|
10
|
-
applyFilters(baseRows: Locator, filters: Record<string, string | RegExp | number>, map: Map<string, number>, exact: boolean, page: Page): Locator;
|
|
11
|
-
}
|
package/dist/src/filterEngine.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FilterEngine = void 0;
|
|
4
|
-
const stringUtils_1 = require("./utils/stringUtils");
|
|
5
|
-
class FilterEngine {
|
|
6
|
-
constructor(config, resolve) {
|
|
7
|
-
this.config = config;
|
|
8
|
-
this.resolve = resolve;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Applies filters to a set of rows.
|
|
12
|
-
*/
|
|
13
|
-
applyFilters(baseRows, filters, map, exact, page) {
|
|
14
|
-
let filtered = baseRows;
|
|
15
|
-
// Iterate through each filter criteria
|
|
16
|
-
for (const [colName, value] of Object.entries(filters)) {
|
|
17
|
-
// Find column index
|
|
18
|
-
const colIndex = map.get(colName);
|
|
19
|
-
// TODO: Use ColumnStrategy for better resolution error handling
|
|
20
|
-
if (colIndex === undefined) {
|
|
21
|
-
throw new Error((0, stringUtils_1.buildColumnNotFoundError)(colName, Array.from(map.keys())));
|
|
22
|
-
}
|
|
23
|
-
const filterVal = typeof value === 'number' ? String(value) : value;
|
|
24
|
-
// Use strategy if provided (For future: configured filter strategies)
|
|
25
|
-
// But for now, we implement the default logic or use custom if we add it to config later
|
|
26
|
-
// Default Filter Logic
|
|
27
|
-
const cellTemplate = this.resolve(this.config.cellSelector, page);
|
|
28
|
-
// This logic assumes 1:1 row-to-cell mapping based on index.
|
|
29
|
-
// filter({ has: ... }) checks if the row *contains* the matching cell.
|
|
30
|
-
// But we need to be specific about WHICH cell.
|
|
31
|
-
// Locator filtering by `has: locator.nth(index)` works if `locator` search is relative to the row.
|
|
32
|
-
filtered = filtered.filter({
|
|
33
|
-
has: cellTemplate.nth(colIndex).getByText(filterVal, { exact }),
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
return filtered;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
exports.FilterEngine = FilterEngine;
|
package/dist/src/index.d.ts
DELETED
package/dist/src/index.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./useTable"), exports);
|
|
18
|
-
__exportStar(require("./types"), exports);
|
package/dist/src/smartRow.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { Locator, Page } from '@playwright/test';
|
|
2
|
-
import { SmartRow as SmartRowType, FinalTableConfig, TableResult } from './types';
|
|
3
|
-
/**
|
|
4
|
-
* Factory to create a SmartRow by extending a Playwright Locator.
|
|
5
|
-
* We avoid Class/Proxy to ensure full compatibility with Playwright's expect(locator) matchers.
|
|
6
|
-
*/
|
|
7
|
-
export declare const createSmartRow: <T = any>(rowLocator: Locator, map: Map<string, number>, rowIndex: number | undefined, config: FinalTableConfig, rootLocator: Locator, resolve: (item: any, parent: Locator | Page) => Locator, table: TableResult<T> | null) => SmartRowType<T>;
|
package/dist/src/smartRow.js
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.createSmartRow = void 0;
|
|
13
|
-
const fill_1 = require("./strategies/fill");
|
|
14
|
-
const stringUtils_1 = require("./utils/stringUtils");
|
|
15
|
-
const debugUtils_1 = require("./utils/debugUtils");
|
|
16
|
-
/**
|
|
17
|
-
* Factory to create a SmartRow by extending a Playwright Locator.
|
|
18
|
-
* We avoid Class/Proxy to ensure full compatibility with Playwright's expect(locator) matchers.
|
|
19
|
-
*/
|
|
20
|
-
const createSmartRow = (rowLocator, map, rowIndex, config, rootLocator, resolve, table) => {
|
|
21
|
-
const smart = rowLocator;
|
|
22
|
-
// Attach State
|
|
23
|
-
smart.rowIndex = rowIndex;
|
|
24
|
-
// Attach Methods
|
|
25
|
-
smart.getCell = (colName) => {
|
|
26
|
-
const idx = map.get(colName);
|
|
27
|
-
if (idx === undefined) {
|
|
28
|
-
throw new Error((0, stringUtils_1.buildColumnNotFoundError)(colName, Array.from(map.keys())));
|
|
29
|
-
}
|
|
30
|
-
if (config.strategies.getCellLocator) {
|
|
31
|
-
return config.strategies.getCellLocator({
|
|
32
|
-
row: rowLocator,
|
|
33
|
-
columnName: colName,
|
|
34
|
-
columnIndex: idx,
|
|
35
|
-
rowIndex: rowIndex,
|
|
36
|
-
page: rootLocator.page()
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
return resolve(config.cellSelector, rowLocator).nth(idx);
|
|
40
|
-
};
|
|
41
|
-
smart.toJSON = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
42
|
-
const result = {};
|
|
43
|
-
const page = rootLocator.page();
|
|
44
|
-
for (const [col, idx] of map.entries()) {
|
|
45
|
-
if ((options === null || options === void 0 ? void 0 : options.columns) && !options.columns.includes(col)) {
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
// Get the cell locator
|
|
49
|
-
const cell = config.strategies.getCellLocator
|
|
50
|
-
? config.strategies.getCellLocator({
|
|
51
|
-
row: rowLocator,
|
|
52
|
-
columnName: col,
|
|
53
|
-
columnIndex: idx,
|
|
54
|
-
rowIndex: rowIndex,
|
|
55
|
-
page: page
|
|
56
|
-
})
|
|
57
|
-
: resolve(config.cellSelector, rowLocator).nth(idx);
|
|
58
|
-
let targetCell = cell;
|
|
59
|
-
// Check if cell exists
|
|
60
|
-
const count = yield cell.count();
|
|
61
|
-
if (count === 0) {
|
|
62
|
-
// Optimization: Check if we are ALREADY at the target cell
|
|
63
|
-
if (config.strategies.getActiveCell) {
|
|
64
|
-
const active = yield config.strategies.getActiveCell({
|
|
65
|
-
config,
|
|
66
|
-
root: rootLocator,
|
|
67
|
-
page,
|
|
68
|
-
resolve
|
|
69
|
-
});
|
|
70
|
-
if (active && active.rowIndex === rowIndex && active.columnIndex === idx) {
|
|
71
|
-
if (config.debug)
|
|
72
|
-
console.log(`[SmartRow] Already at target cell (r:${active.rowIndex}, c:${active.columnIndex}), skipping navigation.`);
|
|
73
|
-
targetCell = active.locator;
|
|
74
|
-
// Skip navigation and go to reading text
|
|
75
|
-
const text = yield targetCell.innerText();
|
|
76
|
-
result[col] = (text || '').trim();
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
// Cell doesn't exist - navigate to it
|
|
81
|
-
if (config.debug) {
|
|
82
|
-
console.log(`[SmartRow.toJSON] Cell not found for column "${col}" (index ${idx}), navigating...`);
|
|
83
|
-
}
|
|
84
|
-
yield config.strategies.cellNavigation({
|
|
85
|
-
config: config,
|
|
86
|
-
root: rootLocator,
|
|
87
|
-
page: page,
|
|
88
|
-
resolve: resolve,
|
|
89
|
-
column: col,
|
|
90
|
-
index: idx,
|
|
91
|
-
rowLocator: rowLocator,
|
|
92
|
-
rowIndex: rowIndex
|
|
93
|
-
});
|
|
94
|
-
// Optimization: check if we can get the active cell directly
|
|
95
|
-
if (config.strategies.getActiveCell) {
|
|
96
|
-
const activeCell = yield config.strategies.getActiveCell({
|
|
97
|
-
config,
|
|
98
|
-
root: rootLocator,
|
|
99
|
-
page,
|
|
100
|
-
resolve
|
|
101
|
-
});
|
|
102
|
-
if (activeCell) {
|
|
103
|
-
if (config.debug) {
|
|
104
|
-
console.log(`[SmartRow.toJSON] switching to active cell locator (r:${activeCell.rowIndex}, c:${activeCell.columnIndex})`);
|
|
105
|
-
}
|
|
106
|
-
targetCell = activeCell.locator;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
const text = yield targetCell.innerText();
|
|
111
|
-
result[col] = (text || '').trim();
|
|
112
|
-
}
|
|
113
|
-
return result;
|
|
114
|
-
});
|
|
115
|
-
smart.smartFill = (data, fillOptions) => __awaiter(void 0, void 0, void 0, function* () {
|
|
116
|
-
(0, debugUtils_1.logDebug)(config, 'info', 'Filling row', data);
|
|
117
|
-
for (const [colName, value] of Object.entries(data)) {
|
|
118
|
-
if (value === undefined)
|
|
119
|
-
continue;
|
|
120
|
-
const colIdx = map.get(colName);
|
|
121
|
-
if (colIdx === undefined) {
|
|
122
|
-
throw new Error((0, stringUtils_1.buildColumnNotFoundError)(colName, Array.from(map.keys())));
|
|
123
|
-
}
|
|
124
|
-
yield config.strategies.cellNavigation({
|
|
125
|
-
config: config,
|
|
126
|
-
root: rootLocator,
|
|
127
|
-
page: rootLocator.page(),
|
|
128
|
-
resolve: resolve,
|
|
129
|
-
column: colName,
|
|
130
|
-
index: colIdx,
|
|
131
|
-
rowLocator: rowLocator,
|
|
132
|
-
rowIndex: rowIndex
|
|
133
|
-
});
|
|
134
|
-
const strategy = config.strategies.fill || fill_1.FillStrategies.default;
|
|
135
|
-
(0, debugUtils_1.logDebug)(config, 'verbose', `Filling cell "${colName}" with value`, value);
|
|
136
|
-
yield strategy({
|
|
137
|
-
row: smart,
|
|
138
|
-
columnName: colName,
|
|
139
|
-
value,
|
|
140
|
-
index: rowIndex !== null && rowIndex !== void 0 ? rowIndex : -1,
|
|
141
|
-
page: rowLocator.page(),
|
|
142
|
-
rootLocator,
|
|
143
|
-
table: table,
|
|
144
|
-
fillOptions
|
|
145
|
-
});
|
|
146
|
-
// Delay after filling
|
|
147
|
-
yield (0, debugUtils_1.debugDelay)(config, 'getCell');
|
|
148
|
-
}
|
|
149
|
-
(0, debugUtils_1.logDebug)(config, 'info', 'Row fill complete');
|
|
150
|
-
});
|
|
151
|
-
smart.bringIntoView = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
152
|
-
if (rowIndex === undefined) {
|
|
153
|
-
throw new Error('Cannot bring row into view - row index is unknown. Use getRowByIndex() instead of getRow().');
|
|
154
|
-
}
|
|
155
|
-
// Scroll row into view using Playwright's built-in method
|
|
156
|
-
yield rowLocator.scrollIntoViewIfNeeded();
|
|
157
|
-
});
|
|
158
|
-
return smart;
|
|
159
|
-
};
|
|
160
|
-
exports.createSmartRow = createSmartRow;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { StrategyContext } from '../types';
|
|
2
|
-
/**
|
|
3
|
-
* Defines the contract for a cell navigation strategy.
|
|
4
|
-
* It is responsible for ensuring a specific CELL is visible/focused (navigates to row + column),
|
|
5
|
-
* typically by scrolling or using keyboard navigation.
|
|
6
|
-
*/
|
|
7
|
-
export type CellNavigationStrategy = (context: StrategyContext & {
|
|
8
|
-
column: string;
|
|
9
|
-
index: number;
|
|
10
|
-
rowIndex?: number;
|
|
11
|
-
}) => Promise<void>;
|
|
12
|
-
export declare const CellNavigationStrategies: {
|
|
13
|
-
/**
|
|
14
|
-
* Default strategy: Assumes column is accessible or standard scrolling works.
|
|
15
|
-
* No specific action taken other than what Playwright's default locator handling does.
|
|
16
|
-
*/
|
|
17
|
-
default: () => Promise<void>;
|
|
18
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.CellNavigationStrategies = void 0;
|
|
13
|
-
exports.CellNavigationStrategies = {
|
|
14
|
-
/**
|
|
15
|
-
* Default strategy: Assumes column is accessible or standard scrolling works.
|
|
16
|
-
* No specific action taken other than what Playwright's default locator handling does.
|
|
17
|
-
*/
|
|
18
|
-
default: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
19
|
-
// No-op
|
|
20
|
-
})
|
|
21
|
-
};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { FillStrategy } from '../types';
|
|
2
|
-
export declare const FillStrategies: {
|
|
3
|
-
/**
|
|
4
|
-
* Default strategy: Detects input type and fills accordingly (Text, Select, Checkbox, ContentEditable).
|
|
5
|
-
*/
|
|
6
|
-
default: ({ row, columnName, value, fillOptions }: Parameters<FillStrategy>[0]) => Promise<void>;
|
|
7
|
-
};
|