@rickcedwhat/playwright-smart-table 1.0.7 ā 2.0.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/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/presets.d.ts +2 -26
- package/dist/types.d.ts +43 -13
- package/dist/useTable.d.ts +2 -14
- package/dist/useTable.js +79 -155
- package/package.json +9 -4
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/presets.d.ts
CHANGED
|
@@ -7,19 +7,7 @@ import { TableConfig } from './types';
|
|
|
7
7
|
* - Cell: Direct children (> *)
|
|
8
8
|
* - Columns: ['Label', 'Input']
|
|
9
9
|
*/
|
|
10
|
-
export declare const useForm: (rootLocator: Locator, options?: TableConfig) =>
|
|
11
|
-
getHeaders: () => Promise<string[]>;
|
|
12
|
-
getByRow: (filters: Record<string, string | RegExp | number>, options?: {
|
|
13
|
-
exact?: boolean;
|
|
14
|
-
maxPages?: number;
|
|
15
|
-
}) => Promise<Locator>;
|
|
16
|
-
getByCell: (rowFilters: Record<string, string | RegExp | number>, targetColumn: string) => Promise<Locator>;
|
|
17
|
-
getRows: () => Promise<Record<string, string>[]>;
|
|
18
|
-
getRowAsJSON: (filters: Record<string, string | RegExp | number>) => Promise<Record<string, string>>;
|
|
19
|
-
setColumnName: (colIndex: number, newNameOrFn: string | ((current: string) => string)) => Promise<void>;
|
|
20
|
-
generateConfigPrompt: () => Promise<void>;
|
|
21
|
-
generateStrategyPrompt: () => Promise<void>;
|
|
22
|
-
};
|
|
10
|
+
export declare const useForm: (rootLocator: Locator, options?: TableConfig) => import("./types").TableResult;
|
|
23
11
|
/**
|
|
24
12
|
* Preset for Navigation Menus.
|
|
25
13
|
* * Default Structure:
|
|
@@ -27,16 +15,4 @@ export declare const useForm: (rootLocator: Locator, options?: TableConfig) => {
|
|
|
27
15
|
* - Cell: null (The row IS the cell)
|
|
28
16
|
* - Columns: ['Item']
|
|
29
17
|
*/
|
|
30
|
-
export declare const useMenu: (menuLocator: Locator, options?: TableConfig) =>
|
|
31
|
-
getHeaders: () => Promise<string[]>;
|
|
32
|
-
getByRow: (filters: Record<string, string | RegExp | number>, options?: {
|
|
33
|
-
exact?: boolean;
|
|
34
|
-
maxPages?: number;
|
|
35
|
-
}) => Promise<Locator>;
|
|
36
|
-
getByCell: (rowFilters: Record<string, string | RegExp | number>, targetColumn: string) => Promise<Locator>;
|
|
37
|
-
getRows: () => Promise<Record<string, string>[]>;
|
|
38
|
-
getRowAsJSON: (filters: Record<string, string | RegExp | number>) => Promise<Record<string, string>>;
|
|
39
|
-
setColumnName: (colIndex: number, newNameOrFn: string | ((current: string) => string)) => Promise<void>;
|
|
40
|
-
generateConfigPrompt: () => Promise<void>;
|
|
41
|
-
generateStrategyPrompt: () => Promise<void>;
|
|
42
|
-
};
|
|
18
|
+
export declare const useMenu: (menuLocator: Locator, options?: TableConfig) => import("./types").TableResult;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,26 +1,56 @@
|
|
|
1
1
|
import { Locator, Page } from '@playwright/test';
|
|
2
|
+
export type Selector = string | ((root: Locator | Page) => Locator);
|
|
3
|
+
export type SmartRow = Locator & {
|
|
4
|
+
getCell(column: string): Locator;
|
|
5
|
+
toJSON(): Promise<Record<string, string>>;
|
|
6
|
+
};
|
|
7
|
+
export interface TableContext {
|
|
8
|
+
root: Locator;
|
|
9
|
+
config: Required<TableConfig>;
|
|
10
|
+
page: Page;
|
|
11
|
+
resolve: (selector: Selector, parent: Locator | Page) => Locator;
|
|
12
|
+
}
|
|
2
13
|
/**
|
|
3
|
-
* A
|
|
14
|
+
* A function that handles pagination logic.
|
|
15
|
+
* Returns true if more data was loaded (navigation occurred), false if end of data.
|
|
4
16
|
*/
|
|
5
|
-
export type
|
|
17
|
+
export type PaginationStrategy = (context: TableContext) => Promise<boolean>;
|
|
6
18
|
export interface TableConfig {
|
|
7
19
|
rowSelector?: Selector;
|
|
8
20
|
headerSelector?: Selector;
|
|
9
21
|
cellSelector?: Selector;
|
|
22
|
+
/**
|
|
23
|
+
* Strategy for handling pagination.
|
|
24
|
+
* Use presets from TableStrategies or write your own.
|
|
25
|
+
*/
|
|
10
26
|
pagination?: PaginationStrategy;
|
|
11
27
|
maxPages?: number;
|
|
12
28
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* Use this to name columns for Menus or Forms that have no headers.
|
|
16
|
-
* Example: ['MenuItem'] or [undefined, "Actions"]
|
|
29
|
+
* Optional hook to rename columns dynamically.
|
|
30
|
+
* Useful for naming empty columns (like '__col_0') to something semantic like 'Actions'.
|
|
17
31
|
*/
|
|
18
|
-
|
|
32
|
+
headerTransformer?: (text: string, index: number) => string;
|
|
19
33
|
}
|
|
20
|
-
export interface
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
34
|
+
export interface TableResult {
|
|
35
|
+
getHeaders: () => Promise<string[]>;
|
|
36
|
+
getHeaderCell: (columnName: string) => Promise<Locator>;
|
|
37
|
+
/** * Find a specific row by its content.
|
|
38
|
+
* Default: Returns SmartRow (Locator).
|
|
39
|
+
* Option { asJSON: true }: Returns Record<string, string> (Data).
|
|
40
|
+
*/
|
|
41
|
+
getByRow: <T extends {
|
|
42
|
+
asJSON?: boolean;
|
|
43
|
+
}>(filters: Record<string, string | RegExp | number>, options?: {
|
|
44
|
+
exact?: boolean;
|
|
45
|
+
maxPages?: number;
|
|
46
|
+
} & T) => Promise<T['asJSON'] extends true ? Record<string, string> : SmartRow>;
|
|
47
|
+
/** * Get all rows on the current page.
|
|
48
|
+
* Default: Returns SmartRow[] (Locators).
|
|
49
|
+
* Option { asJSON: true }: Returns Record<string, string>[] (Data).
|
|
50
|
+
*/
|
|
51
|
+
getAllRows: <T extends {
|
|
52
|
+
asJSON?: boolean;
|
|
53
|
+
}>(options?: T) => Promise<T['asJSON'] extends true ? Record<string, string>[] : SmartRow[]>;
|
|
54
|
+
generateConfigPrompt: () => Promise<void>;
|
|
55
|
+
generateStrategyPrompt: () => Promise<void>;
|
|
25
56
|
}
|
|
26
|
-
export type PaginationStrategy = (context: TableContext) => Promise<boolean>;
|
package/dist/useTable.d.ts
CHANGED
|
@@ -1,15 +1,3 @@
|
|
|
1
1
|
import { Locator } from '@playwright/test';
|
|
2
|
-
import { TableConfig } from './types';
|
|
3
|
-
export declare const useTable: (rootLocator: Locator, configOptions?: TableConfig) =>
|
|
4
|
-
getHeaders: () => Promise<string[]>;
|
|
5
|
-
getByRow: (filters: Record<string, string | RegExp | number>, options?: {
|
|
6
|
-
exact?: boolean;
|
|
7
|
-
maxPages?: number;
|
|
8
|
-
}) => Promise<Locator>;
|
|
9
|
-
getByCell: (rowFilters: Record<string, string | RegExp | number>, targetColumn: string) => Promise<Locator>;
|
|
10
|
-
getRows: () => Promise<Record<string, string>[]>;
|
|
11
|
-
getRowAsJSON: (filters: Record<string, string | RegExp | number>) => Promise<Record<string, string>>;
|
|
12
|
-
setColumnName: (colIndex: number, newNameOrFn: string | ((current: string) => string)) => Promise<void>;
|
|
13
|
-
generateConfigPrompt: () => Promise<void>;
|
|
14
|
-
generateStrategyPrompt: () => Promise<void>;
|
|
15
|
-
};
|
|
2
|
+
import { TableConfig, TableResult } from './types';
|
|
3
|
+
export declare const useTable: (rootLocator: Locator, configOptions?: TableConfig) => TableResult;
|
package/dist/useTable.js
CHANGED
|
@@ -11,40 +11,58 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.useTable = void 0;
|
|
13
13
|
const useTable = (rootLocator, configOptions = {}) => {
|
|
14
|
-
const config = Object.assign({ rowSelector: "tbody tr", headerSelector: "th", cellSelector: "td", pagination: undefined, maxPages: 1,
|
|
14
|
+
const config = Object.assign({ rowSelector: "tbody tr", headerSelector: "th", cellSelector: "td", pagination: undefined, maxPages: 1, headerTransformer: undefined }, configOptions);
|
|
15
15
|
const resolve = (item, parent) => {
|
|
16
16
|
if (typeof item === 'string')
|
|
17
17
|
return parent.locator(item);
|
|
18
18
|
if (typeof item === 'function')
|
|
19
19
|
return item(parent);
|
|
20
|
-
|
|
20
|
+
return item;
|
|
21
21
|
};
|
|
22
22
|
let _headerMap = null;
|
|
23
23
|
const _getMap = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
24
|
if (_headerMap)
|
|
25
25
|
return _headerMap;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const headerLoc = resolve(config.headerSelector, rootLocator);
|
|
30
|
-
try {
|
|
31
|
-
yield headerLoc.first().waitFor({ state: 'visible', timeout: 3000 });
|
|
32
|
-
texts = yield headerLoc.allInnerTexts();
|
|
33
|
-
}
|
|
34
|
-
catch (e) { /* Ignore hydration/empty/timeout */ }
|
|
35
|
-
}
|
|
36
|
-
// 2. Merge Scraped Data with Config Overrides
|
|
37
|
-
_headerMap = new Map();
|
|
38
|
-
const overrides = config.columnNames || [];
|
|
39
|
-
const colCount = Math.max(texts.length, overrides.length);
|
|
40
|
-
for (let i = 0; i < colCount; i++) {
|
|
41
|
-
const scrapedText = (texts[i] || "").trim() || `__col_${i}`;
|
|
42
|
-
const overrideText = overrides[i];
|
|
43
|
-
const finalName = (overrideText !== undefined) ? overrideText : scrapedText;
|
|
44
|
-
_headerMap.set(finalName, i);
|
|
26
|
+
const headerLoc = resolve(config.headerSelector, rootLocator);
|
|
27
|
+
try {
|
|
28
|
+
yield headerLoc.first().waitFor({ state: 'visible', timeout: 3000 });
|
|
45
29
|
}
|
|
30
|
+
catch (e) { /* Ignore hydration */ }
|
|
31
|
+
const texts = yield headerLoc.allInnerTexts();
|
|
32
|
+
_headerMap = new Map(texts.map((t, i) => {
|
|
33
|
+
let text = t.trim() || `__col_${i}`;
|
|
34
|
+
if (config.headerTransformer)
|
|
35
|
+
text = config.headerTransformer(text, i);
|
|
36
|
+
return [text, i];
|
|
37
|
+
}));
|
|
46
38
|
return _headerMap;
|
|
47
39
|
});
|
|
40
|
+
const _makeSmart = (rowLocator, map) => {
|
|
41
|
+
const smart = rowLocator;
|
|
42
|
+
smart.getCell = (colName) => {
|
|
43
|
+
const idx = map.get(colName);
|
|
44
|
+
if (idx === undefined)
|
|
45
|
+
throw new Error(`Column '${colName}' not found.`);
|
|
46
|
+
if (typeof config.cellSelector === 'string') {
|
|
47
|
+
return rowLocator.locator(config.cellSelector).nth(idx);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
return resolve(config.cellSelector, rowLocator).nth(idx);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
smart.toJSON = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
54
|
+
const result = {};
|
|
55
|
+
const cells = typeof config.cellSelector === 'string'
|
|
56
|
+
? rowLocator.locator(config.cellSelector)
|
|
57
|
+
: resolve(config.cellSelector, rowLocator);
|
|
58
|
+
const texts = yield cells.allInnerTexts();
|
|
59
|
+
for (const [col, idx] of map.entries()) {
|
|
60
|
+
result[col] = (texts[idx] || '').trim();
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
});
|
|
64
|
+
return smart;
|
|
65
|
+
};
|
|
48
66
|
const _findRowLocator = (filters_1, ...args_1) => __awaiter(void 0, [filters_1, ...args_1], void 0, function* (filters, options = {}) {
|
|
49
67
|
var _a;
|
|
50
68
|
const map = yield _getMap();
|
|
@@ -52,67 +70,32 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
52
70
|
const effectiveMaxPages = (_a = options.maxPages) !== null && _a !== void 0 ? _a : config.maxPages;
|
|
53
71
|
let currentPage = 1;
|
|
54
72
|
while (true) {
|
|
55
|
-
if (!config.rowSelector)
|
|
56
|
-
throw new Error("rowSelector cannot be null");
|
|
57
73
|
let rowLocator = resolve(config.rowSelector, rootLocator);
|
|
58
74
|
for (const [colName, value] of Object.entries(filters)) {
|
|
59
75
|
const colIndex = map.get(colName);
|
|
60
76
|
if (colIndex === undefined)
|
|
61
|
-
throw new Error(`Column '${colName}' not found. Available: ${
|
|
77
|
+
throw new Error(`Column '${colName}' not found. Available: ${[...map.keys()].join(', ')}`);
|
|
62
78
|
const exact = options.exact || false;
|
|
63
79
|
const filterVal = typeof value === 'number' ? String(value) : value;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
rowLocator = rowLocator.filter({ hasText: filterVal });
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// Case 2: String Cell Selector - Standard Table Logic (Restored)
|
|
74
|
-
else if (typeof config.cellSelector === 'string') {
|
|
75
|
-
// RESTORED: This logic worked for standard tables.
|
|
76
|
-
// We resolve against the PAGE to create a generic locator template.
|
|
77
|
-
// Playwright handles the relative filtering correctly for standard tables.
|
|
78
|
-
const cellTemplate = resolve(config.cellSelector, page);
|
|
79
|
-
rowLocator = rowLocator.filter({
|
|
80
|
-
has: cellTemplate.nth(colIndex).getByText(filterVal, { exact }),
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
// Case 3: Function Cell Selector - Forms (Iterative Fallback)
|
|
84
|
-
else {
|
|
85
|
-
const count = yield rowLocator.count();
|
|
86
|
-
let matchFound = false;
|
|
87
|
-
for (let i = 0; i < count; i++) {
|
|
88
|
-
const specificRow = rowLocator.nth(i);
|
|
89
|
-
// Resolve cell relative to this specific row
|
|
90
|
-
const specificCell = config.cellSelector(specificRow).nth(colIndex);
|
|
91
|
-
if ((yield specificCell.getByText(filterVal, { exact }).count()) > 0) {
|
|
92
|
-
if (matchFound) {
|
|
93
|
-
throw new Error(`Strict Mode Violation: Found multiple rows matching ${JSON.stringify(filters)}.`);
|
|
94
|
-
}
|
|
95
|
-
rowLocator = specificRow;
|
|
96
|
-
matchFound = true;
|
|
97
|
-
// Break inner loop to proceed to next filter or return
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
if (!matchFound) {
|
|
102
|
-
// Return empty locator to fail gracefully
|
|
103
|
-
return resolve(config.rowSelector, rootLocator).filter({ hasText: "NON_EXISTENT_ROW_" + Date.now() });
|
|
104
|
-
}
|
|
105
|
-
}
|
|
80
|
+
const cellTemplate = resolve(config.cellSelector, page);
|
|
81
|
+
rowLocator = rowLocator.filter({
|
|
82
|
+
has: cellTemplate.nth(colIndex).getByText(filterVal, { exact }),
|
|
83
|
+
});
|
|
106
84
|
}
|
|
107
85
|
const count = yield rowLocator.count();
|
|
108
86
|
if (count > 1)
|
|
109
87
|
throw new Error(`Strict Mode Violation: Found ${count} rows matching ${JSON.stringify(filters)}.`);
|
|
110
88
|
if (count === 1)
|
|
111
89
|
return rowLocator.first();
|
|
112
|
-
// --- PAGINATION ---
|
|
113
90
|
if (config.pagination && currentPage < effectiveMaxPages) {
|
|
114
|
-
const context = {
|
|
115
|
-
|
|
91
|
+
const context = {
|
|
92
|
+
root: rootLocator,
|
|
93
|
+
config: config,
|
|
94
|
+
page: page,
|
|
95
|
+
resolve: resolve
|
|
96
|
+
};
|
|
97
|
+
const didLoadMore = yield config.pagination(context);
|
|
98
|
+
if (didLoadMore) {
|
|
116
99
|
currentPage++;
|
|
117
100
|
continue;
|
|
118
101
|
}
|
|
@@ -122,107 +105,48 @@ const useTable = (rootLocator, configOptions = {}) => {
|
|
|
122
105
|
});
|
|
123
106
|
return {
|
|
124
107
|
getHeaders: () => __awaiter(void 0, void 0, void 0, function* () { return Array.from((yield _getMap()).keys()); }),
|
|
125
|
-
|
|
126
|
-
const row = yield _findRowLocator(filters, options);
|
|
127
|
-
if (!row)
|
|
128
|
-
return resolve(config.rowSelector, rootLocator).filter({ hasText: "NON_EXISTENT_ROW_SENTINEL_" + Date.now() });
|
|
129
|
-
return row;
|
|
130
|
-
}),
|
|
131
|
-
getByCell: (rowFilters, targetColumn) => __awaiter(void 0, void 0, void 0, function* () {
|
|
132
|
-
const row = yield _findRowLocator(rowFilters);
|
|
133
|
-
if (!row)
|
|
134
|
-
throw new Error(`Row not found: ${JSON.stringify(rowFilters)}`);
|
|
135
|
-
// Guard: getByCell makes no sense for Menus (no cells)
|
|
136
|
-
if (!config.cellSelector) {
|
|
137
|
-
throw new Error("getByCell is not supported when 'cellSelector' is null (e.g. Menus). Use getByRow instead.");
|
|
138
|
-
}
|
|
108
|
+
getHeaderCell: (columnName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
139
109
|
const map = yield _getMap();
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
142
|
-
throw new Error(`Column '${
|
|
143
|
-
|
|
144
|
-
return row.locator(config.cellSelector).nth(colIndex);
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
return resolve(config.cellSelector, row).nth(colIndex);
|
|
148
|
-
}
|
|
149
|
-
}),
|
|
150
|
-
getRows: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
151
|
-
const map = yield _getMap();
|
|
152
|
-
const rowLocator = resolve(config.rowSelector, rootLocator);
|
|
153
|
-
const rowCount = yield rowLocator.count();
|
|
154
|
-
const results = [];
|
|
155
|
-
for (let i = 0; i < rowCount; i++) {
|
|
156
|
-
const row = rowLocator.nth(i);
|
|
157
|
-
let cellTexts = [];
|
|
158
|
-
if (!config.cellSelector) {
|
|
159
|
-
cellTexts = [yield row.innerText()];
|
|
160
|
-
}
|
|
161
|
-
else if (typeof config.cellSelector === 'string') {
|
|
162
|
-
// For string selectors, we query all matching cells in the row
|
|
163
|
-
cellTexts = yield row.locator(config.cellSelector).allInnerTexts();
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
// For function selectors, we resolve against the row
|
|
167
|
-
cellTexts = yield resolve(config.cellSelector, row).allInnerTexts();
|
|
168
|
-
}
|
|
169
|
-
const rowData = {};
|
|
170
|
-
for (const [colName, colIdx] of map.entries()) {
|
|
171
|
-
rowData[colName] = (cellTexts[colIdx] || "").trim();
|
|
172
|
-
}
|
|
173
|
-
results.push(rowData);
|
|
174
|
-
}
|
|
175
|
-
return results;
|
|
110
|
+
const idx = map.get(columnName);
|
|
111
|
+
if (idx === undefined)
|
|
112
|
+
throw new Error(`Column '${columnName}' not found.`);
|
|
113
|
+
return resolve(config.headerSelector, rootLocator).nth(idx);
|
|
176
114
|
}),
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (!config.cellSelector) {
|
|
183
|
-
cellTexts = [yield row.innerText()];
|
|
184
|
-
}
|
|
185
|
-
else if (typeof config.cellSelector === 'string') {
|
|
186
|
-
cellTexts = yield row.locator(config.cellSelector).allInnerTexts();
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
cellTexts = yield resolve(config.cellSelector, row).allInnerTexts();
|
|
115
|
+
getByRow: (filters, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
116
|
+
let row = yield _findRowLocator(filters, options);
|
|
117
|
+
// ā
FIX: Sentinel Logic for negative assertions (expect(row).not.toBeVisible())
|
|
118
|
+
if (!row) {
|
|
119
|
+
row = resolve(config.rowSelector, rootLocator).filter({ hasText: "___SENTINEL_ROW_NOT_FOUND___" + Date.now() });
|
|
190
120
|
}
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
121
|
+
const smartRow = _makeSmart(row, yield _getMap());
|
|
122
|
+
if (options === null || options === void 0 ? void 0 : options.asJSON) {
|
|
123
|
+
// If row doesn't exist, toJSON() returns empty object or throws?
|
|
124
|
+
// For safety, let's let it run naturally (it will likely return empty strings)
|
|
125
|
+
return smartRow.toJSON();
|
|
195
126
|
}
|
|
196
|
-
return
|
|
127
|
+
return smartRow;
|
|
197
128
|
}),
|
|
198
|
-
|
|
129
|
+
getAllRows: (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
199
130
|
const map = yield _getMap();
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
break;
|
|
205
|
-
}
|
|
131
|
+
const rowLocators = yield resolve(config.rowSelector, rootLocator).all();
|
|
132
|
+
const smartRows = rowLocators.map(loc => _makeSmart(loc, map));
|
|
133
|
+
if (options === null || options === void 0 ? void 0 : options.asJSON) {
|
|
134
|
+
return Promise.all(smartRows.map(r => r.toJSON()));
|
|
206
135
|
}
|
|
207
|
-
|
|
208
|
-
oldName = `__col_${colIndex}`;
|
|
209
|
-
const newName = typeof newNameOrFn === 'function' ? newNameOrFn(oldName) : newNameOrFn;
|
|
210
|
-
if (map.has(oldName))
|
|
211
|
-
map.delete(oldName);
|
|
212
|
-
map.set(newName, colIndex);
|
|
136
|
+
return smartRows;
|
|
213
137
|
}),
|
|
214
138
|
generateConfigPrompt: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
215
139
|
const html = yield rootLocator.evaluate((el) => el.outerHTML);
|
|
216
|
-
|
|
140
|
+
const separator = "=".repeat(50);
|
|
141
|
+
const prompt = `\n${separator}\nš¤ COPY INTO GEMINI/ChatGPT š¤\n${separator}\nI am using 'playwright-smart-table'. Generate config for:\n\`\`\`html\n${html.substring(0, 5000)} ...\n\`\`\`\n${separator}\n`;
|
|
142
|
+
console.log(prompt);
|
|
217
143
|
}),
|
|
218
144
|
generateStrategyPrompt: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
219
145
|
const container = rootLocator.locator('xpath=..');
|
|
220
146
|
const html = yield container.evaluate((el) => el.outerHTML);
|
|
221
|
-
|
|
147
|
+
const prompt = `\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, 5000)} ...\n\`\`\`\n`;
|
|
148
|
+
console.log(prompt);
|
|
222
149
|
})
|
|
223
150
|
};
|
|
224
151
|
};
|
|
225
152
|
exports.useTable = useTable;
|
|
226
|
-
function escapeRegExp(string) {
|
|
227
|
-
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
228
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rickcedwhat/playwright-smart-table",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A smart table utility for Playwright with built-in pagination strategies.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -10,14 +10,19 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "tsc",
|
|
12
12
|
"prepublishOnly": "npm run build",
|
|
13
|
-
"publish": "npm publish --access public",
|
|
13
|
+
"publish-public": "npm publish --access public",
|
|
14
14
|
"test": "npx playwright test"
|
|
15
15
|
},
|
|
16
|
-
"keywords": [
|
|
16
|
+
"keywords": [
|
|
17
|
+
"playwright",
|
|
18
|
+
"testing",
|
|
19
|
+
"table",
|
|
20
|
+
"automation"
|
|
21
|
+
],
|
|
17
22
|
"author": "",
|
|
18
23
|
"license": "ISC",
|
|
19
24
|
"peerDependencies": {
|
|
20
|
-
"@playwright/test": "*"
|
|
25
|
+
"@playwright/test": "*"
|
|
21
26
|
},
|
|
22
27
|
"peerDependenciesMeta": {
|
|
23
28
|
"@playwright/test": {
|