@cronn/element-snapshot 0.15.0 → 0.16.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 CHANGED
@@ -1,52 +1,52 @@
1
- # Element Snapshots
1
+ # Playwright Element Snapshots
2
2
 
3
- Element Snapshots are a custom snapshot implementation inspired by [Playwright's ARIA Snapshots](https://playwright.dev/docs/aria-snapshots#aria-snapshots) and the [Accessibility Object Model](https://wicg.github.io/aom/explainer.html). They cover additional properties, e.g. validation attributes like `required` or `invalid` on form inputs, and are optimized to be serialized as JSON.
3
+ Element snapshots for Playwright.
4
4
 
5
- Element Snapshots are designed to be used in combination with [playwright-file-snapshots](../playwright-file-snapshots/README.md) for writing Playwright tests.
5
+ [Read the full documentation](https://cronn.github.io/file-snapshots/playwright/element-snapshots/)
6
6
 
7
7
  > [!NOTE]
8
8
  > Element Snapshots are currently experimental. Not all HTML elements, ARIA roles and attributes are covered. Breaking changes to the snapshot format are possible.
9
9
 
10
10
  ## Getting Started
11
11
 
12
- ### Adding the library to your project
12
+ ### Installation
13
13
 
14
14
  ```shell
15
- npm install -D @cronn/element-snapshot
15
+ pnpm add -D @cronn/element-snapshot
16
16
  ```
17
17
 
18
18
  ```shell
19
- yarn add -D @cronn/element-snapshot
19
+ npm install -D @cronn/element-snapshot
20
20
  ```
21
21
 
22
22
  ```shell
23
- pnpm add -D @cronn/element-snapshot
23
+ yarn add -D @cronn/element-snapshot
24
24
  ```
25
25
 
26
26
  ## Writing Tests
27
27
 
28
- This package provides multiple snapshot formats for different use cases:
29
-
30
- - **General-Purpose Snapshots**: Human-readable JSON format for all element types
31
- - **Markdown Table Snapshots**: Specialized format for tables and grids ([documentation](docs/markdown-table-snapshot.md))
32
- - **Custom Snapshots**: Build your own snapshot formats using raw element data and utility functions
33
-
34
- ### General-Purpose Snapshots
35
-
36
- The function `snapshotElement` provides a general-purpose snapshot including all supported roles and attributes. It can be used to achieve a high test coverage, but can become hard to read for complex HTML structures.
37
-
38
28
  ```ts
39
- import { snapshotElement } from "@cronn/element-snapshot";
29
+ import { semanticSnapshot } from "@cronn/element-snapshot";
40
30
  import { defineValidationFileExpect } from "@cronn/playwright-file-snapshots";
41
31
 
42
32
  const expect = defineValidationFileExpect();
43
33
 
44
34
  test("matches element snapshot", async ({ page }) => {
45
- await expect(snapshotElement(page.getByRole("main"))).toMatchJsonFile();
35
+ await page.setContent(`
36
+ <main>
37
+ <h1>List</h1>
38
+ <ul>
39
+ <li>Apple</li>
40
+ <li>Peach</li>
41
+ </ul>
42
+ </main>
43
+ `);
44
+
45
+ await expect(semanticSnapshot(page.getByRole("main"))).toMatchJsonFile();
46
46
  });
47
47
  ```
48
48
 
49
- Element Snapshot Example:
49
+ **Output (`matches_element_snapshot.json`):**
50
50
 
51
51
  ```json
52
52
  {
@@ -70,62 +70,3 @@ Element Snapshot Example:
70
70
  ]
71
71
  }
72
72
  ```
73
-
74
- To improve the specificity of certain tests, `snapshotElement` can be called on certain areas of the page only:
75
-
76
- ```ts
77
- test("matches navigation snapshot", async ({ page }) => {
78
- await expect(snapshotElement(page.getByRole("navigation"))).toMatchJsonFile({
79
- name: "navigation",
80
- });
81
- });
82
- ```
83
-
84
- #### Snapshot Options
85
-
86
- Snapshot options can be passed when calling the snapshot function:
87
-
88
- ```ts
89
- await expect(
90
- snapshotElement(page.getByLabel("My select"), {
91
- filter: (element) => element.role === "heading",
92
- }),
93
- ).toMatchJsonFile({
94
- name: "headings",
95
- });
96
- ```
97
-
98
- | Option | Default Value | Description |
99
- | ------------------------ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
100
- | `filter` | `() => true` | Include only elements in the snapshot for which the specified filter returns `true`. |
101
- | `recurseFilter` | `false` | Recursively apply specified filter to children of filtered elements. By default, recursion ends when the filter returns `true` for an element. Should be `true` for filters intended to remove specific elements recursively. |
102
- | `includeComboboxOptions` | `false` | Include combobox options in the snapshot. |
103
-
104
- ### Custom Snapshots
105
-
106
- The function `snapshotElementRaw` provides the raw element snapshot in a strictly typed structure. This format is not well suited to be read by humans, but can be utilized to derive custom snapshot formats, e.g. for HTML tables.
107
-
108
- ```ts
109
- import { snapshotElementRaw } from "@cronn/element-snapshot";
110
-
111
- test("matches custom snapshot", async ({ page }) => {
112
- const tableSnapshot = await snapshotElementRaw(page.getByRole("table"));
113
- const markdownTable = transformToMarkdownTable(tableSnapshot);
114
-
115
- await expect(markdownTable).toMatchTextFile({ fileExtension: "md" });
116
- });
117
-
118
- function transformToMarkdownTable(snapshot: Array<NodeSnapshot>): string {
119
- // transform table snapshot to markdown table
120
- }
121
- ```
122
-
123
- #### Utility Functions for Custom Snapshots
124
-
125
- | Function | Description |
126
- | ---------------- | --------------------------------------------------------------------- |
127
- | `filter` | Filters node snapshots based on the provided predicate function. |
128
- | `filterByRole` | Filters node snapshots by the specified role. |
129
- | `includeRole` | Includes only elements with the specified role. |
130
- | `excludeRole` | Excludes elements with the specified role. |
131
- | `getTextContent` | Aggregates and normalizes the text content of all provided snapshots. |
package/dist/index.d.mts CHANGED
@@ -186,7 +186,7 @@ declare function filter(options: FilterOptions): Array<NodeSnapshot>;
186
186
  declare function filterByRole<TRole extends NodeRole>(role: TRole, snapshots: Array<NodeSnapshot>): Array<SnapshotByRole<TRole>>;
187
187
  //#endregion
188
188
  //#region src/playwright/snapshot.d.ts
189
- interface ElementSnapshotOptions {
189
+ interface SemanticSnapshotOptions {
190
190
  /**
191
191
  * Include only elements in the snapshot for which the specified filter returns `true`
192
192
  *
@@ -210,23 +210,26 @@ interface ElementSnapshotOptions {
210
210
  includeComboboxOptions?: boolean;
211
211
  }
212
212
  /**
213
- * Creates an Element Snapshot of the specified element
213
+ * Captures a semantic snapshot of the specified locator's DOM structure.
214
214
  *
215
- * @example
216
- * ```ts
217
- * await expect(snapshotElement(page.getByRole("main"))).toMatchJsonSnapshot();
218
- * ```
219
- * @param locator Locator for the element to snapshot
220
- * @experimental
215
+ * This function creates a raw snapshot of the DOM element identified by the locator
216
+ * and transforms it into a semantic representation using the provided options.
217
+ *
218
+ * @param locator - The Locator instance that identifies the DOM element to snapshot
219
+ * @param options - Optional configuration settings for controlling the snapshot behavior
220
+ * @return A promise that resolves to the semantic snapshot
221
221
  */
222
- declare function snapshotElement(locator: Locator, options?: ElementSnapshotOptions): Promise<unknown>;
222
+ declare function semanticSnapshot(locator: Locator, options?: SemanticSnapshotOptions): Promise<unknown>;
223
223
  /**
224
- * Creates an Element Snapshot of the specified element, returning the raw snapshot data for custom transformations
224
+ * Captures a raw snapshot of the element matched by the provided locator.
225
+ *
226
+ * Returns an array of node snapshots representing the current state of the matched elements
227
+ * in the DOM, including their properties, attributes, and structure.
225
228
  *
226
- * @param locator Locator for the element to snapshot
227
- * @experimental
229
+ * @param locator - The Locator instance used to identify the target element to snapshot
230
+ * @return A promise that resolves to an array of NodeSnapshot objects representing the captured element
228
231
  */
229
- declare function snapshotElementRaw(locator: Locator): Promise<Array<NodeSnapshot>>;
232
+ declare function rawSnapshot(locator: Locator): Promise<Array<NodeSnapshot>>;
230
233
  //#endregion
231
234
  //#region src/utils/predicates.d.ts
232
235
  /**
@@ -244,4 +247,4 @@ declare function excludeRole<TRole extends NodeRole>(role: TRole | Array<TRole>)
244
247
  */
245
248
  declare function getTextContent(snapshots: Array<NodeSnapshot>): string;
246
249
  //#endregion
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 MarkdownTableSnapshotOptions, type MenuitemSnapshot, type NodeRole, type NodeSnapshot, type OptionSnapshot, type ProgressbarSnapshot, type RadiogroupSnapshot, type SeparatorSnapshot, type SnapshotByRole, type TabSnapshot, type TextSnapshot, excludeRole, filter, filterByRole, getTextContent, includeRole, markdownTableSnapshot, snapshotElement, snapshotElementRaw };
250
+ 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 MarkdownTableSnapshotOptions, type MenuitemSnapshot, type NodeRole, type NodeSnapshot, type OptionSnapshot, type ProgressbarSnapshot, type RadiogroupSnapshot, type SeparatorSnapshot, type SnapshotByRole, type TabSnapshot, type TextSnapshot, excludeRole, filter, filterByRole, getTextContent, includeRole, markdownTableSnapshot, rawSnapshot, semanticSnapshot };
package/dist/index.mjs CHANGED
@@ -106,8 +106,8 @@ var ElementSnapshotProxy = class {
106
106
  }
107
107
  };
108
108
  //#endregion
109
- //#region src/playwright/transformer.ts
110
- var ElementSnapshotTransformer = class {
109
+ //#region src/playwright/semantic-snapshot-transformer.ts
110
+ var SemanticSnapshotTransformer = class {
111
111
  filter;
112
112
  recurseFilter;
113
113
  includeComboboxOptions;
@@ -206,26 +206,29 @@ var ElementSnapshotTransformer = class {
206
206
  //#endregion
207
207
  //#region src/playwright/snapshot.ts
208
208
  /**
209
- * Creates an Element Snapshot of the specified element
209
+ * Captures a semantic snapshot of the specified locator's DOM structure.
210
210
  *
211
- * @example
212
- * ```ts
213
- * await expect(snapshotElement(page.getByRole("main"))).toMatchJsonSnapshot();
214
- * ```
215
- * @param locator Locator for the element to snapshot
216
- * @experimental
211
+ * This function creates a raw snapshot of the DOM element identified by the locator
212
+ * and transforms it into a semantic representation using the provided options.
213
+ *
214
+ * @param locator - The Locator instance that identifies the DOM element to snapshot
215
+ * @param options - Optional configuration settings for controlling the snapshot behavior
216
+ * @return A promise that resolves to the semantic snapshot
217
217
  */
218
- async function snapshotElement(locator, options) {
219
- const snapshot = await snapshotElementRaw(locator);
220
- return new ElementSnapshotTransformer(options).transform(snapshot);
218
+ async function semanticSnapshot(locator, options) {
219
+ const snapshot = await rawSnapshot(locator);
220
+ return new SemanticSnapshotTransformer(options).transform(snapshot);
221
221
  }
222
222
  /**
223
- * Creates an Element Snapshot of the specified element, returning the raw snapshot data for custom transformations
223
+ * Captures a raw snapshot of the element matched by the provided locator.
224
+ *
225
+ * Returns an array of node snapshots representing the current state of the matched elements
226
+ * in the DOM, including their properties, attributes, and structure.
224
227
  *
225
- * @param locator Locator for the element to snapshot
226
- * @experimental
228
+ * @param locator - The Locator instance used to identify the target element to snapshot
229
+ * @return A promise that resolves to an array of NodeSnapshot objects representing the captured element
227
230
  */
228
- async function snapshotElementRaw(locator) {
231
+ async function rawSnapshot(locator) {
229
232
  return await new ElementSnapshotProxy(locator.page()).snapshotElement(locator);
230
233
  }
231
234
  //#endregion
@@ -245,7 +248,7 @@ const sortIndicators = {
245
248
  * Creates a Markdown table snapshot from a table or grid element
246
249
  */
247
250
  async function markdownTableSnapshot(locator, options = {}) {
248
- const { columnHeaders, rows } = parseTable(await snapshotElementRaw(locator), options);
251
+ const { columnHeaders, rows } = parseTable(await rawSnapshot(locator), options);
249
252
  return markdownTable([columnHeaders, ...rows]);
250
253
  }
251
254
  function parseTable(snapshot, options) {
@@ -279,4 +282,4 @@ function getCellTexts(row) {
279
282
  }).map((cell) => getTextContent(cell.children));
280
283
  }
281
284
  //#endregion
282
- export { excludeRole, filter, filterByRole, getTextContent, includeRole, markdownTableSnapshot, snapshotElement, snapshotElementRaw };
285
+ export { excludeRole, filter, filterByRole, getTextContent, includeRole, markdownTableSnapshot, rawSnapshot, semanticSnapshot };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cronn/element-snapshot",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "description": "Element snapshots for Playwright",
5
5
  "bugs": {
6
6
  "url": "https://github.com/cronn/file-snapshots/issues"
@@ -12,19 +12,19 @@
12
12
  "url": "git+https://github.com/cronn/file-snapshots.git",
13
13
  "directory": "packages/element-snapshot"
14
14
  },
15
- "homepage": "https://github.com/cronn/file-snapshots",
15
+ "homepage": "https://cronn.github.io/file-snapshots/playwright/element-snapshots/",
16
16
  "engines": {
17
17
  "node": "^20 || ^22 || >=24"
18
18
  },
19
19
  "devEngines": {
20
20
  "runtime": {
21
21
  "name": "node",
22
- "version": ">=24.13 <25",
22
+ "version": ">=24.14.1 <25",
23
23
  "onFail": "error"
24
24
  },
25
25
  "packageManager": {
26
26
  "name": "pnpm",
27
- "version": ">=10.28.2 <11",
27
+ "version": ">=10.33.0 <11",
28
28
  "onFail": "error"
29
29
  }
30
30
  },
@@ -48,21 +48,21 @@
48
48
  "@playwright/test": "1.58.2",
49
49
  "@trivago/prettier-plugin-sort-imports": "6.0.2",
50
50
  "@types/node": "24.12.0",
51
- "@typescript/native-preview": "7.0.0-dev.20260309.1",
52
- "@vitest/coverage-v8": "4.0.18",
53
- "eslint": "10.0.3",
51
+ "@typescript/native-preview": "7.0.0-dev.20260323.1",
52
+ "@vitest/coverage-v8": "4.1.0",
53
+ "eslint": "10.1.0",
54
54
  "eslint-config-prettier": "10.1.8",
55
55
  "eslint-plugin-check-file": "3.3.1",
56
56
  "eslint-plugin-unused-imports": "4.4.1",
57
57
  "prettier": "3.8.1",
58
58
  "publint": "0.3.18",
59
- "tsdown": "0.21.1",
60
- "typescript-eslint": "8.56.1",
61
- "vitest": "4.0.18",
62
- "@cronn/playwright-file-snapshots": "1.0.1",
59
+ "tsdown": "0.21.4",
60
+ "typescript-eslint": "8.57.1",
61
+ "vitest": "4.1.0",
62
+ "@cronn/playwright-file-snapshots": "1.0.2",
63
63
  "@cronn/shared-configs": "0.0.0",
64
64
  "@cronn/test-utils": "0.0.0",
65
- "@cronn/vitest-file-snapshots": "1.0.1"
65
+ "@cronn/vitest-file-snapshots": "1.0.2"
66
66
  },
67
67
  "peerDependencies": {
68
68
  "@playwright/test": "^1.55"