@cronn/element-snapshot 0.11.0 → 0.12.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
@@ -89,10 +89,11 @@ await expect(
89
89
  });
90
90
  ```
91
91
 
92
- | Option | Default Value | Description |
93
- | ------------------------ | ------------- | ------------------------------------------------------------------------------------ |
94
- | `filter` | `() => true` | Include only elements in the snapshot for which the specified filter returns `true`. |
95
- | `includeComboboxOptions` | `false` | Include combobox options in the snapshot. |
92
+ | Option | Default Value | Description |
93
+ | ------------------------ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
94
+ | `filter` | `() => true` | Include only elements in the snapshot for which the specified filter returns `true`. |
95
+ | `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. |
96
+ | `includeComboboxOptions` | `false` | Include combobox options in the snapshot. |
96
97
 
97
98
  ### Custom Snapshots
98
99
 
@@ -32,14 +32,22 @@
32
32
 
33
33
  //#endregion
34
34
  //#region src/utils/snapshot.ts
35
- function filterSnapshots(snapshots, filter) {
35
+ function filterSnapshots(options) {
36
+ const { filter, snapshots, recurse = false } = options;
36
37
  return snapshots.flatMap((snapshot) => {
37
- const filteredChildren = hasChildren(snapshot) ? filterSnapshots(snapshot.children ?? [], filter) : [];
38
- if (filter(snapshot)) return {
38
+ const isFilteredIn = filter(snapshot);
39
+ if (isFilteredIn && !recurse) return snapshot;
40
+ if (!isFilteredIn && recurse) return [];
41
+ const filteredChildren = hasChildren(snapshot) ? filterSnapshots({
42
+ filter,
43
+ snapshots: snapshot.children ?? [],
44
+ recurse
45
+ }) : [];
46
+ if (!isFilteredIn) return filteredChildren;
47
+ return {
39
48
  ...snapshot,
40
49
  children: filteredChildren.length > 0 ? filteredChildren : void 0
41
50
  };
42
- return filteredChildren;
43
51
  });
44
52
  }
45
53
  function hasChildren(snapshot) {
@@ -68,7 +76,10 @@
68
76
  function resolveAccessibleTextContent(node, excludedNodes = []) {
69
77
  const children = snapshotChildren(node, excludedNodes);
70
78
  if (children === void 0) return;
71
- const normalizedText = normalizeText(filterSnapshots(children, (element) => element.role === "text").map((textNode) => textNode.name).join(" "));
79
+ const normalizedText = normalizeText(filterSnapshots({
80
+ snapshots: children,
81
+ filter: (element) => element.role === "text"
82
+ }).map((textNode) => textNode.name).join(" "));
72
83
  return normalizedText.length > 0 ? normalizedText : void 0;
73
84
  }
74
85
  function normalizeText(text) {
@@ -159,6 +170,7 @@
159
170
  "navigation",
160
171
  "region",
161
172
  "search",
173
+ "descriptionlist",
162
174
  "term",
163
175
  "definition",
164
176
  "table",
@@ -234,6 +246,7 @@
234
246
  textarea: "textbox",
235
247
  select: "combobox",
236
248
  option: "option",
249
+ dl: "descriptionlist",
237
250
  dt: "term",
238
251
  dd: "definition",
239
252
  table: "table",
@@ -246,8 +259,7 @@
246
259
  fieldset: "group",
247
260
  progress: "progressbar",
248
261
  hr: "separator",
249
- img: "img",
250
- svg: "img"
262
+ img: "img"
251
263
  };
252
264
  const CONTEXT_DEPENDENT_ROLES = {
253
265
  banner: isTopLevelBanner,
@@ -536,9 +548,11 @@
536
548
  //#endregion
537
549
  //#region src/browser/image.ts
538
550
  function snapshotImage(element) {
551
+ const imageName = resolveImageName(element);
552
+ if (imageName === void 0) return null;
539
553
  return {
540
554
  role: "img",
541
- name: resolveImageName(element)
555
+ name: imageName
542
556
  };
543
557
  }
544
558
  function resolveImageName(element) {
package/dist/index.d.mts CHANGED
@@ -51,7 +51,7 @@ interface OptionAttributes {
51
51
  }
52
52
  //#endregion
53
53
  //#region src/browser/container.d.ts
54
- declare const CONTAINER_ROLES: Set<"paragraph" | "list" | "listitem" | "listbox" | "article" | "banner" | "complementary" | "contentinfo" | "form" | "main" | "navigation" | "region" | "search" | "term" | "definition" | "table" | "grid" | "rowgroup" | "row" | "rowheader" | "cell" | "gridcell" | "alert" | "menu" | "tablist" | "tabpanel">;
54
+ declare const CONTAINER_ROLES: Set<"paragraph" | "list" | "listitem" | "listbox" | "article" | "banner" | "complementary" | "contentinfo" | "form" | "main" | "navigation" | "region" | "search" | "descriptionlist" | "term" | "definition" | "table" | "grid" | "rowgroup" | "row" | "rowheader" | "cell" | "gridcell" | "alert" | "menu" | "tablist" | "tabpanel">;
55
55
  interface ContainerSnapshot extends GenericElementSnapshot<ContainerRole> {}
56
56
  type ContainerRole = SetValues<typeof CONTAINER_ROLES>;
57
57
  //#endregion
@@ -128,6 +128,22 @@ type SetValues<TSet> = TSet extends Set<infer TValue> ? TValue : never;
128
128
  //#endregion
129
129
  //#region src/utils/snapshot.d.ts
130
130
  type SnapshotFilter = (snapshot: NodeSnapshot) => boolean;
131
+ type GuardedSnapshotFilter<TSnapshot extends NodeSnapshot> = (snapshot: NodeSnapshot) => snapshot is TSnapshot;
132
+ type FilteredSnapshot<TSnapshot extends NodeSnapshot> = TSnapshot extends GenericElementSnapshot ? TSnapshot & {
133
+ children?: Array<TSnapshot>;
134
+ } : TSnapshot;
135
+ interface SnapshotFilterOptions {
136
+ filter: SnapshotFilter;
137
+ snapshots: Array<NodeSnapshot>;
138
+ recurse: boolean;
139
+ }
140
+ interface GuardedSnapshotFilterOptions<TSnapshot extends NodeSnapshot> {
141
+ filter: GuardedSnapshotFilter<TSnapshot>;
142
+ snapshots: Array<NodeSnapshot>;
143
+ recurse?: boolean;
144
+ }
145
+ declare function filterSnapshots<TSnapshot extends NodeSnapshot = NodeSnapshot>(options: GuardedSnapshotFilterOptions<TSnapshot>): Array<FilteredSnapshot<TSnapshot>>;
146
+ declare function filterSnapshots(options: SnapshotFilterOptions): Array<NodeSnapshot>;
131
147
  //#endregion
132
148
  //#region src/playwright/snapshot.d.ts
133
149
  interface ElementSnapshotOptions {
@@ -137,6 +153,15 @@ interface ElementSnapshotOptions {
137
153
  * @default () => true
138
154
  */
139
155
  filter?: SnapshotFilter;
156
+ /**
157
+ * Recursively apply specified filter to children of filtered elements
158
+ *
159
+ * By default, recursion ends when the filter returns `true` for an element.
160
+ * Should be `true` for filters intended to remove specific elements recursively.
161
+ *
162
+ * @default false
163
+ */
164
+ recurseFilter?: boolean;
140
165
  /**
141
166
  * Include combobox options in the snapshot
142
167
  *
@@ -163,4 +188,4 @@ declare function snapshotElement(locator: Locator, options?: ElementSnapshotOpti
163
188
  */
164
189
  declare function snapshotElementRaw(locator: Locator): Promise<Array<NodeSnapshot>>;
165
190
  //#endregion
166
- export { type ButtonSnapshot, type ColumnheaderSnapshot, type ComboboxSnapshot, type ContainerSnapshot, type DialogSnapshot, type ElementRole, type ElementSnapshot, type GroupSnapshot, type HeadingSnapshot, type InputSnapshot, type LinkSnapshot, type MenuitemSnapshot, type NodeRole, type NodeSnapshot, type OptionSnapshot, type ProgressbarSnapshot, type RadiogroupSnapshot, type TabSnapshot, type TextSnapshot, snapshotElement, snapshotElementRaw };
191
+ 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, filterSnapshots, snapshotElement, snapshotElementRaw };
package/dist/index.mjs CHANGED
@@ -30,14 +30,22 @@ var ElementSnapshotProxy = class {
30
30
 
31
31
  //#endregion
32
32
  //#region src/utils/snapshot.ts
33
- function filterSnapshots(snapshots, filter) {
33
+ function filterSnapshots(options) {
34
+ const { filter, snapshots, recurse = false } = options;
34
35
  return snapshots.flatMap((snapshot) => {
35
- const filteredChildren = hasChildren(snapshot) ? filterSnapshots(snapshot.children ?? [], filter) : [];
36
- if (filter(snapshot)) return {
36
+ const isFilteredIn = filter(snapshot);
37
+ if (isFilteredIn && !recurse) return snapshot;
38
+ if (!isFilteredIn && recurse) return [];
39
+ const filteredChildren = hasChildren(snapshot) ? filterSnapshots({
40
+ filter,
41
+ snapshots: snapshot.children ?? [],
42
+ recurse
43
+ }) : [];
44
+ if (!isFilteredIn) return filteredChildren;
45
+ return {
37
46
  ...snapshot,
38
47
  children: filteredChildren.length > 0 ? filteredChildren : void 0
39
48
  };
40
- return filteredChildren;
41
49
  });
42
50
  }
43
51
  function hasChildren(snapshot) {
@@ -48,9 +56,11 @@ function hasChildren(snapshot) {
48
56
  //#region src/playwright/transformer.ts
49
57
  var ElementSnapshotTransformer = class {
50
58
  filter;
59
+ recurseFilter;
51
60
  includeComboboxOptions;
52
61
  constructor(options = {}) {
53
62
  this.filter = options.filter;
63
+ this.recurseFilter = options.recurseFilter ?? false;
54
64
  this.includeComboboxOptions = options.includeComboboxOptions ?? false;
55
65
  }
56
66
  transform(snapshots) {
@@ -61,7 +71,11 @@ var ElementSnapshotTransformer = class {
61
71
  }
62
72
  filterSnapshots(snapshots) {
63
73
  if (this.filter === void 0) return snapshots;
64
- return filterSnapshots(snapshots, this.filter);
74
+ return filterSnapshots({
75
+ filter: this.filter,
76
+ snapshots,
77
+ recurse: this.recurseFilter
78
+ });
65
79
  }
66
80
  transformSnapshots(snapshots) {
67
81
  return snapshots.map((snapshot) => this.transformSnapshotRecursive(snapshot));
@@ -163,4 +177,4 @@ async function snapshotElementRaw(locator) {
163
177
  }
164
178
 
165
179
  //#endregion
166
- export { snapshotElement, snapshotElementRaw };
180
+ export { filterSnapshots, snapshotElement, snapshotElementRaw };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cronn/element-snapshot",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Element snapshots for Playwright",
5
5
  "author": "cronn",
6
6
  "license": "Apache-2.0",
@@ -53,8 +53,8 @@
53
53
  "typescript-eslint": "8.54.0",
54
54
  "vitest": "4.0.18",
55
55
  "@cronn/playwright-file-snapshots": "0.38.1",
56
- "@cronn/test-utils": "0.0.0",
57
- "@cronn/shared-configs": "0.0.0"
56
+ "@cronn/shared-configs": "0.0.0",
57
+ "@cronn/test-utils": "0.0.0"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "@playwright/test": "^1.55"