Skip to content

visual-report-status-from-vitest - #9115

Open
yashgoyal0110 wants to merge 1 commit into
processing:mainfrom
yashgoyal0110:fix/visual-report-status-from-vitest
Open

visual-report-status-from-vitest#9115
yashgoyal0110 wants to merge 1 commit into
processing:mainfrom
yashgoyal0110:fix/visual-report-status-from-vitest

Conversation

@yashgoyal0110

@yashgoyal0110 yashgoyal0110 commented Aug 25, 2026

Copy link
Copy Markdown

fixes: #9113

Problem

visual-report.js inferred status from disk (hasExpected && hasActual && !hasDiff), so a test with no actual screenshot was indistinguishable from one that failed.

Confirmed against the tree: 322 metadata.json directories, 71 under WebGPU/ (CI runs --project=unit-tests, which excludes cases/webgpu.js), plus one { skip: true } in cases/noise.js:34. 71 + 1 + 1 real failure = the 73 reported.

Fix

The report now reads vitest's json reporter output as the source of truth, matching each result to its screenshot directory via ancestorTitles and the same /%2F escaping visualTest.js uses. Four states: passed, failed,
skipped, not run. Percentages are taken against tests run. Falls back to the old disk heuristic with a visible banner when the JSON is absent, so node visual-report.js still works locally.

Testing

Ran the full suite locally, then generated the report with both the old and new
generator against the same test-results.json and screenshots on disk:

npm test -- --project=unit-tests --reporter=default --reporter=json
--outputFile.json=./test/unit/visual/test-results.json
node visual-report.js

before after
Total tests 322 322
Passed 249 (77%) 249 (99.6% of tests run)
Failed 73 (23%) 1 (0.4% of tests run)
Skipped 1
Not run 71
Screenshot 2026-08-25 at 1 53 20 PM

The 71 "not run" are the WebGPU/ tests, excluded because CI runs
--project=unit-tests. The 1 skip is { skip: true } in cases/noise.js:34.
The 1 failure is a pre-existing local rendering diff in
Typography > textWeight > can control non-variable fonts, unrelated to this change.

Also exercised the fallback paths: missing JSON (disk heuristic + warning banner),
malformed JSON (same), and empty testResults (all tests reported as not run).

@yashgoyal0110

Copy link
Copy Markdown
Author

@Vaivaswat2244 kindly review

@Vaivaswat2244 Vaivaswat2244 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @yashgoyal0110 ! Thanks a lot for your pr. It looks great. I've left a few comments. Have a look and let me know if you have any questions or need clarification.

Comment thread visual-report.js
reportedStatus === NOT_RUN ||
reportedStatus === PASSED
) {
status = reportedStatus;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When vitest says passed, the disk is never consulted, so a stale -diff.png renders a Diff panel next to a PASS badge, and a missing actual renders the missing-image notice under one. Both reproducible locally.

Could skip rendering the diff and the missing-image notice when the status is PASSED, since neither is meaningful then. If you'd rather not hide a real disagreement, a third state that says so is fine too, but showing both without comment is the one option I'd avoid.

Comment thread visual-report.js
// Percentages only make sense against the tests that actually ran.
const executedTests = tests.passed + tests.failed;
const executedScreenshots =
screenshots.passed + screenshots.failed + screenshots.notCaptured;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notCaptured shouldn't be in this denominator, it's labelled "% of screenshots compared" below and those are the ones that were never compared.

Dropping it from executedScreenshots is enough, it's already reported on its own line.

Comment thread visual-report.js
No vitest results were found at <code>${escapeHTML(path.relative(process.cwd(), resultsFile))}</code>,
so statuses below were inferred from the screenshots on disk. Tests that
were skipped or never ran are indistinguishable from failures in this mode.
Run the tests with <code>--reporter=json --outputFile.json=test/unit/visual/test-results.json</code>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the reporter moves into config, this should just say to re-run npm test, since there'd be no flags for a contributor to pass.

id: test
if: matrix.os == 'ubuntu-latest'
run: npm test -- --project=unit-tests
run: npm test -- --project=unit-tests --reporter=default --reporter=json --outputFile.json=./test/unit/visual/test-results.json

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should go in the Vitest config, since a regular contributor won't add this many flags just to generate a report, especially given that most of our contributors are students.
That's on me, the command in the issue was a CLI example and it reads like it belongs in the workflow. Config is the better home for it.

Can you check once again if that works?

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.

visual-test-report artifact showing more failures than it should

2 participants