@rickcedwhat/playwright-smart-table 6.7.4 → 6.7.6
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/README.md +7 -3
- package/dist/engine/rowFinder.d.ts +1 -1
- package/dist/engine/rowFinder.js +7 -6
- package/dist/engine/tableIteration.d.ts +25 -0
- package/dist/engine/tableIteration.js +210 -0
- package/dist/filterEngine.d.ts +5 -1
- package/dist/filterEngine.js +23 -13
- package/dist/index.d.ts +1 -1
- package/dist/{strategies → plugins}/glide/columns.js +2 -5
- package/dist/{strategies → plugins}/glide/headers.js +0 -3
- package/dist/plugins/glide/index.d.ts +31 -0
- package/dist/{strategies/glide.js → plugins/glide/index.js} +29 -48
- package/dist/plugins/index.d.ts +16 -0
- package/dist/plugins/index.js +16 -0
- package/dist/plugins/mui/index.d.ts +8 -0
- package/dist/plugins/mui/index.js +25 -0
- package/dist/plugins/rdg/index.d.ts +17 -0
- package/dist/{strategies/rdg.js → plugins/rdg/index.js} +25 -26
- package/dist/smartRow.d.ts +6 -1
- package/dist/smartRow.js +27 -9
- package/dist/strategies/filter.d.ts +13 -0
- package/dist/strategies/filter.js +38 -0
- package/dist/strategies/index.d.ts +21 -0
- package/dist/strategies/index.js +6 -0
- package/dist/typeContext.d.ts +1 -1
- package/dist/typeContext.js +19 -13
- package/dist/types.d.ts +19 -20
- package/dist/useTable.js +52 -186
- package/dist/utils/sentinel.d.ts +5 -0
- package/dist/utils/sentinel.js +8 -0
- package/package.json +4 -4
- package/dist/plugins.d.ts +0 -44
- package/dist/plugins.js +0 -13
- package/dist/strategies/glide.d.ts +0 -45
- package/dist/strategies/rdg.d.ts +0 -34
- /package/dist/{strategies → plugins}/glide/columns.d.ts +0 -0
- /package/dist/{strategies → plugins}/glide/headers.d.ts +0 -0
package/dist/types.d.ts
CHANGED
|
@@ -259,7 +259,8 @@ import { NavigationPrimitives } from './strategies/columns';
|
|
|
259
259
|
*/
|
|
260
260
|
export type { ColumnResolutionStrategy } from './strategies/resolution';
|
|
261
261
|
/**
|
|
262
|
-
* Strategy to filter rows based on criteria.
|
|
262
|
+
* Strategy to filter rows based on criteria. Applied when using getRow/findRow/findRows with filters.
|
|
263
|
+
* The default engine handles string, RegExp, number, and function (cell) => Locator filters.
|
|
263
264
|
*/
|
|
264
265
|
export interface FilterStrategy {
|
|
265
266
|
apply(options: {
|
|
@@ -273,7 +274,8 @@ export interface FilterStrategy {
|
|
|
273
274
|
}): Locator;
|
|
274
275
|
}
|
|
275
276
|
/**
|
|
276
|
-
* Strategy to check if the table or rows are loading.
|
|
277
|
+
* Strategy to check if the table or rows are loading. Used after pagination/sort to wait for content.
|
|
278
|
+
* E.g. isHeaderLoading for init stability; isTableLoading after sort/pagination.
|
|
277
279
|
*/
|
|
278
280
|
export interface LoadingStrategy {
|
|
279
281
|
isTableLoading?: (context: TableContext) => Promise<boolean>;
|
|
@@ -300,26 +302,21 @@ export interface TableStrategies {
|
|
|
300
302
|
getCellLocator?: GetCellLocatorFn;
|
|
301
303
|
/** Function to get the currently active/focused cell */
|
|
302
304
|
getActiveCell?: GetActiveCellFn;
|
|
305
|
+
/**
|
|
306
|
+
* Strategy for filtering rows. If present, FilterEngine will delegate filter application
|
|
307
|
+
* to this pluggable strategy.
|
|
308
|
+
*/
|
|
309
|
+
filter?: FilterStrategy;
|
|
303
310
|
/**
|
|
304
311
|
* Hook called before each cell value is read in toJSON and columnOverrides.read.
|
|
305
312
|
* Fires for both the default innerText extraction and custom read mappers.
|
|
306
313
|
* Useful for scrolling off-screen columns into view in horizontally virtualized tables.
|
|
307
314
|
*/
|
|
308
315
|
beforeCellRead?: BeforeCellReadFn;
|
|
309
|
-
/**
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
row: Locator;
|
|
314
|
-
index: number;
|
|
315
|
-
}) => Promise<boolean>;
|
|
316
|
-
/** Custom helper to check if a cell is fully loaded/ready (e.g. for editing) */
|
|
317
|
-
isCellLoaded?: (args: {
|
|
318
|
-
cell: Locator;
|
|
319
|
-
column: string;
|
|
320
|
-
row: Locator;
|
|
321
|
-
}) => Promise<boolean>;
|
|
322
|
-
/** Strategy for detecting loading states */
|
|
316
|
+
/**
|
|
317
|
+
* Strategy for detecting loading states. Use this for table-, row-, and header-level readiness.
|
|
318
|
+
* E.g. after sort/pagination, the engine uses loading.isTableLoading when present.
|
|
319
|
+
*/
|
|
323
320
|
loading?: LoadingStrategy;
|
|
324
321
|
}
|
|
325
322
|
export interface TableConfig<T = any> {
|
|
@@ -328,7 +325,7 @@ export interface TableConfig<T = any> {
|
|
|
328
325
|
/** Selector for the table rows */
|
|
329
326
|
rowSelector?: string;
|
|
330
327
|
/** Selector for the cells within a row */
|
|
331
|
-
cellSelector?: string;
|
|
328
|
+
cellSelector?: string | ((row: Locator) => Locator);
|
|
332
329
|
/** Number of pages to scan for verification */
|
|
333
330
|
maxPages?: number;
|
|
334
331
|
/** Hook to rename columns dynamically */
|
|
@@ -355,7 +352,7 @@ export interface TableConfig<T = any> {
|
|
|
355
352
|
export interface FinalTableConfig<T = any> extends TableConfig<T> {
|
|
356
353
|
headerSelector: string | ((root: Locator) => Locator);
|
|
357
354
|
rowSelector: string;
|
|
358
|
-
cellSelector: string;
|
|
355
|
+
cellSelector: string | ((row: Locator) => Locator);
|
|
359
356
|
maxPages: number;
|
|
360
357
|
autoScroll: boolean;
|
|
361
358
|
debug?: TableConfig['debug'];
|
|
@@ -427,6 +424,8 @@ export interface TableResult<T = any> extends AsyncIterable<{
|
|
|
427
424
|
/**
|
|
428
425
|
* Finds a row by filters on the current page only. Returns immediately (sync).
|
|
429
426
|
* Throws error if table is not initialized.
|
|
427
|
+
* @note The returned SmartRow may have `rowIndex` as 0 when the match is not the first row.
|
|
428
|
+
* Use getRowByIndex(index) when you need a known index (e.g. for bringIntoView()).
|
|
430
429
|
*/
|
|
431
430
|
getRow: (filters: Record<string, FilterValue>, options?: {
|
|
432
431
|
exact?: boolean;
|
|
@@ -450,10 +449,10 @@ export interface TableResult<T = any> extends AsyncIterable<{
|
|
|
450
449
|
/**
|
|
451
450
|
* ASYNC: Searches for all matching rows across pages using pagination.
|
|
452
451
|
* Auto-initializes the table if not already initialized.
|
|
453
|
-
* @param filters - The filter criteria to match
|
|
452
|
+
* @param filters - The filter criteria to match (omit or pass {} for all rows)
|
|
454
453
|
* @param options - Search options including exact match and max pages
|
|
455
454
|
*/
|
|
456
|
-
findRows: (filters
|
|
455
|
+
findRows: (filters?: Record<string, FilterValue>, options?: {
|
|
457
456
|
exact?: boolean;
|
|
458
457
|
maxPages?: number;
|
|
459
458
|
}) => Promise<SmartRowArray<T>>;
|
package/dist/useTable.js
CHANGED
|
@@ -21,6 +21,9 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar
|
|
|
21
21
|
function reject(value) { resume("throw", value); }
|
|
22
22
|
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
23
23
|
};
|
|
24
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
25
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
26
|
+
};
|
|
24
27
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
28
|
exports.useTable = void 0;
|
|
26
29
|
const minimalConfigContext_1 = require("./minimalConfigContext");
|
|
@@ -28,10 +31,11 @@ const validation_1 = require("./strategies/validation");
|
|
|
28
31
|
const loading_1 = require("./strategies/loading");
|
|
29
32
|
const fill_1 = require("./strategies/fill");
|
|
30
33
|
const headers_1 = require("./strategies/headers");
|
|
31
|
-
const smartRow_1 = require("./smartRow");
|
|
34
|
+
const smartRow_1 = __importDefault(require("./smartRow"));
|
|
32
35
|
const filterEngine_1 = require("./filterEngine");
|
|
33
36
|
const tableMapper_1 = require("./engine/tableMapper");
|
|
34
37
|
const rowFinder_1 = require("./engine/rowFinder");
|
|
38
|
+
const tableIteration_1 = require("./engine/tableIteration");
|
|
35
39
|
const debugUtils_1 = require("./utils/debugUtils");
|
|
36
40
|
const smartRowArray_1 = require("./utils/smartRowArray");
|
|
37
41
|
const elementTracker_1 = require("./utils/elementTracker");
|
|
@@ -91,10 +95,12 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
91
95
|
let finalTable = null;
|
|
92
96
|
// Helper factory
|
|
93
97
|
const _makeSmart = (rowLocator, map, rowIndex, tablePageIndex) => {
|
|
94
|
-
return (0, smartRow_1.
|
|
98
|
+
return (0, smartRow_1.default)(rowLocator, map, rowIndex, config, rootLocator, resolve, finalTable, tablePageIndex);
|
|
95
99
|
};
|
|
96
100
|
const tableState = { currentPageIndex: 0 };
|
|
97
101
|
const rowFinder = new rowFinder_1.RowFinder(rootLocator, config, resolve, filterEngine, tableMapper, _makeSmart, tableState);
|
|
102
|
+
/** Builds a full TableContext/StrategyContext with getHeaderCell, getHeaders, scrollToColumn. Set after result is created. */
|
|
103
|
+
let createStrategyContext = () => ({ root: rootLocator, config, page: rootLocator.page(), resolve });
|
|
98
104
|
const _getCleanHtml = (loc) => __awaiter(void 0, void 0, void 0, function* () {
|
|
99
105
|
return loc.evaluate((el) => {
|
|
100
106
|
const clone = el.cloneNode(true);
|
|
@@ -128,7 +134,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
128
134
|
});
|
|
129
135
|
// Default: goNext (one page). Pass useBulk true to prefer goNextBulk. "How far" uses numeric return when strategy provides it.
|
|
130
136
|
const _advancePage = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (useBulk = false) {
|
|
131
|
-
const context =
|
|
137
|
+
const context = createStrategyContext();
|
|
132
138
|
const pagination = config.strategies.pagination;
|
|
133
139
|
let rawResult;
|
|
134
140
|
if (useBulk && (pagination === null || pagination === void 0 ? void 0 : pagination.goNextBulk)) {
|
|
@@ -183,11 +189,10 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
183
189
|
reset: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
184
190
|
var _a;
|
|
185
191
|
log("Resetting table...");
|
|
186
|
-
|
|
187
|
-
yield config.onReset(context);
|
|
192
|
+
yield config.onReset(createStrategyContext());
|
|
188
193
|
if ((_a = config.strategies.pagination) === null || _a === void 0 ? void 0 : _a.goToFirst) {
|
|
189
194
|
log("Auto-navigating to first page...");
|
|
190
|
-
yield config.strategies.pagination.goToFirst(
|
|
195
|
+
yield config.strategies.pagination.goToFirst(createStrategyContext());
|
|
191
196
|
}
|
|
192
197
|
else if (hasPaginationInConfig) {
|
|
193
198
|
log("No goToFirst strategy configured. Table may not be on page 1.");
|
|
@@ -208,7 +213,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
208
213
|
if (!map)
|
|
209
214
|
throw new Error('Table not initialized. Call await table.init() first, or use async methods like table.findRow() or table.findRows() which auto-initialize.');
|
|
210
215
|
const allRows = resolve(config.rowSelector, rootLocator);
|
|
211
|
-
const matchedRows = filterEngine.applyFilters(allRows, filters, map, options.exact || false, rootLocator.page());
|
|
216
|
+
const matchedRows = filterEngine.applyFilters(allRows, filters, map, options.exact || false, rootLocator.page(), rootLocator);
|
|
212
217
|
const rowLocator = matchedRows.first();
|
|
213
218
|
return _makeSmart(rowLocator, map, 0); // fallback index 0
|
|
214
219
|
},
|
|
@@ -220,11 +225,10 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
220
225
|
return _makeSmart(rowLocator, map, index);
|
|
221
226
|
},
|
|
222
227
|
findRow: (filters, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
223
|
-
// @ts-ignore
|
|
224
228
|
return rowFinder.findRow(filters, options);
|
|
225
229
|
}),
|
|
226
230
|
findRows: (filters, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
227
|
-
return rowFinder.findRows(filters, options);
|
|
231
|
+
return rowFinder.findRows(filters !== null && filters !== void 0 ? filters : {}, options);
|
|
228
232
|
}),
|
|
229
233
|
isInitialized: () => {
|
|
230
234
|
return tableMapper.isInitialized();
|
|
@@ -236,7 +240,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
236
240
|
if (!config.strategies.sorting)
|
|
237
241
|
throw new Error('No sorting strategy has been configured.');
|
|
238
242
|
log(`Applying sort for column "${columnName}" (${direction})`);
|
|
239
|
-
const context = {
|
|
243
|
+
const context = Object.assign(Object.assign({}, createStrategyContext()), { getHeaderCell: result.getHeaderCell });
|
|
240
244
|
const maxRetries = 3;
|
|
241
245
|
for (let i = 0; i < maxRetries; i++) {
|
|
242
246
|
const currentState = yield config.strategies.sorting.getSortState({ columnName, context });
|
|
@@ -264,7 +268,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
264
268
|
yield _autoInit();
|
|
265
269
|
if (!config.strategies.sorting)
|
|
266
270
|
throw new Error('No sorting strategy has been configured.');
|
|
267
|
-
const context = {
|
|
271
|
+
const context = Object.assign(Object.assign({}, createStrategyContext()), { getHeaderCell: result.getHeaderCell });
|
|
268
272
|
return config.strategies.sorting.getSortState({ columnName, context });
|
|
269
273
|
})
|
|
270
274
|
},
|
|
@@ -299,189 +303,42 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
299
303
|
}
|
|
300
304
|
});
|
|
301
305
|
},
|
|
302
|
-
// ───
|
|
306
|
+
// ─── Row iteration (delegated to engine/tableIteration) ──────────────────
|
|
303
307
|
forEach: (callback_1, ...args_1) => __awaiter(void 0, [callback_1, ...args_1], void 0, function* (callback, options = {}) {
|
|
304
|
-
var _a, _b, _c, _d;
|
|
305
308
|
yield _autoInit();
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
let stopped = false;
|
|
316
|
-
let pagesScanned = 1;
|
|
317
|
-
const stop = () => { stopped = true; };
|
|
318
|
-
while (!stopped) {
|
|
319
|
-
const rowLocators = resolve(config.rowSelector, rootLocator);
|
|
320
|
-
const newIndices = yield tracker.getUnseenIndices(rowLocators);
|
|
321
|
-
const pageRows = yield rowLocators.all();
|
|
322
|
-
const smartRows = newIndices.map((idx, i) => _makeSmart(pageRows[idx], map, rowIndex + i));
|
|
323
|
-
if (parallel) {
|
|
324
|
-
yield Promise.all(smartRows.map((row) => __awaiter(void 0, void 0, void 0, function* () {
|
|
325
|
-
if (stopped)
|
|
326
|
-
return;
|
|
327
|
-
if (dedupeKeys) {
|
|
328
|
-
const key = yield dedupeStrategy(row);
|
|
329
|
-
if (dedupeKeys.has(key))
|
|
330
|
-
return;
|
|
331
|
-
dedupeKeys.add(key);
|
|
332
|
-
}
|
|
333
|
-
yield callback({ row, rowIndex: row.rowIndex, stop });
|
|
334
|
-
})));
|
|
335
|
-
}
|
|
336
|
-
else {
|
|
337
|
-
for (const row of smartRows) {
|
|
338
|
-
if (stopped)
|
|
339
|
-
break;
|
|
340
|
-
if (dedupeKeys) {
|
|
341
|
-
const key = yield dedupeStrategy(row);
|
|
342
|
-
if (dedupeKeys.has(key))
|
|
343
|
-
continue;
|
|
344
|
-
dedupeKeys.add(key);
|
|
345
|
-
}
|
|
346
|
-
yield callback({ row, rowIndex: row.rowIndex, stop });
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
rowIndex += smartRows.length;
|
|
350
|
-
if (stopped || pagesScanned >= effectiveMaxPages)
|
|
351
|
-
break;
|
|
352
|
-
if (!(yield _advancePage(useBulk)))
|
|
353
|
-
break;
|
|
354
|
-
pagesScanned++;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
finally {
|
|
358
|
-
yield tracker.cleanup(rootLocator.page());
|
|
359
|
-
}
|
|
309
|
+
yield (0, tableIteration_1.runForEach)({
|
|
310
|
+
getRowLocators: () => resolve(config.rowSelector, rootLocator),
|
|
311
|
+
getMap: () => tableMapper.getMapSync(),
|
|
312
|
+
advancePage: _advancePage,
|
|
313
|
+
makeSmartRow: (loc, map, idx, pageIdx) => _makeSmart(loc, map, idx, pageIdx),
|
|
314
|
+
createSmartRowArray: smartRowArray_1.createSmartRowArray,
|
|
315
|
+
config,
|
|
316
|
+
getPage: () => rootLocator.page(),
|
|
317
|
+
}, callback, options);
|
|
360
318
|
}),
|
|
361
319
|
map: (callback_1, ...args_1) => __awaiter(void 0, [callback_1, ...args_1], void 0, function* (callback, options = {}) {
|
|
362
|
-
var _a, _b, _c, _d;
|
|
363
320
|
yield _autoInit();
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
let rowIndex = 0;
|
|
374
|
-
let stopped = false;
|
|
375
|
-
let pagesScanned = 1;
|
|
376
|
-
const stop = () => { stopped = true; };
|
|
377
|
-
while (!stopped) {
|
|
378
|
-
const rowLocators = resolve(config.rowSelector, rootLocator);
|
|
379
|
-
const newIndices = yield tracker.getUnseenIndices(rowLocators);
|
|
380
|
-
const pageRows = yield rowLocators.all();
|
|
381
|
-
const smartRows = newIndices.map((idx, i) => _makeSmart(pageRows[idx], map, rowIndex + i));
|
|
382
|
-
if (parallel) {
|
|
383
|
-
const SKIP = Symbol('skip');
|
|
384
|
-
const pageResults = yield Promise.all(smartRows.map((row) => __awaiter(void 0, void 0, void 0, function* () {
|
|
385
|
-
if (dedupeKeys) {
|
|
386
|
-
const key = yield dedupeStrategy(row);
|
|
387
|
-
if (dedupeKeys.has(key))
|
|
388
|
-
return SKIP;
|
|
389
|
-
dedupeKeys.add(key);
|
|
390
|
-
}
|
|
391
|
-
return callback({ row, rowIndex: row.rowIndex, stop });
|
|
392
|
-
})));
|
|
393
|
-
for (const r of pageResults) {
|
|
394
|
-
if (r !== SKIP)
|
|
395
|
-
results.push(r);
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
else {
|
|
399
|
-
for (const row of smartRows) {
|
|
400
|
-
if (stopped)
|
|
401
|
-
break;
|
|
402
|
-
if (dedupeKeys) {
|
|
403
|
-
const key = yield dedupeStrategy(row);
|
|
404
|
-
if (dedupeKeys.has(key))
|
|
405
|
-
continue;
|
|
406
|
-
dedupeKeys.add(key);
|
|
407
|
-
}
|
|
408
|
-
results.push(yield callback({ row, rowIndex: row.rowIndex, stop }));
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
rowIndex += smartRows.length;
|
|
412
|
-
if (stopped || pagesScanned >= effectiveMaxPages)
|
|
413
|
-
break;
|
|
414
|
-
if (!(yield _advancePage(useBulk)))
|
|
415
|
-
break;
|
|
416
|
-
pagesScanned++;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
finally {
|
|
420
|
-
yield tracker.cleanup(rootLocator.page());
|
|
421
|
-
}
|
|
422
|
-
return results;
|
|
321
|
+
return (0, tableIteration_1.runMap)({
|
|
322
|
+
getRowLocators: () => resolve(config.rowSelector, rootLocator),
|
|
323
|
+
getMap: () => tableMapper.getMapSync(),
|
|
324
|
+
advancePage: _advancePage,
|
|
325
|
+
makeSmartRow: (loc, map, idx, pageIdx) => _makeSmart(loc, map, idx, pageIdx),
|
|
326
|
+
createSmartRowArray: smartRowArray_1.createSmartRowArray,
|
|
327
|
+
config,
|
|
328
|
+
getPage: () => rootLocator.page(),
|
|
329
|
+
}, callback, options);
|
|
423
330
|
}),
|
|
424
331
|
filter: (predicate_1, ...args_1) => __awaiter(void 0, [predicate_1, ...args_1], void 0, function* (predicate, options = {}) {
|
|
425
|
-
var _a, _b, _c, _d;
|
|
426
332
|
yield _autoInit();
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
let rowIndex = 0;
|
|
437
|
-
let stopped = false;
|
|
438
|
-
let pagesScanned = 1;
|
|
439
|
-
const stop = () => { stopped = true; };
|
|
440
|
-
while (!stopped) {
|
|
441
|
-
const rowLocators = resolve(config.rowSelector, rootLocator);
|
|
442
|
-
const newIndices = yield tracker.getUnseenIndices(rowLocators);
|
|
443
|
-
const pageRows = yield rowLocators.all();
|
|
444
|
-
const smartRows = newIndices.map((idx, i) => _makeSmart(pageRows[idx], map, rowIndex + i, pagesScanned - 1));
|
|
445
|
-
if (parallel) {
|
|
446
|
-
const flags = yield Promise.all(smartRows.map((row) => __awaiter(void 0, void 0, void 0, function* () {
|
|
447
|
-
if (dedupeKeys) {
|
|
448
|
-
const key = yield dedupeStrategy(row);
|
|
449
|
-
if (dedupeKeys.has(key))
|
|
450
|
-
return false;
|
|
451
|
-
dedupeKeys.add(key);
|
|
452
|
-
}
|
|
453
|
-
return predicate({ row, rowIndex: row.rowIndex, stop });
|
|
454
|
-
})));
|
|
455
|
-
smartRows.forEach((row, i) => { if (flags[i])
|
|
456
|
-
matched.push(row); });
|
|
457
|
-
}
|
|
458
|
-
else {
|
|
459
|
-
for (const row of smartRows) {
|
|
460
|
-
if (stopped)
|
|
461
|
-
break;
|
|
462
|
-
if (dedupeKeys) {
|
|
463
|
-
const key = yield dedupeStrategy(row);
|
|
464
|
-
if (dedupeKeys.has(key))
|
|
465
|
-
continue;
|
|
466
|
-
dedupeKeys.add(key);
|
|
467
|
-
}
|
|
468
|
-
if (yield predicate({ row, rowIndex: row.rowIndex, stop })) {
|
|
469
|
-
matched.push(row);
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
rowIndex += smartRows.length;
|
|
474
|
-
if (stopped || pagesScanned >= effectiveMaxPages)
|
|
475
|
-
break;
|
|
476
|
-
if (!(yield _advancePage(useBulk)))
|
|
477
|
-
break;
|
|
478
|
-
pagesScanned++;
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
finally {
|
|
482
|
-
yield tracker.cleanup(rootLocator.page());
|
|
483
|
-
}
|
|
484
|
-
return (0, smartRowArray_1.createSmartRowArray)(matched);
|
|
333
|
+
return (0, tableIteration_1.runFilter)({
|
|
334
|
+
getRowLocators: () => resolve(config.rowSelector, rootLocator),
|
|
335
|
+
getMap: () => tableMapper.getMapSync(),
|
|
336
|
+
advancePage: _advancePage,
|
|
337
|
+
makeSmartRow: (loc, map, idx, pageIdx) => _makeSmart(loc, map, idx, pageIdx),
|
|
338
|
+
createSmartRowArray: smartRowArray_1.createSmartRowArray,
|
|
339
|
+
config,
|
|
340
|
+
getPage: () => rootLocator.page(),
|
|
341
|
+
}, predicate, options);
|
|
485
342
|
}),
|
|
486
343
|
generateConfig: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
487
344
|
const html = yield _getCleanHtml(rootLocator);
|
|
@@ -494,6 +351,15 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
494
351
|
return result.generateConfig();
|
|
495
352
|
}),
|
|
496
353
|
};
|
|
354
|
+
createStrategyContext = () => ({
|
|
355
|
+
root: rootLocator,
|
|
356
|
+
config,
|
|
357
|
+
page: rootLocator.page(),
|
|
358
|
+
resolve,
|
|
359
|
+
getHeaderCell: result.getHeaderCell,
|
|
360
|
+
getHeaders: result.getHeaders,
|
|
361
|
+
scrollToColumn: result.scrollToColumn,
|
|
362
|
+
});
|
|
497
363
|
finalTable = result;
|
|
498
364
|
return result;
|
|
499
365
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SENTINEL_ROW = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Internal symbol used to mark a SmartRow as a "sentinel" (row not found).
|
|
6
|
+
* Use SmartRow.wasFound() to detect; do not rely on this symbol in user code.
|
|
7
|
+
*/
|
|
8
|
+
exports.SENTINEL_ROW = Symbol.for('playwright-smart-table.sentinelRow');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rickcedwhat/playwright-smart-table",
|
|
3
|
-
"version": "6.7.
|
|
3
|
+
"version": "6.7.6",
|
|
4
4
|
"description": "Smart, column-aware table interactions for Playwright",
|
|
5
5
|
"author": "Cedrick Catalan",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,12 +27,11 @@
|
|
|
27
27
|
"pretest": "npm run clean-port",
|
|
28
28
|
"posttest": "npm run clean-port",
|
|
29
29
|
"test": "npm run test:unit && npx playwright test",
|
|
30
|
-
"test:unit": "vitest run --reporter=verbose --reporter=html",
|
|
30
|
+
"test:unit": "vitest run --coverage --reporter=verbose --reporter=html",
|
|
31
31
|
"test:unit:ui": "vitest --ui",
|
|
32
32
|
"pretest:e2e": "npm run clean-port",
|
|
33
33
|
"posttest:e2e": "npm run clean-port",
|
|
34
34
|
"test:e2e": "npx playwright test",
|
|
35
|
-
"test:compatibility": "npm run clean-port && npx playwright test compatibility",
|
|
36
35
|
"prepare": "husky install"
|
|
37
36
|
},
|
|
38
37
|
"keywords": [
|
|
@@ -47,6 +46,7 @@
|
|
|
47
46
|
"devDependencies": {
|
|
48
47
|
"@playwright/test": "^1.49.1",
|
|
49
48
|
"@types/node": "^22.10.5",
|
|
49
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
50
50
|
"@vitest/ui": "^4.0.18",
|
|
51
51
|
"happy-dom": "^20.6.1",
|
|
52
52
|
"husky": "^9.1.7",
|
|
@@ -54,4 +54,4 @@
|
|
|
54
54
|
"vitepress": "^1.6.4",
|
|
55
55
|
"vitest": "^4.0.18"
|
|
56
56
|
}
|
|
57
|
-
}
|
|
57
|
+
}
|
package/dist/plugins.d.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
export declare const Plugins: {
|
|
2
|
-
RDG: {
|
|
3
|
-
Strategies: {
|
|
4
|
-
header: (context: import("./types").TableContext) => Promise<string[]>;
|
|
5
|
-
getCellLocator: ({ row, columnIndex }: any) => any;
|
|
6
|
-
navigation: {
|
|
7
|
-
goRight: ({ root, page }: any) => Promise<void>;
|
|
8
|
-
goLeft: ({ root, page }: any) => Promise<void>;
|
|
9
|
-
goDown: ({ root, page }: any) => Promise<void>;
|
|
10
|
-
goUp: ({ root, page }: any) => Promise<void>;
|
|
11
|
-
goHome: ({ root, page }: any) => Promise<void>;
|
|
12
|
-
};
|
|
13
|
-
pagination: import("./types").PaginationPrimitives;
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
Glide: {
|
|
17
|
-
Strategies: {
|
|
18
|
-
fill: import("./types").FillStrategy;
|
|
19
|
-
fillSimple: import("./types").FillStrategy;
|
|
20
|
-
pagination: import("./types").PaginationPrimitives;
|
|
21
|
-
header: (context: import("./types").StrategyContext, options?: {
|
|
22
|
-
limit?: number;
|
|
23
|
-
selector?: string;
|
|
24
|
-
scrollAmount?: number;
|
|
25
|
-
}) => Promise<string[]>;
|
|
26
|
-
navigation: {
|
|
27
|
-
goUp: (context: import("./types").StrategyContext) => Promise<void>;
|
|
28
|
-
goDown: (context: import("./types").StrategyContext) => Promise<void>;
|
|
29
|
-
goLeft: (context: import("./types").StrategyContext) => Promise<void>;
|
|
30
|
-
goRight: (context: import("./types").StrategyContext) => Promise<void>;
|
|
31
|
-
goHome: (context: import("./types").StrategyContext) => Promise<void>;
|
|
32
|
-
};
|
|
33
|
-
loading: {
|
|
34
|
-
isHeaderLoading: () => Promise<boolean>;
|
|
35
|
-
};
|
|
36
|
-
getCellLocator: ({ row, columnIndex }: any) => any;
|
|
37
|
-
getActiveCell: ({ page }: any) => Promise<{
|
|
38
|
-
rowIndex: number;
|
|
39
|
-
columnIndex: number;
|
|
40
|
-
locator: any;
|
|
41
|
-
} | null>;
|
|
42
|
-
};
|
|
43
|
-
};
|
|
44
|
-
};
|
package/dist/plugins.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Plugins = void 0;
|
|
4
|
-
const rdg_1 = require("./strategies/rdg");
|
|
5
|
-
const glide_1 = require("./strategies/glide");
|
|
6
|
-
exports.Plugins = {
|
|
7
|
-
RDG: {
|
|
8
|
-
Strategies: rdg_1.RDGStrategies
|
|
9
|
-
},
|
|
10
|
-
Glide: {
|
|
11
|
-
Strategies: glide_1.GlideStrategies
|
|
12
|
-
}
|
|
13
|
-
};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { FillStrategy } from '../types';
|
|
2
|
-
/**
|
|
3
|
-
* Fill strategy for Glide Data Grid with textarea validation.
|
|
4
|
-
* This is the default strategy that works with the standard Glide Data Grid editor.
|
|
5
|
-
*/
|
|
6
|
-
export declare const glideFillStrategy: FillStrategy;
|
|
7
|
-
/**
|
|
8
|
-
* Simple fill strategy for Glide Data Grid.
|
|
9
|
-
* Use this if your Glide implementation doesn't use the standard textarea editor.
|
|
10
|
-
* This is faster but may not work for all Glide configurations.
|
|
11
|
-
*/
|
|
12
|
-
export declare const glideFillSimple: FillStrategy;
|
|
13
|
-
export declare const glidePaginationStrategy: import("../types").PaginationPrimitives;
|
|
14
|
-
export declare const glideGetCellLocator: ({ row, columnIndex }: any) => any;
|
|
15
|
-
export declare const glideGetActiveCell: ({ page }: any) => Promise<{
|
|
16
|
-
rowIndex: number;
|
|
17
|
-
columnIndex: number;
|
|
18
|
-
locator: any;
|
|
19
|
-
} | null>;
|
|
20
|
-
export declare const GlideStrategies: {
|
|
21
|
-
fill: FillStrategy;
|
|
22
|
-
fillSimple: FillStrategy;
|
|
23
|
-
pagination: import("../types").PaginationPrimitives;
|
|
24
|
-
header: (context: import("../types").StrategyContext, options?: {
|
|
25
|
-
limit?: number;
|
|
26
|
-
selector?: string;
|
|
27
|
-
scrollAmount?: number;
|
|
28
|
-
}) => Promise<string[]>;
|
|
29
|
-
navigation: {
|
|
30
|
-
goUp: (context: import("../types").StrategyContext) => Promise<void>;
|
|
31
|
-
goDown: (context: import("../types").StrategyContext) => Promise<void>;
|
|
32
|
-
goLeft: (context: import("../types").StrategyContext) => Promise<void>;
|
|
33
|
-
goRight: (context: import("../types").StrategyContext) => Promise<void>;
|
|
34
|
-
goHome: (context: import("../types").StrategyContext) => Promise<void>;
|
|
35
|
-
};
|
|
36
|
-
loading: {
|
|
37
|
-
isHeaderLoading: () => Promise<boolean>;
|
|
38
|
-
};
|
|
39
|
-
getCellLocator: ({ row, columnIndex }: any) => any;
|
|
40
|
-
getActiveCell: ({ page }: any) => Promise<{
|
|
41
|
-
rowIndex: number;
|
|
42
|
-
columnIndex: number;
|
|
43
|
-
locator: any;
|
|
44
|
-
} | null>;
|
|
45
|
-
};
|
package/dist/strategies/rdg.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { TableContext } from '../types';
|
|
2
|
-
/**
|
|
3
|
-
* Scrolls the grid horizontally to collect all column headers.
|
|
4
|
-
* Handles empty headers by labeling them (e.g. "Checkbox").
|
|
5
|
-
*/
|
|
6
|
-
export declare const scrollRightHeaderRDG: (context: TableContext) => Promise<string[]>;
|
|
7
|
-
/**
|
|
8
|
-
* Uses a row-relative locator to avoid issues with absolute aria-rowindex
|
|
9
|
-
* changing during pagination/scrolling.
|
|
10
|
-
*/
|
|
11
|
-
export declare const rdgGetCellLocator: ({ row, columnIndex }: any) => any;
|
|
12
|
-
/**
|
|
13
|
-
* Scrolls the grid vertically to load more virtualized rows.
|
|
14
|
-
*/
|
|
15
|
-
export declare const rdgPaginationStrategy: import("../types").PaginationPrimitives;
|
|
16
|
-
export declare const rdgNavigation: {
|
|
17
|
-
goRight: ({ root, page }: any) => Promise<void>;
|
|
18
|
-
goLeft: ({ root, page }: any) => Promise<void>;
|
|
19
|
-
goDown: ({ root, page }: any) => Promise<void>;
|
|
20
|
-
goUp: ({ root, page }: any) => Promise<void>;
|
|
21
|
-
goHome: ({ root, page }: any) => Promise<void>;
|
|
22
|
-
};
|
|
23
|
-
export declare const RDGStrategies: {
|
|
24
|
-
header: (context: TableContext) => Promise<string[]>;
|
|
25
|
-
getCellLocator: ({ row, columnIndex }: any) => any;
|
|
26
|
-
navigation: {
|
|
27
|
-
goRight: ({ root, page }: any) => Promise<void>;
|
|
28
|
-
goLeft: ({ root, page }: any) => Promise<void>;
|
|
29
|
-
goDown: ({ root, page }: any) => Promise<void>;
|
|
30
|
-
goUp: ({ root, page }: any) => Promise<void>;
|
|
31
|
-
goHome: ({ root, page }: any) => Promise<void>;
|
|
32
|
-
};
|
|
33
|
-
pagination: import("../types").PaginationPrimitives;
|
|
34
|
-
};
|
|
File without changes
|
|
File without changes
|