@bughunters/vision 1.0.4 ā 1.0.5
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 +21 -0
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +13 -14
- package/dist/reporter.d.ts.map +1 -1
- package/dist/reporter.js +180 -87
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -130,6 +130,27 @@ The report includes side-by-side Baseline / Current / Diff views with full-scree
|
|
|
130
130
|
|
|
131
131
|
---
|
|
132
132
|
|
|
133
|
+
## Terminal output
|
|
134
|
+
|
|
135
|
+
BugHunters Vision keeps terminal output compact and linear ā one line per step, no duplicates:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
šø [BugHunters Vision] Baseline created: cart-page
|
|
139
|
+
ā
[BugHunters Vision] FAST PIXEL MATCH: shipping-form
|
|
140
|
+
š [BugHunters Vision] AI evaluating: payment-page (12 pixel(s) differ)ā¦
|
|
141
|
+
š¤ [BugHunters Vision] AI PASS: payment-page
|
|
142
|
+
ā ļø [BugHunters Vision] AI error: header ā Claude AI is temporarily overloaded.
|
|
143
|
+
ā [BugHunters Vision] off: footer
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
When a check fails, a single clear error is thrown (no repeated messages):
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
Error: [BugHunters Vision] Visual regression detected in step "payment-page": Button label changed from "Pay now" to "Subscribe".
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
133
154
|
## IDE & VS Code integration
|
|
134
155
|
|
|
135
156
|
BugHunters Vision is fully compatible with the **VS Code Playwright extension** and **Playwright UI mode**.
|
package/dist/check.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAY,MAAM,kBAAkB,CAAC;AAOhE,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAKD,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,IAAI,CAEvD;AAoHD,wBAAsB,cAAc,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAY,MAAM,kBAAkB,CAAC;AAOhE,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAKD,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,IAAI,CAEvD;AAoHD,wBAAsB,cAAc,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyJ/E"}
|
package/dist/check.js
CHANGED
|
@@ -156,7 +156,7 @@ async function runVisionCheck(opts) {
|
|
|
156
156
|
const token = projectUse['bvToken'] ?? process.env.BUGHUNTERS_VISION_TOKEN ?? undefined;
|
|
157
157
|
// Mode: off ā skip all visual testing immediately
|
|
158
158
|
if (mode === 'off') {
|
|
159
|
-
console.log(
|
|
159
|
+
console.log(`ā [BugHunters Vision] off: ${name}`);
|
|
160
160
|
return;
|
|
161
161
|
}
|
|
162
162
|
const resolvedDir = path.resolve(process.cwd(), snapshotsDir);
|
|
@@ -173,8 +173,7 @@ async function runVisionCheck(opts) {
|
|
|
173
173
|
if (!fs.existsSync(baselinePath) || updateBaseline) {
|
|
174
174
|
// First run ā save as baseline
|
|
175
175
|
fs.writeFileSync(baselinePath, currentBuffer);
|
|
176
|
-
console.log(
|
|
177
|
-
console.log(' ā
Test PASSED (baseline created ā no previous reference exists)\n');
|
|
176
|
+
console.log(`šø [BugHunters Vision] Baseline created: ${name}`);
|
|
178
177
|
(0, results_1.appendResult)(resolvedDir, {
|
|
179
178
|
testName,
|
|
180
179
|
status: 'BASELINE_CREATED',
|
|
@@ -194,8 +193,7 @@ async function runVisionCheck(opts) {
|
|
|
194
193
|
fs.writeFileSync(path.join(resolvedDir, currentFileName), currentBuffer);
|
|
195
194
|
if (diffPixels === 0) {
|
|
196
195
|
// ā
Pixel-perfect match ā skip AI call entirely
|
|
197
|
-
console.log(
|
|
198
|
-
console.log(' ā
Test PASSED (Fast Pixel Match)\n');
|
|
196
|
+
console.log(`ā
[BugHunters Vision] FAST PIXEL MATCH: ${name}`);
|
|
199
197
|
(0, results_1.appendResult)(resolvedDir, {
|
|
200
198
|
testName,
|
|
201
199
|
status: 'PASS',
|
|
@@ -212,7 +210,6 @@ async function runVisionCheck(opts) {
|
|
|
212
210
|
const diffLabel = diffPixels === -1 ? 'dimension mismatch' : `${diffPixels} pixel(s) differ`;
|
|
213
211
|
if (mode === 'strict') {
|
|
214
212
|
// strict: fail immediately without calling AI
|
|
215
|
-
console.log(`\nā [BugHunters Vision] "${name}" ā ${diffLabel}. FAILED (strict mode ā no AI call).\n`);
|
|
216
213
|
(0, results_1.appendResult)(resolvedDir, {
|
|
217
214
|
testName,
|
|
218
215
|
status: 'FAIL',
|
|
@@ -223,18 +220,17 @@ async function runVisionCheck(opts) {
|
|
|
223
220
|
timestamp: new Date().toISOString(),
|
|
224
221
|
});
|
|
225
222
|
await pushToPlaywright(testInfo, name, 'FAIL', `Pixel mismatch detected (${diffLabel}). Strict mode.`, resolvedDir, `${filePrefix}.baseline.png`, currentFileName);
|
|
226
|
-
(0, test_1.expect)(false, `[BugHunters Vision
|
|
223
|
+
(0, test_1.expect)(false, `[BugHunters Vision] Visual regression detected in step "${name}": ${diffLabel} (strict mode)`).toBe(true);
|
|
227
224
|
return;
|
|
228
225
|
}
|
|
229
226
|
// ai mode ā escalate to AI for intelligent evaluation
|
|
230
|
-
console.log(
|
|
227
|
+
console.log(`š [BugHunters Vision] AI evaluating: ${name} (${diffLabel})ā¦`);
|
|
231
228
|
let result;
|
|
232
229
|
try {
|
|
233
230
|
result = await callVisionApi(baselineBuffer.toString('base64'), currentBuffer.toString('base64'), prompt, apiUrl, token);
|
|
234
231
|
}
|
|
235
232
|
catch (err) {
|
|
236
233
|
const reason = humanReadableApiError(err instanceof Error ? err.message : String(err));
|
|
237
|
-
console.log(`\nā [BugHunters Vision] ${reason}\n`);
|
|
238
234
|
(0, results_1.appendResult)(resolvedDir, {
|
|
239
235
|
testName,
|
|
240
236
|
status: 'FAIL',
|
|
@@ -245,11 +241,11 @@ async function runVisionCheck(opts) {
|
|
|
245
241
|
timestamp: new Date().toISOString(),
|
|
246
242
|
});
|
|
247
243
|
await pushToPlaywright(testInfo, name, 'FAIL', reason, resolvedDir, `${filePrefix}.baseline.png`, currentFileName);
|
|
248
|
-
throw
|
|
244
|
+
throw new Error(`[BugHunters Vision] Visual regression detected in step "${name}": ${reason}`);
|
|
249
245
|
}
|
|
250
246
|
// ERROR: AI temporarily unavailable ā record but do NOT fail the Playwright test
|
|
251
247
|
if (result.status === 'ERROR') {
|
|
252
|
-
console.log(
|
|
248
|
+
console.log(`ā ļø [BugHunters Vision] AI error: ${name} ā ${result.reason}`);
|
|
253
249
|
(0, results_1.appendResult)(resolvedDir, {
|
|
254
250
|
testName,
|
|
255
251
|
status: 'ERROR',
|
|
@@ -262,8 +258,6 @@ async function runVisionCheck(opts) {
|
|
|
262
258
|
await pushToPlaywright(testInfo, name, 'ERROR', result.reason, resolvedDir, `${filePrefix}.baseline.png`, currentFileName);
|
|
263
259
|
return; // test stays green
|
|
264
260
|
}
|
|
265
|
-
const icon = result.status === 'PASS' ? 'ā
' : 'ā';
|
|
266
|
-
console.log(`${icon} [BugHunters Vision] ${result.status}: ${result.reason}\n`);
|
|
267
261
|
(0, results_1.appendResult)(resolvedDir, {
|
|
268
262
|
testName,
|
|
269
263
|
status: result.status,
|
|
@@ -274,5 +268,10 @@ async function runVisionCheck(opts) {
|
|
|
274
268
|
timestamp: new Date().toISOString(),
|
|
275
269
|
});
|
|
276
270
|
await pushToPlaywright(testInfo, name, result.status, result.reason, resolvedDir, `${filePrefix}.baseline.png`, currentFileName);
|
|
277
|
-
|
|
271
|
+
if (result.status === 'PASS') {
|
|
272
|
+
console.log(`š¤ [BugHunters Vision] AI PASS: ${name}`);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
throw new Error(`[BugHunters Vision] Visual regression detected in step "${name}": ${result.reason}`);
|
|
276
|
+
}
|
|
278
277
|
}
|
package/dist/reporter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAI1D,MAAM,WAAW,+BAA+B;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAI1D,MAAM,WAAW,+BAA+B;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA4hCD,cAAM,wBAAyB,YAAW,QAAQ;IAChD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,CAAC,EAAE,+BAA+B;IAKrD,aAAa,IAAI,OAAO;IAIxB,OAAO,IAAI,IAAI;IAKf,KAAK,IAAI,IAAI;CAkDd;AAED,eAAe,wBAAwB,CAAC;AACxC,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
|
package/dist/reporter.js
CHANGED
|
@@ -37,6 +37,36 @@ exports.BugHuntersVisionReporter = void 0;
|
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
39
|
const check_1 = require("./check");
|
|
40
|
+
// āāā Group flat step results by Playwright test title āāāāāāāāāāāāāāāāāāāāāāāāā
|
|
41
|
+
function groupResults(results) {
|
|
42
|
+
const order = [];
|
|
43
|
+
const map = new Map();
|
|
44
|
+
for (const r of results) {
|
|
45
|
+
const sep = r.testName.indexOf(' āŗ ');
|
|
46
|
+
const title = sep >= 0 ? r.testName.slice(0, sep) : r.testName;
|
|
47
|
+
if (!map.has(title)) {
|
|
48
|
+
map.set(title, []);
|
|
49
|
+
order.push(title);
|
|
50
|
+
}
|
|
51
|
+
map.get(title).push(r);
|
|
52
|
+
}
|
|
53
|
+
return order.map(testTitle => {
|
|
54
|
+
const steps = map.get(testTitle);
|
|
55
|
+
const hasFail = steps.some(s => s.status === 'FAIL');
|
|
56
|
+
const hasError = steps.some(s => s.status === 'ERROR');
|
|
57
|
+
const allBase = steps.every(s => s.status === 'BASELINE_CREATED');
|
|
58
|
+
const status = hasFail ? 'FAIL' : hasError ? 'ERROR' : allBase ? 'BASELINE_CREATED' : 'PASS';
|
|
59
|
+
return {
|
|
60
|
+
testTitle,
|
|
61
|
+
status,
|
|
62
|
+
passedSteps: steps.filter(s => s.status === 'PASS').length,
|
|
63
|
+
failedSteps: steps.filter(s => s.status === 'FAIL').length,
|
|
64
|
+
erroredSteps: steps.filter(s => s.status === 'ERROR').length,
|
|
65
|
+
baselineSteps: steps.filter(s => s.status === 'BASELINE_CREATED').length,
|
|
66
|
+
steps,
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
}
|
|
40
70
|
// āāā CSS āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
41
71
|
function getCss() {
|
|
42
72
|
return `
|
|
@@ -192,27 +222,36 @@ body {
|
|
|
192
222
|
|
|
193
223
|
/* āā Test list āā */
|
|
194
224
|
.test-list { display: flex; flex-direction: column; gap: 6px; padding-bottom: 48px; }
|
|
195
|
-
.test-item { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); }
|
|
196
|
-
.test-item.s-fail { border-left: 3px solid var(--fail); }
|
|
197
|
-
.test-item.s-base { border-left: 3px solid var(--base); }
|
|
198
|
-
.test-item.s-warn { border-left: 3px solid var(--pixel); }
|
|
199
225
|
|
|
200
|
-
|
|
226
|
+
/* āā Test group ā one Playwright test āā */
|
|
227
|
+
.test-group {
|
|
228
|
+
background: var(--surface); border: 1px solid var(--border);
|
|
229
|
+
border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm);
|
|
230
|
+
}
|
|
231
|
+
.test-group.s-fail { border-left: 3px solid var(--fail); }
|
|
232
|
+
.test-group.s-base { border-left: 3px solid var(--base); }
|
|
233
|
+
.test-group.s-warn { border-left: 3px solid var(--pixel); }
|
|
234
|
+
|
|
235
|
+
/* āā Group header row (clickable, expands step list) āā */
|
|
236
|
+
.group-row {
|
|
201
237
|
display: flex; align-items: center; gap: 11px;
|
|
202
238
|
padding: 12px 14px; cursor: pointer;
|
|
203
239
|
transition: background .1s; user-select: none;
|
|
204
240
|
}
|
|
205
|
-
.
|
|
241
|
+
.group-row:hover { background: var(--surface-2); }
|
|
206
242
|
|
|
243
|
+
/* āā Status dot āā */
|
|
207
244
|
.s-dot {
|
|
208
245
|
width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
|
|
209
246
|
margin-top: 1px;
|
|
210
247
|
}
|
|
248
|
+
.s-dot-sm { width: 6px; height: 6px; margin-top: 0; }
|
|
211
249
|
.s-pass .s-dot { background: var(--pass); }
|
|
212
250
|
.s-fail .s-dot { background: var(--fail); }
|
|
213
251
|
.s-base .s-dot { background: var(--base); }
|
|
214
252
|
.s-warn .s-dot { background: var(--pixel); }
|
|
215
253
|
|
|
254
|
+
/* āā Group text āā */
|
|
216
255
|
.test-meta { flex: 1; min-width: 0; }
|
|
217
256
|
.test-name {
|
|
218
257
|
font-family: ui-monospace, 'SFMono-Regular', 'Fira Code', monospace;
|
|
@@ -224,6 +263,7 @@ body {
|
|
|
224
263
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
225
264
|
}
|
|
226
265
|
|
|
266
|
+
/* āā Badges āā */
|
|
227
267
|
.badges { display: flex; gap: 5px; align-items: center; flex-shrink: 0; }
|
|
228
268
|
.badge {
|
|
229
269
|
font-size: 10px; font-weight: 600; padding: 2px 7px; border-radius: 4px;
|
|
@@ -240,9 +280,35 @@ body {
|
|
|
240
280
|
.chev { font-size: 16px; color: var(--text-3); flex-shrink: 0; line-height: 1; transition: transform .2s; display: inline-block; }
|
|
241
281
|
.chev.open { transform: rotate(90deg); }
|
|
242
282
|
|
|
243
|
-
/* āā
|
|
244
|
-
.
|
|
283
|
+
/* āā Step list (expands when group is open) āā */
|
|
284
|
+
.group-steps { display: none; }
|
|
285
|
+
|
|
286
|
+
/* āā Individual step āā */
|
|
287
|
+
.step-item { border-top: 1px solid var(--border); }
|
|
288
|
+
|
|
289
|
+
/* āā Step header row (clickable, expands detail) āā */
|
|
290
|
+
.step-row {
|
|
291
|
+
display: flex; align-items: center; gap: 9px;
|
|
292
|
+
padding: 9px 14px 9px 34px; cursor: pointer;
|
|
293
|
+
transition: background .1s; user-select: none;
|
|
294
|
+
}
|
|
295
|
+
.step-row:hover { background: var(--surface-2); }
|
|
245
296
|
|
|
297
|
+
/* āā Step text āā */
|
|
298
|
+
.step-meta { flex: 1; min-width: 0; }
|
|
299
|
+
.step-name {
|
|
300
|
+
font-family: ui-monospace, 'SFMono-Regular', 'Fira Code', monospace;
|
|
301
|
+
font-size: 12px; font-weight: 500; color: var(--text-2);
|
|
302
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/* āā Step detail (verdict + images) āā */
|
|
306
|
+
.step-detail {
|
|
307
|
+
display: none; border-top: 1px solid var(--border);
|
|
308
|
+
padding: 16px 14px 16px 34px;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/* āā Verdict box āā */
|
|
246
312
|
.verdict {
|
|
247
313
|
background: var(--accent-soft); border-left: 3px solid var(--accent);
|
|
248
314
|
border-radius: 0 6px 6px 0; padding: 12px 14px; margin-bottom: 18px;
|
|
@@ -267,9 +333,7 @@ body {
|
|
|
267
333
|
.view-tab.diff-tab.on { color: var(--fail); }
|
|
268
334
|
|
|
269
335
|
/* āā Image views āā */
|
|
270
|
-
.img-section { }
|
|
271
336
|
.img-lbl { font-size: 10px; text-transform: uppercase; letter-spacing: 1.2px; color: var(--text-3); font-weight: 500; margin-bottom: 12px; }
|
|
272
|
-
.img-view { }
|
|
273
337
|
.view-img {
|
|
274
338
|
width: 100%; display: block; border-radius: 6px; border: 1px solid var(--border);
|
|
275
339
|
max-height: 360px; object-fit: contain; object-position: top center;
|
|
@@ -380,8 +444,8 @@ function getJs() {
|
|
|
380
444
|
(function () {
|
|
381
445
|
'use strict';
|
|
382
446
|
|
|
383
|
-
var
|
|
384
|
-
var META
|
|
447
|
+
var GROUPS = JSON.parse(document.getElementById('bv-g').textContent);
|
|
448
|
+
var META = JSON.parse(document.getElementById('bv-m').textContent);
|
|
385
449
|
|
|
386
450
|
/* āā State āā */
|
|
387
451
|
var state = {
|
|
@@ -423,23 +487,19 @@ function getJs() {
|
|
|
423
487
|
|
|
424
488
|
/* āā Pixel diff engine (100% client-side, zero server calls) āā */
|
|
425
489
|
|
|
426
|
-
/* Weighted squared RGB distance ā perceptually accurate, fast (no sqrt needed) */
|
|
427
490
|
function colorDist(r1, g1, b1, r2, g2, b2) {
|
|
428
491
|
var rd = r1 - r2, gd = g1 - g2, bd = b1 - b2;
|
|
429
492
|
return rd * rd * 0.299 + gd * gd * 0.587 + bd * bd * 0.114;
|
|
430
493
|
}
|
|
431
494
|
|
|
432
|
-
/* Render diff image: changed pixels = neon red, unchanged = desaturated baseline */
|
|
433
495
|
function renderDiff(d1, d2, w, h) {
|
|
434
496
|
var n = w * h * 4;
|
|
435
497
|
var out = new Uint8ClampedArray(n);
|
|
436
|
-
var thr = 900;
|
|
498
|
+
var thr = 900;
|
|
437
499
|
for (var i = 0; i < n; i += 4) {
|
|
438
500
|
if (colorDist(d1[i], d1[i+1], d1[i+2], d2[i], d2[i+1], d2[i+2]) > thr) {
|
|
439
|
-
/* neon red highlight */
|
|
440
501
|
out[i] = 220; out[i+1] = 38; out[i+2] = 38; out[i+3] = 255;
|
|
441
502
|
} else {
|
|
442
|
-
/* desaturated baseline ā guides the eye to red pixels */
|
|
443
503
|
var lum = (d1[i] * 77 + d1[i+1] * 150 + d1[i+2] * 29) >> 8;
|
|
444
504
|
out[i] = lum; out[i+1] = lum; out[i+2] = lum; out[i+3] = 210;
|
|
445
505
|
}
|
|
@@ -447,7 +507,6 @@ function getJs() {
|
|
|
447
507
|
return new ImageData(out, w, h);
|
|
448
508
|
}
|
|
449
509
|
|
|
450
|
-
/* Load image and extract raw pixel data via canvas */
|
|
451
510
|
function loadImgPixels(url, cb) {
|
|
452
511
|
var img = new Image();
|
|
453
512
|
img.crossOrigin = 'anonymous';
|
|
@@ -469,7 +528,6 @@ function getJs() {
|
|
|
469
528
|
var diffCache = {};
|
|
470
529
|
|
|
471
530
|
function genDiff(idx, baseUrl, curUrl, container) {
|
|
472
|
-
/* Return cached result if already computed */
|
|
473
531
|
if (diffCache[idx]) {
|
|
474
532
|
var cached = diffCache[idx];
|
|
475
533
|
var clone = document.createElement('canvas');
|
|
@@ -525,7 +583,6 @@ function getJs() {
|
|
|
525
583
|
|
|
526
584
|
function lbReset() { lb.scale = 1; lb.tx = 0; lb.ty = 0; lbApply(); }
|
|
527
585
|
|
|
528
|
-
/* Zoom towards a viewport-center-relative point (mx, my) */
|
|
529
586
|
function lbZoom(factor, mx, my) {
|
|
530
587
|
var ns = Math.max(lb.minScale, Math.min(lb.maxScale, lb.scale * factor));
|
|
531
588
|
var r = ns / lb.scale;
|
|
@@ -535,7 +592,6 @@ function getJs() {
|
|
|
535
592
|
lbApply();
|
|
536
593
|
}
|
|
537
594
|
|
|
538
|
-
/* Auto-fit: scale image to fill viewport on first open */
|
|
539
595
|
function lbAutoFit(w, h) {
|
|
540
596
|
var vw = lb.inner.clientWidth - 48;
|
|
541
597
|
var vh = lb.inner.clientHeight - 48;
|
|
@@ -556,7 +612,6 @@ function getJs() {
|
|
|
556
612
|
el.onload = function () { lbAutoFit(el.naturalWidth, el.naturalHeight); };
|
|
557
613
|
el.src = payload;
|
|
558
614
|
} else {
|
|
559
|
-
/* diff canvas */
|
|
560
615
|
var src = diffCache[payload];
|
|
561
616
|
if (!src) return;
|
|
562
617
|
el = document.createElement('canvas');
|
|
@@ -603,28 +658,19 @@ function getJs() {
|
|
|
603
658
|
lb.wrap = ov.querySelector('.lb-img-wrap');
|
|
604
659
|
lb.zoomLbl = ov.querySelector('.lb-zoom-label');
|
|
605
660
|
|
|
606
|
-
/* close button */
|
|
607
661
|
ov.querySelector('.lb-close').addEventListener('click', lbClose);
|
|
608
|
-
|
|
609
|
-
/* click on backdrop (not on image) */
|
|
610
662
|
lb.inner.addEventListener('click', function (e) {
|
|
611
663
|
if (e.target === lb.inner) lbClose();
|
|
612
664
|
});
|
|
613
|
-
|
|
614
|
-
/* double-click: reset zoom */
|
|
615
665
|
lb.inner.addEventListener('dblclick', function (e) {
|
|
616
666
|
e.preventDefault();
|
|
617
667
|
lbReset();
|
|
618
668
|
});
|
|
619
|
-
|
|
620
|
-
/* scroll-to-zoom */
|
|
621
669
|
lb.inner.addEventListener('wheel', function (e) {
|
|
622
670
|
e.preventDefault();
|
|
623
671
|
var p = lbCenterPos(e);
|
|
624
672
|
lbZoom(e.deltaY < 0 ? 1.12 : 1 / 1.12, p.x, p.y);
|
|
625
673
|
}, { passive: false });
|
|
626
|
-
|
|
627
|
-
/* mouse drag: pan */
|
|
628
674
|
lb.inner.addEventListener('mousedown', function (e) {
|
|
629
675
|
if (e.button !== 0) return;
|
|
630
676
|
lb.dragging = true;
|
|
@@ -644,8 +690,6 @@ function getJs() {
|
|
|
644
690
|
lb.dragging = false;
|
|
645
691
|
lb.wrap.classList.remove('dragging');
|
|
646
692
|
});
|
|
647
|
-
|
|
648
|
-
/* touch: pan + pinch-to-zoom */
|
|
649
693
|
lb.inner.addEventListener('touchstart', function (e) {
|
|
650
694
|
if (e.touches.length === 2) {
|
|
651
695
|
var dx = e.touches[0].clientX - e.touches[1].clientX;
|
|
@@ -674,8 +718,6 @@ function getJs() {
|
|
|
674
718
|
}
|
|
675
719
|
}, { passive: false });
|
|
676
720
|
lb.inner.addEventListener('touchend', function () { lb.dragging = false; }, { passive: true });
|
|
677
|
-
|
|
678
|
-
/* keyboard shortcuts */
|
|
679
721
|
document.addEventListener('keydown', function (e) {
|
|
680
722
|
if (!lb.overlay.classList.contains('open')) return;
|
|
681
723
|
if (e.key === 'Escape') lbClose();
|
|
@@ -684,6 +726,7 @@ function getJs() {
|
|
|
684
726
|
}
|
|
685
727
|
|
|
686
728
|
/* āā HTML builders āā */
|
|
729
|
+
|
|
687
730
|
function statusInfo(r) {
|
|
688
731
|
if (r.status === 'PASS') return { cls:'s-pass', badge:'m-pass', label:'PASS' };
|
|
689
732
|
if (r.status === 'FAIL') return { cls:'s-fail', badge:'m-fail', label:'FAIL' };
|
|
@@ -749,40 +792,75 @@ function getJs() {
|
|
|
749
792
|
+ tabs + basePanel + curPanel + diffPanel;
|
|
750
793
|
}
|
|
751
794
|
|
|
752
|
-
|
|
753
|
-
|
|
795
|
+
/* Build a single visual-check step row + expandable detail */
|
|
796
|
+
function buildStep(r) {
|
|
797
|
+
var s = statusInfo(r);
|
|
798
|
+
var method = methodLabel(r);
|
|
799
|
+
var methodCls = methodBadgeCls(r);
|
|
800
|
+
|
|
801
|
+
/* Extract step name: "Test title āŗ step name" ā "step name" */
|
|
802
|
+
var raw = r.testName || '';
|
|
803
|
+
var sepIdx = raw.indexOf(' \u203a ');
|
|
804
|
+
var stepName = sepIdx >= 0 ? raw.slice(sepIdx + 3) : raw;
|
|
805
|
+
|
|
754
806
|
var verdictLbl = r.method === 'FAST_PIXEL_MATCH'
|
|
755
807
|
? '\u26A1 Fast Pixel Match'
|
|
756
808
|
: '\uD83E\uDD16 AI Verdict';
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
809
|
+
var imgWrap = r.status === 'PASS' ? 'img-section pass-imgs' : 'img-section';
|
|
810
|
+
|
|
811
|
+
return '<div class="step-item ' + s.cls + '">'
|
|
812
|
+
+ '<div class="step-row" data-s="' + r.index + '">'
|
|
813
|
+
+ '<div class="s-dot s-dot-sm"></div>'
|
|
814
|
+
+ '<div class="step-meta">'
|
|
815
|
+
+ '<div class="step-name">' + esc(stepName) + '</div>'
|
|
816
|
+
+ '</div>'
|
|
817
|
+
+ '<div class="badges">'
|
|
818
|
+
+ '<span class="badge ' + methodCls + '">' + method + '</span>'
|
|
819
|
+
+ '<span class="badge ' + s.badge + '">' + s.label + '</span>'
|
|
820
|
+
+ '</div>'
|
|
821
|
+
+ '<span class="chev" id="sc' + r.index + '">\u203a</span>'
|
|
822
|
+
+ '</div>'
|
|
823
|
+
+ '<div class="step-detail" id="sd' + r.index + '">'
|
|
824
|
+
+ '<div class="verdict">'
|
|
825
|
+
+ '<div class="verdict-lbl">' + verdictLbl + '</div>'
|
|
826
|
+
+ '<p class="verdict-txt">\u201C' + esc(r.reason) + '\u201D</p>'
|
|
827
|
+
+ '</div>'
|
|
828
|
+
+ '<div class="' + imgWrap + '">' + buildImages(r) + '</div>'
|
|
761
829
|
+ '</div>'
|
|
762
|
-
|
|
763
|
-
+ '</div>';
|
|
830
|
+
+ '</div>';
|
|
764
831
|
}
|
|
765
832
|
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
var
|
|
769
|
-
var
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
833
|
+
/* Build a test group row (Playwright test + its visual-check steps) */
|
|
834
|
+
function buildGroup(g, gIdx) {
|
|
835
|
+
var s = statusInfo(g);
|
|
836
|
+
var n = g.steps.length;
|
|
837
|
+
|
|
838
|
+
/* Snip: "5 visual checks Ā· 2 failed" or "3 visual checks Ā· all passed" */
|
|
839
|
+
var parts = [];
|
|
840
|
+
if (g.failedSteps > 0) parts.push(g.failedSteps + ' failed');
|
|
841
|
+
if (g.erroredSteps > 0) parts.push(g.erroredSteps + (g.erroredSteps !== 1 ? ' errors' : ' error'));
|
|
842
|
+
if (g.baselineSteps > 0 && g.failedSteps === 0 && g.erroredSteps === 0)
|
|
843
|
+
parts.push('baselines created');
|
|
844
|
+
var checkWord = n === 1 ? 'visual check' : 'visual checks';
|
|
845
|
+
var snip = n + ' ' + checkWord
|
|
846
|
+
+ (parts.length > 0 ? ' \u00b7 ' + parts.join(' \u00b7 ') : ' \u00b7 all passed');
|
|
847
|
+
|
|
848
|
+
var stepsHtml = g.steps.map(buildStep).join('');
|
|
849
|
+
|
|
850
|
+
return '<div class="test-group ' + s.cls + '" data-gst="' + g.status + '">'
|
|
851
|
+
+ '<div class="group-row" data-g="' + gIdx + '">'
|
|
773
852
|
+ '<div class="s-dot"></div>'
|
|
774
853
|
+ '<div class="test-meta">'
|
|
775
|
-
+ '<div class="test-name">' + esc(
|
|
776
|
-
+ '<div class="test-snip">'
|
|
854
|
+
+ '<div class="test-name">' + esc(g.testTitle) + '</div>'
|
|
855
|
+
+ '<div class="test-snip">' + esc(snip) + '</div>'
|
|
777
856
|
+ '</div>'
|
|
778
857
|
+ '<div class="badges">'
|
|
779
|
-
+ '<span class="badge ' +
|
|
780
|
-
+ '<span class="badge ' + s.badge + '">' + s.label + '</span>'
|
|
858
|
+
+ '<span class="badge ' + s.badge + '">' + s.label + '</span>'
|
|
781
859
|
+ '</div>'
|
|
782
|
-
+ '<span class="chev" id="
|
|
860
|
+
+ '<span class="chev" id="gc' + gIdx + '">\u203a</span>'
|
|
783
861
|
+ '</div>'
|
|
784
|
-
+
|
|
785
|
-
|
|
862
|
+
+ '<div class="group-steps" id="gs' + gIdx + '">' + stepsHtml + '</div>'
|
|
863
|
+
+ '</div>';
|
|
786
864
|
}
|
|
787
865
|
|
|
788
866
|
function buildThemeBtns() {
|
|
@@ -812,7 +890,7 @@ function getJs() {
|
|
|
812
890
|
var warnFilter = hasErrors
|
|
813
891
|
? '<button class="f-btn" data-f="warn">Errors (' + META.errored + ')</button>'
|
|
814
892
|
: '';
|
|
815
|
-
var items
|
|
893
|
+
var items = GROUPS.map(function (g, i) { return buildGroup(g, i); }).join('');
|
|
816
894
|
|
|
817
895
|
return '<header class="hdr">'
|
|
818
896
|
+ '<div class="wrap"><div class="hdr-inner">'
|
|
@@ -826,7 +904,7 @@ function getJs() {
|
|
|
826
904
|
+ '</header>'
|
|
827
905
|
+ '<div class="wrap">'
|
|
828
906
|
+ '<div class="summary">'
|
|
829
|
-
+ '<div class="stat"><div class="stat-lbl">
|
|
907
|
+
+ '<div class="stat"><div class="stat-lbl">Tests</div><div class="stat-val">' + META.total + '</div></div>'
|
|
830
908
|
+ '<div class="stat s-pass"><div class="stat-lbl">Passed</div><div class="stat-val">' + META.passed + '</div></div>'
|
|
831
909
|
+ '<div class="stat' + failCls + '"><div class="stat-lbl">Failed</div><div class="stat-val">' + META.failed + '</div></div>'
|
|
832
910
|
+ warnStat
|
|
@@ -853,35 +931,45 @@ function getJs() {
|
|
|
853
931
|
function bind() {
|
|
854
932
|
var tlist = document.getElementById('tlist');
|
|
855
933
|
|
|
856
|
-
/* accordion expand/collapse
|
|
934
|
+
/* Level 1: test group accordion ā expand/collapse step list */
|
|
935
|
+
tlist.addEventListener('click', function (e) {
|
|
936
|
+
var row = e.target.closest('[data-g]');
|
|
937
|
+
if (!row) return;
|
|
938
|
+
var idx = row.getAttribute('data-g');
|
|
939
|
+
var steps = document.getElementById('gs' + idx);
|
|
940
|
+
var chev = document.getElementById('gc' + idx);
|
|
941
|
+
if (!steps) return;
|
|
942
|
+
var open = steps.style.display !== 'none';
|
|
943
|
+
steps.style.display = open ? 'none' : 'block';
|
|
944
|
+
if (chev) chev.classList.toggle('open', !open);
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
/* Level 2: step accordion ā expand/collapse verdict + images */
|
|
857
948
|
tlist.addEventListener('click', function (e) {
|
|
858
|
-
var row = e.target.closest('[data-
|
|
949
|
+
var row = e.target.closest('[data-s]');
|
|
859
950
|
if (!row) return;
|
|
860
|
-
var idx
|
|
861
|
-
var detail
|
|
862
|
-
var
|
|
951
|
+
var idx = row.getAttribute('data-s');
|
|
952
|
+
var detail = document.getElementById('sd' + idx);
|
|
953
|
+
var chev = document.getElementById('sc' + idx);
|
|
863
954
|
if (!detail) return;
|
|
864
955
|
var open = detail.style.display !== 'none';
|
|
865
956
|
detail.style.display = open ? 'none' : 'block';
|
|
866
|
-
if (
|
|
957
|
+
if (chev) chev.classList.toggle('open', !open);
|
|
867
958
|
});
|
|
868
959
|
|
|
869
|
-
/*
|
|
960
|
+
/* View-tab switching: Baseline / Current / Diff */
|
|
870
961
|
tlist.addEventListener('click', function (e) {
|
|
871
962
|
var tab = e.target.closest('[data-tab]');
|
|
872
963
|
if (!tab) return;
|
|
873
964
|
var tidx = tab.getAttribute('data-tidx');
|
|
874
965
|
var tabName = tab.getAttribute('data-tab');
|
|
875
|
-
/* update active tab */
|
|
876
966
|
tab.closest('.view-tabs').querySelectorAll('.view-tab').forEach(function (t) {
|
|
877
967
|
t.classList.toggle('on', t === tab);
|
|
878
968
|
});
|
|
879
|
-
/* show correct panel, hide others */
|
|
880
969
|
['base', 'cur', 'diff'].forEach(function (key) {
|
|
881
970
|
var panel = document.getElementById('v' + key + '-' + tidx);
|
|
882
971
|
if (panel) panel.style.display = key === tabName ? '' : 'none';
|
|
883
972
|
});
|
|
884
|
-
/* lazy diff generation ā only on first click */
|
|
885
973
|
if (tabName === 'diff') {
|
|
886
974
|
var dp = document.getElementById('vdiff-' + tidx);
|
|
887
975
|
if (dp && dp.getAttribute('data-ready') === '0') {
|
|
@@ -891,7 +979,7 @@ function getJs() {
|
|
|
891
979
|
}
|
|
892
980
|
});
|
|
893
981
|
|
|
894
|
-
/*
|
|
982
|
+
/* Image / diff-canvas click ā open lightbox */
|
|
895
983
|
tlist.addEventListener('click', function (e) {
|
|
896
984
|
var el = e.target.closest('[data-lb]');
|
|
897
985
|
if (!el) return;
|
|
@@ -900,7 +988,7 @@ function getJs() {
|
|
|
900
988
|
if (type === 'diff') lbOpen('diff', el.getAttribute('data-lb-idx'));
|
|
901
989
|
});
|
|
902
990
|
|
|
903
|
-
/*
|
|
991
|
+
/* Theme */
|
|
904
992
|
document.getElementById('t-toggle').addEventListener('click', function (e) {
|
|
905
993
|
var btn = e.target.closest('[data-th]');
|
|
906
994
|
if (!btn) return;
|
|
@@ -912,7 +1000,7 @@ function getJs() {
|
|
|
912
1000
|
});
|
|
913
1001
|
});
|
|
914
1002
|
|
|
915
|
-
/*
|
|
1003
|
+
/* Screenshots on pass toggle */
|
|
916
1004
|
document.getElementById('img-btn').addEventListener('click', function () {
|
|
917
1005
|
state.showPassImg = !state.showPassImg;
|
|
918
1006
|
localStorage.setItem('bv-pass-img', String(state.showPassImg));
|
|
@@ -920,18 +1008,20 @@ function getJs() {
|
|
|
920
1008
|
this.classList.toggle('on', state.showPassImg);
|
|
921
1009
|
});
|
|
922
1010
|
|
|
923
|
-
/*
|
|
1011
|
+
/* Filter ā operates at test-group level */
|
|
924
1012
|
document.querySelectorAll('[data-f]').forEach(function (btn) {
|
|
925
1013
|
btn.addEventListener('click', function () {
|
|
926
1014
|
var f = btn.getAttribute('data-f');
|
|
927
1015
|
document.querySelectorAll('[data-f]').forEach(function (b) {
|
|
928
1016
|
b.classList.toggle('on', b.getAttribute('data-f') === f);
|
|
929
1017
|
});
|
|
930
|
-
document.querySelectorAll('.test-
|
|
1018
|
+
document.querySelectorAll('.test-group').forEach(function (el) {
|
|
1019
|
+
var gst = el.getAttribute('data-gst');
|
|
931
1020
|
var show = f === 'all'
|
|
932
|
-
|| (f === 'pass' &&
|
|
933
|
-
|| (f === 'fail' &&
|
|
934
|
-
|| (f === 'warn' &&
|
|
1021
|
+
|| (f === 'pass' && gst === 'PASS')
|
|
1022
|
+
|| (f === 'fail' && gst === 'FAIL')
|
|
1023
|
+
|| (f === 'warn' && gst === 'ERROR')
|
|
1024
|
+
|| (f === 'base' && gst === 'BASELINE_CREATED');
|
|
935
1025
|
el.style.display = show ? '' : 'none';
|
|
936
1026
|
});
|
|
937
1027
|
});
|
|
@@ -952,8 +1042,8 @@ function getJs() {
|
|
|
952
1042
|
`.trim();
|
|
953
1043
|
}
|
|
954
1044
|
// āāā HTML Assembly āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
955
|
-
function generateHTML(
|
|
956
|
-
const
|
|
1045
|
+
function generateHTML(groups, meta) {
|
|
1046
|
+
const groupsJson = JSON.stringify(groups);
|
|
957
1047
|
const metaJson = JSON.stringify(meta);
|
|
958
1048
|
const svgPass = encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="6" fill="#1a2e22"/><path d="M7 16.5L13 22L25 10" stroke="#73c991" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></svg>');
|
|
959
1049
|
const svgFail = encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="6" fill="#2a1515"/><path d="M10 10L22 22M22 10L10 22" stroke="#f14c4c" stroke-width="3" stroke-linecap="round"/></svg>');
|
|
@@ -977,7 +1067,7 @@ function generateHTML(results, meta) {
|
|
|
977
1067
|
</head>
|
|
978
1068
|
<body>
|
|
979
1069
|
<div id="root"></div>
|
|
980
|
-
<script type="application/json" id="bv-
|
|
1070
|
+
<script type="application/json" id="bv-g">${groupsJson}</script>
|
|
981
1071
|
<script type="application/json" id="bv-m">${metaJson}</script>
|
|
982
1072
|
<script>${getJs()}</script>
|
|
983
1073
|
</body>
|
|
@@ -1010,13 +1100,14 @@ class BugHuntersVisionReporter {
|
|
|
1010
1100
|
return;
|
|
1011
1101
|
}
|
|
1012
1102
|
const results = JSON.parse(raw);
|
|
1013
|
-
const
|
|
1014
|
-
const
|
|
1015
|
-
const
|
|
1016
|
-
const
|
|
1103
|
+
const groups = groupResults(results);
|
|
1104
|
+
const passed = groups.filter(g => g.status === 'PASS').length;
|
|
1105
|
+
const failed = groups.filter(g => g.status === 'FAIL').length;
|
|
1106
|
+
const baselines = groups.filter(g => g.status === 'BASELINE_CREATED').length;
|
|
1107
|
+
const errored = groups.filter(g => g.status === 'ERROR').length;
|
|
1017
1108
|
const meta = {
|
|
1018
1109
|
generatedAt: new Date().toISOString(),
|
|
1019
|
-
total:
|
|
1110
|
+
total: groups.length,
|
|
1020
1111
|
passed,
|
|
1021
1112
|
failed,
|
|
1022
1113
|
baselines,
|
|
@@ -1024,11 +1115,13 @@ class BugHuntersVisionReporter {
|
|
|
1024
1115
|
};
|
|
1025
1116
|
const reportPath = path.join(this.reportDir, 'index.html');
|
|
1026
1117
|
fs.mkdirSync(this.reportDir, { recursive: true });
|
|
1027
|
-
fs.writeFileSync(reportPath, generateHTML(
|
|
1118
|
+
fs.writeFileSync(reportPath, generateHTML(groups, meta), 'utf-8');
|
|
1119
|
+
const testWord = groups.length === 1 ? 'test' : 'tests';
|
|
1120
|
+
const stepWord = results.length === 1 ? 'check' : 'checks';
|
|
1028
1121
|
console.log('\n\uD83D\uDC1E BugHunters Vision Report generated:');
|
|
1029
1122
|
console.log(' \uD83D\uDCC4 ' + reportPath);
|
|
1030
1123
|
const erroredStr = errored > 0 ? ' \u26A0\uFE0F ' + errored + ' errored' : '';
|
|
1031
|
-
console.log(' \u2705 ' + passed + ' passed \u274C ' + failed + ' failed' + erroredStr + ' (' + results.length + ' total)');
|
|
1124
|
+
console.log(' \u2705 ' + passed + ' passed \u274C ' + failed + ' failed' + erroredStr + ' (' + groups.length + ' ' + testWord + ' \u00B7 ' + results.length + ' ' + stepWord + ' total)');
|
|
1032
1125
|
// Show remaining API balance if an AI call was made this run
|
|
1033
1126
|
const balance = (0, check_1.getLastRemainingBalance)();
|
|
1034
1127
|
if (balance !== null) {
|
package/dist/types.d.ts
CHANGED
|
@@ -9,6 +9,15 @@ export interface TestResult {
|
|
|
9
9
|
currentFile: string | null;
|
|
10
10
|
timestamp: string;
|
|
11
11
|
}
|
|
12
|
+
export interface TestGroup {
|
|
13
|
+
testTitle: string;
|
|
14
|
+
status: 'PASS' | 'FAIL' | 'BASELINE_CREATED' | 'ERROR';
|
|
15
|
+
passedSteps: number;
|
|
16
|
+
failedSteps: number;
|
|
17
|
+
erroredSteps: number;
|
|
18
|
+
baselineSteps: number;
|
|
19
|
+
steps: TestResult[];
|
|
20
|
+
}
|
|
12
21
|
export interface Meta {
|
|
13
22
|
generatedAt: string;
|
|
14
23
|
total: number;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEjD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,kBAAkB,GAAG,OAAO,CAAC;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,IAAI,GAAG,kBAAkB,GAAG,IAAI,CAAC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEjD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,kBAAkB,GAAG,OAAO,CAAC;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,IAAI,GAAG,kBAAkB,GAAG,IAAI,CAAC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,kBAAkB,GAAG,OAAO,CAAC;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,IAAI;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB"}
|