@cronn/element-snapshot 0.14.0 → 0.14.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.
- package/dist/index.d.mts +15 -1
- package/dist/index.mjs +90 -38
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -126,6 +126,20 @@ interface GenericElementSnapshot<TRole extends NodeRole = NodeRole, TAttributes
|
|
|
126
126
|
}
|
|
127
127
|
type SetValues<TSet> = TSet extends Set<infer TValue> ? TValue : never;
|
|
128
128
|
//#endregion
|
|
129
|
+
//#region src/playwright/markdown-table.d.ts
|
|
130
|
+
interface TableSnapshotOptions {
|
|
131
|
+
/**
|
|
132
|
+
* Show sort indicator for column headers
|
|
133
|
+
*
|
|
134
|
+
* @default true
|
|
135
|
+
*/
|
|
136
|
+
showSortIndicator?: boolean;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Creates a Markdown table snapshot from a table or grid element
|
|
140
|
+
*/
|
|
141
|
+
declare function markdownTableSnapshot(locator: Locator, options?: TableSnapshotOptions): Promise<string>;
|
|
142
|
+
//#endregion
|
|
129
143
|
//#region src/types/snapshot.d.ts
|
|
130
144
|
type SnapshotByRole<TRole extends NodeRole> = NodeSnapshot & {
|
|
131
145
|
role: TRole;
|
|
@@ -230,4 +244,4 @@ declare function excludeRole<TRole extends NodeRole>(role: TRole | Array<TRole>)
|
|
|
230
244
|
*/
|
|
231
245
|
declare function getTextContent(snapshots: Array<NodeSnapshot>): string;
|
|
232
246
|
//#endregion
|
|
233
|
-
export { type ButtonSnapshot, type ColumnheaderSnapshot, type ComboboxSnapshot, type ContainerSnapshot, type DialogSnapshot, type ElementRole, type ElementSnapshot, type GroupSnapshot, type HeadingSnapshot, type ImageSnapshot, type InputSnapshot, type LinkSnapshot, type MenuitemSnapshot, type NodeRole, type NodeSnapshot, type OptionSnapshot, type ProgressbarSnapshot, type RadiogroupSnapshot, type SeparatorSnapshot, type TabSnapshot, type TextSnapshot, excludeRole, filter, filterByRole, getTextContent, includeRole, snapshotElement, snapshotElementRaw };
|
|
247
|
+
export { type ButtonSnapshot, type ColumnheaderSnapshot, type ComboboxSnapshot, type ContainerSnapshot, type DialogSnapshot, type ElementRole, type ElementSnapshot, type GroupSnapshot, type HeadingSnapshot, type ImageSnapshot, type InputSnapshot, type LinkSnapshot, type MenuitemSnapshot, type NodeRole, type NodeSnapshot, type OptionSnapshot, type ProgressbarSnapshot, type RadiogroupSnapshot, type SeparatorSnapshot, type TabSnapshot, type TextSnapshot, excludeRole, filter, filterByRole, getTextContent, includeRole, markdownTableSnapshot, snapshotElement, snapshotElementRaw };
|
package/dist/index.mjs
CHANGED
|
@@ -1,34 +1,7 @@
|
|
|
1
|
+
import { markdownTable } from "markdown-table";
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
import { packageDirectory } from "package-directory";
|
|
3
4
|
|
|
4
|
-
//#region src/playwright/proxy.ts
|
|
5
|
-
var ElementSnapshotProxy = class {
|
|
6
|
-
page;
|
|
7
|
-
constructor(page) {
|
|
8
|
-
this.page = page;
|
|
9
|
-
}
|
|
10
|
-
async snapshotElement(locator) {
|
|
11
|
-
if (!await this.isLibraryLoaded()) await this.loadLibrary();
|
|
12
|
-
return await locator.evaluate((element) => {
|
|
13
|
-
return window.snapshotElement(element);
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
async isLibraryLoaded() {
|
|
17
|
-
return await this.page.evaluate(() => typeof window.snapshotElement === "function");
|
|
18
|
-
}
|
|
19
|
-
async loadLibrary() {
|
|
20
|
-
const packageRootDir = await this.resolvePackageRootDir();
|
|
21
|
-
const libPath = path.resolve(packageRootDir, "dist", "browser-lib.iife.js");
|
|
22
|
-
await this.page.addScriptTag({ path: libPath });
|
|
23
|
-
}
|
|
24
|
-
async resolvePackageRootDir() {
|
|
25
|
-
const packageDir = await packageDirectory({ cwd: import.meta.dirname });
|
|
26
|
-
if (packageDir === void 0) throw new Error("Unable to resolve root directory of package");
|
|
27
|
-
return packageDir;
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
//#endregion
|
|
32
5
|
//#region src/utils/guards.ts
|
|
33
6
|
function isTextSnapshot(snapshot) {
|
|
34
7
|
return hasRole("text", snapshot);
|
|
@@ -92,6 +65,49 @@ function hasChildren(snapshot) {
|
|
|
92
65
|
return "children" in snapshot && snapshot.children.length > 0;
|
|
93
66
|
}
|
|
94
67
|
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/utils/text.ts
|
|
70
|
+
/**
|
|
71
|
+
* Aggregates and normalizes the text content of all provided snapshots
|
|
72
|
+
*/
|
|
73
|
+
function getTextContent(snapshots) {
|
|
74
|
+
return normalizeText(filter({
|
|
75
|
+
snapshots,
|
|
76
|
+
predicate: isTextSnapshot
|
|
77
|
+
}).map((textNode) => textNode.name).join(" "));
|
|
78
|
+
}
|
|
79
|
+
function normalizeText(text) {
|
|
80
|
+
return text.replaceAll(/\s+/g, " ").trim();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/playwright/proxy.ts
|
|
85
|
+
var ElementSnapshotProxy = class {
|
|
86
|
+
page;
|
|
87
|
+
constructor(page) {
|
|
88
|
+
this.page = page;
|
|
89
|
+
}
|
|
90
|
+
async snapshotElement(locator) {
|
|
91
|
+
if (!await this.isLibraryLoaded()) await this.loadLibrary();
|
|
92
|
+
return await locator.evaluate((element) => {
|
|
93
|
+
return window.snapshotElement(element);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
async isLibraryLoaded() {
|
|
97
|
+
return await this.page.evaluate(() => typeof window.snapshotElement === "function");
|
|
98
|
+
}
|
|
99
|
+
async loadLibrary() {
|
|
100
|
+
const packageRootDir = await this.resolvePackageRootDir();
|
|
101
|
+
const libPath = path.resolve(packageRootDir, "dist", "browser-lib.iife.js");
|
|
102
|
+
await this.page.addScriptTag({ path: libPath });
|
|
103
|
+
}
|
|
104
|
+
async resolvePackageRootDir() {
|
|
105
|
+
const packageDir = await packageDirectory({ cwd: import.meta.dirname });
|
|
106
|
+
if (packageDir === void 0) throw new Error("Unable to resolve root directory of package");
|
|
107
|
+
return packageDir;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
95
111
|
//#endregion
|
|
96
112
|
//#region src/playwright/transformer.ts
|
|
97
113
|
var ElementSnapshotTransformer = class {
|
|
@@ -218,19 +234,55 @@ async function snapshotElementRaw(locator) {
|
|
|
218
234
|
}
|
|
219
235
|
|
|
220
236
|
//#endregion
|
|
221
|
-
//#region src/
|
|
237
|
+
//#region src/playwright/markdown-table.ts
|
|
238
|
+
const tableRoles = ["table", "grid"];
|
|
239
|
+
const cellRoles = [
|
|
240
|
+
"rowheader",
|
|
241
|
+
"cell",
|
|
242
|
+
"gridcell"
|
|
243
|
+
];
|
|
244
|
+
const sortIndicators = {
|
|
245
|
+
ascending: "⯅",
|
|
246
|
+
descending: "⯆",
|
|
247
|
+
other: "⯁"
|
|
248
|
+
};
|
|
222
249
|
/**
|
|
223
|
-
*
|
|
250
|
+
* Creates a Markdown table snapshot from a table or grid element
|
|
224
251
|
*/
|
|
225
|
-
function
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
predicate: isTextSnapshot
|
|
229
|
-
}).map((textNode) => textNode.name).join(" "));
|
|
252
|
+
async function markdownTableSnapshot(locator, options = {}) {
|
|
253
|
+
const { columnHeaders, rows } = parseTable(await snapshotElementRaw(locator), options);
|
|
254
|
+
return markdownTable([columnHeaders, ...rows]);
|
|
230
255
|
}
|
|
231
|
-
function
|
|
232
|
-
|
|
256
|
+
function parseTable(snapshot, options) {
|
|
257
|
+
const { showSortIndicator = true } = options;
|
|
258
|
+
const tableOrGridResult = filter({
|
|
259
|
+
predicate: includeRole(tableRoles),
|
|
260
|
+
snapshots: snapshot
|
|
261
|
+
});
|
|
262
|
+
if (tableOrGridResult.length > 1) throw new Error("Multiple tables or grids found");
|
|
263
|
+
const [tableOrGrid] = tableOrGridResult;
|
|
264
|
+
if (tableOrGrid === void 0) throw new Error("No table or grid found");
|
|
265
|
+
const [headerRow, ...bodyRows] = filterByRole("row", tableOrGrid.children);
|
|
266
|
+
if (headerRow === void 0) throw new Error("No header row found");
|
|
267
|
+
const columnHeaders = filterByRole("columnheader", headerRow.children);
|
|
268
|
+
if (columnHeaders.length === 0) throw new Error("No column headers found");
|
|
269
|
+
return {
|
|
270
|
+
columnHeaders: columnHeaders.map((columnHeader) => getColumnHeaderText(columnHeader, showSortIndicator)),
|
|
271
|
+
rows: bodyRows.map(getCellTexts)
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
function getColumnHeaderText(columnHeader, showSortIndicator) {
|
|
275
|
+
const headerText = getTextContent([columnHeader]);
|
|
276
|
+
const sortType = columnHeader.attributes.sort;
|
|
277
|
+
if (!showSortIndicator || sortType === void 0) return headerText;
|
|
278
|
+
return `${headerText} ${sortIndicators[sortType]}`;
|
|
279
|
+
}
|
|
280
|
+
function getCellTexts(row) {
|
|
281
|
+
return filter({
|
|
282
|
+
predicate: includeRole(cellRoles),
|
|
283
|
+
snapshots: row.children
|
|
284
|
+
}).map((cell) => getTextContent(cell.children));
|
|
233
285
|
}
|
|
234
286
|
|
|
235
287
|
//#endregion
|
|
236
|
-
export { excludeRole, filter, filterByRole, getTextContent, includeRole, snapshotElement, snapshotElementRaw };
|
|
288
|
+
export { excludeRole, filter, filterByRole, getTextContent, includeRole, markdownTableSnapshot, snapshotElement, snapshotElementRaw };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cronn/element-snapshot",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "Element snapshots for Playwright",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/cronn/file-snapshots/issues"
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
"tsdown": "0.20.3",
|
|
60
60
|
"typescript-eslint": "8.56.1",
|
|
61
61
|
"vitest": "4.0.18",
|
|
62
|
-
"@cronn/shared-configs": "0.0.0",
|
|
63
62
|
"@cronn/playwright-file-snapshots": "1.0.1",
|
|
64
63
|
"@cronn/test-utils": "0.0.0",
|
|
65
|
-
"@cronn/vitest-file-snapshots": "1.0.1"
|
|
64
|
+
"@cronn/vitest-file-snapshots": "1.0.1",
|
|
65
|
+
"@cronn/shared-configs": "0.0.0"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
|
68
68
|
"@playwright/test": "^1.55"
|