This document provides comprehensive instructions for setting up and running tests for the Checklist application.
- Testing Overview
- Test Environment Setup
- Running Tests
- Unit Tests
- Integration Tests
- End-to-End Tests
- Test Database Configuration
- Common Testing Issues
The Checklist application uses a comprehensive testing strategy with three levels of tests:
- Unit Tests: Test individual components in isolation
- Integration Tests: Test interactions between components and API endpoints
- End-to-End Tests: Test complete user flows and application functionality
- Node.js (v18 or later)
- npm (v9 or later)
- PostgreSQL (v14 or later)
- A properly configured test database (see Test Database Configuration)
-
Install dependencies:
npm install
-
Create a
.env.testfile in the project root:DATABASE_URL="postgresql://checklist_user:securepassword@localhost:5432/checklist_test?schema=public" NODE_ENV=test -
Set up the test database (see the Database Configuration section)
-
Generate Prisma client:
npx prisma generate
npm testFor unit tests:
npm run test:unitFor integration tests:
npm run test:integrationFor end-to-end tests:
npm run test:e2enpm test -- --watchUnit tests focus on testing individual components in isolation. They use Jest and React Testing Library.
Component tests verify that UI components render correctly and handle user interactions as expected.
Example component test (create-button.test.tsx):
describe("CreateChecklistButton", () => {
it("renders correctly", () => {
render(<CreateChecklistButton />);
expect(screen.getByText("Start New Checklist")).toBeInTheDocument();
});
it("handles successful checklist creation", async () => {
// Test implementation
});
});- Test component rendering
- Test user interactions (clicks, input changes)
- Test component state changes
- Test proper handling of props
- Mock external dependencies (API calls, context providers)
Integration tests verify that different parts of the application work together correctly.
API tests verify that API endpoints correctly handle requests and responses.
Example API test:
test("should create a new checklist", async () => {
const checklist = await prisma.checklist.create({
data: {
hash: generateUniqueHash(),
title: "Test Checklist",
},
});
expect(checklist).toHaveProperty("id");
});Database tests verify that the application correctly interacts with the database.
End-to-end tests verify complete user flows and application functionality.
These tests simulate user interactions with the application, testing features like:
- Creating a new checklist
- Adding items to a checklist
- Checking/unchecking items
- Reordering items
- Sharing a checklist via URL
For testing, we use a separate database to avoid affecting development data.
-
Access PostgreSQL as a superuser:
sudo -u postgres psql
-
Create the test database and user:
CREATE DATABASE checklist_test; GRANT ALL PRIVILEGES ON DATABASE checklist_test TO checklist_user;
-
Connect to the test database and set up permissions:
\c checklist_test GRANT USAGE ON SCHEMA public TO checklist_user; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO checklist_user; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO checklist_user; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO checklist_user; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO checklist_user; ALTER SCHEMA public OWNER TO checklist_user;
Run migrations on the test database:
NODE_ENV=test npx prisma migrate devCreate test data for consistent testing:
NODE_ENV=test npx prisma db seedIf you encounter database connection issues during testing:
- Verify the test database exists and is properly configured
- Check that your
.env.testfile has the correct connection string - Ensure the test database user has the necessary permissions
- Verify that PostgreSQL is running
If tests are failing due to inconsistent test data:
- Use
beforeEachorbeforeAllhooks to reset the database state - Implement database transactions for each test
- Use unique identifiers for test data to avoid collisions
If tests are running too slowly:
- Mock external dependencies when possible
- Use in-memory databases for unit tests
- Parallelize test execution
- Optimize database queries in test setup
If you're having trouble with mocks:
- Verify that all external dependencies are properly mocked
- Use Jest's
jest.mock()function to mock modules - Use
jest.spyOn()to spy on specific functions - Reset mocks between tests with
jest.clearAllMocks()