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

> Discover how OpenCut uses Vitest and @testing-library/react for efficient React component testing. Set up your testing environment with ease, leveraging Vite-native speed without extra configuration.

- Repository: [OpenCut.app/OpenCut](https://github.com/OpenCut-app/OpenCut)
- Tags: how-to-guide
- Published: 2026-06-23

---

**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`](https://github.com/OpenCut-app/OpenCut/blob/main/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`](https://github.com/OpenCut-app/OpenCut/blob/main/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.

```json
// 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`](https://github.com/OpenCut-app/OpenCut/blob/main/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`](https://github.com/OpenCut-app/OpenCut/blob/main/.test.tsx) suffix for TypeScript React components.

For example, a component located at [`apps/web/src/components/ui/button.tsx`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/src/components/ui/button.tsx) would have its corresponding test at [`apps/web/src/components/ui/button.test.tsx`](https://github.com/OpenCut-app/OpenCut/blob/main/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:

```tsx
// 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`](https://github.com/OpenCut-app/OpenCut/blob/main/package.json):

```bash

# 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`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/vite.config.ts) for module resolution and transpilation, requiring no separate Vitest configuration file.
- Dependencies are managed in [`apps/web/package.json`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/package.json), which defines the `test` script as `vitest run`.
- Test files use the [`.test.tsx`](https://github.com/OpenCut-app/OpenCut/blob/main/.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`](https://github.com/OpenCut-app/OpenCut/blob/main/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.