### Example Vitest Setup File Source: https://main.vitest.dev/config/setupfiles This example demonstrates how to use a setup file to initialize a testing library's configuration and perform a heavy computation only once. It also includes an `afterEach` hook for cleanup and a global variable to track initialization. ```typescript import { config } from '@some-testing-lib' if (!globalThis.setupInitialized) { config.plugins = [myCoolPlugin] computeHeavyThing() globalThis.setupInitialized = true } // hooks reset before each test file afterEach(() => { cleanup() }) globalThis.resetBeforeEachTest = true ``` -------------------------------- ### Setup File with AfterEach Hook Source: https://main.vitest.dev/guide/lifecycle Execute setup files before each test file to initialize global state or register hooks. This example registers an `afterEach` hook for cleanup. ```typescript import { afterEach } from 'vitest' // Runs before each test file console.log('Setup file executing') // Register hooks that apply to all tests afterEach(() => { cleanup() }) ``` -------------------------------- ### Complex Fixture Setup and Cleanup Source: https://main.vitest.dev/guide/test-context This example shows how to set up and clean up more complex fixtures, such as a database connection and test user, using `onCleanup` for both file-scoped and test-scoped fixtures. ```typescript const test = baseTest .extend('database', { scope: 'file' }, async ({}, { onCleanup }) => { const db = await createDatabase() await db.connect() onCleanup(async () => { await db.disconnect() }) return db }) .extend('user', async ({ database }, { onCleanup }) => { const user = await database.createTestUser() onCleanup(async () => { await database.deleteUser(user.id) }) return user }) ``` -------------------------------- ### Start Vitest Programmatically Source: https://main.vitest.dev/guide/advanced/tests Use `startVitest` to initiate Vitest, validate installations, and run tests immediately. It returns a Vitest instance for further interaction. ```typescript import { startVitest } from 'vitest/node' const vitest = await startVitest( 'test', [], // CLI filters {}, {}, {}, ) const testModules = vitest.state.getTestModules() for (const testModule of testModules) { console.log(testModule.moduleId, testModule.ok() ? 'passed' : 'failed') } ``` -------------------------------- ### Global Setup with Named Exports Source: https://main.vitest.dev/config/globalsetup Use named `setup` and `teardown` functions for global setup and cleanup. The `setup` function receives the test project. ```js export function setup(project) { console.log('setup') } export function teardown() { console.log('teardown') } ``` -------------------------------- ### Manual Installation of Preview Provider with bun Source: https://main.vitest.dev/guide/browser Install Vitest and the browser preview provider manually using bun. ```bash bun add -D vitest @vitest/browser-preview ``` -------------------------------- ### Manual Installation of Preview Provider with yarn Source: https://main.vitest.dev/guide/browser Install Vitest and the browser preview provider manually using yarn. ```bash yarn add -D vitest @vitest/browser-preview ``` -------------------------------- ### Manual Installation of Preview Provider with npm Source: https://main.vitest.dev/guide/browser Install Vitest and the browser preview provider manually using npm. ```bash npm install -D vitest @vitest/browser-preview ``` -------------------------------- ### Manual Installation of Preview Provider with pnpm Source: https://main.vitest.dev/guide/browser Install Vitest and the browser preview provider manually using pnpm. ```bash pnpm add -D vitest @vitest/browser-preview ``` -------------------------------- ### Global Setup with Default Export Source: https://main.vitest.dev/config/globalsetup Export a default function that returns a teardown function for global setup and cleanup. The setup function receives the test project. ```js export default function setup(project) { console.log('setup') return function teardown() { console.log('teardown') } } ``` -------------------------------- ### One-Time Setup with beforeAll/afterAll Source: https://main.vitest.dev/guide/learn/setup-teardown Employ `beforeAll` for expensive, one-time setup (e.g., database connection) before any tests run, and `afterAll` for cleanup after all tests in the file have completed. ```javascript import { afterAll, beforeAll, expect, test } from 'vitest' let db beforeAll(async () => { db = await connectToDatabase() }) afterAll(async () => { await db.close() }) test('can query users', async () => { const users = await db.query('SELECT * FROM users') expect(users.length).toBeGreaterThan(0) }) test('can query products', async () => { const products = await db.query('SELECT * FROM products') expect(products.length).toBeGreaterThan(0) }) ``` -------------------------------- ### Install Vitest with bun Source: https://main.vitest.dev/guide Install Vitest as a development dependency using bun. ```bash bun add -D vitest ``` -------------------------------- ### Plugin Implementation Examples Source: https://main.vitest.dev/api/advanced/plugin Examples demonstrating how to implement a Vitest plugin, showing variations for Vitest-only and Vite+Vitest compatible plugins. ```APIDOC ::: code-group ```ts [only vitest] import type { Vite, VitestPluginContext } from 'vitest/node' export function plugin(): Vite.Plugin { return { name: 'vitest:my-plugin', configureVitest(context: VitestPluginContext) { // ... } } } ``` ```ts [vite and vitest] /// import type { Plugin } from 'vite' export function plugin(): Plugin { return { name: 'vitest:my-plugin', transform() { // ... }, configureVitest(context) { // ... } } } ``` ::: ``` -------------------------------- ### Example DOM structure Source: https://main.vitest.dev/api/browser/locators This is an example HTML structure used to demonstrate `getByRole` functionality. ```html

Sign up


``` -------------------------------- ### OpenTelemetry SDK Configuration (otel.js) Source: https://main.vitest.dev/config/experimental Example of an OpenTelemetry SDK file that exposes a started SDK instance as a default export. This file is imported by Vitest when `sdkPath` is configured. ```javascript import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node' import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto' import { NodeSDK } from '@opentelemetry/sdk-node' const sdk = new NodeSDK({ serviceName: 'vitest', traceExporter: new OTLPTraceExporter(), instrumentations: [getNodeAutoInstrumentations()], }) sdk.start() export default sdk ``` -------------------------------- ### Install Vitest with pnpm Source: https://main.vitest.dev/guide Install Vitest as a development dependency using pnpm. ```bash pnpm add -D vitest ``` -------------------------------- ### Install Istanbul Coverage Package Source: https://main.vitest.dev/guide/coverage Install the Istanbul coverage support package using npm. ```bash npm i -D @vitest/coverage-istanbul ``` -------------------------------- ### Install Vitest UI Source: https://main.vitest.dev/guide/ui Install the Vitest UI package as a development dependency. ```bash npm i -D @vitest/ui ``` -------------------------------- ### Install Playwright Provider with bun Source: https://main.vitest.dev/guide/browser Install Vitest and the Playwright browser provider using bun. Recommended for CI and faster local testing. ```bash bun add -D vitest @vitest/browser-playwright ``` -------------------------------- ### Install Vitest with npm Source: https://main.vitest.dev/guide Install Vitest as a development dependency using npm. ```bash npm install -D vitest ``` -------------------------------- ### sequence.setupFiles Configuration Source: https://main.vitest.dev/config/sequence Configure the order in which setup files are executed. Options include running them in a list (sequential) or in parallel. ```APIDOC ## sequence.setupFiles ### Description Changes the order in which setup files are executed. * `list` will run setup files in the order they are defined * `parallel` will run setup files in parallel ### Type `'list' | 'parallel'` ### Default `'parallel'` ### CLI `--sequence.setupFiles=` ``` -------------------------------- ### Install Vitest with yarn Source: https://main.vitest.dev/guide Install Vitest as a development dependency using yarn. ```bash yarn add -D vitest ``` -------------------------------- ### Custom Matcher Setup with Domain Adapters Source: https://main.vitest.dev/guide/snapshot Register custom snapshot matchers using `expect.extend` and Vitest's snapshot composables. This example shows how to set up matchers for both file-based and inline snapshots with a custom adapter. ```typescript import { expect, Snaphsots } from 'vitest' expect.extend({ toMatchMyDomainSnapshot(received: unknown) { return Snaphsots.toMatchDomainSnapshot.call(this, myAdapter, received) }, toMatchMyDomainInlineSnapshot(received: unknown, inlineSnapshot?: string) { return Snaphsots.toMatchDomainInlineSnapshot.call( this, myAdapter, received, inlineSnapshot, ) }, }) ``` ```typescript expect(value).toMatchMyDomainSnapshot() expect(value).toMatchMyDomainInlineSnapshot(`key=value`) ``` -------------------------------- ### Configure Setup Files in Vitest Source: https://main.vitest.dev/guide/learn/setup-teardown Specify setup files in `vitest.config.js` to run code before every test file. This is ideal for global configurations, polyfills, or custom matchers. ```javascript import { defineConfig } from 'vitest/config' export default defineConfig({ test: { setupFiles: ['./test/setup.js'], }, }) ``` -------------------------------- ### Install V8 Coverage Package Source: https://main.vitest.dev/guide/coverage Install the V8 coverage support package using npm. ```bash npm i -D @vitest/coverage-v8 ``` -------------------------------- ### Comprehensive Test Tag Configuration Example Source: https://main.vitest.dev/config/tags An example demonstrating various tag configurations including name, description, timeout, retry, priority, and skip options. Note that `retry.condition` must be a regexp. ```typescript import { defineConfig } from 'vitest/config' export default defineConfig({ test: { tags: [ { name: 'unit', description: 'Unit tests.', }, { name: 'e2e', description: 'End-to-end tests.', timeout: 60_000, }, { name: 'flaky', description: 'Flaky tests that need retries.', retry: process.env.CI ? 3 : 0, priority: 1, }, { name: 'slow', description: 'Slow tests.', timeout: 120_000, }, { name: 'skip-ci', description: 'Tests to skip in CI.', skip: !!process.env.CI, }, ], }, }) ``` -------------------------------- ### Install WebdriverIO Provider with bun Source: https://main.vitest.dev/guide/browser Install Vitest and the WebdriverIO browser provider using bun. Allows running tests locally using the WebDriver protocol. ```bash bun add -D vitest @vitest/browser-webdriverio ``` -------------------------------- ### Install Playwright Provider with yarn Source: https://main.vitest.dev/guide/browser Install Vitest and the Playwright browser provider using yarn. Recommended for CI and faster local testing. ```bash yarn add -D vitest @vitest/browser-playwright ``` -------------------------------- ### Install Playwright Provider with pnpm Source: https://main.vitest.dev/guide/browser Install Vitest and the Playwright browser provider using pnpm. Recommended for CI and faster local testing. ```bash pnpm add -D vitest @vitest/browser-playwright ``` -------------------------------- ### Install OpenTelemetry Packages Source: https://main.vitest.dev/guide/open-telemetry Install the necessary OpenTelemetry packages for Node.js tracing. These include the SDK, auto-instrumentations, and an exporter. ```shell npm i @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-trace-otlp-proto ``` -------------------------------- ### Istanbul Coverage Instrumentation Example Source: https://main.vitest.dev/guide/coverage Illustrates how Istanbul instruments JavaScript files by adding counters for branches and functions. This is a simplified example. ```js // Simplified example of branch and function coverage counters const coverage = { // [!code ++] branches: { 1: [0, 0] }, // [!code ++] functions: { 1: 0 }, // [!code ++] } // [!code ++] export function getUsername(id) { // Function coverage increased when this is invoked // [!code ++] coverage.functions['1']++ // [!code ++] if (id == null) { // Branch coverage increased when this is invoked // [!code ++] coverage.branches['1'][0]++ // [!code ++] throw new Error('User ID is required') } // Implicit else coverage increased when if-statement condition not met // [!code ++] coverage.branches['1'][1]++ // [!code ++] return database.getUser(id) } globalThis.__VITEST_COVERAGE__ ||= {} globalThis.__VITEST_COVERAGE__[filename] = coverage ``` -------------------------------- ### Global Setup and Teardown Hooks Source: https://main.vitest.dev/guide/lifecycle Define global setup and teardown functions that run once before and after all tests. Use `project.provide` to share data with tests. ```typescript export function setup(project) { // Runs once before all tests console.log('Global setup') // Share data with tests project.provide('apiUrl', 'http://localhost:3000') } export function teardown() { // Runs once after all tests console.log('Global teardown') } ``` -------------------------------- ### Install WebdriverIO Provider with npm Source: https://main.vitest.dev/guide/browser Install Vitest and the WebdriverIO browser provider using npm. Allows running tests locally using the WebDriver protocol. ```bash npm install -D vitest @vitest/browser-webdriverio ``` -------------------------------- ### Run Vitest with UI Source: https://main.vitest.dev/guide/ui Start Vitest with the --ui flag to launch the interactive UI. ```bash vitest --ui ``` -------------------------------- ### Install Playwright Provider with npm Source: https://main.vitest.dev/guide/browser Install Vitest and the Playwright browser provider using npm. Recommended for CI and faster local testing. ```bash npm install -D vitest @vitest/browser-playwright ``` -------------------------------- ### Custom Runner Example Source: https://main.vitest.dev/api/advanced/runner Example implementation of a custom Vitest runner class, demonstrating how to extend the base `TestRunner` and implement specific methods like `onAfterRunFiles`. ```APIDOC ## Custom Runner Example ### Description This example shows how to create a custom runner by extending `TestRunner` and implementing the `VitestTestRunner` interface. It demonstrates initializing the `config` property and overriding lifecycle methods. ### Class ```ts import type { RunnerTestFile, SerializedConfig, TestRunner, VitestTestRunner } from 'vitest' class CustomRunner extends TestRunner implements VitestTestRunner { public config: SerializedConfig constructor(config: SerializedConfig) { this.config = config } onAfterRunFiles(files: RunnerTestFile[]) { console.log('finished running', files) } } export default CustomRunner ``` ### Usage To use a custom runner, specify its path in the Vitest configuration file using the `runner` option. ``` -------------------------------- ### Install Browser OpenTelemetry Packages Source: https://main.vitest.dev/guide/open-telemetry Install the necessary OpenTelemetry packages for browser tracing. This includes the web trace provider and an exporter. ```shell npm i @opentelemetry/sdk-trace-web @opentelemetry/exporter-trace-otlp-proto ``` -------------------------------- ### Render Hook Example Source: https://main.vitest.dev/api/browser/react A basic example of rendering a custom hook using `renderHook`. It asserts the initial state returned by the hook. ```jsx import { renderHook } from 'vitest-browser-react' test('returns logged in user', async () => { const { result } = await renderHook(() => useLoggedInUser()) expect(result.current).toEqual({ name: 'Alice' }) }) ``` -------------------------------- ### Install WebdriverIO Provider with yarn Source: https://main.vitest.dev/guide/browser Install Vitest and the WebdriverIO browser provider using yarn. Allows running tests locally using the WebDriver protocol. ```bash yarn add -D vitest @vitest/browser-webdriverio ``` -------------------------------- ### Configure Different Browser Setups with Custom Options Source: https://main.vitest.dev/guide/browser/multiple-setups Define distinct configurations for browser instances, including custom setup files and injected values using the `provide` field. This allows for varied test environments within the same browser. ```typescript import { defineConfig } from 'vitest/config' import { playwright } from '@vitest/browser-playwright' export default defineConfig({ test: { browser: { enabled: true, provider: playwright(), headless: true, instances: [ { browser: 'chromium', name: 'chromium-1', setupFiles: ['./ratio-setup.ts'], provide: { ratio: 1, }, }, { browser: 'chromium', name: 'chromium-2', provide: { ratio: 2, }, }, ], }, }, }) ``` ```typescript import { expect, inject, test } from 'vitest' import { globalSetupModifier } from './example.js' test('ratio works', () => { expect(inject('ratio') * globalSetupModifier).toBe(14) }) ``` -------------------------------- ### Install WebdriverIO Provider with pnpm Source: https://main.vitest.dev/guide/browser Install Vitest and the WebdriverIO browser provider using pnpm. Allows running tests locally using the WebDriver protocol. ```bash pnpm add -D vitest @vitest/browser-webdriverio ``` -------------------------------- ### Install DOM Mocking Environment Source: https://main.vitest.dev/guide/features Install happy-dom or jsdom to mock browser DOM and APIs. Choose the environment that best suits your project's needs. ```bash $ npm i -D happy-dom ``` ```bash $ npm i -D jsdom ``` -------------------------------- ### Conditionally Run Setup Logic with Tags Source: https://main.vitest.dev/guide/test-tags Use `TestRunner.matchesTags` within `beforeAll` to execute setup logic only when tests matching specific tags are included by the `--tags-filter` CLI option. This helps avoid running expensive operations unnecessarily. ```typescript import { beforeAll, TestRunner } from 'vitest' beforeAll(async () => { // Seed database when "vitest --tags-filter db" is used if (TestRunner.matchesTags(['db'])) { await seedDatabase() } }) ``` -------------------------------- ### Extend Expect API in Setup File Source: https://main.vitest.dev/guide/learn/setup-teardown Import and extend Vitest's `expect` object within a setup file to add custom matchers globally for all tests. ```javascript // This runs before every test file import { expect } from 'vitest' import { customMatchers } from './custom-matchers.js' expect.extend(customMatchers) ``` -------------------------------- ### Setup HTTP Request Mocking with MSW Source: https://main.vitest.dev/guide/mocking/requests Configure Mock Service Worker to intercept and mock HTTP GET requests. Ensure the server is started before all tests, closed after all tests, and handlers are reset after each test for isolation. Use `onUnhandledRequest: 'error'` to catch unhandled requests. ```javascript import { afterAll, afterEach, beforeAll } from 'vitest' import { setupServer } from 'msw/node' import { http, HttpResponse } from 'msw' const posts = [ { userId: 1, id: 1, title: 'first post title', body: 'first post body', }, // ... ] export const restHandlers = [ http.get('https://rest-endpoint.example/path/to/posts', () => { return HttpResponse.json(posts) }), ] const server = setupServer(...restHandlers) // Start server before all tests beforeAll(() => server.listen({ onUnhandledRequest: 'error' })) // Close server after all tests afterAll(() => server.close()) // Reset handlers after each test for test isolation afterEach(() => server.resetHandlers()) ``` -------------------------------- ### createVitest API Source: https://main.vitest.dev/guide/advanced Creates a Vitest instance without starting tests or validating installed packages. It returns the same `Vitest` instance as `startVitest`. ```APIDOC ## createVitest ### Description Creates a Vitest instance. It returns the same `Vitest` instance as `startVitest`, but it does not start tests and does not validate installed packages. ### Method `createVitest(mode: VitestRunMode, options: CliOptions, viteOverrides: ViteUserConfig = {}, vitestOptions: VitestOptions = {}): Promise` ### Parameters - **mode** (VitestRunMode) - Required - The mode to create Vitest in (e.g., 'test'). - **options** (CliOptions) - Required - CLI arguments. - **viteOverrides** (ViteUserConfig) - Optional - Complete Vite config, which takes precedence over other user-defined options. - **vitestOptions** (VitestOptions) - Optional - Vitest specific options. ### Request Example ```js import { createVitest } from 'vitest/node' const vitest = await createVitest('test', { watch: false, }) ``` ``` -------------------------------- ### Setup GraphQL Request Mocking with MSW Source: https://main.vitest.dev/guide/mocking/requests Configure Mock Service Worker to intercept and mock GraphQL queries. This setup includes starting the server, closing it after tests, and resetting handlers between tests. The `onUnhandledRequest: 'error'` option is used for error handling. ```javascript import { afterAll, afterEach, beforeAll } from 'vitest' import { setupServer } from 'msw/node' import { graphql, HttpResponse } from 'msw' const posts = [ { userId: 1, id: 1, title: 'first post title', body: 'first post body', }, // ... ] const graphqlHandlers = [ graphql.query('ListPosts', () => { return HttpResponse.json({ data: { posts }, }) }), ] const server = setupServer(...graphqlHandlers) // Start server before all tests beforeAll(() => server.listen({ onUnhandledRequest: 'error' })) // Close server after all tests afterAll(() => server.close()) // Reset handlers after each test for test isolation afterEach(() => server.resetHandlers()) ``` -------------------------------- ### Logging Console Output During Collection Source: https://main.vitest.dev/api/advanced/test-suite Example showing console logs generated during test suite definition and setup phases, which are captured by the API. ```typescript describe('suite', () => { console.log('included') // [!code highlight] beforeAll(() => { console.log('included') // [!code highlight] }) test('test', () => { console.log('not included') // [!code error] }) }) ``` -------------------------------- ### Playwright server Docker Compose configuration Source: https://main.vitest.dev/config/browser/playwright Example Docker Compose configuration to start a Playwright server. Ensure the image and command are correctly set for your needs. ```yaml services: playwright: image: mcr.microsoft.com/playwright:v1.58.1-noble command: /bin/sh -c "npx -y playwright@1.58.1 run-server --port 6677 --host 0.0.0.0" init: true ipc: host user: pwuser ports: - '6677:6677' ``` -------------------------------- ### Render Qwik Component with Vitest Browser Source: https://main.vitest.dev/guide/browser Example of rendering a Qwik component using `vitest-browser-qwik` and performing interactions. ```tsx import { render } from 'vitest-browser-qwik' import Greeting from './greeting' test('greeting appears on click', async () => { // renderSSR and renderHook are also available const screen = render() const button = screen.getByRole('button') await button.click() const greeting = screen.getByText(/hello world/iu) await expect.element(greeting).toBeInTheDocument() }) ``` -------------------------------- ### Setup userEvent Instance Source: https://main.vitest.dev/api/browser/interactivity Use `userEvent.setup()` to create a new instance if you need to manage keyboard state across multiple interactions. The default instance is created once. ```typescript function setup(): UserEvent ``` -------------------------------- ### User Event Setup Source: https://main.vitest.dev/api/browser/interactivity The `userEvent.setup()` function creates a new user event instance. This is particularly useful for maintaining keyboard state across multiple interactions, ensuring correct behavior for key presses and releases. ```APIDOC ## userEvent.setup ### Description Creates a new user event instance. This is useful if you need to keep the state of keyboard to press and release buttons correctly. ### Method `function setup(): UserEvent` ### Notes - Unlike `@testing-library/user-event`, the default `userEvent` instance from `vitest/browser` is created once. - With `playwright` and `webdriverio` providers, interactions can persist between tests. Vitest resets keyboard state automatically before each test, but pointer state is not reset. - To ensure a neutral hover state, use `userEvent.unhover(document.body)` in a `beforeEach` hook. ``` -------------------------------- ### GitHub Actions Workflow for Updating Screenshots Source: https://main.vitest.dev/guide/browser/visual-regression-testing This workflow is designed to be manually triggered. It runs on feature branches, prevents concurrent runs, and commits updated screenshots with co-authorship credit. It includes steps for checkout, Git configuration, Node.js setup, dependency installation, Playwright browser installation, running the visual regression test, checking for changes, committing, pushing, and generating a summary. ```yaml name: Update Visual Regression Screenshots on: workflow_dispatch: # manual trigger only env: AUTHOR_NAME: 'github-actions[bot]' AUTHOR_EMAIL: '41898282+github-actions[bot]@users.noreply.github.com' COMMIT_MESSAGE: | test: update visual regression screenshots Co-authored-by: ${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com> jobs: update-screenshots: runs-on: ubuntu-24.04 # safety first: don't run on main if: github.ref_name != github.event.repository.default_branch # one at a time per branch concurrency: group: visual-regression-screenshots@${{ github.ref_name }} cancel-in-progress: true permissions: contents: write # needs to push changes steps: - name: Checkout selected branch uses: actions/checkout@v4 with: ref: ${{ github.ref_name }} # use PAT if triggering other workflows # token: ${{ secrets.GITHUB_TOKEN }} - name: Configure Git run: | git config --global user.name "${{ env.AUTHOR_NAME }}" git config --global user.email "${{ env.AUTHOR_EMAIL }}" # your setup steps here (node, pnpm, whatever) - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 24 - name: Install dependencies run: npm ci - name: Install Playwright Browsers run: npx --no playwright install --with-deps --only-shell # the magic happens below đŸĒ„ - name: Update Visual Regression Screenshots run: npm run test:visual --update # check what changed - name: Check for changes id: check_changes run: | CHANGED_FILES=$(git status --porcelain | awk '{print $2}') if [ "${CHANGED_FILES:+x}" ]; then echo "changes=true" >> $GITHUB_OUTPUT echo "Changes detected" # save the list for the summary echo "changed_files<> $GITHUB_OUTPUT echo "$CHANGED_FILES" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT echo "changed_count=$(echo "$CHANGED_FILES" | wc -l)" >> $GITHUB_OUTPUT else echo "changes=false" >> $GITHUB_OUTPUT echo "No changes detected" fi # commit if there are changes - name: Commit changes if: steps.check_changes.outputs.changes == 'true' run: | git add -A git commit -m "${{ env.COMMIT_MESSAGE }}" - name: Push changes if: steps.check_changes.outputs.changes == 'true' run: git push origin ${{ github.ref_name }} # pretty summary for humans - name: Summary run: | if [[ "${{ steps.check_changes.outputs.changes }}" == "true" ]]; then echo "### 📸 Visual Regression Screenshots Updated" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "Successfully updated **${{ steps.check_changes.outputs.changed_count }}** screenshot(s) on `${{ github.ref_name }} `" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "#### Changed Files:" >> $GITHUB_STEP_SUMMARY echo " ``` " >> $GITHUB_STEP_SUMMARY echo "${{ steps.check_changes.outputs.changed_files }}" >> $GITHUB_STEP_SUMMARY echo " ``` " >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "✅ The updated screenshots have been committed and pushed. Your visual regression baseline is now up to date!" >> $GITHUB_STEP_SUMMARY else echo "### â„šī¸ No Screenshot Updates Required" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "The visual regression test command ran successfully but no screenshots needed updating." >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "All screenshots are already up to date! 🎉" >> $GITHUB_STEP_SUMMARY fi ``` -------------------------------- ### start Source: https://main.vitest.dev/api/advanced/vitest Initializes reporters, the coverage provider, and runs tests. Accepts string filters for matching test files. ```APIDOC ## start ### Description Initializes reporters, the coverage provider, and runs tests. This method accepts string filters to match the test files. ### Method ```ts function start(filters?: string[]): Promise ``` ### Parameters #### Query Parameters - **filters** (string[]) - Optional - Filters to match the test files. ``` -------------------------------- ### Initialize Vitest Browser Mode with npm Source: https://main.vitest.dev/guide/browser Use this command to install necessary dependencies and set up browser configuration for Vitest. ```bash npx vitest init browser ``` -------------------------------- ### Initialize Vitest Browser Mode with bun Source: https://main.vitest.dev/guide/browser Use this command to install necessary dependencies and set up browser configuration for Vitest. ```bash bunx vitest init browser ``` -------------------------------- ### Implement Vitest Reporter with onInit and onTestRunStart Source: https://main.vitest.dev/api/advanced/reporters Demonstrates implementing a custom Vitest reporter by storing the Vitest instance in onInit and logging the number of test files in onTestRunStart. Requires importing necessary types from 'vitest/node'. ```typescript import type { Reporter, TestSpecification, Vitest } from 'vitest/node' class MyReporter implements Reporter { private vitest!: Vitest onInit(vitest: Vitest) { this.vitest = vitest } onTestRunStart(specifications: TestSpecification[]) { console.log( specifications.length, 'test files will run in', this.vitest.config.root, ) } } export default new MyReporter() ``` -------------------------------- ### Initialize Vitest Browser Mode with pnpm Source: https://main.vitest.dev/guide/browser Use this command to install necessary dependencies and set up browser configuration for Vitest. ```bash pnpx vitest init browser ``` -------------------------------- ### Initialize Vitest Browser Mode with yarn Source: https://main.vitest.dev/guide/browser Use this command to install necessary dependencies and set up browser configuration for Vitest. ```bash yarn exec vitest init browser ``` -------------------------------- ### Setup Chrome for WebdriverIO in CI Source: https://main.vitest.dev/guide/browser/visual-regression-testing This YAML snippet demonstrates setting up Chrome using the browser-actions/setup-chrome action for WebdriverIO tests in a CI environment. ```yaml # ...the rest of the workflow - uses: browser-actions/setup-chrome@v1 with: chrome-version: 120 ``` -------------------------------- ### GitHub Actions Example for Vitest Sharding Source: https://main.vitest.dev/guide/improving-performance This GitHub Actions workflow demonstrates how to set up test sharding across different operating systems and shard indices. It includes steps for checking out code, setting up Node.js and pnpm, running tests with sharding, uploading artifacts, and merging reports. ```yaml name: Tests on: push: branches: - main jobs: tests: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest] shardIndex: [1, 2, 3, 4] shardTotal: [4] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 24 - name: Install pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Install dependencies run: pnpm i - name: Run tests run: pnpm run test --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} env: VITEST_BLOB_LABEL: ${{ matrix.os }} - name: Upload Vitest results GitHub Actions Artifacts if: ${{ !cancelled() }} uses: actions/upload-artifact@v4 with: name: vitest-results-${{ matrix.os }}-${{ matrix.shardIndex }} path: .vitest include-hidden-files: true retention-days: 1 merge-reports: if: ${{ !cancelled() }} needs: [tests] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 24 - name: Install pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Install dependencies run: pnpm i - name: Download Vitest results from GitHub Actions Artifacts uses: actions/download-artifact@v4 with: path: .vitest merge-multiple: true - name: Merge reports run: npx vitest --merge-reports ``` -------------------------------- ### Rendering Marko Components with @marko/testing-library Source: https://main.vitest.dev/guide/browser Example of rendering a Marko component using the `@marko/testing-library` package. It shows how to pass props and assert the rendered output, including snapshot testing. ```ts // based on @testing-library/marko API // https://testing-library.com/docs/marko-testing-library/api import { render, screen } from '@marko/testing-library' import Greeting from './greeting.marko' test('renders a message', async () => { const { baseElement } = await render(Greeting, { name: 'Marko' }) const screen = page.elementLocator(baseElement) await expect.element(screen.getByText(/Marko/)).toBeInTheDocument() expect(container.firstChild).toMatchInlineSnapshot( `

Hello, Marko!

` ) }) ``` -------------------------------- ### onHookStart Source: https://main.vitest.dev/api/advanced/reporters This method is called when any of the specified hooks (beforeAll, afterAll, beforeEach, afterEach) have started running. The context provided indicates the type of hook and the associated test entity. ```APIDOC ## onHookStart ### Description This method is called when any of these hooks have started running: `beforeAll`, `afterAll`, `beforeEach`, `afterEach`. If `beforeAll` or `afterAll` are started, the `entity` will be either `TestSuite` or `TestModule`. If `beforeEach` or `afterEach` are started, the `entity` will always be `TestCase`. ### Method `onHookStart` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **context** (ReportedHookContext) - Required - Contextual information about the hook that started. ### Request Example ```ts function onHookStart(context: ReportedHookContext): Awaitable ``` ### Response #### Success Response (200) Void #### Response Example None ``` -------------------------------- ### Asynchronous Render Example Source: https://main.vitest.dev/api/browser/react Demonstrates the correct way to await the `render` function, which is necessary for proper Suspense handling. ```tsx import { render } from 'vitest-browser-react' const screen = render() // [!code --] const screen = await render() // [!code ++] ``` -------------------------------- ### Async Rejects toThrow Example Source: https://main.vitest.dev/api/expect Use `rejects.toThrow()` to assert that an asynchronous operation throws an error. This example demonstrates catching a rejected promise. ```typescript test('expect rejects toThrow', async ({ expect }) => { const promise = Promise.reject(new Error('Test')) await expect(promise).rejects.toThrow() }) ``` -------------------------------- ### Detecting Async Leaks Example Source: https://main.vitest.dev/config/detectasyncleaks This output shows an example of an asynchronous leak detected by Vitest, specifically a `setTimeout` that executes after the test has finished. ```sh ⎯⎯⎯⎯⎯⎯⎯⎯ Async Leaks 1 ⎯⎯⎯⎯⎯⎯⎯⎯ Timeout leaking in test/checkout-screen.test.tsx 26| 27| 28| | 29| 30| ``` -------------------------------- ### Example TAP Flat Report Output Source: https://main.vitest.dev/guide/reporters An example of the output generated by the TAP flat reporter, showing test results in a flat TAP format. ```bash TAP version 13 1..2 not ok 1 - __tests__/test-file-1.test.ts > first test file > 2 + 2 should equal 4 # time=11.00ms --- error: name: "AssertionError" message: "expected 5 to be 4 // Object.is equality" at: "/root-directory/__tests__/test-file-1.test.ts:20:28" actual: "5" expected: "4" ... ok 2 - __tests__/test-file-1.test.ts > first test file > 4 - 2 should equal 2 # time=0.00ms ``` -------------------------------- ### Basic Snapshot Test Example Source: https://main.vitest.dev/guide/snapshot Demonstrates a basic snapshot test for user data using `toMatchKvSnapshot`. The actual output will be saved in a snapshot file. ```typescript import { expect, test } from 'vitest' test('user data', () => { const user = { name: 'Alice', score: '42' } expect(user).toMatchKvSnapshot() }) ``` -------------------------------- ### Install Playwright Browsers in CI Source: https://main.vitest.dev/guide/browser/visual-regression-testing This YAML snippet shows how to install Playwright browsers as a step in a GitHub Actions workflow before running visual regression tests. ```yaml # ...the rest of the workflow - name: Install Playwright Browsers run: npx --no playwright install --with-deps --only-shell ``` -------------------------------- ### Configure Multiple Projects with Names Source: https://main.vitest.dev/config/name This example demonstrates how to configure multiple projects within Vitest, each with a distinct name to differentiate them in the terminal output. ```javascript import { defineConfig } from 'vitest/config' export default defineConfig({ test: { projects: [ { name: 'unit', include: ['./test/*.unit.test.js'], }, { name: 'e2e', include: ['./test/*.e2e.test.js'], }, ], }, }) ``` -------------------------------- ### Vitest Config with Default and Custom Project Names Source: https://main.vitest.dev/guide/browser/multiple-setups Example Vitest configuration demonstrating how project names are assigned, both automatically for default browser instances and manually for custom configurations. ```typescript export default defineConfig({ test: { browser: { instances: [ // name: chromium { browser: 'chromium' }, // name: custom { browser: 'firefox', name: 'custom' }, ] } } }) ``` ```typescript export default defineConfig({ test: { name: 'custom', browser: { instances: [ // name: custom (chromium) { browser: 'chromium' }, // name: manual { browser: 'firefox', name: 'manual' }, ] } } }) ``` -------------------------------- ### Example JUnit XML Report Structure Source: https://main.vitest.dev/guide/reporters This is an example of the XML output generated by the JUnit reporter. It shows the nested structure of test suites, test cases, and failures. ```xml AssertionError: expected 5 to be 4 // Object.is equality ❯ __tests__/test-file-1.test.ts:20:28 ``` -------------------------------- ### Define a Custom Vitest Environment Source: https://main.vitest.dev/config/environment Export a custom environment object with name, viteEnvironment, and setup/teardown functions. The setup function can perform custom setup and return teardown logic. ```ts import type { Environment } from 'vitest' export default { name: 'custom', viteEnvironment: 'ssr', setup() { // custom setup return { teardown() { // called after all tests with this env have been run } } } } ``` -------------------------------- ### Retriable Assertion Example Source: https://main.vitest.dev/api/browser/assertions Use `expect.element` with `page.getBy*` locators for retriable DOM assertions. This example checks for an error banner with specific text content, retrying until the condition is met. ```typescript import { expect, test } from 'vitest' import { page } from 'vitest/browser' test('error banner is rendered', async () => { triggerError() // This creates a locator that will try to find the element // when any of its methods are called. // This call by itself doesn't check the existence of the element. const banner = page.getByRole('alert', { name: /error/i, }) // Vitest provides `expect.element` with built-in retry-ability // It will repeatedly check that the element exists in the DOM and that // the content of `element.textContent` is equal to "Error!" // until all the conditions are met await expect.element(banner).toHaveTextContent('Error!') }) ``` -------------------------------- ### Initial ARIA Snapshot Generation Source: https://main.vitest.dev/guide/browser/aria-snapshots This example shows the initial HTML of a shopping cart and the ARIA snapshot generated by Vitest with the `--update` flag. ```html

Your Cart

  • Wireless Headphones — $79.99
``` ```yaml - heading "Your Cart" [level=1] - list "Cart Items": - listitem: Wireless Headphones — $79.99 - button "Checkout" ``` -------------------------------- ### Get multiple elements with .elements() Source: https://main.vitest.dev/api/browser/locators Use `.elements()` to get an array of all DOM elements matching the locator's selector. This method never throws an error; it returns an empty array if no elements are found. ```typescript function elements(): Element[] ``` ```typescript page.getByText('Hello World').elements() // ✅ [HTMLElement] ``` ```typescript page.getByText('World').elements() // ✅ [HTMLElement] ``` ```typescript page.getByText('Hello', { exact: true }).elements() // ✅ [HTMLElement] ``` ```typescript page.getByText('Hello').elements() // ✅ [HTMLElement, HTMLElement] ``` ```typescript page.getByText('Hello USA').elements() // ✅ [] ``` -------------------------------- ### CLI: Configure Test Sequence Options Source: https://main.vitest.dev/config/sequence Provides an example of how to set sequence options like shuffle and seed using the Vitest CLI. ```sh npx vitest --sequence.shuffle --sequence.seed=1000 ``` -------------------------------- ### Implement Vitest Reporter with onTestRunStart Source: https://main.vitest.dev/api/advanced/reporters Shows a basic implementation of a Vitest reporter focusing on the onTestRunStart method to log the number of test files scheduled to run. Requires importing types from 'vitest/node'. ```typescript import type { Reporter, TestSpecification } from 'vitest/node' class MyReporter implements Reporter { onTestRunStart(specifications: TestSpecification[]) { console.log(specifications.length, 'test files will run') } } export default new MyReporter() ``` -------------------------------- ### startVitest API Source: https://main.vitest.dev/guide/advanced Starts Vitest tests programmatically. It returns a Vitest instance if tests can be started. If watch mode is not enabled, Vitest will call the `close` method automatically. If watch mode is enabled and the terminal supports TTY, Vitest will register console shortcuts. ```APIDOC ## startVitest ### Description Starts Vitest tests programmatically. Returns a `Vitest` instance if tests can be started. Automatically calls `close` if not in watch mode. Registers console shortcuts in watch mode if the terminal supports TTY. ### Method `startVitest(mode: VitestRunMode, cliFilters: string[] = [], options: CliOptions = {}, viteOverrides?: ViteUserConfig, vitestOptions?: VitestOptions): Promise` ### Parameters - **mode** (VitestRunMode) - Required - The mode to run Vitest in (e.g., 'test'). - **cliFilters** (string[]) - Optional - A list of filters. Vitest will run only tests whose file path contains at least one of these strings. - **options** (CliOptions) - Optional - CLI arguments that will override any test config options. - **viteOverrides** (ViteUserConfig) - Optional - Complete Vite config, which takes precedence over other user-defined options. - **vitestOptions** (VitestOptions) - Optional - Vitest specific options. ### Request Example ```js import { startVitest } from 'vitest/node' const vitest = await startVitest('test') await vitest.close() ``` ### Response #### Success Response (Vitest Instance) - **state.getTestModules** (Array) - Returns an array of `TestModule` objects containing test results. #### Response Example ```ts import type { TestModule } from 'vitest/node' const vitest = await startVitest('test') console.log(vitest.state.getTestModules()) // [TestModule] ``` ```