| name | testing-patterns |
| description | Testing patterns for Jest and Playwright. Use when writing tests, setting up test fixtures, or validating RLS enforcement. Routes to existing test conventions and provides evidence templates. |
Testing Patterns Skill
Purpose
Guide consistent and effective testing. Routes to existing test patterns and provides evidence templates for Linear.
When This Skill Applies
Invoke this skill when:
- Writing new unit tests
- Creating integration tests
- Setting up test fixtures with RLS
- Running test suites
- Packaging test evidence for Linear
Test Directory Structure
__tests__/
├── unit/ # Fast, isolated tests
│ ├── components/ # React component tests
│ ├── lib/ # Library function tests
│ ├── services/ # Service layer tests
│ └── user/ # User helper tests
├── integration/ # API and database tests
├── database/ # Database helper tests
├── e2e/ # End-to-end tests (Playwright)
├── payments/ # Payment flow tests
└── setup.ts # Global test setup
Configuration Files
- Jest Config:
jest.config.js - Test Setup:
__tests__/setup.ts - Playwright Config:
playwright.config.ts
RLS-Aware Testing
Setting Up Test Context
Always use RLS context helpers in tests:
import { withUserContext, withSystemContext } from "@/lib/rls-context";
import { prisma } from "@/lib/prisma";
describe("User payments", () => {
const testUserId = "test-user-123";
beforeEach(async () => {
// Create test user with RLS context
await withSystemContext(prisma, "test", async (client) => {
await client.user.create({
data: {
user_id: testUserId,
email: `test-${Date.now()}@example.com`,
first_name: "Test",
last_name: "User",
},
});
});
});
it("should only see own payments", async () => {
const payments = await withUserContext(
prisma,
testUserId,
async (client) => {
return client.payments.findMany();
},
);
// RLS ensures only this user's payments returned
expect(payments.every((p) => p.user_id === testUserId)).toBe(true);
});
});
Test Isolation
Use unique identifiers to prevent test pollution:
const uniqueEmail = `test-${Date.now()}@example.com`;
const uniqueUserId = `user-${crypto.randomUUID()}`;
Test Commands
# Run all unit tests
yarn test:unit
# Run integration tests
yarn test:integration
# Run specific test file
yarn jest __tests__/unit/components/my-component.test.tsx
# Run tests matching pattern
yarn jest --testNamePattern="should handle"
# Run with coverage
yarn test:unit --coverage
# Run E2E tests
yarn test:e2e
Common Patterns
Component Testing
import { render, screen, fireEvent } from "@testing-library/react";
import { MyComponent } from "@/components/my-component";
describe("MyComponent", () => {
it("renders correctly", () => {
render(<MyComponent />);
expect(screen.getByRole("button")).toBeInTheDocument();
});
it("handles click events", async () => {
const onClickMock = jest.fn();
render(<MyComponent onClick={onClickMock} />);
fireEvent.click(screen.getByRole("button"));
expect(onClickMock).toHaveBeenCalledTimes(1);
});
});
API Route Testing
import { GET } from "@/app/api/my-route/route";
import { NextRequest } from "next/server";
describe("GET /api/my-route", () => {
it("returns 200 with data", async () => {
const request = new NextRequest("http://localhost:3000/api/my-route");
const response = await GET(request);
expect(response.status).toBe(200);
const data = await response.json();
expect(data).toHaveProperty("success", true);
});
});
Mocking Prisma
jest.mock("@/lib/prisma", () => ({
prisma: {
user: {
findUnique: jest.fn(),
create: jest.fn(),
},
},
}));
Evidence Template for Linear
When completing test work, attach this evidence block:
**Test Execution Evidence**
**Test Suite**: [unit/integration/e2e]
**Files Changed**: [list files]
**Test Results:**
- Total Tests: [X]
- Passed: [X]
- Failed: [0]
- Skipped: [X]
**Coverage** (if applicable):
- Statements: X%
- Branches: X%
- Functions: X%
- Lines: X%
**Commands Run:**
\`\`\`bash
yarn test:unit --coverage
\`\`\`
**Output:**
[Paste relevant test output]
Pre-Push Validation
Always run before pushing:
yarn ci:validate
This runs:
- Type checking
- ESLint
- Unit tests
- Format check
Authoritative References
- Jest Config:
jest.config.js - Test Setup:
__tests__/setup.ts - RLS Context:
lib/rls-context.ts - CI Validation:
package.jsonscripts