@flighthq/capture 0.3.0 → 0.3.1-next.1041.35b950c
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/captureBaseline.d.ts +8 -3
- package/dist/captureBaseline.d.ts.map +1 -1
- package/dist/captureBaseline.js +18 -0
- package/dist/captureBaseline.js.map +1 -1
- package/dist/captureComparison.d.ts +7 -0
- package/dist/captureComparison.d.ts.map +1 -1
- package/dist/captureComparison.js +7 -0
- package/dist/captureComparison.js.map +1 -1
- package/package.json +3 -3
- package/src/captureBaseline.test.ts +47 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CaptureBaseline,
|
|
1
|
+
import type { CaptureBaseline, CaptureBaselineField, CaptureBaselineProvenance, CaptureBaselineProvenanceField } from '@flighthq/types/contract';
|
|
2
2
|
/** Allocates an empty baseline record. Columns are added via setCaptureBaselineField. */
|
|
3
3
|
export declare function createCaptureBaseline(): CaptureBaseline;
|
|
4
4
|
/**
|
|
@@ -12,7 +12,10 @@ export declare function formatCaptureBaseline(baseline: Readonly<CaptureBaseline
|
|
|
12
12
|
* The value of one column's field, or `null` when the column or field is absent. `field` is
|
|
13
13
|
* `'fingerprint'` or `'sha256'`.
|
|
14
14
|
*/
|
|
15
|
-
export declare function getCaptureBaselineField(baseline: Readonly<CaptureBaseline>, column: string, field:
|
|
15
|
+
export declare function getCaptureBaselineField(baseline: Readonly<CaptureBaseline>, column: string, field: CaptureBaselineField): string | null;
|
|
16
|
+
/** What produced ONE of a column's values — `field` names which. `null` when that value is absent or
|
|
17
|
+
* predates provenance recording, which reads as UNKNOWN provenance and never as agreement. */
|
|
18
|
+
export declare function getCaptureBaselineProvenance(baseline: Readonly<CaptureBaseline>, column: string, field: CaptureBaselineProvenanceField): CaptureBaselineProvenance | null;
|
|
16
19
|
/**
|
|
17
20
|
* Parses the text form produced by formatCaptureBaseline. Returns `null` for malformed input — invalid
|
|
18
21
|
* JSON, or a top-level value that is not a plain object — so a corrupt baseline reads as "no baseline"
|
|
@@ -20,5 +23,7 @@ export declare function getCaptureBaselineField(baseline: Readonly<CaptureBaseli
|
|
|
20
23
|
*/
|
|
21
24
|
export declare function parseCaptureBaseline(text: string): CaptureBaseline | null;
|
|
22
25
|
/** Sets one column's field to `value`, creating the column entry if it does not yet exist. */
|
|
23
|
-
export declare function setCaptureBaselineField(baseline: CaptureBaseline, column: string, field:
|
|
26
|
+
export declare function setCaptureBaselineField(baseline: CaptureBaseline, column: string, field: CaptureBaselineField, value: string): void;
|
|
27
|
+
/** Records what produced ONE of a column's values, creating the column entry if it does not yet exist. */
|
|
28
|
+
export declare function setCaptureBaselineProvenance(baseline: CaptureBaseline, column: string, field: CaptureBaselineProvenanceField, provenance: Readonly<CaptureBaselineProvenance>): void;
|
|
24
29
|
//# sourceMappingURL=captureBaseline.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captureBaseline.d.ts","sourceRoot":"","sources":["../src/captureBaseline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"captureBaseline.d.ts","sourceRoot":"","sources":["../src/captureBaseline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACpB,yBAAyB,EACzB,8BAA8B,EAE/B,MAAM,0BAA0B,CAAC;AAElC,yFAAyF;AACzF,wBAAgB,qBAAqB,IAAI,eAAe,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,CAAC,eAAe,CAAC,GAAG,MAAM,CAejF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,QAAQ,CAAC,eAAe,CAAC,EACnC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,oBAAoB,GAC1B,MAAM,GAAG,IAAI,CAEf;AAED;8FAC8F;AAC9F,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,QAAQ,CAAC,eAAe,CAAC,EACnC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,8BAA8B,GACpC,yBAAyB,GAAG,IAAI,CAElC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CASzE;AAED,8FAA8F;AAC9F,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,oBAAoB,EAC3B,KAAK,EAAE,MAAM,GACZ,IAAI,CAEN;AAED,0GAA0G;AAC1G,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,8BAA8B,EACrC,UAAU,EAAE,QAAQ,CAAC,yBAAyB,CAAC,GAC9C,IAAI,CAEN"}
|
package/dist/captureBaseline.js
CHANGED
|
@@ -19,6 +19,12 @@ export function formatCaptureBaseline(baseline) {
|
|
|
19
19
|
out.sourceHash = entry.sourceHash;
|
|
20
20
|
if (entry.sha256 !== undefined)
|
|
21
21
|
out.sha256 = entry.sha256;
|
|
22
|
+
// Provenance is emitted LAST so adding it to a column leaves every existing line in place and the
|
|
23
|
+
// diff is one appended block rather than a rewrite of the record.
|
|
24
|
+
if (entry.fingerprintProvenance !== undefined)
|
|
25
|
+
out.fingerprintProvenance = entry.fingerprintProvenance;
|
|
26
|
+
if (entry.sha256Provenance !== undefined)
|
|
27
|
+
out.sha256Provenance = entry.sha256Provenance;
|
|
22
28
|
sorted[column] = out;
|
|
23
29
|
}
|
|
24
30
|
return JSON.stringify(sorted, null, 2) + '\n';
|
|
@@ -30,6 +36,11 @@ export function formatCaptureBaseline(baseline) {
|
|
|
30
36
|
export function getCaptureBaselineField(baseline, column, field) {
|
|
31
37
|
return baseline[column]?.[field] ?? null;
|
|
32
38
|
}
|
|
39
|
+
/** What produced ONE of a column's values — `field` names which. `null` when that value is absent or
|
|
40
|
+
* predates provenance recording, which reads as UNKNOWN provenance and never as agreement. */
|
|
41
|
+
export function getCaptureBaselineProvenance(baseline, column, field) {
|
|
42
|
+
return baseline[column]?.[provenanceMember(field)] ?? null;
|
|
43
|
+
}
|
|
33
44
|
/**
|
|
34
45
|
* Parses the text form produced by formatCaptureBaseline. Returns `null` for malformed input — invalid
|
|
35
46
|
* JSON, or a top-level value that is not a plain object — so a corrupt baseline reads as "no baseline"
|
|
@@ -51,4 +62,11 @@ export function parseCaptureBaseline(text) {
|
|
|
51
62
|
export function setCaptureBaselineField(baseline, column, field, value) {
|
|
52
63
|
(baseline[column] ??= {})[field] = value;
|
|
53
64
|
}
|
|
65
|
+
/** Records what produced ONE of a column's values, creating the column entry if it does not yet exist. */
|
|
66
|
+
export function setCaptureBaselineProvenance(baseline, column, field, provenance) {
|
|
67
|
+
(baseline[column] ??= {})[provenanceMember(field)] = { ...provenance };
|
|
68
|
+
}
|
|
69
|
+
function provenanceMember(field) {
|
|
70
|
+
return field === 'fingerprint' ? 'fingerprintProvenance' : 'sha256Provenance';
|
|
71
|
+
}
|
|
54
72
|
//# sourceMappingURL=captureBaseline.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captureBaseline.js","sourceRoot":"","sources":["../src/captureBaseline.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"captureBaseline.js","sourceRoot":"","sources":["../src/captureBaseline.ts"],"names":[],"mappings":"AAQA,yFAAyF;AACzF,MAAM,UAAU,qBAAqB;IACnC,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAmC;IACvE,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAClD,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,GAAG,GAA0B,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;YAAE,GAAG,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QACzE,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS;YAAE,GAAG,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;QACtE,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;YAAE,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC1D,kGAAkG;QAClG,kEAAkE;QAClE,IAAI,KAAK,CAAC,qBAAqB,KAAK,SAAS;YAAE,GAAG,CAAC,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,CAAC;QACvG,IAAI,KAAK,CAAC,gBAAgB,KAAK,SAAS;YAAE,GAAG,CAAC,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC;QACxF,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;IACvB,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,QAAmC,EACnC,MAAc,EACd,KAA2B;IAE3B,OAAO,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AAC3C,CAAC;AAED;8FAC8F;AAC9F,MAAM,UAAU,4BAA4B,CAC1C,QAAmC,EACnC,MAAc,EACd,KAAqC;IAErC,OAAO,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC;AAC7D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACxF,OAAO,MAAyB,CAAC;AACnC,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,uBAAuB,CACrC,QAAyB,EACzB,MAAc,EACd,KAA2B,EAC3B,KAAa;IAEb,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;AAC3C,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,4BAA4B,CAC1C,QAAyB,EACzB,MAAc,EACd,KAAqC,EACrC,UAA+C;IAE/C,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,GAAG,UAAU,EAAE,CAAC;AACzE,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAqC;IAC7D,OAAO,KAAK,KAAK,aAAa,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,kBAAkB,CAAC;AAChF,CAAC"}
|
|
@@ -21,6 +21,13 @@ export declare function evaluateCaptureParity(a: string, b: string, tolerance?:
|
|
|
21
21
|
* Regression: whether a freshly captured `fingerprint` still matches its own committed
|
|
22
22
|
* `baselineFingerprint` within `tolerance`. `difference` is the tolerant distance (Infinity when
|
|
23
23
|
* either fingerprint is unparseable); `pass` is `difference <= tolerance`.
|
|
24
|
+
*
|
|
25
|
+
* ⚠ A PASS MEANS THE FINGERPRINT DID NOT MOVE, WHICH IS NOT THE SAME AS THE RENDER NOT MOVING. Each
|
|
26
|
+
* cell averages the pixels beneath it, so a pattern finer than a cell — scanlines, dithering, a fine
|
|
27
|
+
* periodic warp — can change completely while every cell average stays put. Three separate defects in
|
|
28
|
+
* this repository passed this check while the pixels underneath disagreed, one of them by more than
|
|
29
|
+
* fifty times the distance reported here. Where the subject is high-frequency, a passing regression
|
|
30
|
+
* is evidence about the fingerprint and not about the image.
|
|
24
31
|
*/
|
|
25
32
|
export declare function evaluateCaptureRegression(fingerprint: string, baselineFingerprint: string, tolerance?: number): CaptureCheckResult;
|
|
26
33
|
//# sourceMappingURL=captureComparison.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captureComparison.d.ts","sourceRoot":"","sources":["../src/captureComparison.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAInE,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAK3C,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAKvE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,SAA2B,GAAG,kBAAkB,CAGpH;AAED
|
|
1
|
+
{"version":3,"file":"captureComparison.d.ts","sourceRoot":"","sources":["../src/captureComparison.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAInE,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAK3C,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAKvE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,SAA2B,GAAG,kBAAkB,CAGpH;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,mBAAmB,EAAE,MAAM,EAC3B,SAAS,SAA+B,GACvC,kBAAkB,CAGpB"}
|
|
@@ -35,6 +35,13 @@ export function evaluateCaptureParity(a, b, tolerance = CAPTURE_PARITY_TOLERANCE
|
|
|
35
35
|
* Regression: whether a freshly captured `fingerprint` still matches its own committed
|
|
36
36
|
* `baselineFingerprint` within `tolerance`. `difference` is the tolerant distance (Infinity when
|
|
37
37
|
* either fingerprint is unparseable); `pass` is `difference <= tolerance`.
|
|
38
|
+
*
|
|
39
|
+
* ⚠ A PASS MEANS THE FINGERPRINT DID NOT MOVE, WHICH IS NOT THE SAME AS THE RENDER NOT MOVING. Each
|
|
40
|
+
* cell averages the pixels beneath it, so a pattern finer than a cell — scanlines, dithering, a fine
|
|
41
|
+
* periodic warp — can change completely while every cell average stays put. Three separate defects in
|
|
42
|
+
* this repository passed this check while the pixels underneath disagreed, one of them by more than
|
|
43
|
+
* fifty times the distance reported here. Where the subject is high-frequency, a passing regression
|
|
44
|
+
* is evidence about the fingerprint and not about the image.
|
|
38
45
|
*/
|
|
39
46
|
export function evaluateCaptureRegression(fingerprint, baselineFingerprint, tolerance = CAPTURE_REGRESSION_TOLERANCE) {
|
|
40
47
|
const difference = compareCaptureFingerprints(fingerprint, baselineFingerprint);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captureComparison.js","sourceRoot":"","sources":["../src/captureComparison.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAG9F,sGAAsG;AACtG,sGAAsG;AACtG,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C,uGAAuG;AACvG,uGAAuG;AACvG,iEAAiE;AACjE,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,UAAU,0BAA0B,CAAC,CAAS,EAAE,CAAS;IAC7D,MAAM,EAAE,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,EAAE,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACrC,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,CAAC,QAAQ,KAAK,EAAE,CAAC,QAAQ;QAAE,OAAO,MAAM,CAAC,iBAAiB,CAAC;IAC/F,OAAO,yBAAyB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,CAAS,EAAE,CAAS,EAAE,SAAS,GAAG,wBAAwB;IAC9F,MAAM,UAAU,GAAG,0BAA0B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpD,OAAO,EAAE,IAAI,EAAE,UAAU,IAAI,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;AAClE,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"captureComparison.js","sourceRoot":"","sources":["../src/captureComparison.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAG9F,sGAAsG;AACtG,sGAAsG;AACtG,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C,uGAAuG;AACvG,uGAAuG;AACvG,iEAAiE;AACjE,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,UAAU,0BAA0B,CAAC,CAAS,EAAE,CAAS;IAC7D,MAAM,EAAE,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,EAAE,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACrC,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,CAAC,QAAQ,KAAK,EAAE,CAAC,QAAQ;QAAE,OAAO,MAAM,CAAC,iBAAiB,CAAC;IAC/F,OAAO,yBAAyB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,CAAS,EAAE,CAAS,EAAE,SAAS,GAAG,wBAAwB;IAC9F,MAAM,UAAU,GAAG,0BAA0B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpD,OAAO,EAAE,IAAI,EAAE,UAAU,IAAI,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,yBAAyB,CACvC,WAAmB,EACnB,mBAA2B,EAC3B,SAAS,GAAG,4BAA4B;IAExC,MAAM,UAAU,GAAG,0BAA0B,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAChF,OAAO,EAAE,IAAI,EAAE,UAAU,IAAI,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;AAClE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/capture",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1-next.1041.35b950c",
|
|
4
4
|
"author": "Joshua Granick and other contributors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@flighthq/bitmap": "0.3.
|
|
42
|
-
"@flighthq/types": "0.3.
|
|
41
|
+
"@flighthq/bitmap": "0.3.1-next.1041.35b950c",
|
|
42
|
+
"@flighthq/types": "0.3.1-next.1041.35b950c"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"typescript": "^5.3.0"
|
|
@@ -4,8 +4,10 @@ import {
|
|
|
4
4
|
createCaptureBaseline,
|
|
5
5
|
formatCaptureBaseline,
|
|
6
6
|
getCaptureBaselineField,
|
|
7
|
+
getCaptureBaselineProvenance,
|
|
7
8
|
parseCaptureBaseline,
|
|
8
9
|
setCaptureBaselineField,
|
|
10
|
+
setCaptureBaselineProvenance,
|
|
9
11
|
} from './captureBaseline';
|
|
10
12
|
|
|
11
13
|
describe('createCaptureBaseline', () => {
|
|
@@ -72,6 +74,31 @@ describe('getCaptureBaselineField', () => {
|
|
|
72
74
|
});
|
|
73
75
|
});
|
|
74
76
|
|
|
77
|
+
describe('getCaptureBaselineProvenance', () => {
|
|
78
|
+
it('reads back what was recorded', () => {
|
|
79
|
+
const baseline = createCaptureBaseline();
|
|
80
|
+
setCaptureBaselineProvenance(baseline, 'webgl', 'sha256', PROVENANCE);
|
|
81
|
+
expect(getCaptureBaselineProvenance(baseline, 'webgl', 'sha256')).toEqual(PROVENANCE);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('does NOT answer for the other value — one provenance per independently-written field', () => {
|
|
85
|
+
const baseline = createCaptureBaseline();
|
|
86
|
+
setCaptureBaselineProvenance(baseline, 'webgl', 'sha256', PROVENANCE);
|
|
87
|
+
// fingerprint is written by a DIFFERENT pass. A sha256 stamp must not read as covering it, or the
|
|
88
|
+
// record reports agreement it never established.
|
|
89
|
+
expect(getCaptureBaselineProvenance(baseline, 'webgl', 'fingerprint')).toBeNull();
|
|
90
|
+
expect(getCaptureBaselineProvenance(baseline, 'webgl', 'sha256')).toEqual(PROVENANCE);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('reads a column written before provenance existed as UNKNOWN, not as agreement', () => {
|
|
94
|
+
const baseline = createCaptureBaseline();
|
|
95
|
+
setCaptureBaselineField(baseline, 'webgl', 'sha256', 'abc');
|
|
96
|
+
// null is the whole staging decision: a legacy record must not read as "produced the same way".
|
|
97
|
+
expect(getCaptureBaselineProvenance(baseline, 'webgl', 'sha256')).toBeNull();
|
|
98
|
+
expect(getCaptureBaselineProvenance(baseline, 'absent', 'sha256')).toBeNull();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
75
102
|
describe('parseCaptureBaseline', () => {
|
|
76
103
|
it('round-trips format output to a stable, equal record', () => {
|
|
77
104
|
const baseline = createCaptureBaseline();
|
|
@@ -114,3 +141,23 @@ describe('setCaptureBaselineField', () => {
|
|
|
114
141
|
expect(getCaptureBaselineField(baseline, 'canvas', 'fingerprint')).toBe('1:ffffff');
|
|
115
142
|
});
|
|
116
143
|
});
|
|
144
|
+
|
|
145
|
+
describe('setCaptureBaselineProvenance', () => {
|
|
146
|
+
it('creates the column and leaves the other fields alone', () => {
|
|
147
|
+
const baseline = createCaptureBaseline();
|
|
148
|
+
setCaptureBaselineField(baseline, 'webgl', 'sha256', 'abc');
|
|
149
|
+
setCaptureBaselineProvenance(baseline, 'webgl', 'sha256', PROVENANCE);
|
|
150
|
+
expect(getCaptureBaselineField(baseline, 'webgl', 'sha256')).toBe('abc');
|
|
151
|
+
expect(getCaptureBaselineProvenance(baseline, 'webgl', 'sha256')).toEqual(PROVENANCE);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('copies rather than aliasing, so a later caller mutation cannot rewrite the record', () => {
|
|
155
|
+
const baseline = createCaptureBaseline();
|
|
156
|
+
const source = { ...PROVENANCE };
|
|
157
|
+
setCaptureBaselineProvenance(baseline, 'webgl', 'sha256', source);
|
|
158
|
+
source.frames = 99;
|
|
159
|
+
expect(getCaptureBaselineProvenance(baseline, 'webgl', 'sha256')?.frames).toBe(PROVENANCE.frames);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const PROVENANCE = { frames: 1, sourceHash: 'a1b2c3', targetKind: 'webgl', verifyPublished: true, warmupFrames: 0 };
|