🎯

e2e-test-optimizer

🎯Skill

from d-oit/do-novelist-ai

VibeIndex|
What it does

Optimizes Playwright E2E tests by replacing arbitrary waits with smart waits, enabling parallel test execution, and reducing test flakiness.

πŸ“¦

Part of

d-oit/do-novelist-ai(14 items)

e2e-test-optimizer

Installation

git cloneClone repository
git clone https://github.com/yourusername/novelist-goap-ebook-engine.git
npm runRun npm script
npm run dev
npm runRun npm script
npm run dev # Start Vite dev server (http://localhost:5173)
npm runRun npm script
npm run build # Build for production
npxRun with npx
npx playwright test
πŸ“– Extracted from docs: d-oit/do-novelist-ai
1Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Overview

# E2E Test Optimizer

Quick Start

This skill helps fix three critical E2E test issues:

  1. Anti-pattern removal: Replace arbitrary waitForTimeout with smart waits
  2. Test sharding: Enable parallel test execution in CI
  3. Mock optimization: Reduce mock setup overhead

When to Use

  • E2E tests timing out or failing due to arbitrary waits
  • CI execution time exceeds 10 minutes
  • Need test parallelization for faster feedback
  • Test flakiness from race conditions

Smart Wait Patterns

Navigation Waits

```typescript

// ❌ Arbitrary wait

await page.click('[data-testid="nav-dashboard"]');

await page.waitForTimeout(1000);

// βœ… Wait for specific element

await page.click('[data-testid="nav-dashboard"]');

await expect(page.getByTestId('dashboard-content')).toBeVisible({

timeout: 5000,

});

```

State Transition Waits

```typescript

// ❌ Arbitrary wait after action

await page.getByRole('button', { name: 'Generate' }).click();

await page.waitForTimeout(2000);

// βœ… Wait for loading state completion

await page.getByRole('button', { name: 'Generate' }).click();

await expect(page.getByTestId('loading-spinner')).not.toBeVisible();

await expect(page.getByTestId('result')).toBeVisible();

```

Network Waits

```typescript

// ❌ Arbitrary wait after submit

await page.getByRole('button', { name: 'Save' }).click();

await page.waitForTimeout(1500);

// βœ… Wait for network idle or success message

await page.getByRole('button', { name: 'Save' }).click();

await page.waitForLoadState('networkidle');

// OR

await expect(page.getByText('Saved successfully')).toBeVisible();

```

Test Sharding Setup

Add to .github/workflows/ci.yml:

```yaml

e2e-tests:

name: πŸ§ͺ E2E Tests [Shard ${{ matrix.shard }}/3]

runs-on: ubuntu-latest

timeout-minutes: 30

needs: build-and-test

strategy:

fail-fast: false

matrix:

shard: [1, 2, 3]

steps:

- name: Run Playwright tests

run: pnpm exec playwright test --shard=${{ matrix.shard }}/3

env:

CI: true

```

Expected improvement: 60-65% faster (27 minutes β†’ 9-10 minutes)

Detection Commands

```bash

# Find all waitForTimeout usage

grep -r "waitForTimeout" tests/specs/*.spec.ts

# Count per file

grep -c "waitForTimeout" tests/specs/*.spec.ts

```

Standard Test Structure

```typescript

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

import { setupGeminiMock } from '../utils/mock-ai-gateway';

test.describe('Feature Name', () => {

test.beforeEach(async ({ page }) => {

await setupGeminiMock(page);

await page.goto('/');

await page.waitForLoadState('networkidle');

});

test('should perform action', async ({ page }) => {

// Navigate

await page.getByTestId('nav-target').click();

await expect(page.getByTestId('target-page')).toBeVisible();

// Interact

await page.getByRole('button', { name: 'Action' }).click();

await expect(page.getByTestId('loading')).not.toBeVisible();

// Assert

await expect(page.getByTestId('result')).toBeVisible();

});

});

```

Element Selection Priority

```typescript

// βœ… Best: data-testid (stable, explicit)

await page.getByTestId('project-card');

// βœ… Good: role + name (semantic, accessible)

await page.getByRole('button', { name: 'Create' });

// ⚠️ OK: text (can break with i18n)

await page.getByText('Dashboard');

// ❌ Avoid: CSS selectors (brittle)

await page.locator('.project-card > div.title');

```

Optimization Workflow

Phase 1: Analysis

  1. Scan test files for waitForTimeout
  2. Count occurrences per file
  3. Prioritize files by occurrence count

Phase 2: Fix Anti-Patterns

  1. Start with highest-priority file
  2. Replace each waitForTimeout with smart wait
  3. Run tests after each file: playwright test path/to/file.spec.ts
  4. Commit per-file changes

Phase 3: Implement Sharding

  1. Update CI workflow with matrix strategy
  2. Test locally: playwright test --shard=1/3
  3. Push and monitor all 3 shards in CI

Phase 4: Validation

  1. Verify all tests pass
  2. Confirm execution time < 10 minutes
  3. Check shard balance (Β±2 min variance acceptable)

Common Issues

Tests still timing out after fix

  • Increase timeout on slow operations:

expect(...).toBeVisible({ timeout: 10000 })

Unbalanced shards (one takes much longer)

  • Use --grep to manually distribute heavy tests across shards

Mock setup still slow

  • Implement global browser warm-up (see MOCK-OPTIMIZATION-GUIDE.md in

tests/docs)

Success Criteria

  • Zero waitForTimeout calls in active tests
  • CI execution time < 10 minutes
  • All shards complete within Β±2 minutes of each other
  • 100% test pass rate (no flaky tests)

References

See tests/docs/ for detailed guides:

  • MOCK-OPTIMIZATION-GUIDE.md - Mock performance patterns
  • MOCK-PERFORMANCE-ANALYSIS.md - Optimization results

External documentation:

  • Playwright Best Practices: https://playwright.dev/docs/best-practices
  • Test Sharding: https://playwright.dev/docs/test-sharding