Skip to main content

Testing Strategy

Comprehensive testing approach for reliability.

Test Types​

Unit Tests​

  • Component testing
  • Utility functions
  • Business logic
  • Isolated modules

Integration Tests​

  • API endpoints
  • Database operations
  • Authentication flows
  • External services

E2E Tests​

  • User journeys
  • Critical paths
  • Cross-browser
  • Mobile testing

Testing Tools​

Jest​

// jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/$1'
}
}

React Testing Library​

import { render, screen, fireEvent } from '@testing-library/react'
import { Button } from '@/components/ui/button'

describe('Button', () => {
it('handles click events', () => {
const handleClick = jest.fn()

render(
<Button onClick={handleClick}>
Click me
</Button>
)

fireEvent.click(screen.getByText('Click me'))
expect(handleClick).toHaveBeenCalledTimes(1)
})
})

Component Testing​

Basic Component Test​

import { render, screen } from '@testing-library/react'
import { UserCard } from '@/components/UserCard'

describe('UserCard', () => {
const mockUser = {
id: '1',
name: 'John Doe',
email: 'john@example.com',
role: 'instructor'
}

it('displays user information', () => {
render(<UserCard user={mockUser} />)

expect(screen.getByText('John Doe')).toBeInTheDocument()
expect(screen.getByText('john@example.com')).toBeInTheDocument()
expect(screen.getByText('Instructor')).toBeInTheDocument()
})
})

Testing Hooks​

import { renderHook, act } from "@testing-library/react";
import { useCounter } from "@/hooks/useCounter";

describe("useCounter", () => {
it("increments counter", () => {
const { result } = renderHook(() => useCounter());

act(() => {
result.current.increment();
});

expect(result.current.count).toBe(1);
});
});

API Testing​

Server Action Tests​

import { createSession } from "@/actions/sessions";
import { prisma } from "@/lib/db";

jest.mock("@/lib/db", () => ({
prisma: {
session: {
create: jest.fn(),
},
},
}));

describe("createSession", () => {
it("creates a new session", async () => {
const mockSession = { id: "1", title: "Test Session" };
prisma.session.create.mockResolvedValue(mockSession);

const result = await createSession({
title: "Test Session",
startTime: new Date(),
});

expect(result).toEqual(mockSession);
});
});

Database Testing​

Test Database Setup​

// tests/helpers/db.ts
import { PrismaClient } from "@prisma/client";

const testDb = new PrismaClient({
datasources: {
db: {
url: process.env.DATABASE_TEST_URL,
},
},
});

beforeEach(async () => {
await testDb.$executeRaw`TRUNCATE TABLE "User" CASCADE`;
});

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

Mocking​

Mock Providers​

// tests/providers.tsx
export function TestProviders({ children }: { children: React.ReactNode }) {
return (
<ClerkProvider>
<QueryClient>
{children}
</QueryClient>
</ClerkProvider>
)
}

Mock Data​

// tests/mocks/users.ts
export const mockUsers = [
{
id: "1",
clerkId: "clerk_1",
email: "admin@test.com",
role: "admin",
},
{
id: "2",
clerkId: "clerk_2",
email: "instructor@test.com",
role: "instructor",
},
];

Running Tests​

Commands​

# Run all tests
pnpm test

# Watch mode
pnpm test:watch

# Coverage report
pnpm test:coverage

# Specific file
pnpm test UserCard.test.tsx

CI/CD Integration​

# .github/workflows/test.yml
name: Tests
on: [push, pull_request]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
- run: pnpm install
- run: pnpm test:ci