# How Unit Tests Are Structured in the makeplane/plane Repository

> Discover how unit tests are structured in the makeplane/plane repository. Learn about Vitest, co-located test files, and inline snapshot testing with TypeScript for robust assertions.

- Repository: [Plane/plane](https://github.com/makeplane/plane)
- Tags: how-to-guide
- Published: 2026-08-25

---

**The makeplane/plane repository uses Vitest for all unit tests, co-locates [`.test.ts`](https://github.com/makeplane/plane/blob/main/.test.ts) and [`.spec.ts`](https://github.com/makeplane/plane/blob/main/.spec.ts) files in dedicated `tests` directories that mirror source structure, and leverages TypeScript with inline snapshot testing for deterministic assertions.**

The makeplane/plane monorepo follows a strict, convention-driven approach to testing that ensures consistency across its apps and packages. If you are contributing to this open-source project, understanding how unit tests are structured in the makeplane/plane repository is essential for writing maintainable, effective test coverage that aligns with the project's architectural standards.

## Test Framework and File Conventions

### Vitest as the Standard Runner

All unit tests in the repository are written using **Vitest**, a Jest-compatible test runner optimized for modern TypeScript projects. According to the source code, every test file imports `describe`, `it`, `expect`, and `assert` directly from the `vitest` package rather than relying on global definitions.

### File Naming Patterns

The repository distinguishes between two file suffixes to indicate test type:

- **[`.test.ts`](https://github.com/makeplane/plane/blob/main/.test.ts)** – Used for standard unit tests (e.g., [`effect-utils.test.ts`](https://github.com/makeplane/plane/blob/main/effect-utils.test.ts), [`pdf-rendering.test.ts`](https://github.com/makeplane/plane/blob/main/pdf-rendering.test.ts))
- **[`.spec.ts`](https://github.com/makeplane/plane/blob/main/.spec.ts)** – Reserved for specification-style tests, particularly codemod transformations (e.g., [`remove-directives.spec.ts`](https://github.com/makeplane/plane/blob/main/remove-directives.spec.ts), [`function-declaration.spec.ts`](https://github.com/makeplane/plane/blob/main/function-declaration.spec.ts))

## Directory Structure and Organization

Tests are organized in dedicated `tests` directories that mirror the production code they exercise. This co-location strategy ensures that navigation remains straightforward, with test files maintaining parallel paths to their corresponding source modules.

```

apps/
└─ live/
    └─ tests/
        ├─ services/
        │   └─ pdf-export/
        │       └─ effect-utils.test.ts
        └─ lib/
            └─ pdf/
                └─ pdf-rendering.test.ts
packages/
└─ codemods/
    └─ tests/
        ├─ remove-directives.spec.ts
        └─ function-declaration.spec.ts

```

## Writing Tests in the Plane Codebase

### The describe/it Pattern

Each test file follows the classic **`describe → it`** nesting pattern. Top-level `describe` blocks identify the module under test, while nested `describe` blocks group related scenarios by function or method. Individual `it` blocks contain concise, behavior-focused descriptions that read as full sentences when combined with the function name.

### Snapshot Testing and Effect Handling

The codebase makes heavy use of **inline snapshots** via `expect(...).toMatchInlineSnapshot` for deterministic output checks, particularly in codemod tests located in `packages/codemods/tests/`. For asynchronous logic involving the Effect library, tests use `Effect.runPromise` to execute workflows and assert on returned values or `Either` types to verify error conditions like `PdfTimeoutError`.

## Practical Examples from the Source

### Testing PDF Export Utilities

In [`apps/live/tests/services/pdf-export/effect-utils.test.ts`](https://github.com/makeplane/plane/blob/main/apps/live/tests/services/pdf-export/effect-utils.test.ts), the test suite validates utility functions including `withTimeoutAndRetry`, `recoverWithDefault`, and `tryAsync`. These tests import production code using the `@/` alias and verify both success paths and error handling through Effect's `Either` type.

```typescript
// apps/live/tests/services/pdf-export/effect-utils.test.ts
import { describe, it, expect, assert } from "vitest";
import { Effect, Duration, Either } from "effect";
import { withTimeoutAndRetry, recoverWithDefault, tryAsync } from "@/services/pdf-export/effect-utils";
import { PdfTimeoutError } from "@/schema/pdf-export";

describe("effect-utils", () => {
  describe("withTimeoutAndRetry", () => {
    it("should succeed when effect completes within timeout", async () => {
      const effect = Effect.succeed("success");
      const wrapped = withTimeoutAndRetry("test-operation")(effect);

      const result = await Effect.runPromise(wrapped);
      expect(result).toBe("success");
    });
  });

  describe("recoverWithDefault", () => {
    it("should return default on failure", async () => {
      const effect = Effect.fail("error");
      const recovered = recoverWithDefault("default-value")(effect);
      
      const result = await Effect.runPromise(recovered);
      expect(result).toBe("default-value");
    });
  });
});

```

### Testing Codemod Transformations

The codemod tests in [`packages/codemods/tests/remove-directives.spec.ts`](https://github.com/makeplane/plane/blob/main/packages/codemods/tests/remove-directives.spec.ts) demonstrate how to test AST transformations. These tests import `applyTransform` from `@hypermod/utils` to run codemods against source strings and compare outputs using inline snapshots.

```typescript
// packages/codemods/tests/remove-directives.spec.ts
import { describe, it, expect } from "vitest";
import { applyTransform } from "@hypermod/utils";
import * as transformer from "../remove-directives";

describe("remove-directives", () => {
  it("should remove 'use client' directive", async () => {
    const result = await applyTransform(
      transformer,
      `
      "use client";
      import React from "react";

      export const MyComponent = () => {
        return <div>Hello, world!</div>;
      };
      `,
      { parser: "tsx" },
    );

    expect(result).toMatchInlineSnapshot(`
      "import React from "react";

                export const MyComponent = () => {
                  return <div>Hello, world!</div>;
                };"
    `);
  });
});

```

## Running Tests Locally

While the repository includes a Docker-based Django test suite for backend validation, frontend unit tests execute via standard npm scripts. The monorepo leverages Turborepo to enable both global and filtered test execution.

```bash

# Run all unit tests across the monorepo

pnpm test

# Run tests for a specific application only

pnpm turbo run test --filter=apps/live

# Run tests for the codemods package

pnpm turbo run test --filter=packages/codemods

```

## Summary

- **Vitest powers all testing**: The repository standardizes on Vitest for its Jest-compatible API and first-class TypeScript support.
- **Co-located test directories**: Files live in `tests/` folders that mirror source structure, using [`.test.ts`](https://github.com/makeplane/plane/blob/main/.test.ts) for unit tests and [`.spec.ts`](https://github.com/makeplane/plane/blob/main/.spec.ts) for codemod specifications.
- **Inline snapshots dominate**: Codemod and utility tests prefer `toMatchInlineSnapshot` for deterministic regression detection and easier code review.
- **Effect library integration**: Async tests in the PDF export services use `Effect.runPromise` and assert on `Either` types to verify both success and error paths.
- **Monorepo-aware execution**: Tests run via `pnpm` and Turborepo, supporting both global runs and targeted filtering by app or package.

## Frequently Asked Questions

### What test runner does makeplane/plane use?

The repository uses **Vitest** as its exclusive unit testing framework. All test files import `describe`, `it`, `expect`, and `assert` from `vitest`, providing a Jest-compatible API with native TypeScript support and faster execution than traditional Jest configurations.

### Where are unit tests located in the repository?

Unit tests reside in dedicated `tests` directories within each app or package that mirror the production code layout. For example, `apps/live/tests/` contains tests for the live application, while `packages/codemods/tests/` houses codemod specifications. This structure places [`effect-utils.test.ts`](https://github.com/makeplane/plane/blob/main/effect-utils.test.ts) adjacent to its source code in the services directory.

### How do I run unit tests for a specific app or package?

Use Turborepo's filter syntax with pnpm. Executing `pnpm turbo run test --filter=apps/live` runs tests only for the live app, while `pnpm turbo run test --filter=packages/codemods` targets the codemods package. To run all tests across the monorepo, execute `pnpm test` from the repository root.

### Does the repository use snapshot testing for unit tests?

Yes, snapshot testing is prevalent throughout the codebase, particularly in codemod tests. The repository favors **inline snapshots** (`toMatchInlineSnapshot`) over external `.snap` files, embedding expected output directly in the test file for better visibility during code reviews and reduced file system clutter.