How Tests Are Organized in the usekaneo/kaneo Repository

Tests in the Kaneo repository are organized into two top-level scopes under tests/: tests/api/ for fast unit tests and tests/api-integration/ for full-stack integration tests, with feature-specific subfolders mirroring the source layout.

The usekaneo/kaneo project is an open-source platform built with a monorepo structure. Understanding how tests are organized in this repository helps contributors locate existing tests and follow established patterns when adding new functionality. This guide breaks down the directory structure, test runner configuration, and naming conventions based on the actual source code.

Test Directory Structure

All test files live under the top-level tests/ directory. The organization follows a clear separation between isolated unit tests and end-to-end integration tests.

API Unit Tests: tests/api/

The tests/api/ directory contains fast, isolated tests that exercise individual utilities, helpers, and lightweight API logic without spinning up the full server or database.

API Integration Tests: tests/api-integration/

The tests/api-integration/ directory holds end-to-end tests that start the full API server, run database migrations, and exercise real HTTP routes.

Test Helpers: tests/api-integration/helpers/

Reusable test utilities live under tests/api-integration/helpers/. These include fixtures, database helpers, and authentication mocks that provide consistent setup and teardown across integration suites.

Feature-Specific Subfolders

Each logical feature gets its own subdirectory inside the appropriate test scope. This mirroring makes it easy to locate the test corresponding to any source file.

Common feature folders include:

  • utils/ — utility function tests
  • ws/ — WebSocket-related tests
  • redis/ — caching layer tests
  • plugins/github/ — GitHub integration tests
  • billing/ — subscription and payment tests

Test Runner and Configuration

Vitest powers the test runner for both the API and Web packages. Separate configuration files ensure correct TypeScript paths and environment variables for each package.

Configuration Files

File Purpose
apps/api/vitest.config.ts API package configuration (tsconfig paths, globals, coverage)
apps/web/vitest.config.ts Web client configuration (React testing environment)

Running Tests


# Run all tests

pnpm test

# Run integration tests specifically

pnpm test:integration

Vitest automatically discovers all *.test.ts files under tests/ and applies the appropriate configuration based on the package being exercised.

Code Examples

Unit Test Structure

This example from tests/api/utils/verify-turnstile.test.ts shows the typical pattern for API unit tests:

import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { verifyTurnstile } from "../../../apps/api/src/utils/verify-turnstile";

describe("verifyTurnstile", () => {
  beforeEach(() => {
    process.env.TURNSTILE_SECRET_KEY = "test-secret";
  });

  afterEach(() => {
    vi.restoreAllMocks();
  });

  it("posts the secret, token, and remoteip to Cloudflare", async () => {
    const fetchMock = vi.fn().mockResolvedValue({
      json: async () => ({ success: true }),
    });
    globalThis.fetch = fetchMock as unknown as typeof fetch;

    const result = await verifyTurnstile("good-token", "203.0.113.7");
    expect(result.ok).toBe(true);
    expect(fetchMock).toHaveBeenCalledOnce();
  });
});

Integration Test Structure

This example from tests/api-integration/task.test.ts demonstrates a full end-to-end flow using helper utilities:

import { describe, it, expect } from "vitest";
import { apiClient } from "./helpers/fixtures";

describe("Task API", () => {
  it("creates, reads, updates and deletes a task", async () => {
    const created = await apiClient.post("/tasks", { title: "Demo" });
    expect(created.status).toBe(201);

    const fetched = await apiClient.get(`/tasks/${created.body.id}`);
    expect(fetched.body.title).toBe("Demo");

    await apiClient.patch(`/tasks/${created.body.id}`, { title: "Edited" });
    const updated = await apiClient.get(`/tasks/${created.body.id}`);
    expect(updated.body.title).toBe("Edited");

    await apiClient.delete(`/tasks/${created.body.id}`);
    const deleted = await apiClient.get(`/tasks/${created.body.id}`);
    expect(deleted.status).toBe(404);
  });
});

Key Files and Their Purposes

File Purpose
tests/api/utils/verify-turnstile.test.ts Unit test template showing Vitest patterns with mocking
tests/api-integration/task.test.ts Integration test exercising complete REST endpoint flows
apps/api/vitest.config.ts API-specific Vitest configuration
apps/web/vitest.config.ts Web client Vitest configuration
tests/api-integration/helpers/ Shared fixtures and database utilities

CI Pipeline Benefits

The separation between unit and integration tests enables optimized CI workflows:

  1. Fast feedback — unit tests run quickly in the main pipeline
  2. Full coverage — heavier integration suite runs in a dedicated step
  3. Parallel execution — different test scopes can execute on separate runners

Summary

  • Two top-level scopes: tests/api/ for unit tests, tests/api-integration/ for integration tests
  • Feature mirroring: subfolders match the source tree structure for easy navigation
  • Vitest runner: separate configs at apps/api/vitest.config.ts and apps/web/vitest.config.ts
  • Helper utilities: centralized in tests/api-integration/helpers/ for reuse
  • Naming convention: all test files use *.test.ts suffix

Frequently Asked Questions

Where should I add a new test in the Kaneo repository?

Add unit tests for isolated logic in tests/api/{feature}/ and full-stack tests in tests/api-integration/{feature}/. Mirror the source file path under apps/api/src/ to keep tests discoverable.

How do I run only the unit tests without starting the database?

Run pnpm test from the API package directory or use Vitest's file pattern filtering. Unit tests in tests/api/ are designed to run without external dependencies.

What testing utilities are available for integration tests?

The tests/api-integration/helpers/ directory contains reusable fixtures including apiClient for HTTP requests, database seeding utilities, and authentication mocks. Import these in your integration test files to ensure consistent setup.

Does the Web client have its own test configuration?

Yes. The Web client uses apps/web/vitest.config.ts with React Testing Library configured, separate from the API's configuration. This allows proper testing of React components with the appropriate environment setup.

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 →