@testivai/witness 1.0.1 → 1.0.3

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.
Files changed (92) hide show
  1. package/README.md +44 -13
  2. package/dist/baselines/index.d.ts +6 -0
  3. package/dist/baselines/index.d.ts.map +1 -0
  4. package/dist/baselines/index.js +9 -0
  5. package/dist/baselines/index.js.map +1 -0
  6. package/dist/baselines/store.d.ts +100 -0
  7. package/dist/baselines/store.d.ts.map +1 -0
  8. package/dist/baselines/store.js +298 -0
  9. package/dist/baselines/store.js.map +1 -0
  10. package/dist/bin/testivai.js +2 -0
  11. package/dist/bin/testivai.js.map +1 -1
  12. package/dist/browser/binding.d.ts.map +1 -1
  13. package/dist/browser/binding.js +173 -42
  14. package/dist/browser/binding.js.map +1 -1
  15. package/dist/browser/capture.d.ts.map +1 -1
  16. package/dist/browser/capture.js +7 -4
  17. package/dist/browser/capture.js.map +1 -1
  18. package/dist/commands/approve.d.ts +3 -0
  19. package/dist/commands/approve.d.ts.map +1 -0
  20. package/dist/commands/approve.js +94 -0
  21. package/dist/commands/approve.js.map +1 -0
  22. package/dist/commands/init.d.ts.map +1 -1
  23. package/dist/commands/init.js +53 -0
  24. package/dist/commands/init.js.map +1 -1
  25. package/dist/commands/run.d.ts.map +1 -1
  26. package/dist/commands/run.js +98 -0
  27. package/dist/commands/run.js.map +1 -1
  28. package/dist/config/index.d.ts +6 -0
  29. package/dist/config/index.d.ts.map +1 -0
  30. package/dist/config/index.js +14 -0
  31. package/dist/config/index.js.map +1 -0
  32. package/dist/config/local-config.d.ts +54 -0
  33. package/dist/config/local-config.d.ts.map +1 -0
  34. package/dist/config/local-config.js +130 -0
  35. package/dist/config/local-config.js.map +1 -0
  36. package/dist/diff/diff.d.ts +27 -0
  37. package/dist/diff/diff.d.ts.map +1 -0
  38. package/dist/diff/diff.js +216 -0
  39. package/dist/diff/diff.js.map +1 -0
  40. package/dist/diff/dom-diff.d.ts +85 -0
  41. package/dist/diff/dom-diff.d.ts.map +1 -0
  42. package/dist/diff/dom-diff.js +291 -0
  43. package/dist/diff/dom-diff.js.map +1 -0
  44. package/dist/diff/ignore.d.ts +22 -0
  45. package/dist/diff/ignore.d.ts.map +1 -0
  46. package/dist/diff/ignore.js +43 -0
  47. package/dist/diff/ignore.js.map +1 -0
  48. package/dist/diff/index.d.ts +18 -0
  49. package/dist/diff/index.d.ts.map +1 -0
  50. package/dist/diff/index.js +25 -0
  51. package/dist/diff/index.js.map +1 -0
  52. package/dist/diff/minimap.d.ts +23 -0
  53. package/dist/diff/minimap.d.ts.map +1 -0
  54. package/dist/diff/minimap.js +43 -0
  55. package/dist/diff/minimap.js.map +1 -0
  56. package/dist/diff/regions.d.ts +23 -0
  57. package/dist/diff/regions.d.ts.map +1 -0
  58. package/dist/diff/regions.js +129 -0
  59. package/dist/diff/regions.js.map +1 -0
  60. package/dist/diff/resize.d.ts +27 -0
  61. package/dist/diff/resize.d.ts.map +1 -0
  62. package/dist/diff/resize.js +82 -0
  63. package/dist/diff/resize.js.map +1 -0
  64. package/dist/diff/types.d.ts +79 -0
  65. package/dist/diff/types.d.ts.map +1 -0
  66. package/dist/diff/types.js +10 -0
  67. package/dist/diff/types.js.map +1 -0
  68. package/dist/index.d.ts +8 -0
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +23 -2
  71. package/dist/index.js.map +1 -1
  72. package/dist/report/compare.d.ts +18 -0
  73. package/dist/report/compare.d.ts.map +1 -0
  74. package/dist/report/compare.js +193 -0
  75. package/dist/report/compare.js.map +1 -0
  76. package/dist/report/generator.d.ts +31 -0
  77. package/dist/report/generator.d.ts.map +1 -0
  78. package/dist/report/generator.js +123 -0
  79. package/dist/report/generator.js.map +1 -0
  80. package/dist/report/index.d.ts +10 -0
  81. package/dist/report/index.d.ts.map +1 -0
  82. package/dist/report/index.js +13 -0
  83. package/dist/report/index.js.map +1 -0
  84. package/dist/report/results.d.ts +56 -0
  85. package/dist/report/results.d.ts.map +1 -0
  86. package/dist/report/results.js +8 -0
  87. package/dist/report/results.js.map +1 -0
  88. package/dist/report/template.d.ts +14 -0
  89. package/dist/report/template.d.ts.map +1 -0
  90. package/dist/report/template.js +275 -0
  91. package/dist/report/template.js.map +1 -0
  92. package/package.json +58 -15
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ /**
3
+ * TestivAI Diff Engine — Ignore regions
4
+ *
5
+ * Before the diff loop runs, copy candidate pixel values into the
6
+ * baseline buffer for ignored regions. This makes ignored areas
7
+ * appear identical to the differ.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.applyIgnoreRegions = applyIgnoreRegions;
11
+ /**
12
+ * Mask ignored regions by copying candidate pixels into baseline.
13
+ * After this, the diff loop will see no difference in those areas.
14
+ *
15
+ * Mutates `baseline` in place.
16
+ *
17
+ * @param baseline - Baseline pixel buffer (will be mutated)
18
+ * @param candidate - Candidate pixel buffer
19
+ * @param width - Image width
20
+ * @param height - Image height
21
+ * @param regions - Regions to ignore
22
+ */
23
+ function applyIgnoreRegions(baseline, candidate, width, height, regions) {
24
+ for (const region of regions) {
25
+ // Clamp to image bounds
26
+ const x0 = Math.max(0, Math.min(region.x, width));
27
+ const y0 = Math.max(0, Math.min(region.y, height));
28
+ const x1 = Math.max(0, Math.min(region.x + region.width, width));
29
+ const y1 = Math.max(0, Math.min(region.y + region.height, height));
30
+ for (let y = y0; y < y1; y++) {
31
+ const rowOffset = y * width * 4;
32
+ for (let x = x0; x < x1; x++) {
33
+ const pixelOffset = rowOffset + x * 4;
34
+ // Copy RGBA from candidate to baseline
35
+ baseline[pixelOffset] = candidate[pixelOffset];
36
+ baseline[pixelOffset + 1] = candidate[pixelOffset + 1];
37
+ baseline[pixelOffset + 2] = candidate[pixelOffset + 2];
38
+ baseline[pixelOffset + 3] = candidate[pixelOffset + 3];
39
+ }
40
+ }
41
+ }
42
+ }
43
+ //# sourceMappingURL=ignore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ignore.js","sourceRoot":"","sources":["../../src/diff/ignore.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAgBH,gDA0BC;AAtCD;;;;;;;;;;;GAWG;AACH,SAAgB,kBAAkB,CAChC,QAAwC,EACxC,SAAyC,EACzC,KAAa,EACb,MAAc,EACd,OAAuB;IAEvB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,wBAAwB;QACxB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QAClD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACnD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACjE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAEnE,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YAChC,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,MAAM,WAAW,GAAG,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC;gBACtC,uCAAuC;gBACvC,QAAQ,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;gBAC/C,QAAQ,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;gBACvD,QAAQ,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;gBACvD,QAAQ,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * TestivAI Diff Engine
3
+ *
4
+ * Pixel-level visual comparison engine forked from pixel-buffer-diff (Pbd)
5
+ * by @p01 (MIT license). Extended with ignore regions, size mismatch
6
+ * handling, region detection, and TypeScript support.
7
+ *
8
+ * @see https://github.com/p01/pixel-buffer-diff
9
+ */
10
+ export { diff } from './diff';
11
+ export { applyIgnoreRegions } from './ignore';
12
+ export { applyMinimap } from './minimap';
13
+ export { normalizeDimensions } from './resize';
14
+ export { detectRegions } from './regions';
15
+ export { domDiff } from './dom-diff';
16
+ export type { DiffOptions, DiffResult, DiffRegion, IgnoreRegion, SizeMismatch, PbdRawResult, } from './types';
17
+ export type { DomDiffResult, DomDiffSummary } from './dom-diff';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/diff/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,YAAY,EACV,WAAW,EACX,UAAU,EACV,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ /**
3
+ * TestivAI Diff Engine
4
+ *
5
+ * Pixel-level visual comparison engine forked from pixel-buffer-diff (Pbd)
6
+ * by @p01 (MIT license). Extended with ignore regions, size mismatch
7
+ * handling, region detection, and TypeScript support.
8
+ *
9
+ * @see https://github.com/p01/pixel-buffer-diff
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.domDiff = exports.detectRegions = exports.normalizeDimensions = exports.applyMinimap = exports.applyIgnoreRegions = exports.diff = void 0;
13
+ var diff_1 = require("./diff");
14
+ Object.defineProperty(exports, "diff", { enumerable: true, get: function () { return diff_1.diff; } });
15
+ var ignore_1 = require("./ignore");
16
+ Object.defineProperty(exports, "applyIgnoreRegions", { enumerable: true, get: function () { return ignore_1.applyIgnoreRegions; } });
17
+ var minimap_1 = require("./minimap");
18
+ Object.defineProperty(exports, "applyMinimap", { enumerable: true, get: function () { return minimap_1.applyMinimap; } });
19
+ var resize_1 = require("./resize");
20
+ Object.defineProperty(exports, "normalizeDimensions", { enumerable: true, get: function () { return resize_1.normalizeDimensions; } });
21
+ var regions_1 = require("./regions");
22
+ Object.defineProperty(exports, "detectRegions", { enumerable: true, get: function () { return regions_1.detectRegions; } });
23
+ var dom_diff_1 = require("./dom-diff");
24
+ Object.defineProperty(exports, "domDiff", { enumerable: true, get: function () { return dom_diff_1.domDiff; } });
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/diff/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,+BAA8B;AAArB,4FAAA,IAAI,OAAA;AACb,mCAA8C;AAArC,4GAAA,kBAAkB,OAAA;AAC3B,qCAAyC;AAAhC,uGAAA,YAAY,OAAA;AACrB,mCAA+C;AAAtC,6GAAA,mBAAmB,OAAA;AAC5B,qCAA0C;AAAjC,wGAAA,aAAa,OAAA;AACtB,uCAAqC;AAA5B,mGAAA,OAAO,OAAA"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * TestivAI Diff Engine — Minimap overlay
3
+ *
4
+ * Applies a low-resolution overlay on the diff buffer to help
5
+ * spot isolated pixel changes at a glance.
6
+ *
7
+ * Ported from pixel-buffer-diff by @p01, licensed under MIT.
8
+ */
9
+ /**
10
+ * Apply minimap overlay to the diff buffer.
11
+ * Regions with any changed pixels get a colored tint.
12
+ *
13
+ * @param diff32 - Diff image as Uint32Array
14
+ * @param miniMap - Minimap cell hit counts
15
+ * @param miniWidth - Number of minimap columns
16
+ * @param miniHeight - Number of minimap rows
17
+ * @param width - Full image width
18
+ * @param height - Full image height
19
+ * @param scale - Pixels per minimap cell (e.g. 128)
20
+ * @param color - 32-bit ABGR color to OR into diff pixels
21
+ */
22
+ export declare function applyMinimap(diff32: Uint32Array, miniMap: Uint8ClampedArray, miniWidth: number, miniHeight: number, width: number, height: number, scale: number, color: number): void;
23
+ //# sourceMappingURL=minimap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minimap.d.ts","sourceRoot":"","sources":["../../src/diff/minimap.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,iBAAiB,EAC1B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,IAAI,CAkBN"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ /**
3
+ * TestivAI Diff Engine — Minimap overlay
4
+ *
5
+ * Applies a low-resolution overlay on the diff buffer to help
6
+ * spot isolated pixel changes at a glance.
7
+ *
8
+ * Ported from pixel-buffer-diff by @p01, licensed under MIT.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.applyMinimap = applyMinimap;
12
+ /**
13
+ * Apply minimap overlay to the diff buffer.
14
+ * Regions with any changed pixels get a colored tint.
15
+ *
16
+ * @param diff32 - Diff image as Uint32Array
17
+ * @param miniMap - Minimap cell hit counts
18
+ * @param miniWidth - Number of minimap columns
19
+ * @param miniHeight - Number of minimap rows
20
+ * @param width - Full image width
21
+ * @param height - Full image height
22
+ * @param scale - Pixels per minimap cell (e.g. 128)
23
+ * @param color - 32-bit ABGR color to OR into diff pixels
24
+ */
25
+ function applyMinimap(diff32, miniMap, miniWidth, miniHeight, width, height, scale, color) {
26
+ for (let i = 0; i < miniWidth * miniHeight; i++) {
27
+ if (miniMap[i] > 0) {
28
+ const miniX = i % miniWidth;
29
+ const miniY = (i / miniWidth) | 0;
30
+ const x0 = miniX * scale;
31
+ const x1 = Math.min(x0 + scale, width);
32
+ const y0 = miniY * scale;
33
+ const y1 = Math.min(y0 + scale, height);
34
+ for (let y = y0; y < y1; y++) {
35
+ let d32i = x0 + y * width;
36
+ for (let x = x0; x < x1; x++) {
37
+ diff32[d32i++] |= color;
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
43
+ //# sourceMappingURL=minimap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minimap.js","sourceRoot":"","sources":["../../src/diff/minimap.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAeH,oCA2BC;AAxCD;;;;;;;;;;;;GAYG;AACH,SAAgB,YAAY,CAC1B,MAAmB,EACnB,OAA0B,EAC1B,SAAiB,EACjB,UAAkB,EAClB,KAAa,EACb,MAAc,EACd,KAAa,EACb,KAAa;IAEb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC;YAC5B,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,CAAC;YACzB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;YACvC,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,CAAC;YACzB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC;YAExC,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;gBAC1B,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC7B,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * TestivAI Diff Engine — Region bounding box detection
3
+ *
4
+ * Scans the diff output buffer for non-zero (changed) pixels
5
+ * and groups them into rectangular bounding boxes using a simple
6
+ * connected-component labeling approach.
7
+ */
8
+ import { DiffRegion } from './types';
9
+ /**
10
+ * Detect regions of change in the diff buffer.
11
+ *
12
+ * Scans for non-transparent pixels (any pixel with alpha > 0 in
13
+ * the diff output), groups adjacent changed pixels into rectangular
14
+ * bounding boxes, and filters out regions smaller than minSize.
15
+ *
16
+ * @param diff8 - Diff image pixel buffer (RGBA)
17
+ * @param width - Image width
18
+ * @param height - Image height
19
+ * @param minSize - Minimum pixels to include a region (default: 10)
20
+ * @returns Array of DiffRegion bounding boxes
21
+ */
22
+ export declare function detectRegions(diff8: Uint8Array | Uint8ClampedArray, width: number, height: number, minSize?: number): DiffRegion[];
23
+ //# sourceMappingURL=regions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regions.d.ts","sourceRoot":"","sources":["../../src/diff/regions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,UAAU,GAAG,iBAAiB,EACrC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,MAAW,GACnB,UAAU,EAAE,CAkHd"}
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ /**
3
+ * TestivAI Diff Engine — Region bounding box detection
4
+ *
5
+ * Scans the diff output buffer for non-zero (changed) pixels
6
+ * and groups them into rectangular bounding boxes using a simple
7
+ * connected-component labeling approach.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.detectRegions = detectRegions;
11
+ /**
12
+ * Detect regions of change in the diff buffer.
13
+ *
14
+ * Scans for non-transparent pixels (any pixel with alpha > 0 in
15
+ * the diff output), groups adjacent changed pixels into rectangular
16
+ * bounding boxes, and filters out regions smaller than minSize.
17
+ *
18
+ * @param diff8 - Diff image pixel buffer (RGBA)
19
+ * @param width - Image width
20
+ * @param height - Image height
21
+ * @param minSize - Minimum pixels to include a region (default: 10)
22
+ * @returns Array of DiffRegion bounding boxes
23
+ */
24
+ function detectRegions(diff8, width, height, minSize = 10) {
25
+ // Build a binary grid: 1 = changed pixel, 0 = unchanged
26
+ const changed = new Uint8Array(width * height);
27
+ for (let y = 0; y < height; y++) {
28
+ for (let x = 0; x < width; x++) {
29
+ const idx = (y * width + x) * 4;
30
+ // A pixel is considered "changed" if it has any non-zero alpha
31
+ // in the diff buffer (the diff engine writes colored pixels for changes)
32
+ if (diff8[idx + 3] > 0) {
33
+ changed[y * width + x] = 1;
34
+ }
35
+ }
36
+ }
37
+ // Connected-component labeling using union-find
38
+ const labels = new Int32Array(width * height).fill(-1);
39
+ const parent = [];
40
+ let nextLabel = 0;
41
+ function find(x) {
42
+ while (parent[x] !== x) {
43
+ parent[x] = parent[parent[x]]; // path compression
44
+ x = parent[x];
45
+ }
46
+ return x;
47
+ }
48
+ function union(a, b) {
49
+ const ra = find(a);
50
+ const rb = find(b);
51
+ if (ra !== rb) {
52
+ parent[rb] = ra;
53
+ }
54
+ }
55
+ // First pass: assign labels
56
+ for (let y = 0; y < height; y++) {
57
+ for (let x = 0; x < width; x++) {
58
+ const idx = y * width + x;
59
+ if (!changed[idx])
60
+ continue;
61
+ const neighbors = [];
62
+ // Check left
63
+ if (x > 0 && labels[idx - 1] >= 0) {
64
+ neighbors.push(labels[idx - 1]);
65
+ }
66
+ // Check above
67
+ if (y > 0 && labels[idx - width] >= 0) {
68
+ neighbors.push(labels[idx - width]);
69
+ }
70
+ if (neighbors.length === 0) {
71
+ // New label
72
+ labels[idx] = nextLabel;
73
+ parent.push(nextLabel);
74
+ nextLabel++;
75
+ }
76
+ else {
77
+ // Use the smallest label
78
+ const minLabel = Math.min(...neighbors.map(find));
79
+ labels[idx] = minLabel;
80
+ // Union all neighbor labels
81
+ for (const n of neighbors) {
82
+ union(minLabel, n);
83
+ }
84
+ }
85
+ }
86
+ }
87
+ // Second pass: collect bounding boxes per component
88
+ const boxes = new Map();
89
+ for (let y = 0; y < height; y++) {
90
+ for (let x = 0; x < width; x++) {
91
+ const idx = y * width + x;
92
+ if (labels[idx] < 0)
93
+ continue;
94
+ const root = find(labels[idx]);
95
+ const box = boxes.get(root);
96
+ if (box) {
97
+ box.x0 = Math.min(box.x0, x);
98
+ box.y0 = Math.min(box.y0, y);
99
+ box.x1 = Math.max(box.x1, x);
100
+ box.y1 = Math.max(box.y1, y);
101
+ box.count++;
102
+ }
103
+ else {
104
+ boxes.set(root, { x0: x, y0: y, x1: x, y1: y, count: 1 });
105
+ }
106
+ }
107
+ }
108
+ // Convert to DiffRegion array, filtering by minSize
109
+ const regions = [];
110
+ for (const box of boxes.values()) {
111
+ if (box.count < minSize)
112
+ continue;
113
+ const regionWidth = box.x1 - box.x0 + 1;
114
+ const regionHeight = box.y1 - box.y0 + 1;
115
+ const regionArea = regionWidth * regionHeight;
116
+ regions.push({
117
+ x: box.x0,
118
+ y: box.y0,
119
+ width: regionWidth,
120
+ height: regionHeight,
121
+ diffPixels: box.count,
122
+ diffPercent: regionArea > 0 ? (box.count / regionArea) * 100 : 0,
123
+ });
124
+ }
125
+ // Sort by position (top-left first)
126
+ regions.sort((a, b) => a.y - b.y || a.x - b.x);
127
+ return regions;
128
+ }
129
+ //# sourceMappingURL=regions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regions.js","sourceRoot":"","sources":["../../src/diff/regions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * TestivAI Diff Engine — Size mismatch handling
3
+ *
4
+ * When baseline and candidate have different dimensions,
5
+ * normalize them before diffing.
6
+ */
7
+ import { SizeMismatch } from './types';
8
+ export interface NormalizeResult {
9
+ normalizedBaseline: Uint8ClampedArray;
10
+ normalizedCandidate: Uint8ClampedArray;
11
+ width: number;
12
+ height: number;
13
+ sizeMismatch: SizeMismatch;
14
+ }
15
+ /**
16
+ * Normalize two pixel buffers to the same dimensions.
17
+ *
18
+ * @param baseline - Baseline pixel buffer (RGBA)
19
+ * @param bw - Baseline width
20
+ * @param bh - Baseline height
21
+ * @param candidate - Candidate pixel buffer (RGBA)
22
+ * @param cw - Candidate width
23
+ * @param ch - Candidate height
24
+ * @param mode - 'pad' (fill with transparent), 'crop' (use min dims), or 'error'
25
+ */
26
+ export declare function normalizeDimensions(baseline: Uint8Array | Uint8ClampedArray, bw: number, bh: number, candidate: Uint8Array | Uint8ClampedArray, cw: number, ch: number, mode: 'pad' | 'crop' | 'error'): NormalizeResult;
27
+ //# sourceMappingURL=resize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resize.d.ts","sourceRoot":"","sources":["../../src/diff/resize.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,WAAW,eAAe;IAC9B,kBAAkB,EAAE,iBAAiB,CAAC;IACtC,mBAAmB,EAAE,iBAAiB,CAAC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,UAAU,GAAG,iBAAiB,EACxC,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,UAAU,GAAG,iBAAiB,EACzC,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAC7B,eAAe,CA0EjB"}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /**
3
+ * TestivAI Diff Engine — Size mismatch handling
4
+ *
5
+ * When baseline and candidate have different dimensions,
6
+ * normalize them before diffing.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.normalizeDimensions = normalizeDimensions;
10
+ /**
11
+ * Normalize two pixel buffers to the same dimensions.
12
+ *
13
+ * @param baseline - Baseline pixel buffer (RGBA)
14
+ * @param bw - Baseline width
15
+ * @param bh - Baseline height
16
+ * @param candidate - Candidate pixel buffer (RGBA)
17
+ * @param cw - Candidate width
18
+ * @param ch - Candidate height
19
+ * @param mode - 'pad' (fill with transparent), 'crop' (use min dims), or 'error'
20
+ */
21
+ function normalizeDimensions(baseline, bw, bh, candidate, cw, ch, mode) {
22
+ if (bw === cw && bh === ch) {
23
+ return {
24
+ normalizedBaseline: new Uint8ClampedArray(baseline),
25
+ normalizedCandidate: new Uint8ClampedArray(candidate),
26
+ width: bw,
27
+ height: bh,
28
+ sizeMismatch: {
29
+ baseline: { width: bw, height: bh },
30
+ candidate: { width: cw, height: ch },
31
+ normalized: { width: bw, height: bh },
32
+ },
33
+ };
34
+ }
35
+ if (mode === 'error') {
36
+ throw new Error(`Size mismatch: baseline is ${bw}×${bh}, candidate is ${cw}×${ch}. ` +
37
+ `Set handleSizeMismatch to 'pad' or 'crop' to handle this automatically.`);
38
+ }
39
+ let targetWidth;
40
+ let targetHeight;
41
+ if (mode === 'pad') {
42
+ targetWidth = Math.max(bw, cw);
43
+ targetHeight = Math.max(bh, ch);
44
+ }
45
+ else {
46
+ // crop
47
+ targetWidth = Math.min(bw, cw);
48
+ targetHeight = Math.min(bh, ch);
49
+ }
50
+ const normalizedBaseline = new Uint8ClampedArray(targetWidth * targetHeight * 4);
51
+ const normalizedCandidate = new Uint8ClampedArray(targetWidth * targetHeight * 4);
52
+ // Copy baseline rows
53
+ const copyWidthB = Math.min(bw, targetWidth);
54
+ const copyHeightB = Math.min(bh, targetHeight);
55
+ for (let y = 0; y < copyHeightB; y++) {
56
+ const srcStart = y * bw * 4;
57
+ const dstStart = y * targetWidth * 4;
58
+ const bytesToCopy = copyWidthB * 4;
59
+ normalizedBaseline.set(baseline.slice(srcStart, srcStart + bytesToCopy), dstStart);
60
+ }
61
+ // Copy candidate rows
62
+ const copyWidthC = Math.min(cw, targetWidth);
63
+ const copyHeightC = Math.min(ch, targetHeight);
64
+ for (let y = 0; y < copyHeightC; y++) {
65
+ const srcStart = y * cw * 4;
66
+ const dstStart = y * targetWidth * 4;
67
+ const bytesToCopy = copyWidthC * 4;
68
+ normalizedCandidate.set(candidate.slice(srcStart, srcStart + bytesToCopy), dstStart);
69
+ }
70
+ return {
71
+ normalizedBaseline,
72
+ normalizedCandidate,
73
+ width: targetWidth,
74
+ height: targetHeight,
75
+ sizeMismatch: {
76
+ baseline: { width: bw, height: bh },
77
+ candidate: { width: cw, height: ch },
78
+ normalized: { width: targetWidth, height: targetHeight },
79
+ },
80
+ };
81
+ }
82
+ //# sourceMappingURL=resize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resize.js","sourceRoot":"","sources":["../../src/diff/resize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * TestivAI Diff Engine Types
3
+ *
4
+ * Originally forked from pixel-buffer-diff (Pbd) by @p01.
5
+ * Extended with ignore regions, size mismatch handling,
6
+ * region detection, and TypeScript support.
7
+ */
8
+ export interface DiffOptions {
9
+ /** Individual pixel matching threshold (0-1). Default: 0.1 */
10
+ threshold?: number;
11
+ /** Cumulated pixel matching threshold for anti-aliasing filtering. Default: 0.5 */
12
+ cumulatedThreshold?: number;
13
+ /** Enable low-resolution minimap overlay on diff output. Default: false */
14
+ enableMinimap?: boolean;
15
+ /** Coordinate-based regions to ignore during comparison */
16
+ ignoreRegions?: IgnoreRegion[];
17
+ /** Detect and return bounding boxes of changed regions. Default: false */
18
+ detectRegions?: boolean;
19
+ /** How to handle size mismatches between baseline and candidate */
20
+ handleSizeMismatch?: 'pad' | 'crop' | 'error';
21
+ }
22
+ export interface IgnoreRegion {
23
+ x: number;
24
+ y: number;
25
+ width: number;
26
+ height: number;
27
+ }
28
+ export interface DiffResult {
29
+ /** Number of pixels that exceeded the threshold */
30
+ diffCount: number;
31
+ /** Cumulated difference of every pixel change (for anti-aliasing detection) */
32
+ cumulatedDiff: number;
33
+ /** Numeric hash of pixel changes for deduplication */
34
+ hash: number;
35
+ /** Percentage of pixels that differ (0-100) */
36
+ diffPercent: number;
37
+ /** Total number of pixels compared */
38
+ totalPixels: number;
39
+ /** True if images are identical (within thresholds) */
40
+ isIdentical: boolean;
41
+ /** Bounding boxes of change clusters (if detectRegions was enabled) */
42
+ regions?: DiffRegion[];
43
+ /** Size mismatch info (if dimensions differed and were normalized) */
44
+ sizeMismatch?: SizeMismatch;
45
+ }
46
+ export interface DiffRegion {
47
+ x: number;
48
+ y: number;
49
+ width: number;
50
+ height: number;
51
+ /** Number of changed pixels within this region's bounding box */
52
+ diffPixels: number;
53
+ /** Percentage of changed pixels within this region's bounding box */
54
+ diffPercent: number;
55
+ }
56
+ export interface SizeMismatch {
57
+ baseline: {
58
+ width: number;
59
+ height: number;
60
+ };
61
+ candidate: {
62
+ width: number;
63
+ height: number;
64
+ };
65
+ normalized: {
66
+ width: number;
67
+ height: number;
68
+ };
69
+ }
70
+ /**
71
+ * Raw result from the core Pbd diff loop (before extensions).
72
+ * @internal
73
+ */
74
+ export interface PbdRawResult {
75
+ diff: number;
76
+ cumulatedDiff: number;
77
+ hash: number;
78
+ }
79
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /**
3
+ * TestivAI Diff Engine Types
4
+ *
5
+ * Originally forked from pixel-buffer-diff (Pbd) by @p01.
6
+ * Extended with ignore regions, size mismatch handling,
7
+ * region detection, and TypeScript support.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/diff/types.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG"}
package/dist/index.d.ts CHANGED
@@ -11,10 +11,18 @@ export { logger, createLogger } from './utils/logger';
11
11
  export { toSafeFilename, generateUniqueFilename, extractNameFromUrl, sanitizeTestName, isSafeFilename } from './utils/file-naming';
12
12
  export { ProcessManager, spawnProcess, setupSignalHandlers, commandExists } from './utils/process';
13
13
  export { FrameworkDetector } from './utils/framework-detect';
14
+ export * from './diff';
15
+ export { BaselineStore } from './baselines';
16
+ export type { BaselineMetadata } from './baselines';
17
+ export { loadLocalConfig, createDefaultConfig, localConfigExists, isLocalMode, getConfigPath, getDefaultConfig, } from './config';
18
+ export type { LocalConfig } from './config';
19
+ export { generateReport, compareAll, renderHtml } from './report';
20
+ export type { GenerateReportOptions, CompareOptions, ReportData, ReportSummary, SnapshotResult, SnapshotStatus } from './report';
14
21
  export { authCommand } from './commands/auth';
15
22
  export { initCommand } from './commands/init';
16
23
  export { runCommand } from './commands/run';
17
24
  export { witnessCommand } from './commands/capture';
25
+ export { approveCommand } from './commands/approve';
18
26
  export { CoreApiClient, DEFAULT_CORE_API_URL, saveCredentials, loadCredentials, deleteCredentials, getApiKey, isAuthenticated, findConfigFile, loadConfig, configExists, getOutputDir, CompressionHelper, compressionHelper, } from '@testivai/common';
19
27
  export declare const VERSION: any;
20
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAG9E,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACnI,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,cAAc,EACd,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,eAAO,MAAM,OAAO,KAAwC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAG9E,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACnI,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,cAAc,QAAQ,CAAC;AAGvB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,gBAAgB,GACjB,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG5C,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAClE,YAAY,EAAE,qBAAqB,EAAE,cAAc,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAGjI,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,cAAc,EACd,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAI1B,eAAO,MAAM,OAAO,KAAqC,CAAC"}