Skip to content

Writing report files ​

EasyTrace reads the report files your test runner writes. Put them under .easytrace/ (and add .easytrace/ to .gitignore), then list them in easytrace.config.json.

Vitest ​

Add the JSON reporter on the command line, keeping the default one for the terminal:

bash
vitest run --reporter=default --reporter=json --outputFile.json=.easytrace/vitest.json

Or in vitest.config.ts:

ts
export default defineConfig({
  test: {
    reporters: ['default', 'json'],
    outputFile: { json: '.easytrace/vitest.json' },
  },
});

Add --coverage to upload coverage as well (Coverage). Vitest 2 and 3 are both supported. The JSON report records how many times a test was retried, but not the errors of intermediate attempts.

Jest ​

bash
jest --json --outputFile=.easytrace/jest.json

Retries appear as failed attempts with Jest 29 or later (retryReasons). Jest doesn't put console output in its JSON report.

Playwright ​

Add the json reporter next to the ones you already use, in playwright.config.ts:

ts
export default defineConfig({
  reporter: [['list'], ['json', { outputFile: '.easytrace/playwright.json' }]],
  use: { trace: 'on-first-retry', screenshot: 'only-on-failure' },
});

Playwright reports carry every attempt, steps, stdout/stderr and attachments. To upload screenshots, videos and traces, list the output folder as the suite's attachments (usually test-results).

Cypress ​

Use the mochawesome reporter with JSON output, one file per spec:

bash
cypress run --reporter mochawesome --reporter-options "reportDir=.easytrace/cypress,json=true,html=false,overwrite=false"

List .easytrace/cypress/*.json as the suite's reports; all files of a suite form one run. Screenshots are matched by test name from the suite's attachments folder (e.g. cypress/screenshots).

JUnit XML ​

Any tool that writes JUnit XML works (--format junit is detected automatically). Retries are only visible with <flakyFailure> / <rerunFailure> elements (Maven Surefire style). Files referenced as [[ATTACHMENT|path]] in <system-out> are uploaded as attachments.

Monorepos ​

In a monorepo each package writes its own report into its own folder, and easytrace.config.json at the root picks them up with globs — one suite per package, or one suite for several:

json
{
  "suites": {
    "server": {
      "reports": "apps/server/.easytrace/vitest.json",
      "coverage": "apps/server/coverage/coverage-final.json"
    },
    "packages": { "reports": "packages/*/.easytrace/vitest.json" }
  }
}

Turborepo: no per-package scripts ​

With turbo you don't need to touch the packages. turbo run test -- <flags> appends the flags to every package's own test script (vitest run …), so one script at the root makes every package write its report:

json
{
  "scripts": {
    "test:json": "turbo run test --continue --force -- --coverage --reporter=default --reporter=json --outputFile.json=.easytrace/vitest.json",
    "test:report": "easytrace run -- pnpm test:json",
    "test:report:all": "easytrace run -- sh -c 'pnpm test:json; unit=$?; playwright test && exit $unit'"
  }
}
PartWhy
--continueA failing package doesn't stop the others, so every suite has a report.
--forceTurbo must really run the tests. A cache hit replays the output but doesn't rewrite the report file, and easytrace run skips report files older than the run.
-- …Everything after -- is appended to each package's vitest run.
--coverageEvery package computes coverage; only suites that declare coverage upload it. Packages without @vitest/coverage-v8 need it installed at the root: pnpm add -Dw @vitest/coverage-v8@<your vitest major>.

test:report:all runs Vitest then Playwright in one build: it fails if either failed, and uploads every suite once both are done.

Don't pass turbo options after the script

pnpm test:json --filter=web appends --filter=web after the --, so Vitest receives it instead of turbo. Filter with pnpm exec turbo run test --filter=web -- … instead.