@rickcedwhat/playwright-smart-table 2.2.0 → 2.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 +3 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/strategies/index.d.ts +2 -15
- package/dist/strategies/index.js +16 -109
- package/dist/strategies/pagination.d.ts +32 -0
- package/dist/strategies/pagination.js +72 -0
- package/dist/strategies/sorting.d.ts +12 -0
- package/dist/strategies/sorting.js +68 -0
- package/dist/typeContext.d.ts +1 -1
- package/dist/typeContext.js +53 -2
- package/dist/types.d.ts +48 -2
- package/dist/useTable.d.ts +37 -1
- package/dist/useTable.js +74 -1
- package/dist/utils.d.ts +7 -0
- package/dist/utils.js +29 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -480,7 +480,7 @@ export type PaginationStrategy = (context: TableContext) => Promise<boolean>;
|
|
|
480
480
|
```typescript
|
|
481
481
|
export interface TableContext {
|
|
482
482
|
root: Locator;
|
|
483
|
-
config:
|
|
483
|
+
config: FinalTableConfig;
|
|
484
484
|
page: Page;
|
|
485
485
|
resolve: (selector: Selector, parent: Locator | Page) => Locator;
|
|
486
486
|
}
|
|
@@ -513,7 +513,7 @@ await table.generateStrategyPrompt({ output: 'console' });
|
|
|
513
513
|
export interface PromptOptions {
|
|
514
514
|
/**
|
|
515
515
|
* Output Strategy:
|
|
516
|
-
* - 'error': Throws an error with the prompt (
|
|
516
|
+
* - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).
|
|
517
517
|
* - 'console': Standard console logs (Default).
|
|
518
518
|
*/
|
|
519
519
|
output?: 'console' | 'error';
|
|
@@ -563,6 +563,7 @@ export interface TableConfig {
|
|
|
563
563
|
headerSelector?: Selector;
|
|
564
564
|
cellSelector?: Selector;
|
|
565
565
|
pagination?: PaginationStrategy;
|
|
566
|
+
sorting?: SortingStrategy;
|
|
566
567
|
maxPages?: number;
|
|
567
568
|
/**
|
|
568
569
|
* Hook to rename columns dynamically.
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -16,4 +16,3 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./useTable"), exports);
|
|
18
18
|
__exportStar(require("./types"), exports);
|
|
19
|
-
__exportStar(require("./strategies"), exports);
|
|
@@ -1,15 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
/**
|
|
4
|
-
* Strategy: Clicks a "Next" button and waits for the first row of data to change.
|
|
5
|
-
*/
|
|
6
|
-
clickNext: (nextButtonSelector: Selector, timeout?: number) => PaginationStrategy;
|
|
7
|
-
/**
|
|
8
|
-
* Strategy: Clicks a "Load More" button and waits for the row count to increase.
|
|
9
|
-
*/
|
|
10
|
-
clickLoadMore: (buttonSelector: Selector, timeout?: number) => PaginationStrategy;
|
|
11
|
-
/**
|
|
12
|
-
* Strategy: Scrolls to the bottom and waits for more rows to appear.
|
|
13
|
-
*/
|
|
14
|
-
infiniteScroll: (timeout?: number) => PaginationStrategy;
|
|
15
|
-
};
|
|
1
|
+
export * from './pagination';
|
|
2
|
+
export * from './sorting';
|
package/dist/strategies/index.js
CHANGED
|
@@ -1,112 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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.TableStrategies = void 0;
|
|
13
|
-
/**
|
|
14
|
-
* Internal helper to wait for a condition to be met.
|
|
15
|
-
* Replaces the dependency on 'expect(...).toPass()' to ensure compatibility
|
|
16
|
-
* with environments like QA Wolf where 'expect' is not globally available.
|
|
17
|
-
*/
|
|
18
|
-
const waitForCondition = (predicate, timeout, page // Context page for pauses
|
|
19
|
-
) => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
|
-
const startTime = Date.now();
|
|
21
|
-
while (Date.now() - startTime < timeout) {
|
|
22
|
-
if (yield predicate()) {
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
// Wait 100ms before next check (Standard Polling)
|
|
26
|
-
yield page.waitForTimeout(100).catch(() => new Promise(r => setTimeout(r, 100)));
|
|
27
|
-
}
|
|
28
|
-
return false;
|
|
29
|
-
});
|
|
30
|
-
exports.TableStrategies = {
|
|
31
|
-
/**
|
|
32
|
-
* Strategy: Clicks a "Next" button and waits for the first row of data to change.
|
|
33
|
-
*/
|
|
34
|
-
clickNext: (nextButtonSelector, timeout = 5000) => {
|
|
35
|
-
return (_a) => __awaiter(void 0, [_a], void 0, function* ({ root, config, resolve, page }) {
|
|
36
|
-
const nextBtn = resolve(nextButtonSelector, root).first();
|
|
37
|
-
// Debug log (can be verbose, maybe useful for debugging only)
|
|
38
|
-
// console.log(`[Strategy: clickNext] Checking button...`);
|
|
39
|
-
// Check if button exists/enabled before clicking.
|
|
40
|
-
// We do NOT wait here because if the button isn't visible/enabled,
|
|
41
|
-
// we assume we reached the last page.
|
|
42
|
-
if (!(yield nextBtn.isVisible())) {
|
|
43
|
-
console.log(`[Strategy: clickNext] Button not visible. Stopping pagination.`);
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
if (!(yield nextBtn.isEnabled())) {
|
|
47
|
-
console.log(`[Strategy: clickNext] Button disabled. Stopping pagination.`);
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
// 1. Snapshot current state
|
|
51
|
-
const firstRow = resolve(config.rowSelector, root).first();
|
|
52
|
-
const oldText = yield firstRow.innerText().catch(() => "");
|
|
53
|
-
// 2. Click
|
|
54
|
-
console.log(`[Strategy: clickNext] Clicking next button...`);
|
|
55
|
-
try {
|
|
56
|
-
yield nextBtn.click({ timeout: 2000 });
|
|
57
|
-
}
|
|
58
|
-
catch (e) {
|
|
59
|
-
console.warn(`[Strategy: clickNext] Click failed (blocked or detached): ${e}`);
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
// 3. Smart Wait (Polling)
|
|
63
|
-
const success = yield waitForCondition(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
64
|
-
const newText = yield firstRow.innerText().catch(() => "");
|
|
65
|
-
return newText !== oldText;
|
|
66
|
-
}), timeout, page);
|
|
67
|
-
if (!success) {
|
|
68
|
-
console.warn(`[Strategy: clickNext] Warning: Table content did not change after clicking Next.`);
|
|
69
|
-
}
|
|
70
|
-
return success;
|
|
71
|
-
});
|
|
72
|
-
},
|
|
73
|
-
/**
|
|
74
|
-
* Strategy: Clicks a "Load More" button and waits for the row count to increase.
|
|
75
|
-
*/
|
|
76
|
-
clickLoadMore: (buttonSelector, timeout = 5000) => {
|
|
77
|
-
return (_a) => __awaiter(void 0, [_a], void 0, function* ({ root, config, resolve, page }) {
|
|
78
|
-
const loadMoreBtn = resolve(buttonSelector, root).first();
|
|
79
|
-
if (!(yield loadMoreBtn.isVisible()) || !(yield loadMoreBtn.isEnabled())) {
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
// 1. Snapshot count
|
|
83
|
-
const rows = resolve(config.rowSelector, root);
|
|
84
|
-
const oldCount = yield rows.count();
|
|
85
|
-
// 2. Click
|
|
86
|
-
yield loadMoreBtn.click();
|
|
87
|
-
// 3. Smart Wait (Polling)
|
|
88
|
-
return yield waitForCondition(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
89
|
-
const newCount = yield rows.count();
|
|
90
|
-
return newCount > oldCount;
|
|
91
|
-
}), timeout, page);
|
|
92
|
-
});
|
|
93
|
-
},
|
|
94
|
-
/**
|
|
95
|
-
* Strategy: Scrolls to the bottom and waits for more rows to appear.
|
|
96
|
-
*/
|
|
97
|
-
infiniteScroll: (timeout = 5000) => {
|
|
98
|
-
return (_a) => __awaiter(void 0, [_a], void 0, function* ({ root, config, resolve, page }) {
|
|
99
|
-
const rows = resolve(config.rowSelector, root);
|
|
100
|
-
const oldCount = yield rows.count();
|
|
101
|
-
if (oldCount === 0)
|
|
102
|
-
return false;
|
|
103
|
-
// 1. Trigger Scroll
|
|
104
|
-
yield rows.last().scrollIntoViewIfNeeded();
|
|
105
|
-
// 2. Smart Wait (Polling)
|
|
106
|
-
return yield waitForCondition(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
107
|
-
const newCount = yield rows.count();
|
|
108
|
-
return newCount > oldCount;
|
|
109
|
-
}), timeout, page);
|
|
110
|
-
});
|
|
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]; } };
|
|
111
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);
|
|
112
15
|
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// src/strategies/index.ts
|
|
18
|
+
__exportStar(require("./pagination"), exports);
|
|
19
|
+
__exportStar(require("./sorting"), exports);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { PaginationStrategy, Selector } from '../types';
|
|
2
|
+
export declare const PaginationStrategies: {
|
|
3
|
+
/**
|
|
4
|
+
* Strategy: Clicks a "Next" button and waits for the first row of data to change.
|
|
5
|
+
*/
|
|
6
|
+
clickNext: (nextButtonSelector: Selector, timeout?: number) => PaginationStrategy;
|
|
7
|
+
/**
|
|
8
|
+
* Strategy: Clicks a "Load More" button and waits for the row count to increase.
|
|
9
|
+
*/
|
|
10
|
+
clickLoadMore: (buttonSelector: Selector, timeout?: number) => PaginationStrategy;
|
|
11
|
+
/**
|
|
12
|
+
* Strategy: Scrolls to the bottom and waits for more rows to appear.
|
|
13
|
+
*/
|
|
14
|
+
infiniteScroll: (timeout?: number) => PaginationStrategy;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* @deprecated Use `PaginationStrategies` instead. This alias will be removed in a future major version.
|
|
18
|
+
*/
|
|
19
|
+
export declare const TableStrategies: {
|
|
20
|
+
/**
|
|
21
|
+
* Strategy: Clicks a "Next" button and waits for the first row of data to change.
|
|
22
|
+
*/
|
|
23
|
+
clickNext: (nextButtonSelector: Selector, timeout?: number) => PaginationStrategy;
|
|
24
|
+
/**
|
|
25
|
+
* Strategy: Clicks a "Load More" button and waits for the row count to increase.
|
|
26
|
+
*/
|
|
27
|
+
clickLoadMore: (buttonSelector: Selector, timeout?: number) => PaginationStrategy;
|
|
28
|
+
/**
|
|
29
|
+
* Strategy: Scrolls to the bottom and waits for more rows to appear.
|
|
30
|
+
*/
|
|
31
|
+
infiniteScroll: (timeout?: number) => PaginationStrategy;
|
|
32
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
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.TableStrategies = exports.PaginationStrategies = void 0;
|
|
13
|
+
const utils_1 = require("../utils");
|
|
14
|
+
exports.PaginationStrategies = {
|
|
15
|
+
/**
|
|
16
|
+
* Strategy: Clicks a "Next" button and waits for the first row of data to change.
|
|
17
|
+
*/
|
|
18
|
+
clickNext: (nextButtonSelector, timeout = 5000) => {
|
|
19
|
+
return (_a) => __awaiter(void 0, [_a], void 0, function* ({ root, config, resolve, page }) {
|
|
20
|
+
const nextBtn = resolve(nextButtonSelector, root).first();
|
|
21
|
+
if (!(yield nextBtn.isVisible()) || !(yield nextBtn.isEnabled())) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const firstRow = resolve(config.rowSelector, root).first();
|
|
25
|
+
const oldText = yield firstRow.innerText().catch(() => "");
|
|
26
|
+
yield nextBtn.click({ timeout: 2000 }).catch(() => { });
|
|
27
|
+
const success = yield (0, utils_1.waitForCondition)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
|
+
const newText = yield firstRow.innerText().catch(() => "");
|
|
29
|
+
return newText !== oldText;
|
|
30
|
+
}), timeout, page);
|
|
31
|
+
return success;
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* Strategy: Clicks a "Load More" button and waits for the row count to increase.
|
|
36
|
+
*/
|
|
37
|
+
clickLoadMore: (buttonSelector, timeout = 5000) => {
|
|
38
|
+
return (_a) => __awaiter(void 0, [_a], void 0, function* ({ root, config, resolve, page }) {
|
|
39
|
+
const loadMoreBtn = resolve(buttonSelector, root).first();
|
|
40
|
+
if (!(yield loadMoreBtn.isVisible()) || !(yield loadMoreBtn.isEnabled())) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const rows = resolve(config.rowSelector, root);
|
|
44
|
+
const oldCount = yield rows.count();
|
|
45
|
+
yield loadMoreBtn.click();
|
|
46
|
+
return yield (0, utils_1.waitForCondition)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
+
const newCount = yield rows.count();
|
|
48
|
+
return newCount > oldCount;
|
|
49
|
+
}), timeout, page);
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
/**
|
|
53
|
+
* Strategy: Scrolls to the bottom and waits for more rows to appear.
|
|
54
|
+
*/
|
|
55
|
+
infiniteScroll: (timeout = 5000) => {
|
|
56
|
+
return (_a) => __awaiter(void 0, [_a], void 0, function* ({ root, config, resolve, page }) {
|
|
57
|
+
const rows = resolve(config.rowSelector, root);
|
|
58
|
+
const oldCount = yield rows.count();
|
|
59
|
+
if (oldCount === 0)
|
|
60
|
+
return false;
|
|
61
|
+
yield rows.last().scrollIntoViewIfNeeded();
|
|
62
|
+
return yield (0, utils_1.waitForCondition)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
63
|
+
const newCount = yield rows.count();
|
|
64
|
+
return newCount > oldCount;
|
|
65
|
+
}), timeout, page);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* @deprecated Use `PaginationStrategies` instead. This alias will be removed in a future major version.
|
|
71
|
+
*/
|
|
72
|
+
exports.TableStrategies = exports.PaginationStrategies;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SortingStrategy } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* A collection of pre-built sorting strategies.
|
|
4
|
+
*/
|
|
5
|
+
export declare const SortingStrategies: {
|
|
6
|
+
/**
|
|
7
|
+
* A sorting strategy that interacts with column headers based on ARIA attributes.
|
|
8
|
+
* - `doSort`: Clicks the header repeatedly until the desired `aria-sort` state is achieved.
|
|
9
|
+
* - `getSortState`: Reads the `aria-sort` attribute from the header.
|
|
10
|
+
*/
|
|
11
|
+
AriaSort: () => SortingStrategy;
|
|
12
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
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.SortingStrategies = void 0;
|
|
13
|
+
/**
|
|
14
|
+
* A collection of pre-built sorting strategies.
|
|
15
|
+
*/
|
|
16
|
+
exports.SortingStrategies = {
|
|
17
|
+
/**
|
|
18
|
+
* A sorting strategy that interacts with column headers based on ARIA attributes.
|
|
19
|
+
* - `doSort`: Clicks the header repeatedly until the desired `aria-sort` state is achieved.
|
|
20
|
+
* - `getSortState`: Reads the `aria-sort` attribute from the header.
|
|
21
|
+
*/
|
|
22
|
+
AriaSort: () => {
|
|
23
|
+
return {
|
|
24
|
+
doSort(_a) {
|
|
25
|
+
return __awaiter(this, arguments, void 0, function* ({ columnName, direction, context }) {
|
|
26
|
+
const { resolve, config, root } = context;
|
|
27
|
+
const headerLoc = resolve(config.headerSelector, root);
|
|
28
|
+
const headers = yield headerLoc.all();
|
|
29
|
+
const headerTexts = yield Promise.all(headers.map(h => h.innerText()));
|
|
30
|
+
const columnIndex = headerTexts.findIndex(text => text.trim() === columnName);
|
|
31
|
+
if (columnIndex === -1) {
|
|
32
|
+
throw new Error(`[AriaSort] Header with text "${columnName}" not found.`);
|
|
33
|
+
}
|
|
34
|
+
const targetHeader = headers[columnIndex];
|
|
35
|
+
// Click repeatedly to cycle through sort states
|
|
36
|
+
for (let i = 0; i < 3; i++) { // Max 3 clicks to prevent infinite loops (none -> asc -> desc)
|
|
37
|
+
const currentState = yield targetHeader.getAttribute('aria-sort');
|
|
38
|
+
const mappedState = currentState === 'ascending' ? 'asc' : currentState === 'descending' ? 'desc' : 'none';
|
|
39
|
+
if (mappedState === direction) {
|
|
40
|
+
return; // Desired state achieved
|
|
41
|
+
}
|
|
42
|
+
yield targetHeader.click();
|
|
43
|
+
}
|
|
44
|
+
throw new Error(`[AriaSort] Could not achieve sort direction "${direction}" for column "${columnName}" after 3 clicks.`);
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
getSortState(_a) {
|
|
48
|
+
return __awaiter(this, arguments, void 0, function* ({ columnName, context }) {
|
|
49
|
+
const { resolve, config, root } = context;
|
|
50
|
+
const headerLoc = resolve(config.headerSelector, root);
|
|
51
|
+
const headers = yield headerLoc.all();
|
|
52
|
+
const headerTexts = yield Promise.all(headers.map(h => h.innerText()));
|
|
53
|
+
const columnIndex = headerTexts.findIndex(text => text.trim() === columnName);
|
|
54
|
+
if (columnIndex === -1) {
|
|
55
|
+
return 'none'; // Header not found, so it's not sorted
|
|
56
|
+
}
|
|
57
|
+
const targetHeader = headers[columnIndex];
|
|
58
|
+
const ariaSort = yield targetHeader.getAttribute('aria-sort');
|
|
59
|
+
if (ariaSort === 'ascending')
|
|
60
|
+
return 'asc';
|
|
61
|
+
if (ariaSort === 'descending')
|
|
62
|
+
return 'desc';
|
|
63
|
+
return 'none';
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
};
|
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 = "\nexport type Selector = string | ((root: Locator | Page) => Locator);\n\nexport type SmartRow = Omit<Locator, 'fill'> & {\n getCell(column: string): Locator;\n toJSON(): Promise<Record<string, string>>;\n /**\n * Fills the row with data. Automatically detects input types (text input, select, checkbox, etc.).\n */\n fill: (data: Record<string, any>, options?: FillOptions) => Promise<void>;\n};\n\nexport interface TableContext {\n root: Locator;\n config:
|
|
6
|
+
export declare const TYPE_CONTEXT = "\nexport type Selector = string | ((root: Locator | Page) => Locator);\n\nexport type SmartRow = Omit<Locator, 'fill'> & {\n getCell(column: string): Locator;\n toJSON(): Promise<Record<string, string>>;\n /**\n * Fills the row with data. Automatically detects input types (text input, select, checkbox, etc.).\n */\n fill: (data: Record<string, any>, options?: FillOptions) => Promise<void>;\n};\n\nexport type StrategyContext = TableContext;\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\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 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 interface TableConfig {\n rowSelector?: Selector;\n headerSelector?: Selector;\n cellSelector?: Selector;\n pagination?: PaginationStrategy;\n sorting?: SortingStrategy;\n maxPages?: number;\n /**\n * Hook to rename columns dynamically.\n * * @param args.text - The default innerText of the header.\n * @param args.index - The column index.\n * @param args.locator - The specific header cell locator.\n */\n headerTransformer?: (args: { text: string, index: number, locator: Locator }) => string | Promise<string>;\n autoScroll?: boolean;\n /**\n * Enable debug mode to log internal state to console.\n */\n debug?: boolean;\n /**\n * Strategy to reset the table to the first page.\n * Called when table.reset() is invoked.\n */\n onReset?: (context: TableContext) => Promise<void>;\n}\n\n/**\n * Represents the final, resolved table configuration after default values have been applied.\n * All optional properties from TableConfig are now required, except for `sorting`.\n */\nexport type FinalTableConfig = Required<Omit<TableConfig, 'sorting'>> & {\n sorting?: SortingStrategy;\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 * Columns not specified here will use auto-detection.\n */\n inputMappers?: Record<string, (cell: Locator) => Locator>;\n}\n\nexport interface TableResult {\n getHeaders: () => Promise<string[]>;\n getHeaderCell: (columnName: string) => Promise<Locator>;\n\n getByRow: <T extends { asJSON?: boolean }>(\n filters: Record<string, string | RegExp | number>, \n options?: { exact?: boolean, maxPages?: number } & T\n ) => Promise<T['asJSON'] extends true ? Record<string, string> : SmartRow>;\n\n getAllRows: <T extends { asJSON?: boolean }>(\n options?: { filter?: Record<string, any>, exact?: boolean } & T\n ) => Promise<T['asJSON'] extends true ? Record<string, string>[] : SmartRow[]>;\n\n generateConfigPrompt: (options?: PromptOptions) => Promise<void>;\n generateStrategyPrompt: (options?: PromptOptions) => Promise<void>;\n\n /**\n * Resets the table state (clears cache, flags) and invokes the onReset strategy.\n */\n reset: () => 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";
|
package/dist/typeContext.js
CHANGED
|
@@ -18,9 +18,33 @@ export type SmartRow = Omit<Locator, 'fill'> & {
|
|
|
18
18
|
fill: (data: Record<string, any>, options?: FillOptions) => Promise<void>;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
+
export type StrategyContext = TableContext;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Defines the contract for a sorting strategy.
|
|
25
|
+
*/
|
|
26
|
+
export interface SortingStrategy {
|
|
27
|
+
/**
|
|
28
|
+
* Performs the sort action on a column.
|
|
29
|
+
*/
|
|
30
|
+
doSort(options: {
|
|
31
|
+
columnName: string;
|
|
32
|
+
direction: 'asc' | 'desc';
|
|
33
|
+
context: StrategyContext;
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Retrieves the current sort state of a column.
|
|
38
|
+
*/
|
|
39
|
+
getSortState(options: {
|
|
40
|
+
columnName: string;
|
|
41
|
+
context: StrategyContext;
|
|
42
|
+
}): Promise<'asc' | 'desc' | 'none'>;
|
|
43
|
+
}
|
|
44
|
+
|
|
21
45
|
export interface TableContext {
|
|
22
46
|
root: Locator;
|
|
23
|
-
config:
|
|
47
|
+
config: FinalTableConfig;
|
|
24
48
|
page: Page;
|
|
25
49
|
resolve: (selector: Selector, parent: Locator | Page) => Locator;
|
|
26
50
|
}
|
|
@@ -30,7 +54,7 @@ export type PaginationStrategy = (context: TableContext) => Promise<boolean>;
|
|
|
30
54
|
export interface PromptOptions {
|
|
31
55
|
/**
|
|
32
56
|
* Output Strategy:
|
|
33
|
-
* - 'error': Throws an error with the prompt (
|
|
57
|
+
* - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).
|
|
34
58
|
* - 'console': Standard console logs (Default).
|
|
35
59
|
*/
|
|
36
60
|
output?: 'console' | 'error';
|
|
@@ -42,6 +66,7 @@ export interface TableConfig {
|
|
|
42
66
|
headerSelector?: Selector;
|
|
43
67
|
cellSelector?: Selector;
|
|
44
68
|
pagination?: PaginationStrategy;
|
|
69
|
+
sorting?: SortingStrategy;
|
|
45
70
|
maxPages?: number;
|
|
46
71
|
/**
|
|
47
72
|
* Hook to rename columns dynamically.
|
|
@@ -62,6 +87,14 @@ export interface TableConfig {
|
|
|
62
87
|
onReset?: (context: TableContext) => Promise<void>;
|
|
63
88
|
}
|
|
64
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Represents the final, resolved table configuration after default values have been applied.
|
|
92
|
+
* All optional properties from TableConfig are now required, except for \`sorting\`.
|
|
93
|
+
*/
|
|
94
|
+
export type FinalTableConfig = Required<Omit<TableConfig, 'sorting'>> & {
|
|
95
|
+
sorting?: SortingStrategy;
|
|
96
|
+
};
|
|
97
|
+
|
|
65
98
|
export interface FillOptions {
|
|
66
99
|
/**
|
|
67
100
|
* Custom input mappers for specific columns.
|
|
@@ -96,5 +129,23 @@ export interface TableResult {
|
|
|
96
129
|
* Scans a specific column across all pages and returns the values.
|
|
97
130
|
*/
|
|
98
131
|
getColumnValues: <V = string>(column: string, options?: { mapper?: (cell: Locator) => Promise<V> | V, maxPages?: number }) => Promise<V[]>;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Provides access to sorting actions and assertions.
|
|
135
|
+
*/
|
|
136
|
+
sorting: {
|
|
137
|
+
/**
|
|
138
|
+
* Applies the configured sorting strategy to the specified column.
|
|
139
|
+
* @param columnName The name of the column to sort.
|
|
140
|
+
* @param direction The direction to sort ('asc' or 'desc').
|
|
141
|
+
*/
|
|
142
|
+
apply(columnName: string, direction: 'asc' | 'desc'): Promise<void>;
|
|
143
|
+
/**
|
|
144
|
+
* Gets the current sort state of a column using the configured sorting strategy.
|
|
145
|
+
* @param columnName The name of the column to check.
|
|
146
|
+
* @returns A promise that resolves to 'asc', 'desc', or 'none'.
|
|
147
|
+
*/
|
|
148
|
+
getState(columnName: string): Promise<'asc' | 'desc' | 'none'>;
|
|
149
|
+
};
|
|
99
150
|
}
|
|
100
151
|
`;
|
package/dist/types.d.ts
CHANGED
|
@@ -8,9 +8,30 @@ export type SmartRow = Omit<Locator, 'fill'> & {
|
|
|
8
8
|
*/
|
|
9
9
|
fill: (data: Record<string, any>, options?: FillOptions) => Promise<void>;
|
|
10
10
|
};
|
|
11
|
+
export type StrategyContext = TableContext;
|
|
12
|
+
/**
|
|
13
|
+
* Defines the contract for a sorting strategy.
|
|
14
|
+
*/
|
|
15
|
+
export interface SortingStrategy {
|
|
16
|
+
/**
|
|
17
|
+
* Performs the sort action on a column.
|
|
18
|
+
*/
|
|
19
|
+
doSort(options: {
|
|
20
|
+
columnName: string;
|
|
21
|
+
direction: 'asc' | 'desc';
|
|
22
|
+
context: StrategyContext;
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Retrieves the current sort state of a column.
|
|
26
|
+
*/
|
|
27
|
+
getSortState(options: {
|
|
28
|
+
columnName: string;
|
|
29
|
+
context: StrategyContext;
|
|
30
|
+
}): Promise<'asc' | 'desc' | 'none'>;
|
|
31
|
+
}
|
|
11
32
|
export interface TableContext {
|
|
12
33
|
root: Locator;
|
|
13
|
-
config:
|
|
34
|
+
config: FinalTableConfig;
|
|
14
35
|
page: Page;
|
|
15
36
|
resolve: (selector: Selector, parent: Locator | Page) => Locator;
|
|
16
37
|
}
|
|
@@ -18,7 +39,7 @@ export type PaginationStrategy = (context: TableContext) => Promise<boolean>;
|
|
|
18
39
|
export interface PromptOptions {
|
|
19
40
|
/**
|
|
20
41
|
* Output Strategy:
|
|
21
|
-
* - 'error': Throws an error with the prompt (
|
|
42
|
+
* - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).
|
|
22
43
|
* - 'console': Standard console logs (Default).
|
|
23
44
|
*/
|
|
24
45
|
output?: 'console' | 'error';
|
|
@@ -29,6 +50,7 @@ export interface TableConfig {
|
|
|
29
50
|
headerSelector?: Selector;
|
|
30
51
|
cellSelector?: Selector;
|
|
31
52
|
pagination?: PaginationStrategy;
|
|
53
|
+
sorting?: SortingStrategy;
|
|
32
54
|
maxPages?: number;
|
|
33
55
|
/**
|
|
34
56
|
* Hook to rename columns dynamically.
|
|
@@ -52,6 +74,13 @@ export interface TableConfig {
|
|
|
52
74
|
*/
|
|
53
75
|
onReset?: (context: TableContext) => Promise<void>;
|
|
54
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Represents the final, resolved table configuration after default values have been applied.
|
|
79
|
+
* All optional properties from TableConfig are now required, except for `sorting`.
|
|
80
|
+
*/
|
|
81
|
+
export type FinalTableConfig = Required<Omit<TableConfig, 'sorting'>> & {
|
|
82
|
+
sorting?: SortingStrategy;
|
|
83
|
+
};
|
|
55
84
|
export interface FillOptions {
|
|
56
85
|
/**
|
|
57
86
|
* Custom input mappers for specific columns.
|
|
@@ -88,4 +117,21 @@ export interface TableResult {
|
|
|
88
117
|
mapper?: (cell: Locator) => Promise<V> | V;
|
|
89
118
|
maxPages?: number;
|
|
90
119
|
}) => Promise<V[]>;
|
|
120
|
+
/**
|
|
121
|
+
* Provides access to sorting actions and assertions.
|
|
122
|
+
*/
|
|
123
|
+
sorting: {
|
|
124
|
+
/**
|
|
125
|
+
* Applies the configured sorting strategy to the specified column.
|
|
126
|
+
* @param columnName The name of the column to sort.
|
|
127
|
+
* @param direction The direction to sort ('asc' or 'desc').
|
|
128
|
+
*/
|
|
129
|
+
apply(columnName: string, direction: 'asc' | 'desc'): Promise<void>;
|
|
130
|
+
/**
|
|
131
|
+
* Gets the current sort state of a column using the configured sorting strategy.
|
|
132
|
+
* @param columnName The name of the column to check.
|
|
133
|
+
* @returns A promise that resolves to 'asc', 'desc', or 'none'.
|
|
134
|
+
*/
|
|
135
|
+
getState(columnName: string): Promise<'asc' | 'desc' | 'none'>;
|
|
136
|
+
};
|
|
91
137
|
}
|
package/dist/useTable.d.ts
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
1
|
import type { Locator } from '@playwright/test';
|
|
2
|
-
import { TableConfig, TableResult } from './types';
|
|
2
|
+
import { TableConfig, TableContext, TableResult } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* A collection of pre-built pagination strategies.
|
|
5
|
+
*/
|
|
6
|
+
export declare const PaginationStrategies: {
|
|
7
|
+
/**
|
|
8
|
+
* Clicks a "Next" button.
|
|
9
|
+
* @param selector - The CSS selector for the "Next" button.
|
|
10
|
+
*/
|
|
11
|
+
NextButton: (selector: string) => ((context: TableContext) => Promise<boolean>);
|
|
12
|
+
/**
|
|
13
|
+
* Clicks numbered page links.
|
|
14
|
+
* @param selector - The CSS selector for the page number links.
|
|
15
|
+
*/
|
|
16
|
+
NumberedPages: (selector: string) => ((context: TableContext) => Promise<boolean>);
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* @deprecated Use `PaginationStrategies` instead. This alias will be removed in a future major version.
|
|
20
|
+
*/
|
|
21
|
+
export declare const TableStrategies: {
|
|
22
|
+
/**
|
|
23
|
+
* Clicks a "Next" button.
|
|
24
|
+
* @param selector - The CSS selector for the "Next" button.
|
|
25
|
+
*/
|
|
26
|
+
NextButton: (selector: string) => ((context: TableContext) => Promise<boolean>);
|
|
27
|
+
/**
|
|
28
|
+
* Clicks numbered page links.
|
|
29
|
+
* @param selector - The CSS selector for the page number links.
|
|
30
|
+
*/
|
|
31
|
+
NumberedPages: (selector: string) => ((context: TableContext) => Promise<boolean>);
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* A collection of pre-built sorting strategies.
|
|
35
|
+
*/
|
|
36
|
+
export declare const SortingStrategies: {
|
|
37
|
+
AriaSort: () => import("./types").SortingStrategy;
|
|
38
|
+
};
|
|
3
39
|
export declare const useTable: (rootLocator: Locator, configOptions?: TableConfig) => TableResult;
|
package/dist/useTable.js
CHANGED
|
@@ -9,8 +9,52 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.useTable = void 0;
|
|
12
|
+
exports.useTable = exports.SortingStrategies = exports.TableStrategies = exports.PaginationStrategies = void 0;
|
|
13
13
|
const typeContext_1 = require("./typeContext");
|
|
14
|
+
const sorting_1 = require("./strategies/sorting");
|
|
15
|
+
/**
|
|
16
|
+
* A collection of pre-built pagination strategies.
|
|
17
|
+
*/
|
|
18
|
+
exports.PaginationStrategies = {
|
|
19
|
+
/**
|
|
20
|
+
* Clicks a "Next" button.
|
|
21
|
+
* @param selector - The CSS selector for the "Next" button.
|
|
22
|
+
*/
|
|
23
|
+
NextButton: (selector) => {
|
|
24
|
+
return (_a) => __awaiter(void 0, [_a], void 0, function* ({ root }) {
|
|
25
|
+
const nextButton = root.locator(selector);
|
|
26
|
+
if ((yield nextButton.isVisible()) && (yield nextButton.isEnabled())) {
|
|
27
|
+
yield nextButton.click();
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
/**
|
|
34
|
+
* Clicks numbered page links.
|
|
35
|
+
* @param selector - The CSS selector for the page number links.
|
|
36
|
+
*/
|
|
37
|
+
NumberedPages: (selector) => {
|
|
38
|
+
let currentPage = 1;
|
|
39
|
+
return (_a) => __awaiter(void 0, [_a], void 0, function* ({ root }) {
|
|
40
|
+
currentPage++;
|
|
41
|
+
const pageLink = root.locator(selector).filter({ hasText: String(currentPage) });
|
|
42
|
+
if (yield pageLink.isVisible()) {
|
|
43
|
+
yield pageLink.click();
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* @deprecated Use `PaginationStrategies` instead. This alias will be removed in a future major version.
|
|
52
|
+
*/
|
|
53
|
+
exports.TableStrategies = exports.PaginationStrategies;
|
|
54
|
+
/**
|
|
55
|
+
* A collection of pre-built sorting strategies.
|
|
56
|
+
*/
|
|
57
|
+
exports.SortingStrategies = sorting_1.SortingStrategies;
|
|
14
58
|
const useTable = (rootLocator, configOptions = {}) => {
|
|
15
59
|
const config = Object.assign({ rowSelector: "tbody tr", headerSelector: "th", cellSelector: "td", pagination: () => __awaiter(void 0, void 0, void 0, function* () { return false; }), maxPages: 1, headerTransformer: ({ text, index, locator }) => text, autoScroll: true, debug: false, onReset: () => __awaiter(void 0, void 0, void 0, function* () { console.warn("⚠️ .reset() called but no 'onReset' strategy defined in config."); }) }, configOptions);
|
|
16
60
|
const resolve = (item, parent) => {
|
|
@@ -313,6 +357,34 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
313
357
|
return clone.outerHTML;
|
|
314
358
|
});
|
|
315
359
|
});
|
|
360
|
+
const sortingNamespace = {
|
|
361
|
+
apply: (columnName, direction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
362
|
+
if (!config.sorting) {
|
|
363
|
+
throw new Error('No sorting strategy has been configured. Please add a `sorting` strategy to your useTable config.');
|
|
364
|
+
}
|
|
365
|
+
logDebug(`Applying sort for column "${columnName}" (${direction})`);
|
|
366
|
+
const context = {
|
|
367
|
+
root: rootLocator,
|
|
368
|
+
config: config,
|
|
369
|
+
page: rootLocator.page(),
|
|
370
|
+
resolve: resolve
|
|
371
|
+
};
|
|
372
|
+
yield config.sorting.doSort({ columnName, direction, context });
|
|
373
|
+
}),
|
|
374
|
+
getState: (columnName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
375
|
+
if (!config.sorting) {
|
|
376
|
+
throw new Error('No sorting strategy has been configured. Please add a `sorting` strategy to your useTable config.');
|
|
377
|
+
}
|
|
378
|
+
logDebug(`Getting sort state for column "${columnName}"`);
|
|
379
|
+
const context = {
|
|
380
|
+
root: rootLocator,
|
|
381
|
+
config: config,
|
|
382
|
+
page: rootLocator.page(),
|
|
383
|
+
resolve: resolve
|
|
384
|
+
};
|
|
385
|
+
return config.sorting.getSortState({ columnName, context });
|
|
386
|
+
})
|
|
387
|
+
};
|
|
316
388
|
return {
|
|
317
389
|
getHeaders: () => __awaiter(void 0, void 0, void 0, function* () { return Array.from((yield _getMap()).keys()); }),
|
|
318
390
|
getHeaderCell: (columnName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -404,6 +476,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
404
476
|
const content = `\n==================================================\n🤖 COPY INTO GEMINI/ChatGPT TO WRITE A STRATEGY 🤖\n==================================================\nI need a custom Pagination Strategy for 'playwright-smart-table'.\nContainer HTML:\n\`\`\`html\n${html.substring(0, 10000)} ...\n\`\`\`\n`;
|
|
405
477
|
yield _handlePrompt('Smart Table Strategy', content, options);
|
|
406
478
|
}),
|
|
479
|
+
sorting: sortingNamespace,
|
|
407
480
|
};
|
|
408
481
|
};
|
|
409
482
|
exports.useTable = useTable;
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Page } from '@playwright/test';
|
|
2
|
+
/**
|
|
3
|
+
* Internal helper to wait for a condition to be met.
|
|
4
|
+
* Replaces the dependency on 'expect(...).toPass()' to ensure compatibility
|
|
5
|
+
* with environments where 'expect' is not globally available.
|
|
6
|
+
*/
|
|
7
|
+
export declare const waitForCondition: (predicate: () => Promise<boolean>, timeout: number, page: Page) => Promise<boolean>;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
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.waitForCondition = void 0;
|
|
13
|
+
/**
|
|
14
|
+
* Internal helper to wait for a condition to be met.
|
|
15
|
+
* Replaces the dependency on 'expect(...).toPass()' to ensure compatibility
|
|
16
|
+
* with environments where 'expect' is not globally available.
|
|
17
|
+
*/
|
|
18
|
+
const waitForCondition = (predicate, timeout, page) => __awaiter(void 0, void 0, void 0, function* () {
|
|
19
|
+
const startTime = Date.now();
|
|
20
|
+
while (Date.now() - startTime < timeout) {
|
|
21
|
+
if (yield predicate()) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
// Wait 100ms before next check (Standard Polling)
|
|
25
|
+
yield page.waitForTimeout(100).catch(() => new Promise(r => setTimeout(r, 100)));
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
});
|
|
29
|
+
exports.waitForCondition = waitForCondition;
|
package/package.json
CHANGED