testing-patterns

Test Hierarchy (ALWAYS prefer simpler)

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "testing-patterns" with this command: npx skills add blogic-cz/blogic-marketplace/blogic-cz-blogic-marketplace-testing-patterns

Testing Patterns

Test Hierarchy (ALWAYS prefer simpler)

  • Unit tests (preferred) - Pure functions, parsers, Effect services

  • TRPC Integration (ask first) - Full TRPC stack with PGlite

  • E2E (ask + justify) - Browser automation, slowest

When to Use Each

Situation Test Type Action

Pure function, parser, util Unit Write immediately

Effect service with dependencies Unit with mock layers Write immediately

TRPC procedure (DB logic) TRPC Integration Ask user first

User-facing flow, UI behavior E2E Ask + warn about maintenance

Test File Locations

Code Location Test Location

packages/X/src/file.ts

packages/X/src/tests/file.test.ts

apps/web-app/src/infrastructure/trpc/routers/X.ts

apps/web-app/src/tests/X.test.ts

apps/web-app/src/routes/**

apps/web-app/e2e/feature.e2e.ts

Unit Test Patterns

Basic Vitest

import { describe, expect, it } from "vitest";

describe("parseResourceSize", () => { it("parses Ki units", () => { expect(parseResourceSize("512Ki")).toBe(524288); }); });

Effect with @effect/vitest

import { describe, expect, it } from "@effect/vitest"; import { Effect, Either, Layer } from "effect";

describe("K8sMetricsService", () => { // Mock layer factory const createMockLayer = (responses: Map<string, unknown>) => Layer.succeed(K8sHttpClient, { request: (params) => Effect.succeed(responses.get(params.path)), });

const testLayer = K8sMetricsService.layer.pipe( Layer.provide(createMockLayer(mockResponses)) );

it.effect("collects metrics", () => Effect.gen(function* () { const service = yield* K8sMetricsService; const result = yield* service.collectMetrics({ ... }); expect(result.namespaces).toHaveLength(3); }).pipe(Effect.provide(testLayer)) );

// Error handling with Either.match it.effect("handles error case", () => Effect.gen(function* () { const result = yield* myEffect.pipe(Effect.either); Either.match(result, { onLeft: (error) => { expect(error._tag).toBe("K8sConnectionError"); }, onRight: () => { expect.fail("Expected Left but got Right"); }, }); }).pipe(Effect.provide(testLayer)) ); });

Live Effect tests (real dependencies)

it.live("returns success when endpoint is ready", () => { globalThis.fetch = vi.fn().mockResolvedValue(new Response("ok", { status: 200 }));

return Effect.gen(function* () { const svc = yield* HealthCheckService; const result = yield* svc.checkApiHealth("http://api", { maxRetries: 1, }); expect(result.success).toBe(true); }).pipe(Effect.provide(HealthCheckServiceLive)); });

TRPC Integration Test Patterns

Ask user before writing: "Does an integration test make sense for this TRPC endpoint?"

Setup

import { describe, expect, it, beforeEach, afterEach } from "vitest"; import type { PGlite } from "@electric-sql/pglite"; import { createTestDb, cleanupTestDb, type TestDb, seedUser, seedOrganization, seedMember, seedProject, } from "@project/db/testing"; import { createTestCaller } from "./trpc-test-utils";

describe("agents.listRuns", () => { let db: TestDb; let client: PGlite | undefined;

beforeEach(async () => { const testDb = await createTestDb(); db = testDb.db; client = testDb.client; });

afterEach(async () => { await cleanupTestDb(client); client = undefined; });

it("returns correct results", async () => { // Seed data const user = await seedUser(db); const org = await seedOrganization(db); await seedMember(db, { userId: user.id, organizationId: org.id, }); const project = await seedProject(db, { organizationId: org.id, });

// Create caller with auth context
const caller = createTestCaller({
  db,
  userId: user.id,
});

// Call TRPC procedure
const result = await caller.agents.listRuns({
  projectId: project.id,
  page: 1,
  pageSize: 10,
});

expect(result.runs).toHaveLength(0);
expect(result.total).toBe(0);

}); });

Available seed helpers

import { seedUser, seedOrganization, seedMember, seedProject, seedAgentTemplate, seedAgentInstance, seedAgentRun, seedGitHubIssue, seedCompleteScenario, // Creates full user -> org -> project -> agent -> run chain } from "@project/db/testing";

E2E Test Patterns

Ask user + warn: "E2E tests are the most expensive to maintain. Is this really needed for this feature?"

Basic E2E

import { expect, test } from "@playwright/test"; import { e2eEnv } from "./env"; import { ensureTestUserExists, signInWithEmail } from "./auth-helpers";

const testEmail = e2eEnv.E2E_TEST_EMAIL; const testPassword = e2eEnv.E2E_TEST_PASSWORD;

test("auth: can sign in with email", async ({ page }) => { await ensureTestUserExists(page.request, { email: testEmail, password: testPassword, name: "E2E Test User", });

await signInWithEmail(page, { email: testEmail, password: testPassword, });

await expect( page.getByRole("heading", { name: "Dashboard", exact: true, }), ).toBeVisible({ timeout: 5_000 }); });

Auth helpers

import { signInWithEmail, ensureTestUserExists } from "./auth-helpers"; import { waitForHydration } from "./wait-for-hydration";

// Before interacting with forms await waitForHydration(page);

Test credentials

// From e2eEnv const testEmail = e2eEnv.E2E_TEST_EMAIL; // test@example.com const testPassword = e2eEnv.E2E_TEST_PASSWORD; // TestPass123

Commands

bun run test # Run all unit + TRPC integration tests bun run test:watch # Watch mode bun run test:coverage # With coverage bun run test:e2e # Run E2E tests bun run test:e2e:ui # E2E with UI

Run specific test file (FROM PROJECT ROOT, full path required)

bun run vitest run packages/common/src/tests/pagination.test.ts bun run vitest run apps/web-app/src/tests/formatters.test.ts

WRONG syntax (DO NOT USE):

These DO NOT work:

bun run test packages/common/src/tests/file.test.ts # script doesn't accept path cd packages/common && bun run vitest run src/tests/file.test.ts # wrong cwd

Decision Process

Before writing ANY test:

  • Can this be unit tested? -> Write unit test immediately

  • Need DB behavior (joins, constraints)? -> Ask: "Does an integration test make sense here?"

  • Need browser/UI? -> Ask + warn: "E2E tests are expensive to maintain. Is this necessary?"

Never write integration or E2E tests without user confirmation.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

git-workflow

No summary provided by upstream source.

Repository SourceNeeds Review
General

update-packages

No summary provided by upstream source.

Repository SourceNeeds Review
General

debugging-with-opensrc

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

code-review

No summary provided by upstream source.

Repository SourceNeeds Review