Skip to content

✨ Surface honeydiff analysis data in comparisons output#209

Merged
Robdel12 merged 4 commits intomainfrom
surface-honeydiff-analysis-data
Feb 9, 2026
Merged

✨ Surface honeydiff analysis data in comparisons output#209
Robdel12 merged 4 commits intomainfrom
surface-honeydiff-analysis-data

Conversation

@Robdel12
Copy link
Contributor

@Robdel12 Robdel12 commented Feb 9, 2026

Summary

  • Add honeydiff object to --json output for comparisons containing SSIM/GMSD scores, cluster classification/metadata, fingerprint hash, diff regions, diff lines, and fingerprint data
  • Fix URL resolution across all API response shapes — handles nested objects (single comparison endpoint), flat fields like diff_image_url/baseline_original_url (build detail), and nested diff_image (search)
  • Add urls and honeydiff to builds --build <id> --comparisons --json comparison details
  • Show classification, SSIM, GMSD, and fingerprint in --verbose single comparison display
  • Append [classification] label to comparison lines in --verbose build and search list views

Corresponds to vizzly-testing/vizzly#277 which exposes these fields from the API.

Test plan

  • node --test tests/commands/comparisons.test.js — 17/17 pass
  • node --test tests/commands/builds.test.js — 12/12 pass
  • Honeydiff fields in JSON for single comparison (top-level fields)
  • Honeydiff fields in JSON for search results (nested diff_image)
  • honeydiff: null when no analysis data present
  • URLs resolved from flat field names (baseline_screenshot_url, diff_url)
  • URLs resolved from build detail field names (baseline_original_url, diff_image_url)
  • Builds command includes URLs and honeydiff in comparisonDetails
  • Verbose display shows Classification, SSIM, GMSD, Fingerprint

Expose SSIM/GMSD scores, cluster classification, fingerprint hashes,
and diff regions from the API in both --json and --verbose output.
@vizzly-testing

This comment has been minimized.

@claude
Copy link

claude bot commented Feb 9, 2026

Code Review

This PR successfully surfaces honeydiff analysis data in the comparisons command output. The implementation is solid with comprehensive test coverage. Here are my findings:

Strengths

  1. Excellent test coverage - 163 new lines of tests covering all major scenarios including both API response shapes, null states, and verbose display
  2. Clear documentation - Inline comment at src/commands/comparisons.js:189-191 explains the dual response shape pattern well
  3. Consistent handling - Code handles both top-level and nested diff_image fields throughout
  4. Graceful degradation - Returns honeydiff: null when no data is present rather than omitting the field or returning partial data

Issues Found

1. Potential false positive in hasHoneydiff check (src/commands/comparisons.js:198)

The current logic:

let hasHoneydiff = clusterMetadata || ssimScore \!= null || gmsdScore \!= null || fingerprintHash;

Issue: If ssimScore is exactly 0, the check ssimScore \!= null evaluates to true, but then the final || fingerprintHash could short-circuit if fingerprintHash is truthy. However, the real issue is that 0 is a valid SSIM score, so this should be fine. But there's an edge case: if ALL values are falsy but ssimScore or gmsdScore is 0 (a valid score), we'd get hasHoneydiff = false due to the final || fingerprintHash evaluation.

Fix: Add explicit null check for fingerprintHash:

let hasHoneydiff = clusterMetadata || ssimScore \!= null || gmsdScore \!= null || fingerprintHash \!= null;

Wait, actually reviewing more carefully - the current code is:

let hasHoneydiff = clusterMetadata || ssimScore \!= null || gmsdScore \!= null || fingerprintHash;

This is checking if fingerprintHash is truthy (non-empty string), which is fine since hashes should never be empty strings. The nullish checks for scores are correct. This is actually fine as-is.

2. Inconsistent handling of diff_regions field (src/commands/comparisons.js:221)

diffRegions: comparison.diff_regions || diffImage.diff_regions || null,

Issue: Uses || operator which treats [] (empty array) as falsy. If comparison.diff_regions is an empty array, it will check diffImage.diff_regions instead, which is incorrect - an empty array means "no regions" not "check elsewhere".

Fix: Use nullish coalescing for consistency:

diffRegions: comparison.diff_regions ?? diffImage.diff_regions ?? null,

3. Inconsistent operator usage for diff_lines and fingerprint_data

src/commands/comparisons.js:222-223 use || operator:

diffLines: comparison.diff_lines || null,
fingerprintData: comparison.fingerprint_data || null,

Issue: Same problem as above - empty arrays would be treated as falsy. Also, these fields don't check diffImage fallback like other fields do.

Questions:

  • Should diff_lines and fingerprint_data also check nested diffImage fields for consistency?
  • Should these use ?? instead of || to properly handle empty arrays?

Minor Observations

  1. Fingerprint not shown when classification is missing (src/commands/comparisons.js:282)
    The condition if (clusterMetadata || ssim \!= null || gmsd \!= null) controls displaying the entire honeydiff section, but fingerprint is only displayed inside. If only fingerprint exists (no scores/classification), it won't be shown. This might be intentional, but worth confirming.

  2. Consistent naming - Good use of camelCase in JSON output (ssimScore, clusterClassification) vs snake_case from API

  3. toFixed(4) for scores - Good precision choice for SSIM/GMSD display

Performance & Security

  • No performance concerns - all operations are simple property access
  • No security issues - data is directly from API responses
  • No SQL injection or XSS vectors

Recommendations

  1. Fix the ?? vs || inconsistency for array fields
  2. Consider whether diff_lines and fingerprint_data should check diffImage fallback
  3. Optional: Add JSDoc comments to the new getClassificationLabel function describing what classifications might look like
  4. Consider showing fingerprint even when scores are missing (edge case)

Test Plan Verification

Based on the PR description, all tests pass:

  • ✅ Honeydiff fields in JSON for single comparison
  • ✅ Honeydiff fields in JSON for search results (nested)
  • honeydiff: null when no data present
  • ✅ Verbose display shows Classification, SSIM, GMSD, Fingerprint

The test file shows proper coverage of edge cases.

Verdict

This is a well-implemented feature with good test coverage. The main issues are minor consistency problems with || vs ?? operators that could cause bugs with edge cases (empty arrays). I'd recommend addressing the operator consistency before merging.

The code follows repository conventions from CLAUDE.md and maintains the existing architecture patterns.

Handle all API response shapes for image URLs: nested objects (single
comparison), flat fields (build detail), and diff_image (search). Add
URLs and honeydiff data to builds --comparisons --json output.
@vizzly-testing

This comment has been minimized.

@vizzly-testing

This comment has been minimized.

…rprint display

- Use ?? instead of || for diff_regions, diff_lines, fingerprint_data
  so empty arrays aren't treated as falsy
- Add diffImage fallback for diff_lines and fingerprint_data
- Show fingerprint in verbose display even when scores are missing
@vizzly-testing
Copy link

vizzly-testing bot commented Feb 9, 2026

Vizzly - Visual Test Results

CLI Reporter - 7 changes need review
Status Count
Passed 12
Changed 7
Auto-approved 12
Changes needing review (7)

filter-failed-only · Firefox · 1920×1080 · 0.1% diff

filter-failed-only

bulk-accept-dialog · Firefox · 1920×1080 · 10.4% diff

bulk-accept-dialog

viewer-slide-mode · Firefox · 1920×1080 · 0.5% diff

viewer-slide-mode

viewer-zoomed-100 · Firefox · 1920×1080 · 0.5% diff

viewer-zoomed-100

filter-failed-only · Firefox · 375×703 · 0.3% diff

filter-failed-only

fullscreen-viewer · Firefox · 375×667 · 197.9% diff

fullscreen-viewer

...and 1 more in Vizzly.

Review changes

CLI TUI - Approved

5 comparisons, no changes detected.

View build


surface-honeydiff-analysis-data · e39e8c38

@Robdel12 Robdel12 merged commit c623c0e into main Feb 9, 2026
26 of 27 checks passed
@Robdel12 Robdel12 deleted the surface-honeydiff-analysis-data branch February 9, 2026 06:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant