How Unit Tests Are Structured in the makeplane/plane Repository
The makeplane/plane repository uses Vitest for all unit tests, co-locates .test.ts and .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– Used for standard unit tests (e.g.,effect-utils.test.ts,pdf-rendering.test.ts).spec.ts– Reserved for specification-style tests, particularly codemod transformations (e.g.,remove-directives.spec.ts,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, 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.
// 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 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.
// 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.
# 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.tsfor unit tests and.spec.tsfor codemod specifications. - Inline snapshots dominate: Codemod and utility tests prefer
toMatchInlineSnapshotfor deterministic regression detection and easier code review. - Effect library integration: Async tests in the PDF export services use
Effect.runPromiseand assert onEithertypes to verify both success and error paths. - Monorepo-aware execution: Tests run via
pnpmand 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 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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →