# E2E Testing Guide This guide explains how to run End-to-End (E2E) tests for the Temporal workflows. ## Overview Our E2E testing strategy uses: - **Temporal TestWorkflowEnvironment** for time-skipping unit tests - **temporalio/auto-setup Docker container** for full integration tests - **Main application database** for realistic data validation - **Vitest** as the test runner with proper timeout configuration ## Test Types ### 1. Unit Tests (Database Logic) Location: `src/activities/__tests__/*-simple.test.ts` - Test database operations without Temporal context - Fast execution, isolated test data - Focus on business logic validation ```bash npm run test:unit ``` ### 2. E2E Tests (Full Workflow) Location: `src/__tests__/e2e/*.e2e.test.ts` - Test complete workflows with Temporal - Real activity execution with database operations - End-to-end validation of business processes ```bash npm run test:e2e ``` ## Prerequisites 1. **Main Application Database**: Must be running on port 5432 ```bash cd /Users/robertisaacs/alga-psa docker-compose -f docker-compose.base.yaml up -d postgres ``` 2. **Node.js 20+**: Required for Temporal SDK compatibility 3. **Docker**: For running Temporal test environment ## Running E2E Tests ### Method 1: Using NPM Scripts (Recommended) ```bash # Run E2E tests once npm run test:e2e # Run E2E tests in watch mode npm run test:e2e:watch # Run all tests (unit + E2E) npm run test:all ``` ### Method 2: Manual Docker Setup ```bash # Start Temporal test environment npm run docker:test:up # Wait for services to be ready (check logs) docker-compose -f docker-compose.test.yml logs -f # Run tests manually npm test -- src/__tests__/e2e # Clean up npm run docker:test:down ``` ### Method 3: Using Test Script ```bash # Run the comprehensive E2E test script ./scripts/test-e2e.sh # Run in watch mode ./scripts/test-e2e.sh --watch ``` ## Test Environment Configuration ### Environment Files - `.env.test`: Unit test configuration (uses main app DB) - `.env.e2e`: E2E test configuration (Temporal + main app DB) ### Docker Services **docker-compose.test.yml** includes: - `temporal`: Temporal server with auto-setup - `postgres`: Dedicated PostgreSQL for Temporal metadata - `temporal-admin-tools`: CLI tools for debugging ### Ports - **7233**: Temporal gRPC endpoint - **8233**: Temporal Web UI (http://localhost:8233) - **5433**: Temporal PostgreSQL - **5432**: Main application PostgreSQL (external) ## Test Configuration ### Vitest Settings ```typescript { testTimeout: 120000, // 2 minutes for E2E tests hookTimeout: 60000, // 1 minute for setup/teardown pool: 'forks', // Required for Temporal poolOptions: { forks: { singleFork: true } // Prevent concurrent environments } } ``` ### Temporal Settings ```typescript { address: 'localhost:7233', namespace: 'default', taskQueue: 'e2e-temporal-workflows' } ``` ## Writing E2E Tests ### Basic Structure ```typescript import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { TestWorkflowEnvironment } from '@temporalio/testing'; import { Worker } from '@temporalio/worker'; import * as activities from '../../activities'; import { myWorkflow } from '../../workflows/my-workflow'; describe('My Workflow E2E', () => { let testEnv: TestWorkflowEnvironment; beforeAll(async () => { testEnv = await TestWorkflowEnvironment.createTimeSkipping(); }); afterAll(async () => { await testEnv?.teardown(); }); it('should complete workflow successfully', async () => { const worker = await Worker.create({ connection: testEnv.nativeConnection, taskQueue: 'test-queue', workflowsPath: require.resolve('../../workflows'), activities, }); const handle = await testEnv.client.workflow.start(myWorkflow, { args: [{ input: 'test' }], taskQueue: 'test-queue', workflowId: 'test-' + Date.now(), }); const result = await handle.result(); expect(result.success).toBe(true); await worker.shutdown(); }); }); ``` ### Best Practices 1. **Unique Test Data**: Use timestamps to avoid conflicts ```typescript const timestamp = Date.now(); const email = `test-${timestamp}@example.com`; ``` 2. **Proper Cleanup**: Always clean up test data ```typescript afterEach(async () => { await testDb.cleanup(); }); ``` 3. **Realistic Data**: Use actual database operations ```typescript // Verify in database, not just workflow result const tenant = await testDb.getTenant(result.tenantId); expect(tenant.client_name).toBe(input.companyName ?? input.tenantName); ``` 4. **Error Testing**: Test failure scenarios ```typescript await expect(handle.result()).rejects.toThrow('Expected error'); ``` ## Debugging ### Temporal Web UI Visit http://localhost:8233 when test environment is running to: - View workflow executions - Inspect workflow history - Debug failed workflows ### Logs ```bash # View Temporal server logs docker-compose -f docker-compose.test.yml logs temporal # View PostgreSQL logs docker-compose -f docker-compose.test.yml logs postgres ``` ### Database Inspection ```bash # Connect to test database docker exec -it temporal-workflows-postgres-1 psql -U temporal -d temporal # Connect to main app database docker exec -it alga-psa-postgres-1 psql -U postgres -d server ``` ## Troubleshooting ### Common Issues 1. **Timeout Errors**: Increase test timeouts in vitest.config.ts 2. **Port Conflicts**: Ensure ports 7233, 8233, 5433 are available 3. **Database Connection**: Verify main app database is running 4. **Memory Issues**: Use `singleFork: true` in Vitest pool options ### Error: "Main application database not running" ```bash cd /Users/robertisaacs/alga-psa docker-compose -f docker-compose.base.yaml up -d postgres ``` ### Error: "Temporal connection failed" ```bash # Restart test environment npm run docker:test:down npm run docker:test:up ``` ### Error: "Test timeout" - Check Temporal Web UI for stuck workflows - Increase timeouts in vitest.config.ts - Verify all services are healthy ## Performance ### Expected Test Times - Basic setup test: ~10-30 seconds - Simple workflow test: ~30-60 seconds - Complex workflow test: ~1-2 minutes ### Optimization Tips - Use `TestWorkflowEnvironment.createTimeSkipping()` for faster tests - Minimize database operations in tests - Use test data factories for consistent setup - Run tests in single fork mode to avoid conflicts ## Integration with CI/CD ```yaml # Example GitHub Actions step - name: Run E2E Tests run: | docker-compose -f docker-compose.base.yaml up -d postgres npm run test:e2e env: NODE_ENV: test ``` For more details, see the test files in `src/__tests__/e2e/` and the setup utilities in `src/test-utils/`.