Testing Setup in OpenCut Using Vitest and @testing-library/react

OpenCut leverages Vitest and @testing-library/react to provide a fast, Vite-native testing environment for React components, requiring no additional configuration beyond the standard apps/web/package.json dependencies.

The OpenCut repository is a modern video editing application built with React, TypeScript, and Vite. Its testing architecture resides primarily in the apps/web workspace, where Vitest serves as the test runner and @testing-library/react handles component rendering and assertions. This setup reuses the existing Vite configuration, ensuring that tests run with the same module resolution and transpilation settings as the development server.

Testing Stack Overview

The testing infrastructure in OpenCut combines two primary tools: Vitest as the test runner and @testing-library/react for DOM testing utilities. Because Vitest is designed specifically for Vite projects, it integrates seamlessly with the build tooling already present in the apps/web directory.

Vitest executes tests in a Node.js environment with JSDOM support, allowing React components to render in a virtual browser context without requiring an actual browser. The @testing-library/react package provides declarative utilities such as render, screen, and userEvent to simulate user interactions and query the DOM structure.

Configuration and Dependencies

Package.json Setup

The testing dependencies are declared in apps/web/package.json as development dependencies. This file also defines the npm script that invokes the test runner.

According to the OpenCut source code, the web application declares both Vitest and the React Testing Library in its manifest. The test script typically maps to vitest run, which executes the entire suite once and exits, making it suitable for continuous integration pipelines.

// apps/web/package.json
{
  "scripts": {
    "test": "vitest run"
  },
  "devDependencies": {
    "vitest": "^x.x.x",
    "@testing-library/react": "^x.x.x",
    "@testing-library/jest-dom": "^x.x.x"
  }
}

Vite Integration

Rather than maintaining a separate configuration file, OpenCut's Vitest instance inherits settings directly from apps/web/vite.config.ts. This approach ensures that TypeScript path aliases, JSX transformation, and plugin configurations remain consistent between the development build and the test environment.

When Vitest starts, it automatically detects the Vite configuration in the same directory and applies those settings to the test bundler. This eliminates configuration drift and reduces maintenance overhead.

Writing Component Tests

Test File Location and Naming

Test files in OpenCut follow the co-location pattern, residing alongside the components they verify within apps/web/src/. The naming convention uses the .test.tsx suffix for TypeScript React components.

For example, a component located at apps/web/src/components/ui/button.tsx would have its corresponding test at apps/web/src/components/ui/button.test.tsx.

Example: Testing a Button Component

The following example demonstrates a typical unit test for a React component using Vitest's mocking capabilities and @testing-library/react's querying utilities:

// apps/web/src/components/ui/button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
import Button from './button';

describe('Button Component', () => {
  it('calls onClick handler when clicked', () => {
    const handleClick = vi.fn();
    render(<Button onClick={handleClick}>OK</Button>);

    fireEvent.click(screen.getByRole('button', { name: /ok/i }));
    
    expect(handleClick).toHaveBeenCalledOnce();
  });
});

In this example, vi.fn() creates a Vitest mock function to track calls to the click handler. The render method mounts the component into the virtual DOM, while screen.getByRole queries the element using accessibility semantics rather than implementation details.

Running the Test Suite

Executing Tests

To run the test suite from the command line, navigate to the apps/web directory and execute the test script defined in package.json:


# Run all tests once (CI mode)

npm test

# Run tests in watch mode during development

npx vitest

# Alternative using bun

bun test

The npm test command invokes vitest run, which executes all discovered test files and reports results without entering watch mode. For continuous development, running vitest without the run flag starts the interactive watch mode, re-running affected tests when files change.

Test Discovery

Vitest automatically discovers files matching the pattern *.test.{js,ts,tsx} or *.spec.{js,ts,tsx} within the project directory. The runner respects the root configuration inherited from Vite, ensuring that tests are looked for within the apps/web/src hierarchy.

Summary

  • OpenCut uses Vitest as the test runner and @testing-library/react for component testing, configured within the apps/web workspace.
  • The testing setup reuses apps/web/vite.config.ts for module resolution and transpilation, requiring no separate Vitest configuration file.
  • Dependencies are managed in apps/web/package.json, which defines the test script as vitest run.
  • Test files use the .test.tsx suffix and are co-located with their corresponding components in apps/web/src/.
  • Vitest provides mocking utilities via vi.fn() and runs tests in a JSDOM environment compatible with React Testing Library's render and screen APIs.

Frequently Asked Questions

How do I run tests in the OpenCut repository?

Execute npm test from the apps/web directory to run the full test suite once. For development, use npx vitest to start watch mode, which automatically re-runs tests when you modify source files. If using Bun, the command bun test also invokes the Vitest runner.

Where should I place new test files in the OpenCut project?

Place test files adjacent to the components they test within apps/web/src/, using the naming convention [ComponentName].test.tsx. This co-location pattern keeps tests visible and maintains the project's modular structure.

Does OpenCut require a separate Vitest configuration file?

No. OpenCut's Vitest instance inherits configuration directly from apps/web/vite.config.ts. This ensures that TypeScript settings, path aliases, and plugins remain consistent between the application build and the test environment without maintaining duplicate configuration files.

How does OpenCut handle DOM assertions in tests?

The project uses @testing-library/jest-dom matchers alongside Vitest's assertion library. This provides semantic methods like toBeInTheDocument() and toHaveBeenCalledOnce() for readable test assertions. The JSDOM environment provided by Vitest supplies the necessary browser APIs for these assertions to function in Node.js.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →