@rickcedwhat/playwright-smart-table 6.20.1-next.6671496 → 6.20.1-next.720a2e5

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.
@@ -24,6 +24,7 @@ export declare class RowFinder<T = any> {
24
24
  exact?: boolean;
25
25
  maxPages?: number;
26
26
  }): Promise<SmartRow<T>>;
27
+ private waitForTableReady;
27
28
  findRows(filters?: Record<string, FilterValue>, options?: {
28
29
  exact?: boolean;
29
30
  maxPages?: number;
@@ -104,6 +104,22 @@ class RowFinder {
104
104
  smartRow[sentinel_1.SENTINEL_ROW] = true;
105
105
  return smartRow;
106
106
  }
107
+ async waitForTableReady() {
108
+ var _a;
109
+ const isTableLoading = (_a = this.config.strategies.loading) === null || _a === void 0 ? void 0 : _a.isTableLoading;
110
+ if (!isTableLoading)
111
+ return;
112
+ const context = {
113
+ root: this.rootLocator,
114
+ config: this.config,
115
+ page: this.rootLocator.page(),
116
+ resolve: this.resolve
117
+ };
118
+ while (await isTableLoading(context)) {
119
+ (0, debugUtils_1.logDebug)(this.config, 'verbose', 'Table is loading... waiting');
120
+ await this.rootLocator.page().waitForTimeout(200);
121
+ }
122
+ }
107
123
  async findRows(filters = {}, options) {
108
124
  var _a, _b, _c;
109
125
  const filtersRecord = filters;
@@ -114,6 +130,7 @@ class RowFinder {
114
130
  (0, debugUtils_1.logDebug)(this.config, 'verbose', `findRows: starting (maxPages=${effectiveMaxPages}, filters=${JSON.stringify(filtersRecord)})`);
115
131
  const tracker = new elementTracker_1.ElementTracker('findRows');
116
132
  try {
133
+ await this.waitForTableReady();
117
134
  const { domFilters, overrideFilters, syntheticFilters } = this.splitFilters(filtersRecord);
118
135
  const hasOverrideFilters = Object.keys(overrideFilters).length > 0;
119
136
  const hasSyntheticFilters = Object.keys(syntheticFilters).length > 0;
@@ -186,26 +203,13 @@ class RowFinder {
186
203
  return (0, smartRowArray_1.createSmartRowArray)(allRows);
187
204
  }
188
205
  async findRowLocator(filters, options = {}) {
189
- var _a, _b, _c;
206
+ var _a, _b;
190
207
  const map = await this.tableMapper.getMap();
191
208
  const effectiveMaxPages = (_a = options.maxPages) !== null && _a !== void 0 ? _a : this.config.maxPages;
192
209
  let pagesScanned = 1;
193
210
  (0, debugUtils_1.logDebug)(this.config, 'verbose', `Looking for row: ${JSON.stringify(filters)} (MaxPages: ${effectiveMaxPages})`);
194
211
  while (true) {
195
- // Check Loading
196
- if ((_b = this.config.strategies.loading) === null || _b === void 0 ? void 0 : _b.isTableLoading) {
197
- const isLoading = await this.config.strategies.loading.isTableLoading({
198
- root: this.rootLocator,
199
- config: this.config,
200
- page: this.rootLocator.page(),
201
- resolve: this.resolve
202
- });
203
- if (isLoading) {
204
- (0, debugUtils_1.logDebug)(this.config, 'verbose', 'Table is loading... waiting');
205
- await this.rootLocator.page().waitForTimeout(200);
206
- continue;
207
- }
208
- }
212
+ await this.waitForTableReady();
209
213
  const allRows = this.resolve(this.config.rowSelector, this.rootLocator);
210
214
  const { domFilters, overrideFilters, syntheticFilters } = this.splitFilters(filters);
211
215
  const hasPostFilters = Object.keys(overrideFilters).length > 0 || Object.keys(syntheticFilters).length > 0;
@@ -242,7 +246,7 @@ class RowFinder {
242
246
  (0, debugUtils_1.logDebug)(this.config, 'verbose', `Page ${this.tableState.currentPageIndex}: Not found. Attempting pagination...`);
243
247
  // Default to single-step goNext; bulk is opt-in via useBulkPagination: true (#349).
244
248
  // Bulk-by-default made findRow jump past the page holding the target row.
245
- const useBulk = options.useBulkPagination === true && !!((_c = this.config.strategies.pagination) === null || _c === void 0 ? void 0 : _c.goNextBulk);
249
+ const useBulk = options.useBulkPagination === true && !!((_b = this.config.strategies.pagination) === null || _b === void 0 ? void 0 : _b.goNextBulk);
246
250
  const prevPage = this.tableState.currentPageIndex;
247
251
  const didLoadMore = await this.advancePage(useBulk);
248
252
  if (didLoadMore) {
@@ -63,9 +63,12 @@ async function runMap(env, callback, options = {}, label = 'map') {
63
63
  // #384: overscan rows ABOVE the visible range have already scrolled past and will never
64
64
  // re-enter the viewport — collect them now. Only defer rows BELOW the visible range
65
65
  // (they'll scroll into view on a later page).
66
+ //
67
+ // #417 follow-up: skip viewport filtering on the final scan — there are no more pages
68
+ // to defer to, so collect all remaining unseen rows regardless of visibility.
66
69
  let candidateIndices = allIndices;
67
70
  const getVisibleRowIndices = (_f = env.config.strategies.viewport) === null || _f === void 0 ? void 0 : _f.getVisibleRowIndices;
68
- if (getVisibleRowIndices) {
71
+ if (getVisibleRowIndices && !reachedEnd) {
69
72
  const visible = new Set(await getVisibleRowIndices(env.getContext()));
70
73
  const minVisible = visible.size > 0 ? Math.min(...visible) : Infinity;
71
74
  candidateIndices = allIndices.filter(idx => visible.has(idx) || idx < minVisible);
@@ -3,4 +3,4 @@
3
3
  * Generated by scripts/embed-version.mjs from package.json
4
4
  */
5
5
  /** Semver of this package. Use in logs or diagnostics to confirm the installed build. */
6
- export declare const PLAYWRIGHT_SMART_TABLE_VERSION: "6.20.1-next.6671496";
6
+ export declare const PLAYWRIGHT_SMART_TABLE_VERSION: "6.20.1-next.720a2e5";
@@ -6,4 +6,4 @@ exports.PLAYWRIGHT_SMART_TABLE_VERSION = void 0;
6
6
  * Generated by scripts/embed-version.mjs from package.json
7
7
  */
8
8
  /** Semver of this package. Use in logs or diagnostics to confirm the installed build. */
9
- exports.PLAYWRIGHT_SMART_TABLE_VERSION = "6.20.1-next.6671496";
9
+ exports.PLAYWRIGHT_SMART_TABLE_VERSION = "6.20.1-next.720a2e5";
@@ -83,6 +83,7 @@ exports.PaginationStrategies = {
83
83
  const scrollTarget = options.scrollTarget
84
84
  ? resolve(options.scrollTarget, root)
85
85
  : root;
86
+ const beforeScrollTop = await scrollTarget.evaluate((el) => el.scrollTop);
86
87
  const doScroll = async () => {
87
88
  const box = await scrollTarget.boundingBox();
88
89
  const scrollValue = amount * directionMultiplier;
@@ -98,8 +99,16 @@ exports.PaginationStrategies = {
98
99
  await page.mouse.wheel(0, scrollValue);
99
100
  }
100
101
  };
101
- // Stabilization: Wait
102
- return await stabilization(context, doScroll);
102
+ // Stabilization: Wait for content to settle
103
+ const stabilizationResult = await stabilization(context, doScroll);
104
+ // EOF detection: use scroll position, not stabilization result.
105
+ // Stabilization may time out for recycling virtualizers when the scroll
106
+ // amount is small enough to stay within the overscan window (no new rows
107
+ // rendered), but the scroll position still changed — we haven't reached
108
+ // the end of the data.
109
+ const afterScrollTop = await scrollTarget.evaluate((el) => el.scrollTop);
110
+ const scrollMoved = Math.abs(afterScrollTop - beforeScrollTop) >= 1;
111
+ return scrollMoved || stabilizationResult;
103
112
  };
104
113
  };
105
114
  const createGoToFirst = () => {
package/dist/useTable.js CHANGED
@@ -301,7 +301,7 @@ const useTable = (rootLocator, configOptions = {}) => {
301
301
  return resolve(config.headerSelector, rootLocator).nth(idx);
302
302
  },
303
303
  countRows: async (filters, options) => {
304
- var _a, _b, _c, _d;
304
+ var _a, _b, _c, _d, _e;
305
305
  if (tableState.empty)
306
306
  return 0;
307
307
  await _autoInit();
@@ -359,6 +359,15 @@ const useTable = (rootLocator, configOptions = {}) => {
359
359
  }
360
360
  return count;
361
361
  };
362
+ // Wait for table to finish loading before counting
363
+ const isTableLoading = (_e = config.strategies.loading) === null || _e === void 0 ? void 0 : _e.isTableLoading;
364
+ if (isTableLoading) {
365
+ const ctx = createStrategyContext();
366
+ while (await isTableLoading(ctx)) {
367
+ log('countRows: table is loading... waiting');
368
+ await rootLocator.page().waitForTimeout(200);
369
+ }
370
+ }
362
371
  if (!hasPagination) {
363
372
  log(`countRows: counting rows in current viewport (no pagination)${hasFilters ? ` filters=${safeStringify(filtersRecord)}` : ''}`);
364
373
  if (!hasPostFilters)
@@ -18,7 +18,8 @@ class ElementTracker {
18
18
  const seenMap = win[trackerId];
19
19
  const newIndices = [];
20
20
  elements.forEach((el, index) => {
21
- const signature = el.textContent || '';
21
+ const htmlEl = el;
22
+ const signature = htmlEl.offsetTop + '|' + (el.textContent || '');
22
23
  if (seenMap.get(el) !== signature) {
23
24
  newIndices.push(index);
24
25
  }
@@ -39,8 +40,10 @@ class ElementTracker {
39
40
  const seenMap = win[trackerId];
40
41
  for (const index of indicesToCommit) {
41
42
  const el = elements[index];
42
- if (el)
43
- seenMap.set(el, el.textContent || '');
43
+ if (el) {
44
+ const htmlEl = el;
45
+ seenMap.set(el, htmlEl.offsetTop + '|' + (el.textContent || ''));
46
+ }
44
47
  }
45
48
  }, [this.id, indices]);
46
49
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rickcedwhat/playwright-smart-table",
3
- "version": "6.20.1-next.6671496",
3
+ "version": "6.20.1-next.720a2e5",
4
4
  "description": "Smart, column-aware table interactions for Playwright",
5
5
  "author": "Cedrick Catalan",
6
6
  "license": "MIT",