@cronn/element-snapshot 0.12.0 → 0.13.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.
@@ -26,8 +26,13 @@
26
26
  //#endregion
27
27
  //#region src/browser/children.ts
28
28
  function snapshotChildren(node, excludedNodes = []) {
29
- const children = Array.from(node.childNodes).map((node) => snapshotNodeRecursive(node, excludedNodes)).filter((childSnapshot) => childSnapshot !== null).flat();
30
- return children.length > 0 ? children : void 0;
29
+ return Array.from(node.childNodes).map((childNode) => snapshotNodeRecursive(childNode, excludedNodes)).filter((childSnapshot) => childSnapshot !== null).flat();
30
+ }
31
+
32
+ //#endregion
33
+ //#region src/utils/guards.ts
34
+ function isTextSnapshot(snapshot) {
35
+ return snapshot.role === "text";
31
36
  }
32
37
 
33
38
  //#endregion
@@ -46,12 +51,12 @@
46
51
  if (!isFilteredIn) return filteredChildren;
47
52
  return {
48
53
  ...snapshot,
49
- children: filteredChildren.length > 0 ? filteredChildren : void 0
54
+ children: filteredChildren
50
55
  };
51
56
  });
52
57
  }
53
58
  function hasChildren(snapshot) {
54
- return "children" in snapshot && snapshot.children !== void 0 && snapshot.children.length > 0;
59
+ return "children" in snapshot && snapshot.children.length > 0;
55
60
  }
56
61
 
57
62
  //#endregion
@@ -67,7 +72,7 @@
67
72
  }
68
73
  function snapshotPresentationalChildren(node) {
69
74
  const accessibleTextContent = resolveAccessibleTextContent(node);
70
- if (accessibleTextContent === void 0 || accessibleTextContent.length === 0) return;
75
+ if (accessibleTextContent === void 0 || accessibleTextContent.length === 0) return [];
71
76
  return [{
72
77
  role: "text",
73
78
  name: accessibleTextContent
@@ -78,7 +83,7 @@
78
83
  if (children === void 0) return;
79
84
  const normalizedText = normalizeText(filterSnapshots({
80
85
  snapshots: children,
81
- filter: (element) => element.role === "text"
86
+ filter: isTextSnapshot
82
87
  }).map((textNode) => textNode.name).join(" "));
83
88
  return normalizedText.length > 0 ? normalizedText : void 0;
84
89
  }
@@ -190,6 +195,7 @@
190
195
  return {
191
196
  role,
192
197
  name: resolveAccessibleName(element, false),
198
+ attributes: {},
193
199
  children
194
200
  };
195
201
  }
@@ -396,7 +402,8 @@
396
402
  value,
397
403
  checked: resolveChecked(element),
398
404
  ...snapshotCommonInputAttributes(element, value === void 0)
399
- }
405
+ },
406
+ children: []
400
407
  };
401
408
  }
402
409
  function snapshotTextareaElement(element) {
@@ -407,7 +414,8 @@
407
414
  attributes: {
408
415
  value,
409
416
  ...snapshotCommonInputAttributes(element, value === void 0)
410
- }
417
+ },
418
+ children: []
411
419
  };
412
420
  }
413
421
  function snapshotCommonInputAttributes(element, isEmpty) {
@@ -454,6 +462,7 @@
454
462
  value,
455
463
  ...snapshotCommonInputAttributes(element, value === void 0)
456
464
  },
465
+ children: [],
457
466
  options
458
467
  };
459
468
  }
@@ -512,6 +521,7 @@
512
521
  return {
513
522
  role: "group",
514
523
  name: resolveGroupName(element),
524
+ attributes: {},
515
525
  children: snapshotChildren(element)
516
526
  };
517
527
  }
@@ -552,7 +562,9 @@
552
562
  if (imageName === void 0) return null;
553
563
  return {
554
564
  role: "img",
555
- name: imageName
565
+ name: imageName,
566
+ attributes: {},
567
+ children: []
556
568
  };
557
569
  }
558
570
  function resolveImageName(element) {
@@ -608,6 +620,7 @@
608
620
  function snapshotSeparator(element) {
609
621
  return {
610
622
  role: "separator",
623
+ attributes: {},
611
624
  children: snapshotPresentationalChildren(element)
612
625
  };
613
626
  }
package/dist/index.d.mts CHANGED
@@ -40,7 +40,7 @@ interface CommonInputAttributes extends InputStateAttributes, DiscribableAttribu
40
40
  //#endregion
41
41
  //#region src/browser/combobox.d.ts
42
42
  interface ComboboxSnapshot extends GenericElementSnapshot<"combobox", ComboboxAttributes> {
43
- options?: Array<OptionSnapshot>;
43
+ options: Array<OptionSnapshot>;
44
44
  }
45
45
  interface ComboboxAttributes extends CommonInputAttributes {
46
46
  value?: string | Array<string>;
@@ -118,20 +118,17 @@ type NodeRole = ElementRole | "text";
118
118
  type ElementRole = "heading" | "link" | "button" | "option" | "tab" | "menuitem" | "columnheader" | "group" | "radiogroup" | "progressbar" | "img" | "separator" | ContainerRole | InputRole | DialogRole;
119
119
  type NodeSnapshot = ElementSnapshot | TextSnapshot;
120
120
  type ElementSnapshot = ContainerSnapshot | HeadingSnapshot | LinkSnapshot | ButtonSnapshot | InputSnapshot | ComboboxSnapshot | OptionSnapshot | DialogSnapshot | TabSnapshot | MenuitemSnapshot | ColumnheaderSnapshot | GroupSnapshot | RadiogroupSnapshot | ProgressbarSnapshot | ImageSnapshot | SeparatorSnapshot;
121
- interface GenericElementSnapshot<TRole extends NodeRole = NodeRole, TAttributes = unknown> {
121
+ interface GenericElementSnapshot<TRole extends NodeRole = NodeRole, TAttributes = Record<string, unknown>> {
122
122
  role: TRole;
123
123
  name?: string;
124
- attributes?: TAttributes;
125
- children?: Array<NodeSnapshot>;
124
+ attributes: TAttributes;
125
+ children: Array<NodeSnapshot>;
126
126
  }
127
127
  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
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
132
  interface SnapshotFilterOptions {
136
133
  filter: SnapshotFilter;
137
134
  snapshots: Array<NodeSnapshot>;
@@ -142,7 +139,7 @@ interface GuardedSnapshotFilterOptions<TSnapshot extends NodeSnapshot> {
142
139
  snapshots: Array<NodeSnapshot>;
143
140
  recurse?: boolean;
144
141
  }
145
- declare function filterSnapshots<TSnapshot extends NodeSnapshot = NodeSnapshot>(options: GuardedSnapshotFilterOptions<TSnapshot>): Array<FilteredSnapshot<TSnapshot>>;
142
+ declare function filterSnapshots<TSnapshot extends NodeSnapshot = NodeSnapshot>(options: GuardedSnapshotFilterOptions<TSnapshot>): Array<TSnapshot>;
146
143
  declare function filterSnapshots(options: SnapshotFilterOptions): Array<NodeSnapshot>;
147
144
  //#endregion
148
145
  //#region src/playwright/snapshot.d.ts
package/dist/index.mjs CHANGED
@@ -28,6 +28,16 @@ var ElementSnapshotProxy = class {
28
28
  }
29
29
  };
30
30
 
31
+ //#endregion
32
+ //#region src/utils/guards.ts
33
+ function isTextSnapshot(snapshot) {
34
+ return snapshot.role === "text";
35
+ }
36
+ function isEmpty(value) {
37
+ if (typeof value === "string" || Array.isArray(value)) return value.length === 0;
38
+ return Object.keys(value).length === 0;
39
+ }
40
+
31
41
  //#endregion
32
42
  //#region src/utils/snapshot.ts
33
43
  function filterSnapshots(options) {
@@ -44,12 +54,12 @@ function filterSnapshots(options) {
44
54
  if (!isFilteredIn) return filteredChildren;
45
55
  return {
46
56
  ...snapshot,
47
- children: filteredChildren.length > 0 ? filteredChildren : void 0
57
+ children: filteredChildren
48
58
  };
49
59
  });
50
60
  }
51
61
  function hasChildren(snapshot) {
52
- return "children" in snapshot && snapshot.children !== void 0 && snapshot.children.length > 0;
62
+ return "children" in snapshot && snapshot.children.length > 0;
53
63
  }
54
64
 
55
65
  //#endregion
@@ -81,7 +91,7 @@ var ElementSnapshotTransformer = class {
81
91
  return snapshots.map((snapshot) => this.transformSnapshotRecursive(snapshot));
82
92
  }
83
93
  transformSnapshotRecursive(snapshot) {
84
- if (snapshot.role === "text") return this.simplifyTextSnapshot(snapshot);
94
+ if (isTextSnapshot(snapshot)) return this.simplifyTextSnapshot(snapshot);
85
95
  return this.simplifyElementSnapshot(snapshot);
86
96
  }
87
97
  simplifyTextSnapshot(snapshot) {
@@ -104,25 +114,26 @@ var ElementSnapshotTransformer = class {
104
114
  if (snapshot.role === "combobox") return this.simplifyComboboxSnapshot(snapshot);
105
115
  const { role, name, attributes, children } = normalizedSnapshot;
106
116
  return this.transformedSnapshot(role, {
107
- name,
117
+ name: name.length === 0 ? void 0 : name,
108
118
  ...attributes,
109
- children
119
+ children: children.length === 0 ? void 0 : children
110
120
  });
111
121
  }
112
122
  normalizeElementSnapshot(snapshot) {
113
- const sparseAttributes = this.removeUndefinedProperties(snapshot.attributes ?? {});
114
- const transformedChildren = this.transformSnapshots(snapshot?.children ?? []);
115
- const nameEqualsChildren = transformedChildren.length === 1 && snapshot.name === transformedChildren.at(0);
123
+ const normalizedName = snapshot.name ?? "";
124
+ const sparseAttributes = this.removeUndefinedProperties(snapshot.attributes);
125
+ const transformedChildren = this.transformSnapshots(snapshot.children);
126
+ const nameEqualsChildren = transformedChildren.length === 1 && normalizedName === transformedChildren.at(0);
116
127
  return {
117
128
  role: snapshot.role,
118
- name: snapshot.name,
129
+ name: normalizedName,
119
130
  attributes: sparseAttributes,
120
- children: nameEqualsChildren ? void 0 : transformedChildren.length === 0 ? void 0 : transformedChildren
131
+ children: nameEqualsChildren ? [] : transformedChildren
121
132
  };
122
133
  }
123
134
  simplifyComboboxSnapshot(snapshot) {
124
135
  const { role, name, attributes } = this.normalizeElementSnapshot(snapshot);
125
- const transformedOptions = (snapshot.options ?? []).map((optionSnapshot) => this.simplifyElementSnapshot(optionSnapshot));
136
+ const transformedOptions = snapshot.options.map((optionSnapshot) => this.simplifyElementSnapshot(optionSnapshot));
126
137
  return this.transformedSnapshot(role, {
127
138
  name,
128
139
  ...attributes,
@@ -130,20 +141,20 @@ var ElementSnapshotTransformer = class {
130
141
  });
131
142
  }
132
143
  isEmpty(snapshot) {
133
- return snapshot.name === void 0 && (snapshot.attributes === void 0 || Object.keys(snapshot.attributes).length === 0) && (snapshot.children === void 0 || snapshot.children.length === 0);
144
+ return isEmpty(snapshot.name) && isEmpty(snapshot.attributes) && isEmpty(snapshot.children);
134
145
  }
135
146
  hasOnlyName(snapshot) {
136
- return snapshot.name !== void 0 && snapshot.attributes === void 0 && snapshot.children === void 0;
147
+ return !isEmpty(snapshot.name) && isEmpty(snapshot.attributes) && isEmpty(snapshot.children);
137
148
  }
138
149
  hasOnlyChildren(snapshot) {
139
- return snapshot.name === void 0 && snapshot.attributes === void 0 && snapshot.children !== void 0;
150
+ return isEmpty(snapshot.name) && isEmpty(snapshot.attributes) && !isEmpty(snapshot.children);
140
151
  }
141
152
  removeUndefinedProperties(attributes) {
142
153
  const sparseAttributes = {};
143
154
  Object.entries(attributes).forEach(([key, value]) => {
144
155
  if (value !== void 0) sparseAttributes[key] = value;
145
156
  });
146
- return Object.keys(sparseAttributes).length > 0 ? sparseAttributes : void 0;
157
+ return sparseAttributes;
147
158
  }
148
159
  transformedSnapshot(role, content) {
149
160
  return { [role]: content };
package/package.json CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "@cronn/element-snapshot",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Element snapshots for Playwright",
5
+ "bugs": {
6
+ "url": "https://github.com/cronn/file-snapshots/issues"
7
+ },
5
8
  "author": "cronn",
6
9
  "license": "Apache-2.0",
7
10
  "repository": {
8
11
  "type": "git",
9
- "url": "https://github.com/cronn/file-snapshots.git",
12
+ "url": "git+https://github.com/cronn/file-snapshots.git",
10
13
  "directory": "packages/element-snapshot"
11
14
  },
12
15
  "homepage": "https://github.com/cronn/file-snapshots",
@@ -40,19 +43,21 @@
40
43
  "package-directory": "8.2.0"
41
44
  },
42
45
  "devDependencies": {
46
+ "@arethetypeswrong/core": "0.18.2",
43
47
  "@playwright/test": "1.58.2",
44
48
  "@trivago/prettier-plugin-sort-imports": "6.0.2",
45
- "@types/node": "24.10.12",
49
+ "@typescript/native-preview": "7.0.0-dev.20260218.1",
50
+ "@types/node": "24.10.13",
46
51
  "@vitest/coverage-v8": "4.0.18",
47
- "eslint": "9.39.2",
52
+ "eslint": "10.0.1",
48
53
  "eslint-config-prettier": "10.1.8",
49
- "eslint-plugin-unused-imports": "4.3.0",
54
+ "eslint-plugin-unused-imports": "4.4.1",
50
55
  "prettier": "3.8.1",
56
+ "publint": "0.3.17",
51
57
  "tsdown": "0.20.3",
52
- "typescript": "5.9.3",
53
- "typescript-eslint": "8.54.0",
58
+ "typescript-eslint": "8.56.0",
54
59
  "vitest": "4.0.18",
55
- "@cronn/playwright-file-snapshots": "0.38.1",
60
+ "@cronn/playwright-file-snapshots": "1.0.0",
56
61
  "@cronn/shared-configs": "0.0.0",
57
62
  "@cronn/test-utils": "0.0.0"
58
63
  },
@@ -60,13 +65,13 @@
60
65
  "@playwright/test": "^1.55"
61
66
  },
62
67
  "scripts": {
63
- "lint:check": "eslint src/ --max-warnings=0",
64
- "lint:fix": "eslint src/ --max-warnings=0 --fix",
68
+ "lint:check": "eslint src/ tests/ --max-warnings=0",
69
+ "lint:fix": "eslint src/ tests/ --max-warnings=0 --fix",
65
70
  "test:unit": "vitest run",
66
71
  "test:unit:coverage": "vitest run --coverage",
67
72
  "test:integration": "playwright test",
68
73
  "playwright:install": "playwright install chromium",
69
- "compile": "tsc",
74
+ "compile": "tsgo",
70
75
  "build": "tsdown"
71
76
  }
72
77
  }