# E2E Test Troubleshooting Quick reference for common E2E test issues and solutions. ## Table of Contents - [Test Failures](#test-failures) - [Environment Issues](#environment-issues) - [Browser Issues](#browser-issues) - [Network Issues](#network-issues) - [Database Issues](#database-issues) - [Performance Issues](#performance-issues) - [CI/CD Issues](#cicd-issues) ## Test Failures ### "Element not found" or "Timeout" **Symptoms**: Test fails with timeout waiting for element **Solutions**: ```typescript // 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**: ```typescript // 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**: ```bash # 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**: ```typescript // 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**: ```bash # 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 ``` ### "E2E_TEST not recognized" **Symptoms**: Tests don't bypass OAuth **Solution**: ```typescript // 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**: ```bash # 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**: ```bash npx playwright install --with-deps chromium ``` ### "Browser crashes during test" **Solutions**: ```bash # 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**: ```typescript // 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**: ```typescript // 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: ```typescript // Add CORS headers response.headers.set("Access-Control-Allow-Origin", "*"); ``` ### "API returns 401/403" **Solutions**: ```typescript // 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**: ```bash # 1. Check local PostgreSQL is reachable psql -h localhost -U postgres -c "SELECT 1;" # 2. Check connection string echo $POSTGRES_OPTIONS # 3. Restart local PostgreSQL service sudo systemctl restart postgresql # 4. Check database exists psql -h localhost -U postgres -l | grep cyberhybridhub ``` ### "Test data conflicts" **Symptoms**: Tests interfere with each other's data **Solutions**: ```typescript // 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**: ```bash # 1. Run migrations deno task db:push # 2. Apply migrations from drizzle folder deno task db:migrate ``` ## Performance Issues ### "Tests are too slow" **Solutions**: ```bash # 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**: ```bash # 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**: ```typescript // 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**: ```typescript // 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**: ```yaml # .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**: ```yaml # Ensure artifact upload step runs even on failure - name: Upload artifacts if: always() # Important! uses: actions/upload-artifact@v4 ``` ### "Tests timeout in CI" **Solutions**: ```yaml # Increase job timeout - name: Run tests timeout-minutes: 60 # Increase from default 35 run: npx playwright test ``` ## Debugging Tips ### Enable verbose logging ```bash # Playwright verbose mode DEBUG=pw:* npx playwright test # Deno verbose mode DENO_LOG=INFO npx playwright test ``` ### Take screenshots manually ```typescript await page.screenshot({ path: "debug-screenshot.png", fullPage: true, }); ``` ### Pause test execution ```typescript // Add pause to inspect state await page.pause(); ``` ### Log page state ```typescript console.log("URL:", page.url()); console.log("Title:", await page.title()); console.log("Content:", await page.content()); ``` ### Check network requests ```typescript 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: 1. Check [Playwright documentation](https://playwright.dev/docs/debug) 2. Review test output in `test-results/` 3. Open trace file: `npx playwright show-trace test-results/trace.zip` 4. Run in debug mode: `npx playwright test --debug` 5. Check GitHub issues for similar problems 6. Consult [E2E_TEST_GUIDE.md](./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 |