@testivai/witness 1.0.1 → 1.0.2
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 +44 -13
- package/dist/baselines/index.d.ts +6 -0
- package/dist/baselines/index.d.ts.map +1 -0
- package/dist/baselines/index.js +9 -0
- package/dist/baselines/index.js.map +1 -0
- package/dist/baselines/store.d.ts +79 -0
- package/dist/baselines/store.d.ts.map +1 -0
- package/dist/baselines/store.js +234 -0
- package/dist/baselines/store.js.map +1 -0
- package/dist/bin/testivai.js +2 -0
- package/dist/bin/testivai.js.map +1 -1
- package/dist/browser/binding.d.ts.map +1 -1
- package/dist/browser/binding.js +173 -42
- package/dist/browser/binding.js.map +1 -1
- package/dist/browser/capture.d.ts.map +1 -1
- package/dist/browser/capture.js +7 -4
- package/dist/browser/capture.js.map +1 -1
- package/dist/commands/approve.d.ts +3 -0
- package/dist/commands/approve.d.ts.map +1 -0
- package/dist/commands/approve.js +94 -0
- package/dist/commands/approve.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +53 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +98 -0
- package/dist/commands/run.js.map +1 -1
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +14 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/local-config.d.ts +54 -0
- package/dist/config/local-config.d.ts.map +1 -0
- package/dist/config/local-config.js +130 -0
- package/dist/config/local-config.js.map +1 -0
- package/dist/diff/diff.d.ts +27 -0
- package/dist/diff/diff.d.ts.map +1 -0
- package/dist/diff/diff.js +216 -0
- package/dist/diff/diff.js.map +1 -0
- package/dist/diff/ignore.d.ts +22 -0
- package/dist/diff/ignore.d.ts.map +1 -0
- package/dist/diff/ignore.js +43 -0
- package/dist/diff/ignore.js.map +1 -0
- package/dist/diff/index.d.ts +16 -0
- package/dist/diff/index.d.ts.map +1 -0
- package/dist/diff/index.js +23 -0
- package/dist/diff/index.js.map +1 -0
- package/dist/diff/minimap.d.ts +23 -0
- package/dist/diff/minimap.d.ts.map +1 -0
- package/dist/diff/minimap.js +43 -0
- package/dist/diff/minimap.js.map +1 -0
- package/dist/diff/regions.d.ts +23 -0
- package/dist/diff/regions.d.ts.map +1 -0
- package/dist/diff/regions.js +129 -0
- package/dist/diff/regions.js.map +1 -0
- package/dist/diff/resize.d.ts +27 -0
- package/dist/diff/resize.d.ts.map +1 -0
- package/dist/diff/resize.js +82 -0
- package/dist/diff/resize.js.map +1 -0
- package/dist/diff/types.d.ts +79 -0
- package/dist/diff/types.d.ts.map +1 -0
- package/dist/diff/types.js +10 -0
- package/dist/diff/types.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -2
- package/dist/index.js.map +1 -1
- package/dist/report/compare.d.ts +18 -0
- package/dist/report/compare.d.ts.map +1 -0
- package/dist/report/compare.js +163 -0
- package/dist/report/compare.js.map +1 -0
- package/dist/report/generator.d.ts +31 -0
- package/dist/report/generator.d.ts.map +1 -0
- package/dist/report/generator.js +123 -0
- package/dist/report/generator.js.map +1 -0
- package/dist/report/index.d.ts +10 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +13 -0
- package/dist/report/index.js.map +1 -0
- package/dist/report/results.d.ts +35 -0
- package/dist/report/results.d.ts.map +1 -0
- package/dist/report/results.js +8 -0
- package/dist/report/results.js.map +1 -0
- package/dist/report/template.d.ts +14 -0
- package/dist/report/template.d.ts.map +1 -0
- package/dist/report/template.js +229 -0
- package/dist/report/template.js.map +1 -0
- package/package.json +58 -15
|
@@ -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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
18
18
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.VERSION = exports.compressionHelper = exports.CompressionHelper = exports.getOutputDir = exports.configExists = exports.loadConfig = exports.findConfigFile = exports.isAuthenticated = exports.getApiKey = exports.deleteCredentials = exports.loadCredentials = exports.saveCredentials = exports.DEFAULT_CORE_API_URL = exports.CoreApiClient = exports.witnessCommand = exports.runCommand = exports.initCommand = exports.authCommand = exports.FrameworkDetector = exports.commandExists = exports.setupSignalHandlers = exports.spawnProcess = exports.ProcessManager = exports.isSafeFilename = exports.sanitizeTestName = exports.extractNameFromUrl = exports.generateUniqueFilename = exports.toSafeFilename = exports.createLogger = exports.logger = exports.BrowserDiscoveryError = exports.BrowserDiscovery = exports.BrowserBinding = exports.BrowserCapture = exports.BrowserClient = void 0;
|
|
21
|
+
exports.VERSION = exports.compressionHelper = exports.CompressionHelper = exports.getOutputDir = exports.configExists = exports.loadConfig = exports.findConfigFile = exports.isAuthenticated = exports.getApiKey = exports.deleteCredentials = exports.loadCredentials = exports.saveCredentials = exports.DEFAULT_CORE_API_URL = exports.CoreApiClient = exports.approveCommand = exports.witnessCommand = exports.runCommand = exports.initCommand = exports.authCommand = exports.renderHtml = exports.compareAll = exports.generateReport = exports.getDefaultConfig = exports.getConfigPath = exports.isLocalMode = exports.localConfigExists = exports.createDefaultConfig = exports.loadLocalConfig = exports.BaselineStore = exports.FrameworkDetector = exports.commandExists = exports.setupSignalHandlers = exports.spawnProcess = exports.ProcessManager = exports.isSafeFilename = exports.sanitizeTestName = exports.extractNameFromUrl = exports.generateUniqueFilename = exports.toSafeFilename = exports.createLogger = exports.logger = exports.BrowserDiscoveryError = exports.BrowserDiscovery = exports.BrowserBinding = exports.BrowserCapture = exports.BrowserClient = void 0;
|
|
22
22
|
// Export types
|
|
23
23
|
__exportStar(require("./types"), exports);
|
|
24
24
|
// Export browser modules
|
|
@@ -48,6 +48,24 @@ Object.defineProperty(exports, "setupSignalHandlers", { enumerable: true, get: f
|
|
|
48
48
|
Object.defineProperty(exports, "commandExists", { enumerable: true, get: function () { return process_1.commandExists; } });
|
|
49
49
|
var framework_detect_1 = require("./utils/framework-detect");
|
|
50
50
|
Object.defineProperty(exports, "FrameworkDetector", { enumerable: true, get: function () { return framework_detect_1.FrameworkDetector; } });
|
|
51
|
+
// Export diff engine
|
|
52
|
+
__exportStar(require("./diff"), exports);
|
|
53
|
+
// Export baselines
|
|
54
|
+
var baselines_1 = require("./baselines");
|
|
55
|
+
Object.defineProperty(exports, "BaselineStore", { enumerable: true, get: function () { return baselines_1.BaselineStore; } });
|
|
56
|
+
// Export local config
|
|
57
|
+
var config_1 = require("./config");
|
|
58
|
+
Object.defineProperty(exports, "loadLocalConfig", { enumerable: true, get: function () { return config_1.loadLocalConfig; } });
|
|
59
|
+
Object.defineProperty(exports, "createDefaultConfig", { enumerable: true, get: function () { return config_1.createDefaultConfig; } });
|
|
60
|
+
Object.defineProperty(exports, "localConfigExists", { enumerable: true, get: function () { return config_1.localConfigExists; } });
|
|
61
|
+
Object.defineProperty(exports, "isLocalMode", { enumerable: true, get: function () { return config_1.isLocalMode; } });
|
|
62
|
+
Object.defineProperty(exports, "getConfigPath", { enumerable: true, get: function () { return config_1.getConfigPath; } });
|
|
63
|
+
Object.defineProperty(exports, "getDefaultConfig", { enumerable: true, get: function () { return config_1.getDefaultConfig; } });
|
|
64
|
+
// Export report generator
|
|
65
|
+
var report_1 = require("./report");
|
|
66
|
+
Object.defineProperty(exports, "generateReport", { enumerable: true, get: function () { return report_1.generateReport; } });
|
|
67
|
+
Object.defineProperty(exports, "compareAll", { enumerable: true, get: function () { return report_1.compareAll; } });
|
|
68
|
+
Object.defineProperty(exports, "renderHtml", { enumerable: true, get: function () { return report_1.renderHtml; } });
|
|
51
69
|
// Export commands (for programmatic use)
|
|
52
70
|
var auth_1 = require("./commands/auth");
|
|
53
71
|
Object.defineProperty(exports, "authCommand", { enumerable: true, get: function () { return auth_1.authCommand; } });
|
|
@@ -57,6 +75,8 @@ var run_1 = require("./commands/run");
|
|
|
57
75
|
Object.defineProperty(exports, "runCommand", { enumerable: true, get: function () { return run_1.runCommand; } });
|
|
58
76
|
var capture_2 = require("./commands/capture");
|
|
59
77
|
Object.defineProperty(exports, "witnessCommand", { enumerable: true, get: function () { return capture_2.witnessCommand; } });
|
|
78
|
+
var approve_1 = require("./commands/approve");
|
|
79
|
+
Object.defineProperty(exports, "approveCommand", { enumerable: true, get: function () { return approve_1.approveCommand; } });
|
|
60
80
|
// Re-export common utilities
|
|
61
81
|
var common_1 = require("@testivai/common");
|
|
62
82
|
Object.defineProperty(exports, "CoreApiClient", { enumerable: true, get: function () { return common_1.CoreApiClient; } });
|
|
@@ -73,5 +93,6 @@ Object.defineProperty(exports, "getOutputDir", { enumerable: true, get: function
|
|
|
73
93
|
Object.defineProperty(exports, "CompressionHelper", { enumerable: true, get: function () { return common_1.CompressionHelper; } });
|
|
74
94
|
Object.defineProperty(exports, "compressionHelper", { enumerable: true, get: function () { return common_1.compressionHelper; } });
|
|
75
95
|
// Version
|
|
76
|
-
|
|
96
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
97
|
+
exports.VERSION = require('../package.json').version;
|
|
77
98
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,eAAe;AACf,0CAAwB;AAExB,yBAAyB;AACzB,2CAAiD;AAAxC,uGAAA,aAAa,OAAA;AACtB,6CAAmD;AAA1C,yGAAA,cAAc,OAAA;AACvB,6CAAmD;AAA1C,yGAAA,cAAc,OAAA;AACvB,iDAA8E;AAArE,6GAAA,gBAAgB,OAAA;AAAE,kHAAA,qBAAqB,OAAA;AAEhD,mBAAmB;AACnB,yCAAsD;AAA7C,gGAAA,MAAM,OAAA;AAAE,sGAAA,YAAY,OAAA;AAC7B,mDAAmI;AAA1H,6GAAA,cAAc,OAAA;AAAE,qHAAA,sBAAsB,OAAA;AAAE,iHAAA,kBAAkB,OAAA;AAAE,+GAAA,gBAAgB,OAAA;AAAE,6GAAA,cAAc,OAAA;AACrG,2CAAmG;AAA1F,yGAAA,cAAc,OAAA;AAAE,uGAAA,YAAY,OAAA;AAAE,8GAAA,mBAAmB,OAAA;AAAE,wGAAA,aAAa,OAAA;AACzE,6DAA6D;AAApD,qHAAA,iBAAiB,OAAA;AAE1B,yCAAyC;AACzC,wCAA8C;AAArC,mGAAA,WAAW,OAAA;AACpB,wCAA8C;AAArC,mGAAA,WAAW,OAAA;AACpB,sCAA4C;AAAnC,iGAAA,UAAU,OAAA;AACnB,8CAAoD;AAA3C,yGAAA,cAAc,OAAA;AAEvB,6BAA6B;AAC7B,2CAc0B;AAbxB,uGAAA,aAAa,OAAA;AACb,8GAAA,oBAAoB,OAAA;AACpB,yGAAA,eAAe,OAAA;AACf,yGAAA,eAAe,OAAA;AACf,2GAAA,iBAAiB,OAAA;AACjB,mGAAA,SAAS,OAAA;AACT,yGAAA,eAAe,OAAA;AACf,wGAAA,cAAc,OAAA;AACd,oGAAA,UAAU,OAAA;AACV,sGAAA,YAAY,OAAA;AACZ,sGAAA,YAAY,OAAA;AACZ,2GAAA,iBAAiB,OAAA;AACjB,2GAAA,iBAAiB,OAAA;AAGnB,UAAU;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,eAAe;AACf,0CAAwB;AAExB,yBAAyB;AACzB,2CAAiD;AAAxC,uGAAA,aAAa,OAAA;AACtB,6CAAmD;AAA1C,yGAAA,cAAc,OAAA;AACvB,6CAAmD;AAA1C,yGAAA,cAAc,OAAA;AACvB,iDAA8E;AAArE,6GAAA,gBAAgB,OAAA;AAAE,kHAAA,qBAAqB,OAAA;AAEhD,mBAAmB;AACnB,yCAAsD;AAA7C,gGAAA,MAAM,OAAA;AAAE,sGAAA,YAAY,OAAA;AAC7B,mDAAmI;AAA1H,6GAAA,cAAc,OAAA;AAAE,qHAAA,sBAAsB,OAAA;AAAE,iHAAA,kBAAkB,OAAA;AAAE,+GAAA,gBAAgB,OAAA;AAAE,6GAAA,cAAc,OAAA;AACrG,2CAAmG;AAA1F,yGAAA,cAAc,OAAA;AAAE,uGAAA,YAAY,OAAA;AAAE,8GAAA,mBAAmB,OAAA;AAAE,wGAAA,aAAa,OAAA;AACzE,6DAA6D;AAApD,qHAAA,iBAAiB,OAAA;AAE1B,qBAAqB;AACrB,yCAAuB;AAEvB,mBAAmB;AACnB,yCAA4C;AAAnC,0GAAA,aAAa,OAAA;AAGtB,sBAAsB;AACtB,mCAOkB;AANhB,yGAAA,eAAe,OAAA;AACf,6GAAA,mBAAmB,OAAA;AACnB,2GAAA,iBAAiB,OAAA;AACjB,qGAAA,WAAW,OAAA;AACX,uGAAA,aAAa,OAAA;AACb,0GAAA,gBAAgB,OAAA;AAIlB,0BAA0B;AAC1B,mCAAkE;AAAzD,wGAAA,cAAc,OAAA;AAAE,oGAAA,UAAU,OAAA;AAAE,oGAAA,UAAU,OAAA;AAG/C,yCAAyC;AACzC,wCAA8C;AAArC,mGAAA,WAAW,OAAA;AACpB,wCAA8C;AAArC,mGAAA,WAAW,OAAA;AACpB,sCAA4C;AAAnC,iGAAA,UAAU,OAAA;AACnB,8CAAoD;AAA3C,yGAAA,cAAc,OAAA;AACvB,8CAAoD;AAA3C,yGAAA,cAAc,OAAA;AAEvB,6BAA6B;AAC7B,2CAc0B;AAbxB,uGAAA,aAAa,OAAA;AACb,8GAAA,oBAAoB,OAAA;AACpB,yGAAA,eAAe,OAAA;AACf,yGAAA,eAAe,OAAA;AACf,2GAAA,iBAAiB,OAAA;AACjB,mGAAA,SAAS,OAAA;AACT,yGAAA,eAAe,OAAA;AACf,wGAAA,cAAc,OAAA;AACd,oGAAA,UAAU,OAAA;AACV,sGAAA,YAAY,OAAA;AACZ,sGAAA,YAAY,OAAA;AACZ,2GAAA,iBAAiB,OAAA;AACjB,2GAAA,iBAAiB,OAAA;AAGnB,UAAU;AACV,8DAA8D;AACjD,QAAA,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TestivAI Report — Compare all snapshots
|
|
3
|
+
*
|
|
4
|
+
* Diffs all temp captures against baselines using the Phase 1 diff engine.
|
|
5
|
+
*/
|
|
6
|
+
import { SnapshotResult } from './results';
|
|
7
|
+
export interface CompareOptions {
|
|
8
|
+
threshold?: number;
|
|
9
|
+
projectRoot: string;
|
|
10
|
+
reportDir: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Compare all temp screenshots against their baselines.
|
|
14
|
+
*
|
|
15
|
+
* @returns Array of SnapshotResult for each snapshot
|
|
16
|
+
*/
|
|
17
|
+
export declare function compareAll(options: CompareOptions): SnapshotResult[];
|
|
18
|
+
//# sourceMappingURL=compare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../src/report/compare.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAAE,cAAc,EAAkB,MAAM,WAAW,CAAC;AAE3D,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,EAAE,CAuDpE"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TestivAI Report — Compare all snapshots
|
|
4
|
+
*
|
|
5
|
+
* Diffs all temp captures against baselines using the Phase 1 diff engine.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.compareAll = compareAll;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const diff_1 = require("../diff");
|
|
45
|
+
const store_1 = require("../baselines/store");
|
|
46
|
+
/**
|
|
47
|
+
* Compare all temp screenshots against their baselines.
|
|
48
|
+
*
|
|
49
|
+
* @returns Array of SnapshotResult for each snapshot
|
|
50
|
+
*/
|
|
51
|
+
function compareAll(options) {
|
|
52
|
+
const { projectRoot, reportDir, threshold = 0.1 } = options;
|
|
53
|
+
const store = new store_1.BaselineStore(projectRoot);
|
|
54
|
+
const tempNames = store.listTemp();
|
|
55
|
+
const results = [];
|
|
56
|
+
const imagesDir = path.join(reportDir, 'images');
|
|
57
|
+
for (const name of tempNames) {
|
|
58
|
+
const snapshotImagesDir = path.join(imagesDir, name);
|
|
59
|
+
fs.mkdirSync(snapshotImagesDir, { recursive: true });
|
|
60
|
+
const tempBuffer = store.readTemp(name);
|
|
61
|
+
if (!tempBuffer)
|
|
62
|
+
continue;
|
|
63
|
+
// Write current image to report
|
|
64
|
+
const currentPath = path.join(snapshotImagesDir, 'current.png');
|
|
65
|
+
fs.writeFileSync(currentPath, tempBuffer);
|
|
66
|
+
if (!store.exists(name)) {
|
|
67
|
+
// New snapshot — no baseline to compare against
|
|
68
|
+
results.push({
|
|
69
|
+
name,
|
|
70
|
+
status: 'new',
|
|
71
|
+
diffPercent: 0,
|
|
72
|
+
diffCount: 0,
|
|
73
|
+
totalPixels: 0,
|
|
74
|
+
currentPath: `images/${name}/current.png`,
|
|
75
|
+
});
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
// Read baseline
|
|
79
|
+
const baselineBuffer = store.read(name);
|
|
80
|
+
const baselinePath = path.join(snapshotImagesDir, 'baseline.png');
|
|
81
|
+
fs.writeFileSync(baselinePath, baselineBuffer);
|
|
82
|
+
// Parse raw RGBA from PNG buffers
|
|
83
|
+
// For now, we compare raw buffers directly. In a real implementation
|
|
84
|
+
// we'd decode PNGs to RGBA pixel data. Since temp/baseline are raw
|
|
85
|
+
// screenshots from the browser, we need to handle the PNG decoding.
|
|
86
|
+
// For simplicity and zero-dep, we do a byte-level comparison first,
|
|
87
|
+
// then fall back to diff engine for actual pixel data.
|
|
88
|
+
const result = compareBuffers(baselineBuffer, tempBuffer, name, snapshotImagesDir, threshold);
|
|
89
|
+
results.push(result);
|
|
90
|
+
}
|
|
91
|
+
return results;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Compare two PNG buffers.
|
|
95
|
+
*
|
|
96
|
+
* If buffers are identical bytes, returns passed immediately.
|
|
97
|
+
* Otherwise attempts pixel-level diff using the diff engine.
|
|
98
|
+
*/
|
|
99
|
+
function compareBuffers(baselineBuffer, candidateBuffer, name, snapshotImagesDir, threshold) {
|
|
100
|
+
// Quick byte-level comparison
|
|
101
|
+
if (baselineBuffer.equals(candidateBuffer)) {
|
|
102
|
+
return {
|
|
103
|
+
name,
|
|
104
|
+
status: 'passed',
|
|
105
|
+
diffPercent: 0,
|
|
106
|
+
diffCount: 0,
|
|
107
|
+
totalPixels: 0,
|
|
108
|
+
baselinePath: `images/${name}/baseline.png`,
|
|
109
|
+
currentPath: `images/${name}/current.png`,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
// Buffers differ — attempt pixel-level diff
|
|
113
|
+
// We assume raw RGBA pixel data with known dimensions
|
|
114
|
+
// In practice, we need to decode PNGs first. For now, treat as raw RGBA.
|
|
115
|
+
// The actual PNG decoding will be added when fast-png is available.
|
|
116
|
+
try {
|
|
117
|
+
// Try to use as raw RGBA data
|
|
118
|
+
// Calculate dimensions assuming square-ish aspect ratio
|
|
119
|
+
const pixelCount = baselineBuffer.length / 4;
|
|
120
|
+
const width = Math.ceil(Math.sqrt(pixelCount));
|
|
121
|
+
const height = Math.ceil(pixelCount / width);
|
|
122
|
+
const expectedLen = width * height * 4;
|
|
123
|
+
// Pad buffers if needed
|
|
124
|
+
const baseline8 = new Uint8ClampedArray(expectedLen);
|
|
125
|
+
baseline8.set(new Uint8ClampedArray(baselineBuffer.buffer, baselineBuffer.byteOffset, Math.min(baselineBuffer.length, expectedLen)));
|
|
126
|
+
const candidate8 = new Uint8ClampedArray(expectedLen);
|
|
127
|
+
candidate8.set(new Uint8ClampedArray(candidateBuffer.buffer, candidateBuffer.byteOffset, Math.min(candidateBuffer.length, expectedLen)));
|
|
128
|
+
const diffOutput = new Uint8ClampedArray(expectedLen);
|
|
129
|
+
const diffResult = (0, diff_1.diff)(baseline8, candidate8, diffOutput, width, height, { threshold });
|
|
130
|
+
// Write diff image (raw RGBA for now)
|
|
131
|
+
const diffPath = path.join(snapshotImagesDir, 'diff.png');
|
|
132
|
+
fs.writeFileSync(diffPath, Buffer.from(diffOutput.buffer));
|
|
133
|
+
// We already know the raw bytes differ (byte-equal returns early above).
|
|
134
|
+
// If the pixel diff still reports identical (sub-threshold), the images
|
|
135
|
+
// are visually equivalent but binary-different — still flag as "changed"
|
|
136
|
+
// so the user is aware.
|
|
137
|
+
const status = 'changed';
|
|
138
|
+
const diffPercent = diffResult.diffPercent > 0 ? diffResult.diffPercent : 0.01;
|
|
139
|
+
return {
|
|
140
|
+
name,
|
|
141
|
+
status,
|
|
142
|
+
diffPercent,
|
|
143
|
+
diffCount: diffResult.diffCount,
|
|
144
|
+
totalPixels: diffResult.totalPixels,
|
|
145
|
+
baselinePath: `images/${name}/baseline.png`,
|
|
146
|
+
currentPath: `images/${name}/current.png`,
|
|
147
|
+
diffPath: `images/${name}/diff.png`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// If pixel diff fails (e.g., not raw RGBA), fall back to binary comparison
|
|
152
|
+
return {
|
|
153
|
+
name,
|
|
154
|
+
status: 'changed',
|
|
155
|
+
diffPercent: 100,
|
|
156
|
+
diffCount: 0,
|
|
157
|
+
totalPixels: 0,
|
|
158
|
+
baselinePath: `images/${name}/baseline.png`,
|
|
159
|
+
currentPath: `images/${name}/current.png`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=compare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.js","sourceRoot":"","sources":["../../src/report/compare.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TestivAI Report — Generator
|
|
3
|
+
*
|
|
4
|
+
* Orchestrator: compareAll → build ReportData → write results.json
|
|
5
|
+
* → render HTML → optionally auto-open browser.
|
|
6
|
+
*/
|
|
7
|
+
import { ReportData } from './results';
|
|
8
|
+
export interface GenerateReportOptions {
|
|
9
|
+
projectRoot: string;
|
|
10
|
+
/** Directory for report output. Default: 'visual-report' */
|
|
11
|
+
reportDir?: string;
|
|
12
|
+
/** Diff threshold (0-1). Default: 0.1 */
|
|
13
|
+
threshold?: number;
|
|
14
|
+
/** Auto-open browser after generating. Default: true */
|
|
15
|
+
autoOpen?: boolean;
|
|
16
|
+
/** SDK version string for the report header */
|
|
17
|
+
version?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Generate a complete visual regression report.
|
|
21
|
+
*
|
|
22
|
+
* 1. Compare all temp screenshots against baselines
|
|
23
|
+
* 2. Build ReportData with summary
|
|
24
|
+
* 3. Write results.json (machine-readable)
|
|
25
|
+
* 4. Render and write index.html
|
|
26
|
+
* 5. Optionally open in browser
|
|
27
|
+
*
|
|
28
|
+
* @returns The report data
|
|
29
|
+
*/
|
|
30
|
+
export declare function generateReport(options: GenerateReportOptions): ReportData;
|
|
31
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,UAAU,EAAiB,MAAM,WAAW,CAAC;AAGtD,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;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,UAAU,CAuDzE"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TestivAI Report — Generator
|
|
4
|
+
*
|
|
5
|
+
* Orchestrator: compareAll → build ReportData → write results.json
|
|
6
|
+
* → render HTML → optionally auto-open browser.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.generateReport = generateReport;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const child_process_1 = require("child_process");
|
|
46
|
+
const compare_1 = require("./compare");
|
|
47
|
+
const template_1 = require("./template");
|
|
48
|
+
/**
|
|
49
|
+
* Generate a complete visual regression report.
|
|
50
|
+
*
|
|
51
|
+
* 1. Compare all temp screenshots against baselines
|
|
52
|
+
* 2. Build ReportData with summary
|
|
53
|
+
* 3. Write results.json (machine-readable)
|
|
54
|
+
* 4. Render and write index.html
|
|
55
|
+
* 5. Optionally open in browser
|
|
56
|
+
*
|
|
57
|
+
* @returns The report data
|
|
58
|
+
*/
|
|
59
|
+
function generateReport(options) {
|
|
60
|
+
const { projectRoot, reportDir: reportDirRelative = 'visual-report', threshold = 0.1, autoOpen = true, version = '2.0.0', } = options;
|
|
61
|
+
const reportDir = path.isAbsolute(reportDirRelative)
|
|
62
|
+
? reportDirRelative
|
|
63
|
+
: path.join(projectRoot, reportDirRelative);
|
|
64
|
+
// Ensure report directory exists
|
|
65
|
+
fs.mkdirSync(reportDir, { recursive: true });
|
|
66
|
+
// 1. Compare all snapshots
|
|
67
|
+
const compareOptions = {
|
|
68
|
+
projectRoot,
|
|
69
|
+
reportDir,
|
|
70
|
+
threshold,
|
|
71
|
+
};
|
|
72
|
+
const snapshots = (0, compare_1.compareAll)(compareOptions);
|
|
73
|
+
// 2. Build summary
|
|
74
|
+
const summary = {
|
|
75
|
+
total: snapshots.length,
|
|
76
|
+
passed: snapshots.filter((s) => s.status === 'passed').length,
|
|
77
|
+
changed: snapshots.filter((s) => s.status === 'changed').length,
|
|
78
|
+
newSnapshots: snapshots.filter((s) => s.status === 'new').length,
|
|
79
|
+
};
|
|
80
|
+
// 3. Build report data
|
|
81
|
+
const reportData = {
|
|
82
|
+
version,
|
|
83
|
+
timestamp: new Date().toISOString(),
|
|
84
|
+
summary,
|
|
85
|
+
snapshots,
|
|
86
|
+
};
|
|
87
|
+
// 4. Write results.json
|
|
88
|
+
const resultsPath = path.join(reportDir, 'results.json');
|
|
89
|
+
fs.writeFileSync(resultsPath, JSON.stringify(reportData, null, 2));
|
|
90
|
+
// 5. Render and write HTML
|
|
91
|
+
const html = (0, template_1.renderHtml)(reportData);
|
|
92
|
+
const htmlPath = path.join(reportDir, 'index.html');
|
|
93
|
+
fs.writeFileSync(htmlPath, html);
|
|
94
|
+
// 6. Auto-open browser
|
|
95
|
+
if (autoOpen) {
|
|
96
|
+
openInBrowser(htmlPath);
|
|
97
|
+
}
|
|
98
|
+
return reportData;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Open a file in the default browser.
|
|
102
|
+
* Best-effort — does not throw on failure.
|
|
103
|
+
*/
|
|
104
|
+
function openInBrowser(filePath) {
|
|
105
|
+
const url = `file://${filePath}`;
|
|
106
|
+
const platform = process.platform;
|
|
107
|
+
let cmd;
|
|
108
|
+
if (platform === 'darwin') {
|
|
109
|
+
cmd = `open "${url}"`;
|
|
110
|
+
}
|
|
111
|
+
else if (platform === 'win32') {
|
|
112
|
+
cmd = `start "" "${url}"`;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
cmd = `xdg-open "${url}"`;
|
|
116
|
+
}
|
|
117
|
+
(0, child_process_1.exec)(cmd, (err) => {
|
|
118
|
+
if (err) {
|
|
119
|
+
// Silently ignore — CI environments won't have a browser
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":"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"}
|