@rickcedwhat/playwright-smart-table 5.3.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +78 -957
  2. package/dist/examples/glide-strategies/columns.d.ts +13 -0
  3. package/dist/examples/glide-strategies/columns.js +43 -0
  4. package/dist/examples/glide-strategies/headers.d.ts +9 -0
  5. package/dist/examples/glide-strategies/headers.js +68 -0
  6. package/dist/src/filterEngine.d.ts +11 -0
  7. package/dist/src/filterEngine.js +39 -0
  8. package/dist/src/index.d.ts +2 -0
  9. package/dist/src/index.js +18 -0
  10. package/dist/src/plugins.d.ts +32 -0
  11. package/dist/src/plugins.js +13 -0
  12. package/dist/src/smartRow.d.ts +7 -0
  13. package/dist/src/smartRow.js +160 -0
  14. package/dist/src/strategies/columns.d.ts +18 -0
  15. package/dist/src/strategies/columns.js +21 -0
  16. package/dist/src/strategies/dedupe.d.ts +9 -0
  17. package/dist/src/strategies/dedupe.js +27 -0
  18. package/dist/src/strategies/fill.d.ts +7 -0
  19. package/dist/src/strategies/fill.js +88 -0
  20. package/dist/src/strategies/glide.d.ts +29 -0
  21. package/dist/src/strategies/glide.js +98 -0
  22. package/dist/src/strategies/headers.d.ts +13 -0
  23. package/dist/src/strategies/headers.js +30 -0
  24. package/dist/src/strategies/index.d.ts +54 -0
  25. package/dist/src/strategies/index.js +43 -0
  26. package/dist/src/strategies/loading.d.ts +48 -0
  27. package/dist/src/strategies/loading.js +82 -0
  28. package/dist/src/strategies/pagination.d.ts +33 -0
  29. package/dist/src/strategies/pagination.js +79 -0
  30. package/dist/src/strategies/rdg.d.ts +25 -0
  31. package/dist/src/strategies/rdg.js +100 -0
  32. package/dist/src/strategies/resolution.d.ts +22 -0
  33. package/dist/src/strategies/resolution.js +30 -0
  34. package/dist/src/strategies/sorting.d.ts +12 -0
  35. package/dist/src/strategies/sorting.js +68 -0
  36. package/dist/src/strategies/stabilization.d.ts +29 -0
  37. package/dist/src/strategies/stabilization.js +91 -0
  38. package/dist/src/strategies/validation.d.ts +22 -0
  39. package/dist/src/strategies/validation.js +54 -0
  40. package/dist/src/strategies/virtualizedPagination.d.ts +32 -0
  41. package/dist/src/strategies/virtualizedPagination.js +80 -0
  42. package/dist/src/typeContext.d.ts +6 -0
  43. package/dist/src/typeContext.js +465 -0
  44. package/dist/src/types.d.ts +458 -0
  45. package/dist/src/types.js +2 -0
  46. package/dist/src/useTable.d.ts +44 -0
  47. package/dist/src/useTable.js +642 -0
  48. package/dist/src/utils/debugUtils.d.ts +17 -0
  49. package/dist/src/utils/debugUtils.js +62 -0
  50. package/dist/src/utils/smartRowArray.d.ts +14 -0
  51. package/dist/src/utils/smartRowArray.js +22 -0
  52. package/dist/src/utils/stringUtils.d.ts +22 -0
  53. package/dist/src/utils/stringUtils.js +73 -0
  54. package/dist/src/utils.d.ts +7 -0
  55. package/dist/src/utils.js +29 -0
  56. package/dist/typeContext.d.ts +1 -1
  57. package/dist/typeContext.js +27 -5
  58. package/dist/types.d.ts +27 -6
  59. package/dist/useTable.js +21 -16
  60. package/dist/utils/smartRowArray.d.ts +14 -0
  61. package/dist/utils/smartRowArray.js +22 -0
  62. package/package.json +16 -20
@@ -0,0 +1,465 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TYPE_CONTEXT = void 0;
4
+ /**
5
+ * 🤖 AUTO-GENERATED FILE. DO NOT EDIT.
6
+ * This file is generated by scripts/embed-types.js
7
+ * It contains the raw text of types.ts to provide context for LLM prompts.
8
+ */
9
+ exports.TYPE_CONTEXT = `
10
+ /**
11
+ * Flexible selector type - can be a CSS string, function returning a Locator, or Locator itself.
12
+ * @example
13
+ * // String selector
14
+ * rowSelector: 'tbody tr'
15
+ *
16
+ * // Function selector
17
+ * rowSelector: (root) => root.locator('[role="row"]')
18
+ */
19
+ export type Selector = string | ((root: Locator | Page) => Locator);
20
+
21
+ /**
22
+ * Function to get a cell locator given row, column info.
23
+ * Replaces the old cellResolver.
24
+ */
25
+ export type GetCellLocatorFn = (args: {
26
+ row: Locator;
27
+ columnName: string;
28
+ columnIndex: number;
29
+ rowIndex?: number;
30
+ page: Page;
31
+ }) => Locator;
32
+
33
+ /**
34
+ * Function to get the currently active/focused cell.
35
+ * Returns null if no cell is active.
36
+ */
37
+ export type GetActiveCellFn = (args: TableContext) => Promise<{
38
+ rowIndex: number;
39
+ columnIndex: number;
40
+ columnName?: string;
41
+ locator: Locator;
42
+ } | null>;
43
+
44
+
45
+ /**
46
+ * SmartRow - A Playwright Locator with table-aware methods.
47
+ *
48
+ * Extends all standard Locator methods (click, isVisible, etc.) with table-specific functionality.
49
+ *
50
+ * @example
51
+ * const row = table.getRow({ Name: 'John Doe' });
52
+ * await row.click(); // Standard Locator method
53
+ * const email = row.getCell('Email'); // Table-aware method
54
+ * const data = await row.toJSON(); // Extract all row data
55
+ * await row.smartFill({ Name: 'Jane', Status: 'Active' }); // Fill form fields
56
+ */
57
+ export type SmartRow<T = any> = Locator & {
58
+ /** Optional row index (0-based) if known */
59
+ rowIndex?: number;
60
+
61
+ /**
62
+ * Get a cell locator by column name.
63
+ * @param column - Column name (case-sensitive)
64
+ * @returns Locator for the cell
65
+ * @example
66
+ * const emailCell = row.getCell('Email');
67
+ * await expect(emailCell).toHaveText('john@example.com');
68
+ */
69
+ getCell(column: string): Locator;
70
+
71
+ /**
72
+ * Extract all cell data as a key-value object.
73
+ * @param options - Optional configuration
74
+ * @param options.columns - Specific columns to extract (extracts all if not specified)
75
+ * @returns Promise resolving to row data
76
+ * @example
77
+ * const data = await row.toJSON();
78
+ * // { Name: 'John', Email: 'john@example.com', ... }
79
+ *
80
+ * const partial = await row.toJSON({ columns: ['Name', 'Email'] });
81
+ * // { Name: 'John', Email: 'john@example.com' }
82
+ */
83
+ toJSON(options?: { columns?: string[] }): Promise<T>;
84
+
85
+ /**
86
+ * Scrolls/paginates to bring this row into view.
87
+ * Only works if rowIndex is known (e.g., from getRowByIndex).
88
+ * @throws Error if rowIndex is unknown
89
+ */
90
+ bringIntoView(): Promise<void>;
91
+
92
+ /**
93
+ * Intelligently fills form fields in the row.
94
+ * Automatically detects input types (text, select, checkbox, contenteditable).
95
+ *
96
+ * @param data - Column-value pairs to fill
97
+ * @param options - Optional configuration
98
+ * @param options.inputMappers - Custom input selectors per column
99
+ * @example
100
+ * // Auto-detection
101
+ * await row.smartFill({ Name: 'John', Status: 'Active', Subscribe: true });
102
+ *
103
+ * // Custom input mappers
104
+ * await row.smartFill(
105
+ * { Name: 'John' },
106
+ * { inputMappers: { Name: (cell) => cell.locator('.custom-input') } }
107
+ * );
108
+ */
109
+ smartFill: (data: Partial<T> | Record<string, any>, options?: FillOptions) => Promise<void>;
110
+ };
111
+
112
+ export type StrategyContext = TableContext & { rowLocator?: Locator; rowIndex?: number };
113
+
114
+ /**
115
+ * Defines the contract for a sorting strategy.
116
+ */
117
+ export interface SortingStrategy {
118
+ /**
119
+ * Performs the sort action on a column.
120
+ */
121
+ doSort(options: {
122
+ columnName: string;
123
+ direction: 'asc' | 'desc';
124
+ context: StrategyContext;
125
+ }): Promise<void>;
126
+
127
+ /**
128
+ * Retrieves the current sort state of a column.
129
+ */
130
+ getSortState(options: {
131
+ columnName: string;
132
+ context: StrategyContext;
133
+ }): Promise<'asc' | 'desc' | 'none'>;
134
+ }
135
+
136
+ /**
137
+ * Debug configuration for development and troubleshooting
138
+ */
139
+ export type DebugConfig = {
140
+ /**
141
+ * Slow down operations for debugging
142
+ * - number: Apply same delay to all operations (ms)
143
+ * - object: Granular delays per operation type
144
+ */
145
+ slow?: number | {
146
+ pagination?: number;
147
+ getCell?: number;
148
+ findRow?: number;
149
+ default?: number;
150
+ };
151
+ /**
152
+ * Log level for debug output
153
+ * - 'verbose': All logs (verbose, info, error)
154
+ * - 'info': Info and error logs only
155
+ * - 'error': Error logs only
156
+ * - 'none': No logs
157
+ */
158
+ logLevel?: 'verbose' | 'info' | 'error' | 'none';
159
+ };
160
+
161
+ export interface TableContext {
162
+ root: Locator;
163
+ config: FinalTableConfig;
164
+ page: Page;
165
+ resolve: (selector: Selector, parent: Locator | Page) => Locator;
166
+ }
167
+
168
+ export type PaginationStrategy = (context: TableContext) => Promise<boolean>;
169
+
170
+ export type DedupeStrategy = (row: SmartRow) => string | number | Promise<string | number>;
171
+
172
+ export interface PromptOptions {
173
+ /**
174
+ * Output Strategy:
175
+ * - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).
176
+ * - 'console': Standard console logs (Default).
177
+ */
178
+ output?: 'console' | 'error';
179
+ includeTypes?: boolean;
180
+ }
181
+
182
+ export type FillStrategy = (options: {
183
+ row: SmartRow;
184
+ columnName: string;
185
+ value: any;
186
+ index: number;
187
+ page: Page;
188
+ rootLocator: Locator;
189
+ table: TableResult; // The parent table instance
190
+ fillOptions?: FillOptions;
191
+ }) => Promise<void>;
192
+
193
+ export type { HeaderStrategy } from './strategies/headers';
194
+ export type { CellNavigationStrategy } from './strategies/columns';
195
+
196
+ /**
197
+ * Strategy to resolve column names (string or regex) to their index.
198
+ */
199
+ export type { ColumnResolutionStrategy } from './strategies/resolution';
200
+
201
+ /**
202
+ * Strategy to filter rows based on criteria.
203
+ */
204
+ export interface FilterStrategy {
205
+ apply(options: {
206
+ rows: Locator;
207
+ filter: { column: string, value: string | RegExp | number };
208
+ colIndex: number;
209
+ tableContext: TableContext;
210
+ }): Locator;
211
+ }
212
+
213
+ /**
214
+ * Strategy to check if the table or rows are loading.
215
+ */
216
+ export interface LoadingStrategy {
217
+ isTableLoading?: (context: TableContext) => Promise<boolean>;
218
+ isRowLoading?: (row: SmartRow) => Promise<boolean>;
219
+ }
220
+
221
+ /**
222
+ * Organized container for all table interaction strategies.
223
+ */
224
+ export interface TableStrategies {
225
+ /** Strategy for discovering/scanning headers */
226
+ header?: HeaderStrategy;
227
+ /** Strategy for navigating to specific cells (row + column) */
228
+ cellNavigation?: CellNavigationStrategy;
229
+ /** Strategy for filling form inputs */
230
+ fill?: FillStrategy;
231
+ /** Strategy for paginating through data */
232
+ pagination?: PaginationStrategy;
233
+ /** Strategy for sorting columns */
234
+ sorting?: SortingStrategy;
235
+ /** Strategy for deduplicating rows during iteration/scrolling */
236
+ dedupe?: DedupeStrategy;
237
+ /** Function to get a cell locator */
238
+ getCellLocator?: GetCellLocatorFn;
239
+ /** Function to get the currently active/focused cell */
240
+ getActiveCell?: GetActiveCellFn;
241
+ /** Custom helper to check if a table is fully loaded/ready */
242
+ isTableLoaded?: (args: TableContext) => Promise<boolean>;
243
+ /** Custom helper to check if a row is fully loaded/ready */
244
+ isRowLoaded?: (args: { row: Locator, index: number }) => Promise<boolean>;
245
+ /** Custom helper to check if a cell is fully loaded/ready (e.g. for editing) */
246
+ isCellLoaded?: (args: { cell: Locator, column: string, row: Locator }) => Promise<boolean>;
247
+ /** Strategy for detecting loading states */
248
+ loading?: LoadingStrategy;
249
+ }
250
+
251
+ /**
252
+ * Configuration options for useTable.
253
+ */
254
+ export interface TableConfig {
255
+ /** Selector for the table headers */
256
+ headerSelector?: string;
257
+ /** Selector for the table rows */
258
+ rowSelector?: string;
259
+ /** Selector for the cells within a row */
260
+ cellSelector?: string;
261
+ /** Number of pages to scan for verification */
262
+ maxPages?: number;
263
+ /** Hook to rename columns dynamically */
264
+ headerTransformer?: (args: { text: string, index: number, locator: Locator, seenHeaders: Set<string> }) => string | Promise<string>;
265
+ /** Automatically scroll to table on init */
266
+ autoScroll?: boolean;
267
+ /** Debug options for development and troubleshooting */
268
+ debug?: DebugConfig;
269
+ /** Reset hook */
270
+ onReset?: (context: TableContext) => Promise<void>;
271
+ /** All interaction strategies */
272
+ strategies?: TableStrategies;
273
+ }
274
+
275
+ export interface FinalTableConfig extends TableConfig {
276
+ headerSelector: string;
277
+ rowSelector: string;
278
+ cellSelector: string;
279
+ maxPages: number;
280
+ autoScroll: boolean;
281
+ debug?: TableConfig['debug'];
282
+ headerTransformer: (args: { text: string, index: number, locator: Locator, seenHeaders: Set<string> }) => string | Promise<string>;
283
+ onReset: (context: TableContext) => Promise<void>;
284
+ strategies: TableStrategies;
285
+ }
286
+
287
+
288
+ export interface FillOptions {
289
+ /**
290
+ * Custom input mappers for specific columns.
291
+ * Maps column names to functions that return the input locator for that cell.
292
+ */
293
+ inputMappers?: Record<string, (cell: Locator) => Locator>;
294
+ }
295
+
296
+ /**
297
+ * Options for generateConfigPrompt
298
+ */
299
+ export interface PromptOptions {
300
+ /**
301
+ * Output Strategy:
302
+ * - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).
303
+ * - 'console': Standard console logs (Default).
304
+ */
305
+ output?: 'console' | 'error';
306
+ /**
307
+ * Include TypeScript type definitions in the prompt
308
+ * @default true
309
+ */
310
+ includeTypes?: boolean;
311
+ }
312
+
313
+ export interface TableResult<T = any> {
314
+ /**
315
+ * Initializes the table by resolving headers. Must be called before using sync methods.
316
+ * @param options Optional timeout for header resolution (default: 3000ms)
317
+ */
318
+ init(options?: { timeout?: number }): Promise<TableResult>;
319
+
320
+ /**
321
+ * SYNC: Checks if the table has been initialized.
322
+ * @returns true if init() has been called and completed, false otherwise
323
+ */
324
+ isInitialized(): boolean;
325
+
326
+ getHeaders: () => Promise<string[]>;
327
+ getHeaderCell: (columnName: string) => Promise<Locator>;
328
+
329
+ /**
330
+ * Finds a row by filters on the current page only. Returns immediately (sync).
331
+ * Throws error if table is not initialized.
332
+ */
333
+ getRow: (
334
+ filters: Record<string, string | RegExp | number>,
335
+ options?: { exact?: boolean }
336
+ ) => SmartRow;
337
+
338
+ /**
339
+ * Gets a row by 1-based index on the current page.
340
+ * Throws error if table is not initialized.
341
+ * @param index 1-based row index
342
+ * @param options Optional settings including bringIntoView
343
+ */
344
+ getRowByIndex: (
345
+ index: number,
346
+ options?: { bringIntoView?: boolean }
347
+ ) => SmartRow;
348
+
349
+ /**
350
+ * ASYNC: Searches for a single row across pages using pagination.
351
+ * Auto-initializes the table if not already initialized.
352
+ * @param filters - The filter criteria to match
353
+ * @param options - Search options including exact match and max pages
354
+ */
355
+ findRow: (
356
+ filters: Record<string, string | RegExp | number>,
357
+ options?: { exact?: boolean, maxPages?: number }
358
+ ) => Promise<SmartRow>;
359
+
360
+ /**
361
+ * ASYNC: Searches for all matching rows across pages using pagination.
362
+ * Auto-initializes the table if not already initialized.
363
+ * @param filters - The filter criteria to match
364
+ * @param options - Search options including exact match, max pages, and asJSON
365
+ */
366
+ findRows: <R extends { asJSON?: boolean }>(
367
+ filters: Record<string, string | RegExp | number>,
368
+ options?: { exact?: boolean, maxPages?: number } & R
369
+ ) => Promise<R['asJSON'] extends true ? Record<string, string>[] : SmartRow[]>;
370
+
371
+ /**
372
+ * Navigates to a specific column using the configured CellNavigationStrategy.
373
+ */
374
+ scrollToColumn: (columnName: string) => Promise<void>;
375
+
376
+ /**
377
+ * Gets all rows on the current page only (does not paginate).
378
+ * Auto-initializes the table if not already initialized.
379
+ * Returns a SmartRowArray which extends Array with a toJSON() helper method.
380
+ * @param options - Filter options
381
+ */
382
+ getRows: (options?: { filter?: Record<string, any>, exact?: boolean }) => Promise<SmartRowArray>;
383
+
384
+ /**
385
+ * Resets the table state (clears cache, flags) and invokes the onReset strategy.
386
+ */
387
+ reset: () => Promise<void>;
388
+
389
+ /**
390
+ * Revalidates the table's structure (headers, columns) without resetting pagination or state.
391
+ * Useful when columns change visibility or order dynamically.
392
+ */
393
+ revalidate: () => Promise<void>;
394
+
395
+ /**
396
+ * Scans a specific column across all pages and returns the values.
397
+ */
398
+ getColumnValues: <V = string>(column: string, options?: { mapper?: (cell: Locator) => Promise<V> | V, maxPages?: number }) => Promise<V[]>;
399
+
400
+ /**
401
+ * Provides access to sorting actions and assertions.
402
+ */
403
+ sorting: {
404
+ /**
405
+ * Applies the configured sorting strategy to the specified column.
406
+ * @param columnName The name of the column to sort.
407
+ * @param direction The direction to sort ('asc' or 'desc').
408
+ */
409
+ apply(columnName: string, direction: 'asc' | 'desc'): Promise<void>;
410
+ /**
411
+ * Gets the current sort state of a column using the configured sorting strategy.
412
+ * @param columnName The name of the column to check.
413
+ * @returns A promise that resolves to 'asc', 'desc', or 'none'.
414
+ */
415
+ getState(columnName: string): Promise<'asc' | 'desc' | 'none'>;
416
+ };
417
+
418
+ /**
419
+ * Iterates through paginated table data, calling the callback for each iteration.
420
+ * Callback return values are automatically appended to allData, which is returned.
421
+ */
422
+ iterateThroughTable: <T = any>(
423
+ callback: (context: {
424
+ index: number;
425
+ isFirst: boolean;
426
+ isLast: boolean;
427
+ rows: SmartRowArray;
428
+ allData: T[];
429
+ table: RestrictedTableResult;
430
+ batchInfo?: {
431
+ startIndex: number;
432
+ endIndex: number;
433
+ size: number;
434
+ };
435
+
436
+ }) => T | T[] | Promise<T | T[]>,
437
+ options?: {
438
+ pagination?: PaginationStrategy;
439
+ dedupeStrategy?: DedupeStrategy;
440
+ maxIterations?: number;
441
+ batchSize?: number;
442
+ getIsFirst?: (context: { index: number }) => boolean;
443
+ getIsLast?: (context: { index: number, paginationResult: boolean }) => boolean;
444
+ beforeFirst?: (context: { index: number, rows: SmartRow[], allData: any[] }) => void | Promise<void>;
445
+ afterLast?: (context: { index: number, rows: SmartRow[], allData: any[] }) => void | Promise<void>;
446
+ /**
447
+ * If true, flattens array results from callback into the main data array.
448
+ * If false (default), pushes the return value as-is (preserves batching/arrays).
449
+ */
450
+ autoFlatten?: boolean;
451
+ }
452
+ ) => Promise<T[]>;
453
+
454
+ /**
455
+ * Generate an AI-friendly configuration prompt for debugging.
456
+ * Outputs table HTML and TypeScript definitions to help AI assistants generate config.
457
+ */
458
+ generateConfigPrompt: (options?: PromptOptions) => Promise<void>;
459
+ }
460
+
461
+ /**
462
+ * Restricted table result that excludes methods that shouldn't be called during iteration.
463
+ */
464
+ export type RestrictedTableResult<T = any> = Omit<TableResult<T>, 'searchForRow' | 'iterateThroughTable' | 'reset'>;
465
+ `;