Skip to content

New skill: monotemplate:integration-tests #25

Description

@firstloop-jake

Skill

monotemplate:integration-tests (new skill)

Problem

The monotemplate has no skill for guiding the creation and management of integration tests. Developers need a clear, repeatable pattern for:

  • Adding new repository integration tests
  • Adding new API integration tests
  • Setting up the integration test infrastructure for a fresh project

Proposed Solution

Create a new monotemplate:integration-tests skill split into two files:

1. SKILL.md — Day-to-day test authoring (loaded every time the skill triggers)

This is the main skill file. It should cover:

When to trigger: When a user asks to add integration tests, test a repository, test an API endpoint, or mentions "integration test".

Architecture overview:

  • Two test categories: Repository tests (direct DB via Prisma) and API tests (HTTP via supertest)
  • Test isolation: truncateAllTables() in beforeEach, resetSeq() for predictable factory IDs
  • Auth mocking: setMockUserId() / resetMockAuth() for API tests
  • Testcontainers provides a throwaway Postgres per run

Repository test pattern:

import { PrismaClient } from "@server/generated/prisma";
import { SomeRepository } from "@server/repositories/SomeRepository";
import { createTestPrismaClient, truncateAllTables } from "../utils/db/prisma-test-client";
import { resetSeq } from "../utils/db/test-factories";

let prisma: PrismaClient;
let repo: SomeRepository;

beforeAll(() => {
    prisma = createTestPrismaClient();
    repo = new SomeRepository(prisma);
});

beforeEach(async () => {
    await truncateAllTables(prisma);
    resetSeq();
});

afterAll(async () => {
    await prisma.$disconnect();
});

API test pattern:

import request from "supertest";
import type { Express } from "express";
import { PrismaClient } from "@server/generated/prisma";
import { resetMockAuth, setMockUserId } from "../utils/api/auth-helper";
import createApp from "@server/server";
import { createTestPrismaClient, truncateAllTables } from "../utils/db/prisma-test-client";
import { resetSeq } from "../utils/db/test-factories";

let app: Express;
let prisma: PrismaClient;

beforeAll(async () => {
    app = createApp();
    prisma = createTestPrismaClient();
});

beforeEach(async () => {
    await truncateAllTables(prisma);
    resetSeq();
    resetMockAuth();
});

afterAll(async () => {
    await prisma.$disconnect();
});

Checklist when adding tests for a new entity:

  1. Add factory function(s) to tests/integration/utils/db/test-factories.ts
  2. Add the new table to truncateAllTables() in FK-safe order in tests/integration/utils/db/prisma-test-client.ts
  3. Create tests/integration/repositories/<Entity>Repository.integration.test.ts
  4. Create tests/integration/api/<entity>.integration.test.ts
  5. Test file naming: *.integration.test.ts

Factory pattern:

export async function createEntity(
    prisma: PrismaClient,
    overrides: Partial<{ field1: string; field2: string }> = {},
) {
    const n = seq();
    return prisma.entities.create({
        data: {
            field1: overrides.field1 ?? `Default ${n}`,
            field2: overrides.field2 ?? `value-${n}`,
        },
    });
}

Key conventions:

  • Factory functions use seq() for unique auto-incrementing defaults
  • Factories accept overrides partial for test-specific values
  • Repository tests instantiate repos directly with test PrismaClient (bypasses DI)
  • API tests use the real Express app with mocked auth via DI container rebinding
  • Always test: happy path, auth rejection (API), soft-delete exclusion, cross-user isolation
  • Link to [setup.md](setup.md) for first-time setup instructions

2. setup.md — One-time infrastructure setup (linked from SKILL.md, not loaded by default)

This file documents how to set up integration testing from scratch. It should cover:

Dependencies:

bun add -d @testcontainers/postgresql testcontainers

(vitest and supertest should already be in the template)

Files to create:

  • apps/server/vitest.integration.config.mts — Vitest config with fileParallelism: false, globalSetup, dummy Clerk env vars, @server path aliases
  • apps/server/tests/integration/global-setup.ts — Starts Postgres via testcontainers, runs prisma migrate deploy, sets DATABASE_URL
  • apps/server/tests/integration/utils/test-env.ts — Validates DATABASE_URL
  • apps/server/tests/integration/utils/db/prisma-test-client.tscreateTestPrismaClient() and truncateAllTables()
  • apps/server/tests/integration/utils/db/test-factories.ts — Factory functions with seq() counter
  • apps/server/tests/integration/utils/api/auth-helper.ts — Mocks AuthContextFactory via container.rebindSync(), exposes setMockUserId() / resetMockAuth()

Package.json scripts:

  • apps/server/package.json: "test:integration": "vitest run --config vitest.integration.config.mts"
  • Root package.json: "test:integration": "bun --filter server test:integration"

knip.json updates:

  • Add testcontainers to ignoreDependencies
  • Add vitest.integration.config.mts to vitest config array
  • Add tests/**/*.ts to entry and project arrays

tsconfig.json updates:

  • Add vitest.integration.config.mts to includes

CI (.github/workflows/pr-gate.yml):

  • Add integration-tests job that runs bun run test:integration (Docker is available on ubuntu-latest by default)

Directory structure:

apps/server/
├── vitest.integration.config.mts
└── tests/
    └── integration/
        ├── global-setup.ts
        ├── utils/
        │   ├── test-env.ts
        │   ├── db/
        │   │   ├── prisma-test-client.ts
        │   │   └── test-factories.ts
        │   └── api/
        │       └── auth-helper.ts
        ├── repositories/
        │   └── *.integration.test.ts
        └── api/
            └── *.integration.test.ts

Requirements: Docker must be running locally. GitHub Actions ubuntu-latest has Docker by default.

Examples

User says: "Add integration tests for the new Orders entity"
→ Trigger SKILL.md. Follow the checklist: add factory, update truncation, create repo + API test files.

User says: "Set up integration testing for this project"
→ Trigger SKILL.md which links to setup.md. Follow the one-time setup guide.

Reference Implementation

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions