@testivai/witness 1.3.0 → 1.4.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/dist/commands/report.d.ts.map +1 -1
- package/dist/commands/report.js +3 -1
- package/dist/commands/report.js.map +1 -1
- package/dist/config/local-config.d.ts +17 -0
- package/dist/config/local-config.d.ts.map +1 -1
- package/dist/config/local-config.js +8 -0
- package/dist/config/local-config.js.map +1 -1
- package/dist/diff/diff.d.ts.map +1 -1
- package/dist/diff/diff.js +13 -2
- package/dist/diff/diff.js.map +1 -1
- package/dist/diff/mask.d.ts +98 -0
- package/dist/diff/mask.d.ts.map +1 -0
- package/dist/diff/mask.js +209 -0
- package/dist/diff/mask.js.map +1 -0
- package/dist/diff/regions.d.ts +17 -4
- package/dist/diff/regions.d.ts.map +1 -1
- package/dist/diff/regions.js +70 -5
- package/dist/diff/regions.js.map +1 -1
- package/dist/diff/types.d.ts +13 -0
- package/dist/diff/types.d.ts.map +1 -1
- package/dist/report/compare.d.ts +9 -0
- package/dist/report/compare.d.ts.map +1 -1
- package/dist/report/compare.js +72 -12
- package/dist/report/compare.js.map +1 -1
- package/dist/report/generator.d.ts +12 -1
- package/dist/report/generator.d.ts.map +1 -1
- package/dist/report/generator.js +36 -15
- package/dist/report/generator.js.map +1 -1
- package/dist/report/results.d.ts +12 -0
- package/dist/report/results.d.ts.map +1 -1
- package/dist/report/template.d.ts.map +1 -1
- package/dist/report/template.js +74 -0
- package/dist/report/template.js.map +1 -1
- package/package.json +1 -1
package/dist/diff/regions.js
CHANGED
|
@@ -7,21 +7,36 @@
|
|
|
7
7
|
* connected-component labeling approach.
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.DEFAULT_REGION_OPTIONS = void 0;
|
|
10
11
|
exports.detectRegions = detectRegions;
|
|
12
|
+
exports.mergeRegions = mergeRegions;
|
|
13
|
+
/** Defaults for region clustering (config-overridable). */
|
|
14
|
+
exports.DEFAULT_REGION_OPTIONS = {
|
|
15
|
+
minSize: 10,
|
|
16
|
+
mergeDistance: 12,
|
|
17
|
+
};
|
|
11
18
|
/**
|
|
12
19
|
* Detect regions of change in the diff buffer.
|
|
13
20
|
*
|
|
14
21
|
* Scans for non-transparent pixels (any pixel with alpha > 0 in
|
|
15
22
|
* the diff output), groups adjacent changed pixels into rectangular
|
|
16
|
-
* bounding boxes,
|
|
23
|
+
* bounding boxes, filters out regions smaller than the noise floor,
|
|
24
|
+
* and merges regions whose bounding boxes are within mergeDistance px
|
|
25
|
+
* of each other (an anti-fragmentation pass — one logical change often
|
|
26
|
+
* rasterizes as several nearby specks).
|
|
17
27
|
*
|
|
18
28
|
* @param diff8 - Diff image pixel buffer (RGBA)
|
|
19
29
|
* @param width - Image width
|
|
20
30
|
* @param height - Image height
|
|
21
|
-
* @param
|
|
31
|
+
* @param options - { minSize, mergeDistance }, or a bare number meaning
|
|
32
|
+
* minSize (legacy signature, mergeDistance 0)
|
|
22
33
|
* @returns Array of DiffRegion bounding boxes
|
|
23
34
|
*/
|
|
24
|
-
function detectRegions(diff8, width, height,
|
|
35
|
+
function detectRegions(diff8, width, height, options = {}) {
|
|
36
|
+
const opts = typeof options === 'number'
|
|
37
|
+
? { minSize: options, mergeDistance: 0 }
|
|
38
|
+
: { ...exports.DEFAULT_REGION_OPTIONS, ...options };
|
|
39
|
+
const minSize = opts.minSize;
|
|
25
40
|
// Build a binary grid: 1 = changed pixel, 0 = unchanged
|
|
26
41
|
const changed = new Uint8Array(width * height);
|
|
27
42
|
for (let y = 0; y < height; y++) {
|
|
@@ -122,8 +137,58 @@ function detectRegions(diff8, width, height, minSize = 10) {
|
|
|
122
137
|
diffPercent: regionArea > 0 ? (box.count / regionArea) * 100 : 0,
|
|
123
138
|
});
|
|
124
139
|
}
|
|
140
|
+
const merged = mergeRegions(regions, opts.mergeDistance);
|
|
125
141
|
// Sort by position (top-left first)
|
|
126
|
-
|
|
127
|
-
return
|
|
142
|
+
merged.sort((a, b) => a.y - b.y || a.x - b.x);
|
|
143
|
+
return merged;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Merge regions whose bounding boxes are within `distance` px of each
|
|
147
|
+
* other (Chebyshev gap: both axis gaps must be within the distance).
|
|
148
|
+
* Merging cascades until stable; pixel counts sum, boxes union.
|
|
149
|
+
* Region counts are small, so the O(n²) pass is fine.
|
|
150
|
+
*/
|
|
151
|
+
function mergeRegions(regions, distance) {
|
|
152
|
+
if (distance <= 0 || regions.length < 2)
|
|
153
|
+
return regions;
|
|
154
|
+
const gap = (a, b) => {
|
|
155
|
+
const dx = Math.max(0, Math.max(a.x, b.x) - Math.min(a.x + a.width, b.x + b.width));
|
|
156
|
+
const dy = Math.max(0, Math.max(a.y, b.y) - Math.min(a.y + a.height, b.y + b.height));
|
|
157
|
+
return Math.max(dx, dy);
|
|
158
|
+
};
|
|
159
|
+
const out = [...regions];
|
|
160
|
+
let mergedAny = true;
|
|
161
|
+
while (mergedAny) {
|
|
162
|
+
mergedAny = false;
|
|
163
|
+
outer: for (let i = 0; i < out.length; i++) {
|
|
164
|
+
for (let j = i + 1; j < out.length; j++) {
|
|
165
|
+
if (gap(out[i], out[j]) <= distance) {
|
|
166
|
+
const a = out[i];
|
|
167
|
+
const b = out[j];
|
|
168
|
+
const x0 = Math.min(a.x, b.x);
|
|
169
|
+
const y0 = Math.min(a.y, b.y);
|
|
170
|
+
const x1 = Math.max(a.x + a.width, b.x + b.width);
|
|
171
|
+
const y1 = Math.max(a.y + a.height, b.y + b.height);
|
|
172
|
+
const union = {
|
|
173
|
+
x: x0,
|
|
174
|
+
y: y0,
|
|
175
|
+
width: x1 - x0,
|
|
176
|
+
height: y1 - y0,
|
|
177
|
+
diffPixels: a.diffPixels + b.diffPixels,
|
|
178
|
+
diffPercent: 0, // recomputed below
|
|
179
|
+
};
|
|
180
|
+
out.splice(j, 1);
|
|
181
|
+
out[i] = union;
|
|
182
|
+
mergedAny = true;
|
|
183
|
+
break outer;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
for (const r of out) {
|
|
189
|
+
const area = r.width * r.height;
|
|
190
|
+
r.diffPercent = area > 0 ? (r.diffPixels / area) * 100 : 0;
|
|
191
|
+
}
|
|
192
|
+
return out;
|
|
128
193
|
}
|
|
129
194
|
//# sourceMappingURL=regions.js.map
|
package/dist/diff/regions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"regions.js","sourceRoot":"","sources":["../../src/diff/regions.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG
|
|
1
|
+
{"version":3,"file":"regions.js","sourceRoot":"","sources":["../../src/diff/regions.ts"],"names":[],"mappings":"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"}
|
package/dist/diff/types.d.ts
CHANGED
|
@@ -16,9 +16,22 @@ export interface DiffOptions {
|
|
|
16
16
|
ignoreRegions?: IgnoreRegion[];
|
|
17
17
|
/** Detect and return bounding boxes of changed regions. Default: false */
|
|
18
18
|
detectRegions?: boolean;
|
|
19
|
+
/** Clustering tunables used when detectRegions is enabled. */
|
|
20
|
+
regionOptions?: RegionOptions;
|
|
21
|
+
/**
|
|
22
|
+
* Resolved mask rects: excluded from diffing (candidate copied over
|
|
23
|
+
* baseline) AND hatched in the diff output for auditability.
|
|
24
|
+
*/
|
|
25
|
+
masks?: import('./mask').MaskRect[];
|
|
19
26
|
/** How to handle size mismatches between baseline and candidate */
|
|
20
27
|
handleSizeMismatch?: 'pad' | 'crop' | 'error';
|
|
21
28
|
}
|
|
29
|
+
export interface RegionOptions {
|
|
30
|
+
/** Minimum changed pixels for a region to count (noise floor). Default 10. */
|
|
31
|
+
minSize?: number;
|
|
32
|
+
/** Merge regions whose boxes are within this many px. Default 12. */
|
|
33
|
+
mergeDistance?: number;
|
|
34
|
+
}
|
|
22
35
|
export interface IgnoreRegion {
|
|
23
36
|
x: number;
|
|
24
37
|
y: number;
|
package/dist/diff/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/diff/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,WAAW;IAC1B,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2DAA2D;IAC3D,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mEAAmE;IACnE,kBAAkB,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;CAC/C;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,CAAC;IACtB,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,WAAW,EAAE,OAAO,CAAC;IACrB,uEAAuE;IACvE,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,sEAAsE;IACtE,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/diff/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,WAAW;IAC1B,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2DAA2D;IAC3D,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACpC,mEAAmE;IACnE,kBAAkB,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;CAC/C;AAED,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,CAAC;IACtB,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,WAAW,EAAE,OAAO,CAAC;IACrB,uEAAuE;IACvE,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,sEAAsE;IACtE,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd"}
|
package/dist/report/compare.d.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Diffs all temp captures against baselines using the Phase 1 diff engine.
|
|
5
5
|
*/
|
|
6
6
|
import { SnapshotResult } from './results';
|
|
7
|
+
import { MaskSpec } from '../diff/mask';
|
|
8
|
+
import { RegionOptions } from '../diff/types';
|
|
7
9
|
export interface CompareOptions {
|
|
8
10
|
threshold?: number;
|
|
9
11
|
projectRoot: string;
|
|
@@ -14,6 +16,13 @@ export interface CompareOptions {
|
|
|
14
16
|
* marks the snapshot changed.
|
|
15
17
|
*/
|
|
16
18
|
passCriteria?: PassCriteria;
|
|
19
|
+
/**
|
|
20
|
+
* Global masks (from .testivai/config.json `mask`). Merged with any
|
|
21
|
+
* per-call masks recorded in the capture's metadata.
|
|
22
|
+
*/
|
|
23
|
+
mask?: MaskSpec[];
|
|
24
|
+
/** Region clustering tunables (config `diffRegions`). */
|
|
25
|
+
diffRegions?: RegionOptions;
|
|
17
26
|
}
|
|
18
27
|
export interface PassCriteria {
|
|
19
28
|
/** Pass when diff percentage (0-100) is at or below this. Default 0. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../src/report/compare.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,EAAqB,cAAc,EAAkB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../src/report/compare.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,EAAqB,cAAc,EAAkB,MAAM,WAAW,CAAC;AAC9E,OAAO,EAEL,QAAQ,EAET,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC;IAClB,yDAAyD;IACzD,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B;AAsBD,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+FAA+F;IAC/F,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,EAAE,CA8EpE"}
|
package/dist/report/compare.js
CHANGED
|
@@ -45,13 +45,24 @@ const pngjs_1 = require("pngjs");
|
|
|
45
45
|
const diff_1 = require("../diff");
|
|
46
46
|
const dom_diff_1 = require("../diff/dom-diff");
|
|
47
47
|
const store_1 = require("../baselines/store");
|
|
48
|
+
const mask_1 = require("../diff/mask");
|
|
49
|
+
function readTempMaskMetadata(projectRoot, name) {
|
|
50
|
+
const metaPath = path.join(projectRoot, '.testivai', 'temp', name, 'metadata.json');
|
|
51
|
+
try {
|
|
52
|
+
const parsed = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
|
|
53
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return {}; // absent or malformed metadata never breaks the compare
|
|
57
|
+
}
|
|
58
|
+
}
|
|
48
59
|
/**
|
|
49
60
|
* Compare all temp screenshots against their baselines.
|
|
50
61
|
*
|
|
51
62
|
* @returns Array of SnapshotResult for each snapshot
|
|
52
63
|
*/
|
|
53
64
|
function compareAll(options) {
|
|
54
|
-
const { projectRoot, reportDir, threshold = 0.1, passCriteria = {} } = options;
|
|
65
|
+
const { projectRoot, reportDir, threshold = 0.1, passCriteria = {}, diffRegions } = options;
|
|
55
66
|
const store = new store_1.BaselineStore(projectRoot);
|
|
56
67
|
const tempNames = store.listTemp();
|
|
57
68
|
const results = [];
|
|
@@ -87,7 +98,16 @@ function compareAll(options) {
|
|
|
87
98
|
// screenshots from the browser, we need to handle the PNG decoding.
|
|
88
99
|
// For simplicity and zero-dep, we do a byte-level comparison first,
|
|
89
100
|
// then fall back to diff engine for actual pixel data.
|
|
90
|
-
const
|
|
101
|
+
const captureMeta = readTempMaskMetadata(projectRoot, name);
|
|
102
|
+
const result = compareBuffers(baselineBuffer, tempBuffer, name, snapshotImagesDir, threshold, {
|
|
103
|
+
configMasks: options.mask ?? [],
|
|
104
|
+
callMasks: [
|
|
105
|
+
...(captureMeta.masks ?? []),
|
|
106
|
+
...(captureMeta.maskSelectors ?? []),
|
|
107
|
+
],
|
|
108
|
+
capturedRects: captureMeta.maskRects,
|
|
109
|
+
regionOptions: diffRegions,
|
|
110
|
+
});
|
|
91
111
|
// DOM-level noise hint. Only meaningful when both sides captured DOM.
|
|
92
112
|
// For 'passed' (pixel-identical) we skip the work — it's already the
|
|
93
113
|
// strongest possible signal.
|
|
@@ -151,6 +171,17 @@ function computeDomSignal(baselineDom, candidateDom) {
|
|
|
151
171
|
noiseHint: !result.domChanged,
|
|
152
172
|
};
|
|
153
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Read a PNG's dimensions from its IHDR header without a full decode.
|
|
176
|
+
* Returns null for anything that doesn't look like a PNG.
|
|
177
|
+
*/
|
|
178
|
+
function readPngDims(buffer) {
|
|
179
|
+
// PNG signature (8 bytes) + IHDR length/type (8) → width at 16, height at 20
|
|
180
|
+
if (buffer.length < 24 || buffer.readUInt32BE(12) !== 0x49484452 /* 'IHDR' */) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
return { width: buffer.readUInt32BE(16), height: buffer.readUInt32BE(20) };
|
|
184
|
+
}
|
|
154
185
|
/**
|
|
155
186
|
* Decode a PNG buffer to raw RGBA pixel data using pngjs.
|
|
156
187
|
*/
|
|
@@ -166,16 +197,10 @@ function encodePng(data, width, height) {
|
|
|
166
197
|
png.data = data;
|
|
167
198
|
return pngjs_1.PNG.sync.write(png);
|
|
168
199
|
}
|
|
169
|
-
|
|
170
|
-
* Compare two PNG buffers.
|
|
171
|
-
*
|
|
172
|
-
* Decodes both PNGs to raw RGBA, runs the pixel-level diff engine,
|
|
173
|
-
* writes a valid diff PNG, and returns a SnapshotResult.
|
|
174
|
-
*/
|
|
175
|
-
function compareBuffers(baselineBuffer, candidateBuffer, name, snapshotImagesDir, threshold) {
|
|
200
|
+
function compareBuffers(baselineBuffer, candidateBuffer, name, snapshotImagesDir, threshold, maskContext = { configMasks: [], callMasks: [] }) {
|
|
176
201
|
// Quick byte-level comparison — identical files need no decoding
|
|
177
202
|
if (baselineBuffer.equals(candidateBuffer)) {
|
|
178
|
-
|
|
203
|
+
const result = {
|
|
179
204
|
name,
|
|
180
205
|
status: 'passed',
|
|
181
206
|
diffPercent: 0,
|
|
@@ -184,6 +209,23 @@ function compareBuffers(baselineBuffer, candidateBuffer, name, snapshotImagesDir
|
|
|
184
209
|
baselinePath: `images/${name}/baseline.png`,
|
|
185
210
|
currentPath: `images/${name}/current.png`,
|
|
186
211
|
};
|
|
212
|
+
// Masks are moot for identical bytes, but the audit trail (and any
|
|
213
|
+
// could-not-apply warnings) must still surface. Header-only dims read.
|
|
214
|
+
const specCount = maskContext.configMasks.length + maskContext.callMasks.length;
|
|
215
|
+
if (specCount > 0) {
|
|
216
|
+
const dims = readPngDims(baselineBuffer);
|
|
217
|
+
if (dims) {
|
|
218
|
+
const fromConfig = (0, mask_1.resolveMasks)(maskContext.configMasks, dims.width, dims.height, maskContext.capturedRects, 'config');
|
|
219
|
+
const fromCall = (0, mask_1.resolveMasks)(maskContext.callMasks, dims.width, dims.height, maskContext.capturedRects, 'call');
|
|
220
|
+
const rects = [...fromConfig.rects, ...fromCall.rects];
|
|
221
|
+
const warnings = [...fromConfig.warnings, ...fromCall.warnings];
|
|
222
|
+
if (rects.length > 0)
|
|
223
|
+
result.masks = rects;
|
|
224
|
+
if (warnings.length > 0)
|
|
225
|
+
result.maskWarnings = warnings;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
187
229
|
}
|
|
188
230
|
try {
|
|
189
231
|
// Decode PNG → raw RGBA so the diff engine gets real pixel data
|
|
@@ -198,7 +240,18 @@ function compareBuffers(baselineBuffer, candidateBuffer, name, snapshotImagesDir
|
|
|
198
240
|
const candidate8 = new Uint8ClampedArray(expectedLen);
|
|
199
241
|
candidate8.set(new Uint8ClampedArray(candidate.data.buffer, candidate.data.byteOffset, Math.min(candidate.data.length, expectedLen)));
|
|
200
242
|
const diffOutput = new Uint8ClampedArray(expectedLen);
|
|
201
|
-
|
|
243
|
+
// Resolve masks against this image's dimensions. Config and per-call
|
|
244
|
+
// specs are resolved separately so the audit trail records the origin.
|
|
245
|
+
const fromConfig = (0, mask_1.resolveMasks)(maskContext.configMasks, width, height, maskContext.capturedRects, 'config');
|
|
246
|
+
const fromCall = (0, mask_1.resolveMasks)(maskContext.callMasks, width, height, maskContext.capturedRects, 'call');
|
|
247
|
+
const maskRects = [...fromConfig.rects, ...fromCall.rects];
|
|
248
|
+
const maskWarnings = [...fromConfig.warnings, ...fromCall.warnings];
|
|
249
|
+
const diffResult = (0, diff_1.diff)(baseline8, candidate8, diffOutput, width, height, {
|
|
250
|
+
threshold,
|
|
251
|
+
masks: maskRects,
|
|
252
|
+
detectRegions: true,
|
|
253
|
+
regionOptions: maskContext.regionOptions,
|
|
254
|
+
});
|
|
202
255
|
// Encode the diff RGBA back to a valid PNG and write it
|
|
203
256
|
const diffPngBuffer = encodePng(Buffer.from(diffOutput.buffer), width, height);
|
|
204
257
|
const diffPath = path.join(snapshotImagesDir, 'diff.png');
|
|
@@ -206,7 +259,7 @@ function compareBuffers(baselineBuffer, candidateBuffer, name, snapshotImagesDir
|
|
|
206
259
|
// Status starts as 'changed'; applyPassCriteria() in compareAll may
|
|
207
260
|
// flip it to 'passed' based on the configured tolerances.
|
|
208
261
|
const status = 'changed';
|
|
209
|
-
|
|
262
|
+
const result = {
|
|
210
263
|
name,
|
|
211
264
|
status,
|
|
212
265
|
diffPercent: diffResult.diffPercent,
|
|
@@ -216,6 +269,13 @@ function compareBuffers(baselineBuffer, candidateBuffer, name, snapshotImagesDir
|
|
|
216
269
|
currentPath: `images/${name}/current.png`,
|
|
217
270
|
diffPath: `images/${name}/diff.png`,
|
|
218
271
|
};
|
|
272
|
+
if (diffResult.regions)
|
|
273
|
+
result.regions = diffResult.regions;
|
|
274
|
+
if (maskRects.length > 0)
|
|
275
|
+
result.masks = maskRects;
|
|
276
|
+
if (maskWarnings.length > 0)
|
|
277
|
+
result.maskWarnings = maskWarnings;
|
|
278
|
+
return result;
|
|
219
279
|
}
|
|
220
280
|
catch (err) {
|
|
221
281
|
// PNG decode failed (corrupt file, unexpected format) — report as changed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compare.js","sourceRoot":"","sources":["../../src/report/compare.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"compare.js","sourceRoot":"","sources":["../../src/report/compare.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* → render HTML → optionally auto-open browser.
|
|
6
6
|
*/
|
|
7
7
|
import { PassCriteria } from './compare';
|
|
8
|
-
import { ReportData } from './results';
|
|
8
|
+
import { ReportData, SnapshotResult } from './results';
|
|
9
9
|
export interface GenerateReportOptions {
|
|
10
10
|
projectRoot: string;
|
|
11
11
|
/** Directory for report output. Default: 'visual-report' */
|
|
@@ -35,5 +35,16 @@ export interface GenerateReportOptions {
|
|
|
35
35
|
*
|
|
36
36
|
* @returns The report data
|
|
37
37
|
*/
|
|
38
|
+
/**
|
|
39
|
+
* results.json schema version. 2.2.0 adds per-snapshot `regions[]`
|
|
40
|
+
* (clustered diff bounding boxes), `masks[]` (applied masks with their
|
|
41
|
+
* source — the audit trail), and `maskWarnings[]`. Additive over 2.1.0.
|
|
42
|
+
*/
|
|
43
|
+
export declare const RESULTS_SCHEMA_VERSION = "2.2.0";
|
|
44
|
+
/**
|
|
45
|
+
* Write results.json for an already-computed set of snapshot results.
|
|
46
|
+
* Exposed for callers that manage comparison and rendering separately.
|
|
47
|
+
*/
|
|
48
|
+
export declare function generateResults(results: SnapshotResult[], reportDir: string, version?: string): void;
|
|
38
49
|
export declare function generateReport(options: GenerateReportOptions): ReportData;
|
|
39
50
|
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAA8B,YAAY,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,UAAU,EAAiB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAA8B,YAAY,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,UAAU,EAAiB,cAAc,EAAC,MAAM,WAAW,CAAC;AAIrE,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;;;;;;;;GAUG;AACH;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,UAAU,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,cAAc,EAAE,EACzB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,MAA+B,GACvC,IAAI,CAGN;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,UAAU,CAqDzE"}
|
package/dist/report/generator.js
CHANGED
|
@@ -39,6 +39,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
};
|
|
40
40
|
})();
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.RESULTS_SCHEMA_VERSION = void 0;
|
|
43
|
+
exports.generateResults = generateResults;
|
|
42
44
|
exports.generateReport = generateReport;
|
|
43
45
|
const fs = __importStar(require("fs"));
|
|
44
46
|
const path = __importStar(require("path"));
|
|
@@ -57,8 +59,22 @@ const local_config_1 = require("../config/local-config");
|
|
|
57
59
|
*
|
|
58
60
|
* @returns The report data
|
|
59
61
|
*/
|
|
62
|
+
/**
|
|
63
|
+
* results.json schema version. 2.2.0 adds per-snapshot `regions[]`
|
|
64
|
+
* (clustered diff bounding boxes), `masks[]` (applied masks with their
|
|
65
|
+
* source — the audit trail), and `maskWarnings[]`. Additive over 2.1.0.
|
|
66
|
+
*/
|
|
67
|
+
exports.RESULTS_SCHEMA_VERSION = '2.2.0';
|
|
68
|
+
/**
|
|
69
|
+
* Write results.json for an already-computed set of snapshot results.
|
|
70
|
+
* Exposed for callers that manage comparison and rendering separately.
|
|
71
|
+
*/
|
|
72
|
+
function generateResults(results, reportDir, version = exports.RESULTS_SCHEMA_VERSION) {
|
|
73
|
+
const data = buildReportData(results, version);
|
|
74
|
+
fs.writeFileSync(path.join(reportDir, 'results.json'), JSON.stringify(data, null, 2));
|
|
75
|
+
}
|
|
60
76
|
function generateReport(options) {
|
|
61
|
-
const { projectRoot, reportDir: reportDirRelative = 'visual-report', threshold = 0.1, autoOpen = true, version =
|
|
77
|
+
const { projectRoot, reportDir: reportDirRelative = 'visual-report', threshold = 0.1, autoOpen = true, version = exports.RESULTS_SCHEMA_VERSION, } = options;
|
|
62
78
|
const reportDir = path.isAbsolute(reportDirRelative)
|
|
63
79
|
? reportDirRelative
|
|
64
80
|
: path.join(projectRoot, reportDirRelative);
|
|
@@ -78,22 +94,12 @@ function generateReport(options) {
|
|
|
78
94
|
reportDir,
|
|
79
95
|
threshold,
|
|
80
96
|
passCriteria,
|
|
97
|
+
mask: localConfig.mask,
|
|
98
|
+
diffRegions: localConfig.diffRegions,
|
|
81
99
|
};
|
|
82
100
|
const snapshots = (0, compare_1.compareAll)(compareOptions);
|
|
83
|
-
// 2. Build summary
|
|
84
|
-
const
|
|
85
|
-
total: snapshots.length,
|
|
86
|
-
passed: snapshots.filter((s) => s.status === 'passed').length,
|
|
87
|
-
changed: snapshots.filter((s) => s.status === 'changed').length,
|
|
88
|
-
newSnapshots: snapshots.filter((s) => s.status === 'new').length,
|
|
89
|
-
};
|
|
90
|
-
// 3. Build report data
|
|
91
|
-
const reportData = {
|
|
92
|
-
version,
|
|
93
|
-
timestamp: new Date().toISOString(),
|
|
94
|
-
summary,
|
|
95
|
-
snapshots,
|
|
96
|
-
};
|
|
101
|
+
// 2-3. Build summary + report data
|
|
102
|
+
const reportData = buildReportData(snapshots, version);
|
|
97
103
|
// 4. Write results.json
|
|
98
104
|
const resultsPath = path.join(reportDir, 'results.json');
|
|
99
105
|
fs.writeFileSync(resultsPath, JSON.stringify(reportData, null, 2));
|
|
@@ -107,6 +113,21 @@ function generateReport(options) {
|
|
|
107
113
|
}
|
|
108
114
|
return reportData;
|
|
109
115
|
}
|
|
116
|
+
/** Assemble the ReportData envelope for a set of snapshot results. */
|
|
117
|
+
function buildReportData(snapshots, version) {
|
|
118
|
+
const summary = {
|
|
119
|
+
total: snapshots.length,
|
|
120
|
+
passed: snapshots.filter((s) => s.status === 'passed').length,
|
|
121
|
+
changed: snapshots.filter((s) => s.status === 'changed').length,
|
|
122
|
+
newSnapshots: snapshots.filter((s) => s.status === 'new').length,
|
|
123
|
+
};
|
|
124
|
+
return {
|
|
125
|
+
version,
|
|
126
|
+
timestamp: new Date().toISOString(),
|
|
127
|
+
summary,
|
|
128
|
+
snapshots,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
110
131
|
/**
|
|
111
132
|
* Open a file in the default browser.
|
|
112
133
|
* Best-effort — does not throw on failure.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":";AAAA;;;;;GAKG
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":"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"}
|
package/dist/report/results.d.ts
CHANGED
|
@@ -41,6 +41,18 @@ export interface SnapshotResult {
|
|
|
41
41
|
* captured DOM HTML alongside the screenshot.
|
|
42
42
|
*/
|
|
43
43
|
dom?: SnapshotDomSignal;
|
|
44
|
+
/**
|
|
45
|
+
* Changed-pixel clusters as bounding boxes (top-left sorted). Present
|
|
46
|
+
* for 'changed' results (and auto-passed ones — the boxes stay useful).
|
|
47
|
+
*/
|
|
48
|
+
regions?: import('../diff/types').DiffRegion[];
|
|
49
|
+
/**
|
|
50
|
+
* Masks applied to this comparison (resolved to pixels, with their
|
|
51
|
+
* source) — the audit trail for excluded areas. Present when non-empty.
|
|
52
|
+
*/
|
|
53
|
+
masks?: import('../diff/mask').MaskRect[];
|
|
54
|
+
/** Mask specs that could not be applied (e.g. selector without captured geometry). */
|
|
55
|
+
maskWarnings?: string[];
|
|
44
56
|
/**
|
|
45
57
|
* Present when the snapshot's pixels differed but a pass criterion
|
|
46
58
|
* reported it as passed: 'threshold' (within maxDiffPercent /
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"results.d.ts","sourceRoot":"","sources":["../../src/report/results.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC;AAE1D,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACnG;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,GAAG,CAAC,EAAE,iBAAiB,CAAC;IACxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,aAAa,CAAC;IACvB,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B"}
|
|
1
|
+
{"version":3,"file":"results.d.ts","sourceRoot":"","sources":["../../src/report/results.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC;AAE1D,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACnG;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,GAAG,CAAC,EAAE,iBAAiB,CAAC;IACxB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,eAAe,EAAE,UAAU,EAAE,CAAC;IAC/C;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,cAAc,EAAE,QAAQ,EAAE,CAAC;IAC1C,sFAAsF;IACtF,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,aAAa,CAAC;IACvB,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/report/template.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAkB,MAAM,WAAW,CAAC;AAEvD;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/report/template.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAkB,MAAM,WAAW,CAAC;AAEvD;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CA+NnD"}
|