@vizzly-testing/cli 0.28.0 → 0.29.0
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/commands/builds.js +30 -10
- package/dist/commands/comparisons.js +69 -18
- package/package.json +1 -1
package/dist/commands/builds.js
CHANGED
|
@@ -50,9 +50,7 @@ export async function buildsCommand(options = {}, globalOptions = {}, deps = {})
|
|
|
50
50
|
if (options.build) {
|
|
51
51
|
output.startSpinner('Fetching build...');
|
|
52
52
|
let include = options.comparisons ? 'comparisons' : undefined;
|
|
53
|
-
let response = await getBuild(client, options.build,
|
|
54
|
-
include
|
|
55
|
-
});
|
|
53
|
+
let response = await getBuild(client, options.build, include);
|
|
56
54
|
output.stopSpinner();
|
|
57
55
|
let build = response.build || response;
|
|
58
56
|
if (globalOptions.json) {
|
|
@@ -163,13 +161,35 @@ function formatBuildForJson(build, includeComparisons = false) {
|
|
|
163
161
|
completedAt: build.completed_at
|
|
164
162
|
};
|
|
165
163
|
if (includeComparisons && build.comparisons) {
|
|
166
|
-
result.comparisonDetails = build.comparisons.map(c =>
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
164
|
+
result.comparisonDetails = build.comparisons.map(c => {
|
|
165
|
+
let diffUrl = c.diff_image?.url || c.diff_image_url || c.diff_url || null;
|
|
166
|
+
let diffImage = c.diff_image || {};
|
|
167
|
+
let clusterMetadata = c.cluster_metadata || diffImage.cluster_metadata || null;
|
|
168
|
+
let ssimScore = c.ssim_score ?? diffImage.ssim_score ?? null;
|
|
169
|
+
let gmsdScore = c.gmsd_score ?? diffImage.gmsd_score ?? null;
|
|
170
|
+
let fingerprintHash = c.fingerprint_hash || diffImage.fingerprint_hash || null;
|
|
171
|
+
let hasHoneydiff = clusterMetadata || ssimScore != null || gmsdScore != null || fingerprintHash;
|
|
172
|
+
return {
|
|
173
|
+
id: c.id,
|
|
174
|
+
name: c.name,
|
|
175
|
+
status: c.status,
|
|
176
|
+
diffPercentage: c.diff_percentage,
|
|
177
|
+
approvalStatus: c.approval_status,
|
|
178
|
+
urls: {
|
|
179
|
+
baseline: c.baseline_screenshot?.original_url || c.baseline_original_url || c.baseline_screenshot_url || null,
|
|
180
|
+
current: c.current_screenshot?.original_url || c.current_original_url || c.current_screenshot_url || null,
|
|
181
|
+
diff: diffUrl
|
|
182
|
+
},
|
|
183
|
+
honeydiff: hasHoneydiff ? {
|
|
184
|
+
ssimScore,
|
|
185
|
+
gmsdScore,
|
|
186
|
+
clusterClassification: clusterMetadata?.classification || null,
|
|
187
|
+
clusterMetadata,
|
|
188
|
+
fingerprintHash,
|
|
189
|
+
diffRegions: c.diff_regions ?? diffImage.diff_regions ?? null
|
|
190
|
+
} : null
|
|
191
|
+
};
|
|
192
|
+
});
|
|
173
193
|
}
|
|
174
194
|
return result;
|
|
175
195
|
}
|
|
@@ -65,9 +65,7 @@ export async function comparisonsCommand(options = {}, globalOptions = {}, deps
|
|
|
65
65
|
// Get comparisons for a specific build
|
|
66
66
|
if (options.build) {
|
|
67
67
|
output.startSpinner('Fetching comparisons for build...');
|
|
68
|
-
let response = await getBuild(client, options.build,
|
|
69
|
-
include: 'comparisons'
|
|
70
|
-
});
|
|
68
|
+
let response = await getBuild(client, options.build, 'comparisons');
|
|
71
69
|
output.stopSpinner();
|
|
72
70
|
let build = response.build || response;
|
|
73
71
|
let comparisons = build.comparisons || [];
|
|
@@ -156,6 +154,16 @@ export async function comparisonsCommand(options = {}, globalOptions = {}, deps
|
|
|
156
154
|
* Format a comparison for JSON output
|
|
157
155
|
*/
|
|
158
156
|
function formatComparisonForJson(comparison) {
|
|
157
|
+
// API endpoints return different shapes:
|
|
158
|
+
// - Single comparison: nested baseline_screenshot/current_screenshot + flat diff_url, honeydiff at top level
|
|
159
|
+
// - Build comparisons: flat diff_url/diff_image_url, no storage URLs, limited honeydiff
|
|
160
|
+
// - Search: nested diff_image with honeydiff, no current/baseline URLs
|
|
161
|
+
let diffImage = comparison.diff_image || {};
|
|
162
|
+
let clusterMetadata = comparison.cluster_metadata || diffImage.cluster_metadata || null;
|
|
163
|
+
let ssimScore = comparison.ssim_score ?? diffImage.ssim_score ?? null;
|
|
164
|
+
let gmsdScore = comparison.gmsd_score ?? diffImage.gmsd_score ?? null;
|
|
165
|
+
let fingerprintHash = comparison.fingerprint_hash || diffImage.fingerprint_hash || null;
|
|
166
|
+
let hasHoneydiff = clusterMetadata || ssimScore != null || gmsdScore != null || fingerprintHash;
|
|
159
167
|
return {
|
|
160
168
|
id: comparison.id,
|
|
161
169
|
name: comparison.name,
|
|
@@ -168,10 +176,20 @@ function formatComparisonForJson(comparison) {
|
|
|
168
176
|
} : null,
|
|
169
177
|
browser: comparison.browser || null,
|
|
170
178
|
urls: {
|
|
171
|
-
baseline: comparison.baseline_screenshot?.original_url || null,
|
|
172
|
-
current: comparison.current_screenshot?.original_url || null,
|
|
173
|
-
diff: comparison.diff_image?.url || null
|
|
179
|
+
baseline: comparison.baseline_screenshot?.original_url || comparison.baseline_original_url || comparison.baseline_screenshot_url || null,
|
|
180
|
+
current: comparison.current_screenshot?.original_url || comparison.current_original_url || comparison.current_screenshot_url || null,
|
|
181
|
+
diff: comparison.diff_image?.url || comparison.diff_image_url || comparison.diff_url || null
|
|
174
182
|
},
|
|
183
|
+
honeydiff: hasHoneydiff ? {
|
|
184
|
+
ssimScore,
|
|
185
|
+
gmsdScore,
|
|
186
|
+
clusterClassification: clusterMetadata?.classification || null,
|
|
187
|
+
clusterMetadata,
|
|
188
|
+
fingerprintHash,
|
|
189
|
+
diffRegions: comparison.diff_regions ?? diffImage.diff_regions ?? null,
|
|
190
|
+
diffLines: comparison.diff_lines ?? diffImage.diff_lines ?? null,
|
|
191
|
+
fingerprintData: comparison.fingerprint_data ?? diffImage.fingerprint_data ?? null
|
|
192
|
+
} : null,
|
|
175
193
|
buildId: comparison.build_id,
|
|
176
194
|
buildName: comparison.build_name,
|
|
177
195
|
buildBranch: comparison.build_branch,
|
|
@@ -211,18 +229,40 @@ function displayComparison(output, comparison, verbose) {
|
|
|
211
229
|
output.labelValue('Commit', comparison.build_commit_sha.substring(0, 8));
|
|
212
230
|
}
|
|
213
231
|
|
|
214
|
-
//
|
|
232
|
+
// Honeydiff analysis in verbose mode
|
|
215
233
|
if (verbose) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
234
|
+
let clusterMetadata = comparison.cluster_metadata || comparison.diff_image?.cluster_metadata;
|
|
235
|
+
let ssim = comparison.ssim_score ?? comparison.diff_image?.ssim_score;
|
|
236
|
+
let gmsd = comparison.gmsd_score ?? comparison.diff_image?.gmsd_score;
|
|
237
|
+
let fingerprint = comparison.fingerprint_hash || comparison.diff_image?.fingerprint_hash;
|
|
238
|
+
if (clusterMetadata || ssim != null || gmsd != null || fingerprint) {
|
|
239
|
+
output.blank();
|
|
240
|
+
if (clusterMetadata?.classification) {
|
|
241
|
+
output.labelValue('Classification', clusterMetadata.classification);
|
|
242
|
+
}
|
|
243
|
+
if (ssim != null) {
|
|
244
|
+
output.labelValue('SSIM', ssim.toFixed(4));
|
|
245
|
+
}
|
|
246
|
+
if (gmsd != null) {
|
|
247
|
+
output.labelValue('GMSD', gmsd.toFixed(4));
|
|
248
|
+
}
|
|
249
|
+
if (fingerprint) {
|
|
250
|
+
output.labelValue('Fingerprint', fingerprint);
|
|
251
|
+
}
|
|
223
252
|
}
|
|
224
|
-
|
|
225
|
-
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// URLs in verbose mode
|
|
256
|
+
if (verbose) {
|
|
257
|
+
let baselineUrl = comparison.baseline_screenshot?.original_url || comparison.baseline_original_url || comparison.baseline_screenshot_url;
|
|
258
|
+
let currentUrl = comparison.current_screenshot?.original_url || comparison.current_original_url || comparison.current_screenshot_url;
|
|
259
|
+
let diffUrl = comparison.diff_image?.url || comparison.diff_image_url || comparison.diff_url;
|
|
260
|
+
if (baselineUrl || currentUrl || diffUrl) {
|
|
261
|
+
output.blank();
|
|
262
|
+
output.labelValue('URLs', '');
|
|
263
|
+
if (baselineUrl) output.print(` Baseline: ${baselineUrl}`);
|
|
264
|
+
if (currentUrl) output.print(` Current: ${currentUrl}`);
|
|
265
|
+
if (diffUrl) output.print(` Diff: ${diffUrl}`);
|
|
226
266
|
}
|
|
227
267
|
}
|
|
228
268
|
if (comparison.created_at) {
|
|
@@ -260,7 +300,8 @@ function displayBuildComparisons(output, build, comparisons, verbose) {
|
|
|
260
300
|
for (let comp of comparisons.slice(0, verbose ? 100 : 20)) {
|
|
261
301
|
let icon = getStatusIcon(colors, comp.status);
|
|
262
302
|
let diffInfo = comp.diff_percentage != null ? colors.dim(` (${(comp.diff_percentage * 100).toFixed(1)}%)`) : '';
|
|
263
|
-
|
|
303
|
+
let classification = verbose ? getClassificationLabel(colors, comp.cluster_metadata) : '';
|
|
304
|
+
output.print(` ${icon} ${comp.name}${diffInfo}${classification}`);
|
|
264
305
|
}
|
|
265
306
|
if (comparisons.length > (verbose ? 100 : 20)) {
|
|
266
307
|
output.blank();
|
|
@@ -301,7 +342,8 @@ function displaySearchResults(output, comparisons, searchPattern, pagination, ve
|
|
|
301
342
|
}
|
|
302
343
|
for (let comp of group.comparisons.slice(0, verbose ? 10 : 3)) {
|
|
303
344
|
let icon = getStatusIcon(colors, comp.status);
|
|
304
|
-
|
|
345
|
+
let classification = verbose ? getClassificationLabel(colors, comp.cluster_metadata || comp.diff_image?.cluster_metadata) : '';
|
|
346
|
+
output.print(` ${icon} ${comp.name}${classification}`);
|
|
305
347
|
}
|
|
306
348
|
if (group.comparisons.length > (verbose ? 10 : 3)) {
|
|
307
349
|
output.print(` ${colors.dim(`... and ${group.comparisons.length - (verbose ? 10 : 3)} more`)}`);
|
|
@@ -313,6 +355,15 @@ function displaySearchResults(output, comparisons, searchPattern, pagination, ve
|
|
|
313
355
|
}
|
|
314
356
|
}
|
|
315
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Get a classification label for verbose display
|
|
360
|
+
*/
|
|
361
|
+
function getClassificationLabel(colors, clusterMetadata) {
|
|
362
|
+
let classification = clusterMetadata?.classification;
|
|
363
|
+
if (!classification) return '';
|
|
364
|
+
return colors.dim(` [${classification}]`);
|
|
365
|
+
}
|
|
366
|
+
|
|
316
367
|
/**
|
|
317
368
|
* Get icon for comparison status
|
|
318
369
|
*/
|