@rickcedwhat/playwright-smart-table 6.0.1 → 6.1.1
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/dist/{examples/glide-strategies → strategies/glide}/columns.d.ts +1 -1
- package/dist/{examples/glide-strategies → strategies/glide}/headers.d.ts +1 -1
- package/dist/{src/strategies → strategies}/glide.js +2 -2
- package/dist/strategies/index.d.ts +29 -2
- package/dist/strategies/index.js +6 -0
- package/dist/strategies/pagination.d.ts +26 -4
- package/dist/strategies/pagination.js +52 -23
- package/dist/typeContext.d.ts +1 -1
- package/dist/typeContext.js +28 -4
- package/dist/types.d.ts +33 -2
- package/dist/useTable.d.ts +28 -3
- package/dist/useTable.js +92 -36
- package/package.json +1 -1
- package/dist/src/filterEngine.d.ts +0 -11
- package/dist/src/filterEngine.js +0 -39
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.js +0 -18
- package/dist/src/smartRow.d.ts +0 -7
- package/dist/src/smartRow.js +0 -160
- package/dist/src/strategies/columns.d.ts +0 -18
- package/dist/src/strategies/columns.js +0 -21
- package/dist/src/strategies/fill.d.ts +0 -7
- package/dist/src/strategies/fill.js +0 -88
- package/dist/src/strategies/headers.d.ts +0 -13
- package/dist/src/strategies/headers.js +0 -30
- package/dist/src/strategies/index.d.ts +0 -54
- package/dist/src/strategies/index.js +0 -43
- package/dist/src/strategies/pagination.d.ts +0 -33
- package/dist/src/strategies/pagination.js +0 -79
- package/dist/src/strategies/resolution.d.ts +0 -22
- package/dist/src/strategies/resolution.js +0 -30
- package/dist/src/strategies/sorting.d.ts +0 -12
- package/dist/src/strategies/sorting.js +0 -68
- package/dist/src/strategies/validation.d.ts +0 -22
- package/dist/src/strategies/validation.js +0 -54
- package/dist/src/strategies/virtualizedPagination.d.ts +0 -32
- package/dist/src/strategies/virtualizedPagination.js +0 -80
- package/dist/src/typeContext.d.ts +0 -6
- package/dist/src/typeContext.js +0 -465
- package/dist/src/types.d.ts +0 -458
- package/dist/src/types.js +0 -2
- package/dist/src/useTable.d.ts +0 -44
- package/dist/src/useTable.js +0 -642
- package/dist/src/utils/debugUtils.d.ts +0 -17
- package/dist/src/utils/debugUtils.js +0 -62
- package/dist/src/utils/smartRowArray.d.ts +0 -14
- package/dist/src/utils/smartRowArray.js +0 -22
- package/dist/src/utils/stringUtils.d.ts +0 -22
- package/dist/src/utils/stringUtils.js +0 -73
- package/dist/src/utils.d.ts +0 -7
- package/dist/src/utils.js +0 -29
- package/dist/utils/traceUtils.d.ts +0 -11
- package/dist/utils/traceUtils.js +0 -47
- /package/dist/{src/plugins.d.ts → plugins.d.ts} +0 -0
- /package/dist/{src/plugins.js → plugins.js} +0 -0
- /package/dist/{src/strategies → strategies}/dedupe.d.ts +0 -0
- /package/dist/{src/strategies → strategies}/dedupe.js +0 -0
- /package/dist/{examples/glide-strategies → strategies/glide}/columns.js +0 -0
- /package/dist/{examples/glide-strategies → strategies/glide}/headers.js +0 -0
- /package/dist/{src/strategies → strategies}/glide.d.ts +0 -0
- /package/dist/{src/strategies → strategies}/loading.d.ts +0 -0
- /package/dist/{src/strategies → strategies}/loading.js +0 -0
- /package/dist/{src/strategies → strategies}/rdg.d.ts +0 -0
- /package/dist/{src/strategies → strategies}/rdg.js +0 -0
- /package/dist/{src/strategies → strategies}/stabilization.d.ts +0 -0
- /package/dist/{src/strategies → strategies}/stabilization.js +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StrategyContext } from '../../
|
|
1
|
+
import { StrategyContext } from '../../types';
|
|
2
2
|
/**
|
|
3
3
|
* Strategy that clicks into the table to establish focus and then uses the Right Arrow key
|
|
4
4
|
* to navigate to the target CELL (navigates down to the row, then right to the column).
|
|
@@ -10,8 +10,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.GlideStrategies = exports.glideGetActiveCell = exports.glideGetCellLocator = exports.glidePaginationStrategy = exports.glideFillStrategy = void 0;
|
|
13
|
-
const columns_1 = require("
|
|
14
|
-
const headers_1 = require("
|
|
13
|
+
const columns_1 = require("./glide/columns");
|
|
14
|
+
const headers_1 = require("./glide/headers");
|
|
15
15
|
const pagination_1 = require("./pagination");
|
|
16
16
|
const stabilization_1 = require("./stabilization");
|
|
17
17
|
const glideFillStrategy = (_a) => __awaiter(void 0, [_a], void 0, function* ({ value, page }) {
|
|
@@ -4,10 +4,21 @@ export * from './columns';
|
|
|
4
4
|
export * from './headers';
|
|
5
5
|
export * from './fill';
|
|
6
6
|
export * from './resolution';
|
|
7
|
+
export * from './dedupe';
|
|
8
|
+
export * from './loading';
|
|
7
9
|
export declare const Strategies: {
|
|
8
10
|
Pagination: {
|
|
9
|
-
clickNext: (nextButtonSelector: import("..").Selector,
|
|
10
|
-
|
|
11
|
+
clickNext: (nextButtonSelector: import("..").Selector, options?: {
|
|
12
|
+
stabilization?: import("./stabilization").StabilizationStrategy;
|
|
13
|
+
timeout?: number;
|
|
14
|
+
}) => import("..").PaginationStrategy;
|
|
15
|
+
infiniteScroll: (options?: {
|
|
16
|
+
action?: "scroll" | "js-scroll";
|
|
17
|
+
scrollTarget?: import("..").Selector;
|
|
18
|
+
scrollAmount?: number;
|
|
19
|
+
stabilization?: import("./stabilization").StabilizationStrategy;
|
|
20
|
+
timeout?: number;
|
|
21
|
+
}) => import("..").PaginationStrategy;
|
|
11
22
|
};
|
|
12
23
|
Sorting: {
|
|
13
24
|
AriaSort: () => import("..").SortingStrategy;
|
|
@@ -24,4 +35,20 @@ export declare const Strategies: {
|
|
|
24
35
|
Resolution: {
|
|
25
36
|
default: import("./resolution").ColumnResolutionStrategy;
|
|
26
37
|
};
|
|
38
|
+
Dedupe: {
|
|
39
|
+
byTopPosition: (tolerance?: number) => import("..").DedupeStrategy;
|
|
40
|
+
};
|
|
41
|
+
Loading: {
|
|
42
|
+
Table: {
|
|
43
|
+
hasSpinner: (selector?: string) => ({ root }: import("..").TableContext) => Promise<boolean>;
|
|
44
|
+
custom: (fn: (context: import("..").TableContext) => Promise<boolean>) => (context: import("..").TableContext) => Promise<boolean>;
|
|
45
|
+
never: () => Promise<boolean>;
|
|
46
|
+
};
|
|
47
|
+
Row: {
|
|
48
|
+
hasClass: (className?: string) => (row: import("..").SmartRow) => Promise<boolean>;
|
|
49
|
+
hasText: (text?: string | RegExp) => (row: import("..").SmartRow) => Promise<boolean>;
|
|
50
|
+
hasEmptyCells: () => (row: import("..").SmartRow) => Promise<boolean>;
|
|
51
|
+
never: () => Promise<boolean>;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
27
54
|
};
|
package/dist/strategies/index.js
CHANGED
|
@@ -21,12 +21,16 @@ const columns_1 = require("./columns");
|
|
|
21
21
|
const headers_1 = require("./headers");
|
|
22
22
|
const fill_1 = require("./fill");
|
|
23
23
|
const resolution_1 = require("./resolution");
|
|
24
|
+
const dedupe_1 = require("./dedupe");
|
|
25
|
+
const loading_1 = require("./loading");
|
|
24
26
|
__exportStar(require("./pagination"), exports);
|
|
25
27
|
__exportStar(require("./sorting"), exports);
|
|
26
28
|
__exportStar(require("./columns"), exports);
|
|
27
29
|
__exportStar(require("./headers"), exports);
|
|
28
30
|
__exportStar(require("./fill"), exports);
|
|
29
31
|
__exportStar(require("./resolution"), exports);
|
|
32
|
+
__exportStar(require("./dedupe"), exports);
|
|
33
|
+
__exportStar(require("./loading"), exports);
|
|
30
34
|
exports.Strategies = {
|
|
31
35
|
Pagination: pagination_1.PaginationStrategies,
|
|
32
36
|
Sorting: sorting_1.SortingStrategies,
|
|
@@ -34,4 +38,6 @@ exports.Strategies = {
|
|
|
34
38
|
Header: headers_1.HeaderStrategies,
|
|
35
39
|
Fill: fill_1.FillStrategies,
|
|
36
40
|
Resolution: resolution_1.ResolutionStrategies,
|
|
41
|
+
Dedupe: dedupe_1.DedupeStrategies,
|
|
42
|
+
Loading: loading_1.LoadingStrategies,
|
|
37
43
|
};
|
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
import type { PaginationStrategy, Selector } from '../types';
|
|
2
|
+
import { StabilizationStrategy } from './stabilization';
|
|
2
3
|
export declare const PaginationStrategies: {
|
|
3
4
|
/**
|
|
4
|
-
* Strategy: Clicks a "Next" button and waits for
|
|
5
|
+
* Strategy: Clicks a "Next" button and waits for stabilization.
|
|
6
|
+
* @param nextButtonSelector Selector for the next page button.
|
|
7
|
+
* @param options.stabilization Strategy to determine when the page has updated.
|
|
8
|
+
* Defaults to `contentChanged({ scope: 'first' })`.
|
|
9
|
+
* @param options.timeout Timeout for the click action.
|
|
5
10
|
*/
|
|
6
|
-
clickNext: (nextButtonSelector: Selector,
|
|
11
|
+
clickNext: (nextButtonSelector: Selector, options?: {
|
|
12
|
+
stabilization?: StabilizationStrategy;
|
|
13
|
+
timeout?: number;
|
|
14
|
+
}) => PaginationStrategy;
|
|
7
15
|
/**
|
|
8
|
-
* Strategy:
|
|
16
|
+
* Strategy: Infinite Scroll (generic).
|
|
17
|
+
* Supports both simple "Scroll to Bottom" and "Virtualized Scroll".
|
|
18
|
+
*
|
|
19
|
+
* @param options.action 'scroll' (mouse wheel) or 'js-scroll' (direct scrollTop).
|
|
20
|
+
* @param options.scrollTarget Selector for the scroll container (defaults to table root).
|
|
21
|
+
* @param options.scrollAmount Amount to scroll in pixels (default 500).
|
|
22
|
+
* @param options.stabilization Strategy to determine if new content loaded.
|
|
23
|
+
* Defaults to `rowCountIncreased` (simple append).
|
|
24
|
+
* Use `contentChanged` for virtualization.
|
|
9
25
|
*/
|
|
10
|
-
infiniteScroll: (
|
|
26
|
+
infiniteScroll: (options?: {
|
|
27
|
+
action?: "scroll" | "js-scroll";
|
|
28
|
+
scrollTarget?: Selector;
|
|
29
|
+
scrollAmount?: number;
|
|
30
|
+
stabilization?: StabilizationStrategy;
|
|
31
|
+
timeout?: number;
|
|
32
|
+
}) => PaginationStrategy;
|
|
11
33
|
};
|
|
@@ -10,41 +10,70 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.PaginationStrategies = void 0;
|
|
13
|
-
const
|
|
13
|
+
const stabilization_1 = require("./stabilization");
|
|
14
14
|
exports.PaginationStrategies = {
|
|
15
15
|
/**
|
|
16
|
-
* Strategy: Clicks a "Next" button and waits for
|
|
16
|
+
* Strategy: Clicks a "Next" button and waits for stabilization.
|
|
17
|
+
* @param nextButtonSelector Selector for the next page button.
|
|
18
|
+
* @param options.stabilization Strategy to determine when the page has updated.
|
|
19
|
+
* Defaults to `contentChanged({ scope: 'first' })`.
|
|
20
|
+
* @param options.timeout Timeout for the click action.
|
|
17
21
|
*/
|
|
18
|
-
clickNext: (nextButtonSelector,
|
|
19
|
-
return (
|
|
22
|
+
clickNext: (nextButtonSelector, options = {}) => {
|
|
23
|
+
return (context) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
|
+
var _a;
|
|
25
|
+
const { root, resolve, page } = context;
|
|
20
26
|
const nextBtn = resolve(nextButtonSelector, root).first();
|
|
21
27
|
if (!(yield nextBtn.isVisible()) || !(yield nextBtn.isEnabled())) {
|
|
22
28
|
return false;
|
|
23
29
|
}
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
const success = yield (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}), timeout, page);
|
|
30
|
+
// Default stabilization: Wait for first row content to change
|
|
31
|
+
const stabilization = (_a = options.stabilization) !== null && _a !== void 0 ? _a : stabilization_1.StabilizationStrategies.contentChanged({ scope: 'first', timeout: options.timeout });
|
|
32
|
+
// Stabilization: Wrap action
|
|
33
|
+
const success = yield stabilization(context, () => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
+
yield nextBtn.click({ timeout: 2000 }).catch(() => { });
|
|
35
|
+
}));
|
|
31
36
|
return success;
|
|
32
37
|
});
|
|
33
38
|
},
|
|
34
39
|
/**
|
|
35
|
-
* Strategy:
|
|
40
|
+
* Strategy: Infinite Scroll (generic).
|
|
41
|
+
* Supports both simple "Scroll to Bottom" and "Virtualized Scroll".
|
|
42
|
+
*
|
|
43
|
+
* @param options.action 'scroll' (mouse wheel) or 'js-scroll' (direct scrollTop).
|
|
44
|
+
* @param options.scrollTarget Selector for the scroll container (defaults to table root).
|
|
45
|
+
* @param options.scrollAmount Amount to scroll in pixels (default 500).
|
|
46
|
+
* @param options.stabilization Strategy to determine if new content loaded.
|
|
47
|
+
* Defaults to `rowCountIncreased` (simple append).
|
|
48
|
+
* Use `contentChanged` for virtualization.
|
|
36
49
|
*/
|
|
37
|
-
infiniteScroll: (
|
|
38
|
-
return (
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
infiniteScroll: (options = {}) => {
|
|
51
|
+
return (context) => __awaiter(void 0, void 0, void 0, function* () {
|
|
52
|
+
var _a, _b;
|
|
53
|
+
const { root, resolve, page } = context;
|
|
54
|
+
const scrollTarget = options.scrollTarget
|
|
55
|
+
? resolve(options.scrollTarget, root)
|
|
56
|
+
: root;
|
|
57
|
+
// Default stabilization: Wait for row count to increase (Append mode)
|
|
58
|
+
const stabilization = (_a = options.stabilization) !== null && _a !== void 0 ? _a : stabilization_1.StabilizationStrategies.rowCountIncreased({ timeout: options.timeout });
|
|
59
|
+
const amount = (_b = options.scrollAmount) !== null && _b !== void 0 ? _b : 500;
|
|
60
|
+
const doScroll = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
61
|
+
const box = yield scrollTarget.boundingBox();
|
|
62
|
+
// Action: Scroll
|
|
63
|
+
if (options.action === 'js-scroll' || !box) {
|
|
64
|
+
yield scrollTarget.evaluate((el, y) => {
|
|
65
|
+
el.scrollTop += y;
|
|
66
|
+
}, amount);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// Mouse Wheel
|
|
70
|
+
yield page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
|
|
71
|
+
yield page.mouse.wheel(0, amount);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
// Stabilization: Wait
|
|
75
|
+
const success = yield stabilization(context, doScroll);
|
|
76
|
+
return success;
|
|
48
77
|
});
|
|
49
78
|
}
|
|
50
79
|
};
|
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 = "\n/**\n * Flexible selector type - can be a CSS string, function returning a Locator, or Locator itself.\n * @example\n * // String selector\n * rowSelector: 'tbody tr'\n * \n * // Function selector\n * rowSelector: (root) => root.locator('[role=\"row\"]')\n */\nexport type Selector = string | ((root: Locator | Page) => Locator);\n\n/**\n * Function to get a cell locator given row, column info.\n * Replaces the old cellResolver.\n */\nexport type GetCellLocatorFn = (args: {\n row: Locator;\n columnName: string;\n columnIndex: number;\n rowIndex?: number;\n page: Page;\n}) => Locator;\n\n/**\n * Function to get the currently active/focused cell.\n * Returns null if no cell is active.\n */\nexport type GetActiveCellFn = (args: TableContext) => Promise<{\n rowIndex: number;\n columnIndex: number;\n columnName?: string;\n locator: Locator;\n} | null>;\n\n\n/**\n * SmartRow - A Playwright Locator with table-aware methods.\n * \n * Extends all standard Locator methods (click, isVisible, etc.) with table-specific functionality.\n * \n * @example\n * const row = table.getRow({ Name: 'John Doe' });\n * await row.click(); // Standard Locator method\n * const email = row.getCell('Email'); // Table-aware method\n * const data = await row.toJSON(); // Extract all row data\n * await row.smartFill({ Name: 'Jane', Status: 'Active' }); // Fill form fields\n */\nexport type SmartRow<T = any> = Locator & {\n /** Optional row index (0-based) if known */\n rowIndex?: number;\n\n /**\n * Get a cell locator by column name.\n * @param column - Column name (case-sensitive)\n * @returns Locator for the cell\n * @example\n * const emailCell = row.getCell('Email');\n * await expect(emailCell).toHaveText('john@example.com');\n */\n getCell(column: string): Locator;\n\n /**\n * Extract all cell data as a key-value object.\n * @param options - Optional configuration\n * @param options.columns - Specific columns to extract (extracts all if not specified)\n * @returns Promise resolving to row data\n * @example\n * const data = await row.toJSON();\n * // { Name: 'John', Email: 'john@example.com', ... }\n * \n * const partial = await row.toJSON({ columns: ['Name', 'Email'] });\n * // { Name: 'John', Email: 'john@example.com' }\n */\n toJSON(options?: { columns?: string[] }): Promise<T>;\n\n /**\n * Scrolls/paginates to bring this row into view.\n * Only works if rowIndex is known (e.g., from getRowByIndex).\n * @throws Error if rowIndex is unknown\n */\n bringIntoView(): Promise<void>;\n\n /**\n * Intelligently fills form fields in the row.\n * Automatically detects input types (text, select, checkbox, contenteditable).\n * \n * @param data - Column-value pairs to fill\n * @param options - Optional configuration\n * @param options.inputMappers - Custom input selectors per column\n * @example\n * // Auto-detection\n * await row.smartFill({ Name: 'John', Status: 'Active', Subscribe: true });\n * \n * // Custom input mappers\n * await row.smartFill(\n * { Name: 'John' },\n * { inputMappers: { Name: (cell) => cell.locator('.custom-input') } }\n * );\n */\n smartFill: (data: Partial<T> | Record<string, any>, options?: FillOptions) => Promise<void>;\n};\n\nexport type StrategyContext = TableContext & { rowLocator?: Locator; rowIndex?: number };\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\n/**\n * Debug configuration for development and troubleshooting\n */\nexport type DebugConfig = {\n /**\n * Slow down operations for debugging\n * - number: Apply same delay to all operations (ms)\n * - object: Granular delays per operation type\n */\n slow?: number | {\n pagination?: number;\n getCell?: number;\n findRow?: number;\n default?: number;\n };\n /**\n * Log level for debug output\n * - 'verbose': All logs (verbose, info, error)\n * - 'info': Info and error logs only\n * - 'error': Error logs only\n * - 'none': No logs\n */\n logLevel?: 'verbose' | 'info' | 'error' | '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 type FillStrategy = (options: {\n row: SmartRow;\n columnName: string;\n value: any;\n index: number;\n page: Page;\n rootLocator: Locator;\n table: TableResult; // The parent table instance\n fillOptions?: FillOptions;\n}) => Promise<void>;\n\nexport type { HeaderStrategy } from './strategies/headers';\nexport type { CellNavigationStrategy } from './strategies/columns';\n\n/**\n * Strategy to resolve column names (string or regex) to their index.\n */\nexport type { ColumnResolutionStrategy } from './strategies/resolution';\n\n/**\n * Strategy to filter rows based on criteria.\n */\nexport interface FilterStrategy {\n apply(options: {\n rows: Locator;\n filter: { column: string, value: string | RegExp | number };\n colIndex: number;\n tableContext: TableContext;\n }): Locator;\n}\n\n/**\n * Organized container for all table interaction strategies.\n */\nexport interface TableStrategies {\n /** Strategy for discovering/scanning headers */\n header?: HeaderStrategy;\n /** Strategy for navigating to specific cells (row + column) */\n cellNavigation?: CellNavigationStrategy;\n /** Strategy for filling form inputs */\n fill?: FillStrategy;\n /** Strategy for paginating through data */\n pagination?: PaginationStrategy;\n /** Strategy for sorting columns */\n sorting?: SortingStrategy;\n /** Function to get a cell locator */\n getCellLocator?: GetCellLocatorFn;\n /** Function to get the currently active/focused cell */\n getActiveCell?: GetActiveCellFn;\n}\n\n/**\n * Configuration options for useTable.\n */\nexport interface TableConfig {\n /** Selector for the table headers */\n headerSelector?: string;\n /** Selector for the table rows */\n rowSelector?: string;\n /** Selector for the cells within a row */\n cellSelector?: string;\n /** Number of pages to scan for verification */\n maxPages?: number;\n /** Hook to rename columns dynamically */\n headerTransformer?: (args: { text: string, index: number, locator: Locator }) => string | Promise<string>;\n /** Automatically scroll to table on init */\n autoScroll?: boolean;\n /** Debug options for development and troubleshooting */\n debug?: DebugConfig;\n /** Reset hook */\n onReset?: (context: TableContext) => Promise<void>;\n /** All interaction strategies */\n strategies?: TableStrategies;\n}\n\nexport interface FinalTableConfig extends TableConfig {\n headerSelector: string;\n rowSelector: string;\n cellSelector: string;\n maxPages: number;\n autoScroll: boolean;\n debug?: TableConfig['debug'];\n headerTransformer: (args: { text: string, index: number, locator: Locator }) => string | Promise<string>;\n onReset: (context: TableContext) => Promise<void>;\n strategies: TableStrategies;\n}\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 */\n inputMappers?: Record<string, (cell: Locator) => Locator>;\n}\n\n/**\n * Options for generateConfigPrompt\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 /**\n * Include TypeScript type definitions in the prompt\n * @default true\n */\n includeTypes?: boolean;\n}\n\nexport interface TableResult<T = any> {\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 /**\n * SYNC: Checks if the table has been initialized.\n * @returns true if init() has been called and completed, false otherwise\n */\n isInitialized(): boolean;\n\n getHeaders: () => Promise<string[]>;\n getHeaderCell: (columnName: string) => Promise<Locator>;\n\n /**\n * Finds a row by filters on the current page only. Returns immediately (sync).\n * Throws error if table is not initialized.\n */\n getRow: (\n filters: Record<string, string | RegExp | number>,\n options?: { exact?: boolean }\n ) => SmartRow;\n\n /**\n * Gets a row by 1-based index on the current page.\n * Throws error if table is not initialized.\n * @param index 1-based row index\n * @param options Optional settings including bringIntoView\n */\n getRowByIndex: (\n index: number,\n options?: { bringIntoView?: boolean }\n ) => SmartRow;\n\n /**\n * ASYNC: Searches for a single row across pages using pagination.\n * Auto-initializes the table if not already initialized.\n * @param filters - The filter criteria to match\n * @param options - Search options including exact match and max pages\n */\n findRow: (\n filters: Record<string, string | RegExp | number>,\n options?: { exact?: boolean, maxPages?: number }\n ) => Promise<SmartRow>;\n\n /**\n * ASYNC: Searches for all matching rows across pages using pagination.\n * Auto-initializes the table if not already initialized.\n * @param filters - The filter criteria to match\n * @param options - Search options including exact match, max pages, and asJSON\n */\n findRows: <R extends { asJSON?: boolean }>(\n filters: Record<string, string | RegExp | number>,\n options?: { exact?: boolean, maxPages?: number } & R\n ) => Promise<R['asJSON'] extends true ? Record<string, string>[] : SmartRow[]>;\n\n /**\n * Navigates to a specific column using the configured CellNavigationStrategy.\n */\n scrollToColumn: (columnName: string) => Promise<void>;\n\n /**\n * Gets all rows on the current page only (does not paginate).\n * Auto-initializes the table if not already initialized.\n * Returns a SmartRowArray which extends Array with a toJSON() helper method.\n * @param options - Filter options\n */\n getRows: (options?: { filter?: Record<string, any>, exact?: boolean }) => Promise<SmartRowArray>;\n\n /**\n * Resets the table state (clears cache, flags) and invokes the onReset strategy.\n */\n reset: () => Promise<void>;\n\n /**\n * Revalidates the table's structure (headers, columns) without resetting pagination or state.\n * Useful when columns change visibility or order dynamically.\n */\n revalidate: () => 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 batchInfo?: {\n startIndex: number;\n endIndex: number;\n size: number;\n };\n }) => T | Promise<T>,\n options?: {\n pagination?: PaginationStrategy;\n dedupeStrategy?: DedupeStrategy;\n maxIterations?: number;\n batchSize?: number;\n getIsFirst?: (context: { index: number }) => boolean;\n getIsLast?: (context: { index: number, paginationResult: boolean }) => boolean;\n beforeFirst?: (context: { index: number, rows: SmartRow[], allData: any[] }) => void | Promise<void>;\n afterLast?: (context: { index: number, rows: SmartRow[], allData: any[] }) => void | Promise<void>;\n }\n ) => Promise<T[]>;\n\n /**\n * Generate an AI-friendly configuration prompt for debugging.\n * Outputs table HTML and TypeScript definitions to help AI assistants generate config.\n */\n generateConfigPrompt: (options?: PromptOptions) => Promise<void>;\n}\n\n/**\n * Restricted table result that excludes methods that shouldn't be called during iteration.\n */\nexport type RestrictedTableResult<T = any> = Omit<TableResult<T>, 'searchForRow' | 'iterateThroughTable' | 'reset'>;\n";
|
|
6
|
+
export declare const TYPE_CONTEXT = "\n/**\n * Flexible selector type - can be a CSS string, function returning a Locator, or Locator itself.\n * @example\n * // String selector\n * rowSelector: 'tbody tr'\n * \n * // Function selector\n * rowSelector: (root) => root.locator('[role=\"row\"]')\n */\nexport type Selector = string | ((root: Locator | Page) => Locator);\n\n/**\n * Function to get a cell locator given row, column info.\n * Replaces the old cellResolver.\n */\nexport type GetCellLocatorFn = (args: {\n row: Locator;\n columnName: string;\n columnIndex: number;\n rowIndex?: number;\n page: Page;\n}) => Locator;\n\n/**\n * Function to get the currently active/focused cell.\n * Returns null if no cell is active.\n */\nexport type GetActiveCellFn = (args: TableContext) => Promise<{\n rowIndex: number;\n columnIndex: number;\n columnName?: string;\n locator: Locator;\n} | null>;\n\n\n/**\n * SmartRow - A Playwright Locator with table-aware methods.\n * \n * Extends all standard Locator methods (click, isVisible, etc.) with table-specific functionality.\n * \n * @example\n * const row = table.getRow({ Name: 'John Doe' });\n * await row.click(); // Standard Locator method\n * const email = row.getCell('Email'); // Table-aware method\n * const data = await row.toJSON(); // Extract all row data\n * await row.smartFill({ Name: 'Jane', Status: 'Active' }); // Fill form fields\n */\nexport type SmartRow<T = any> = Locator & {\n /** Optional row index (0-based) if known */\n rowIndex?: number;\n\n /**\n * Get a cell locator by column name.\n * @param column - Column name (case-sensitive)\n * @returns Locator for the cell\n * @example\n * const emailCell = row.getCell('Email');\n * await expect(emailCell).toHaveText('john@example.com');\n */\n getCell(column: string): Locator;\n\n /**\n * Extract all cell data as a key-value object.\n * @param options - Optional configuration\n * @param options.columns - Specific columns to extract (extracts all if not specified)\n * @returns Promise resolving to row data\n * @example\n * const data = await row.toJSON();\n * // { Name: 'John', Email: 'john@example.com', ... }\n * \n * const partial = await row.toJSON({ columns: ['Name', 'Email'] });\n * // { Name: 'John', Email: 'john@example.com' }\n */\n toJSON(options?: { columns?: string[] }): Promise<T>;\n\n /**\n * Scrolls/paginates to bring this row into view.\n * Only works if rowIndex is known (e.g., from getRowByIndex).\n * @throws Error if rowIndex is unknown\n */\n bringIntoView(): Promise<void>;\n\n /**\n * Intelligently fills form fields in the row.\n * Automatically detects input types (text, select, checkbox, contenteditable).\n * \n * @param data - Column-value pairs to fill\n * @param options - Optional configuration\n * @param options.inputMappers - Custom input selectors per column\n * @example\n * // Auto-detection\n * await row.smartFill({ Name: 'John', Status: 'Active', Subscribe: true });\n * \n * // Custom input mappers\n * await row.smartFill(\n * { Name: 'John' },\n * { inputMappers: { Name: (cell) => cell.locator('.custom-input') } }\n * );\n */\n smartFill: (data: Partial<T> | Record<string, any>, options?: FillOptions) => Promise<void>;\n};\n\nexport type StrategyContext = TableContext & { rowLocator?: Locator; rowIndex?: number };\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\n/**\n * Debug configuration for development and troubleshooting\n */\nexport type DebugConfig = {\n /**\n * Slow down operations for debugging\n * - number: Apply same delay to all operations (ms)\n * - object: Granular delays per operation type\n */\n slow?: number | {\n pagination?: number;\n getCell?: number;\n findRow?: number;\n default?: number;\n };\n /**\n * Log level for debug output\n * - 'verbose': All logs (verbose, info, error)\n * - 'info': Info and error logs only\n * - 'error': Error logs only\n * - 'none': No logs\n */\n logLevel?: 'verbose' | 'info' | 'error' | '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 type FillStrategy = (options: {\n row: SmartRow;\n columnName: string;\n value: any;\n index: number;\n page: Page;\n rootLocator: Locator;\n table: TableResult; // The parent table instance\n fillOptions?: FillOptions;\n}) => Promise<void>;\n\nexport type { HeaderStrategy } from './strategies/headers';\nexport type { CellNavigationStrategy } from './strategies/columns';\n\n/**\n * Strategy to resolve column names (string or regex) to their index.\n */\nexport type { ColumnResolutionStrategy } from './strategies/resolution';\n\n/**\n * Strategy to filter rows based on criteria.\n */\nexport interface FilterStrategy {\n apply(options: {\n rows: Locator;\n filter: { column: string, value: string | RegExp | number };\n colIndex: number;\n tableContext: TableContext;\n }): Locator;\n}\n\n/**\n * Strategy to check if the table or rows are loading.\n */\nexport interface LoadingStrategy {\n isTableLoading?: (context: TableContext) => Promise<boolean>;\n isRowLoading?: (row: SmartRow) => Promise<boolean>;\n}\n\n/**\n * Organized container for all table interaction strategies.\n */\nexport interface TableStrategies {\n /** Strategy for discovering/scanning headers */\n header?: HeaderStrategy;\n /** Strategy for navigating to specific cells (row + column) */\n cellNavigation?: CellNavigationStrategy;\n /** Strategy for filling form inputs */\n fill?: FillStrategy;\n /** Strategy for paginating through data */\n pagination?: PaginationStrategy;\n /** Strategy for sorting columns */\n sorting?: SortingStrategy;\n /** Strategy for deduplicating rows during iteration/scrolling */\n dedupe?: DedupeStrategy;\n /** Function to get a cell locator */\n getCellLocator?: GetCellLocatorFn;\n /** Function to get the currently active/focused cell */\n getActiveCell?: GetActiveCellFn;\n /** Custom helper to check if a table is fully loaded/ready */\n isTableLoaded?: (args: TableContext) => Promise<boolean>;\n /** Custom helper to check if a row is fully loaded/ready */\n isRowLoaded?: (args: { row: Locator, index: number }) => Promise<boolean>;\n /** Custom helper to check if a cell is fully loaded/ready (e.g. for editing) */\n isCellLoaded?: (args: { cell: Locator, column: string, row: Locator }) => Promise<boolean>;\n /** Strategy for detecting loading states */\n loading?: LoadingStrategy;\n}\n\n/**\n * Configuration options for useTable.\n */\nexport interface TableConfig {\n /** Selector for the table headers */\n headerSelector?: string;\n /** Selector for the table rows */\n rowSelector?: string;\n /** Selector for the cells within a row */\n cellSelector?: string;\n /** Number of pages to scan for verification */\n maxPages?: number;\n /** Hook to rename columns dynamically */\n headerTransformer?: (args: { text: string, index: number, locator: Locator, seenHeaders: Set<string> }) => string | Promise<string>;\n /** Automatically scroll to table on init */\n autoScroll?: boolean;\n /** Debug options for development and troubleshooting */\n debug?: DebugConfig;\n /** Reset hook */\n onReset?: (context: TableContext) => Promise<void>;\n /** All interaction strategies */\n strategies?: TableStrategies;\n}\n\nexport interface FinalTableConfig extends TableConfig {\n headerSelector: string;\n rowSelector: string;\n cellSelector: string;\n maxPages: number;\n autoScroll: boolean;\n debug?: TableConfig['debug'];\n headerTransformer: (args: { text: string, index: number, locator: Locator, seenHeaders: Set<string> }) => string | Promise<string>;\n onReset: (context: TableContext) => Promise<void>;\n strategies: TableStrategies;\n}\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 */\n inputMappers?: Record<string, (cell: Locator) => Locator>;\n}\n\n/**\n * Options for generateConfigPrompt\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 /**\n * Include TypeScript type definitions in the prompt\n * @default true\n */\n includeTypes?: boolean;\n}\n\nexport interface TableResult<T = any> {\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 /**\n * SYNC: Checks if the table has been initialized.\n * @returns true if init() has been called and completed, false otherwise\n */\n isInitialized(): boolean;\n\n getHeaders: () => Promise<string[]>;\n getHeaderCell: (columnName: string) => Promise<Locator>;\n\n /**\n * Finds a row by filters on the current page only. Returns immediately (sync).\n * Throws error if table is not initialized.\n */\n getRow: (\n filters: Record<string, string | RegExp | number>,\n options?: { exact?: boolean }\n ) => SmartRow;\n\n /**\n * Gets a row by 1-based index on the current page.\n * Throws error if table is not initialized.\n * @param index 1-based row index\n * @param options Optional settings including bringIntoView\n */\n getRowByIndex: (\n index: number,\n options?: { bringIntoView?: boolean }\n ) => SmartRow;\n\n /**\n * ASYNC: Searches for a single row across pages using pagination.\n * Auto-initializes the table if not already initialized.\n * @param filters - The filter criteria to match\n * @param options - Search options including exact match and max pages\n */\n findRow: (\n filters: Record<string, string | RegExp | number>,\n options?: { exact?: boolean, maxPages?: number }\n ) => Promise<SmartRow>;\n\n /**\n * ASYNC: Searches for all matching rows across pages using pagination.\n * Auto-initializes the table if not already initialized.\n * @param filters - The filter criteria to match\n * @param options - Search options including exact match, max pages, and asJSON\n */\n findRows: <R extends { asJSON?: boolean }>(\n filters: Record<string, string | RegExp | number>,\n options?: { exact?: boolean, maxPages?: number } & R\n ) => Promise<R['asJSON'] extends true ? Record<string, string>[] : SmartRow[]>;\n\n /**\n * Navigates to a specific column using the configured CellNavigationStrategy.\n */\n scrollToColumn: (columnName: string) => Promise<void>;\n\n /**\n * Gets all rows on the current page only (does not paginate).\n * Auto-initializes the table if not already initialized.\n * Returns a SmartRowArray which extends Array with a toJSON() helper method.\n * @param options - Filter options\n */\n getRows: (options?: { filter?: Record<string, any>, exact?: boolean }) => Promise<SmartRowArray>;\n\n /**\n * Resets the table state (clears cache, flags) and invokes the onReset strategy.\n */\n reset: () => Promise<void>;\n\n /**\n * Revalidates the table's structure (headers, columns) without resetting pagination or state.\n * Useful when columns change visibility or order dynamically.\n */\n revalidate: () => 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: SmartRowArray;\n allData: T[];\n table: RestrictedTableResult;\n batchInfo?: {\n startIndex: number;\n endIndex: number;\n size: number;\n };\n\n }) => T | T[] | Promise<T | T[]>,\n options?: {\n pagination?: PaginationStrategy;\n dedupeStrategy?: DedupeStrategy;\n maxIterations?: number;\n batchSize?: number;\n getIsFirst?: (context: { index: number }) => boolean;\n getIsLast?: (context: { index: number, paginationResult: boolean }) => boolean;\n beforeFirst?: (context: { index: number, rows: SmartRow[], allData: any[] }) => void | Promise<void>;\n afterLast?: (context: { index: number, rows: SmartRow[], allData: any[] }) => void | Promise<void>;\n /**\n * If true, flattens array results from callback into the main data array.\n * If false (default), pushes the return value as-is (preserves batching/arrays).\n */\n autoFlatten?: boolean;\n }\n ) => Promise<T[]>;\n\n /**\n * Generate an AI-friendly configuration prompt for debugging.\n * Outputs table HTML and TypeScript definitions to help AI assistants generate config.\n */\n generateConfigPrompt: (options?: PromptOptions) => Promise<void>;\n}\n\n/**\n * Restricted table result that excludes methods that shouldn't be called during iteration.\n */\nexport type RestrictedTableResult<T = any> = Omit<TableResult<T>, 'searchForRow' | 'iterateThroughTable' | 'reset'>;\n";
|
package/dist/typeContext.js
CHANGED
|
@@ -210,6 +210,14 @@ export interface FilterStrategy {
|
|
|
210
210
|
}): Locator;
|
|
211
211
|
}
|
|
212
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
|
+
|
|
213
221
|
/**
|
|
214
222
|
* Organized container for all table interaction strategies.
|
|
215
223
|
*/
|
|
@@ -224,10 +232,20 @@ export interface TableStrategies {
|
|
|
224
232
|
pagination?: PaginationStrategy;
|
|
225
233
|
/** Strategy for sorting columns */
|
|
226
234
|
sorting?: SortingStrategy;
|
|
235
|
+
/** Strategy for deduplicating rows during iteration/scrolling */
|
|
236
|
+
dedupe?: DedupeStrategy;
|
|
227
237
|
/** Function to get a cell locator */
|
|
228
238
|
getCellLocator?: GetCellLocatorFn;
|
|
229
239
|
/** Function to get the currently active/focused cell */
|
|
230
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;
|
|
231
249
|
}
|
|
232
250
|
|
|
233
251
|
/**
|
|
@@ -243,7 +261,7 @@ export interface TableConfig {
|
|
|
243
261
|
/** Number of pages to scan for verification */
|
|
244
262
|
maxPages?: number;
|
|
245
263
|
/** Hook to rename columns dynamically */
|
|
246
|
-
headerTransformer?: (args: { text: string, index: number, locator: Locator }) => string | Promise<string>;
|
|
264
|
+
headerTransformer?: (args: { text: string, index: number, locator: Locator, seenHeaders: Set<string> }) => string | Promise<string>;
|
|
247
265
|
/** Automatically scroll to table on init */
|
|
248
266
|
autoScroll?: boolean;
|
|
249
267
|
/** Debug options for development and troubleshooting */
|
|
@@ -261,7 +279,7 @@ export interface FinalTableConfig extends TableConfig {
|
|
|
261
279
|
maxPages: number;
|
|
262
280
|
autoScroll: boolean;
|
|
263
281
|
debug?: TableConfig['debug'];
|
|
264
|
-
headerTransformer: (args: { text: string, index: number, locator: Locator }) => string | Promise<string>;
|
|
282
|
+
headerTransformer: (args: { text: string, index: number, locator: Locator, seenHeaders: Set<string> }) => string | Promise<string>;
|
|
265
283
|
onReset: (context: TableContext) => Promise<void>;
|
|
266
284
|
strategies: TableStrategies;
|
|
267
285
|
}
|
|
@@ -406,7 +424,7 @@ export interface TableResult<T = any> {
|
|
|
406
424
|
index: number;
|
|
407
425
|
isFirst: boolean;
|
|
408
426
|
isLast: boolean;
|
|
409
|
-
rows:
|
|
427
|
+
rows: SmartRowArray;
|
|
410
428
|
allData: T[];
|
|
411
429
|
table: RestrictedTableResult;
|
|
412
430
|
batchInfo?: {
|
|
@@ -414,7 +432,8 @@ export interface TableResult<T = any> {
|
|
|
414
432
|
endIndex: number;
|
|
415
433
|
size: number;
|
|
416
434
|
};
|
|
417
|
-
|
|
435
|
+
|
|
436
|
+
}) => T | T[] | Promise<T | T[]>,
|
|
418
437
|
options?: {
|
|
419
438
|
pagination?: PaginationStrategy;
|
|
420
439
|
dedupeStrategy?: DedupeStrategy;
|
|
@@ -424,6 +443,11 @@ export interface TableResult<T = any> {
|
|
|
424
443
|
getIsLast?: (context: { index: number, paginationResult: boolean }) => boolean;
|
|
425
444
|
beforeFirst?: (context: { index: number, rows: SmartRow[], allData: any[] }) => void | Promise<void>;
|
|
426
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;
|
|
427
451
|
}
|
|
428
452
|
) => Promise<T[]>;
|
|
429
453
|
|
package/dist/types.d.ts
CHANGED
|
@@ -192,6 +192,13 @@ export interface FilterStrategy {
|
|
|
192
192
|
tableContext: TableContext;
|
|
193
193
|
}): Locator;
|
|
194
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Strategy to check if the table or rows are loading.
|
|
197
|
+
*/
|
|
198
|
+
export interface LoadingStrategy {
|
|
199
|
+
isTableLoading?: (context: TableContext) => Promise<boolean>;
|
|
200
|
+
isRowLoading?: (row: SmartRow) => Promise<boolean>;
|
|
201
|
+
}
|
|
195
202
|
/**
|
|
196
203
|
* Organized container for all table interaction strategies.
|
|
197
204
|
*/
|
|
@@ -206,10 +213,27 @@ export interface TableStrategies {
|
|
|
206
213
|
pagination?: PaginationStrategy;
|
|
207
214
|
/** Strategy for sorting columns */
|
|
208
215
|
sorting?: SortingStrategy;
|
|
216
|
+
/** Strategy for deduplicating rows during iteration/scrolling */
|
|
217
|
+
dedupe?: DedupeStrategy;
|
|
209
218
|
/** Function to get a cell locator */
|
|
210
219
|
getCellLocator?: GetCellLocatorFn;
|
|
211
220
|
/** Function to get the currently active/focused cell */
|
|
212
221
|
getActiveCell?: GetActiveCellFn;
|
|
222
|
+
/** Custom helper to check if a table is fully loaded/ready */
|
|
223
|
+
isTableLoaded?: (args: TableContext) => Promise<boolean>;
|
|
224
|
+
/** Custom helper to check if a row is fully loaded/ready */
|
|
225
|
+
isRowLoaded?: (args: {
|
|
226
|
+
row: Locator;
|
|
227
|
+
index: number;
|
|
228
|
+
}) => Promise<boolean>;
|
|
229
|
+
/** Custom helper to check if a cell is fully loaded/ready (e.g. for editing) */
|
|
230
|
+
isCellLoaded?: (args: {
|
|
231
|
+
cell: Locator;
|
|
232
|
+
column: string;
|
|
233
|
+
row: Locator;
|
|
234
|
+
}) => Promise<boolean>;
|
|
235
|
+
/** Strategy for detecting loading states */
|
|
236
|
+
loading?: LoadingStrategy;
|
|
213
237
|
}
|
|
214
238
|
/**
|
|
215
239
|
* Configuration options for useTable.
|
|
@@ -228,6 +252,7 @@ export interface TableConfig {
|
|
|
228
252
|
text: string;
|
|
229
253
|
index: number;
|
|
230
254
|
locator: Locator;
|
|
255
|
+
seenHeaders: Set<string>;
|
|
231
256
|
}) => string | Promise<string>;
|
|
232
257
|
/** Automatically scroll to table on init */
|
|
233
258
|
autoScroll?: boolean;
|
|
@@ -249,6 +274,7 @@ export interface FinalTableConfig extends TableConfig {
|
|
|
249
274
|
text: string;
|
|
250
275
|
index: number;
|
|
251
276
|
locator: Locator;
|
|
277
|
+
seenHeaders: Set<string>;
|
|
252
278
|
}) => string | Promise<string>;
|
|
253
279
|
onReset: (context: TableContext) => Promise<void>;
|
|
254
280
|
strategies: TableStrategies;
|
|
@@ -384,7 +410,7 @@ export interface TableResult<T = any> {
|
|
|
384
410
|
index: number;
|
|
385
411
|
isFirst: boolean;
|
|
386
412
|
isLast: boolean;
|
|
387
|
-
rows:
|
|
413
|
+
rows: SmartRowArray;
|
|
388
414
|
allData: T[];
|
|
389
415
|
table: RestrictedTableResult;
|
|
390
416
|
batchInfo?: {
|
|
@@ -392,7 +418,7 @@ export interface TableResult<T = any> {
|
|
|
392
418
|
endIndex: number;
|
|
393
419
|
size: number;
|
|
394
420
|
};
|
|
395
|
-
}) => T | Promise<T>, options?: {
|
|
421
|
+
}) => T | T[] | Promise<T | T[]>, options?: {
|
|
396
422
|
pagination?: PaginationStrategy;
|
|
397
423
|
dedupeStrategy?: DedupeStrategy;
|
|
398
424
|
maxIterations?: number;
|
|
@@ -414,6 +440,11 @@ export interface TableResult<T = any> {
|
|
|
414
440
|
rows: SmartRow[];
|
|
415
441
|
allData: any[];
|
|
416
442
|
}) => void | Promise<void>;
|
|
443
|
+
/**
|
|
444
|
+
* If true, flattens array results from callback into the main data array.
|
|
445
|
+
* If false (default), pushes the return value as-is (preserves batching/arrays).
|
|
446
|
+
*/
|
|
447
|
+
autoFlatten?: boolean;
|
|
417
448
|
}) => Promise<T[]>;
|
|
418
449
|
/**
|
|
419
450
|
* Generate an AI-friendly configuration prompt for debugging.
|
package/dist/useTable.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Locator } from '@playwright/test';
|
|
2
|
-
import { TableConfig, Selector, TableResult, PaginationStrategy } from './types';
|
|
2
|
+
import { TableConfig, TableContext, Selector, TableResult, SmartRow as SmartRowType, DedupeStrategy, PaginationStrategy } from './types';
|
|
3
3
|
import { FillStrategies } from './strategies/fill';
|
|
4
4
|
import { HeaderStrategies } from './strategies/headers';
|
|
5
5
|
import { CellNavigationStrategies } from './strategies/columns';
|
|
@@ -10,10 +10,35 @@ import { Strategies } from './strategies';
|
|
|
10
10
|
*/
|
|
11
11
|
export declare const useTable: <T = any>(rootLocator: Locator, configOptions?: TableConfig) => TableResult<T>;
|
|
12
12
|
export declare const PaginationStrategies: {
|
|
13
|
-
clickNext: (nextButtonSelector: Selector,
|
|
14
|
-
|
|
13
|
+
clickNext: (nextButtonSelector: Selector, options?: {
|
|
14
|
+
stabilization?: import("./strategies/stabilization").StabilizationStrategy;
|
|
15
|
+
timeout?: number;
|
|
16
|
+
}) => PaginationStrategy;
|
|
17
|
+
infiniteScroll: (options?: {
|
|
18
|
+
action?: "scroll" | "js-scroll";
|
|
19
|
+
scrollTarget?: Selector;
|
|
20
|
+
scrollAmount?: number;
|
|
21
|
+
stabilization?: import("./strategies/stabilization").StabilizationStrategy;
|
|
22
|
+
timeout?: number;
|
|
23
|
+
}) => PaginationStrategy;
|
|
24
|
+
};
|
|
25
|
+
export declare const LoadingStrategies: {
|
|
26
|
+
Table: {
|
|
27
|
+
hasSpinner: (selector?: string) => ({ root }: TableContext) => Promise<boolean>;
|
|
28
|
+
custom: (fn: (context: TableContext) => Promise<boolean>) => (context: TableContext) => Promise<boolean>;
|
|
29
|
+
never: () => Promise<boolean>;
|
|
30
|
+
};
|
|
31
|
+
Row: {
|
|
32
|
+
hasClass: (className?: string) => (row: SmartRowType) => Promise<boolean>;
|
|
33
|
+
hasText: (text?: string | RegExp) => (row: SmartRowType) => Promise<boolean>;
|
|
34
|
+
hasEmptyCells: () => (row: SmartRowType) => Promise<boolean>;
|
|
35
|
+
never: () => Promise<boolean>;
|
|
36
|
+
};
|
|
15
37
|
};
|
|
16
38
|
export declare const SortingStrategies: {
|
|
17
39
|
AriaSort: () => import("./types").SortingStrategy;
|
|
18
40
|
};
|
|
41
|
+
export declare const DedupeStrategies: {
|
|
42
|
+
byTopPosition: (tolerance?: number) => DedupeStrategy;
|
|
43
|
+
};
|
|
19
44
|
export { FillStrategies, HeaderStrategies, CellNavigationStrategies, ResolutionStrategies, Strategies };
|