Testing Patterns in Open-SEO: How to Run the Test Suite with Vitest and Playwright

Open-SEO uses Vitest for unit and integration tests located in src/**/*.test.ts files, and Playwright for end-to-end tests in the e2e/ directory, with all commands available via npm scripts in package.json.

The open-source SEO platform Open-SEO relies on a layered testing strategy to ensure code quality across its TypeScript codebase. Understanding the testing patterns used in this repository helps contributors write reliable features and debug issues efficiently. This guide explains exactly how the test suite is organized and how to execute both Vitest and Playwright tests locally or in CI pipelines.

Testing Architecture Overview

Open-SEO implements two complementary testing patterns that cover different levels of the application stack.

Unit and Integration Tests with Vitest

The codebase uses Vitest as its primary unit testing framework. Test files follow the convention src/**/*.test.ts, such as src/shared/targetDetection.test.ts. Each suite employs the standard Jest-compatible API using describe, it, and expect globals. Vitest is configured with restoreMocks and clearMocks enabled to ensure a clean state between every test execution.

End-to-End Tests with Playwright

For full-stack validation, Open-SEO uses Playwright to run E2E tests against a real browser environment. Test specifications reside in the e2e/ folder, including examples like e2e/keyword-research-navigation.spec.ts. These tests exercise the complete application stack including both frontend and backend components running on a local dev server.

Continuous Integration Configuration

The repository optimizes test execution for CI pipelines through dedicated reporter settings. The test:ci script runs Vitest with the minimal dot reporter to reduce log noise, while E2E tests run via the standard test:e2e script using Playwright's built-in reporting.

Configuration Deep Dive

Understanding the configuration files reveals how the testing patterns are implemented technically.

Vitest Configuration (vitest.config.ts)

In vitest.config.ts, the test environment targets Node.js with specific inclusion patterns and mock cleanup settings:

// https://github.com/every-app/open-seo/blob/main/vitest.config.ts
export default defineConfig({
  plugins: [tsConfigPaths()],
  test: {
    environment: "node",
    include: ["src/**/*.test.ts"],
    restoreMocks: true,
    clearMocks: true,
  },
});

This configuration ensures that all files matching src/**/*.test.ts are discovered automatically, and test isolation is maintained through automatic mock resetting.

Playwright Configuration (playwright.config.ts)

The playwright.config.ts file defines the E2E test directory, timeouts, and automatic dev server management:

// https://github.com/every-app/open-seo/blob/main/playwright.config.ts
export default defineConfig({
  testDir: "./e2e",
  timeout: 45_000,
  workers: 1,
  use: {
    baseURL: "http://localhost:3101",
    screenshot: "only-on-failure",
    trace: "retain-on-failure",
    video: "retain-on-failure",
  },
  webServer: {
    command:
      "NODE_OPTIONS= AUTH_MODE=local_noauth VITE_E2E_DOMAIN_FIXTURES=1 VITE_E2E_KEYWORD_FIXTURES=1 PORT=3101 pnpm exec vite dev --host 127.0.0.1 --strictPort",
    url: "http://localhost:3101",
    reuseExistingServer: false,
    timeout: 120_000,
  },
});

The webServer configuration automatically launches the application on localhost:3101 before executing tests, ensuring consistent test environments without manual server startup.

How to Run the Test Suite

All test execution commands are defined in package.json under the scripts section.

Execute Unit and Integration Tests

To run the test suite for unit and integration tests, use the following npm scripts:


# Run all Vitest tests once

npm run test

# Start Vitest in watch mode for development

npm run test:watch

The test:watch command keeps the test runner active in your terminal, automatically re-running relevant tests whenever you modify source files.

Execute E2E Tests

To execute the full Playwright end-to-end suite or specific test files:


# Run all E2E tests (spins up dev server automatically)

npm run test:e2e

# Run specific E2E test files

npm run test:e2e:domain
npm run test:e2e:keywords

The test:e2e:domain script targets e2e/domain-overview-filters.spec.ts, while test:e2e:keywords runs e2e/keyword-research-navigation.spec.ts. There is also a performance-specific variant available via test:e2e:domain:perf.

CI-Optimized Commands

When running in continuous integration environments, use these optimized commands:


# CI-optimized unit tests with minimal reporter

npm run test:ci

# E2E tests for CI pipelines

npm run test:e2e

The test:ci command executes vitest run --reporter=dot, which provides deterministic feedback without verbose output, while the E2E command runs Playwright with the configuration settings appropriate for automated environments.

Summary

  • Open-SEO employs a dual-layer testing strategy using Vitest for unit/integration tests and Playwright for end-to-end browser automation.
  • Unit test files follow the src/**/*.test.ts pattern and are configured in vitest.config.ts with automatic mock cleanup.
  • E2E tests reside in the e2e/ directory and are managed via playwright.config.ts, which automatically spawns a dev server on localhost:3101.
  • Run the full test suite using npm run test for unit tests or npm run test:e2e for browser-based integration tests.
  • Use npm run test:ci and npm run test:e2e in CI pipelines for optimized, deterministic execution.

Frequently Asked Questions

What testing framework does Open-SEO use for unit tests?

Open-SEO uses Vitest for all unit and integration testing. The configuration in vitest.config.ts specifies a Node.js environment with restoreMocks and clearMocks enabled to ensure test isolation. Test files are co-located with source code using the *.test.ts naming convention.

How do I run only specific end-to-end test files?

You can run specific E2E tests using the targeted npm scripts: npm run test:e2e:domain executes e2e/domain-overview-filters.spec.ts, while npm run test:e2e:keywords runs e2e/keyword-research-navigation.spec.ts. Alternatively, use npx playwright test with a specific file path argument.

What is the difference between npm run test and npm run test:ci?

The npm run test command executes Vitest once with the default reporter, suitable for local development feedback. The npm run test:ci command runs vitest run --reporter=dot, which uses a minimal dot reporter optimized for CI pipelines where verbose output is discouraged and exit codes matter for build status.

Does Playwright require manual server startup before running E2E tests?

No, manual server startup is unnecessary. The playwright.config.ts includes a webServer configuration that automatically launches the application on localhost:3101 before test execution begins. The configuration waits for the server to be ready with a 120-second timeout, ensuring tests run against a properly initialized environment.

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 →