@acereports/vitest
v1.0.0
Published
Ace Reports for Vitest: zero-setup HTML test reports that automatically capture every API request and response, screenshots on failure, logs, retries and flaky tests.
Maintainers
Readme
Ace Reports for Vitest
Zero-setup HTML reporting for Vitest. Automatically captures every API request and response, takes a screenshot when a test fails, and tracks logs, retries and flaky tests, all in one self-contained HTML file per run. The same report as Ace Reports for .NET, Java and Python.
Website: https://harshadlambate.github.io/AceReportsWebsite/
Live demo report: https://harshadlambate.github.io/AceReportsWebsite/demo.html
Setup
npm install --save-dev @acereports/vitestTwo lines in vitest.config.ts (or vite.config.ts):
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
reporters: ['default', '@acereports/vitest'],
setupFiles: ['@acereports/vitest/setup'],
},
});Run your tests as usual (npx vitest run, watch mode, the IDE, CI) and the report is written to
TestResults/AceReport_<timestamp>.html in the project folder; the path is printed at the end of the run.
In watch mode every run writes a report of its own. To turn it off for one run: ACEREPORTS_ENABLED=false npx vitest run
(PowerShell: $env:ACEREPORTS_ENABLED='false'; npx vitest run).
Configuration
Optional. Pass options to the reporter in vitest.config.ts:
reporters: [
'default',
['@acereports/vitest', { suiteName: 'Checkout Regression', environment: 'UAT', theme: 'dark' }],
],| Option | Default | |
| --- | --- | --- |
| suiteName | the project folder's name | shown at the top of the report |
| environment | ACEREPORTS_ENVIRONMENT, else Local | DEV, QA, UAT... |
| outputPath | TestResults/AceReport_<timestamp>.html | a file, or a folder for the timestamped file |
| theme | system | light, dark or system (follows the reader's OS; the report has a toggle) |
| captureHttp | true | record API calls |
| captureConsole | true | add console.log / warn / error output to the test's log |
| screenshotOnFailure | true | take a screenshot when a browser test fails |
| maxBodyLength | 20000 | longer request and response bodies are clipped |
| enabled | true | false switches the report off |
The same settings work as environment variables, e.g. ACEREPORTS_ENVIRONMENT=QA, ACEREPORTS_OUTPUT=reports/run.html,
ACEREPORTS_THEME=dark, ACEREPORTS_ENABLED=false. Or set them from a test, anywhere before the run ends:
import { ace } from '@acereports/vitest';
ace.suiteName('Checkout Regression');
ace.environmentName('UAT');
ace.darkTheme(); // or lightTheme() / systemTheme()
ace.outputPath('reports/report.html');
ace.captureHttpTraffic(false); // API capture is on by defaultEnvironment name
Resolved in this order, first match wins: ace.environmentName('QA'), the reporter's environment option,
the ACEREPORTS_ENVIRONMENT environment variable, Local.
Logging from a test
import { ace } from '@acereports/vitest';
ace.info('Submitting payment');
ace.pass('Payment authorized');
ace.fail('Refund was accepted but should have been rejected'); // logs only; use an assertion to fail
ace.warn('Retrying the payment gateway');
ace.debug('Skipping optional 3-D Secure step');
ace.info('Order created', order); // objects are shown as indented JSON
ace.log('GIVEN', 'the cart is empty'); // any levelEach call attaches to the test that is running, so parallel workers keep their logs apart. Outside a test
the calls do nothing, so helpers shared with other code are safe to instrument. console.log, console.warn
and console.error output written during a test is added to its log too.
Screenshots
For browser tests (Playwright or Puppeteer as a library, Selenium, WebdriverIO), a screenshot is taken
automatically when a test fails. Ace Reports finds a page, context, browser or driver fixture made with
test.extend, and takes the screenshot before fixtures are torn down:
const test = base.extend<{ page: Page }>({
page: async ({}, use) => {
const browser = await chromium.launch();
await use(await browser.newPage());
await browser.close();
},
});Take your own at any point; each becomes its own tab in the report:
await ace.takeScreenshot(); // "Screenshot 1", "Screenshot 2", ...
await ace.takeScreenshot('After login'); // named tab
await ace.takeScreenshot('Cart page', pngBuffer); // an image you already have (Buffer or base64)
await ace.screenshotOf(page.locator('#cart'), 'Cart');When Ace Reports cannot find the browser by itself, tell it where it is:
ace.useScreenshotSource(page); // for this test (call it in beforeEach for every test)
ace.setScreenshotProvider(() => DriverManager.driver); // once, for driver factoriesWorks with Playwright (Page, BrowserContext, Browser, Locator), Puppeteer, Selenium WebDriver and WebdriverIO.
A page that never went anywhere (about:blank) is skipped, so an API test that fails gets no empty screenshot.
Automatic API capture
Nothing to add. Every HTTP call a test makes is recorded: method, URL, request and response bodies, status and
duration, plus connection errors. Ace Reports hooks Node's http / https modules and the global fetch, so it
sees calls from axios, fetch, got, superagent / supertest, node-fetch, ky, and from your own API
clients and vendor SDKs built on them.
Calls are shown per attempt in the API tab, JSON indented. Authorization, Proxy-Authorization, Cookie and
Set-Cookie headers are never stored. Turn capture off with captureHttp: false or ace.captureHttpTraffic(false).
What's automatic, and what needs one line
| What | Automatic | Needs one line | Not captured (yet) |
| --- | --- | --- | --- |
| API calls | axios, fetch, got, superagent / supertest, node-fetch, ky, and anything built on Node's http, https or fetch, including calls made through your own wrappers and API clients | | Clients that bypass them (HTTP/2 via the http2 module, gRPC, native add-ons). Log what matters with ace.info('Response', body) |
| Screenshots | A page / context / browser / driver fixture made with test.extend | A page kept elsewhere: ace.useScreenshotSource(page). A driver factory: ace.setScreenshotProvider(() => driver) once | |
| Retries | retry (config, --retry, or per test); every attempt kept with its own logs, error, API calls and screenshots | | |
| Logs | Errors and stack traces, console output | Your own lines: ace.info(...), ace.pass(...), ace.fail(...) | Loggers that write straight to stdout (pino, winston) |
Retries and flaky tests
Each attempt keeps its own logs, API calls, error and screenshots, shown as separate attempt tabs. A test is retried when it took more than one attempt, and flaky when it passed after an earlier attempt failed.
Retries come from retry: 2 in the config, --retry=2, or test('name', { retry: 2 }, ...).
Categories
Write tags in test or describe names: describe('Payments @smoke', ...), test('refund @api', ...); Vitest's own
test tags are used too where your Vitest version has them. A test with none is filed under "Uncategorized".
What is recorded
| Test | Report |
| --- | --- |
| test(...) / it(...) | one row, named after the test |
| test.each(...) / test.for(...) | one row per set of arguments |
| describe(...) blocks | the "Test Group" column (the file name when there is no describe) |
| a test file that fails to run | one failed row with the error |
| test.skip, test.todo | left out of the table; counted as skipped |
Parallel runs
Vitest's workers (threads or forks) end up in one report, each test with its own logs, API calls and screenshots.
Tests run with test.concurrent inside one file share the log of whichever test is running at that moment.
Requirements
Node.js 18+, Vitest 3+, tests running in Node (not Vitest's browser mode).
License
Ace Reports is free to use under the PolyForm Perimeter License 1.0.1.
Commercial terms (OEM, white-label, or a full buy-out) are available: see the website.
Found it useful? Buy me a coffee ☕
