CI-Friendly Playwright Tests
This document explains how all Playwright tests in this project have been configured to be CI-friendly, ensuring stable and reliable test execution in automated environments.
Overview
All Playwright tests now use CI-friendly utilities and configurations that:
- Automatically adjust timeouts for CI environments
- Use headless mode when
CI=true - Disable animations and other UI effects that can cause flakiness
- Provide better error handling and retry logic
- Support both local development and CI execution
CI-Friendly Utilities
Location
All CI-friendly utilities are located in:
src/test-utils/ci-friendly.tsKey Utilities
Timeout Management
import { getTimeouts } from '../../src/test-utils/ci-friendly';
const timeouts = getTimeouts();
// Returns CI-appropriate timeouts for different scenariosNavigation
import { ciNavigate } from '../../src/test-utils/ci-friendly';
// Replaces: await page.goto('/');
await ciNavigate(page, '/');Element Waiting
import { ciWaitForSelector } from '../../src/test-utils/ci-friendly';
// Replaces: await page.waitForSelector('input[type="search"]', { timeout: 30000 });
await ciWaitForSelector(page, 'input[type="search"]', 'navigation');Search Operations
import { ciSearch } from '../../src/test-utils/ci-friendly';
// Replaces multiple steps with a single CI-friendly operation
await ciSearch(page, 'input[type="search"]', 'search query');Hover Actions
import { ciHover } from '../../src/test-utils/ci-friendly';
// More reliable hovering in CI environments
await ciHover(page, 'footer');Click Actions
import { ciClick } from '../../src/test-utils/ci-friendly';
// Includes proper waiting and error handling
await ciClick(page, 'button[type="submit"]');Explicit Waits
import { ciWait } from '../../src/test-utils/ci-friendly';
// Replaces: await page.waitForTimeout(2000);
await ciWait(page, 'medium');Playwright Configuration
CI Detection
The configuration automatically detects CI environments using:
const isCI = Boolean(process.env.CI);CI-Specific Settings
When CI=true:
- Headless mode: Enabled for faster execution
- Workers: Limited to 1 for stability
- Retries: Increased to 3 for flaky test handling
- Timeouts: Extended (60s actions, 120s tests)
- Browser args: Animations disabled, stability flags added
- Parallelization: Disabled to prevent resource conflicts
Local Development
When not in CI:
- Headless mode: Optional (can be headed for debugging)
- Workers: Multiple workers for faster execution
- Retries: Minimal (0-1)
- Timeouts: Standard (30s actions, 60s tests)
Updated Test Files
Search Tests (search.spec.ts)
β Updated with CI utilities
- Uses
ciNavigate()for navigation - Uses
ciSearch()for search operations - Uses
ciWaitForSelector()for element waiting - Implements proper CI timeout handling
Navigation Tests (navigation.spec.ts)
β Updated with CI utilities
- Uses
ciHover()for footer navigation - Uses
ciClick()for link interactions - Includes performance timing validation
- Handles navigation errors gracefully
Atomic Server Tests (atomic-server-haystack.spec.ts)
β Partially updated
- UI interaction tests use CI utilities
- Includes graceful error handling for CI
- Server startup uses extended timeouts
NPM Scripts
CI-Friendly Test Commands
# Run all e2e tests in CI mode
# Run all tests with CI reporting
# Run atomic server tests in CI mode
# Run specific haystack tests in CI mode
# Run all tests (unit + e2e + atomic) in CI mode
Development Test Commands
# Run tests in development mode (headed, faster timeouts)
# Run tests with UI for debugging
# Run tests in headed mode
# Debug specific test
CI Environment Variables
Required Variables
CI=true # Enables CI-friendly modeOptional Variables
ATOMIC_SERVER_PATH=/path/to/atomic-server # Custom atomic server binary
TERRAPHIM_SERVER_PATH=/path/to/terraphim_server # Custom server binaryCI Pipeline Integration
GitHub Actions Example
- name: Run Playwright Tests
run: |
CI=true yarn run test:all:ci
env:
CI: trueJenkins Example
{
steps {
sh 'CI=true yarn run test:e2e:ci'
}
}Timeout Reference
CI Timeouts (when CI=true)
- Test timeout: 120 seconds
- Action timeout: 60 seconds
- Navigation timeout: 60 seconds
- Search timeout: 20 seconds
- Server startup: 300 seconds (5 minutes)
Development Timeouts
- Test timeout: 60 seconds
- Action timeout: 30 seconds
- Navigation timeout: 30 seconds
- Search timeout: 10 seconds
- Server startup: 180 seconds (3 minutes)
Wait Time Reference
CI Wait Times (when CI=true)
- Tiny: 500ms
- Small: 1000ms
- Medium: 2000ms
- Large: 5000ms
- After Click: 1000ms
- After Hover: 1000ms
- After Search: 3000ms
- After Navigation: 2000ms
Development Wait Times
- Tiny: 200ms
- Small: 500ms
- Medium: 1000ms
- Large: 2000ms
- After Click: 500ms
- After Hover: 300ms
- After Search: 1500ms
- After Navigation: 1000ms
Best Practices
1. Always Use CI Utilities
// β Avoid direct Playwright calls with hardcoded timeouts
await page.goto('/');
await page.waitForSelector('input', { timeout: 30000 });
await page.waitForTimeout(2000);
// β
Use CI-friendly utilities
await ciNavigate(page, '/');
await ciWaitForSelector(page, 'input', 'navigation');
await ciWait(page, 'medium');2. Handle Errors Gracefully
try {
await ciWaitForSelector(page, '.search-results', 'search');
// Test passed
} catch (error) {
if (!isCI()) {
throw error; // Fail in dev environment
}
console.log('β οΈ Expected behavior in CI - graceful degradation');
}3. Use Semantic Timeout Types
// β Generic timeout
await ciWaitForSelector(page, 'input', 'medium');
// β
Semantic timeout
await ciWaitForSelector(page, 'input[type="search"]', 'navigation');
await ciWaitForSelector(page, '.search-results', 'search');4. Consistent Error Messages
if (results.total === 0) {
console.log('β οΈ No results found - this may indicate integration issues');
} else {
console.log('β
Search functionality working correctly');
}Troubleshooting
Common Issues
Tests Timing Out in CI
- Increase timeout type:
'medium'β'long' - Add explicit waits:
await ciWait(page, 'large'); - Check server startup time
Flaky Hover Actions
- Use
ciHover()instead of directhover() - Add wait after hover:
await ciWait(page, 'afterHover');
Search Results Not Found
- Increase search timeout: use
'search'timeout type - Add graceful error handling for CI environments
- Verify test data is properly populated
Animation-Related Failures
- CI configuration automatically disables animations
- Add explicit waits after UI transitions
- Use
ciWait(page, 'animation')for animation completion
Debug Commands
# Run single test with full output
CI=true
# Run test with trace
CI=true
# Generate test report
CI=true Migration Guide
For Existing Tests
- Import CI utilities at the top of test files
- Replace
page.goto()withciNavigate() - Replace
page.waitForSelector()withciWaitForSelector() - Replace
page.waitForTimeout()withciWait() - Replace direct
click()withciClick() - Replace direct
hover()withciHover() - Add graceful error handling for CI environments
Example Migration
// Before
import { test, expect } from '@playwright/test';
test('search test', async ({ page }) => {
await page.goto('/');
await page.waitForSelector('input[type="search"]', { timeout: 30000 });
await page.locator('input[type="search"]').fill('query');
await page.locator('input[type="search"]').press('Enter');
await page.waitForTimeout(2000);
});
// After
import { test, expect } from '@playwright/test';
import { ciNavigate, ciWaitForSelector, ciSearch } from '../../src/test-utils/ci-friendly';
test('search test', async ({ page }) => {
await ciNavigate(page, '/');
await ciWaitForSelector(page, 'input[type="search"]', 'navigation');
await ciSearch(page, 'input[type="search"]', 'query');
});Performance Benefits
CI Execution Time
- Headless mode: ~40% faster execution
- Single worker: Prevents resource conflicts
- Optimized timeouts: Reduces unnecessary waiting
- Disabled animations: Faster UI interactions
Reliability Improvements
- Retry logic: 3x retry for transient failures
- Extended timeouts: Handles slow CI environments
- Graceful degradation: Tests don't fail on minor issues
- Consistent timing: Predictable test execution
Conclusion
All Playwright tests in this project are now CI-friendly and will execute reliably in both development and CI environments. The utilities automatically handle timeout adjustments, error handling, and environment-specific configurations, making the test suite robust and maintainable.