@rickcedwhat/playwright-smart-table 6.3.2 → 6.5.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.
@@ -1,48 +1,6 @@
1
1
  import type { Locator } from '@playwright/test';
2
- import { TableConfig, TableContext, Selector, TableResult, SmartRow as SmartRowType, DedupeStrategy, PaginationStrategy } from './types';
3
- import { FillStrategies } from './strategies/fill';
4
- import { HeaderStrategies } from './strategies/headers';
5
- import { CellNavigationStrategies } from './strategies/columns';
6
- import { ResolutionStrategies } from './strategies/resolution';
7
- import { Strategies } from './strategies';
2
+ import { TableConfig, TableResult } from './types';
8
3
  /**
9
4
  * Main hook to interact with a table.
10
5
  */
11
6
  export declare const useTable: <T = any>(rootLocator: Locator, configOptions?: TableConfig<T>) => TableResult<T>;
12
- export declare const PaginationStrategies: {
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
- };
37
- Headers: {
38
- stable: (duration?: number) => (context: TableContext) => Promise<boolean>;
39
- never: () => Promise<boolean>;
40
- };
41
- };
42
- export declare const SortingStrategies: {
43
- AriaSort: () => import("./types").SortingStrategy;
44
- };
45
- export declare const DedupeStrategies: {
46
- byTopPosition: (tolerance?: number) => DedupeStrategy;
47
- };
48
- export { FillStrategies, HeaderStrategies, CellNavigationStrategies, ResolutionStrategies, Strategies };
package/dist/useTable.js CHANGED
@@ -9,26 +9,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.Strategies = exports.ResolutionStrategies = exports.CellNavigationStrategies = exports.HeaderStrategies = exports.FillStrategies = exports.DedupeStrategies = exports.SortingStrategies = exports.LoadingStrategies = exports.PaginationStrategies = exports.useTable = void 0;
13
- const typeContext_1 = require("./typeContext");
14
- const sorting_1 = require("./strategies/sorting");
15
- const pagination_1 = require("./strategies/pagination");
16
- const dedupe_1 = require("./strategies/dedupe");
12
+ exports.useTable = void 0;
13
+ const minimalConfigContext_1 = require("./minimalConfigContext");
14
+ const validation_1 = require("./strategies/validation");
17
15
  const loading_1 = require("./strategies/loading");
18
16
  const fill_1 = require("./strategies/fill");
19
- Object.defineProperty(exports, "FillStrategies", { enumerable: true, get: function () { return fill_1.FillStrategies; } });
20
17
  const headers_1 = require("./strategies/headers");
21
- Object.defineProperty(exports, "HeaderStrategies", { enumerable: true, get: function () { return headers_1.HeaderStrategies; } });
22
- const columns_1 = require("./strategies/columns");
23
- Object.defineProperty(exports, "CellNavigationStrategies", { enumerable: true, get: function () { return columns_1.CellNavigationStrategies; } });
24
18
  const smartRow_1 = require("./smartRow");
25
19
  const filterEngine_1 = require("./filterEngine");
26
20
  const tableMapper_1 = require("./engine/tableMapper");
27
21
  const rowFinder_1 = require("./engine/rowFinder");
28
- const resolution_1 = require("./strategies/resolution");
29
- Object.defineProperty(exports, "ResolutionStrategies", { enumerable: true, get: function () { return resolution_1.ResolutionStrategies; } });
30
- const strategies_1 = require("./strategies");
31
- Object.defineProperty(exports, "Strategies", { enumerable: true, get: function () { return strategies_1.Strategies; } });
32
22
  const debugUtils_1 = require("./utils/debugUtils");
33
23
  const smartRowArray_1 = require("./utils/smartRowArray");
34
24
  /**
@@ -42,7 +32,6 @@ const useTable = (rootLocator, configOptions = {}) => {
42
32
  const defaultStrategies = {
43
33
  fill: fill_1.FillStrategies.default,
44
34
  header: headers_1.HeaderStrategies.visible,
45
- cellNavigation: columns_1.CellNavigationStrategies.default,
46
35
  pagination: () => __awaiter(void 0, void 0, void 0, function* () { return false; }),
47
36
  loading: {
48
37
  isHeaderLoading: loading_1.LoadingStrategies.Headers.stable(200)
@@ -87,10 +76,11 @@ const useTable = (rootLocator, configOptions = {}) => {
87
76
  // Placeholder for the final table object
88
77
  let finalTable = null;
89
78
  // Helper factory
90
- const _makeSmart = (rowLocator, map, rowIndex) => {
91
- return (0, smartRow_1.createSmartRow)(rowLocator, map, rowIndex, config, rootLocator, resolve, finalTable);
79
+ const _makeSmart = (rowLocator, map, rowIndex, tablePageIndex) => {
80
+ return (0, smartRow_1.createSmartRow)(rowLocator, map, rowIndex, config, rootLocator, resolve, finalTable, tablePageIndex);
92
81
  };
93
- const rowFinder = new rowFinder_1.RowFinder(rootLocator, config, resolve, filterEngine, tableMapper, _makeSmart);
82
+ const tableState = { currentPageIndex: 0 };
83
+ const rowFinder = new rowFinder_1.RowFinder(rootLocator, config, resolve, filterEngine, tableMapper, _makeSmart, tableState);
94
84
  const _getCleanHtml = (loc) => __awaiter(void 0, void 0, void 0, function* () {
95
85
  return loc.evaluate((el) => {
96
86
  const clone = el.cloneNode(true);
@@ -117,7 +107,7 @@ const useTable = (rootLocator, configOptions = {}) => {
117
107
  const { output = 'console', includeTypes = true } = options;
118
108
  let finalPrompt = content;
119
109
  if (includeTypes) {
120
- finalPrompt += `\n\n👇 Useful TypeScript Definitions 👇\n\`\`\`typescript\n${typeContext_1.TYPE_CONTEXT}\n\`\`\`\n`;
110
+ finalPrompt += `\n\n👇 Useful TypeScript Definitions 👇\n\`\`\`typescript\n${minimalConfigContext_1.MINIMAL_CONFIG_CONTEXT}\n\`\`\`\n`;
121
111
  }
122
112
  if (output === 'error') {
123
113
  console.log(`⚠️ Throwing error to display [${promptName}] cleanly...`);
@@ -129,6 +119,8 @@ const useTable = (rootLocator, configOptions = {}) => {
129
119
  yield tableMapper.getMap();
130
120
  });
131
121
  const result = {
122
+ get currentPageIndex() { return tableState.currentPageIndex; },
123
+ set currentPageIndex(v) { tableState.currentPageIndex = v; },
132
124
  init: (options) => __awaiter(void 0, void 0, void 0, function* () {
133
125
  if (tableMapper.isInitialized())
134
126
  return result;
@@ -144,14 +136,9 @@ const useTable = (rootLocator, configOptions = {}) => {
144
136
  const idx = map.get(columnName);
145
137
  if (idx === undefined)
146
138
  throw _createColumnError(columnName, map);
147
- yield config.strategies.cellNavigation({
148
- config: config,
149
- root: rootLocator,
150
- page: rootLocator.page(),
151
- resolve,
152
- column: columnName,
153
- index: idx
154
- });
139
+ // Use header cell for scrolling
140
+ const headerCell = resolve(config.headerSelector, rootLocator).nth(idx);
141
+ yield headerCell.scrollIntoViewIfNeeded();
155
142
  }),
156
143
  getHeaders: () => __awaiter(void 0, void 0, void 0, function* () {
157
144
  const map = yield tableMapper.getMap();
@@ -185,7 +172,7 @@ const useTable = (rootLocator, configOptions = {}) => {
185
172
  throw _createColumnError(column, map);
186
173
  const mapper = (_a = options === null || options === void 0 ? void 0 : options.mapper) !== null && _a !== void 0 ? _a : ((c) => c.innerText());
187
174
  const effectiveMaxPages = (_b = options === null || options === void 0 ? void 0 : options.maxPages) !== null && _b !== void 0 ? _b : config.maxPages;
188
- let currentPage = 1;
175
+ let pagesScanned = 1;
189
176
  const results = [];
190
177
  log(`Getting column values for '${column}' (Pages: ${effectiveMaxPages})`);
191
178
  while (true) {
@@ -196,11 +183,23 @@ const useTable = (rootLocator, configOptions = {}) => {
196
183
  : resolve(config.cellSelector, row).nth(colIdx);
197
184
  results.push(yield mapper(cell));
198
185
  }
199
- if (currentPage < effectiveMaxPages) {
186
+ if (pagesScanned < effectiveMaxPages) {
200
187
  const context = { root: rootLocator, config, page: rootLocator.page(), resolve };
201
- if (yield config.strategies.pagination(context)) {
188
+ let pageRes;
189
+ if (typeof config.strategies.pagination === 'function') {
190
+ pageRes = yield config.strategies.pagination(context);
191
+ }
192
+ else {
193
+ if (!config.strategies.pagination.goNext) {
194
+ log('Cannot paginate: no goNext primitive found.');
195
+ break;
196
+ }
197
+ pageRes = yield config.strategies.pagination.goNext(context);
198
+ }
199
+ if (yield (0, validation_1.validatePaginationResult)(pageRes, 'Pagination Strategy')) {
202
200
  _hasPaginated = true;
203
- currentPage++;
201
+ tableState.currentPageIndex++;
202
+ pagesScanned++;
204
203
  continue;
205
204
  }
206
205
  }
@@ -228,11 +227,6 @@ const useTable = (rootLocator, configOptions = {}) => {
228
227
  // @ts-ignore
229
228
  return rowFinder.findRow(filters, options);
230
229
  }),
231
- getRows: (options) => __awaiter(void 0, void 0, void 0, function* () {
232
- console.warn('DEPRECATED: table.getRows() is deprecated and will be removed in a future version. Use table.findRows() instead.');
233
- // @ts-ignore
234
- return rowFinder.findRows((options === null || options === void 0 ? void 0 : options.filter) || {}, Object.assign(Object.assign({}, options), { maxPages: 1 }));
235
- }),
236
230
  findRows: (filters, options) => __awaiter(void 0, void 0, void 0, function* () {
237
231
  return rowFinder.findRows(filters, options);
238
232
  }),
@@ -267,13 +261,13 @@ const useTable = (rootLocator, configOptions = {}) => {
267
261
  yield result.init();
268
262
  const map = tableMapper.getMapSync();
269
263
  const restrictedTable = {
264
+ get currentPageIndex() { return tableState.currentPageIndex; },
270
265
  init: result.init,
271
266
  getHeaders: result.getHeaders,
272
267
  getHeaderCell: result.getHeaderCell,
273
268
  getRow: result.getRow,
274
269
  getRowByIndex: result.getRowByIndex,
275
270
  findRow: result.findRow,
276
- getRows: result.getRows,
277
271
  findRows: result.findRows,
278
272
  getColumnValues: result.getColumnValues,
279
273
  isInitialized: result.isInitialized,
@@ -362,10 +356,20 @@ const useTable = (rootLocator, configOptions = {}) => {
362
356
  let finalIsLast = isLastDueToMax;
363
357
  if (!isLastIteration) {
364
358
  const context = { root: rootLocator, config, page: rootLocator.page(), resolve };
365
- paginationResult = yield paginationStrategy(context);
359
+ if (typeof paginationStrategy === 'function') {
360
+ paginationResult = yield paginationStrategy(context);
361
+ }
362
+ else {
363
+ const pageObj = paginationStrategy;
364
+ if (!pageObj.goNext)
365
+ break;
366
+ paginationResult = yield pageObj.goNext(context);
367
+ }
366
368
  (0, debugUtils_1.logDebug)(config, 'info', `Pagination ${paginationResult ? 'succeeded' : 'failed'}`);
367
369
  yield (0, debugUtils_1.debugDelay)(config, 'pagination');
368
370
  finalIsLast = getIsLast({ index: callbackIndex, paginationResult }) || !paginationResult;
371
+ if (paginationResult)
372
+ tableState.currentPageIndex++;
369
373
  }
370
374
  if (finalIsLast && (options === null || options === void 0 ? void 0 : options.afterLast)) {
371
375
  yield options.afterLast({ index: callbackIndex, rows: (0, smartRowArray_1.createSmartRowArray)(callbackRows), allData });
@@ -383,9 +387,21 @@ const useTable = (rootLocator, configOptions = {}) => {
383
387
  else {
384
388
  // Continue paginating even when batching
385
389
  const context = { root: rootLocator, config, page: rootLocator.page(), resolve };
386
- paginationResult = yield paginationStrategy(context);
390
+ if (typeof paginationStrategy === 'function') {
391
+ paginationResult = yield paginationStrategy(context);
392
+ }
393
+ else {
394
+ const pageObj = paginationStrategy;
395
+ if (!pageObj.goNext) {
396
+ log(`Cannot paginate: no goNext primitive found.`);
397
+ break;
398
+ }
399
+ paginationResult = yield pageObj.goNext(context);
400
+ }
387
401
  (0, debugUtils_1.logDebug)(config, 'info', `Pagination ${paginationResult ? 'succeeded' : 'failed'} (batching mode)`);
388
402
  yield (0, debugUtils_1.debugDelay)(config, 'pagination');
403
+ if (paginationResult)
404
+ tableState.currentPageIndex++;
389
405
  if (!paginationResult) {
390
406
  // Pagination failed, invoke callback with current batch
391
407
  const callbackIndex = batchStartIndex;
@@ -438,7 +454,3 @@ const useTable = (rootLocator, configOptions = {}) => {
438
454
  return result;
439
455
  };
440
456
  exports.useTable = useTable;
441
- exports.PaginationStrategies = Object.assign({}, pagination_1.PaginationStrategies);
442
- exports.LoadingStrategies = loading_1.LoadingStrategies;
443
- exports.SortingStrategies = sorting_1.SortingStrategies;
444
- exports.DedupeStrategies = dedupe_1.DedupeStrategies;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rickcedwhat/playwright-smart-table",
3
- "version": "6.3.2",
3
+ "version": "6.5.0",
4
4
  "description": "Smart, column-aware table interactions for Playwright",
5
5
  "author": "Cedrick Catalan",
6
6
  "license": "MIT",
@@ -15,12 +15,13 @@
15
15
  ],
16
16
  "scripts": {
17
17
  "generate-types": "node scripts/embed-types.mjs",
18
+ "generate-config-types": "node scripts/embed-config-types.mjs",
18
19
  "generate-docs": "node scripts/generate-readme.mjs",
19
20
  "generate-all-api-docs": "node scripts/generate-all-api-docs.mjs",
20
21
  "update-all-api-signatures": "node scripts/update-all-api-signatures.mjs",
21
22
  "docs:dev": "vitepress dev docs",
22
23
  "docs:build": "vitepress build docs",
23
- "build": "npm run generate-types && npm run generate-docs && npm run generate-all-api-docs && npm run update-all-api-signatures && tsc",
24
+ "build": "npm run generate-types && npm run generate-config-types && npm run generate-docs && npm run generate-all-api-docs && npm run update-all-api-signatures && tsc",
24
25
  "prepublishOnly": "npm run build",
25
26
  "test": "npm run test:unit && npx playwright test",
26
27
  "test:unit": "vitest run --reporter=verbose --reporter=html",