This document outlines the testing strategy for the solid-fortnight project, ensuring reliability across the gateway, management, evaluator, streamer, and analytics services, as well as the admin dashboard.
We follow a layered testing approach to balance speed and confidence:
| Layer | Tool | Scope | Speed |
|---|---|---|---|
| Unit Tests (Backend) | Go testing |
Engine logic, config, utility functions. | Fast (< 1s) |
| Unit Tests (UI) | Vitest + RTL | Dashboard components, modal logic, routing. | Fast (< 2s) |
| Integration Tests | Go testing + Docker |
API handlers interacting with real DB/Redis. | Medium (~5s) |
| End-to-End (E2E) | Playwright + Docker | Full user flows through Gateway & UI. | Slow (> 30s) |
Used for the Admin Dashboard to verify UI behavior without a backend.
- Mocking: Global
fetchis mocked to simulate API Gateway responses. - Location:
cmd/dashboard/src/**/*.test.tsx. - Command:
cd cmd/dashboard && bun run test.
To ensure reliable and maintainable UI tests (both Vitest and Playwright), we use a consistent naming convention for data-testid attributes.
The format is [ComponentOrView]:[ElementName](:[OptionalID]).
- ComponentOrView: The name of the React component or view (e.g.,
ProjectsView,Sidebar). - ElementName: A descriptive name for the element (e.g.,
SubmitBtn,Title,Loading). - OptionalID: A unique identifier if the element is part of a list (e.g., project ID).
Instead of hardcoding strings, use the createTestIdFactory utility from src/test/test-utils.ts.
import { createTestIdFactory } from '../test/test-utils';
const COMPONENT_NAME = 'MyComponent';
const t = createTestIdFactory(COMPONENT_NAME);
// Usage:
<div data-testid={t('Container')}>
<button data-testid={t('SubmitBtn')}>Submit</button>
{items.map(item => (
<div key={item.id} data-testid={t('ItemRow', item.id)}>
{item.name}
</div>
))}
</div>This ensures that all test IDs in your component are prefixed with the component name, preventing collisions and making tests more robust.
When creating a reusable component, accept an optional componentName prop so that the parent can control the test ID scope:
interface MyListProps {
componentName?: string;
// ...
}
export const MyList: React.FC<MyListProps> = ({ componentName = 'MyList', ... }) => {
const t = createTestIdFactory(componentName);
return <ul data-testid={t('List')}>...</ul>;
};Used for the Management API and Gateway. These tests ensure that HTTP requests correctly modify the PostgreSQL state or proxy correctly to internal services.
- Infrastructure: Real PostgreSQL/Redis containers via
make test-db-up. - Location:
apps/*/handlers/*_test.go.
The final verification layer that tests the real integrated system.
- Environment: Isolated Docker Compose stack (
deployments/docker-compose.test.yml). - Location:
cmd/dashboard/tests/e2e/*.spec.ts. - Command:
make test-e2e.
- Backend: Prefer real infrastructure (Postgres/Redis) for Go tests.
- Gateway: Use
httptest.NewServerto mock internal services when testing proxy logic. - UI: Mock
fetchin Vitest to test error states and complex data scenarios without starting Go services.
# 1. Test Backend Logic
go test ./internal/engine/... ./internal/config/...
# 2. Test UI Logic
cd cmd/dashboard && bun run test# 1. Run all Backend Integration Tests
make test
# 2. Run Full Stack E2E
make test-e2e