10 KiB
10 KiB
E2E Test Troubleshooting
Quick reference for common E2E test issues and solutions.
Table of Contents
- Test Failures
- Environment Issues
- Browser Issues
- Network Issues
- Database Issues
- Performance Issues
- CI/CD Issues
Test Failures
"Element not found" or "Timeout"
Symptoms: Test fails with timeout waiting for element
Solutions:
// 1. Increase timeout
await page.locator("#element").isVisible({ timeout: 10000 });
// 2. Use conditional check
if (await page.locator("#element").isVisible({ timeout: 5000 })) {
await expect(page.locator("#element")).toBeVisible();
}
// 3. Wait for specific condition
await page.waitForURL("**/dashboard");
await page.waitForSelector("#element", { state: "visible" });
// 4. Wait for navigation
await Promise.all([
page.waitForURL("**/success"),
page.click("button[type='submit']"),
]);
Common Causes:
- Element hasn't loaded yet
- Page is still redirecting
- Animation in progress
- Element is conditionally rendered
"Assertion failed"
Symptoms: Expect statement fails
Solutions:
// 1. Add more context
await expect(page.locator("#element"), "Element should be visible")
.toBeVisible();
// 2. Use retry with timeout
await expect(async () => {
const isVisible = await page.locator("#element").isVisible();
expect(isVisible).toBe(true);
}).toPass({ timeout: 10000 });
// 3. Check actual value
const text = await page.locator("#element").textContent();
console.log("Actual text:", text);
"Test is flaky" (passes sometimes, fails sometimes)
Solutions:
# 1. Run test multiple times
npx playwright test --repeat-each=5
# 2. Increase retries in playwright.config.ts
retries: 3
# 3. Disable parallel execution
fullyParallel: false
workers: 1
Common Causes:
- Race conditions
- Network timing variations
- Database state not reset
- Previous test state leaking
"Console errors in test"
Symptoms: Test reports console errors
Solutions:
// 1. Filter expected errors
const errors: string[] = [];
page.on("console", (msg) => {
if (msg.type() === "error") {
errors.push(msg.text());
}
});
// After test
const filteredErrors = errors.filter(
(err) => !err.includes("net::ERR_BLOCKED_BY_CLIENT"),
);
expect(filteredErrors.length).toBe(0);
// 2. Fix the actual error in the application
Environment Issues
"Port 8080 already in use"
Solutions:
# 1. Kill process using port
lsof -ti:8080 | xargs kill -9
# 2. Use different port
PORT=8081 npx playwright test
# 3. Find and kill manually
ps aux | grep "deno task dev"
kill <PID>
"E2E_TEST not recognized"
Symptoms: Tests don't bypass OAuth
Solution:
// Ensure E2E mode is set in beforeEach
test.beforeEach(async ({ page }) => {
await page.addInitScript(() => {
globalThis.localStorage.setItem("E2E_TEST", "true");
});
});
"Environment variables not set"
Solutions:
# 1. Set in shell
export E2E_TEST=true
export PORT=8080
# 2. Set in command
E2E_TEST=true PORT=8081 npx playwright test
# 3. Set in .env file (loaded by deno)
echo "E2E_TEST=true" > .env
echo "PORT=8080" >> .env
Browser Issues
"Browser not installed"
Symptoms: Error about chromium not installed
Solution:
npx playwright install --with-deps chromium
"Browser crashes during test"
Solutions:
# 1. Update browsers
npx playwright install --force --with-deps chromium
# 2. Clear cache
rm -rf ~/.cache/ms-playwright
# 3. Run in headed mode to see crash
npx playwright test --headed
# 4. Check system resources
free -h # Memory
df -h # Disk space
"Browser window too small"
Solution:
// In playwright.config.ts
use: {
viewport: { width: 1920, height: 1080 },
}
// Or per test
test.use({ viewport: { width: 1920, height: 1080 } });
Network Issues
"Network request failed"
Solutions:
// 1. Wait for network idle
await page.waitForLoadState("networkidle");
// 2. Wait for specific response
await page.waitForResponse("**/api/endpoint");
// 3. Handle timeout
try {
await page.goto("/slow-page", { timeout: 60000 });
} catch (error) {
console.log("Page load timeout, continuing...");
}
"CORS errors"
Symptoms: Browser blocks requests due to CORS
Solution: This is an application issue, not a test issue. Fix CORS in backend:
// Add CORS headers
response.headers.set("Access-Control-Allow-Origin", "*");
"API returns 401/403"
Solutions:
// 1. Ensure E2E headers are set
await page.goto("/api/endpoint", {
headers: {
"x-e2e-user": "landlord",
},
});
// 2. Check user has permission
const response = await page.request.get("/api/protected", {
headers: {
"x-e2e-user": "admin", // Use admin if landlord lacks permission
},
});
Database Issues
"Database connection failed"
Solutions:
# 1. Check database is running
docker ps | grep postgres
# or
psql -h localhost -U postgres -c "SELECT 1;"
# 2. Check connection string
echo $POSTGRES_OPTIONS
# 3. Restart database
docker-compose restart postgres
# 4. Check database exists
psql -h localhost -U postgres -l | grep cyberhybridhub
"Test data conflicts"
Symptoms: Tests interfere with each other's data
Solutions:
// 1. Use unique data (add timestamp)
const timestamp = Date.now();
await page.locator('input[name="title"]').fill(`Test ${timestamp}`);
// 2. Clean up after test
test.afterEach(async ({ page }) => {
await page.request.delete("/api/test-data/cleanup", {
headers: { "x-e2e-user": "admin" },
});
});
// 3. Run tests serially
fullyParallel: false;
workers: 1;
"Migration errors"
Solutions:
# 1. Run migrations
deno task db:push
# 2. Reset database (destructive!)
deno task db:reset
# 3. Check migration status
deno task db:status
Performance Issues
"Tests are too slow"
Solutions:
# 1. Run tests in parallel
npx playwright test --workers=4
# 2. Run only changed tests
npx playwright test --grep="pattern"
# 3. Skip slow tests
test.skip(process.env.CI, "Skipped in CI");
# 4. Use API tests instead of UI
const response = await page.request.get("/api/data");
"Browser uses too much memory"
Solutions:
# 1. Reduce workers
npx playwright test --workers=1
# 2. Close pages after use
await page.close();
# 3. Restart between test runs
npx playwright test --worker=1
"Test startup is slow"
Solutions:
// 1. Reuse browser context
test.beforeAll(async ({ browser }) => {
context = await browser.newContext();
});
// 2. Use storage state (save/load cookies)
await context.storageState({ path: "state.json" });
// 3. Reduce timeout in config
timeout: 30000, // reduce from 60000
CI/CD Issues
"Tests pass locally but fail in CI"
Solutions:
// 1. Increase retries in CI
retries: process.env.CI ? 2 : 0;
// 2. Increase timeouts in CI
timeout: process.env.CI ? 120000 : 60000;
// 3. Disable parallel in CI
fullyParallel: !process.env.CI;
// 4. Wait longer in tests
await page.waitForTimeout(process.env.CI ? 2000 : 1000);
"CI runner out of disk space"
Solutions:
# .github/workflows/e2e-tests.yml
- name: Clean up disk space
run: |
sudo rm -rf /usr/local/lib/android
sudo rm -rf /usr/share/dotnet
df -h
"Artifacts not uploaded"
Solutions:
# Ensure artifact upload step runs even on failure
- name: Upload artifacts
if: always() # Important!
uses: actions/upload-artifact@v4
"Tests timeout in CI"
Solutions:
# Increase job timeout
- name: Run tests
timeout-minutes: 60 # Increase from default 35
run: npx playwright test
Debugging Tips
Enable verbose logging
# Playwright verbose mode
DEBUG=pw:* npx playwright test
# Deno verbose mode
DENO_LOG=INFO npx playwright test
Take screenshots manually
await page.screenshot({
path: "debug-screenshot.png",
fullPage: true,
});
Pause test execution
// Add pause to inspect state
await page.pause();
Log page state
console.log("URL:", page.url());
console.log("Title:", await page.title());
console.log("Content:", await page.content());
Check network requests
page.on("request", (request) => {
console.log("Request:", request.url());
});
page.on("response", (response) => {
console.log("Response:", response.url(), response.status());
});
Getting Help
If none of these solutions work:
- Check Playwright documentation
- Review test output in
test-results/ - Open trace file:
npx playwright show-trace test-results/trace.zip - Run in debug mode:
npx playwright test --debug - Check GitHub issues for similar problems
- Consult E2E_TEST_GUIDE.md
Common Error Messages
| Error | Cause | Solution |
|---|---|---|
Test timeout of 60000ms exceeded |
Test took too long | Increase timeout or optimize test |
Target closed |
Browser crashed | Check system resources, restart browser |
Failed to find element |
Element not in DOM | Use waitForSelector, check selector |
Strict mode violation |
Multiple elements match | Use first() or more specific selector |
net::ERR_CONNECTION_REFUSED |
Server not running | Start dev server, check port |
401 Unauthorized |
Not authenticated | Set E2E headers properly |
404 Not Found |
Route doesn't exist | Check URL, verify route exists |
500 Internal Server Error |
Server error | Check server logs, fix bug |