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