@rickcedwhat/playwright-smart-table 6.5.0 → 6.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -5
- package/dist/index.d.ts +4 -4
- package/dist/index.js +8 -18
- package/dist/smartRow.js +3 -3
- package/dist/strategies/index.d.ts +10 -12
- package/dist/strategies/pagination.d.ts +2 -18
- package/dist/strategies/pagination.js +2 -17
- package/dist/strategies/sorting.js +19 -32
- package/dist/typeContext.d.ts +1 -1
- package/dist/typeContext.js +90 -64
- package/dist/types.d.ts +73 -73
- package/dist/useTable.js +248 -231
- package/package.json +1 -1
package/dist/typeContext.js
CHANGED
|
@@ -128,7 +128,12 @@ export type SmartRow<T = any> = Locator & {
|
|
|
128
128
|
smartFill: (data: Partial<T> | Record<string, any>, options?: FillOptions) => Promise<void>;
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
-
export type StrategyContext = TableContext & {
|
|
131
|
+
export type StrategyContext = TableContext & {
|
|
132
|
+
rowLocator?: Locator;
|
|
133
|
+
rowIndex?: number;
|
|
134
|
+
/** Helper to reliably get a header cell locator by name */
|
|
135
|
+
getHeaderCell?: (headerName: string) => Promise<Locator>;
|
|
136
|
+
};
|
|
132
137
|
|
|
133
138
|
/**
|
|
134
139
|
* Defines the contract for a sorting strategy.
|
|
@@ -191,6 +196,12 @@ export interface PaginationPrimitives {
|
|
|
191
196
|
/** Classic "Previous Page" or "Scroll Up" */
|
|
192
197
|
goPrevious?: (context: TableContext) => Promise<boolean>;
|
|
193
198
|
|
|
199
|
+
/** Bulk skip forward multiple pages at once */
|
|
200
|
+
goNextBulk?: (context: TableContext) => Promise<boolean>;
|
|
201
|
+
|
|
202
|
+
/** Bulk skip backward multiple pages at once */
|
|
203
|
+
goPreviousBulk?: (context: TableContext) => Promise<boolean>;
|
|
204
|
+
|
|
194
205
|
/** Jump to first page / scroll to top */
|
|
195
206
|
goToFirst?: (context: TableContext) => Promise<boolean>;
|
|
196
207
|
|
|
@@ -313,12 +324,6 @@ export interface TableConfig<T = any> {
|
|
|
313
324
|
onReset?: (context: TableContext) => Promise<void>;
|
|
314
325
|
/** All interaction strategies */
|
|
315
326
|
strategies?: TableStrategies;
|
|
316
|
-
/**
|
|
317
|
-
* @deprecated Use \`columnOverrides\` instead. \`dataMapper\` will be removed in v7.0.0.
|
|
318
|
-
* Custom data mappers for specific columns.
|
|
319
|
-
* Allows extracting complex data types (boolean, number) instead of just string.
|
|
320
|
-
*/
|
|
321
|
-
dataMapper?: Partial<Record<keyof T, (cell: Locator) => Promise<T[keyof T]> | T[keyof T]>>;
|
|
322
327
|
|
|
323
328
|
/**
|
|
324
329
|
* Unified interface for reading and writing data to specific columns.
|
|
@@ -348,24 +353,32 @@ export interface FillOptions {
|
|
|
348
353
|
inputMappers?: Record<string, (cell: Locator) => Locator>;
|
|
349
354
|
}
|
|
350
355
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
*/
|
|
354
|
-
export
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
/** Callback context passed to forEach, map, and filter. */
|
|
359
|
+
export type RowIterationContext<T = any> = {
|
|
360
|
+
row: SmartRow<T>;
|
|
361
|
+
rowIndex: number;
|
|
362
|
+
stop: () => void;
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
/** Shared options for forEach, map, and filter. */
|
|
366
|
+
export type RowIterationOptions = {
|
|
367
|
+
/** Maximum number of pages to iterate. Defaults to config.maxPages. */
|
|
368
|
+
maxPages?: number;
|
|
355
369
|
/**
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
* - 'console': Standard console logs (Default).
|
|
370
|
+
* Whether to process rows within a page concurrently.
|
|
371
|
+
* @default false for forEach/filter, true for map
|
|
359
372
|
*/
|
|
360
|
-
|
|
373
|
+
parallel?: boolean;
|
|
361
374
|
/**
|
|
362
|
-
*
|
|
363
|
-
*
|
|
375
|
+
* Deduplication strategy. Use when rows may repeat across iterations
|
|
376
|
+
* (e.g. infinite scroll tables). Returns a unique key per row.
|
|
364
377
|
*/
|
|
365
|
-
|
|
366
|
-
}
|
|
378
|
+
dedupe?: DedupeStrategy;
|
|
379
|
+
};
|
|
367
380
|
|
|
368
|
-
export interface TableResult<T = any> {
|
|
381
|
+
export interface TableResult<T = any> extends AsyncIterable<{ row: SmartRow<T>; rowIndex: number }> {
|
|
369
382
|
/**
|
|
370
383
|
* Represents the current page index of the table's DOM.
|
|
371
384
|
* Starts at 0. Automatically maintained by the library during pagination and bringIntoView.
|
|
@@ -448,9 +461,62 @@ export interface TableResult<T = any> {
|
|
|
448
461
|
revalidate: () => Promise<void>;
|
|
449
462
|
|
|
450
463
|
/**
|
|
451
|
-
*
|
|
464
|
+
* Iterates every row across all pages, calling the callback for side effects.
|
|
465
|
+
* Execution is sequential by default (safe for interactions like clicking/filling).
|
|
466
|
+
* Call \`stop()\` in the callback to end iteration early.
|
|
467
|
+
*
|
|
468
|
+
* @example
|
|
469
|
+
* await table.forEach(async ({ row, stop }) => {
|
|
470
|
+
* if (await row.getCell('Status').innerText() === 'Done') stop();
|
|
471
|
+
* await row.getCell('Checkbox').click();
|
|
472
|
+
* });
|
|
452
473
|
*/
|
|
453
|
-
|
|
474
|
+
forEach(
|
|
475
|
+
callback: (ctx: RowIterationContext<T>) => void | Promise<void>,
|
|
476
|
+
options?: RowIterationOptions
|
|
477
|
+
): Promise<void>;
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Transforms every row across all pages into a value. Returns a flat array.
|
|
481
|
+
* Execution is parallel within each page by default (safe for reads).
|
|
482
|
+
* Call \`stop()\` to halt after the current page finishes.
|
|
483
|
+
*
|
|
484
|
+
* > **⚠️ UI Interactions:** \`map\` defaults to \`parallel: true\`. If your callback opens popovers,
|
|
485
|
+
* > fills inputs, or otherwise mutates UI state, pass \`{ parallel: false }\` to avoid concurrent
|
|
486
|
+
* > interactions interfering with each other.
|
|
487
|
+
*
|
|
488
|
+
* @example
|
|
489
|
+
* // Data extraction — parallel is safe
|
|
490
|
+
* const emails = await table.map(({ row }) => row.getCell('Email').innerText());
|
|
491
|
+
*
|
|
492
|
+
* @example
|
|
493
|
+
* // UI interactions — must use parallel: false
|
|
494
|
+
* const assignees = await table.map(async ({ row }) => {
|
|
495
|
+
* await row.getCell('Assignee').locator('button').click();
|
|
496
|
+
* const name = await page.locator('.popover .name').innerText();
|
|
497
|
+
* await page.keyboard.press('Escape');
|
|
498
|
+
* return name;
|
|
499
|
+
* }, { parallel: false });
|
|
500
|
+
*/
|
|
501
|
+
map<R>(
|
|
502
|
+
callback: (ctx: RowIterationContext<T>) => R | Promise<R>,
|
|
503
|
+
options?: RowIterationOptions
|
|
504
|
+
): Promise<R[]>;
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Filters rows across all pages by an async predicate. Returns a SmartRowArray.
|
|
508
|
+
* Rows are returned as-is — call \`bringIntoView()\` on each if needed.
|
|
509
|
+
* Execution is sequential by default.
|
|
510
|
+
*
|
|
511
|
+
* @example
|
|
512
|
+
* const active = await table.filter(async ({ row }) =>
|
|
513
|
+
* await row.getCell('Status').innerText() === 'Active'
|
|
514
|
+
* );
|
|
515
|
+
*/
|
|
516
|
+
filter(
|
|
517
|
+
predicate: (ctx: RowIterationContext<T>) => boolean | Promise<boolean>,
|
|
518
|
+
options?: RowIterationOptions
|
|
519
|
+
): Promise<SmartRowArray<T>>;
|
|
454
520
|
|
|
455
521
|
/**
|
|
456
522
|
* Provides access to sorting actions and assertions.
|
|
@@ -470,51 +536,11 @@ export interface TableResult<T = any> {
|
|
|
470
536
|
getState(columnName: string): Promise<'asc' | 'desc' | 'none'>;
|
|
471
537
|
};
|
|
472
538
|
|
|
473
|
-
/**
|
|
474
|
-
* Iterates through paginated table data, calling the callback for each iteration.
|
|
475
|
-
* Callback return values are automatically appended to allData, which is returned.
|
|
476
|
-
*/
|
|
477
|
-
iterateThroughTable: <T = any>(
|
|
478
|
-
callback: (context: {
|
|
479
|
-
index: number;
|
|
480
|
-
isFirst: boolean;
|
|
481
|
-
isLast: boolean;
|
|
482
|
-
rows: SmartRowArray;
|
|
483
|
-
allData: T[];
|
|
484
|
-
table: RestrictedTableResult;
|
|
485
|
-
batchInfo?: {
|
|
486
|
-
startIndex: number;
|
|
487
|
-
endIndex: number;
|
|
488
|
-
size: number;
|
|
489
|
-
};
|
|
490
|
-
|
|
491
|
-
}) => T | T[] | Promise<T | T[]>,
|
|
492
|
-
options?: {
|
|
493
|
-
pagination?: PaginationStrategy;
|
|
494
|
-
dedupeStrategy?: DedupeStrategy;
|
|
495
|
-
maxIterations?: number;
|
|
496
|
-
batchSize?: number;
|
|
497
|
-
getIsFirst?: (context: { index: number }) => boolean;
|
|
498
|
-
getIsLast?: (context: { index: number, paginationResult: boolean }) => boolean;
|
|
499
|
-
beforeFirst?: (context: { index: number, rows: SmartRowArray, allData: any[] }) => void | Promise<void>;
|
|
500
|
-
afterLast?: (context: { index: number, rows: SmartRowArray, allData: any[] }) => void | Promise<void>;
|
|
501
|
-
/**
|
|
502
|
-
* If true, flattens array results from callback into the main data array.
|
|
503
|
-
* If false (default), pushes the return value as-is (preserves batching/arrays).
|
|
504
|
-
*/
|
|
505
|
-
autoFlatten?: boolean;
|
|
506
|
-
}
|
|
507
|
-
) => Promise<T[]>;
|
|
508
|
-
|
|
509
539
|
/**
|
|
510
540
|
* Generate an AI-friendly configuration prompt for debugging.
|
|
511
541
|
* Outputs table HTML and TypeScript definitions to help AI assistants generate config.
|
|
542
|
+
* Automatically throws an Error containing the prompt.
|
|
512
543
|
*/
|
|
513
|
-
generateConfigPrompt: (
|
|
544
|
+
generateConfigPrompt: () => Promise<void>;
|
|
514
545
|
}
|
|
515
|
-
|
|
516
|
-
/**
|
|
517
|
-
* Restricted table result that excludes methods that shouldn't be called during iteration.
|
|
518
|
-
*/
|
|
519
|
-
export type RestrictedTableResult<T = any> = Omit<TableResult<T>, 'searchForRow' | 'iterateThroughTable' | 'reset'>;
|
|
520
546
|
`;
|
package/dist/types.d.ts
CHANGED
|
@@ -114,6 +114,8 @@ export type SmartRow<T = any> = Locator & {
|
|
|
114
114
|
export type StrategyContext = TableContext & {
|
|
115
115
|
rowLocator?: Locator;
|
|
116
116
|
rowIndex?: number;
|
|
117
|
+
/** Helper to reliably get a header cell locator by name */
|
|
118
|
+
getHeaderCell?: (headerName: string) => Promise<Locator>;
|
|
117
119
|
};
|
|
118
120
|
/**
|
|
119
121
|
* Defines the contract for a sorting strategy.
|
|
@@ -170,6 +172,10 @@ export interface PaginationPrimitives {
|
|
|
170
172
|
goNext?: (context: TableContext) => Promise<boolean>;
|
|
171
173
|
/** Classic "Previous Page" or "Scroll Up" */
|
|
172
174
|
goPrevious?: (context: TableContext) => Promise<boolean>;
|
|
175
|
+
/** Bulk skip forward multiple pages at once */
|
|
176
|
+
goNextBulk?: (context: TableContext) => Promise<boolean>;
|
|
177
|
+
/** Bulk skip backward multiple pages at once */
|
|
178
|
+
goPreviousBulk?: (context: TableContext) => Promise<boolean>;
|
|
173
179
|
/** Jump to first page / scroll to top */
|
|
174
180
|
goToFirst?: (context: TableContext) => Promise<boolean>;
|
|
175
181
|
/** Jump to specific page index (0-indexed) */
|
|
@@ -293,12 +299,6 @@ export interface TableConfig<T = any> {
|
|
|
293
299
|
onReset?: (context: TableContext) => Promise<void>;
|
|
294
300
|
/** All interaction strategies */
|
|
295
301
|
strategies?: TableStrategies;
|
|
296
|
-
/**
|
|
297
|
-
* @deprecated Use `columnOverrides` instead. `dataMapper` will be removed in v7.0.0.
|
|
298
|
-
* Custom data mappers for specific columns.
|
|
299
|
-
* Allows extracting complex data types (boolean, number) instead of just string.
|
|
300
|
-
*/
|
|
301
|
-
dataMapper?: Partial<Record<keyof T, (cell: Locator) => Promise<T[keyof T]> | T[keyof T]>>;
|
|
302
302
|
/**
|
|
303
303
|
* Unified interface for reading and writing data to specific columns.
|
|
304
304
|
* Overrides both default extraction (toJSON) and filling (smartFill) logic.
|
|
@@ -328,23 +328,31 @@ export interface FillOptions {
|
|
|
328
328
|
*/
|
|
329
329
|
inputMappers?: Record<string, (cell: Locator) => Locator>;
|
|
330
330
|
}
|
|
331
|
-
/**
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
331
|
+
/** Callback context passed to forEach, map, and filter. */
|
|
332
|
+
export type RowIterationContext<T = any> = {
|
|
333
|
+
row: SmartRow<T>;
|
|
334
|
+
rowIndex: number;
|
|
335
|
+
stop: () => void;
|
|
336
|
+
};
|
|
337
|
+
/** Shared options for forEach, map, and filter. */
|
|
338
|
+
export type RowIterationOptions = {
|
|
339
|
+
/** Maximum number of pages to iterate. Defaults to config.maxPages. */
|
|
340
|
+
maxPages?: number;
|
|
335
341
|
/**
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
* - 'console': Standard console logs (Default).
|
|
342
|
+
* Whether to process rows within a page concurrently.
|
|
343
|
+
* @default false for forEach/filter, true for map
|
|
339
344
|
*/
|
|
340
|
-
|
|
345
|
+
parallel?: boolean;
|
|
341
346
|
/**
|
|
342
|
-
*
|
|
343
|
-
*
|
|
347
|
+
* Deduplication strategy. Use when rows may repeat across iterations
|
|
348
|
+
* (e.g. infinite scroll tables). Returns a unique key per row.
|
|
344
349
|
*/
|
|
345
|
-
|
|
346
|
-
}
|
|
347
|
-
export interface TableResult<T = any> {
|
|
350
|
+
dedupe?: DedupeStrategy;
|
|
351
|
+
};
|
|
352
|
+
export interface TableResult<T = any> extends AsyncIterable<{
|
|
353
|
+
row: SmartRow<T>;
|
|
354
|
+
rowIndex: number;
|
|
355
|
+
}> {
|
|
348
356
|
/**
|
|
349
357
|
* Represents the current page index of the table's DOM.
|
|
350
358
|
* Starts at 0. Automatically maintained by the library during pagination and bringIntoView.
|
|
@@ -414,12 +422,51 @@ export interface TableResult<T = any> {
|
|
|
414
422
|
*/
|
|
415
423
|
revalidate: () => Promise<void>;
|
|
416
424
|
/**
|
|
417
|
-
*
|
|
425
|
+
* Iterates every row across all pages, calling the callback for side effects.
|
|
426
|
+
* Execution is sequential by default (safe for interactions like clicking/filling).
|
|
427
|
+
* Call `stop()` in the callback to end iteration early.
|
|
428
|
+
*
|
|
429
|
+
* @example
|
|
430
|
+
* await table.forEach(async ({ row, stop }) => {
|
|
431
|
+
* if (await row.getCell('Status').innerText() === 'Done') stop();
|
|
432
|
+
* await row.getCell('Checkbox').click();
|
|
433
|
+
* });
|
|
418
434
|
*/
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
435
|
+
forEach(callback: (ctx: RowIterationContext<T>) => void | Promise<void>, options?: RowIterationOptions): Promise<void>;
|
|
436
|
+
/**
|
|
437
|
+
* Transforms every row across all pages into a value. Returns a flat array.
|
|
438
|
+
* Execution is parallel within each page by default (safe for reads).
|
|
439
|
+
* Call `stop()` to halt after the current page finishes.
|
|
440
|
+
*
|
|
441
|
+
* > **⚠️ UI Interactions:** `map` defaults to `parallel: true`. If your callback opens popovers,
|
|
442
|
+
* > fills inputs, or otherwise mutates UI state, pass `{ parallel: false }` to avoid concurrent
|
|
443
|
+
* > interactions interfering with each other.
|
|
444
|
+
*
|
|
445
|
+
* @example
|
|
446
|
+
* // Data extraction — parallel is safe
|
|
447
|
+
* const emails = await table.map(({ row }) => row.getCell('Email').innerText());
|
|
448
|
+
*
|
|
449
|
+
* @example
|
|
450
|
+
* // UI interactions — must use parallel: false
|
|
451
|
+
* const assignees = await table.map(async ({ row }) => {
|
|
452
|
+
* await row.getCell('Assignee').locator('button').click();
|
|
453
|
+
* const name = await page.locator('.popover .name').innerText();
|
|
454
|
+
* await page.keyboard.press('Escape');
|
|
455
|
+
* return name;
|
|
456
|
+
* }, { parallel: false });
|
|
457
|
+
*/
|
|
458
|
+
map<R>(callback: (ctx: RowIterationContext<T>) => R | Promise<R>, options?: RowIterationOptions): Promise<R[]>;
|
|
459
|
+
/**
|
|
460
|
+
* Filters rows across all pages by an async predicate. Returns a SmartRowArray.
|
|
461
|
+
* Rows are returned as-is — call `bringIntoView()` on each if needed.
|
|
462
|
+
* Execution is sequential by default.
|
|
463
|
+
*
|
|
464
|
+
* @example
|
|
465
|
+
* const active = await table.filter(async ({ row }) =>
|
|
466
|
+
* await row.getCell('Status').innerText() === 'Active'
|
|
467
|
+
* );
|
|
468
|
+
*/
|
|
469
|
+
filter(predicate: (ctx: RowIterationContext<T>) => boolean | Promise<boolean>, options?: RowIterationOptions): Promise<SmartRowArray<T>>;
|
|
423
470
|
/**
|
|
424
471
|
* Provides access to sorting actions and assertions.
|
|
425
472
|
*/
|
|
@@ -437,57 +484,10 @@ export interface TableResult<T = any> {
|
|
|
437
484
|
*/
|
|
438
485
|
getState(columnName: string): Promise<'asc' | 'desc' | 'none'>;
|
|
439
486
|
};
|
|
440
|
-
/**
|
|
441
|
-
* Iterates through paginated table data, calling the callback for each iteration.
|
|
442
|
-
* Callback return values are automatically appended to allData, which is returned.
|
|
443
|
-
*/
|
|
444
|
-
iterateThroughTable: <T = any>(callback: (context: {
|
|
445
|
-
index: number;
|
|
446
|
-
isFirst: boolean;
|
|
447
|
-
isLast: boolean;
|
|
448
|
-
rows: SmartRowArray;
|
|
449
|
-
allData: T[];
|
|
450
|
-
table: RestrictedTableResult;
|
|
451
|
-
batchInfo?: {
|
|
452
|
-
startIndex: number;
|
|
453
|
-
endIndex: number;
|
|
454
|
-
size: number;
|
|
455
|
-
};
|
|
456
|
-
}) => T | T[] | Promise<T | T[]>, options?: {
|
|
457
|
-
pagination?: PaginationStrategy;
|
|
458
|
-
dedupeStrategy?: DedupeStrategy;
|
|
459
|
-
maxIterations?: number;
|
|
460
|
-
batchSize?: number;
|
|
461
|
-
getIsFirst?: (context: {
|
|
462
|
-
index: number;
|
|
463
|
-
}) => boolean;
|
|
464
|
-
getIsLast?: (context: {
|
|
465
|
-
index: number;
|
|
466
|
-
paginationResult: boolean;
|
|
467
|
-
}) => boolean;
|
|
468
|
-
beforeFirst?: (context: {
|
|
469
|
-
index: number;
|
|
470
|
-
rows: SmartRowArray;
|
|
471
|
-
allData: any[];
|
|
472
|
-
}) => void | Promise<void>;
|
|
473
|
-
afterLast?: (context: {
|
|
474
|
-
index: number;
|
|
475
|
-
rows: SmartRowArray;
|
|
476
|
-
allData: any[];
|
|
477
|
-
}) => void | Promise<void>;
|
|
478
|
-
/**
|
|
479
|
-
* If true, flattens array results from callback into the main data array.
|
|
480
|
-
* If false (default), pushes the return value as-is (preserves batching/arrays).
|
|
481
|
-
*/
|
|
482
|
-
autoFlatten?: boolean;
|
|
483
|
-
}) => Promise<T[]>;
|
|
484
487
|
/**
|
|
485
488
|
* Generate an AI-friendly configuration prompt for debugging.
|
|
486
489
|
* Outputs table HTML and TypeScript definitions to help AI assistants generate config.
|
|
490
|
+
* Automatically throws an Error containing the prompt.
|
|
487
491
|
*/
|
|
488
|
-
generateConfigPrompt: (
|
|
492
|
+
generateConfigPrompt: () => Promise<void>;
|
|
489
493
|
}
|
|
490
|
-
/**
|
|
491
|
-
* Restricted table result that excludes methods that shouldn't be called during iteration.
|
|
492
|
-
*/
|
|
493
|
-
export type RestrictedTableResult<T = any> = Omit<TableResult<T>, 'searchForRow' | 'iterateThroughTable' | 'reset'>;
|