Rstest Documentation

website·Indexed 33 days ago

https://rstest.rs

A JavaScript and TypeScript testing framework powered by Rspack and Rsbuild. It features a bundle-based execution model for fast performance, first-class support for the Rspack ecosystem, and an experimental Browser Mode for running tests in real browsers. The framework includes support for mocking, snapshot testing, E2E testing with Playwright, and provides migration guides for users moving from Jest and Vitest.

Tokens
91K
Snippets
559
Records
694
Agent score
70%

What's inside Rstest

  1. Overview of Rstest testing framework

    Rstest is a JavaScript testing framework powered by Rspack. It provides Jest-compatible APIs and native support for TypeScript, ESM, CJS, and CSS Modules. Unlike traditional per-file transform-and-execute frameworks, Rstest uses a dependency graph-based bundle model. This allows it to leverage build-time optimizations like tree-shaking and skipping unused re-exports, making test behavior more consistent with production output and improving performance in large-scale projects.
  2. Overview of Rstest testing framework

    Rstest is a JavaScript and TypeScript testing framework built on Rsbuild and Rspack. It uses a bundle-based execution model leveraging Rspack's Rust-based build pipeline and SWC transforms for fast test compilation. It allows developers to reuse existing build configurations and run tests across Node.js, simulated DOM environments, and real browsers.
  3. Overview of built-in Rstest reporters

    Rstest provides several built-in reporters for different environments and needs:

    • default: Console output with colors; ideal for local development.
    • dot: Compact per-test markers (· pass, x fail, - skip, * todo); fast local feedback.
    • verbose: Detailed output for all test cases; useful for debugging.
    • github-actions: CI error annotations and Markdown summaries for GitHub Actions.
    • junit: JUnit XML format for CI/CD integration.
    • json: Structured JSON report for tooling and scripting.
    • md: Markdown agent report for LLM/Agent integrations.
    • blob: Serialized JSON output for merging sharded reports.
  4. Overview of Rstest Testing Framework

    Rstest is a testing framework based on Rspack that provides first-class support for the Rspack ecosystem. It allows developers to reuse existing Rsbuild or Rspack configurations, ensuring that aliases, transforms, and plugins remain consistent between the development build and the test environment. By running tests through Rspack's bundling model, it closely matches production behavior while maintaining fast startup and rerun speeds. It supports TypeScript, ESM, CJS, CSS Modules, and modern JavaScript out of the box, and includes built-in assertions, snapshots, mocks, coverage, and lifecycle hooks.
  5. Overview of Rstest Adapters

    Adapters in Rstest allow developers to convert configurations from other tools (like build tools or CLIs) into a format Rstest supports. This enables the reuse of existing configurations (e.g., path aliases, global variables), simplifies maintenance by centralizing configuration, and allows frameworks to provide preset test environments.
  6. Overview of the Rstack JavaScript toolchain

    Rstack is a fast, unified JavaScript toolchain designed for developers and AI agents. It consists of several high-performance, Rust-based tools aimed at modernizing the web development workflow:
  7. Overview of Rstest Browser Mode

    Browser Mode allows tests to execute in real browsers (Chromium, Firefox, or WebKit) using Playwright, ensuring that tests run with the exact same browser APIs and behaviors as in production. This is recommended over simulated environments like jsdom or happy-dom when you need full Browser API coverage, native support for Canvas/WebGL and Web Workers, real CSS computed styles, or cross-browser testing.

    Note: Like Node mode, Browser Mode will fail a test file if an unhandled error or promise rejection escapes the file, even if all individual tests passed. Always await promises or attach handlers to prevent leaks.

  8. Understand Rstest's bundle-based execution model

    Rstest uses a bundle-based execution model where files in the bundle graph are transformed by the build pipeline (supporting TypeScript, JSX, and aliases). However, some code is loaded by Node.js at runtime and preserves native Node.js semantics. This includes late dynamic require() or import() calls, externalized modules, and code loaded via custom Node.js loaders or register hooks.

    Rule of thumb:

    • Static imports in the bundle graph: Rstest transforms/bundles them.
    • Dynamic loads, loader hooks, and externalized modules: Expect native Node.js behavior.
  9. Use TestContext for runtime test control and metadata

    The TestContext object is available in tests, hooks, and fixtures. It provides:

    • task: Metadata about the current test, including id, name, filepath, projectRoot, retryCount (0 for initial attempt), and a mutable meta object for custom JSON-serializable data.
    • signal: An AbortSignal that triggers when the test attempt times out. Pass this to async APIs (like fetch or fs.readFile) to cancel pending work.
    • skip(): A method to immediately skip the current test during execution.
    • expect: The bound assertion API.
    import { test } from '@rstest/core';
    import { readFile } from 'node:fs/promises';
    
    test('runtime context example', async ({ signal, task }) => {
      // 1. Use signal for cancellation
      await readFile('./large-data.json', { signal });
    
      // 2. Attach custom metadata to the result
      task.meta.coveredBranches = ['a', 'b'];
    
      // 3. Conditional skip
      if (someCondition) {
        test.skip();
      }
    });
  10. Rstest Test API Overview

    The Rstest Test API provides the core primitives for defining and executing tests. It includes:

    • expect: The assertion library for validating outcomes, featuring soft assertions (expect.soft), polling (expect.poll), and various matchers (common, mock, snapshot, promise, and asymmetric).
    • test: The primary function for defining test cases, with modifiers for isolation (test.only), skipping (test.skip, test.skipIf), requirements (test.todo), and execution mode (test.concurrent, test.sequential).
    • describe: Used to group related tests, supporting similar modifiers as test (e.g., describe.only, describe.skip, describe.each).
    • Hooks: Lifecycle methods to manage setup and teardown, including beforeAll, afterAll, beforeEach, afterEach, onTestFinished, and onTestFailed.
  11. Use Locator for element querying and interaction

    Locator is the core API for element querying and interaction in Browser Mode. The typical workflow involves using the page object to locate elements, performing interactions on the resulting Locator, and using expect.element for assertions. When using the Playwright provider, interaction methods (like click, fill, check) automatically wait for elements to become actionable (visible, enabled, stable) before executing.
    import { page } from '@rstest/browser';
    import { expect, test } from '@rstest/core';
    
    test('interacts with a form using locator', async () => {
      await page.getByLabel('Username').fill('alice');
      await page.getByLabel('Password').fill('secret123');
      await page.getByRole('button', { name: 'Login' }).click();
    
      await expect.element(page.getByLabel('Username')).toHaveValue('alice');
    });
  12. Perform cleanup regardless of test result with onTestFinished

    The onTestFinished hook is called after a test finishes, regardless of whether it passed or failed. It executes after afterEach.

    Important for Concurrent Tests: When using describe.concurrent, do not use the global onTestFinished import. Instead, retrieve onTestFinished from the test context to ensure the hook is associated with the correct test.

    import { onTestFinished, test } from '@rstest/core';
    
    // Standard usage
    test('test server', () => {
      const server = startServer();
      onTestFinished(() => server.close());
    });
    
    // Concurrent usage
    describe.concurrent('concurrent suite', () => {
      test('test 1', async ({ onTestFinished }) => {
        onTestFinished(() => { /* cleanup */ });
      });
    });