@rickcedwhat/playwright-smart-table 6.1.1 → 6.3.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 +4 -2
- package/dist/engine/rowFinder.d.ts +27 -0
- package/dist/engine/rowFinder.js +193 -0
- package/dist/engine/tableMapper.d.ts +16 -0
- package/dist/engine/tableMapper.js +136 -0
- package/dist/filterEngine.d.ts +2 -2
- package/dist/filterEngine.js +15 -4
- package/dist/smartRow.d.ts +1 -1
- package/dist/smartRow.js +57 -36
- package/dist/strategies/index.d.ts +4 -0
- package/dist/strategies/loading.d.ts +14 -0
- package/dist/strategies/loading.js +31 -0
- package/dist/typeContext.d.ts +1 -1
- package/dist/typeContext.js +38 -14
- package/dist/types.d.ts +34 -14
- package/dist/useTable.d.ts +5 -1
- package/dist/useTable.js +45 -242
- package/dist/utils/stringUtils.js +12 -3
- package/package.json +10 -5
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 * 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";
|
|
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 * Value used to filter rows.\n * - string/number/RegExp: filter by text content of the cell.\n * - function: filter by custom locator logic within the cell.\n * @example\n * // Text filter\n * { Name: 'John' }\n * \n * // Custom locator filter (e.g. checkbox is checked)\n * { Status: (cell) => cell.locator('input:checked') }\n */\nexport type FilterValue = string | RegExp | number | ((cell: Locator) => 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<T = any> {\n root: Locator;\n config: FinalTableConfig<T>;\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: FilterValue };\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 isHeaderLoading?: (context: TableContext) => 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 */\n/**\n * Configuration options for useTable.\n */\nexport interface TableConfig<T = any> {\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 * Custom data mappers for specific columns.\n * Allows extracting complex data types (boolean, number) instead of just string.\n */\n dataMapper?: Partial<Record<keyof T, (cell: Locator) => Promise<T[keyof T]> | T[keyof T]>>;\n}\n\nexport interface FinalTableConfigLike<T = any> extends TableConfig<T> {\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// Alias for backward compatibility if needed, or update usages\nexport type FinalTableConfig<T = any> = FinalTableConfigLike<T>;\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, FilterValue>,\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, FilterValue>,\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 and max pages\n */\n findRows: (\n filters: Record<string, FilterValue>,\n options?: { exact?: boolean, maxPages?: number }\n ) => Promise<SmartRowArray<T>>;\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: SmartRowArray, allData: any[] }) => void | Promise<void>;\n afterLast?: (context: { index: number, rows: SmartRowArray, 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
|
@@ -18,6 +18,19 @@ exports.TYPE_CONTEXT = `
|
|
|
18
18
|
*/
|
|
19
19
|
export type Selector = string | ((root: Locator | Page) => Locator);
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Value used to filter rows.
|
|
23
|
+
* - string/number/RegExp: filter by text content of the cell.
|
|
24
|
+
* - function: filter by custom locator logic within the cell.
|
|
25
|
+
* @example
|
|
26
|
+
* // Text filter
|
|
27
|
+
* { Name: 'John' }
|
|
28
|
+
*
|
|
29
|
+
* // Custom locator filter (e.g. checkbox is checked)
|
|
30
|
+
* { Status: (cell) => cell.locator('input:checked') }
|
|
31
|
+
*/
|
|
32
|
+
export type FilterValue = string | RegExp | number | ((cell: Locator) => Locator);
|
|
33
|
+
|
|
21
34
|
/**
|
|
22
35
|
* Function to get a cell locator given row, column info.
|
|
23
36
|
* Replaces the old cellResolver.
|
|
@@ -158,9 +171,9 @@ export type DebugConfig = {
|
|
|
158
171
|
logLevel?: 'verbose' | 'info' | 'error' | 'none';
|
|
159
172
|
};
|
|
160
173
|
|
|
161
|
-
export interface TableContext {
|
|
174
|
+
export interface TableContext<T = any> {
|
|
162
175
|
root: Locator;
|
|
163
|
-
config: FinalTableConfig
|
|
176
|
+
config: FinalTableConfig<T>;
|
|
164
177
|
page: Page;
|
|
165
178
|
resolve: (selector: Selector, parent: Locator | Page) => Locator;
|
|
166
179
|
}
|
|
@@ -204,7 +217,7 @@ export type { ColumnResolutionStrategy } from './strategies/resolution';
|
|
|
204
217
|
export interface FilterStrategy {
|
|
205
218
|
apply(options: {
|
|
206
219
|
rows: Locator;
|
|
207
|
-
filter: { column: string, value:
|
|
220
|
+
filter: { column: string, value: FilterValue };
|
|
208
221
|
colIndex: number;
|
|
209
222
|
tableContext: TableContext;
|
|
210
223
|
}): Locator;
|
|
@@ -216,6 +229,7 @@ export interface FilterStrategy {
|
|
|
216
229
|
export interface LoadingStrategy {
|
|
217
230
|
isTableLoading?: (context: TableContext) => Promise<boolean>;
|
|
218
231
|
isRowLoading?: (row: SmartRow) => Promise<boolean>;
|
|
232
|
+
isHeaderLoading?: (context: TableContext) => Promise<boolean>;
|
|
219
233
|
}
|
|
220
234
|
|
|
221
235
|
/**
|
|
@@ -251,7 +265,10 @@ export interface TableStrategies {
|
|
|
251
265
|
/**
|
|
252
266
|
* Configuration options for useTable.
|
|
253
267
|
*/
|
|
254
|
-
|
|
268
|
+
/**
|
|
269
|
+
* Configuration options for useTable.
|
|
270
|
+
*/
|
|
271
|
+
export interface TableConfig<T = any> {
|
|
255
272
|
/** Selector for the table headers */
|
|
256
273
|
headerSelector?: string;
|
|
257
274
|
/** Selector for the table rows */
|
|
@@ -270,9 +287,14 @@ export interface TableConfig {
|
|
|
270
287
|
onReset?: (context: TableContext) => Promise<void>;
|
|
271
288
|
/** All interaction strategies */
|
|
272
289
|
strategies?: TableStrategies;
|
|
290
|
+
/**
|
|
291
|
+
* Custom data mappers for specific columns.
|
|
292
|
+
* Allows extracting complex data types (boolean, number) instead of just string.
|
|
293
|
+
*/
|
|
294
|
+
dataMapper?: Partial<Record<keyof T, (cell: Locator) => Promise<T[keyof T]> | T[keyof T]>>;
|
|
273
295
|
}
|
|
274
296
|
|
|
275
|
-
export interface
|
|
297
|
+
export interface FinalTableConfigLike<T = any> extends TableConfig<T> {
|
|
276
298
|
headerSelector: string;
|
|
277
299
|
rowSelector: string;
|
|
278
300
|
cellSelector: string;
|
|
@@ -283,6 +305,8 @@ export interface FinalTableConfig extends TableConfig {
|
|
|
283
305
|
onReset: (context: TableContext) => Promise<void>;
|
|
284
306
|
strategies: TableStrategies;
|
|
285
307
|
}
|
|
308
|
+
// Alias for backward compatibility if needed, or update usages
|
|
309
|
+
export type FinalTableConfig<T = any> = FinalTableConfigLike<T>;
|
|
286
310
|
|
|
287
311
|
|
|
288
312
|
export interface FillOptions {
|
|
@@ -331,7 +355,7 @@ export interface TableResult<T = any> {
|
|
|
331
355
|
* Throws error if table is not initialized.
|
|
332
356
|
*/
|
|
333
357
|
getRow: (
|
|
334
|
-
filters: Record<string,
|
|
358
|
+
filters: Record<string, FilterValue>,
|
|
335
359
|
options?: { exact?: boolean }
|
|
336
360
|
) => SmartRow;
|
|
337
361
|
|
|
@@ -353,7 +377,7 @@ export interface TableResult<T = any> {
|
|
|
353
377
|
* @param options - Search options including exact match and max pages
|
|
354
378
|
*/
|
|
355
379
|
findRow: (
|
|
356
|
-
filters: Record<string,
|
|
380
|
+
filters: Record<string, FilterValue>,
|
|
357
381
|
options?: { exact?: boolean, maxPages?: number }
|
|
358
382
|
) => Promise<SmartRow>;
|
|
359
383
|
|
|
@@ -361,12 +385,12 @@ export interface TableResult<T = any> {
|
|
|
361
385
|
* ASYNC: Searches for all matching rows across pages using pagination.
|
|
362
386
|
* Auto-initializes the table if not already initialized.
|
|
363
387
|
* @param filters - The filter criteria to match
|
|
364
|
-
* @param options - Search options including exact match
|
|
388
|
+
* @param options - Search options including exact match and max pages
|
|
365
389
|
*/
|
|
366
|
-
findRows:
|
|
367
|
-
filters: Record<string,
|
|
368
|
-
options?: { exact?: boolean, maxPages?: number }
|
|
369
|
-
) => Promise<
|
|
390
|
+
findRows: (
|
|
391
|
+
filters: Record<string, FilterValue>,
|
|
392
|
+
options?: { exact?: boolean, maxPages?: number }
|
|
393
|
+
) => Promise<SmartRowArray<T>>;
|
|
370
394
|
|
|
371
395
|
/**
|
|
372
396
|
* Navigates to a specific column using the configured CellNavigationStrategy.
|
|
@@ -441,8 +465,8 @@ export interface TableResult<T = any> {
|
|
|
441
465
|
batchSize?: number;
|
|
442
466
|
getIsFirst?: (context: { index: number }) => boolean;
|
|
443
467
|
getIsLast?: (context: { index: number, paginationResult: boolean }) => boolean;
|
|
444
|
-
beforeFirst?: (context: { index: number, rows:
|
|
445
|
-
afterLast?: (context: { index: number, rows:
|
|
468
|
+
beforeFirst?: (context: { index: number, rows: SmartRowArray, allData: any[] }) => void | Promise<void>;
|
|
469
|
+
afterLast?: (context: { index: number, rows: SmartRowArray, allData: any[] }) => void | Promise<void>;
|
|
446
470
|
/**
|
|
447
471
|
* If true, flattens array results from callback into the main data array.
|
|
448
472
|
* If false (default), pushes the return value as-is (preserves batching/arrays).
|
package/dist/types.d.ts
CHANGED
|
@@ -10,6 +10,18 @@ import type { SmartRowArray } from './utils/smartRowArray';
|
|
|
10
10
|
* rowSelector: (root) => root.locator('[role="row"]')
|
|
11
11
|
*/
|
|
12
12
|
export type Selector = string | ((root: Locator | Page) => Locator);
|
|
13
|
+
/**
|
|
14
|
+
* Value used to filter rows.
|
|
15
|
+
* - string/number/RegExp: filter by text content of the cell.
|
|
16
|
+
* - function: filter by custom locator logic within the cell.
|
|
17
|
+
* @example
|
|
18
|
+
* // Text filter
|
|
19
|
+
* { Name: 'John' }
|
|
20
|
+
*
|
|
21
|
+
* // Custom locator filter (e.g. checkbox is checked)
|
|
22
|
+
* { Status: (cell) => cell.locator('input:checked') }
|
|
23
|
+
*/
|
|
24
|
+
export type FilterValue = string | RegExp | number | ((cell: Locator) => Locator);
|
|
13
25
|
/**
|
|
14
26
|
* Function to get a cell locator given row, column info.
|
|
15
27
|
* Replaces the old cellResolver.
|
|
@@ -143,9 +155,9 @@ export type DebugConfig = {
|
|
|
143
155
|
*/
|
|
144
156
|
logLevel?: 'verbose' | 'info' | 'error' | 'none';
|
|
145
157
|
};
|
|
146
|
-
export interface TableContext {
|
|
158
|
+
export interface TableContext<T = any> {
|
|
147
159
|
root: Locator;
|
|
148
|
-
config: FinalTableConfig
|
|
160
|
+
config: FinalTableConfig<T>;
|
|
149
161
|
page: Page;
|
|
150
162
|
resolve: (selector: Selector, parent: Locator | Page) => Locator;
|
|
151
163
|
}
|
|
@@ -186,7 +198,7 @@ export interface FilterStrategy {
|
|
|
186
198
|
rows: Locator;
|
|
187
199
|
filter: {
|
|
188
200
|
column: string;
|
|
189
|
-
value:
|
|
201
|
+
value: FilterValue;
|
|
190
202
|
};
|
|
191
203
|
colIndex: number;
|
|
192
204
|
tableContext: TableContext;
|
|
@@ -198,6 +210,7 @@ export interface FilterStrategy {
|
|
|
198
210
|
export interface LoadingStrategy {
|
|
199
211
|
isTableLoading?: (context: TableContext) => Promise<boolean>;
|
|
200
212
|
isRowLoading?: (row: SmartRow) => Promise<boolean>;
|
|
213
|
+
isHeaderLoading?: (context: TableContext) => Promise<boolean>;
|
|
201
214
|
}
|
|
202
215
|
/**
|
|
203
216
|
* Organized container for all table interaction strategies.
|
|
@@ -238,7 +251,10 @@ export interface TableStrategies {
|
|
|
238
251
|
/**
|
|
239
252
|
* Configuration options for useTable.
|
|
240
253
|
*/
|
|
241
|
-
|
|
254
|
+
/**
|
|
255
|
+
* Configuration options for useTable.
|
|
256
|
+
*/
|
|
257
|
+
export interface TableConfig<T = any> {
|
|
242
258
|
/** Selector for the table headers */
|
|
243
259
|
headerSelector?: string;
|
|
244
260
|
/** Selector for the table rows */
|
|
@@ -262,8 +278,13 @@ export interface TableConfig {
|
|
|
262
278
|
onReset?: (context: TableContext) => Promise<void>;
|
|
263
279
|
/** All interaction strategies */
|
|
264
280
|
strategies?: TableStrategies;
|
|
281
|
+
/**
|
|
282
|
+
* Custom data mappers for specific columns.
|
|
283
|
+
* Allows extracting complex data types (boolean, number) instead of just string.
|
|
284
|
+
*/
|
|
285
|
+
dataMapper?: Partial<Record<keyof T, (cell: Locator) => Promise<T[keyof T]> | T[keyof T]>>;
|
|
265
286
|
}
|
|
266
|
-
export interface
|
|
287
|
+
export interface FinalTableConfigLike<T = any> extends TableConfig<T> {
|
|
267
288
|
headerSelector: string;
|
|
268
289
|
rowSelector: string;
|
|
269
290
|
cellSelector: string;
|
|
@@ -279,6 +300,7 @@ export interface FinalTableConfig extends TableConfig {
|
|
|
279
300
|
onReset: (context: TableContext) => Promise<void>;
|
|
280
301
|
strategies: TableStrategies;
|
|
281
302
|
}
|
|
303
|
+
export type FinalTableConfig<T = any> = FinalTableConfigLike<T>;
|
|
282
304
|
export interface FillOptions {
|
|
283
305
|
/**
|
|
284
306
|
* Custom input mappers for specific columns.
|
|
@@ -321,7 +343,7 @@ export interface TableResult<T = any> {
|
|
|
321
343
|
* Finds a row by filters on the current page only. Returns immediately (sync).
|
|
322
344
|
* Throws error if table is not initialized.
|
|
323
345
|
*/
|
|
324
|
-
getRow: (filters: Record<string,
|
|
346
|
+
getRow: (filters: Record<string, FilterValue>, options?: {
|
|
325
347
|
exact?: boolean;
|
|
326
348
|
}) => SmartRow;
|
|
327
349
|
/**
|
|
@@ -339,7 +361,7 @@ export interface TableResult<T = any> {
|
|
|
339
361
|
* @param filters - The filter criteria to match
|
|
340
362
|
* @param options - Search options including exact match and max pages
|
|
341
363
|
*/
|
|
342
|
-
findRow: (filters: Record<string,
|
|
364
|
+
findRow: (filters: Record<string, FilterValue>, options?: {
|
|
343
365
|
exact?: boolean;
|
|
344
366
|
maxPages?: number;
|
|
345
367
|
}) => Promise<SmartRow>;
|
|
@@ -347,14 +369,12 @@ export interface TableResult<T = any> {
|
|
|
347
369
|
* ASYNC: Searches for all matching rows across pages using pagination.
|
|
348
370
|
* Auto-initializes the table if not already initialized.
|
|
349
371
|
* @param filters - The filter criteria to match
|
|
350
|
-
* @param options - Search options including exact match
|
|
372
|
+
* @param options - Search options including exact match and max pages
|
|
351
373
|
*/
|
|
352
|
-
findRows: <
|
|
353
|
-
asJSON?: boolean;
|
|
354
|
-
}>(filters: Record<string, string | RegExp | number>, options?: {
|
|
374
|
+
findRows: (filters: Record<string, FilterValue>, options?: {
|
|
355
375
|
exact?: boolean;
|
|
356
376
|
maxPages?: number;
|
|
357
|
-
}
|
|
377
|
+
}) => Promise<SmartRowArray<T>>;
|
|
358
378
|
/**
|
|
359
379
|
* Navigates to a specific column using the configured CellNavigationStrategy.
|
|
360
380
|
*/
|
|
@@ -432,12 +452,12 @@ export interface TableResult<T = any> {
|
|
|
432
452
|
}) => boolean;
|
|
433
453
|
beforeFirst?: (context: {
|
|
434
454
|
index: number;
|
|
435
|
-
rows:
|
|
455
|
+
rows: SmartRowArray;
|
|
436
456
|
allData: any[];
|
|
437
457
|
}) => void | Promise<void>;
|
|
438
458
|
afterLast?: (context: {
|
|
439
459
|
index: number;
|
|
440
|
-
rows:
|
|
460
|
+
rows: SmartRowArray;
|
|
441
461
|
allData: any[];
|
|
442
462
|
}) => void | Promise<void>;
|
|
443
463
|
/**
|
package/dist/useTable.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { Strategies } from './strategies';
|
|
|
8
8
|
/**
|
|
9
9
|
* Main hook to interact with a table.
|
|
10
10
|
*/
|
|
11
|
-
export declare const useTable: <T = any>(rootLocator: Locator, configOptions?: TableConfig) => TableResult<T>;
|
|
11
|
+
export declare const useTable: <T = any>(rootLocator: Locator, configOptions?: TableConfig<T>) => TableResult<T>;
|
|
12
12
|
export declare const PaginationStrategies: {
|
|
13
13
|
clickNext: (nextButtonSelector: Selector, options?: {
|
|
14
14
|
stabilization?: import("./strategies/stabilization").StabilizationStrategy;
|
|
@@ -34,6 +34,10 @@ export declare const LoadingStrategies: {
|
|
|
34
34
|
hasEmptyCells: () => (row: SmartRowType) => Promise<boolean>;
|
|
35
35
|
never: () => Promise<boolean>;
|
|
36
36
|
};
|
|
37
|
+
Headers: {
|
|
38
|
+
stable: (duration?: number) => (context: TableContext) => Promise<boolean>;
|
|
39
|
+
never: () => Promise<boolean>;
|
|
40
|
+
};
|
|
37
41
|
};
|
|
38
42
|
export declare const SortingStrategies: {
|
|
39
43
|
AriaSort: () => import("./types").SortingStrategy;
|