Testing Strategy
Relevant source files
The following files were used as context for generating this wiki page:The testing strategy for the Email Platform is a multi-layered approach designed to ensure code quality, stability, and correctness across both the backend API and the frontend web application. It combines unit, integration, and end-to-end (E2E) tests, primarily leveraging the Vitest testing framework. The strategy is integrated into a continuous integration (CI) pipeline to automate build verification and test execution.
A key aspect of the strategy is the separation of tests that can run in isolation (unit tests) from those that require external services like a database (integration and E2E tests). This is explicitly noted in the project's planning documents, indicating a clear distinction in setup and execution requirements for different test suites.
Sources: TESTING_PLAN.md, PLAN.md
Test Levels Overview
The project defines four distinct levels of testing, each with specific tools and purposes. The status indicates that while the configuration is in place, running the full suite requires a dedicated test database environment.
| Level | Tool | Location | Status |
|---|---|---|---|
| Unit Tests | Vitest | src/test/*.test.ts | ✅ Configured |
| Integration Tests | Vitest | src/test/*.test.ts | ⚠️ Needs DB |
| E2E Tests | Vitest | src/test/smtp.e2e.test.ts | ⚠️ Needs DB |
| Build Tests | TypeScript + Vite | CI | ✅ Passing |
Sources: TESTING_PLAN.md:5-11
This diagram illustrates the hierarchical testing structure.
Sources: TESTING_PLAN.md, PLAN.md
Backend (API) Testing
The API service (services/api) employs a robust testing strategy using Vitest for unit, integration, and E2E tests.
Sources: services/api/package.json:11-13
Unit Tests
API unit tests are designed to run in isolation without a database connection. This is achieved by extensively mocking the Prisma database client. Test files such as domains.test.ts use vi.mock to replace the prisma module with a mock object, allowing handlers to be tested based on their interaction with the mocked database layer.
// services/api/src/test/domains.test.ts:5-23
const prismaMock = {
domain: {
findUnique: vi.fn(),
findMany: vi.fn(),
create: vi.fn(),
update: vi.fn(),
delete: vi.fn(),
count: vi.fn(),
},
// ... other models
};
vi.mock("../lib/prisma", () => ({
prisma: prismaMock,
}));
This approach allows for fast execution and focuses solely on the business logic within route handlers and utility functions.
Sources: services/api/src/test/domains.testts:5-23, services/api/src/test/shared_domains.test.ts:4-26
Integration Tests
Integration tests verify the interaction between the API server and a live PostgreSQL database. These tests cover complete user flows. The api.integration.test.ts file defines a test suite that:
- Ensures the database schema is migrated.
- Resets the database before each test run.
- Seeds an admin user.
- Executes a sequence of API calls: login, create a domain, create an inbox, and list messages.
The following diagram shows the typical flow of an API integration test.
This sequence is implemented in api.integration.test.ts.
Sources: services/api/test/api.integration.test.ts:44-77, TESTING_PLAN.md:20-27
E2E (End-to-End) Tests
The primary E2E test validates the entire inbound email flow, from an SMTP transaction to the message appearing in the API. The smtp.e2e.test.ts file orchestrates this by:
- Starting the API server, SMTP server, and a message queue worker.
- Using
nodemailerto send an email to the running SMTP server. - Waiting for the message to be processed and persisted.
- Querying the API's
/inboxes/:id/messagesendpoint to confirm the email was received and stored correctly.
This diagram illustrates the SMTP E2E test flow.
This flow ensures that all components of the email ingestion pipeline are working together correctly.
Sources: services/api/test/smtp.e2e.test.ts
Frontend (Web) Testing
The frontend web application (services/web) uses Vitest with JSDOM and @testing-library/react for component-level testing.
Sources: services/web/package.json:28-31
Component Smoke Tests
The testing approach for the frontend focuses on "smoke tests" for pages and complex components. As seen in Dashboard.test.tsx, this involves:
- Mocking all child components, context providers (
AuthContext), and API utility functions. - Rendering the top-level component (
Dashboard). - Verifying that the main layout elements (e.g., Sidebar, MessageList) are rendered in the document.
This strategy isolates the component under test and avoids complex setup, focusing on rendering correctness rather than deep functional logic.
// services/web/src/pages/Dashboard.test.tsx:18-38
// Mock child components to avoid deep rendering
vi.mock("../components/Sidebar", () => ({
Sidebar: () => <div data-testid="sidebar">Sidebar</div>,
}));
vi.mock("../components/MessageList", () => ({
MessageList: () => <div data-testid="message-list">MessageList</div>,
}));
// ... more mocks
describe("Dashboard Page", () => {
it("renders dashboard layout correctly", async () => {
render(<Dashboard />);
// Verify main layout components
expect(screen.getByTestId("app-header")).toBeInTheDocument();
expect(screen.getByTestId("sidebar")).toBeInTheDocument();
// ... more assertions
});
});
Sources: services/web/src/pages/Dashboard.test.tsx, services/web/package.json
Test Environment and CI/CD
A standardized test environment is crucial for running integration and E2E tests. The project uses Docker to provide the necessary services.
Test Environment Setup
Running the full test suite requires a specific environment configuration.
| Service | Port (for tests) | Notes |
|---|---|---|
| PostgreSQL | 5433 | A dedicated test database is required. |
| Redis | 6380 | Used for BullMQ job queue. |
The following environment variables must be set:
DATABASE_URL=postgresql://postgres:postgres@localhost:5433/email_service_test
JWT_SECRET=test-secret
REDIS_HOST=localhost
REDIS_PORT=6380
Sources: TESTING_PLAN.md:31-41
CI/CD Integration
The recommended CI/CD setup uses GitHub Actions. The workflow defines services to run PostgreSQL and Redis containers, making them available to the test job. This ensures a consistent and clean environment for every test run.
The CI pipeline follows these steps:
- Set up the environment with containerized services (Postgres, Redis).
- Run linting and build verification checks.
- Execute the test suites (
npm test).
# TESTING_PLAN.md:45-58
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_PASSWORD: postgres
ports:
- 5433:5432
redis:
image: redis:7-alpine
ports:
- 6380:6379
This configuration ensures that integration and E2E tests can connect to the required database and Redis instances during the CI run.
Sources: TESTING_PLAN.md:45-58, PLAN.md:5-9