@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 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/utils/text.ts
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
- * Aggregates and normalizes the text content of all provided snapshots
250
+ * Creates a Markdown table snapshot from a table or grid element
224
251
  */
225
- function getTextContent(snapshots) {
226
- return normalizeText(filter({
227
- snapshots,
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 normalizeText(text) {
232
- return text.replaceAll(/\s+/g, " ").trim();
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.0",
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"