Testing Strategies for Open-SEO: A Layered Unit and E2E Approach

Open-SEO uses a dual-layer testing strategy combining Vitest for fast unit and integration checks with Playwright for realistic end-to-end browser testing, ensuring schema parity across SQLite and PostgreSQL while validating full-stack user flows.

The every-app/open-seo repository implements a comprehensive testing strategy that prioritizes both developer velocity and production reliability. By orchestrating Vitest for rapid feedback on business logic and database contracts alongside Playwright for critical user journey validation, the codebase maintains strict quality gates across its Cloudflare Workers deployment target.

Layered Testing Architecture

Open-SEO divides its test suite into two distinct execution layers that run sequentially in CI. This separation allows quick validation of pure functions and data contracts before exercising the full browser-based stack.

Unit and Integration Tests with Vitest

The Vitest configuration in vitest.config.ts restricts test discovery to src/**/*.test.ts, isolating repository-specific tests from dependencies in node_modules. These tests validate pure functions, type-safety, and database schema contracts in milliseconds, providing immediate feedback on commits.

A critical integration test in src/db/schema-parity.test.ts ensures Drizzle ORM schema compatibility across database dialects. This test programmatically generates both SQLite and PostgreSQL schemas from the Drizzle definitions and asserts structural equality, guaranteeing that migrations work on either backend without divergence:

test('SQLite & Postgres schemas stay in sync', async () => {
  const sqlite = await generateSQLiteSchema();
  const pg = await generatePostgresSchema();

  // Deep structural comparison (ignores dialect-specific defaults)
  expect(normalize(sqlite)).toEqual(normalize(pg));
});

End-to-End Tests with Playwright

Configured in playwright.config.ts, the E2E suite resides in the e2e/ directory and exercises the full stack—including the frontend UI, API endpoints, and database—within a browser-like environment. These tests catch regressions that span multiple services by simulating real user interactions.

The e2e/keyword-research-navigation.spec.ts file validates core user flows such as navigating to the keyword research page, entering search terms, and verifying results tables render correctly:

test('navigate to keyword research and verify UI components', async ({ page }) => {
  await page.goto('/keyword-research');
  await expect(page.getByRole('heading', { name: /Keyword Research/ })).toBeVisible();
  await page.getByLabel('Search term').fill('open-seo');
  await page.getByRole('button', { name: /Search/ }).click();
  await expect(page.getByTestId('results-table')).toBeVisible();
});

Performance Guardrails

Beyond functional correctness, Open-SEO enforces performance budgets through dedicated Playwright specs. The e2e/domain-overview-filters.perf.spec.ts file measures response times for critical user interactions, ensuring filter operations on the domain overview page remain within acceptable thresholds:

test('filter performance stays under threshold', async ({ page }) => {
  await page.goto('/domain-overview');
  const start = Date.now();
  await page.getByLabel('Country').selectOption('US');
  await page.waitForResponse(resp => resp.url().includes('/api/domain-overview') && resp.status() === 200);
  const duration = Date.now() - start;
  expect(duration).toBeLessThan(2000); // 2 seconds max
});

Functional filter behavior is separately validated in e2e/domain-overview-filters.spec.ts, maintaining separation between performance and functional concerns.

CI Pipeline Orchestration

The testing strategy relies on strict sequencing within the CI pipeline (defined in the repository’s GitHub Actions workflow). Vitest unit tests execute first on every commit; only upon passage do Playwright E2E tests trigger against the built Cloudflare Workers environment. If either layer fails, the commit is blocked, preserving release quality by preventing broken code from reaching production.

Summary

  • Open-SEO employs Vitest for fast unit and integration tests scoped to src/**/*.test.ts, ensuring rapid feedback on schema parity and business logic.
  • Playwright E2E tests in the e2e/ directory validate full-stack user flows including keyword research navigation and domain overview filtering.
  • The src/db/schema-parity.test.ts file guarantees database agnosticism by asserting structural equality between generated SQLite and PostgreSQL schemas.
  • Performance thresholds (such as the 2-second maximum for filter responses) are enforced through dedicated .perf.spec.ts files.
  • CI orchestration runs Vitest before Playwright, blocking commits if either layer fails.

Frequently Asked Questions

What testing frameworks does Open-SEO use?

Open-SEO uses Vitest for unit and integration testing and Playwright for end-to-end browser testing. This combination allows the repository to validate both isolated business logic and complete user workflows across the Cloudflare Workers stack.

How does Open-SEO ensure compatibility between SQLite and PostgreSQL?

The repository includes a specialized integration test in src/db/schema-parity.test.ts that generates schemas for both database dialects from the Drizzle ORM definitions. It performs deep structural comparisons to ensure migrations remain compatible across SQLite and PostgreSQL backends without manual drift detection.

Where are the end-to-end tests located in the repository?

All E2E tests reside in the e2e/ directory at the project root, keeping them separate from production source code and unit tests. Key files include e2e/keyword-research-navigation.spec.ts, e2e/domain-overview-filters.spec.ts, and e2e/domain-overview-filters.perf.spec.ts.

What performance standards does Open-SEO enforce through testing?

Open-SEO enforces specific timing thresholds in Playwright performance tests. For example, domain overview filter operations must complete within 2 seconds from user interaction to API response, as validated in e2e/domain-overview-filters.perf.spec.ts.

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 →