E2E Testing (Frontend)

E2E Testing (Frontend)

Populaire

End-to-end frontend testing with Playwright. Page Object Model, selectors, fixtures, accessibility audits. Limited E2E coverage currently - area for improvement. Keywords: Playwright, E2E, Page Object Model, POM, data-testid, getByRole, getByLabel, getByText, fixtures, axe-playwright, frontend testing

2.4Kétoiles
513forks
Mis à jour 1/26/2026
SKILL.md
readonlyread-only
name
E2E Testing (Frontend)
description

|

E2E Testing (Frontend)

Note: E2E test coverage is currently limited. This is an area for improvement.

Running Tests

npx playwright install  # First time only
npm run test:e2e

Page Object Model

Create page objects for reusable page interactions:

// e2e/pages/login-page.ts
import { type Page, type Locator, expect } from '@playwright/test';

export class LoginPage {
    readonly page: Page;
    readonly emailInput: Locator;
    readonly passwordInput: Locator;
    readonly submitButton: Locator;
    readonly errorMessage: Locator;

    constructor(page: Page) {
        this.page = page;
        this.emailInput = page.getByLabel('Email');
        this.passwordInput = page.getByLabel('Password');
        this.submitButton = page.getByRole('button', { name: /log in/i });
        this.errorMessage = page.getByRole('alert');
    }

    async goto() {
        await this.page.goto('/login');
    }

    async login(email: string, password: string) {
        await this.emailInput.fill(email);
        await this.passwordInput.fill(password);
        await this.submitButton.click();
    }

    async expectError(message: string) {
        await expect(this.errorMessage).toContainText(message);
    }
}

Using Page Objects in Tests

// e2e/auth/login.spec.ts
import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/login-page';

test.describe('Login', () => {
    test('successful login redirects to dashboard', async ({ page }) => {
        const loginPage = new LoginPage(page);

        await loginPage.goto();
        await loginPage.login('user@example.com', 'password123');

        await expect(page).toHaveURL('/');
    });

    test('invalid credentials shows error', async ({ page }) => {
        const loginPage = new LoginPage(page);

        await loginPage.goto();
        await loginPage.login('wrong@example.com', 'wrongpassword');

        await loginPage.expectError('Invalid email or password');
    });
});

Selector Priority

  1. Semantic selectors first:

    page.getByRole('button', { name: /submit/i });
    page.getByLabel('Email address');
    page.getByText('Welcome back');
    
  2. Fallback to test IDs:

    page.getByTestId('stack-trace');
    
  3. Avoid implementation details:

    // ❌ Avoid CSS classes and IDs
    page.locator('.btn-primary');
    

Backend Data Setup

E2E tests run against the full Aspire stack. The backend uses the same AppWebHostFactory infrastructure from backend-testing.

For tests requiring specific data, consider:

  1. API calls in beforeEach — Use Playwright's request context to set up data
  2. Test-specific endpoints — Create /api/test/* endpoints for test data management
  3. Database seeding — Seed required data before test runs
  4. Aspire orchestration — Tests start with Elasticsearch and Redis pre-configured
test.beforeEach(async ({ request }) => {
    // Set up test data via API
    await request.post('/api/test/seed', {
        data: { scenario: 'events-with-errors' }
    });
});

test.afterEach(async ({ request }) => {
    await request.delete('/api/test/cleanup');
});

Note: Backend services use in-memory implementations during tests. See AppWebHostFactory for how test infrastructure is configured.

Accessibility Audits

import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';

test('login page has no accessibility violations', async ({ page }) => {
    await page.goto('/login');

    const results = await new AxeBuilder({ page }).analyze();
    expect(results.violations).toEqual([]);
});

See accessibility for WCAG guidelines.

You Might Also Like

Related Skills

verify

verify

243K

Use when you want to validate changes before committing, or when you need to check all React contribution requirements.

facebook avatarfacebook
Obtenir
test

test

243K

Use when you need to run tests for React core. Supports source, www, stable, and experimental channels.

facebook avatarfacebook
Obtenir

Use when feature flag tests fail, flags need updating, understanding @gate pragmas, debugging channel-specific test failures, or adding new flags to React.

facebook avatarfacebook
Obtenir

Use when adding new error messages to React, or seeing "unknown error code" warnings.

facebook avatarfacebook
Obtenir
flow

flow

243K

Use when you need to run Flow type checking, or when seeing Flow type errors in React code.

facebook avatarfacebook
Obtenir
flags

flags

243K

Use when you need to check feature flag states, compare channels, or debug why a feature behaves differently across release channels.

facebook avatarfacebook
Obtenir