@rickcedwhat/playwright-smart-table 2.0.2 ā 2.0.6
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/dist/strategies/index.d.ts +8 -3
- package/dist/strategies/index.js +22 -9
- package/dist/typeContext.d.ts +1 -1
- package/dist/typeContext.js +7 -43
- package/dist/types.d.ts +8 -38
- package/dist/useTable.js +26 -17
- package/package.json +5 -2
|
@@ -15,9 +15,14 @@ export declare const TableStrategies: {
|
|
|
15
15
|
*/
|
|
16
16
|
clickLoadMore: (buttonSelector: Selector, timeout?: number) => PaginationStrategy;
|
|
17
17
|
/**
|
|
18
|
-
* Strategy: Scrolls
|
|
18
|
+
* Strategy: Scrolls a specific container (or the window) to the bottom.
|
|
19
19
|
* Best for: Infinite Scroll grids (Ag-Grid, Virtual Lists)
|
|
20
|
-
* * @param timeout - Wait timeout (default: 5000ms)
|
|
20
|
+
* * @param options.timeout - Wait timeout (default: 5000ms)
|
|
21
|
+
* @param options.scrollerSelector - (Optional) Selector for the scrollable container.
|
|
22
|
+
* If omitted, tries to scroll the table root.
|
|
21
23
|
*/
|
|
22
|
-
infiniteScroll: (
|
|
24
|
+
infiniteScroll: (options?: {
|
|
25
|
+
timeout?: number;
|
|
26
|
+
scrollerSelector?: Selector;
|
|
27
|
+
}) => PaginationStrategy;
|
|
23
28
|
};
|
package/dist/strategies/index.js
CHANGED
|
@@ -74,24 +74,37 @@ exports.TableStrategies = {
|
|
|
74
74
|
});
|
|
75
75
|
},
|
|
76
76
|
/**
|
|
77
|
-
* Strategy: Scrolls
|
|
77
|
+
* Strategy: Scrolls a specific container (or the window) to the bottom.
|
|
78
78
|
* Best for: Infinite Scroll grids (Ag-Grid, Virtual Lists)
|
|
79
|
-
* * @param timeout - Wait timeout (default: 5000ms)
|
|
79
|
+
* * @param options.timeout - Wait timeout (default: 5000ms)
|
|
80
|
+
* @param options.scrollerSelector - (Optional) Selector for the scrollable container.
|
|
81
|
+
* If omitted, tries to scroll the table root.
|
|
80
82
|
*/
|
|
81
|
-
infiniteScroll: (
|
|
83
|
+
infiniteScroll: (options) => {
|
|
84
|
+
const { timeout = 5000, scrollerSelector } = options || {};
|
|
82
85
|
return (_a) => __awaiter(void 0, [_a], void 0, function* ({ root, config, resolve, page }) {
|
|
83
86
|
const rows = resolve(config.rowSelector, root);
|
|
84
87
|
const oldCount = yield rows.count();
|
|
85
88
|
if (oldCount === 0)
|
|
86
89
|
return false;
|
|
87
|
-
// Aggressive Scroll Logic:
|
|
88
|
-
// We use expect.poll to RETRY the scroll action if the count hasn't increased.
|
|
89
|
-
// This fixes flakiness where the first scroll might be missed by the intersection observer.
|
|
90
90
|
try {
|
|
91
91
|
yield test_1.expect.poll(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
92
|
-
// 1.
|
|
93
|
-
|
|
94
|
-
//
|
|
92
|
+
// 1. Determine target container
|
|
93
|
+
// If user provided a specific scroller (e.g. the div WRAPPING the table), use it.
|
|
94
|
+
// Otherwise, default to the root locator.
|
|
95
|
+
const scroller = scrollerSelector
|
|
96
|
+
? resolve(scrollerSelector, root)
|
|
97
|
+
: root;
|
|
98
|
+
// 2. Perform the Scroll
|
|
99
|
+
// Method A: DOM Manipulation (Fastest/Most Reliable for containers)
|
|
100
|
+
// We set scrollTop to a huge number to force it to the bottom
|
|
101
|
+
yield scroller.evaluate((el) => {
|
|
102
|
+
el.scrollTop = el.scrollHeight;
|
|
103
|
+
}).catch(() => { }); // Ignore if element doesn't support scrollTop (e.g. it's a window wrapper)
|
|
104
|
+
// Method B: Playwright Native (Fallback)
|
|
105
|
+
// Scroll the last row into view (good for Window scroll)
|
|
106
|
+
yield rows.last().scrollIntoViewIfNeeded().catch(() => { });
|
|
107
|
+
// Method C: Keyboard (Desperation)
|
|
95
108
|
yield page.keyboard.press('End');
|
|
96
109
|
// 3. Return count for assertion
|
|
97
110
|
return rows.count();
|
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 = "\
|
|
6
|
+
export declare const TYPE_CONTEXT = "\nexport type Selector = string | ((root: Locator | Page) => Locator);\n\nexport type SmartRow = Locator & {\n getCell(column: string): Locator;\n toJSON(): Promise<Record<string, string>>;\n};\n\nexport interface TableContext {\n root: Locator;\n config: Required<TableConfig>;\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 (Best for Cloud/QA Wolf to get clean text).\n * - 'console': Standard console logs (Default).\n * - 'report': Attaches to Playwright Report (Requires testInfo).\n */\n output?: 'console' | 'report' | 'error';\n includeTypes?: boolean;\n testInfo?: TestInfo;\n}\n\nexport interface TableConfig {\n rowSelector?: Selector;\n headerSelector?: Selector;\n cellSelector?: Selector;\n pagination?: PaginationStrategy;\n maxPages?: number;\n headerTransformer?: (text: string, index: number) => string;\n autoScroll?: boolean;\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";
|
package/dist/typeContext.js
CHANGED
|
@@ -7,8 +7,6 @@ exports.TYPE_CONTEXT = void 0;
|
|
|
7
7
|
* It contains the raw text of types.ts to provide context for LLM prompts.
|
|
8
8
|
*/
|
|
9
9
|
exports.TYPE_CONTEXT = `
|
|
10
|
-
// src/types.ts
|
|
11
|
-
|
|
12
10
|
export type Selector = string | ((root: Locator | Page) => Locator);
|
|
13
11
|
|
|
14
12
|
export type SmartRow = Locator & {
|
|
@@ -23,48 +21,27 @@ export interface TableContext {
|
|
|
23
21
|
resolve: (selector: Selector, parent: Locator | Page) => Locator;
|
|
24
22
|
}
|
|
25
23
|
|
|
26
|
-
/**
|
|
27
|
-
* A function that handles pagination logic.
|
|
28
|
-
* Returns true if more data was loaded (navigation occurred), false if end of data.
|
|
29
|
-
*/
|
|
30
24
|
export type PaginationStrategy = (context: TableContext) => Promise<boolean>;
|
|
31
25
|
|
|
32
26
|
export interface PromptOptions {
|
|
33
|
-
/** * Where to output the prompt.
|
|
34
|
-
* - 'console': Logs to stdout (default).
|
|
35
|
-
* - 'report': Attaches to the Playwright HTML report (best for CI/VMs).
|
|
36
|
-
* - 'file': Writes to a local file (e.g. 'smart-table-prompt.md').
|
|
37
|
-
*/
|
|
38
|
-
output?: 'console' | 'report' | 'file';
|
|
39
|
-
|
|
40
27
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
28
|
+
* Output Strategy:
|
|
29
|
+
* - 'error': Throws an error with the prompt (Best for Cloud/QA Wolf to get clean text).
|
|
30
|
+
* - 'console': Standard console logs (Default).
|
|
31
|
+
* - 'report': Attaches to Playwright Report (Requires testInfo).
|
|
44
32
|
*/
|
|
33
|
+
output?: 'console' | 'report' | 'error';
|
|
45
34
|
includeTypes?: boolean;
|
|
35
|
+
testInfo?: TestInfo;
|
|
46
36
|
}
|
|
47
37
|
|
|
48
38
|
export interface TableConfig {
|
|
49
39
|
rowSelector?: Selector;
|
|
50
40
|
headerSelector?: Selector;
|
|
51
41
|
cellSelector?: Selector;
|
|
52
|
-
/**
|
|
53
|
-
* Strategy for handling pagination.
|
|
54
|
-
* Use presets from TableStrategies or write your own.
|
|
55
|
-
*/
|
|
56
42
|
pagination?: PaginationStrategy;
|
|
57
43
|
maxPages?: number;
|
|
58
|
-
/**
|
|
59
|
-
* Optional hook to rename columns dynamically.
|
|
60
|
-
* Useful for naming empty columns (like '__col_0') to something semantic like 'Actions'.
|
|
61
|
-
*/
|
|
62
44
|
headerTransformer?: (text: string, index: number) => string;
|
|
63
|
-
/**
|
|
64
|
-
* Automatically scroll the table into view on first interaction.
|
|
65
|
-
* Helps ensure the table is visible in traces/videos.
|
|
66
|
-
* Default: true
|
|
67
|
-
*/
|
|
68
45
|
autoScroll?: boolean;
|
|
69
46
|
}
|
|
70
47
|
|
|
@@ -72,26 +49,13 @@ export interface TableResult {
|
|
|
72
49
|
getHeaders: () => Promise<string[]>;
|
|
73
50
|
getHeaderCell: (columnName: string) => Promise<Locator>;
|
|
74
51
|
|
|
75
|
-
/** * Find a specific row by its content.
|
|
76
|
-
* Default: Returns SmartRow (Locator).
|
|
77
|
-
* Option { asJSON: true }: Returns Record<string, string> (Data).
|
|
78
|
-
*/
|
|
79
52
|
getByRow: <T extends { asJSON?: boolean }>(
|
|
80
53
|
filters: Record<string, string | RegExp | number>,
|
|
81
54
|
options?: { exact?: boolean, maxPages?: number } & T
|
|
82
55
|
) => Promise<T['asJSON'] extends true ? Record<string, string> : SmartRow>;
|
|
83
56
|
|
|
84
|
-
/** * Get all rows on the current page.
|
|
85
|
-
* Can be filtered by column values.
|
|
86
|
-
* * @param options.asJSON - Returns data objects instead of SmartRows
|
|
87
|
-
* @param options.filter - Key-Value pairs to filter rows (e.g. { Status: 'Active' })
|
|
88
|
-
* @param options.exact - Exact match for filters (default: false)
|
|
89
|
-
*/
|
|
90
57
|
getAllRows: <T extends { asJSON?: boolean }>(
|
|
91
|
-
options?: {
|
|
92
|
-
filter?: Record<string, string | RegExp | number>;
|
|
93
|
-
exact?: boolean
|
|
94
|
-
} & T
|
|
58
|
+
options?: { filter?: Record<string, any>, exact?: boolean } & T
|
|
95
59
|
) => Promise<T['asJSON'] extends true ? Record<string, string>[] : SmartRow[]>;
|
|
96
60
|
|
|
97
61
|
generateConfigPrompt: (options?: PromptOptions) => Promise<void>;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Locator, Page } from '@playwright/test';
|
|
1
|
+
import { Locator, Page, TestInfo } from '@playwright/test';
|
|
2
2
|
export type Selector = string | ((root: Locator | Page) => Locator);
|
|
3
3
|
export type SmartRow = Locator & {
|
|
4
4
|
getCell(column: string): Locator;
|
|
@@ -10,70 +10,40 @@ export interface TableContext {
|
|
|
10
10
|
page: Page;
|
|
11
11
|
resolve: (selector: Selector, parent: Locator | Page) => Locator;
|
|
12
12
|
}
|
|
13
|
-
/**
|
|
14
|
-
* A function that handles pagination logic.
|
|
15
|
-
* Returns true if more data was loaded (navigation occurred), false if end of data.
|
|
16
|
-
*/
|
|
17
13
|
export type PaginationStrategy = (context: TableContext) => Promise<boolean>;
|
|
18
14
|
export interface PromptOptions {
|
|
19
|
-
/** * Where to output the prompt.
|
|
20
|
-
* - 'console': Logs to stdout (default).
|
|
21
|
-
* - 'report': Attaches to the Playwright HTML report (best for CI/VMs).
|
|
22
|
-
* - 'file': Writes to a local file (e.g. 'smart-table-prompt.md').
|
|
23
|
-
*/
|
|
24
|
-
output?: 'console' | 'report' | 'file';
|
|
25
15
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
16
|
+
* Output Strategy:
|
|
17
|
+
* - 'error': Throws an error with the prompt (Best for Cloud/QA Wolf to get clean text).
|
|
18
|
+
* - 'console': Standard console logs (Default).
|
|
19
|
+
* - 'report': Attaches to Playwright Report (Requires testInfo).
|
|
29
20
|
*/
|
|
21
|
+
output?: 'console' | 'report' | 'error';
|
|
30
22
|
includeTypes?: boolean;
|
|
23
|
+
testInfo?: TestInfo;
|
|
31
24
|
}
|
|
32
25
|
export interface TableConfig {
|
|
33
26
|
rowSelector?: Selector;
|
|
34
27
|
headerSelector?: Selector;
|
|
35
28
|
cellSelector?: Selector;
|
|
36
|
-
/**
|
|
37
|
-
* Strategy for handling pagination.
|
|
38
|
-
* Use presets from TableStrategies or write your own.
|
|
39
|
-
*/
|
|
40
29
|
pagination?: PaginationStrategy;
|
|
41
30
|
maxPages?: number;
|
|
42
|
-
/**
|
|
43
|
-
* Optional hook to rename columns dynamically.
|
|
44
|
-
* Useful for naming empty columns (like '__col_0') to something semantic like 'Actions'.
|
|
45
|
-
*/
|
|
46
31
|
headerTransformer?: (text: string, index: number) => string;
|
|
47
|
-
/**
|
|
48
|
-
* Automatically scroll the table into view on first interaction.
|
|
49
|
-
* Helps ensure the table is visible in traces/videos.
|
|
50
|
-
* Default: true
|
|
51
|
-
*/
|
|
52
32
|
autoScroll?: boolean;
|
|
53
33
|
}
|
|
54
34
|
export interface TableResult {
|
|
55
35
|
getHeaders: () => Promise<string[]>;
|
|
56
36
|
getHeaderCell: (columnName: string) => Promise<Locator>;
|
|
57
|
-
/** * Find a specific row by its content.
|
|
58
|
-
* Default: Returns SmartRow (Locator).
|
|
59
|
-
* Option { asJSON: true }: Returns Record<string, string> (Data).
|
|
60
|
-
*/
|
|
61
37
|
getByRow: <T extends {
|
|
62
38
|
asJSON?: boolean;
|
|
63
39
|
}>(filters: Record<string, string | RegExp | number>, options?: {
|
|
64
40
|
exact?: boolean;
|
|
65
41
|
maxPages?: number;
|
|
66
42
|
} & T) => Promise<T['asJSON'] extends true ? Record<string, string> : SmartRow>;
|
|
67
|
-
/** * Get all rows on the current page.
|
|
68
|
-
* Can be filtered by column values.
|
|
69
|
-
* * @param options.asJSON - Returns data objects instead of SmartRows
|
|
70
|
-
* @param options.filter - Key-Value pairs to filter rows (e.g. { Status: 'Active' })
|
|
71
|
-
* @param options.exact - Exact match for filters (default: false)
|
|
72
|
-
*/
|
|
73
43
|
getAllRows: <T extends {
|
|
74
44
|
asJSON?: boolean;
|
|
75
45
|
}>(options?: {
|
|
76
|
-
filter?: Record<string,
|
|
46
|
+
filter?: Record<string, any>;
|
|
77
47
|
exact?: boolean;
|
|
78
48
|
} & T) => Promise<T['asJSON'] extends true ? Record<string, string>[] : SmartRow[]>;
|
|
79
49
|
generateConfigPrompt: (options?: PromptOptions) => Promise<void>;
|
package/dist/useTable.js
CHANGED
|
@@ -13,7 +13,7 @@ exports.useTable = void 0;
|
|
|
13
13
|
const test_1 = require("@playwright/test");
|
|
14
14
|
const typeContext_1 = require("./typeContext");
|
|
15
15
|
const useTable = (rootLocator, configOptions = {}) => {
|
|
16
|
-
const config = Object.assign({ rowSelector: "tbody tr", headerSelector: "th", cellSelector: "td", pagination:
|
|
16
|
+
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) => text, autoScroll: true }, configOptions);
|
|
17
17
|
const resolve = (item, parent) => {
|
|
18
18
|
if (typeof item === 'string')
|
|
19
19
|
return parent.locator(item);
|
|
@@ -26,7 +26,10 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
26
26
|
if (_headerMap)
|
|
27
27
|
return _headerMap;
|
|
28
28
|
if (config.autoScroll) {
|
|
29
|
-
|
|
29
|
+
try {
|
|
30
|
+
yield rootLocator.scrollIntoViewIfNeeded({ timeout: 1000 });
|
|
31
|
+
}
|
|
32
|
+
catch (e) { }
|
|
30
33
|
}
|
|
31
34
|
const headerLoc = resolve(config.headerSelector, rootLocator);
|
|
32
35
|
try {
|
|
@@ -36,8 +39,8 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
36
39
|
const texts = yield headerLoc.allInnerTexts();
|
|
37
40
|
_headerMap = new Map(texts.map((t, i) => {
|
|
38
41
|
let text = t.trim() || `__col_${i}`;
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
// Safe call: config.headerTransformer is always defined now
|
|
43
|
+
text = config.headerTransformer(text, i);
|
|
41
44
|
return [text, i];
|
|
42
45
|
}));
|
|
43
46
|
return _headerMap;
|
|
@@ -96,7 +99,7 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
96
99
|
throw new Error(`Strict Mode Violation: Found ${count} rows matching ${JSON.stringify(filters)}.`);
|
|
97
100
|
if (count === 1)
|
|
98
101
|
return matchedRows.first();
|
|
99
|
-
if (
|
|
102
|
+
if (currentPage < effectiveMaxPages) {
|
|
100
103
|
const context = {
|
|
101
104
|
root: rootLocator,
|
|
102
105
|
config: config,
|
|
@@ -113,27 +116,33 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
113
116
|
}
|
|
114
117
|
});
|
|
115
118
|
const _handlePrompt = (promptName_1, content_1, ...args_1) => __awaiter(void 0, [promptName_1, content_1, ...args_1], void 0, function* (promptName, content, options = {}) {
|
|
116
|
-
const { output = 'console', includeTypes = true } = options;
|
|
119
|
+
const { output = 'console', includeTypes = true, testInfo } = options;
|
|
117
120
|
let finalPrompt = content;
|
|
118
121
|
if (includeTypes) {
|
|
119
122
|
finalPrompt += `\n\nš Useful TypeScript Definitions š\n\`\`\`typescript\n${typeContext_1.TYPE_CONTEXT}\n\`\`\`\n`;
|
|
120
123
|
}
|
|
121
|
-
if (output === '
|
|
122
|
-
console.log(
|
|
124
|
+
if (output === 'error') {
|
|
125
|
+
console.log(`ā ļø Throwing error to display [${promptName}] cleanly...`);
|
|
126
|
+
throw new Error(finalPrompt);
|
|
123
127
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
128
|
+
if (output === 'report') {
|
|
129
|
+
let activeInfo = testInfo;
|
|
130
|
+
if (!activeInfo) {
|
|
131
|
+
try {
|
|
132
|
+
activeInfo = test_1.test.info();
|
|
133
|
+
}
|
|
134
|
+
catch (e) { }
|
|
135
|
+
}
|
|
136
|
+
if (activeInfo) {
|
|
137
|
+
yield activeInfo.attach(promptName, { body: finalPrompt, contentType: 'text/markdown' });
|
|
138
|
+
console.log(`ā
[${promptName}] Attached to Playwright Report.`);
|
|
139
|
+
return;
|
|
131
140
|
}
|
|
132
141
|
else {
|
|
133
|
-
console.warn(
|
|
134
|
-
console.log(finalPrompt);
|
|
142
|
+
console.warn(`ā ļø [${promptName}] Cannot attach to report (Context unavailable). Logging to console instead.`);
|
|
135
143
|
}
|
|
136
144
|
}
|
|
145
|
+
console.log(finalPrompt);
|
|
137
146
|
});
|
|
138
147
|
return {
|
|
139
148
|
getHeaders: () => __awaiter(void 0, void 0, void 0, function* () { return Array.from((yield _getMap()).keys()); }),
|
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rickcedwhat/playwright-smart-table",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.6",
|
|
4
4
|
"description": "A smart table utility for Playwright with built-in pagination strategies that are fully extensible.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/rickcedwhat/playwright-smart-table.git"
|
|
8
|
+
},
|
|
5
9
|
"main": "dist/index.js",
|
|
6
10
|
"types": "dist/index.d.ts",
|
|
7
11
|
"files": [
|
|
@@ -11,7 +15,6 @@
|
|
|
11
15
|
"generate-types": "node scripts/embed-types.mjs",
|
|
12
16
|
"build": "npm run generate-types && tsc",
|
|
13
17
|
"prepublishOnly": "npm run build",
|
|
14
|
-
"release": "npm run build && npm publish --access public",
|
|
15
18
|
"test": "npx playwright test"
|
|
16
19
|
},
|
|
17
20
|
"keywords": [
|