@recursica/adapter-tester 5.0.2 → 5.1.1
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 +13 -7
- package/dist/cli.cjs +21 -11
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +165 -145
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +4 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/testing/runVisualRegression.d.ts +9 -9
- package/dist/testing/runVisualRegression.d.ts.map +1 -1
- package/dist/testing.cjs +4 -4
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +166 -150
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/testing.js
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import { expect as
|
|
2
|
-
import { existsSync as v, unlinkSync as
|
|
3
|
-
import
|
|
4
|
-
import { PNG as
|
|
5
|
-
import { join as
|
|
6
|
-
import { a as
|
|
7
|
-
function
|
|
8
|
-
const o =
|
|
1
|
+
import { expect as D } from "@playwright/test";
|
|
2
|
+
import { existsSync as v, unlinkSync as H, readFileSync as E, mkdirSync as b, writeFileSync as A, closeSync as Y, openSync as Q, renameSync as Z, rmSync as ee } from "node:fs";
|
|
3
|
+
import te from "pixelmatch";
|
|
4
|
+
import { PNG as j } from "pngjs";
|
|
5
|
+
import { join as M } from "node:path";
|
|
6
|
+
import { a as re, i as oe } from "./index-DqQzFSAH.js";
|
|
7
|
+
function J(e, t) {
|
|
8
|
+
const o = j.sync.read(e), r = j.sync.read(t);
|
|
9
9
|
if (o.width !== r.width || o.height !== r.height)
|
|
10
10
|
return { diffPixels: 1 / 0, diffImage: null };
|
|
11
|
-
const s = new
|
|
12
|
-
return { diffPixels:
|
|
11
|
+
const s = new j({ width: o.width, height: o.height });
|
|
12
|
+
return { diffPixels: te(
|
|
13
13
|
o.data,
|
|
14
14
|
r.data,
|
|
15
15
|
s.data,
|
|
16
16
|
o.width,
|
|
17
17
|
o.height,
|
|
18
18
|
{ threshold: 0.1 }
|
|
19
|
-
), diffImage:
|
|
19
|
+
), diffImage: j.sync.write(s) };
|
|
20
20
|
}
|
|
21
|
-
const
|
|
22
|
-
$schema:
|
|
23
|
-
$id:
|
|
24
|
-
title:
|
|
25
|
-
description:
|
|
26
|
-
type:
|
|
27
|
-
additionalProperties:
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
function
|
|
32
|
-
if (
|
|
33
|
-
const o = (
|
|
21
|
+
const ne = "http://json-schema.org/draft-07/schema#", se = "https://github.com/borderux/recursica/tree/main/packages/adapter-tester/src/golden/manifest.schema.json", ie = "test/golden/manifest.json", ae = "Tracks golden (baseline) image metadata for @recursica/adapter-tester's golden-image visual regression checks. One manifest lives alongside its adapter's test/golden/<story-id>.png files, keyed by story id.", ce = "object", de = { type: "object", additionalProperties: !1, required: ["createdAt"], properties: { createdAt: { type: "string", format: "date-time", description: "When this story's own golden PNG was last captured, via --update-golden, --approve-divergence, or first-run auto-create." }, sourceOfTruthCreatedAt: { type: "string", format: "date-time", description: "The source-of-truth adapter's (mantine) manifest `createdAt` for this story at the time this adapter's divergence from it was last reviewed via --approve-divergence. Omitted on the source-of-truth adapter's own manifest, and omitted here until the first approval. If mantine's current `createdAt` for this story is newer than this value, the divergence is flagged again for re-review." } } }, ue = {
|
|
22
|
+
$schema: ne,
|
|
23
|
+
$id: se,
|
|
24
|
+
title: ie,
|
|
25
|
+
description: ae,
|
|
26
|
+
type: ce,
|
|
27
|
+
additionalProperties: de
|
|
28
|
+
}, he = oe, K = new re.Ajv({ allErrors: !0, strict: !0 });
|
|
29
|
+
he(K);
|
|
30
|
+
const R = K.compile(ue);
|
|
31
|
+
function L(e, t) {
|
|
32
|
+
if (R(e)) return;
|
|
33
|
+
const o = (R.errors ?? []).map((r) => {
|
|
34
34
|
var i;
|
|
35
35
|
const s = (i = r.params) != null && i.additionalProperty ? ` '${r.params.additionalProperty}'` : "";
|
|
36
36
|
return ` - ${r.instancePath || "root"} ${r.message}${s}`;
|
|
@@ -39,42 +39,42 @@ function F(e, t) {
|
|
|
39
39
|
throw new Error(`Invalid ${t}:
|
|
40
40
|
${o}`);
|
|
41
41
|
}
|
|
42
|
-
function
|
|
43
|
-
return
|
|
42
|
+
function G(e) {
|
|
43
|
+
return M(e, "manifest.json");
|
|
44
44
|
}
|
|
45
|
-
function
|
|
46
|
-
return
|
|
45
|
+
function q(e) {
|
|
46
|
+
return M(e, "manifest.json.lock");
|
|
47
47
|
}
|
|
48
48
|
function S(e, t) {
|
|
49
|
-
return
|
|
49
|
+
return M(e, `${t}.png`);
|
|
50
50
|
}
|
|
51
|
-
function
|
|
52
|
-
const t =
|
|
51
|
+
function P(e) {
|
|
52
|
+
const t = G(e);
|
|
53
53
|
if (!v(t)) return {};
|
|
54
|
-
const o = JSON.parse(
|
|
55
|
-
return
|
|
54
|
+
const o = JSON.parse(E(t, "utf8"));
|
|
55
|
+
return L(o, t), o;
|
|
56
56
|
}
|
|
57
|
-
function
|
|
58
|
-
const o =
|
|
59
|
-
|
|
57
|
+
function le(e, t) {
|
|
58
|
+
const o = G(e);
|
|
59
|
+
L(t, o);
|
|
60
60
|
const r = {};
|
|
61
61
|
for (const i of Object.keys(t).sort())
|
|
62
62
|
r[i] = t[i];
|
|
63
63
|
b(e, { recursive: !0 });
|
|
64
64
|
const s = `${o}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
65
|
-
|
|
66
|
-
`),
|
|
65
|
+
A(s, JSON.stringify(r, null, 2) + `
|
|
66
|
+
`), Z(s, o);
|
|
67
67
|
}
|
|
68
|
-
const
|
|
68
|
+
const fe = 25, pe = 15e3;
|
|
69
69
|
function me(e) {
|
|
70
70
|
return new Promise((t) => setTimeout(t, e));
|
|
71
71
|
}
|
|
72
|
-
async function
|
|
72
|
+
async function ge(e) {
|
|
73
73
|
b(e, { recursive: !0 });
|
|
74
|
-
const t =
|
|
74
|
+
const t = q(e), o = Date.now() + pe;
|
|
75
75
|
for (; ; )
|
|
76
76
|
try {
|
|
77
|
-
Q(
|
|
77
|
+
Y(Q(t, "wx"));
|
|
78
78
|
return;
|
|
79
79
|
} catch (r) {
|
|
80
80
|
if (r.code !== "EEXIST") throw r;
|
|
@@ -82,37 +82,37 @@ async function we(e) {
|
|
|
82
82
|
throw new Error(
|
|
83
83
|
`Timed out waiting for the manifest lock at "${t}" — delete it if a previous run crashed while holding it.`
|
|
84
84
|
);
|
|
85
|
-
await me(
|
|
85
|
+
await me(fe);
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
function
|
|
89
|
-
|
|
88
|
+
function we(e) {
|
|
89
|
+
ee(q(e), { force: !0 });
|
|
90
90
|
}
|
|
91
|
-
async function
|
|
92
|
-
await
|
|
91
|
+
async function V(e, t, o) {
|
|
92
|
+
await ge(e);
|
|
93
93
|
try {
|
|
94
|
-
const r =
|
|
95
|
-
return s === void 0 ? delete r[t] : r[t] = s,
|
|
94
|
+
const r = P(e), s = o(r[t]);
|
|
95
|
+
return s === void 0 ? delete r[t] : r[t] = s, le(e, r), s;
|
|
96
96
|
} finally {
|
|
97
|
-
|
|
97
|
+
we(e);
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
-
function
|
|
101
|
-
b(e, { recursive: !0 }),
|
|
100
|
+
function ye(e, t, o) {
|
|
101
|
+
b(e, { recursive: !0 }), A(S(e, t), o);
|
|
102
102
|
}
|
|
103
|
-
async function
|
|
104
|
-
const o =
|
|
103
|
+
async function ve(e, t) {
|
|
104
|
+
const o = P(e), r = Object.keys(o).filter(
|
|
105
105
|
(s) => !t.has(s)
|
|
106
106
|
);
|
|
107
107
|
for (const s of r) {
|
|
108
108
|
const i = S(e, s);
|
|
109
|
-
v(i) &&
|
|
109
|
+
v(i) && H(i), await V(e, s, () => {
|
|
110
110
|
});
|
|
111
111
|
}
|
|
112
112
|
return r;
|
|
113
113
|
}
|
|
114
|
-
const
|
|
115
|
-
async function
|
|
114
|
+
const Te = "borderux/recursica";
|
|
115
|
+
async function $e(e, t) {
|
|
116
116
|
var i, d;
|
|
117
117
|
const o = await fetch(`https://registry.npmjs.org/${e}`);
|
|
118
118
|
if (!o.ok)
|
|
@@ -126,23 +126,23 @@ async function Oe(e, t) {
|
|
|
126
126
|
);
|
|
127
127
|
return s;
|
|
128
128
|
}
|
|
129
|
-
function
|
|
129
|
+
function Oe(e) {
|
|
130
130
|
return `packages/${e.split("/").pop()}`;
|
|
131
131
|
}
|
|
132
|
-
async function
|
|
132
|
+
async function ke(e) {
|
|
133
133
|
if (e.type === "local")
|
|
134
|
-
return v(
|
|
135
|
-
manifest:
|
|
136
|
-
async readImage(
|
|
137
|
-
const c = S(e.dir,
|
|
138
|
-
return v(c) ?
|
|
134
|
+
return v(G(e.dir)) ? {
|
|
135
|
+
manifest: P(e.dir),
|
|
136
|
+
async readImage(u) {
|
|
137
|
+
const c = S(e.dir, u);
|
|
138
|
+
return v(c) ? E(c) : null;
|
|
139
139
|
}
|
|
140
140
|
} : (console.warn(
|
|
141
141
|
`No golden baseline found yet at ${e.dir} — source-of-truth divergence check skipped for this run.`
|
|
142
142
|
), null);
|
|
143
143
|
let t;
|
|
144
144
|
try {
|
|
145
|
-
t = await
|
|
145
|
+
t = await $e(
|
|
146
146
|
e.packageName,
|
|
147
147
|
e.versionSpec
|
|
148
148
|
);
|
|
@@ -152,45 +152,45 @@ async function xe(e) {
|
|
|
152
152
|
a
|
|
153
153
|
), null;
|
|
154
154
|
}
|
|
155
|
-
const o =
|
|
155
|
+
const o = M(e.cacheDir, t), r = `${e.packageName}@${t}`, s = `https://raw.githubusercontent.com/${Te}/${r}/${Oe(e.packageName)}/test/golden`;
|
|
156
156
|
let i;
|
|
157
|
-
const d =
|
|
157
|
+
const d = G(o);
|
|
158
158
|
if (v(d))
|
|
159
|
-
i =
|
|
159
|
+
i = P(o);
|
|
160
160
|
else {
|
|
161
161
|
let a;
|
|
162
162
|
try {
|
|
163
163
|
a = await fetch(`${s}/manifest.json`);
|
|
164
|
-
} catch (
|
|
164
|
+
} catch (m) {
|
|
165
165
|
return console.warn(
|
|
166
166
|
`Could not reach GitHub to fetch ${r}'s golden baseline — source-of-truth divergence check skipped for this run.`,
|
|
167
|
-
|
|
167
|
+
m
|
|
168
168
|
), null;
|
|
169
169
|
}
|
|
170
170
|
if (!a.ok)
|
|
171
171
|
return console.warn(
|
|
172
172
|
`No golden baseline published for ${r} — source-of-truth divergence check skipped for this run.`
|
|
173
173
|
), null;
|
|
174
|
-
const
|
|
175
|
-
|
|
174
|
+
const u = await a.text(), c = JSON.parse(u);
|
|
175
|
+
L(c, `${s}/manifest.json`), b(o, { recursive: !0 }), A(d, u), i = c;
|
|
176
176
|
}
|
|
177
177
|
return {
|
|
178
178
|
manifest: i,
|
|
179
179
|
async readImage(a) {
|
|
180
|
-
const
|
|
181
|
-
if (v(
|
|
180
|
+
const u = S(o, a);
|
|
181
|
+
if (v(u)) return E(u);
|
|
182
182
|
const c = await fetch(`${s}/${a}.png`);
|
|
183
183
|
if (!c.ok) return null;
|
|
184
|
-
const
|
|
185
|
-
return b(o, { recursive: !0 }),
|
|
184
|
+
const m = Buffer.from(await c.arrayBuffer());
|
|
185
|
+
return b(o, { recursive: !0 }), A(u, m), m;
|
|
186
186
|
}
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
|
-
const
|
|
190
|
-
function
|
|
189
|
+
const xe = ["Theme", "Tokens", "Introduction"];
|
|
190
|
+
function N(e, t) {
|
|
191
191
|
return e === t || e.startsWith(t);
|
|
192
192
|
}
|
|
193
|
-
async function
|
|
193
|
+
async function be(e, t) {
|
|
194
194
|
let o;
|
|
195
195
|
try {
|
|
196
196
|
const r = await fetch(`${e.url}/index.json`);
|
|
@@ -215,141 +215,157 @@ async function Se(e, t) {
|
|
|
215
215
|
}
|
|
216
216
|
return o;
|
|
217
217
|
}
|
|
218
|
-
function
|
|
218
|
+
function U(e, t, o) {
|
|
219
219
|
let r;
|
|
220
220
|
for (const s of Object.keys(t))
|
|
221
|
-
|
|
221
|
+
N(e, s) && (!r || s.length > r.length) && (r = s);
|
|
222
222
|
return r !== void 0 ? t[r] : o;
|
|
223
223
|
}
|
|
224
|
-
async function
|
|
224
|
+
async function Me(e) {
|
|
225
225
|
const t = e.isSourceOfTruthAdapter ? e.targets[0] : e.targets.find((n) => !n.sourceOfTruth);
|
|
226
226
|
if (!t)
|
|
227
227
|
throw new Error(
|
|
228
228
|
"adapter-tester config has no non-sourceOfTruth target to run the golden check against."
|
|
229
229
|
);
|
|
230
|
-
const o = e.excludeTitlePrefixes ??
|
|
230
|
+
const o = e.excludeTitlePrefixes ?? xe, r = e.stories ?? {}, s = Object.keys(r).filter(
|
|
231
231
|
(n) => r[n].exclude
|
|
232
232
|
), i = Object.fromEntries(
|
|
233
|
-
Object.entries(r).filter(([, n]) => n.goldenThreshold !== void 0).map(([n,
|
|
233
|
+
Object.entries(r).filter(([, n]) => n.goldenThreshold !== void 0).map(([n, h]) => [n, h.goldenThreshold])
|
|
234
234
|
), d = Object.fromEntries(
|
|
235
|
-
Object.entries(r).filter(([, n]) => n.sourceOfTruthThreshold !== void 0).map(([n,
|
|
236
|
-
), a = e.goldenDir,
|
|
237
|
-
(n) => !s.some((
|
|
235
|
+
Object.entries(r).filter(([, n]) => n.sourceOfTruthThreshold !== void 0).map(([n, h]) => [n, h.sourceOfTruthThreshold])
|
|
236
|
+
), a = e.goldenDir, u = e.goldenMode, c = e.checkMode, m = await be(t, o), I = m.filter(
|
|
237
|
+
(n) => !s.some((h) => N(n.id, h))
|
|
238
238
|
);
|
|
239
|
-
if (
|
|
240
|
-
const n = await
|
|
239
|
+
if (u === "update-golden") {
|
|
240
|
+
const n = await ve(
|
|
241
241
|
a,
|
|
242
|
-
new Set(
|
|
242
|
+
new Set(I.map((h) => h.id))
|
|
243
243
|
);
|
|
244
244
|
n.length > 0 && console.warn(
|
|
245
245
|
`Pruned ${n.length} orphaned golden(s) no longer in Storybook: ${n.join(", ")}`
|
|
246
246
|
);
|
|
247
247
|
}
|
|
248
|
-
const
|
|
249
|
-
(n) => !
|
|
248
|
+
const g = c !== "divergence" || e.isSourceOfTruthAdapter || !e.sourceOfTruthGolden ? null : await ke(e.sourceOfTruthGolden), W = new Set(m.map((n) => n.id)), T = g ? Object.keys(g.manifest).filter(
|
|
249
|
+
(n) => !W.has(n) && !s.some((h) => N(n, h))
|
|
250
250
|
).sort() : [];
|
|
251
251
|
T.length > 0 && console.error(
|
|
252
252
|
`[adapter-tester] ${T.length} stor(y/ies) exist in the source of truth but are missing here: ${T.join(", ")}. Add the missing story, or mark it \`exclude: true\` under \`stories\` in adapter-tester.config.json if intentional.`
|
|
253
253
|
), console.log(
|
|
254
254
|
[
|
|
255
255
|
`[adapter-tester] target: "${t.name}" (${t.url})`,
|
|
256
|
-
`[adapter-tester] checkMode: "${c}" (${c === "divergence" ? "
|
|
257
|
-
`[adapter-tester] goldenMode: "${
|
|
256
|
+
`[adapter-tester] checkMode: "${c}" (${c === "divergence" ? "live render vs source-of-truth's golden" : "live render vs this project's own golden"})`,
|
|
257
|
+
`[adapter-tester] goldenMode: "${u}"`,
|
|
258
258
|
`[adapter-tester] goldenThresholdPixels: ${e.goldenThresholdPixels}`,
|
|
259
259
|
`[adapter-tester] sourceOfTruthThresholdPixels: ${e.sourceOfTruthThresholdPixels}`,
|
|
260
|
-
c === "divergence" ? e.isSourceOfTruthAdapter ? "[adapter-tester] sourceOfTruthGolden: skipped — this is the source-of-truth adapter, nothing to diverge from" : e.sourceOfTruthGolden ?
|
|
261
|
-
`[adapter-tester] stories: ${
|
|
260
|
+
c === "divergence" ? e.isSourceOfTruthAdapter ? "[adapter-tester] sourceOfTruthGolden: skipped — this is the source-of-truth adapter, nothing to diverge from" : e.sourceOfTruthGolden ? g ? `[adapter-tester] sourceOfTruthGolden: resolved, ${Object.keys(g.manifest).length} golden(s) available (config: ${JSON.stringify(e.sourceOfTruthGolden)})` : `[adapter-tester] sourceOfTruthGolden: unavailable — no baseline found or unreachable (config: ${JSON.stringify(e.sourceOfTruthGolden)}); divergence check will skip every story` : "[adapter-tester] sourceOfTruthGolden: skipped — no sourceOfTruthGolden configured" : '[adapter-tester] sourceOfTruthGolden: not used in "own" checkMode',
|
|
261
|
+
`[adapter-tester] stories: ${I.length} to check (excluded: ${s.length}, title prefixes excluded: ${o.join(", ") || "none"})`,
|
|
262
262
|
`[adapter-tester] story parity with source of truth: ${T.length === 0 ? "OK" : `${T.length} missing (see error above)`}`
|
|
263
263
|
].join(`
|
|
264
264
|
`)
|
|
265
265
|
);
|
|
266
|
-
const
|
|
266
|
+
const X = c === "divergence" ? "Source-of-Truth Divergence Check" : "Own-Drift Golden Image Check";
|
|
267
267
|
return {
|
|
268
268
|
ownTargetName: t.name,
|
|
269
|
-
suiteLabel:
|
|
270
|
-
stories:
|
|
269
|
+
suiteLabel: X,
|
|
270
|
+
stories: I,
|
|
271
271
|
missingFromSourceOfTruth: T,
|
|
272
|
-
checkStory: async (n,
|
|
273
|
-
const
|
|
274
|
-
await
|
|
272
|
+
checkStory: async (n, h, p) => {
|
|
273
|
+
const w = await h.newPage();
|
|
274
|
+
await w.setViewportSize({ width: 800, height: 600 }), await w.goto(
|
|
275
275
|
`${t.url}/iframe.html?id=${n.id}&viewMode=story`,
|
|
276
276
|
{ waitUntil: "networkidle" }
|
|
277
|
-
), await
|
|
277
|
+
), await w.waitForSelector("#storybook-root"), await w.addStyleTag({
|
|
278
278
|
content: "* { -webkit-font-smoothing: antialiased !important; -moz-osx-font-smoothing: grayscale !important; }"
|
|
279
|
-
}), await
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
279
|
+
}), await w.evaluate(
|
|
280
|
+
() => Promise.all(
|
|
281
|
+
Array.from(
|
|
282
|
+
document.querySelectorAll(
|
|
283
|
+
'link[rel="stylesheet"]'
|
|
284
|
+
)
|
|
285
|
+
).map(
|
|
286
|
+
(l) => l.sheet ? Promise.resolve() : new Promise((f) => {
|
|
287
|
+
l.addEventListener("load", () => f(), {
|
|
288
|
+
once: !0
|
|
289
|
+
}), l.addEventListener("error", () => f(), {
|
|
290
|
+
once: !0
|
|
291
|
+
});
|
|
292
|
+
})
|
|
293
|
+
)
|
|
294
|
+
).then(() => document.fonts.ready)
|
|
295
|
+
), await w.waitForTimeout(300);
|
|
296
|
+
const x = await w.screenshot(), B = S(a, n.id), y = P(a)[n.id], z = u !== "check" || !y || !v(B);
|
|
297
|
+
let $;
|
|
298
|
+
if (z)
|
|
299
|
+
ye(a, n.id, x), $ = y != null && y.sourceOfTruthCreatedAt ? {
|
|
284
300
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
285
|
-
sourceOfTruthCreatedAt:
|
|
286
|
-
} : { createdAt: (/* @__PURE__ */ new Date()).toISOString() },
|
|
301
|
+
sourceOfTruthCreatedAt: y.sourceOfTruthCreatedAt
|
|
302
|
+
} : { createdAt: (/* @__PURE__ */ new Date()).toISOString() }, y || p.annotations.push({
|
|
287
303
|
type: "golden-created",
|
|
288
304
|
description: `No golden existed yet for "${n.id}" — captured one from this run.`
|
|
289
305
|
});
|
|
290
|
-
else if (
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
),
|
|
306
|
+
else if ($ = y, c === "own") {
|
|
307
|
+
const l = E(B), { diffPixels: f, diffImage: O } = J(
|
|
308
|
+
x,
|
|
309
|
+
l
|
|
310
|
+
), k = U(
|
|
295
311
|
n.id,
|
|
296
312
|
i,
|
|
297
313
|
e.goldenThresholdPixels
|
|
298
314
|
);
|
|
299
|
-
|
|
300
|
-
body:
|
|
315
|
+
f >= k && (await p.attach("expected", {
|
|
316
|
+
body: l,
|
|
301
317
|
contentType: "image/png"
|
|
302
|
-
}), await
|
|
303
|
-
body:
|
|
318
|
+
}), await p.attach("actual", {
|
|
319
|
+
body: x,
|
|
304
320
|
contentType: "image/png"
|
|
305
|
-
}),
|
|
306
|
-
body:
|
|
321
|
+
}), O && await p.attach("diff", {
|
|
322
|
+
body: O,
|
|
307
323
|
contentType: "image/png"
|
|
308
|
-
})),
|
|
309
|
-
|
|
310
|
-
`"${n.id}" has drifted from its own golden image (${
|
|
311
|
-
).toBeLessThan(
|
|
324
|
+
})), D.soft(
|
|
325
|
+
f,
|
|
326
|
+
`"${n.id}" has drifted from its own golden image (${f} mismatched pixels, threshold ${k})`
|
|
327
|
+
).toBeLessThan(k);
|
|
312
328
|
}
|
|
313
|
-
if (
|
|
314
|
-
const
|
|
315
|
-
if (
|
|
316
|
-
if (
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
sourceOfTruthCreatedAt:
|
|
329
|
+
if (g) {
|
|
330
|
+
const l = g.manifest[n.id], f = l ? await g.readImage(n.id) : null;
|
|
331
|
+
if (l && f)
|
|
332
|
+
if (u === "approve-divergence")
|
|
333
|
+
$ = {
|
|
334
|
+
...$,
|
|
335
|
+
sourceOfTruthCreatedAt: l.createdAt
|
|
320
336
|
};
|
|
321
337
|
else {
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
),
|
|
338
|
+
const { diffPixels: O, diffImage: k } = J(
|
|
339
|
+
x,
|
|
340
|
+
f
|
|
341
|
+
), C = U(
|
|
326
342
|
n.id,
|
|
327
343
|
d,
|
|
328
344
|
e.sourceOfTruthThresholdPixels
|
|
329
|
-
),
|
|
330
|
-
|
|
331
|
-
body:
|
|
345
|
+
), F = $.sourceOfTruthCreatedAt, _ = O < C || F !== void 0 && F >= l.createdAt;
|
|
346
|
+
_ || (await p.attach("expected", {
|
|
347
|
+
body: f,
|
|
332
348
|
contentType: "image/png"
|
|
333
|
-
}), await
|
|
334
|
-
body:
|
|
349
|
+
}), await p.attach("actual", {
|
|
350
|
+
body: x,
|
|
335
351
|
contentType: "image/png"
|
|
336
|
-
}),
|
|
337
|
-
body:
|
|
352
|
+
}), k && await p.attach("diff", {
|
|
353
|
+
body: k,
|
|
338
354
|
contentType: "image/png"
|
|
339
|
-
}),
|
|
355
|
+
}), p.annotations.push({
|
|
340
356
|
type: "source-of-truth-divergence",
|
|
341
|
-
description: `"${n.id}" differs from the source of truth's golden by ${
|
|
342
|
-
})),
|
|
343
|
-
|
|
344
|
-
`"${n.id}" differs from the source of truth's golden by ${
|
|
357
|
+
description: `"${n.id}" differs from the source of truth's golden by ${O} mismatched pixels (threshold ${C}) and hasn't been reviewed — run with --approve-divergence if this is intentional, or fix the adapter styling.`
|
|
358
|
+
})), D.soft(
|
|
359
|
+
_,
|
|
360
|
+
`"${n.id}" differs from the source of truth's golden by ${O} mismatched pixels (threshold ${C}) and hasn't been reviewed — run with --approve-divergence if this is intentional, or fix the adapter styling.`
|
|
345
361
|
).toBe(!0);
|
|
346
362
|
}
|
|
347
363
|
}
|
|
348
|
-
await
|
|
364
|
+
await V(a, n.id, () => $);
|
|
349
365
|
}
|
|
350
366
|
};
|
|
351
367
|
}
|
|
352
368
|
export {
|
|
353
|
-
|
|
369
|
+
Me as resolveVisualRegressionPlan
|
|
354
370
|
};
|
|
355
371
|
//# sourceMappingURL=testing.js.map
|