@rickcedwhat/playwright-smart-table 3.0.0 → 3.1.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 +7 -6
- package/dist/typeContext.d.ts +1 -1
- package/dist/typeContext.js +9 -8
- package/dist/types.d.ts +7 -10
- package/dist/useTable.js +3 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -91,8 +91,8 @@ await table.init();
|
|
|
91
91
|
// ✅ Verify Colleen is NOT visible initially
|
|
92
92
|
await expect(page.getByText("Colleen Hurst")).not.toBeVisible();
|
|
93
93
|
|
|
94
|
-
// Use
|
|
95
|
-
await expect(await table.
|
|
94
|
+
// Use searchForRow for pagination
|
|
95
|
+
await expect(await table.searchForRow({ Name: "Colleen Hurst" })).toBeVisible();
|
|
96
96
|
// NOTE: We're now on the page where Colleen Hurst exists (typically Page 2)
|
|
97
97
|
```
|
|
98
98
|
<!-- /embed: pagination -->
|
|
@@ -126,7 +126,7 @@ If your tests navigate deep into a paginated table, use `.reset()` to return to
|
|
|
126
126
|
// Example from: https://datatables.net/examples/data_sources/dom
|
|
127
127
|
// Navigate deep into the table by searching for a row on a later page
|
|
128
128
|
try {
|
|
129
|
-
await table.
|
|
129
|
+
await table.searchForRow({ Name: 'Angelica Ramos' });
|
|
130
130
|
} catch (e) {}
|
|
131
131
|
|
|
132
132
|
// Reset internal state (and potentially UI) to initial page
|
|
@@ -256,7 +256,7 @@ const currentPageRow = table.getByRow({ "Last name": "Melisandre" });
|
|
|
256
256
|
await expect(currentPageRow).not.toBeVisible();
|
|
257
257
|
|
|
258
258
|
// Then find it across pages
|
|
259
|
-
const row = await table.
|
|
259
|
+
const row = await table.searchForRow({ "Last name": "Melisandre" });
|
|
260
260
|
const actionsCell = row.getCell('Actions');
|
|
261
261
|
await actionsCell.getByLabel("Select row").click();
|
|
262
262
|
```
|
|
@@ -328,8 +328,9 @@ await expect(table.getByRow({ Name: "Ghost User" })).not.toBeVisible();
|
|
|
328
328
|
Get row data as JSON:
|
|
329
329
|
<!-- embed: get-by-row-json -->
|
|
330
330
|
```typescript
|
|
331
|
-
// Get row data
|
|
332
|
-
const
|
|
331
|
+
// Get row data as JSON object
|
|
332
|
+
const row = table.getByRow({ Name: 'Airi Satou' });
|
|
333
|
+
const data = await row.toJSON();
|
|
333
334
|
// Returns: { Name: "Airi Satou", Position: "Accountant", Office: "Tokyo", ... }
|
|
334
335
|
|
|
335
336
|
expect(data).toHaveProperty('Name', 'Airi Satou');
|
package/dist/typeContext.d.ts
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* This file is generated by scripts/embed-types.js
|
|
4
4
|
* It contains the raw text of types.ts to provide context for LLM prompts.
|
|
5
5
|
*/
|
|
6
|
-
export declare const TYPE_CONTEXT = "\nexport type Selector = string | ((root: Locator | Page) => Locator);\n\nexport type SmartRow = Locator & {\n getCell(column: string): Locator;\n toJSON(): Promise<Record<string, string>>;\n /**\n * Fills the row with data. Automatically detects input types (text input, select, checkbox, etc.).\n */\n smartFill: (data: Record<string, any>, options?: FillOptions) => Promise<void>;\n};\n\nexport type StrategyContext = TableContext;\n\n/**\n * Defines the contract for a sorting strategy.\n */\nexport interface SortingStrategy {\n /**\n * Performs the sort action on a column.\n */\n doSort(options: {\n columnName: string;\n direction: 'asc' | 'desc';\n context: StrategyContext;\n }): Promise<void>;\n\n /**\n * Retrieves the current sort state of a column.\n */\n getSortState(options: {\n columnName: string;\n context: StrategyContext;\n }): Promise<'asc' | 'desc' | 'none'>;\n}\n\nexport interface TableContext {\n root: Locator;\n config: FinalTableConfig;\n page: Page;\n resolve: (selector: Selector, parent: Locator | Page) => Locator;\n}\n\nexport type PaginationStrategy = (context: TableContext) => Promise<boolean>;\n\nexport type DedupeStrategy = (row: SmartRow) => string | number | Promise<string | number>;\n\nexport interface PromptOptions {\n /**\n * Output Strategy:\n * - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).\n * - 'console': Standard console logs (Default).\n */\n output?: 'console' | 'error';\n includeTypes?: boolean;\n}\n\nexport interface TableConfig {\n rowSelector?: Selector;\n headerSelector?: Selector;\n cellSelector?: Selector;\n pagination?: PaginationStrategy;\n sorting?: SortingStrategy;\n maxPages?: number;\n /**\n * Hook to rename columns dynamically.\n * * @param args.text - The default innerText of the header.\n * @param args.index - The column index.\n * @param args.locator - The specific header cell locator.\n */\n headerTransformer?: (args: { text: string, index: number, locator: Locator }) => string | Promise<string>;\n autoScroll?: boolean;\n /**\n * Enable debug mode to log internal state to console.\n */\n debug?: boolean;\n /**\n * Strategy to reset the table to the initial page.\n * Called when table.reset() is invoked.\n */\n onReset?: (context: TableContext) => Promise<void>;\n}\n\n/**\n * Represents the final, resolved table configuration after default values have been applied.\n * All optional properties from TableConfig are now required, except for `sorting`.\n */\nexport type FinalTableConfig = Required<Omit<TableConfig, 'sorting'>> & {\n sorting?: SortingStrategy;\n};\n\nexport interface FillOptions {\n /**\n * Custom input mappers for specific columns.\n * Maps column names to functions that return the input locator for that cell.\n * Columns not specified here will use auto-detection.\n */\n inputMappers?: Record<string, (cell: Locator) => Locator>;\n}\n\nexport interface TableResult {\n /**\n * Initializes the table by resolving headers. Must be called before using sync methods.\n * @param options Optional timeout for header resolution (default: 3000ms)\n */\n init(options?: { timeout?: number }): Promise<TableResult>;\n\n getHeaders: () => Promise<string[]>;\n getHeaderCell: (columnName: string) => Promise<Locator>;\n\n /**\n * Finds a row on the current page only. Returns immediately (sync).\n * Throws error if table is not initialized.\n */\n getByRow:
|
|
6
|
+
export declare const TYPE_CONTEXT = "\nexport type Selector = string | ((root: Locator | Page) => Locator);\n\nexport type SmartRow = Locator & {\n getCell(column: string): Locator;\n toJSON(): Promise<Record<string, string>>;\n /**\n * Fills the row with data. Automatically detects input types (text input, select, checkbox, etc.).\n */\n smartFill: (data: Record<string, any>, options?: FillOptions) => Promise<void>;\n};\n\nexport type StrategyContext = TableContext;\n\n/**\n * Defines the contract for a sorting strategy.\n */\nexport interface SortingStrategy {\n /**\n * Performs the sort action on a column.\n */\n doSort(options: {\n columnName: string;\n direction: 'asc' | 'desc';\n context: StrategyContext;\n }): Promise<void>;\n\n /**\n * Retrieves the current sort state of a column.\n */\n getSortState(options: {\n columnName: string;\n context: StrategyContext;\n }): Promise<'asc' | 'desc' | 'none'>;\n}\n\nexport interface TableContext {\n root: Locator;\n config: FinalTableConfig;\n page: Page;\n resolve: (selector: Selector, parent: Locator | Page) => Locator;\n}\n\nexport type PaginationStrategy = (context: TableContext) => Promise<boolean>;\n\nexport type DedupeStrategy = (row: SmartRow) => string | number | Promise<string | number>;\n\nexport interface PromptOptions {\n /**\n * Output Strategy:\n * - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).\n * - 'console': Standard console logs (Default).\n */\n output?: 'console' | 'error';\n includeTypes?: boolean;\n}\n\nexport interface TableConfig {\n rowSelector?: Selector;\n headerSelector?: Selector;\n cellSelector?: Selector;\n pagination?: PaginationStrategy;\n sorting?: SortingStrategy;\n maxPages?: number;\n /**\n * Hook to rename columns dynamically.\n * * @param args.text - The default innerText of the header.\n * @param args.index - The column index.\n * @param args.locator - The specific header cell locator.\n */\n headerTransformer?: (args: { text: string, index: number, locator: Locator }) => string | Promise<string>;\n autoScroll?: boolean;\n /**\n * Enable debug mode to log internal state to console.\n */\n debug?: boolean;\n /**\n * Strategy to reset the table to the initial page.\n * Called when table.reset() is invoked.\n */\n onReset?: (context: TableContext) => Promise<void>;\n}\n\n/**\n * Represents the final, resolved table configuration after default values have been applied.\n * All optional properties from TableConfig are now required, except for `sorting`.\n */\nexport type FinalTableConfig = Required<Omit<TableConfig, 'sorting'>> & {\n sorting?: SortingStrategy;\n};\n\nexport interface FillOptions {\n /**\n * Custom input mappers for specific columns.\n * Maps column names to functions that return the input locator for that cell.\n * Columns not specified here will use auto-detection.\n */\n inputMappers?: Record<string, (cell: Locator) => Locator>;\n}\n\nexport interface TableResult {\n /**\n * Initializes the table by resolving headers. Must be called before using sync methods.\n * @param options Optional timeout for header resolution (default: 3000ms)\n */\n init(options?: { timeout?: number }): Promise<TableResult>;\n\n getHeaders: () => Promise<string[]>;\n getHeaderCell: (columnName: string) => Promise<Locator>;\n\n /**\n * Finds a row on the current page only. Returns immediately (sync).\n * Throws error if table is not initialized.\n */\n getByRow: (\n filters: Record<string, string | RegExp | number>, \n options?: { exact?: boolean }\n ) => SmartRow;\n\n /**\n * Searches for a row across all available data using the configured strategy (pagination, scroll, etc.).\n * Auto-initializes if needed.\n */\n searchForRow: (\n filters: Record<string, string | RegExp | number>, \n options?: { exact?: boolean, maxPages?: number }\n ) => Promise<SmartRow>;\n\n getAllRows: <T extends { asJSON?: boolean }>(\n options?: { filter?: Record<string, any>, exact?: boolean } & T\n ) => Promise<T['asJSON'] extends true ? Record<string, string>[] : SmartRow[]>;\n\n generateConfigPrompt: (options?: PromptOptions) => Promise<void>;\n generateStrategyPrompt: (options?: PromptOptions) => Promise<void>;\n\n /**\n * Resets the table state (clears cache, flags) and invokes the onReset strategy.\n */\n reset: () => Promise<void>;\n\n /**\n * Scans a specific column across all pages and returns the values.\n */\n getColumnValues: <V = string>(column: string, options?: { mapper?: (cell: Locator) => Promise<V> | V, maxPages?: number }) => Promise<V[]>;\n\n /**\n * Provides access to sorting actions and assertions.\n */\n sorting: {\n /**\n * Applies the configured sorting strategy to the specified column.\n * @param columnName The name of the column to sort.\n * @param direction The direction to sort ('asc' or 'desc').\n */\n apply(columnName: string, direction: 'asc' | 'desc'): Promise<void>;\n /**\n * Gets the current sort state of a column using the configured sorting strategy.\n * @param columnName The name of the column to check.\n * @returns A promise that resolves to 'asc', 'desc', or 'none'.\n */\n getState(columnName: string): Promise<'asc' | 'desc' | 'none'>;\n };\n\n /**\n * Iterates through paginated table data, calling the callback for each iteration.\n * Callback return values are automatically appended to allData, which is returned.\n */\n iterateThroughTable: <T = any>(\n callback: (context: {\n index: number;\n isFirst: boolean;\n isLast: boolean;\n rows: SmartRow[];\n allData: T[];\n table: RestrictedTableResult;\n }) => T | Promise<T>,\n options?: {\n pagination?: PaginationStrategy;\n dedupeStrategy?: DedupeStrategy;\n maxIterations?: number;\n getIsFirst?: (context: { index: number }) => boolean;\n getIsLast?: (context: { index: number, paginationResult: boolean }) => boolean;\n onFirst?: (context: { index: number, rows: SmartRow[], allData: any[] }) => void | Promise<void>;\n onLast?: (context: { index: number, rows: SmartRow[], allData: any[] }) => void | Promise<void>;\n }\n ) => Promise<T[]>;\n}\n\n/**\n * Restricted table result that excludes methods that shouldn't be called during iteration.\n */\nexport type RestrictedTableResult = Omit<TableResult, 'searchForRow' | 'iterateThroughTable' | 'reset'>;\n";
|
package/dist/typeContext.js
CHANGED
|
@@ -120,18 +120,19 @@ export interface TableResult {
|
|
|
120
120
|
* Finds a row on the current page only. Returns immediately (sync).
|
|
121
121
|
* Throws error if table is not initialized.
|
|
122
122
|
*/
|
|
123
|
-
getByRow:
|
|
123
|
+
getByRow: (
|
|
124
124
|
filters: Record<string, string | RegExp | number>,
|
|
125
|
-
options?: { exact?: boolean }
|
|
126
|
-
) =>
|
|
125
|
+
options?: { exact?: boolean }
|
|
126
|
+
) => SmartRow;
|
|
127
127
|
|
|
128
128
|
/**
|
|
129
|
-
*
|
|
129
|
+
* Searches for a row across all available data using the configured strategy (pagination, scroll, etc.).
|
|
130
|
+
* Auto-initializes if needed.
|
|
130
131
|
*/
|
|
131
|
-
|
|
132
|
+
searchForRow: (
|
|
132
133
|
filters: Record<string, string | RegExp | number>,
|
|
133
|
-
options?: { exact?: boolean, maxPages?: number }
|
|
134
|
-
) => Promise<
|
|
134
|
+
options?: { exact?: boolean, maxPages?: number }
|
|
135
|
+
) => Promise<SmartRow>;
|
|
135
136
|
|
|
136
137
|
getAllRows: <T extends { asJSON?: boolean }>(
|
|
137
138
|
options?: { filter?: Record<string, any>, exact?: boolean } & T
|
|
@@ -196,5 +197,5 @@ export interface TableResult {
|
|
|
196
197
|
/**
|
|
197
198
|
* Restricted table result that excludes methods that shouldn't be called during iteration.
|
|
198
199
|
*/
|
|
199
|
-
export type RestrictedTableResult = Omit<TableResult, '
|
|
200
|
+
export type RestrictedTableResult = Omit<TableResult, 'searchForRow' | 'iterateThroughTable' | 'reset'>;
|
|
200
201
|
`;
|
package/dist/types.d.ts
CHANGED
|
@@ -104,20 +104,17 @@ export interface TableResult {
|
|
|
104
104
|
* Finds a row on the current page only. Returns immediately (sync).
|
|
105
105
|
* Throws error if table is not initialized.
|
|
106
106
|
*/
|
|
107
|
-
getByRow: <
|
|
108
|
-
asJSON?: boolean;
|
|
109
|
-
}>(filters: Record<string, string | RegExp | number>, options?: {
|
|
107
|
+
getByRow: (filters: Record<string, string | RegExp | number>, options?: {
|
|
110
108
|
exact?: boolean;
|
|
111
|
-
}
|
|
109
|
+
}) => SmartRow;
|
|
112
110
|
/**
|
|
113
|
-
*
|
|
111
|
+
* Searches for a row across all available data using the configured strategy (pagination, scroll, etc.).
|
|
112
|
+
* Auto-initializes if needed.
|
|
114
113
|
*/
|
|
115
|
-
|
|
116
|
-
asJSON?: boolean;
|
|
117
|
-
}>(filters: Record<string, string | RegExp | number>, options?: {
|
|
114
|
+
searchForRow: (filters: Record<string, string | RegExp | number>, options?: {
|
|
118
115
|
exact?: boolean;
|
|
119
116
|
maxPages?: number;
|
|
120
|
-
}
|
|
117
|
+
}) => Promise<SmartRow>;
|
|
121
118
|
getAllRows: <T extends {
|
|
122
119
|
asJSON?: boolean;
|
|
123
120
|
}>(options?: {
|
|
@@ -191,4 +188,4 @@ export interface TableResult {
|
|
|
191
188
|
/**
|
|
192
189
|
* Restricted table result that excludes methods that shouldn't be called during iteration.
|
|
193
190
|
*/
|
|
194
|
-
export type RestrictedTableResult = Omit<TableResult, '
|
|
191
|
+
export type RestrictedTableResult = Omit<TableResult, 'searchForRow' | 'iterateThroughTable' | 'reset'>;
|
package/dist/useTable.js
CHANGED
|
@@ -420,13 +420,9 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
420
420
|
const matchedRows = _applyFilters(allRows, filters, _headerMap, (options === null || options === void 0 ? void 0 : options.exact) || false);
|
|
421
421
|
// Return first match (or sentinel) - lazy, doesn't check existence
|
|
422
422
|
const rowLocator = matchedRows.first();
|
|
423
|
-
|
|
424
|
-
if (options === null || options === void 0 ? void 0 : options.asJSON) {
|
|
425
|
-
return smartRow.toJSON();
|
|
426
|
-
}
|
|
427
|
-
return smartRow;
|
|
423
|
+
return _makeSmart(rowLocator, _headerMap);
|
|
428
424
|
},
|
|
429
|
-
|
|
425
|
+
searchForRow: (filters, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
430
426
|
// Auto-init if needed (async methods can auto-init)
|
|
431
427
|
yield _ensureInitialized();
|
|
432
428
|
// Full pagination logic (existing _findRowLocator logic)
|
|
@@ -434,11 +430,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
434
430
|
if (!row) {
|
|
435
431
|
row = resolve(config.rowSelector, rootLocator).filter({ hasText: "___SENTINEL_ROW_NOT_FOUND___" + Date.now() });
|
|
436
432
|
}
|
|
437
|
-
|
|
438
|
-
if (options === null || options === void 0 ? void 0 : options.asJSON) {
|
|
439
|
-
return smartRow.toJSON();
|
|
440
|
-
}
|
|
441
|
-
return smartRow;
|
|
433
|
+
return _makeSmart(row, _headerMap);
|
|
442
434
|
}),
|
|
443
435
|
getAllRows: (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
444
436
|
// Auto-init if needed (async methods can auto-init)
|
package/package.json
CHANGED