@rickcedwhat/playwright-smart-table 3.1.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,16 +9,51 @@ exports.TYPE_CONTEXT = void 0;
9
9
  exports.TYPE_CONTEXT = `
10
10
  export type Selector = string | ((root: Locator | Page) => Locator);
11
11
 
12
- export type SmartRow = Locator & {
12
+ /**
13
+ * Function to get a cell locator given row, column info.
14
+ * Replaces the old cellResolver.
15
+ */
16
+ export type GetCellLocatorFn = (args: {
17
+ row: Locator;
18
+ columnName: string;
19
+ columnIndex: number;
20
+ rowIndex?: number;
21
+ page: Page;
22
+ }) => Locator;
23
+
24
+ /**
25
+ * Function to get the currently active/focused cell.
26
+ * Returns null if no cell is active.
27
+ */
28
+ export type GetActiveCellFn = (args: TableContext) => Promise<{
29
+ rowIndex: number;
30
+ columnIndex: number;
31
+ columnName?: string;
32
+ locator: Locator;
33
+ } | null>;
34
+
35
+
36
+ export type SmartRow<T = any> = Locator & {
37
+ getRequestIndex(): number | undefined;
38
+ rowIndex?: number;
13
39
  getCell(column: string): Locator;
14
- toJSON(): Promise<Record<string, string>>;
40
+ toJSON(options?: { columns?: string[] }): Promise<T>;
15
41
  /**
16
- * Fills the row with data. Automatically detects input types (text input, select, checkbox, etc.).
42
+ * Scrolls/paginates to bring this row into view.
43
+ * Only works if rowIndex is known.
17
44
  */
18
- smartFill: (data: Record<string, any>, options?: FillOptions) => Promise<void>;
45
+ bringIntoView(): Promise<void>;
46
+ /**
47
+ * Fills the row with data. Automatically detects input types.
48
+ */
49
+ fill: (data: Partial<T> | Record<string, any>, options?: FillOptions) => Promise<void>;
50
+ /**
51
+ * Alias for fill() to avoid conflict with Locator.fill()
52
+ */
53
+ smartFill: (data: Partial<T> | Record<string, any>, options?: FillOptions) => Promise<void>;
19
54
  };
20
55
 
21
- export type StrategyContext = TableContext;
56
+ export type StrategyContext = TableContext & { rowLocator?: Locator; rowIndex?: number };
22
57
 
23
58
  /**
24
59
  * Defines the contract for a sorting strategy.
@@ -63,50 +98,103 @@ export interface PromptOptions {
63
98
  includeTypes?: boolean;
64
99
  }
65
100
 
66
- export interface TableConfig {
67
- rowSelector?: Selector;
68
- headerSelector?: Selector;
69
- cellSelector?: Selector;
101
+ export type FillStrategy = (options: {
102
+ row: SmartRow;
103
+ columnName: string;
104
+ value: any;
105
+ index: number;
106
+ page: Page;
107
+ rootLocator: Locator;
108
+ table: TableResult; // The parent table instance
109
+ fillOptions?: FillOptions;
110
+ }) => Promise<void>;
111
+
112
+ export type { HeaderStrategy } from './strategies/headers';
113
+ export type { CellNavigationStrategy } from './strategies/columns';
114
+
115
+ /**
116
+ * Strategy to resolve column names (string or regex) to their index.
117
+ */
118
+ export type { ColumnResolutionStrategy } from './strategies/resolution';
119
+
120
+ /**
121
+ * Strategy to filter rows based on criteria.
122
+ */
123
+ export interface FilterStrategy {
124
+ apply(options: {
125
+ rows: Locator;
126
+ filter: { column: string, value: string | RegExp | number };
127
+ colIndex: number;
128
+ tableContext: TableContext;
129
+ }): Locator;
130
+ }
131
+
132
+ /**
133
+ * Organized container for all table interaction strategies.
134
+ */
135
+ export interface TableStrategies {
136
+ /** Strategy for discovering/scanning headers */
137
+ header?: HeaderStrategy;
138
+ /** Strategy for navigating to specific cells (row + column) */
139
+ cellNavigation?: CellNavigationStrategy;
140
+ /** Strategy for filling form inputs */
141
+ fill?: FillStrategy;
142
+ /** Strategy for paginating through data */
70
143
  pagination?: PaginationStrategy;
144
+ /** Strategy for sorting columns */
71
145
  sorting?: SortingStrategy;
146
+ /** Function to get a cell locator */
147
+ getCellLocator?: GetCellLocatorFn;
148
+ /** Function to get the currently active/focused cell */
149
+ getActiveCell?: GetActiveCellFn;
150
+ }
151
+
152
+ /**
153
+ * Configuration options for useTable.
154
+ */
155
+ export interface TableConfig {
156
+ /** Selector for the table headers */
157
+ headerSelector?: string;
158
+ /** Selector for the table rows */
159
+ rowSelector?: string;
160
+ /** Selector for the cells within a row */
161
+ cellSelector?: string;
162
+ /** Number of pages to scan for verification */
72
163
  maxPages?: number;
73
- /**
74
- * Hook to rename columns dynamically.
75
- * * @param args.text - The default innerText of the header.
76
- * @param args.index - The column index.
77
- * @param args.locator - The specific header cell locator.
78
- */
164
+ /** Hook to rename columns dynamically */
79
165
  headerTransformer?: (args: { text: string, index: number, locator: Locator }) => string | Promise<string>;
166
+ /** Automatically scroll to table on init */
80
167
  autoScroll?: boolean;
81
- /**
82
- * Enable debug mode to log internal state to console.
83
- */
168
+ /** Enable debug logs */
84
169
  debug?: boolean;
85
- /**
86
- * Strategy to reset the table to the initial page.
87
- * Called when table.reset() is invoked.
88
- */
170
+ /** Reset hook */
89
171
  onReset?: (context: TableContext) => Promise<void>;
172
+ /** All interaction strategies */
173
+ strategies?: TableStrategies;
174
+ }
175
+
176
+ export interface FinalTableConfig extends TableConfig {
177
+ headerSelector: string;
178
+ rowSelector: string;
179
+ cellSelector: string;
180
+ maxPages: number;
181
+ autoScroll: boolean;
182
+ debug: boolean;
183
+ headerTransformer: (args: { text: string, index: number, locator: Locator }) => string | Promise<string>;
184
+ onReset: (context: TableContext) => Promise<void>;
185
+ strategies: TableStrategies;
90
186
  }
91
187
 
92
- /**
93
- * Represents the final, resolved table configuration after default values have been applied.
94
- * All optional properties from TableConfig are now required, except for \`sorting\`.
95
- */
96
- export type FinalTableConfig = Required<Omit<TableConfig, 'sorting'>> & {
97
- sorting?: SortingStrategy;
98
- };
99
188
 
100
189
  export interface FillOptions {
101
190
  /**
102
191
  * Custom input mappers for specific columns.
103
192
  * Maps column names to functions that return the input locator for that cell.
104
- * Columns not specified here will use auto-detection.
105
193
  */
106
194
  inputMappers?: Record<string, (cell: Locator) => Locator>;
107
195
  }
108
196
 
109
- export interface TableResult {
197
+ export interface TableResult<T = any> {
110
198
  /**
111
199
  * Initializes the table by resolving headers. Must be called before using sync methods.
112
200
  * @param options Optional timeout for header resolution (default: 3000ms)
@@ -117,23 +205,46 @@ export interface TableResult {
117
205
  getHeaderCell: (columnName: string) => Promise<Locator>;
118
206
 
119
207
  /**
120
- * Finds a row on the current page only. Returns immediately (sync).
208
+ * Finds a row by filters on the current page only. Returns immediately (sync).
121
209
  * Throws error if table is not initialized.
122
210
  */
123
211
  getByRow: (
124
- filters: Record<string, string | RegExp | number>,
212
+ filters: Record<string, string | RegExp | number>,
125
213
  options?: { exact?: boolean }
126
214
  ) => SmartRow;
127
215
 
216
+ /**
217
+ * Gets a row by 1-based index on the current page.
218
+ * Throws error if table is not initialized.
219
+ * @param index 1-based row index
220
+ * @param options Optional settings including bringIntoView
221
+ */
222
+ getByRowIndex: (
223
+ index: number,
224
+ options?: { bringIntoView?: boolean }
225
+ ) => SmartRow;
226
+
128
227
  /**
129
228
  * Searches for a row across all available data using the configured strategy (pagination, scroll, etc.).
130
229
  * Auto-initializes if needed.
131
230
  */
132
231
  searchForRow: (
133
- filters: Record<string, string | RegExp | number>,
232
+ filters: Record<string, string | RegExp | number>,
134
233
  options?: { exact?: boolean, maxPages?: number }
135
234
  ) => Promise<SmartRow>;
136
235
 
236
+ /**
237
+ * Navigates to a specific column using the configured CellNavigationStrategy.
238
+ */
239
+ scrollToColumn: (columnName: string) => Promise<void>;
240
+
241
+ getAllCurrentRows: <T extends { asJSON?: boolean }>(
242
+ options?: { filter?: Record<string, any>, exact?: boolean } & T
243
+ ) => Promise<T['asJSON'] extends true ? Record<string, string>[] : SmartRow[]>;
244
+
245
+ /**
246
+ * @deprecated Use getAllCurrentRows instead. This method will be removed in a future major version.
247
+ */
137
248
  getAllRows: <T extends { asJSON?: boolean }>(
138
249
  options?: { filter?: Record<string, any>, exact?: boolean } & T
139
250
  ) => Promise<T['asJSON'] extends true ? Record<string, string>[] : SmartRow[]>;
@@ -146,6 +257,12 @@ export interface TableResult {
146
257
  */
147
258
  reset: () => Promise<void>;
148
259
 
260
+ /**
261
+ * Revalidates the table's structure (headers, columns) without resetting pagination or state.
262
+ * Useful when columns change visibility or order dynamically.
263
+ */
264
+ revalidate: () => Promise<void>;
265
+
149
266
  /**
150
267
  * Scans a specific column across all pages and returns the values.
151
268
  */
@@ -197,5 +314,5 @@ export interface TableResult {
197
314
  /**
198
315
  * Restricted table result that excludes methods that shouldn't be called during iteration.
199
316
  */
200
- export type RestrictedTableResult = Omit<TableResult, 'searchForRow' | 'iterateThroughTable' | 'reset'>;
317
+ export type RestrictedTableResult<T = any> = Omit<TableResult<T>, 'searchForRow' | 'iterateThroughTable' | 'reset' | 'getAllRows'>;
201
318
  `;
package/dist/types.d.ts CHANGED
@@ -1,14 +1,51 @@
1
1
  import type { Locator, Page } from '@playwright/test';
2
2
  export type Selector = string | ((root: Locator | Page) => Locator);
3
- export type SmartRow = Locator & {
3
+ /**
4
+ * Function to get a cell locator given row, column info.
5
+ * Replaces the old cellResolver.
6
+ */
7
+ export type GetCellLocatorFn = (args: {
8
+ row: Locator;
9
+ columnName: string;
10
+ columnIndex: number;
11
+ rowIndex?: number;
12
+ page: Page;
13
+ }) => Locator;
14
+ /**
15
+ * Function to get the currently active/focused cell.
16
+ * Returns null if no cell is active.
17
+ */
18
+ export type GetActiveCellFn = (args: TableContext) => Promise<{
19
+ rowIndex: number;
20
+ columnIndex: number;
21
+ columnName?: string;
22
+ locator: Locator;
23
+ } | null>;
24
+ export type SmartRow<T = any> = Locator & {
25
+ getRequestIndex(): number | undefined;
26
+ rowIndex?: number;
4
27
  getCell(column: string): Locator;
5
- toJSON(): Promise<Record<string, string>>;
28
+ toJSON(options?: {
29
+ columns?: string[];
30
+ }): Promise<T>;
31
+ /**
32
+ * Scrolls/paginates to bring this row into view.
33
+ * Only works if rowIndex is known.
34
+ */
35
+ bringIntoView(): Promise<void>;
6
36
  /**
7
- * Fills the row with data. Automatically detects input types (text input, select, checkbox, etc.).
37
+ * Fills the row with data. Automatically detects input types.
8
38
  */
9
- smartFill: (data: Record<string, any>, options?: FillOptions) => Promise<void>;
39
+ fill: (data: Partial<T> | Record<string, any>, options?: FillOptions) => Promise<void>;
40
+ /**
41
+ * Alias for fill() to avoid conflict with Locator.fill()
42
+ */
43
+ smartFill: (data: Partial<T> | Record<string, any>, options?: FillOptions) => Promise<void>;
44
+ };
45
+ export type StrategyContext = TableContext & {
46
+ rowLocator?: Locator;
47
+ rowIndex?: number;
10
48
  };
11
- export type StrategyContext = TableContext;
12
49
  /**
13
50
  * Defines the contract for a sorting strategy.
14
51
  */
@@ -46,51 +83,107 @@ export interface PromptOptions {
46
83
  output?: 'console' | 'error';
47
84
  includeTypes?: boolean;
48
85
  }
49
- export interface TableConfig {
50
- rowSelector?: Selector;
51
- headerSelector?: Selector;
52
- cellSelector?: Selector;
86
+ export type FillStrategy = (options: {
87
+ row: SmartRow;
88
+ columnName: string;
89
+ value: any;
90
+ index: number;
91
+ page: Page;
92
+ rootLocator: Locator;
93
+ table: TableResult;
94
+ fillOptions?: FillOptions;
95
+ }) => Promise<void>;
96
+ export type { HeaderStrategy } from './strategies/headers';
97
+ export type { CellNavigationStrategy } from './strategies/columns';
98
+ import { HeaderStrategy } from './strategies/headers';
99
+ import { CellNavigationStrategy } from './strategies/columns';
100
+ /**
101
+ * Strategy to resolve column names (string or regex) to their index.
102
+ */
103
+ export type { ColumnResolutionStrategy } from './strategies/resolution';
104
+ /**
105
+ * Strategy to filter rows based on criteria.
106
+ */
107
+ export interface FilterStrategy {
108
+ apply(options: {
109
+ rows: Locator;
110
+ filter: {
111
+ column: string;
112
+ value: string | RegExp | number;
113
+ };
114
+ colIndex: number;
115
+ tableContext: TableContext;
116
+ }): Locator;
117
+ }
118
+ /**
119
+ * Organized container for all table interaction strategies.
120
+ */
121
+ export interface TableStrategies {
122
+ /** Strategy for discovering/scanning headers */
123
+ header?: HeaderStrategy;
124
+ /** Strategy for navigating to specific cells (row + column) */
125
+ cellNavigation?: CellNavigationStrategy;
126
+ /** Strategy for filling form inputs */
127
+ fill?: FillStrategy;
128
+ /** Strategy for paginating through data */
53
129
  pagination?: PaginationStrategy;
130
+ /** Strategy for sorting columns */
54
131
  sorting?: SortingStrategy;
132
+ /** Function to get a cell locator */
133
+ getCellLocator?: GetCellLocatorFn;
134
+ /** Function to get the currently active/focused cell */
135
+ getActiveCell?: GetActiveCellFn;
136
+ }
137
+ /**
138
+ * Configuration options for useTable.
139
+ */
140
+ export interface TableConfig {
141
+ /** Selector for the table headers */
142
+ headerSelector?: string;
143
+ /** Selector for the table rows */
144
+ rowSelector?: string;
145
+ /** Selector for the cells within a row */
146
+ cellSelector?: string;
147
+ /** Number of pages to scan for verification */
55
148
  maxPages?: number;
56
- /**
57
- * Hook to rename columns dynamically.
58
- * * @param args.text - The default innerText of the header.
59
- * @param args.index - The column index.
60
- * @param args.locator - The specific header cell locator.
61
- */
149
+ /** Hook to rename columns dynamically */
62
150
  headerTransformer?: (args: {
63
151
  text: string;
64
152
  index: number;
65
153
  locator: Locator;
66
154
  }) => string | Promise<string>;
155
+ /** Automatically scroll to table on init */
67
156
  autoScroll?: boolean;
68
- /**
69
- * Enable debug mode to log internal state to console.
70
- */
157
+ /** Enable debug logs */
71
158
  debug?: boolean;
72
- /**
73
- * Strategy to reset the table to the initial page.
74
- * Called when table.reset() is invoked.
75
- */
159
+ /** Reset hook */
76
160
  onReset?: (context: TableContext) => Promise<void>;
161
+ /** All interaction strategies */
162
+ strategies?: TableStrategies;
163
+ }
164
+ export interface FinalTableConfig extends TableConfig {
165
+ headerSelector: string;
166
+ rowSelector: string;
167
+ cellSelector: string;
168
+ maxPages: number;
169
+ autoScroll: boolean;
170
+ debug: boolean;
171
+ headerTransformer: (args: {
172
+ text: string;
173
+ index: number;
174
+ locator: Locator;
175
+ }) => string | Promise<string>;
176
+ onReset: (context: TableContext) => Promise<void>;
177
+ strategies: TableStrategies;
77
178
  }
78
- /**
79
- * Represents the final, resolved table configuration after default values have been applied.
80
- * All optional properties from TableConfig are now required, except for `sorting`.
81
- */
82
- export type FinalTableConfig = Required<Omit<TableConfig, 'sorting'>> & {
83
- sorting?: SortingStrategy;
84
- };
85
179
  export interface FillOptions {
86
180
  /**
87
181
  * Custom input mappers for specific columns.
88
182
  * Maps column names to functions that return the input locator for that cell.
89
- * Columns not specified here will use auto-detection.
90
183
  */
91
184
  inputMappers?: Record<string, (cell: Locator) => Locator>;
92
185
  }
93
- export interface TableResult {
186
+ export interface TableResult<T = any> {
94
187
  /**
95
188
  * Initializes the table by resolving headers. Must be called before using sync methods.
96
189
  * @param options Optional timeout for header resolution (default: 3000ms)
@@ -101,12 +194,21 @@ export interface TableResult {
101
194
  getHeaders: () => Promise<string[]>;
102
195
  getHeaderCell: (columnName: string) => Promise<Locator>;
103
196
  /**
104
- * Finds a row on the current page only. Returns immediately (sync).
197
+ * Finds a row by filters on the current page only. Returns immediately (sync).
105
198
  * Throws error if table is not initialized.
106
199
  */
107
200
  getByRow: (filters: Record<string, string | RegExp | number>, options?: {
108
201
  exact?: boolean;
109
202
  }) => SmartRow;
203
+ /**
204
+ * Gets a row by 1-based index on the current page.
205
+ * Throws error if table is not initialized.
206
+ * @param index 1-based row index
207
+ * @param options Optional settings including bringIntoView
208
+ */
209
+ getByRowIndex: (index: number, options?: {
210
+ bringIntoView?: boolean;
211
+ }) => SmartRow;
110
212
  /**
111
213
  * Searches for a row across all available data using the configured strategy (pagination, scroll, etc.).
112
214
  * Auto-initializes if needed.
@@ -115,6 +217,19 @@ export interface TableResult {
115
217
  exact?: boolean;
116
218
  maxPages?: number;
117
219
  }) => Promise<SmartRow>;
220
+ /**
221
+ * Navigates to a specific column using the configured CellNavigationStrategy.
222
+ */
223
+ scrollToColumn: (columnName: string) => Promise<void>;
224
+ getAllCurrentRows: <T extends {
225
+ asJSON?: boolean;
226
+ }>(options?: {
227
+ filter?: Record<string, any>;
228
+ exact?: boolean;
229
+ } & T) => Promise<T['asJSON'] extends true ? Record<string, string>[] : SmartRow[]>;
230
+ /**
231
+ * @deprecated Use getAllCurrentRows instead. This method will be removed in a future major version.
232
+ */
118
233
  getAllRows: <T extends {
119
234
  asJSON?: boolean;
120
235
  }>(options?: {
@@ -127,6 +242,11 @@ export interface TableResult {
127
242
  * Resets the table state (clears cache, flags) and invokes the onReset strategy.
128
243
  */
129
244
  reset: () => Promise<void>;
245
+ /**
246
+ * Revalidates the table's structure (headers, columns) without resetting pagination or state.
247
+ * Useful when columns change visibility or order dynamically.
248
+ */
249
+ revalidate: () => Promise<void>;
130
250
  /**
131
251
  * Scans a specific column across all pages and returns the values.
132
252
  */
@@ -188,4 +308,4 @@ export interface TableResult {
188
308
  /**
189
309
  * Restricted table result that excludes methods that shouldn't be called during iteration.
190
310
  */
191
- export type RestrictedTableResult = Omit<TableResult, 'searchForRow' | 'iterateThroughTable' | 'reset'>;
311
+ export type RestrictedTableResult<T = any> = Omit<TableResult<T>, 'searchForRow' | 'iterateThroughTable' | 'reset' | 'getAllRows'>;
@@ -1,25 +1,26 @@
1
1
  import type { Locator } from '@playwright/test';
2
2
  import { TableConfig, Selector, TableResult, PaginationStrategy } from './types';
3
+ import { FillStrategies } from './strategies/fill';
4
+ import { HeaderStrategies } from './strategies/headers';
5
+ import { CellNavigationStrategies, ColumnStrategies } from './strategies/columns';
6
+ import { ResolutionStrategies } from './strategies/resolution';
7
+ import { Strategies } from './strategies';
3
8
  /**
4
- * A collection of pre-built pagination strategies.
9
+ * Main hook to interact with a table.
5
10
  */
11
+ export declare const useTable: <T = any>(rootLocator: Locator, configOptions?: TableConfig) => TableResult<T>;
6
12
  export declare const PaginationStrategies: {
7
13
  clickNext: (nextButtonSelector: Selector, timeout?: number) => PaginationStrategy;
8
14
  clickLoadMore: (buttonSelector: Selector, timeout?: number) => PaginationStrategy;
9
15
  infiniteScroll: (timeout?: number) => PaginationStrategy;
10
16
  };
11
- /**
12
- * @deprecated Use `PaginationStrategies` instead. This alias will be removed in a future major version.
13
- */
14
- export declare const TableStrategies: {
17
+ /** @deprecated Use Strategies.Pagination instead */
18
+ export declare const DeprecatedTableStrategies: {
15
19
  clickNext: (nextButtonSelector: Selector, timeout?: number) => PaginationStrategy;
16
20
  clickLoadMore: (buttonSelector: Selector, timeout?: number) => PaginationStrategy;
17
21
  infiniteScroll: (timeout?: number) => PaginationStrategy;
18
22
  };
19
- /**
20
- * A collection of pre-built sorting strategies.
21
- */
22
23
  export declare const SortingStrategies: {
23
24
  AriaSort: () => import("./types").SortingStrategy;
24
25
  };
25
- export declare const useTable: (rootLocator: Locator, configOptions?: TableConfig) => TableResult;
26
+ export { FillStrategies, HeaderStrategies, CellNavigationStrategies, ColumnStrategies, ResolutionStrategies, Strategies };