@rickcedwhat/playwright-smart-table 6.7.3 ā 6.7.5
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 +2 -0
- package/dist/engine/rowFinder.d.ts +1 -1
- package/dist/engine/rowFinder.js +20 -29
- package/dist/engine/tableIteration.d.ts +25 -0
- package/dist/engine/tableIteration.js +210 -0
- package/dist/minimalConfigContext.d.ts +1 -1
- package/dist/minimalConfigContext.js +0 -3
- package/dist/plugins/glide/columns.d.ts +11 -0
- package/dist/plugins/glide/columns.js +51 -0
- package/dist/plugins/glide/headers.d.ts +9 -0
- package/dist/plugins/glide/headers.js +65 -0
- package/dist/plugins/glide/index.d.ts +31 -0
- package/dist/plugins/glide/index.js +104 -0
- package/dist/plugins/glide.d.ts +31 -0
- package/dist/plugins/glide.js +104 -0
- 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/mui.d.ts +8 -0
- package/dist/plugins/mui.js +25 -0
- package/dist/plugins/rdg/index.d.ts +17 -0
- package/dist/plugins/rdg/index.js +124 -0
- package/dist/plugins/rdg.d.ts +17 -0
- package/dist/plugins/rdg.js +124 -0
- package/dist/plugins.d.ts +12 -40
- package/dist/plugins.js +9 -6
- package/dist/smartRow.js +42 -32
- package/dist/strategies/glide.d.ts +7 -21
- package/dist/strategies/glide.js +22 -12
- package/dist/strategies/mui.d.ts +8 -0
- package/dist/strategies/mui.js +25 -0
- package/dist/strategies/pagination.js +25 -4
- package/dist/strategies/rdg.d.ts +6 -23
- package/dist/strategies/rdg.js +23 -10
- package/dist/strategies/validation.d.ts +2 -7
- package/dist/strategies/validation.js +1 -12
- package/dist/typeContext.d.ts +2 -2
- package/dist/typeContext.js +37 -17
- package/dist/types.d.ts +33 -23
- package/dist/useTable.js +72 -194
- package/dist/utils/paginationPath.d.ts +37 -0
- package/dist/utils/paginationPath.js +227 -0
- package/dist/utils/sentinel.d.ts +5 -0
- package/dist/utils/sentinel.js +8 -0
- package/package.json +1 -1
package/dist/typeContext.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TYPE_CONTEXT = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* š¤ AUTO-GENERATED FILE. DO NOT EDIT.
|
|
6
|
-
* This file is generated by scripts/embed-types.
|
|
6
|
+
* This file is generated by scripts/embed-types.mjs
|
|
7
7
|
* It contains the raw text of types.ts to provide context for LLM prompts.
|
|
8
8
|
*/
|
|
9
9
|
exports.TYPE_CONTEXT = `
|
|
@@ -240,11 +240,21 @@ export interface PaginationPrimitives {
|
|
|
240
240
|
/** Jump to first page / scroll to top */
|
|
241
241
|
goToFirst?: (context: TableContext) => Promise<boolean>;
|
|
242
242
|
|
|
243
|
-
/**
|
|
243
|
+
/**
|
|
244
|
+
* Jump to specific page index (0-indexed).
|
|
245
|
+
* Can be full-range (e.g. page number input: any page works) or windowed (e.g. only visible links 6ā14).
|
|
246
|
+
* Return false when the page is not reachable in the current UI; the library will step toward the target (goNextBulk/goNext or goPreviousBulk/goPrevious) and retry goToPage until it succeeds.
|
|
247
|
+
*/
|
|
244
248
|
goToPage?: (pageIndex: number, context: TableContext) => Promise<boolean>;
|
|
249
|
+
|
|
250
|
+
/** How many pages one goNextBulk() advances. Used by navigation path planner for optimal bringIntoView. */
|
|
251
|
+
nextBulkPages?: number;
|
|
252
|
+
|
|
253
|
+
/** How many pages one goPreviousBulk() goes back. Used by navigation path planner for optimal bringIntoView. */
|
|
254
|
+
previousBulkPages?: number;
|
|
245
255
|
}
|
|
246
256
|
|
|
247
|
-
export type PaginationStrategy =
|
|
257
|
+
export type PaginationStrategy = PaginationPrimitives;
|
|
248
258
|
|
|
249
259
|
export type DedupeStrategy = (row: SmartRow) => string | number | Promise<string | number>;
|
|
250
260
|
|
|
@@ -288,7 +298,8 @@ export type { HeaderStrategy } from './strategies/headers';
|
|
|
288
298
|
export type { ColumnResolutionStrategy } from './strategies/resolution';
|
|
289
299
|
|
|
290
300
|
/**
|
|
291
|
-
* Strategy to filter rows based on criteria.
|
|
301
|
+
* Strategy to filter rows based on criteria. Applied when using getRow/findRow/findRows with filters.
|
|
302
|
+
* The default engine handles string, RegExp, number, and function (cell) => Locator filters.
|
|
292
303
|
*/
|
|
293
304
|
export interface FilterStrategy {
|
|
294
305
|
apply(options: {
|
|
@@ -300,7 +311,8 @@ export interface FilterStrategy {
|
|
|
300
311
|
}
|
|
301
312
|
|
|
302
313
|
/**
|
|
303
|
-
* Strategy to check if the table or rows are loading.
|
|
314
|
+
* Strategy to check if the table or rows are loading. Used after pagination/sort to wait for content.
|
|
315
|
+
* E.g. isHeaderLoading for init stability; isTableLoading after sort/pagination.
|
|
304
316
|
*/
|
|
305
317
|
export interface LoadingStrategy {
|
|
306
318
|
isTableLoading?: (context: TableContext) => Promise<boolean>;
|
|
@@ -335,13 +347,10 @@ export interface TableStrategies {
|
|
|
335
347
|
* Useful for scrolling off-screen columns into view in horizontally virtualized tables.
|
|
336
348
|
*/
|
|
337
349
|
beforeCellRead?: BeforeCellReadFn;
|
|
338
|
-
/**
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
/** Custom helper to check if a cell is fully loaded/ready (e.g. for editing) */
|
|
343
|
-
isCellLoaded?: (args: { cell: Locator, column: string, row: Locator }) => Promise<boolean>;
|
|
344
|
-
/** Strategy for detecting loading states */
|
|
350
|
+
/**
|
|
351
|
+
* Strategy for detecting loading states. Use this for table-, row-, and header-level readiness.
|
|
352
|
+
* E.g. after sort/pagination, the engine uses loading.isTableLoading when present.
|
|
353
|
+
*/
|
|
345
354
|
loading?: LoadingStrategy;
|
|
346
355
|
}
|
|
347
356
|
|
|
@@ -417,6 +426,11 @@ export type RowIterationOptions = {
|
|
|
417
426
|
* (e.g. infinite scroll tables). Returns a unique key per row.
|
|
418
427
|
*/
|
|
419
428
|
dedupe?: DedupeStrategy;
|
|
429
|
+
/**
|
|
430
|
+
* When true, use goNextBulk (if present) to advance pages during iteration.
|
|
431
|
+
* @default false ā uses goNext for one-page-at-a-time advancement
|
|
432
|
+
*/
|
|
433
|
+
useBulkPagination?: boolean;
|
|
420
434
|
};
|
|
421
435
|
|
|
422
436
|
export interface TableResult<T = any> extends AsyncIterable<{ row: SmartRow<T>; rowIndex: number }> {
|
|
@@ -444,6 +458,8 @@ export interface TableResult<T = any> extends AsyncIterable<{ row: SmartRow<T>;
|
|
|
444
458
|
/**
|
|
445
459
|
* Finds a row by filters on the current page only. Returns immediately (sync).
|
|
446
460
|
* Throws error if table is not initialized.
|
|
461
|
+
* @note The returned SmartRow may have \`rowIndex\` as 0 when the match is not the first row.
|
|
462
|
+
* Use getRowByIndex(index) when you need a known index (e.g. for bringIntoView()).
|
|
447
463
|
*/
|
|
448
464
|
getRow: (
|
|
449
465
|
filters: Record<string, FilterValue>,
|
|
@@ -451,10 +467,9 @@ export interface TableResult<T = any> extends AsyncIterable<{ row: SmartRow<T>;
|
|
|
451
467
|
) => SmartRow;
|
|
452
468
|
|
|
453
469
|
/**
|
|
454
|
-
* Gets a row by
|
|
470
|
+
* Gets a row by 0-based index on the current page.
|
|
455
471
|
* Throws error if table is not initialized.
|
|
456
|
-
* @param index
|
|
457
|
-
* @param options Optional settings including bringIntoView
|
|
472
|
+
* @param index 0-based row index
|
|
458
473
|
*/
|
|
459
474
|
getRowByIndex: (
|
|
460
475
|
index: number
|
|
@@ -474,11 +489,11 @@ export interface TableResult<T = any> extends AsyncIterable<{ row: SmartRow<T>;
|
|
|
474
489
|
/**
|
|
475
490
|
* ASYNC: Searches for all matching rows across pages using pagination.
|
|
476
491
|
* Auto-initializes the table if not already initialized.
|
|
477
|
-
* @param filters - The filter criteria to match
|
|
492
|
+
* @param filters - The filter criteria to match (omit or pass {} for all rows)
|
|
478
493
|
* @param options - Search options including exact match and max pages
|
|
479
494
|
*/
|
|
480
495
|
findRows: (
|
|
481
|
-
filters
|
|
496
|
+
filters?: Record<string, FilterValue>,
|
|
482
497
|
options?: { exact?: boolean, maxPages?: number }
|
|
483
498
|
) => Promise<SmartRowArray<T>>;
|
|
484
499
|
|
|
@@ -581,6 +596,11 @@ export interface TableResult<T = any> extends AsyncIterable<{ row: SmartRow<T>;
|
|
|
581
596
|
* Outputs table HTML and TypeScript definitions to help AI assistants generate config.
|
|
582
597
|
* Automatically throws an Error containing the prompt.
|
|
583
598
|
*/
|
|
599
|
+
generateConfig: () => Promise<void>;
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* @deprecated Use \`generateConfig()\` instead. Will be removed in v7.0.0.
|
|
603
|
+
*/
|
|
584
604
|
generateConfigPrompt: () => Promise<void>;
|
|
585
605
|
}
|
|
586
606
|
`;
|
package/dist/types.d.ts
CHANGED
|
@@ -211,10 +211,18 @@ export interface PaginationPrimitives {
|
|
|
211
211
|
goPreviousBulk?: (context: TableContext) => Promise<boolean | number>;
|
|
212
212
|
/** Jump to first page / scroll to top */
|
|
213
213
|
goToFirst?: (context: TableContext) => Promise<boolean>;
|
|
214
|
-
/**
|
|
214
|
+
/**
|
|
215
|
+
* Jump to specific page index (0-indexed).
|
|
216
|
+
* Can be full-range (e.g. page number input: any page works) or windowed (e.g. only visible links 6ā14).
|
|
217
|
+
* Return false when the page is not reachable in the current UI; the library will step toward the target (goNextBulk/goNext or goPreviousBulk/goPrevious) and retry goToPage until it succeeds.
|
|
218
|
+
*/
|
|
215
219
|
goToPage?: (pageIndex: number, context: TableContext) => Promise<boolean>;
|
|
220
|
+
/** How many pages one goNextBulk() advances. Used by navigation path planner for optimal bringIntoView. */
|
|
221
|
+
nextBulkPages?: number;
|
|
222
|
+
/** How many pages one goPreviousBulk() goes back. Used by navigation path planner for optimal bringIntoView. */
|
|
223
|
+
previousBulkPages?: number;
|
|
216
224
|
}
|
|
217
|
-
export type PaginationStrategy =
|
|
225
|
+
export type PaginationStrategy = PaginationPrimitives;
|
|
218
226
|
export type DedupeStrategy = (row: SmartRow) => string | number | Promise<string | number>;
|
|
219
227
|
export type FillStrategy = (options: {
|
|
220
228
|
row: SmartRow;
|
|
@@ -251,7 +259,8 @@ import { NavigationPrimitives } from './strategies/columns';
|
|
|
251
259
|
*/
|
|
252
260
|
export type { ColumnResolutionStrategy } from './strategies/resolution';
|
|
253
261
|
/**
|
|
254
|
-
* 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.
|
|
255
264
|
*/
|
|
256
265
|
export interface FilterStrategy {
|
|
257
266
|
apply(options: {
|
|
@@ -265,7 +274,8 @@ export interface FilterStrategy {
|
|
|
265
274
|
}): Locator;
|
|
266
275
|
}
|
|
267
276
|
/**
|
|
268
|
-
* 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.
|
|
269
279
|
*/
|
|
270
280
|
export interface LoadingStrategy {
|
|
271
281
|
isTableLoading?: (context: TableContext) => Promise<boolean>;
|
|
@@ -298,20 +308,10 @@ export interface TableStrategies {
|
|
|
298
308
|
* Useful for scrolling off-screen columns into view in horizontally virtualized tables.
|
|
299
309
|
*/
|
|
300
310
|
beforeCellRead?: BeforeCellReadFn;
|
|
301
|
-
/**
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
row: Locator;
|
|
306
|
-
index: number;
|
|
307
|
-
}) => Promise<boolean>;
|
|
308
|
-
/** Custom helper to check if a cell is fully loaded/ready (e.g. for editing) */
|
|
309
|
-
isCellLoaded?: (args: {
|
|
310
|
-
cell: Locator;
|
|
311
|
-
column: string;
|
|
312
|
-
row: Locator;
|
|
313
|
-
}) => Promise<boolean>;
|
|
314
|
-
/** Strategy for detecting loading states */
|
|
311
|
+
/**
|
|
312
|
+
* Strategy for detecting loading states. Use this for table-, row-, and header-level readiness.
|
|
313
|
+
* E.g. after sort/pagination, the engine uses loading.isTableLoading when present.
|
|
314
|
+
*/
|
|
315
315
|
loading?: LoadingStrategy;
|
|
316
316
|
}
|
|
317
317
|
export interface TableConfig<T = any> {
|
|
@@ -387,6 +387,11 @@ export type RowIterationOptions = {
|
|
|
387
387
|
* (e.g. infinite scroll tables). Returns a unique key per row.
|
|
388
388
|
*/
|
|
389
389
|
dedupe?: DedupeStrategy;
|
|
390
|
+
/**
|
|
391
|
+
* When true, use goNextBulk (if present) to advance pages during iteration.
|
|
392
|
+
* @default false ā uses goNext for one-page-at-a-time advancement
|
|
393
|
+
*/
|
|
394
|
+
useBulkPagination?: boolean;
|
|
390
395
|
};
|
|
391
396
|
export interface TableResult<T = any> extends AsyncIterable<{
|
|
392
397
|
row: SmartRow<T>;
|
|
@@ -414,15 +419,16 @@ export interface TableResult<T = any> extends AsyncIterable<{
|
|
|
414
419
|
/**
|
|
415
420
|
* Finds a row by filters on the current page only. Returns immediately (sync).
|
|
416
421
|
* Throws error if table is not initialized.
|
|
422
|
+
* @note The returned SmartRow may have `rowIndex` as 0 when the match is not the first row.
|
|
423
|
+
* Use getRowByIndex(index) when you need a known index (e.g. for bringIntoView()).
|
|
417
424
|
*/
|
|
418
425
|
getRow: (filters: Record<string, FilterValue>, options?: {
|
|
419
426
|
exact?: boolean;
|
|
420
427
|
}) => SmartRow;
|
|
421
428
|
/**
|
|
422
|
-
* Gets a row by
|
|
429
|
+
* Gets a row by 0-based index on the current page.
|
|
423
430
|
* Throws error if table is not initialized.
|
|
424
|
-
* @param index
|
|
425
|
-
* @param options Optional settings including bringIntoView
|
|
431
|
+
* @param index 0-based row index
|
|
426
432
|
*/
|
|
427
433
|
getRowByIndex: (index: number) => SmartRow;
|
|
428
434
|
/**
|
|
@@ -438,10 +444,10 @@ export interface TableResult<T = any> extends AsyncIterable<{
|
|
|
438
444
|
/**
|
|
439
445
|
* ASYNC: Searches for all matching rows across pages using pagination.
|
|
440
446
|
* Auto-initializes the table if not already initialized.
|
|
441
|
-
* @param filters - The filter criteria to match
|
|
447
|
+
* @param filters - The filter criteria to match (omit or pass {} for all rows)
|
|
442
448
|
* @param options - Search options including exact match and max pages
|
|
443
449
|
*/
|
|
444
|
-
findRows: (filters
|
|
450
|
+
findRows: (filters?: Record<string, FilterValue>, options?: {
|
|
445
451
|
exact?: boolean;
|
|
446
452
|
maxPages?: number;
|
|
447
453
|
}) => Promise<SmartRowArray<T>>;
|
|
@@ -526,5 +532,9 @@ export interface TableResult<T = any> extends AsyncIterable<{
|
|
|
526
532
|
* Outputs table HTML and TypeScript definitions to help AI assistants generate config.
|
|
527
533
|
* Automatically throws an Error containing the prompt.
|
|
528
534
|
*/
|
|
535
|
+
generateConfig: () => Promise<void>;
|
|
536
|
+
/**
|
|
537
|
+
* @deprecated Use `generateConfig()` instead. Will be removed in v7.0.0.
|
|
538
|
+
*/
|
|
529
539
|
generateConfigPrompt: () => Promise<void>;
|
|
530
540
|
}
|
package/dist/useTable.js
CHANGED
|
@@ -24,6 +24,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar
|
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
25
|
exports.useTable = void 0;
|
|
26
26
|
const minimalConfigContext_1 = require("./minimalConfigContext");
|
|
27
|
+
const validation_1 = require("./strategies/validation");
|
|
27
28
|
const loading_1 = require("./strategies/loading");
|
|
28
29
|
const fill_1 = require("./strategies/fill");
|
|
29
30
|
const headers_1 = require("./strategies/headers");
|
|
@@ -31,6 +32,7 @@ const smartRow_1 = require("./smartRow");
|
|
|
31
32
|
const filterEngine_1 = require("./filterEngine");
|
|
32
33
|
const tableMapper_1 = require("./engine/tableMapper");
|
|
33
34
|
const rowFinder_1 = require("./engine/rowFinder");
|
|
35
|
+
const tableIteration_1 = require("./engine/tableIteration");
|
|
34
36
|
const debugUtils_1 = require("./utils/debugUtils");
|
|
35
37
|
const smartRowArray_1 = require("./utils/smartRowArray");
|
|
36
38
|
const elementTracker_1 = require("./utils/elementTracker");
|
|
@@ -45,7 +47,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
45
47
|
const defaultStrategies = {
|
|
46
48
|
fill: fill_1.FillStrategies.default,
|
|
47
49
|
header: headers_1.HeaderStrategies.visible,
|
|
48
|
-
pagination:
|
|
50
|
+
pagination: {},
|
|
49
51
|
loading: {
|
|
50
52
|
isHeaderLoading: loading_1.LoadingStrategies.Headers.stable(200)
|
|
51
53
|
}
|
|
@@ -94,6 +96,8 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
94
96
|
};
|
|
95
97
|
const tableState = { currentPageIndex: 0 };
|
|
96
98
|
const rowFinder = new rowFinder_1.RowFinder(rootLocator, config, resolve, filterEngine, tableMapper, _makeSmart, tableState);
|
|
99
|
+
/** Builds a full TableContext/StrategyContext with getHeaderCell, getHeaders, scrollToColumn. Set after result is created. */
|
|
100
|
+
let createStrategyContext = () => ({ root: rootLocator, config, page: rootLocator.page(), resolve });
|
|
97
101
|
const _getCleanHtml = (loc) => __awaiter(void 0, void 0, void 0, function* () {
|
|
98
102
|
return loc.evaluate((el) => {
|
|
99
103
|
const clone = el.cloneNode(true);
|
|
@@ -125,20 +129,26 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
125
129
|
const _autoInit = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
126
130
|
yield tableMapper.getMap();
|
|
127
131
|
});
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const context =
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
// Default: goNext (one page). Pass useBulk true to prefer goNextBulk. "How far" uses numeric return when strategy provides it.
|
|
133
|
+
const _advancePage = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (useBulk = false) {
|
|
134
|
+
const context = createStrategyContext();
|
|
135
|
+
const pagination = config.strategies.pagination;
|
|
136
|
+
let rawResult;
|
|
137
|
+
if (useBulk && (pagination === null || pagination === void 0 ? void 0 : pagination.goNextBulk)) {
|
|
138
|
+
rawResult = yield pagination.goNextBulk(context);
|
|
134
139
|
}
|
|
135
|
-
else {
|
|
136
|
-
|
|
140
|
+
else if (pagination === null || pagination === void 0 ? void 0 : pagination.goNext) {
|
|
141
|
+
rawResult = yield pagination.goNext(context);
|
|
137
142
|
}
|
|
138
|
-
if (
|
|
139
|
-
|
|
143
|
+
else if (pagination === null || pagination === void 0 ? void 0 : pagination.goNextBulk) {
|
|
144
|
+
rawResult = yield pagination.goNextBulk(context);
|
|
140
145
|
}
|
|
141
|
-
|
|
146
|
+
const didAdvance = rawResult !== undefined && (0, validation_1.validatePaginationResult)(rawResult, 'Pagination Strategy');
|
|
147
|
+
const pagesJumped = typeof rawResult === 'number' ? rawResult : (didAdvance ? 1 : 0);
|
|
148
|
+
if (pagesJumped > 0) {
|
|
149
|
+
tableState.currentPageIndex += pagesJumped;
|
|
150
|
+
}
|
|
151
|
+
return didAdvance;
|
|
142
152
|
});
|
|
143
153
|
const result = {
|
|
144
154
|
get currentPageIndex() { return tableState.currentPageIndex; },
|
|
@@ -176,11 +186,10 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
176
186
|
reset: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
177
187
|
var _a;
|
|
178
188
|
log("Resetting table...");
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (typeof config.strategies.pagination !== 'function' && ((_a = config.strategies.pagination) === null || _a === void 0 ? void 0 : _a.goToFirst)) {
|
|
189
|
+
yield config.onReset(createStrategyContext());
|
|
190
|
+
if ((_a = config.strategies.pagination) === null || _a === void 0 ? void 0 : _a.goToFirst) {
|
|
182
191
|
log("Auto-navigating to first page...");
|
|
183
|
-
yield config.strategies.pagination.goToFirst(
|
|
192
|
+
yield config.strategies.pagination.goToFirst(createStrategyContext());
|
|
184
193
|
}
|
|
185
194
|
else if (hasPaginationInConfig) {
|
|
186
195
|
log("No goToFirst strategy configured. Table may not be on page 1.");
|
|
@@ -213,11 +222,10 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
213
222
|
return _makeSmart(rowLocator, map, index);
|
|
214
223
|
},
|
|
215
224
|
findRow: (filters, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
216
|
-
// @ts-ignore
|
|
217
225
|
return rowFinder.findRow(filters, options);
|
|
218
226
|
}),
|
|
219
227
|
findRows: (filters, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
220
|
-
return rowFinder.findRows(filters, options);
|
|
228
|
+
return rowFinder.findRows(filters !== null && filters !== void 0 ? filters : {}, options);
|
|
221
229
|
}),
|
|
222
230
|
isInitialized: () => {
|
|
223
231
|
return tableMapper.isInitialized();
|
|
@@ -229,7 +237,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
229
237
|
if (!config.strategies.sorting)
|
|
230
238
|
throw new Error('No sorting strategy has been configured.');
|
|
231
239
|
log(`Applying sort for column "${columnName}" (${direction})`);
|
|
232
|
-
const context = {
|
|
240
|
+
const context = Object.assign(Object.assign({}, createStrategyContext()), { getHeaderCell: result.getHeaderCell });
|
|
233
241
|
const maxRetries = 3;
|
|
234
242
|
for (let i = 0; i < maxRetries; i++) {
|
|
235
243
|
const currentState = yield config.strategies.sorting.getSortState({ columnName, context });
|
|
@@ -257,7 +265,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
257
265
|
yield _autoInit();
|
|
258
266
|
if (!config.strategies.sorting)
|
|
259
267
|
throw new Error('No sorting strategy has been configured.');
|
|
260
|
-
const context = {
|
|
268
|
+
const context = Object.assign(Object.assign({}, createStrategyContext()), { getHeaderCell: result.getHeaderCell });
|
|
261
269
|
return config.strategies.sorting.getSortState({ columnName, context });
|
|
262
270
|
})
|
|
263
271
|
},
|
|
@@ -268,6 +276,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
268
276
|
const map = tableMapper.getMapSync();
|
|
269
277
|
const effectiveMaxPages = config.maxPages;
|
|
270
278
|
const tracker = new elementTracker_1.ElementTracker('iterator');
|
|
279
|
+
const useBulk = false; // iterator has no options; default goNext
|
|
271
280
|
try {
|
|
272
281
|
let rowIndex = 0;
|
|
273
282
|
let pagesScanned = 1;
|
|
@@ -281,7 +290,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
281
290
|
}
|
|
282
291
|
if (pagesScanned >= effectiveMaxPages)
|
|
283
292
|
break;
|
|
284
|
-
if (!(yield __await(_advancePage())))
|
|
293
|
+
if (!(yield __await(_advancePage(useBulk))))
|
|
285
294
|
break;
|
|
286
295
|
pagesScanned++;
|
|
287
296
|
}
|
|
@@ -291,194 +300,63 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
291
300
|
}
|
|
292
301
|
});
|
|
293
302
|
},
|
|
294
|
-
// āāā
|
|
303
|
+
// āāā Row iteration (delegated to engine/tableIteration) āāāāāāāāāāāāāāāāāā
|
|
295
304
|
forEach: (callback_1, ...args_1) => __awaiter(void 0, [callback_1, ...args_1], void 0, function* (callback, options = {}) {
|
|
296
|
-
var _a, _b, _c;
|
|
297
305
|
yield _autoInit();
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
let pagesScanned = 1;
|
|
308
|
-
const stop = () => { stopped = true; };
|
|
309
|
-
while (!stopped) {
|
|
310
|
-
const rowLocators = resolve(config.rowSelector, rootLocator);
|
|
311
|
-
const newIndices = yield tracker.getUnseenIndices(rowLocators);
|
|
312
|
-
const pageRows = yield rowLocators.all();
|
|
313
|
-
const smartRows = newIndices.map((idx, i) => _makeSmart(pageRows[idx], map, rowIndex + i));
|
|
314
|
-
if (parallel) {
|
|
315
|
-
yield Promise.all(smartRows.map((row) => __awaiter(void 0, void 0, void 0, function* () {
|
|
316
|
-
if (stopped)
|
|
317
|
-
return;
|
|
318
|
-
if (dedupeKeys) {
|
|
319
|
-
const key = yield dedupeStrategy(row);
|
|
320
|
-
if (dedupeKeys.has(key))
|
|
321
|
-
return;
|
|
322
|
-
dedupeKeys.add(key);
|
|
323
|
-
}
|
|
324
|
-
yield callback({ row, rowIndex: row.rowIndex, stop });
|
|
325
|
-
})));
|
|
326
|
-
}
|
|
327
|
-
else {
|
|
328
|
-
for (const row of smartRows) {
|
|
329
|
-
if (stopped)
|
|
330
|
-
break;
|
|
331
|
-
if (dedupeKeys) {
|
|
332
|
-
const key = yield dedupeStrategy(row);
|
|
333
|
-
if (dedupeKeys.has(key))
|
|
334
|
-
continue;
|
|
335
|
-
dedupeKeys.add(key);
|
|
336
|
-
}
|
|
337
|
-
yield callback({ row, rowIndex: row.rowIndex, stop });
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
rowIndex += smartRows.length;
|
|
341
|
-
if (stopped || pagesScanned >= effectiveMaxPages)
|
|
342
|
-
break;
|
|
343
|
-
if (!(yield _advancePage()))
|
|
344
|
-
break;
|
|
345
|
-
pagesScanned++;
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
finally {
|
|
349
|
-
yield tracker.cleanup(rootLocator.page());
|
|
350
|
-
}
|
|
306
|
+
yield (0, tableIteration_1.runForEach)({
|
|
307
|
+
getRowLocators: () => resolve(config.rowSelector, rootLocator),
|
|
308
|
+
getMap: () => tableMapper.getMapSync(),
|
|
309
|
+
advancePage: _advancePage,
|
|
310
|
+
makeSmartRow: (loc, map, idx, pageIdx) => _makeSmart(loc, map, idx, pageIdx),
|
|
311
|
+
createSmartRowArray: smartRowArray_1.createSmartRowArray,
|
|
312
|
+
config,
|
|
313
|
+
getPage: () => rootLocator.page(),
|
|
314
|
+
}, callback, options);
|
|
351
315
|
}),
|
|
352
316
|
map: (callback_1, ...args_1) => __awaiter(void 0, [callback_1, ...args_1], void 0, function* (callback, options = {}) {
|
|
353
|
-
var _a, _b, _c;
|
|
354
317
|
yield _autoInit();
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
let stopped = false;
|
|
365
|
-
let pagesScanned = 1;
|
|
366
|
-
const stop = () => { stopped = true; };
|
|
367
|
-
while (!stopped) {
|
|
368
|
-
const rowLocators = resolve(config.rowSelector, rootLocator);
|
|
369
|
-
const newIndices = yield tracker.getUnseenIndices(rowLocators);
|
|
370
|
-
const pageRows = yield rowLocators.all();
|
|
371
|
-
const smartRows = newIndices.map((idx, i) => _makeSmart(pageRows[idx], map, rowIndex + i));
|
|
372
|
-
if (parallel) {
|
|
373
|
-
const SKIP = Symbol('skip');
|
|
374
|
-
const pageResults = yield Promise.all(smartRows.map((row) => __awaiter(void 0, void 0, void 0, function* () {
|
|
375
|
-
if (dedupeKeys) {
|
|
376
|
-
const key = yield dedupeStrategy(row);
|
|
377
|
-
if (dedupeKeys.has(key))
|
|
378
|
-
return SKIP;
|
|
379
|
-
dedupeKeys.add(key);
|
|
380
|
-
}
|
|
381
|
-
return callback({ row, rowIndex: row.rowIndex, stop });
|
|
382
|
-
})));
|
|
383
|
-
for (const r of pageResults) {
|
|
384
|
-
if (r !== SKIP)
|
|
385
|
-
results.push(r);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
else {
|
|
389
|
-
for (const row of smartRows) {
|
|
390
|
-
if (stopped)
|
|
391
|
-
break;
|
|
392
|
-
if (dedupeKeys) {
|
|
393
|
-
const key = yield dedupeStrategy(row);
|
|
394
|
-
if (dedupeKeys.has(key))
|
|
395
|
-
continue;
|
|
396
|
-
dedupeKeys.add(key);
|
|
397
|
-
}
|
|
398
|
-
results.push(yield callback({ row, rowIndex: row.rowIndex, stop }));
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
rowIndex += smartRows.length;
|
|
402
|
-
if (stopped || pagesScanned >= effectiveMaxPages)
|
|
403
|
-
break;
|
|
404
|
-
if (!(yield _advancePage()))
|
|
405
|
-
break;
|
|
406
|
-
pagesScanned++;
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
finally {
|
|
410
|
-
yield tracker.cleanup(rootLocator.page());
|
|
411
|
-
}
|
|
412
|
-
return results;
|
|
318
|
+
return (0, tableIteration_1.runMap)({
|
|
319
|
+
getRowLocators: () => resolve(config.rowSelector, rootLocator),
|
|
320
|
+
getMap: () => tableMapper.getMapSync(),
|
|
321
|
+
advancePage: _advancePage,
|
|
322
|
+
makeSmartRow: (loc, map, idx, pageIdx) => _makeSmart(loc, map, idx, pageIdx),
|
|
323
|
+
createSmartRowArray: smartRowArray_1.createSmartRowArray,
|
|
324
|
+
config,
|
|
325
|
+
getPage: () => rootLocator.page(),
|
|
326
|
+
}, callback, options);
|
|
413
327
|
}),
|
|
414
328
|
filter: (predicate_1, ...args_1) => __awaiter(void 0, [predicate_1, ...args_1], void 0, function* (predicate, options = {}) {
|
|
415
|
-
var _a, _b, _c;
|
|
416
329
|
yield _autoInit();
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
let stopped = false;
|
|
427
|
-
let pagesScanned = 1;
|
|
428
|
-
const stop = () => { stopped = true; };
|
|
429
|
-
while (!stopped) {
|
|
430
|
-
const rowLocators = resolve(config.rowSelector, rootLocator);
|
|
431
|
-
const newIndices = yield tracker.getUnseenIndices(rowLocators);
|
|
432
|
-
const pageRows = yield rowLocators.all();
|
|
433
|
-
const smartRows = newIndices.map((idx, i) => _makeSmart(pageRows[idx], map, rowIndex + i, pagesScanned - 1));
|
|
434
|
-
if (parallel) {
|
|
435
|
-
const flags = yield Promise.all(smartRows.map((row) => __awaiter(void 0, void 0, void 0, function* () {
|
|
436
|
-
if (dedupeKeys) {
|
|
437
|
-
const key = yield dedupeStrategy(row);
|
|
438
|
-
if (dedupeKeys.has(key))
|
|
439
|
-
return false;
|
|
440
|
-
dedupeKeys.add(key);
|
|
441
|
-
}
|
|
442
|
-
return predicate({ row, rowIndex: row.rowIndex, stop });
|
|
443
|
-
})));
|
|
444
|
-
smartRows.forEach((row, i) => { if (flags[i])
|
|
445
|
-
matched.push(row); });
|
|
446
|
-
}
|
|
447
|
-
else {
|
|
448
|
-
for (const row of smartRows) {
|
|
449
|
-
if (stopped)
|
|
450
|
-
break;
|
|
451
|
-
if (dedupeKeys) {
|
|
452
|
-
const key = yield dedupeStrategy(row);
|
|
453
|
-
if (dedupeKeys.has(key))
|
|
454
|
-
continue;
|
|
455
|
-
dedupeKeys.add(key);
|
|
456
|
-
}
|
|
457
|
-
if (yield predicate({ row, rowIndex: row.rowIndex, stop })) {
|
|
458
|
-
matched.push(row);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
rowIndex += smartRows.length;
|
|
463
|
-
if (stopped || pagesScanned >= effectiveMaxPages)
|
|
464
|
-
break;
|
|
465
|
-
if (!(yield _advancePage()))
|
|
466
|
-
break;
|
|
467
|
-
pagesScanned++;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
finally {
|
|
471
|
-
yield tracker.cleanup(rootLocator.page());
|
|
472
|
-
}
|
|
473
|
-
return (0, smartRowArray_1.createSmartRowArray)(matched);
|
|
330
|
+
return (0, tableIteration_1.runFilter)({
|
|
331
|
+
getRowLocators: () => resolve(config.rowSelector, rootLocator),
|
|
332
|
+
getMap: () => tableMapper.getMapSync(),
|
|
333
|
+
advancePage: _advancePage,
|
|
334
|
+
makeSmartRow: (loc, map, idx, pageIdx) => _makeSmart(loc, map, idx, pageIdx),
|
|
335
|
+
createSmartRowArray: smartRowArray_1.createSmartRowArray,
|
|
336
|
+
config,
|
|
337
|
+
getPage: () => rootLocator.page(),
|
|
338
|
+
}, predicate, options);
|
|
474
339
|
}),
|
|
475
|
-
|
|
340
|
+
generateConfig: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
476
341
|
const html = yield _getCleanHtml(rootLocator);
|
|
477
342
|
const separator = "=".repeat(50);
|
|
478
343
|
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`;
|
|
479
344
|
yield _handlePrompt('Smart Table Config', content);
|
|
480
345
|
}),
|
|
346
|
+
generateConfigPrompt: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
347
|
+
console.warn('ā ļø [playwright-smart-table] generateConfigPrompt() is deprecated and will be removed in v7.0.0. Please use generateConfig() instead.');
|
|
348
|
+
return result.generateConfig();
|
|
349
|
+
}),
|
|
481
350
|
};
|
|
351
|
+
createStrategyContext = () => ({
|
|
352
|
+
root: rootLocator,
|
|
353
|
+
config,
|
|
354
|
+
page: rootLocator.page(),
|
|
355
|
+
resolve,
|
|
356
|
+
getHeaderCell: result.getHeaderCell,
|
|
357
|
+
getHeaders: result.getHeaders,
|
|
358
|
+
scrollToColumn: result.scrollToColumn,
|
|
359
|
+
});
|
|
482
360
|
finalTable = result;
|
|
483
361
|
return result;
|
|
484
362
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { PaginationPrimitives, TableContext } from '../types';
|
|
2
|
+
/** A single step in a navigation plan (e.g. "goNextBulk 3 times"). */
|
|
3
|
+
export type NavigationStep = {
|
|
4
|
+
type: 'goToPage';
|
|
5
|
+
pageIndex: number;
|
|
6
|
+
} | {
|
|
7
|
+
type: 'goNextBulk';
|
|
8
|
+
count: number;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'goNext';
|
|
11
|
+
count: number;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'goPreviousBulk';
|
|
14
|
+
count: number;
|
|
15
|
+
} | {
|
|
16
|
+
type: 'goPrevious';
|
|
17
|
+
count: number;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Plans an optimal path from currentPageIndex to targetPageIndex using available primitives.
|
|
21
|
+
* Prefers goToPage when present; otherwise uses bulk steps (goNextBulk / goPreviousBulk) then
|
|
22
|
+
* single steps (goNext / goPrevious). May choose to overshoot with bulk then step back when
|
|
23
|
+
* that reduces total primitive calls (e.g. page 3 ā 12 with bulk 10: goNextBulk once, goPrevious once).
|
|
24
|
+
*/
|
|
25
|
+
export declare function planNavigationPath(currentPageIndex: number, targetPageIndex: number, primitives: PaginationPrimitives): NavigationStep[];
|
|
26
|
+
/**
|
|
27
|
+
* Navigate to targetPageIndex when goToPage is available but may be "windowed"
|
|
28
|
+
* (e.g. only works for visible page links 6ā14). Tries goToPage(target); on false,
|
|
29
|
+
* steps once toward target (goNextBulk/goNext or goPreviousBulk/goPrevious), then retries.
|
|
30
|
+
* Example: from 3 to 38 with windowed goToPage ā goToPage(38) false, goNextBulk(), goToPage(38) false, ⦠goToPage(38) true.
|
|
31
|
+
*/
|
|
32
|
+
export declare function executeNavigationWithGoToPageRetry(targetPageIndex: number, primitives: PaginationPrimitives, context: TableContext, getCurrentPage: () => number, setCurrentPage: (n: number) => void): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Executes a navigation path by calling the corresponding primitives.
|
|
35
|
+
* Updates currentPageIndex via the provided setter as steps run.
|
|
36
|
+
*/
|
|
37
|
+
export declare function executeNavigationPath(path: NavigationStep[], primitives: PaginationPrimitives, context: TableContext, getCurrentPage: () => number, setCurrentPage: (n: number) => void): Promise<void>;
|