Vitest’s HTML reporter is excellent — interactive, fast, and genuinely useful for debugging. But it generates local files. When your teammate asks “what failed?”, you can’t just send them a link. You end up screenshotting terminal output or walking them through downloading CI artifacts.
The Sharing Problem
After vitest run, your HTML report lands in a local directory. To share it with your team, you need to get that file to them somehow. Here’s what most teams do:
Common (Bad) Solutions
1. CI artifacts
- GitHub Actions keeps artifacts for 90 days max, other CI systems are shorter
- Finding the right artifact means clicking through workflow runs
- Recipient downloads a zip, extracts it, opens
index.htmllocally - QA might not even have CI access
2. Email or Slack the file
- “Here’s the test report” with a zip attachment
- Recipient has to download, extract, open in browser
- Version confusion when multiple runs are in flight
3. Upload to S3 manually
- Works, but someone has to set up the bucket, permissions, and cleanup
- Manual step every time — gets skipped when things are busy
4. Paste terminal output
- Loses all the interactive HTML goodness
- Hard to parse in a Slack thread
- Can’t reference it later
Better: Hosted Vitest Reports with Shareable Links
The fix is straightforward: upload your Vitest reports to a hosting service after every CI run. Every test run gets a permanent URL that anyone on your team can open.
What This Looks Like
- CI runs your Vitest tests
- Reports upload automatically
- You get a URL like
https://app.gaffer.sh/reports/abc123 - Share it in Slack, GitHub PRs, Jira — anywhere
- Anyone with access sees the full interactive report
No downloads. No manual steps. No expiring artifacts.
Setting Up Vitest Report Sharing with Gaffer
Step 1: Configure Vitest Reporters
Make sure you’re generating output Gaffer can parse. CTRF gives the richest analytics:
npm install vitest-ctrf-json-reporter --save-dev// vitest.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
reporters: ['default', 'vitest-ctrf-json-reporter'],
}
})Gaffer also accepts Vitest’s built-in HTML and JSON reporters if you prefer those.
Step 2: Add the Upload Step to CI
GitHub Actions:
- name: Run tests
run: npm test
- name: Upload to Gaffer
if: always()
uses: gaffer-sh/gaffer-uploader@v1
with:
gaffer_api_key: ${{ secrets.GAFFER_UPLOAD_TOKEN }}
report_path: ./test-results
commit_sha: ${{ github.sha }}
branch: ${{ github.ref_name }}GitLab CI:
test:
script:
- npm ci
- npm test
after_script:
- |
curl -X POST https://app.gaffer.sh/api/upload \
-H "X-API-Key: $GAFFER_UPLOAD_TOKEN" \
-F "[email protected]" \
-F 'tags={"commitSha":"'"$CI_COMMIT_SHA"'","branch":"'"$CI_COMMIT_REF_NAME"'"}'Step 3: Share the Link
After upload, Gaffer returns a URL. Share it anywhere — Slack, GitHub PR comments, Jira tickets. Recipients see the full report in their browser.
Slack and Webhook Notifications
Instead of checking CI manually, get notified when tests finish:
Slack integration:
- Pass/fail summary posted to your channel
- Direct link to the full report
- Filter by branch — only notify on
main, skip feature branches
Webhooks:
- Send test results to any endpoint
- Integrate with your existing alerting or workflow tools
- Trigger custom actions on failure
No more “did the tests pass?” messages. Your team sees failures as they happen, with a link to investigate.
GitHub Integration
Commit statuses show test results directly on PRs. No clicking through to CI logs — you see pass/fail right on the commit.
What About Flaky Tests?
Vitest’s --retry flag handles flaky tests within a single run. Gaffer tracks flakiness across runs — identifying tests that sometimes pass and sometimes fail over time. Different problem, complementary solution.
Get Started
Gaffer’s free tier includes 500 MB of storage with 7-day retention. Paid plans offer extended retention up to 90 days.