@rickcedwhat/playwright-smart-table 6.1.0 → 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.
Files changed (66) hide show
  1. package/dist/{examples/glide-strategies → strategies/glide}/columns.d.ts +1 -1
  2. package/dist/{examples/glide-strategies → strategies/glide}/headers.d.ts +1 -1
  3. package/dist/{src/strategies → strategies}/glide.js +2 -2
  4. package/dist/strategies/index.d.ts +29 -2
  5. package/dist/strategies/index.js +6 -0
  6. package/dist/strategies/pagination.d.ts +26 -4
  7. package/dist/strategies/pagination.js +52 -23
  8. package/dist/typeContext.d.ts +1 -1
  9. package/dist/typeContext.js +28 -4
  10. package/dist/types.d.ts +33 -2
  11. package/dist/useTable.d.ts +28 -3
  12. package/dist/useTable.js +92 -36
  13. package/package.json +1 -1
  14. package/dist/src/filterEngine.d.ts +0 -11
  15. package/dist/src/filterEngine.js +0 -39
  16. package/dist/src/index.d.ts +0 -2
  17. package/dist/src/index.js +0 -18
  18. package/dist/src/smartRow.d.ts +0 -7
  19. package/dist/src/smartRow.js +0 -160
  20. package/dist/src/strategies/columns.d.ts +0 -18
  21. package/dist/src/strategies/columns.js +0 -21
  22. package/dist/src/strategies/fill.d.ts +0 -7
  23. package/dist/src/strategies/fill.js +0 -88
  24. package/dist/src/strategies/headers.d.ts +0 -13
  25. package/dist/src/strategies/headers.js +0 -30
  26. package/dist/src/strategies/index.d.ts +0 -54
  27. package/dist/src/strategies/index.js +0 -43
  28. package/dist/src/strategies/pagination.d.ts +0 -33
  29. package/dist/src/strategies/pagination.js +0 -79
  30. package/dist/src/strategies/resolution.d.ts +0 -22
  31. package/dist/src/strategies/resolution.js +0 -30
  32. package/dist/src/strategies/sorting.d.ts +0 -12
  33. package/dist/src/strategies/sorting.js +0 -68
  34. package/dist/src/strategies/validation.d.ts +0 -22
  35. package/dist/src/strategies/validation.js +0 -54
  36. package/dist/src/strategies/virtualizedPagination.d.ts +0 -32
  37. package/dist/src/strategies/virtualizedPagination.js +0 -80
  38. package/dist/src/typeContext.d.ts +0 -6
  39. package/dist/src/typeContext.js +0 -465
  40. package/dist/src/types.d.ts +0 -458
  41. package/dist/src/types.js +0 -2
  42. package/dist/src/useTable.d.ts +0 -44
  43. package/dist/src/useTable.js +0 -641
  44. package/dist/src/utils/debugUtils.d.ts +0 -17
  45. package/dist/src/utils/debugUtils.js +0 -62
  46. package/dist/src/utils/smartRowArray.d.ts +0 -14
  47. package/dist/src/utils/smartRowArray.js +0 -22
  48. package/dist/src/utils/stringUtils.d.ts +0 -22
  49. package/dist/src/utils/stringUtils.js +0 -73
  50. package/dist/src/utils.d.ts +0 -7
  51. package/dist/src/utils.js +0 -29
  52. package/dist/utils/traceUtils.d.ts +0 -11
  53. package/dist/utils/traceUtils.js +0 -47
  54. /package/dist/{src/plugins.d.ts → plugins.d.ts} +0 -0
  55. /package/dist/{src/plugins.js → plugins.js} +0 -0
  56. /package/dist/{src/strategies → strategies}/dedupe.d.ts +0 -0
  57. /package/dist/{src/strategies → strategies}/dedupe.js +0 -0
  58. /package/dist/{examples/glide-strategies → strategies/glide}/columns.js +0 -0
  59. /package/dist/{examples/glide-strategies → strategies/glide}/headers.js +0 -0
  60. /package/dist/{src/strategies → strategies}/glide.d.ts +0 -0
  61. /package/dist/{src/strategies → strategies}/loading.d.ts +0 -0
  62. /package/dist/{src/strategies → strategies}/loading.js +0 -0
  63. /package/dist/{src/strategies → strategies}/rdg.d.ts +0 -0
  64. /package/dist/{src/strategies → strategies}/rdg.js +0 -0
  65. /package/dist/{src/strategies → strategies}/stabilization.d.ts +0 -0
  66. /package/dist/{src/strategies → strategies}/stabilization.js +0 -0
package/dist/useTable.js CHANGED
@@ -9,10 +9,12 @@ 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.SortingStrategies = exports.PaginationStrategies = exports.useTable = void 0;
12
+ exports.Strategies = exports.ResolutionStrategies = exports.CellNavigationStrategies = exports.HeaderStrategies = exports.FillStrategies = exports.DedupeStrategies = exports.SortingStrategies = exports.LoadingStrategies = exports.PaginationStrategies = exports.useTable = void 0;
13
13
  const typeContext_1 = require("./typeContext");
14
14
  const sorting_1 = require("./strategies/sorting");
15
15
  const pagination_1 = require("./strategies/pagination");
16
+ const dedupe_1 = require("./strategies/dedupe");
17
+ const loading_1 = require("./strategies/loading");
16
18
  const fill_1 = require("./strategies/fill");
17
19
  Object.defineProperty(exports, "FillStrategies", { enumerable: true, get: function () { return fill_1.FillStrategies; } });
18
20
  const headers_1 = require("./strategies/headers");
@@ -42,7 +44,7 @@ const useTable = (rootLocator, configOptions = {}) => {
42
44
  cellNavigation: columns_1.CellNavigationStrategies.default,
43
45
  pagination: () => __awaiter(void 0, void 0, void 0, function* () { return false; }),
44
46
  };
45
- const config = Object.assign(Object.assign({ rowSelector: "tbody tr", headerSelector: "thead th", cellSelector: "td", maxPages: 1, headerTransformer: ({ text, index, locator }) => text, autoScroll: true, onReset: () => __awaiter(void 0, void 0, void 0, function* () { }) }, configOptions), { strategies: Object.assign(Object.assign({}, defaultStrategies), configOptions.strategies) });
47
+ const config = Object.assign(Object.assign({ rowSelector: "tbody tr", headerSelector: "thead th", cellSelector: "td", maxPages: 1, headerTransformer: ({ text }) => text, autoScroll: true, onReset: () => __awaiter(void 0, void 0, void 0, function* () { }) }, configOptions), { strategies: Object.assign(Object.assign({}, defaultStrategies), configOptions.strategies) });
46
48
  const resolve = (item, parent) => {
47
49
  if (typeof item === 'string')
48
50
  return parent.locator(item);
@@ -73,7 +75,7 @@ const useTable = (rootLocator, configOptions = {}) => {
73
75
  suggestion = `. Available columns: ${availableColumns.map(c => `"${c}"`).join(', ')}`;
74
76
  }
75
77
  else if (availableColumns.length > 0) {
76
- suggestion = `. Available columns (first 5): ${availableColumns.slice(0, 5).map(c => `"${c}"`).join(', ')}, ...`;
78
+ suggestion = `. Available columns (first 10 of ${availableColumns.length}): ${availableColumns.slice(0, 10).map(c => `"${c}"`).join(', ')}, ...`;
77
79
  }
78
80
  const contextMsg = context ? ` (${context})` : '';
79
81
  return new Error(`Column "${colName}" not found${contextMsg}${suggestion}`);
@@ -102,17 +104,21 @@ const useTable = (rootLocator, configOptions = {}) => {
102
104
  resolve: resolve
103
105
  };
104
106
  const rawHeaders = yield strategy(context);
105
- const entries = yield Promise.all(rawHeaders.map((t, i) => __awaiter(void 0, void 0, void 0, function* () {
106
- let text = t.trim() || `__col_${i}`;
107
+ const seenHeaders = new Set();
108
+ const entries = [];
109
+ for (let i = 0; i < rawHeaders.length; i++) {
110
+ let text = rawHeaders[i].trim() || `__col_${i}`;
107
111
  if (config.headerTransformer) {
108
112
  text = yield config.headerTransformer({
109
113
  text,
110
114
  index: i,
111
- locator: rootLocator.locator(config.headerSelector).nth(i)
115
+ locator: rootLocator.locator(config.headerSelector).nth(i),
116
+ seenHeaders
112
117
  });
113
118
  }
114
- return [text, i];
115
- })));
119
+ entries.push([text, i]);
120
+ seenHeaders.add(text);
121
+ }
116
122
  // Validation: Check for empty table
117
123
  if (entries.length === 0) {
118
124
  throw new Error(`Initialization Error: No columns found using selector "${config.headerSelector}". Check your selector or ensure the table is visible.`);
@@ -143,12 +149,21 @@ const useTable = (rootLocator, configOptions = {}) => {
143
149
  return (0, smartRow_1.createSmartRow)(rowLocator, map, rowIndex, config, rootLocator, resolve, finalTable);
144
150
  };
145
151
  const _findRowLocator = (filters_1, ...args_1) => __awaiter(void 0, [filters_1, ...args_1], void 0, function* (filters, options = {}) {
146
- var _a;
152
+ var _a, _b;
147
153
  const map = yield _getMap();
148
154
  const effectiveMaxPages = (_a = options.maxPages) !== null && _a !== void 0 ? _a : config.maxPages;
149
155
  let currentPage = 1;
150
156
  log(`Looking for row: ${JSON.stringify(filters)} (MaxPages: ${effectiveMaxPages})`);
151
157
  while (true) {
158
+ // Check for table loading
159
+ if ((_b = config.strategies.loading) === null || _b === void 0 ? void 0 : _b.isTableLoading) {
160
+ const isLoading = yield config.strategies.loading.isTableLoading({ root: rootLocator, config, page: rootLocator.page(), resolve });
161
+ if (isLoading) {
162
+ log('Table is loading... waiting');
163
+ yield rootLocator.page().waitForTimeout(200);
164
+ continue;
165
+ }
166
+ }
152
167
  const allRows = resolve(config.rowSelector, rootLocator);
153
168
  // Use FilterEngine
154
169
  const matchedRows = filterEngine.applyFilters(allRows, filters, map, options.exact || false, rootLocator.page());
@@ -167,7 +182,7 @@ const useTable = (rootLocator, configOptions = {}) => {
167
182
  }
168
183
  catch (e) { }
169
184
  const sampleMsg = sampleData.length > 0 ? `\nSample matching rows:\n${sampleData.map((d, i) => ` ${i + 1}. ${d}`).join('\n')}` : '';
170
- throw new Error(`Strict Mode Violation: Found ${count} rows matching ${JSON.stringify(filters)} on page ${currentPage}. ` +
185
+ throw new Error(`Ambiguous Row: Found ${count} rows matching ${JSON.stringify(filters)} on page ${currentPage}. ` +
171
186
  `Expected exactly one match. Try adding more filters to make your query unique.${sampleMsg}`);
172
187
  }
173
188
  if (count === 1)
@@ -267,13 +282,11 @@ const useTable = (rootLocator, configOptions = {}) => {
267
282
  });
268
283
  }),
269
284
  getHeaders: () => __awaiter(void 0, void 0, void 0, function* () {
270
- if (!_isInitialized || !_headerMap)
271
- throw new Error('Table not initialized. Call await table.init() first, or use async methods like table.findRow() or table.getRows() which auto-initialize.');
285
+ yield _ensureInitialized();
272
286
  return Array.from(_headerMap.keys());
273
287
  }),
274
288
  getHeaderCell: (columnName) => __awaiter(void 0, void 0, void 0, function* () {
275
- if (!_isInitialized || !_headerMap)
276
- throw new Error('Table not initialized. Call await table.init() first.');
289
+ yield _ensureInitialized();
277
290
  const idx = _headerMap.get(columnName);
278
291
  if (idx === undefined)
279
292
  throw _createColumnError(columnName, _headerMap, 'header cell');
@@ -336,9 +349,8 @@ const useTable = (rootLocator, configOptions = {}) => {
336
349
  getRowByIndex: (index, options = {}) => {
337
350
  if (!_isInitialized || !_headerMap)
338
351
  throw new Error('Table not initialized. Call await table.init() first, or use async methods like table.findRow() or table.getRows() which auto-initialize.');
339
- const rowIndex = index - 1; // Convert 1-based to 0-based
340
- const rowLocator = resolve(config.rowSelector, rootLocator).nth(rowIndex);
341
- return _makeSmart(rowLocator, _headerMap, rowIndex);
352
+ const rowLocator = resolve(config.rowSelector, rootLocator).nth(index);
353
+ return _makeSmart(rowLocator, _headerMap, index);
342
354
  },
343
355
  findRow: (filters, options) => __awaiter(void 0, void 0, void 0, function* () {
344
356
  (0, debugUtils_1.logDebug)(config, 'info', 'Searching for row', filters);
@@ -356,17 +368,28 @@ const useTable = (rootLocator, configOptions = {}) => {
356
368
  return _makeSmart(row, _headerMap, 0);
357
369
  }),
358
370
  getRows: (options) => __awaiter(void 0, void 0, void 0, function* () {
371
+ var _a;
359
372
  yield _ensureInitialized();
360
373
  let rowLocators = resolve(config.rowSelector, rootLocator);
361
374
  if (options === null || options === void 0 ? void 0 : options.filter) {
362
375
  rowLocators = filterEngine.applyFilters(rowLocators, options.filter, _headerMap, options.exact || false, rootLocator.page());
363
376
  }
364
- const rows = yield rowLocators.all();
365
- const smartRows = rows.map((loc, i) => _makeSmart(loc, _headerMap, i));
377
+ const allRowLocs = yield rowLocators.all();
378
+ const smartRows = [];
379
+ const isRowLoading = (_a = config.strategies.loading) === null || _a === void 0 ? void 0 : _a.isRowLoading;
380
+ for (let i = 0; i < allRowLocs.length; i++) {
381
+ const smartRow = _makeSmart(allRowLocs[i], _headerMap, i);
382
+ if (isRowLoading) {
383
+ const loading = yield isRowLoading(smartRow);
384
+ if (loading)
385
+ continue;
386
+ }
387
+ smartRows.push(smartRow);
388
+ }
366
389
  return (0, smartRowArray_1.createSmartRowArray)(smartRows);
367
390
  }),
368
391
  findRows: (filters, options) => __awaiter(void 0, void 0, void 0, function* () {
369
- var _a, _b, _c, _d;
392
+ var _a, _b, _c, _d, _e;
370
393
  yield _ensureInitialized();
371
394
  const allRows = [];
372
395
  const effectiveMaxPages = (_b = (_a = options === null || options === void 0 ? void 0 : options.maxPages) !== null && _a !== void 0 ? _a : config.maxPages) !== null && _b !== void 0 ? _b : Infinity;
@@ -374,8 +397,14 @@ const useTable = (rootLocator, configOptions = {}) => {
374
397
  // Collect rows from current page
375
398
  let rowLocators = resolve(config.rowSelector, rootLocator);
376
399
  rowLocators = filterEngine.applyFilters(rowLocators, filters, _headerMap, (_c = options === null || options === void 0 ? void 0 : options.exact) !== null && _c !== void 0 ? _c : false, rootLocator.page());
377
- let rows = yield rowLocators.all();
378
- allRows.push(...rows.map((loc, i) => _makeSmart(loc, _headerMap, i)));
400
+ let currentRows = yield rowLocators.all();
401
+ const isRowLoading = (_d = config.strategies.loading) === null || _d === void 0 ? void 0 : _d.isRowLoading;
402
+ for (let i = 0; i < currentRows.length; i++) {
403
+ const smartRow = _makeSmart(currentRows[i], _headerMap, i);
404
+ if (isRowLoading && (yield isRowLoading(smartRow)))
405
+ continue;
406
+ allRows.push(smartRow);
407
+ }
379
408
  // Paginate and collect more rows
380
409
  while (pageCount < effectiveMaxPages && config.strategies.pagination) {
381
410
  const paginationResult = yield config.strategies.pagination({
@@ -391,9 +420,14 @@ const useTable = (rootLocator, configOptions = {}) => {
391
420
  _hasPaginated = true;
392
421
  // Collect rows from new page
393
422
  rowLocators = resolve(config.rowSelector, rootLocator);
394
- rowLocators = filterEngine.applyFilters(rowLocators, filters, _headerMap, (_d = options === null || options === void 0 ? void 0 : options.exact) !== null && _d !== void 0 ? _d : false, rootLocator.page());
395
- rows = yield rowLocators.all();
396
- allRows.push(...rows.map((loc, i) => _makeSmart(loc, _headerMap, i)));
423
+ rowLocators = filterEngine.applyFilters(rowLocators, filters, _headerMap, (_e = options === null || options === void 0 ? void 0 : options.exact) !== null && _e !== void 0 ? _e : false, rootLocator.page());
424
+ const newRows = yield rowLocators.all();
425
+ for (let i = 0; i < newRows.length; i++) {
426
+ const smartRow = _makeSmart(newRows[i], _headerMap, i);
427
+ if (isRowLoading && (yield isRowLoading(smartRow)))
428
+ continue;
429
+ allRows.push(smartRow);
430
+ }
397
431
  }
398
432
  if (options === null || options === void 0 ? void 0 : options.asJSON) {
399
433
  return Promise.all(allRows.map(r => r.toJSON()));
@@ -421,7 +455,7 @@ const useTable = (rootLocator, configOptions = {}) => {
421
455
  })
422
456
  },
423
457
  iterateThroughTable: (callback, options) => __awaiter(void 0, void 0, void 0, function* () {
424
- var _a, _b, _c, _d;
458
+ var _a, _b, _c, _d, _e, _f, _g;
425
459
  yield _ensureInitialized();
426
460
  const paginationStrategy = (_a = options === null || options === void 0 ? void 0 : options.pagination) !== null && _a !== void 0 ? _a : config.strategies.pagination;
427
461
  const hasPaginationInOptions = (options === null || options === void 0 ? void 0 : options.pagination) !== undefined;
@@ -451,6 +485,7 @@ const useTable = (rootLocator, configOptions = {}) => {
451
485
  const effectiveMaxIterations = (_d = options === null || options === void 0 ? void 0 : options.maxIterations) !== null && _d !== void 0 ? _d : config.maxPages;
452
486
  const batchSize = options === null || options === void 0 ? void 0 : options.batchSize;
453
487
  const isBatching = batchSize !== undefined && batchSize > 1;
488
+ const autoFlatten = (_e = options === null || options === void 0 ? void 0 : options.autoFlatten) !== null && _e !== void 0 ? _e : false;
454
489
  let index = 0;
455
490
  let paginationResult = true;
456
491
  let seenKeys = null;
@@ -459,19 +494,28 @@ const useTable = (rootLocator, configOptions = {}) => {
459
494
  log(`Starting iterateThroughTable (maxIterations: ${effectiveMaxIterations}, batchSize: ${batchSize !== null && batchSize !== void 0 ? batchSize : 'none'})`);
460
495
  while (index < effectiveMaxIterations) {
461
496
  const rowLocators = yield resolve(config.rowSelector, rootLocator).all();
462
- let rows = rowLocators.map((loc, i) => _makeSmart(loc, _headerMap, i));
463
- if ((options === null || options === void 0 ? void 0 : options.dedupeStrategy) && rows.length > 0) {
497
+ const smartRowsArray = [];
498
+ const isRowLoading = (_f = config.strategies.loading) === null || _f === void 0 ? void 0 : _f.isRowLoading;
499
+ for (let i = 0; i < rowLocators.length; i++) {
500
+ const smartRow = _makeSmart(rowLocators[i], _headerMap, i);
501
+ if (isRowLoading && (yield isRowLoading(smartRow)))
502
+ continue;
503
+ smartRowsArray.push(smartRow);
504
+ }
505
+ let rows = (0, smartRowArray_1.createSmartRowArray)(smartRowsArray);
506
+ const dedupeStrategy = (_g = options === null || options === void 0 ? void 0 : options.dedupeStrategy) !== null && _g !== void 0 ? _g : config.strategies.dedupe;
507
+ if (dedupeStrategy && rows.length > 0) {
464
508
  if (!seenKeys)
465
509
  seenKeys = new Set();
466
510
  const deduplicated = [];
467
511
  for (const row of rows) {
468
- const key = yield options.dedupeStrategy(row);
512
+ const key = yield dedupeStrategy(row);
469
513
  if (!seenKeys.has(key)) {
470
514
  seenKeys.add(key);
471
515
  deduplicated.push(row);
472
516
  }
473
517
  }
474
- rows = deduplicated;
518
+ rows = (0, smartRowArray_1.createSmartRowArray)(deduplicated);
475
519
  log(`Deduplicated ${rowLocators.length} rows to ${rows.length} unique rows (total seen: ${seenKeys.size})`);
476
520
  }
477
521
  // Add rows to batch if batching is enabled
@@ -500,12 +544,17 @@ const useTable = (rootLocator, configOptions = {}) => {
500
544
  index: callbackIndex,
501
545
  isFirst,
502
546
  isLast,
503
- rows: callbackRows,
547
+ rows: (0, smartRowArray_1.createSmartRowArray)(callbackRows),
504
548
  allData,
505
549
  table: restrictedTable,
506
550
  batchInfo
507
551
  });
508
- allData.push(returnValue);
552
+ if (autoFlatten && Array.isArray(returnValue)) {
553
+ allData.push(...returnValue);
554
+ }
555
+ else {
556
+ allData.push(returnValue);
557
+ }
509
558
  // Determine if this is truly the last iteration
510
559
  let finalIsLast = isLastDueToMax;
511
560
  if (!isLastIteration) {
@@ -551,12 +600,17 @@ const useTable = (rootLocator, configOptions = {}) => {
551
600
  index: callbackIndex,
552
601
  isFirst,
553
602
  isLast,
554
- rows: batchRows,
603
+ rows: (0, smartRowArray_1.createSmartRowArray)(batchRows),
555
604
  allData,
556
605
  table: restrictedTable,
557
606
  batchInfo
558
607
  });
559
- allData.push(returnValue);
608
+ if (autoFlatten && Array.isArray(returnValue)) {
609
+ allData.push(...returnValue);
610
+ }
611
+ else {
612
+ allData.push(returnValue);
613
+ }
560
614
  if (options === null || options === void 0 ? void 0 : options.afterLast) {
561
615
  yield options.afterLast({ index: callbackIndex, rows: batchRows, allData });
562
616
  }
@@ -573,7 +627,7 @@ const useTable = (rootLocator, configOptions = {}) => {
573
627
  generateConfigPrompt: (options) => __awaiter(void 0, void 0, void 0, function* () {
574
628
  const html = yield _getCleanHtml(rootLocator);
575
629
  const separator = "=".repeat(50);
576
- const content = `\n${separator}\n🤖 COPY INTO GEMINI/ChatGPT 🤖\n${separator}\nI am using 'playwright-smart-table'.\nTarget Table Locator: ${rootLocator.toString()}\nGenerate config for:\n\`\`\`html\n${html.substring(0, 10000)} ...\n\`\`\`\n${separator}\n`;
630
+ const content = `\n${separator} \n🤖 COPY INTO GEMINI / ChatGPT 🤖\n${separator} \nI am using 'playwright-smart-table'.\nTarget Table Locator: ${rootLocator.toString()} \nGenerate config for: \n\`\`\`html\n${html.substring(0, 10000)} ...\n\`\`\`\n${separator}\n`;
577
631
  yield _handlePrompt('Smart Table Config', content, options);
578
632
  }),
579
633
  };
@@ -581,5 +635,7 @@ const useTable = (rootLocator, configOptions = {}) => {
581
635
  return result;
582
636
  };
583
637
  exports.useTable = useTable;
584
- exports.PaginationStrategies = pagination_1.PaginationStrategies;
638
+ exports.PaginationStrategies = Object.assign({}, pagination_1.PaginationStrategies);
639
+ exports.LoadingStrategies = loading_1.LoadingStrategies;
585
640
  exports.SortingStrategies = sorting_1.SortingStrategies;
641
+ 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.1.0",
3
+ "version": "6.1.1",
4
4
  "description": "Smart, column-aware table interactions for Playwright",
5
5
  "author": "Cedrick Catalan",
6
6
  "license": "MIT",
@@ -1,11 +0,0 @@
1
- import { Locator, Page } from "@playwright/test";
2
- import { FinalTableConfig } from "./types";
3
- export declare class FilterEngine {
4
- private config;
5
- private resolve;
6
- constructor(config: FinalTableConfig, resolve: (selector: any, parent: Locator | Page) => Locator);
7
- /**
8
- * Applies filters to a set of rows.
9
- */
10
- applyFilters(baseRows: Locator, filters: Record<string, string | RegExp | number>, map: Map<string, number>, exact: boolean, page: Page): Locator;
11
- }
@@ -1,39 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FilterEngine = void 0;
4
- const stringUtils_1 = require("./utils/stringUtils");
5
- class FilterEngine {
6
- constructor(config, resolve) {
7
- this.config = config;
8
- this.resolve = resolve;
9
- }
10
- /**
11
- * Applies filters to a set of rows.
12
- */
13
- applyFilters(baseRows, filters, map, exact, page) {
14
- let filtered = baseRows;
15
- // Iterate through each filter criteria
16
- for (const [colName, value] of Object.entries(filters)) {
17
- // Find column index
18
- const colIndex = map.get(colName);
19
- // TODO: Use ColumnStrategy for better resolution error handling
20
- if (colIndex === undefined) {
21
- throw new Error((0, stringUtils_1.buildColumnNotFoundError)(colName, Array.from(map.keys())));
22
- }
23
- const filterVal = typeof value === 'number' ? String(value) : value;
24
- // Use strategy if provided (For future: configured filter strategies)
25
- // But for now, we implement the default logic or use custom if we add it to config later
26
- // Default Filter Logic
27
- const cellTemplate = this.resolve(this.config.cellSelector, page);
28
- // This logic assumes 1:1 row-to-cell mapping based on index.
29
- // filter({ has: ... }) checks if the row *contains* the matching cell.
30
- // But we need to be specific about WHICH cell.
31
- // Locator filtering by `has: locator.nth(index)` works if `locator` search is relative to the row.
32
- filtered = filtered.filter({
33
- has: cellTemplate.nth(colIndex).getByText(filterVal, { exact }),
34
- });
35
- }
36
- return filtered;
37
- }
38
- }
39
- exports.FilterEngine = FilterEngine;
@@ -1,2 +0,0 @@
1
- export * from './useTable';
2
- export * from './types';
package/dist/src/index.js DELETED
@@ -1,18 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./useTable"), exports);
18
- __exportStar(require("./types"), exports);
@@ -1,7 +0,0 @@
1
- import type { Locator, Page } from '@playwright/test';
2
- import { SmartRow as SmartRowType, FinalTableConfig, TableResult } from './types';
3
- /**
4
- * Factory to create a SmartRow by extending a Playwright Locator.
5
- * We avoid Class/Proxy to ensure full compatibility with Playwright's expect(locator) matchers.
6
- */
7
- export declare const createSmartRow: <T = any>(rowLocator: Locator, map: Map<string, number>, rowIndex: number | undefined, config: FinalTableConfig, rootLocator: Locator, resolve: (item: any, parent: Locator | Page) => Locator, table: TableResult<T> | null) => SmartRowType<T>;
@@ -1,160 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.createSmartRow = void 0;
13
- const fill_1 = require("./strategies/fill");
14
- const stringUtils_1 = require("./utils/stringUtils");
15
- const debugUtils_1 = require("./utils/debugUtils");
16
- /**
17
- * Factory to create a SmartRow by extending a Playwright Locator.
18
- * We avoid Class/Proxy to ensure full compatibility with Playwright's expect(locator) matchers.
19
- */
20
- const createSmartRow = (rowLocator, map, rowIndex, config, rootLocator, resolve, table) => {
21
- const smart = rowLocator;
22
- // Attach State
23
- smart.rowIndex = rowIndex;
24
- // Attach Methods
25
- smart.getCell = (colName) => {
26
- const idx = map.get(colName);
27
- if (idx === undefined) {
28
- throw new Error((0, stringUtils_1.buildColumnNotFoundError)(colName, Array.from(map.keys())));
29
- }
30
- if (config.strategies.getCellLocator) {
31
- return config.strategies.getCellLocator({
32
- row: rowLocator,
33
- columnName: colName,
34
- columnIndex: idx,
35
- rowIndex: rowIndex,
36
- page: rootLocator.page()
37
- });
38
- }
39
- return resolve(config.cellSelector, rowLocator).nth(idx);
40
- };
41
- smart.toJSON = (options) => __awaiter(void 0, void 0, void 0, function* () {
42
- const result = {};
43
- const page = rootLocator.page();
44
- for (const [col, idx] of map.entries()) {
45
- if ((options === null || options === void 0 ? void 0 : options.columns) && !options.columns.includes(col)) {
46
- continue;
47
- }
48
- // Get the cell locator
49
- const cell = config.strategies.getCellLocator
50
- ? config.strategies.getCellLocator({
51
- row: rowLocator,
52
- columnName: col,
53
- columnIndex: idx,
54
- rowIndex: rowIndex,
55
- page: page
56
- })
57
- : resolve(config.cellSelector, rowLocator).nth(idx);
58
- let targetCell = cell;
59
- // Check if cell exists
60
- const count = yield cell.count();
61
- if (count === 0) {
62
- // Optimization: Check if we are ALREADY at the target cell
63
- if (config.strategies.getActiveCell) {
64
- const active = yield config.strategies.getActiveCell({
65
- config,
66
- root: rootLocator,
67
- page,
68
- resolve
69
- });
70
- if (active && active.rowIndex === rowIndex && active.columnIndex === idx) {
71
- if (config.debug)
72
- console.log(`[SmartRow] Already at target cell (r:${active.rowIndex}, c:${active.columnIndex}), skipping navigation.`);
73
- targetCell = active.locator;
74
- // Skip navigation and go to reading text
75
- const text = yield targetCell.innerText();
76
- result[col] = (text || '').trim();
77
- continue;
78
- }
79
- }
80
- // Cell doesn't exist - navigate to it
81
- if (config.debug) {
82
- console.log(`[SmartRow.toJSON] Cell not found for column "${col}" (index ${idx}), navigating...`);
83
- }
84
- yield config.strategies.cellNavigation({
85
- config: config,
86
- root: rootLocator,
87
- page: page,
88
- resolve: resolve,
89
- column: col,
90
- index: idx,
91
- rowLocator: rowLocator,
92
- rowIndex: rowIndex
93
- });
94
- // Optimization: check if we can get the active cell directly
95
- if (config.strategies.getActiveCell) {
96
- const activeCell = yield config.strategies.getActiveCell({
97
- config,
98
- root: rootLocator,
99
- page,
100
- resolve
101
- });
102
- if (activeCell) {
103
- if (config.debug) {
104
- console.log(`[SmartRow.toJSON] switching to active cell locator (r:${activeCell.rowIndex}, c:${activeCell.columnIndex})`);
105
- }
106
- targetCell = activeCell.locator;
107
- }
108
- }
109
- }
110
- const text = yield targetCell.innerText();
111
- result[col] = (text || '').trim();
112
- }
113
- return result;
114
- });
115
- smart.smartFill = (data, fillOptions) => __awaiter(void 0, void 0, void 0, function* () {
116
- (0, debugUtils_1.logDebug)(config, 'info', 'Filling row', data);
117
- for (const [colName, value] of Object.entries(data)) {
118
- if (value === undefined)
119
- continue;
120
- const colIdx = map.get(colName);
121
- if (colIdx === undefined) {
122
- throw new Error((0, stringUtils_1.buildColumnNotFoundError)(colName, Array.from(map.keys())));
123
- }
124
- yield config.strategies.cellNavigation({
125
- config: config,
126
- root: rootLocator,
127
- page: rootLocator.page(),
128
- resolve: resolve,
129
- column: colName,
130
- index: colIdx,
131
- rowLocator: rowLocator,
132
- rowIndex: rowIndex
133
- });
134
- const strategy = config.strategies.fill || fill_1.FillStrategies.default;
135
- (0, debugUtils_1.logDebug)(config, 'verbose', `Filling cell "${colName}" with value`, value);
136
- yield strategy({
137
- row: smart,
138
- columnName: colName,
139
- value,
140
- index: rowIndex !== null && rowIndex !== void 0 ? rowIndex : -1,
141
- page: rowLocator.page(),
142
- rootLocator,
143
- table: table,
144
- fillOptions
145
- });
146
- // Delay after filling
147
- yield (0, debugUtils_1.debugDelay)(config, 'getCell');
148
- }
149
- (0, debugUtils_1.logDebug)(config, 'info', 'Row fill complete');
150
- });
151
- smart.bringIntoView = () => __awaiter(void 0, void 0, void 0, function* () {
152
- if (rowIndex === undefined) {
153
- throw new Error('Cannot bring row into view - row index is unknown. Use getRowByIndex() instead of getRow().');
154
- }
155
- // Scroll row into view using Playwright's built-in method
156
- yield rowLocator.scrollIntoViewIfNeeded();
157
- });
158
- return smart;
159
- };
160
- exports.createSmartRow = createSmartRow;
@@ -1,18 +0,0 @@
1
- import { StrategyContext } from '../types';
2
- /**
3
- * Defines the contract for a cell navigation strategy.
4
- * It is responsible for ensuring a specific CELL is visible/focused (navigates to row + column),
5
- * typically by scrolling or using keyboard navigation.
6
- */
7
- export type CellNavigationStrategy = (context: StrategyContext & {
8
- column: string;
9
- index: number;
10
- rowIndex?: number;
11
- }) => Promise<void>;
12
- export declare const CellNavigationStrategies: {
13
- /**
14
- * Default strategy: Assumes column is accessible or standard scrolling works.
15
- * No specific action taken other than what Playwright's default locator handling does.
16
- */
17
- default: () => Promise<void>;
18
- };
@@ -1,21 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.CellNavigationStrategies = void 0;
13
- exports.CellNavigationStrategies = {
14
- /**
15
- * Default strategy: Assumes column is accessible or standard scrolling works.
16
- * No specific action taken other than what Playwright's default locator handling does.
17
- */
18
- default: () => __awaiter(void 0, void 0, void 0, function* () {
19
- // No-op
20
- })
21
- };
@@ -1,7 +0,0 @@
1
- import type { FillStrategy } from '../types';
2
- export declare const FillStrategies: {
3
- /**
4
- * Default strategy: Detects input type and fills accordingly (Text, Select, Checkbox, ContentEditable).
5
- */
6
- default: ({ row, columnName, value, fillOptions }: Parameters<FillStrategy>[0]) => Promise<void>;
7
- };