This project includes comprehensive unit tests covering all critical workflows with minimal complexity and maximum coverage.
auth-workflow.test.ts- Authentication, user creation, PostHog trackingpayment-workflow.test.ts- Stripe checkout, customer portalfile-workflow.test.ts- File upload, download, storage limitsemail-workflow.test.ts- SendGrid integration, notificationsstorage.test.ts- Database operations, user ownership
This template focuses tests on the server API and storage layers. There are no client-side tests included.
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm test -- --coverage
# Run specific test file
npm test -- server/__tests__/auth-workflow.test.ts
# Run tests matching pattern
npm test -- --testNamePattern="payment"Tests run automatically on:
- Push to
mainordevelopbranches - Pull requests to
mainordevelop
- Lines: 80%
- Functions: 75%
- Branches: 70%
- Statements: 80%
All external services are mocked:
- Firebase Auth - Token validation, user state
- Stripe - Payment processing, customer management
- SendGrid - Email delivery
- Firebase Storage - File operations
- PostHog - Analytics tracking
Mocks are centralized in server/__tests__/setup/mocks.ts for consistency.
Tests use:
- Jest with TypeScript support
- React Testing Library for component tests
- Supertest for API endpoint tests
- jsdom environment for browser APIs
Tests use mock environment variables (defined in .env.test for local testing):
NODE_ENV=test
DATABASE_URL=postgresql://test:test@localhost:5432/test_db # Mocked, but required
SENDGRID_API_KEY=SG.test_key
SENDGRID_FROM=test@example.com
STRIPE_SECRET_KEY=sk_test_key
POSTHOG_API_KEY=phc_test_key
FIREBASE_PROJECT_ID=test-project
FIREBASE_PRIVATE_KEY=test-key
FIREBASE_CLIENT_EMAIL=test@test.comNote: The DATABASE_URL is required to prevent initialization errors but the actual database is mocked - no real connection is made.
GET /healthshould always return 200; useful for liveness checks.GET /readyreturns 200 when the DB connection is healthy, 503 otherwise. In tests the DB layer is mocked, so this typically returns 200.
- Global
/apilimiter: 500 requests per 15 minutes, keyed by authenticated user (if token present via mocked auth) or IP. Most tests won’t hit this limit. - AI chat limiter: In test mode, the per-route chat limiter
maxis set very high to avoid flakiness. - If you encounter 429s in tests, narrow the scope of requests or adjust the test to avoid hot loops.
- Import errors - Check module paths and mocks
- Async timeouts - Increase test timeout (currently 10s)
- Mock conflicts - Ensure
resetAllMocks()is called
# Run with verbose output
npm test -- --verbose
# Run single test with debug info
npm test -- --testNamePattern="specific test" --verbose
# Check for open handles
npm test -- --detectOpenHandles- Import mocks:
import './setup/mocks' - Use
resetAllMocks()inbeforeEach - Mock auth middleware for protected routes
- Test both success and error cases
- Wrap components with
QueryClientProvider - Mock hooks and external dependencies
- Use
waitForfor async operations - Test user interactions and error states
Console output (console.log, console.error, console.warn, console.debug) is suppressed during tests to keep output clean. This is configured in jest.afterEnv.js.
To enable console output for debugging, uncomment the relevant lines in jest.afterEnv.js.
jest.setup.js- Environment variables and module mocks (runs before Jest framework loads)jest.afterEnv.js- Console suppression using Jest APIs (runs after Jest framework loads)
- Test behavior, not implementation
- Mock external dependencies completely
- Use descriptive test names
- Test error cases and edge conditions
- Keep tests fast and focused
- Maintain high coverage on critical paths
The test suite is designed for GitHub Actions:
- No external service dependencies
- Fast execution (< 2 minutes)
- Comprehensive coverage reporting
- Automatic security auditing