> ## Documentation Index
> Fetch the complete documentation index at: https://formbricks.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing Methodology

> How we test Formbricks to ensure reliability, performance, and high-quality code.

## Overview

At Formbricks, we maintain a rigorous testing strategy to ensure high-quality code and reliable functionality. Our testing approach is standardized and integrated into our development workflow.

## Testing Structure

### Unit Testing with Vitest

We use Vitest as our primary testing framework. All unit tests follow these conventions:

1. **File Location and Naming**

   * Test files are co-located with the source files they test
   * Test files use the `.test.ts` extension (e.g., `utils.test.ts` tests `utils.ts`)

2. **Test Organization**

   ```typescript theme={null}
   import { describe, expect, test } from "vitest";

   describe("ComponentName or FeatureName", () => {
     describe("functionName or scenario", () => {
       // We use the `test` function instead of `it` throught our test suite
       test("should describe expected behavior", () => {
         // test implementation
       });
     });
   });
   ```

3. **Coverage**
   * Coverage is measured, not targeted: confidence over coverage, and no test exists to move the
     number (see `AGENTS.md`, "Testing Guidelines")
   * The repo enforces exactly one Vitest threshold: `modules/auth/lib/**` at 80%
     (`apps/web/vite.config.mts`). Everything else is reported — `pnpm test:coverage` emits lcov and
     the SonarQube workflow uploads it, with the quality gate configured in SonarQube, not here
   * Coverage is tracked using the V8 provider
   * Coverage reports include:
     * Text summaries
     * HTML reports
     * LCOV reports

### End-to-End Testing with Playwright

E2E tests are located in `apps/web/playwright/` and focus on critical user workflows. `AGENTS.md` is the
source of truth for when one is warranted; the short version:

1. **Level.** Prove a behavior at the cheapest level that can fail on it. A feature's happy path or a
   journey across several surfaces is E2E. Business logic, invariants and anything pure is a unit test on
   the `.ts`. A route's authorization, response shape or query scoping is a unit or integration test on
   that route.
2. **Unit of coverage.** One spec per feature area, not per ticket and not per component. Every feature
   area ships a happy-path spec, and a new spec file is for an area that has none. Inside an area that
   already has one, the level still follows the behavior: journey behavior extends that spec, logic goes
   to a `.ts` unit test, UI detail goes to manual QA (see 3) — never a second spec file.
3. **Neither is an option.** A granular UI detail inside a covered feature — a label, a breadcrumb, an
   ARIA attribute, a keystroke inside one widget, a field's validation message — is verified manually and
   recorded in the PR. It does not get a spec.
4. **Cost.** Every spec is paid on every PR by everyone, forever. The Playwright job is the critical path
   of the PR gate and its wall clock can never drop below its slowest single test, so a new spec has to
   buy risk coverage that nothing cheaper can.

## Testing Setup

### Configuration

The web app's Vitest configuration (`apps/web/vite.config.mts`) includes:

```typescript theme={null}
test: {
  exclude: ["playwright/**", "node_modules/**", ".next/**", "**/*.integration.test.ts"],
  setupFiles: ["./vitestSetup.ts"],
  coverage: {
    provider: "v8",
    reporter: ["text", "html", "lcov"],
    reportsDirectory: "./coverage",
  },
}
```

### Test Utilities

Common test utilities are available in `vitestSetup.ts`:

* Mock implementations for commonly used functions
* Test lifecycle hooks (beforeEach, afterEach)
* Validation test helpers

## Best Practices

1. **Test Independence**

   ```typescript theme={null}
   beforeEach(() => {
     vi.resetModules();
     vi.resetAllMocks();
   });

   afterEach(() => {
     vi.clearAllMocks();
   });
   ```

2. **Mocking**

   * Use Vitest's built-in mocking utilities
   * Mock external dependencies and services
   * Example:

   ```typescript theme={null}
   vi.mock("@formbricks/database", () => ({
     prisma: {
       user: {
         create: vi.fn(),
         findUnique: vi.fn(),
       },
     },
   }));
   ```

3. **Assertions**
   * Write clear, specific assertions
   * Test both success and error cases
   * Example:
   ```typescript theme={null}
   expect(result.ok).toBe(true);
   expect(result.data).toEqual(expectedData);
   expect(async () => await invalidCall()).rejects.toThrow(ValidationError);
   ```

## Quality Assurance Process

1. **Continuous Integration**

   * Automated test suite execution on pull requests
   * Coverage reports generation
   * Test results reporting

2. **New Features**
   * Must include unit tests for the logic they add
   * A new user-facing feature area must include one happy-path E2E spec. Inside an area that already
     has one, the level follows the behavior: journey behavior extends that spec, logic goes to a unit
     test, UI detail is verified manually
   * Must not add tests whose only purpose is to move a coverage metric


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.