Skip to content
e2e-tests logo

e2e-tests

Create and maintain Playwright E2E tests following project patterns. Use when adding new tests, debugging test failures, or understanding test structure.

mattnigh/skills_collection0installs24stars

SKILL.md

Full skill instructions

E2E Test Creation Skill

This skill helps you write and maintain Playwright end-to-end tests following the established patterns in this codebase.

When to Use This Skill

Invoke this skill when:

  • Creating a new e2e test file
  • Adding tests to an existing test file
  • Debugging flaky or failing tests
  • User asks about e2e test patterns or best practices
  • User wants to test a new feature end-to-end

Framework Overview

PropertyValue
FrameworkPlaywright (@playwright/​test v1.56.1)
Location/​e2e/ directory
Configplaywright.config.ts
Run commandnpm run test:e2e
Total tests80+ tests across 13 files

Two Authentication Modes

The project uses a two-tier authentication system:

1. Authenticated Tests (Default - Most Tests)

  • Run with project chromium-authenticated
  • Use cached auth state from .auth/​student.json
  • No login needed - tests start authenticated
  • Excludes: auth.spec.ts, registration.spec.ts

2. Unauthenticated Tests

  • Run with project chromium-unauthenticated
  • For testing login/​registration flows
  • Files: auth.spec.ts, registration.spec.ts
  • Must handle cookie banner dismissal

File Naming Conventions

TypePatternExample
Test file{feature}.spec.tspractice.spec.ts
Setup file*.setup.tsauth.setup.ts
Helper filehelpers/​{name}.tshelpers/​auth.ts

Creating a New Test File

Step 1: Determine Authentication Mode

Ask: Does this test need to start from a logged-out state?

  • YES → Use unauthenticated pattern, add to testMatch in config
  • NO → Use authenticated pattern (default)

Step 2: Create File Structure

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

test.describe('Feature Name', () => {
  // Authentication handled via storageState in playwright.config.ts
  // No beforeEach login needed for authenticated tests

  test('should describe expected behavior', async ({ page }) => {
    await page.goto('/​feature-path', { waitUntil: 'domcontentloaded' });

    // Test implementation
  });
});

Step 3: Apply Selector Strategy

Priority order:

  1. data-testid attributes (most reliable)
  2. getByRole (semantic, accessible)
  3. getByText (user-visible text)
  4. CSS selectors (last resort)

→ See selectors-guide.md for detailed guidance.

Step 4: Apply Wait Patterns

NEVER use waitForTimeout for synchronization.

Use event-based waits:

// Wait for element visibility
await expect(element).toBeVisible({ timeout: 5000 });

// Wait for URL change
await page.waitForURL(/\/​dashboard/, { timeout: 5000 });

// Wait for network
await page.waitForLoadState('networkidle');

→ See anti-patterns.md for common mistakes.


Selector Strategy Quick Reference

// PREFERRED: data-testid
await page.getByTestId('mode-zen').click();

// GOOD: Role-based
await page.getByRole('button', { name: /​Siguiente/​i }).click();
await page.getByRole('heading', { name: /​Dashboard/​i });

// ACCEPTABLE: Text-based
await page.getByText(/​Práctica PAES/​i).toBeVisible();

// LAST RESORT: CSS selectors
await page.locator('.specific-class').click();

→ See selectors-guide.md for comprehensive guidance.


Test Configuration Quick Reference

// Extend timeout for long tests
test('long flow', async ({ page }) => {
  test.setTimeout(60000); // 60 seconds
});

// Retry flaky tests
test('registration', { retries: 2 }, async ({ page }) => {});

// Scope auth to describe block
test.describe('Admin features', () => {
  test.use({ storageState: '.auth/​admin.json' });
});

// Skip in CI
test.skip(process.env.CI === 'true', 'Local only');

→ See advanced-patterns.md for complete configuration options.


Common Test Patterns

Pattern 1: Navigation Test

test('should navigate to feature page', async ({ page }) => {
  await page.goto('/​feature', { waitUntil: 'domcontentloaded' });

  await expect(page.getByRole('heading', { name: /​Feature Title/​i })).toBeVisible();
  await expect(page.getByTestId('main-content')).toBeVisible();
});

Pattern 2: Form Interaction

test('should submit form successfully', async ({ page }) => {
  await page.goto('/​form-page', { waitUntil: 'domcontentloaded' });

  await page.getByTestId('input-field').fill('value');
  await page.getByRole('button', { name: /​Submit/​i }).click();

  await expect(page.getByText(/​Success/​i)).toBeVisible();
});

Pattern 3: API Interception

test('should handle API errors gracefully', async ({ page }) => {
  await page.route('**/​api/​endpoint', route => {
    route.fulfill({
      status: 500,
      contentType: 'application/​json',
      body: JSON.stringify({ error: 'Server error' }),
    });
  });

  await page.goto('/​page');
  await expect(page.getByText(/​error/​i)).toBeVisible();
});

Pattern 4: Cookie Banner Dismissal

// For unauthenticated tests - add at start of test or beforeEach
await page.evaluate(() => {
  localStorage.setItem('cookie-consent', 'accepted');
});

→ See templates.md for 12 complete copy-paste templates. → See advanced-patterns.md for resilience, loops, and advanced waits.


Quality Gates

Before completing any test file:

  • Uses data-testid for critical elements
  • No waitForTimeout for synchronization (only for animations)
  • All waits are event-based
  • Test names start with "should"
  • Uses test.describe() for grouping
  • Handles both success and error cases
  • Cookie banner dismissed if needed (unauthenticated tests)
  • No hardcoded credentials (use test users from db-setup)

Running Tests

# Run all e2e tests
npm run test:e2e

# Run specific test file
npx playwright test e2e/​practice.spec.ts

# Run with UI mode (interactive)
npx playwright test --ui

# Run with headed browser (visible)
npx playwright test --headed

# Debug a specific test
npx playwright test --debug -g "test name"

# Run tests matching pattern
npx playwright test -g "should login"

Test Categories

Current test file organization:

CategoryFilesPurpose
Authauth.spec.ts, registration.spec.tsLogin, registration flows
Practicepractice.spec.ts, adaptive-practice.spec.tsQuiz modes (Zen, Rapid Fire)
Progressprogress.spec.tsAnalytics, history, skills
Profileprofile.spec.tsUser profile, stats
Curriculumcurriculum.spec.tsM1/​M2 curriculum pages
Lessonsmini-lesson-*.spec.tsInteractive mini-lessons
Subscriptionsubscription-trial.spec.tsPricing, trials, paywalls
Livelive-practice.spec.tsReal-time sessions
AIai-tutor.spec.tsAI tutor functionality
Knowledgeknowledge-declarations.spec.tsSkill declarations

Test Credentials

RoleEmailPassword
Student[email protected]StudentTest123!
Admin[email protected]AdminTest123!

→ See helpers-reference.md for complete helper documentation.


Related Files

  • → advanced-patterns.md - Test config, waits, assertions, resilience patterns
  • → anti-patterns.md - Common mistakes to avoid
  • → templates.md - 12 copy-paste test templates
  • → selectors-guide.md - Selector strategy deep-dive
  • → helpers-reference.md - Auth and DB helper documentation