Files
michaelschiemer/tests/e2e/README.md
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

12 KiB

E2E Tests with Playwright

End-to-end testing infrastructure for the Custom PHP Framework using Playwright.

Overview

Comprehensive browser-based E2E tests for:

  • Critical User Journeys - Homepage, authentication, core workflows
  • LiveComponents Functionality - Real-time updates, form validation, fragment rendering
  • Integration Scenarios - Cross-browser compatibility, performance, security

Test Coverage

Critical Paths (critical-paths/)

Homepage Tests (critical-paths/homepage.spec.ts)

  • Page load and accessibility
  • Valid HTML structure and meta tags
  • Navigation functionality
  • JavaScript error detection
  • Security headers verification
  • Responsive design (mobile viewport)
  • ARIA landmarks and accessibility
  • CSS and asset loading

LiveComponents Tests (live-components/)

Form Validation (live-components/form-validation.spec.ts)

  • Real-time validation error display
  • Email format validation
  • Validation error clearing
  • Submit prevention with errors
  • Required field handling
  • Max length validation
  • Character counter functionality

Real-time Updates (live-components/real-time-updates.spec.ts)

  • SSE (Server-Sent Events) connections
  • HTMX request handling
  • DOM updates without page reload
  • Loading states during updates
  • Form data preservation during partial updates
  • WebSocket connections (if present)
  • Connection error handling

Legacy LiveComponents Tests

Fragment Rendering Tests (livecomponents/fragment-rendering.spec.js)

Basic Functionality:

  • Single fragment patching without full re-render
  • Multiple fragment updates simultaneously
  • Nested fragment updates
  • Fallback to full render when fragments not specified

State Preservation:

  • Focus state preservation during fragment updates
  • Scroll position preservation
  • Selection range preservation in text inputs
  • Event listener preservation on updated elements

Performance:

  • Fragment rendering speed vs full HTML rendering
  • Network payload size reduction (fragment vs full)
  • Batch update optimization
  • Rapid successive updates handling

Edge Cases:

  • Empty fragments
  • Very large fragments (1000+ items)
  • Special characters in fragment content
  • Whitespace and formatting changes
  • Data attribute updates
  • Missing fragment error handling

Prerequisites

System Dependencies

Playwright requires certain system libraries. Install them with:

# Option 1: Using Playwright's installer (recommended)
sudo npx playwright install-deps

# Option 2: Using apt directly
sudo apt-get install \
    libatk1.0-0 \
    libatk-bridge2.0-0 \
    libcups2 \
    libxkbcommon0 \
    libatspi2.0-0 \
    libxcomposite1 \
    libxdamage1 \
    libxfixes3 \
    libxrandr2 \
    libgbm1 \
    libcairo2 \
    libpango-1.0-0 \
    libasound2

Node.js Dependencies

Install Playwright and browsers:

# Install Playwright package (already done via package.json)
npm install

# Install browser binaries
npx playwright install chromium  # Chromium only
npx playwright install           # All browsers (Chromium, Firefox, WebKit)

Development Server

E2E tests require the local development server to be running:

# Start Docker containers and development server
make up

# Verify server is accessible
curl -k https://localhost

Running Tests

All E2E Tests

# Run all E2E tests headless
npm run test:e2e

# Run with UI mode (interactive)
npm run test:e2e:ui

# Run with headed browsers (see browser windows)
npm run test:e2e:headed

# Run with debug mode (step through tests)
npm run test:e2e:debug

Specific Test Suites

# Critical path tests only
npm run test:e2e:critical

# LiveComponents tests only
npm run test:e2e:livecomponents

# Specific test files
npm run test:e2e:homepage
npm run test:e2e:validation
npm run test:e2e:realtime

# Legacy fragment tests
npx playwright test livecomponents/fragment-rendering.spec.js

Filtering Tests

# Run specific test by title
npx playwright test --grep "should patch single fragment"

# Run tests in specific browser
npx playwright test --project=chromium
npx playwright test --project=firefox
npx playwright test --project=webkit

Test Output and Reports

# Generate HTML report (automatically opens in browser)
npx playwright show-report

# View last test run results
npx playwright show-report playwright-report

Configuration

Playwright Config (playwright.config.js)

Key Settings:

  • Base URL: https://localhost (local development server)
  • Ignore HTTPS Errors: Enabled for local SSL certificates
  • User-Agent: Set to avoid firewall blocking
  • Timeout: 30 seconds per test
  • Retries: 2 retries in CI, 0 locally
  • Workers: Parallel execution (1 in CI, auto locally)

Projects Configured:

  • Chromium (Desktop)
  • Firefox (Desktop)
  • WebKit/Safari (Desktop)
  • Mobile Chrome (Pixel 5)
  • Mobile Safari (iPhone 12)

Reporters:

  • HTML report: playwright-report/index.html
  • List (console output)
  • JSON: playwright-report/results.json

Test Environment

Tests assume the following URLs are accessible:

https://localhost/livecomponents/test/counter
https://localhost/livecomponents/test/shopping-cart
https://localhost/livecomponents/test/form
https://localhost/livecomponents/test/nested-fragments
https://localhost/livecomponents/test/performance
https://localhost/livecomponents/test/long-list
https://localhost/livecomponents/test/data-attributes
https://localhost/livecomponents/test/event-listeners
https://localhost/livecomponents/test/large-fragment
https://localhost/livecomponents/test/special-chars

Note: These test pages may need to be created in the application.

Writing New E2E Tests

Test Structure

import { test, expect } from '@playwright/test';

test.describe('Feature Name', () => {
    test.beforeEach(async ({ page }) => {
        // Navigate to test page
        await page.goto('https://localhost/path/to/test-page');

        // Wait for LiveComponents to initialize
        await page.waitForFunction(() => window.LiveComponents !== undefined);
    });

    test('should do something', async ({ page }) => {
        // Arrange: Set up test state
        const component = page.locator('[data-component-id="component:id"]');

        // Act: Perform actions
        await page.click('[data-action="someAction"]');
        await page.waitForTimeout(100); // Wait for fragment update

        // Assert: Verify results
        const result = await page.textContent('[data-lc-fragment="result"]');
        expect(result).toContain('Expected Value');
    });
});

Best Practices

1. Use Data Attributes for Selectors:

// ✅ Good: Stable selectors
await page.click('[data-action="increment"]');
await page.locator('[data-lc-fragment="counter"]');

// ❌ Bad: Brittle selectors
await page.click('button.btn-primary');
await page.locator('.counter-display');

2. Wait for LiveComponents Initialization:

// Always wait for LiveComponents to be ready
await page.waitForFunction(() => window.LiveComponents !== undefined);

3. Handle Async Updates:

// Wait for network request to complete
await page.waitForResponse(response =>
    response.url().includes('/live-component/') && response.status() === 200
);

// Or use small timeout for fragment updates
await page.waitForTimeout(100);

4. Use Page Object Pattern for Complex Pages:

class ShoppingCartPage {
    constructor(page) {
        this.page = page;
        this.addItemButton = page.locator('[data-action="addItem"]');
        this.cartItems = page.locator('[data-lc-fragment="cart-items"] .cart-item');
        this.cartTotal = page.locator('[data-lc-fragment="cart-total"]');
    }

    async addItem(item) {
        await this.addItemButton.click();
        await this.page.waitForTimeout(100);
    }

    async getItemCount() {
        return await this.cartItems.count();
    }
}

5. Test Cross-Browser Compatibility:

// Use browser-agnostic APIs
const userAgent = await page.evaluate(() => navigator.userAgent);

// Avoid browser-specific features unless testing for them

Debugging Tests

Visual Debugging

# Run with UI mode (recommended)
npm run test:e2e:ui

# Run with headed browsers
npm run test:e2e:headed

# Debug specific test
npm run test:e2e:debug -- --grep "test name"

Screenshots and Videos

Playwright automatically captures:

  • Screenshots: On test failure
  • Videos: Retained on failure
  • Traces: On first retry

View artifacts in test-results/ directory.

Console Logs

// Listen to console messages
page.on('console', msg => console.log('Browser log:', msg.text()));

// Listen to page errors
page.on('pageerror', err => console.error('Page error:', err));

Playwright Inspector

# Step through test with debugger
npx playwright test --debug

# Pause test at specific point
await page.pause(); // Add this in test code

CI/CD Integration

GitHub Actions Example

name: E2E Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install --with-deps chromium

      - name: Start development server
        run: make up

      - name: Run E2E tests
        run: npm run test:e2e

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: playwright-report
          path: playwright-report/

Troubleshooting

Common Issues

1. Server not accessible:

# Verify Docker containers are running
docker ps

# Check server is responding
curl -k https://localhost

# Check firewall/SSL settings

2. Tests timing out:

// Increase timeout for specific test
test('slow operation', async ({ page }) => {
    test.setTimeout(60000); // 60 seconds
    // ...
});

3. Flaky tests:

// Use waitForSelector with state
await page.waitForSelector('[data-lc-fragment="result"]', {
    state: 'visible',
    timeout: 5000
});

// Or wait for network to be idle
await page.waitForLoadState('networkidle');

4. Browser launch errors:

# Install missing dependencies
sudo npx playwright install-deps

# Use specific browser
npx playwright test --project=chromium

Performance Issues

Slow tests:

  • Run fewer browsers: npx playwright test --project=chromium
  • Disable parallel execution: npx playwright test --workers=1
  • Reduce retries: Set retries: 0 in config

High memory usage:

  • Close browsers between test files
  • Limit workers: --workers=2
  • Use headless mode (default)

Test Maintenance

Keeping Tests Updated

  1. Update test pages when components change
  2. Update selectors when HTML structure changes
  3. Add new tests for new features
  4. Remove obsolete tests for removed features
  5. Review flaky tests regularly

Test Quality Metrics

Track these metrics for test health:

  • Pass rate: Should be >95%
  • Flakiness: Retry rate should be <5%
  • Duration: Average test duration <30s
  • Coverage: All critical user flows tested

Resources

Support

For issues or questions about E2E tests:

  1. Check this README
  2. Review existing tests for examples
  3. Check Playwright documentation
  4. Ask in team chat or create GitHub issue