Claude Code Plugins

Community-maintained marketplace

Feedback

Runs Playwright E2E tests with smart targeting by app and feature, supports multiple environments (local/staging/production), and can generate new E2E test files. This skill should be used when running E2E tests, generating test files for new features, or verifying application functionality end-to-end.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name test-e2e
description Runs Playwright E2E tests with smart targeting by app and feature, supports multiple environments (local/staging/production), and can generate new E2E test files. This skill should be used when running E2E tests, generating test files for new features, or verifying application functionality end-to-end.

Test E2E

This skill provides a smart E2E test runner with targeting by app/feature and the ability to generate new test files for uncovered areas (especially Creator app).

When to Use This Skill

  • Running E2E tests before deployment
  • Testing specific features in isolation
  • Generating new E2E tests for Creator app
  • Verifying staging/production deployments
  • Debugging test failures

Current Test Coverage

Dashboard App (3 test files)

  • auth.e2e.ts - Authentication flows (signup, signin, protected routes, OAuth)
  • comps.e2e.ts - Comps navigator functionality
  • trial.e2e.ts - Trial mode features

Creator App (0 test files)

No E2E tests exist - Use --generate to create tests

Website App (0 test files)

Marketing pages, minimal testing needed

Commands

Running Tests

/test-e2e                                # Run all tests
/test-e2e dashboard                      # Run dashboard tests only
/test-e2e dashboard auth                 # Run dashboard auth tests
/test-e2e creator                        # Run creator tests (if any exist)
/test-e2e --staging                      # Run against staging environment
/test-e2e --production                   # Run against production (read-only tests)
/test-e2e --ui                           # Open Playwright UI mode
/test-e2e --debug                        # Run in headed debug mode

Generating Tests

/test-e2e --generate creator auth        # Generate creator auth tests
/test-e2e --generate creator titles      # Generate creator title management tests
/test-e2e --generate creator profile     # Generate creator profile tests
/test-e2e --generate dashboard mandates  # Generate mandate search tests

Test Running Workflow

Step 1: Environment Setup

Configure test environment:

# Local (default)
export TEST_ENV=local
export BASE_URL=http://localhost:8081  # or 8083 for creator

# Staging
export TEST_ENV=staging
export BASE_URL=https://dashboard-staging.kstorybridge.com

# Production (read-only tests only!)
export TEST_ENV=production
export BASE_URL=https://dashboard.kstorybridge.com

Step 2: Start Dev Server (for local)

If testing locally, ensure dev server is running:

# For dashboard tests
npm run dev:dashboard

# For creator tests
npm run dev:creator

Or use Playwright's webServer config (auto-starts).

Step 3: Run Tests

# All tests
npm run test:e2e

# Specific test file
npx playwright test auth.e2e.ts

# Specific test by name
npx playwright test -g "should show validation errors"

# With UI
npm run test:e2e:ui

# With debugging
npm run test:e2e:debug

Step 4: Analyze Results

# Show HTML report
npm run test:e2e:report

# View test artifacts
ls test-results/
ls playwright-report/

Test Generation Workflow

Step 1: Identify Test Scope

Determine what to test:

App Feature Priority Complexity
Creator Auth (signup/signin) HIGH Medium
Creator Title CRUD HIGH High
Creator Profile editing MEDIUM Low
Creator OAuth MEDIUM Medium
Dashboard Mandate search HIGH Medium
Dashboard AI chatbot LOW High (flaky)

Step 2: Generate Test File

Create test file from template:

# Create test directory if needed
mkdir -p apps/creator/e2e

# Generate file (using template)
# See templates/auth.template.ts for structure

Step 3: Customize Tests

Adjust selectors and assertions for specific app:

// Creator app uses different routes
await page.goto('/signin');  // Not /buyers/signin

// Creator app has different form fields
await page.getByLabel(/pen name/i).fill('Test Author');

Step 4: Run and Verify

# Run new tests
npx playwright test apps/creator/e2e/auth.e2e.ts

# Debug if failures
npx playwright test --debug apps/creator/e2e/auth.e2e.ts

Test Patterns

Authentication Tests

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

test.describe('Creator Auth', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/signup');
  });

  test('should show signup form', async ({ page }) => {
    await expect(page.getByRole('heading', { name: /create.*account/i })).toBeVisible();
    await expect(page.getByLabel(/email/i)).toBeVisible();
    await expect(page.getByLabel(/password/i)).toBeVisible();
  });

  test('should validate required fields', async ({ page }) => {
    await page.getByRole('button', { name: /create account/i }).click();
    await expect(page.getByText(/required/i)).toBeVisible();
  });

  test('should redirect to home after signup', async ({ page }) => {
    // Fill form
    await page.getByLabel(/email/i).fill('test@example.com');
    await page.getByLabel(/password/i).fill('Password123!');
    // ... fill other fields

    await page.getByRole('button', { name: /create account/i }).click();

    // Wait for redirect
    await expect(page).toHaveURL('/home');
  });
});

Protected Route Tests

test.describe('Protected Routes', () => {
  test('should redirect unauthenticated users to signin', async ({ page }) => {
    await page.goto('/home');
    await expect(page).toHaveURL('/signin');
  });

  test('should allow authenticated users to access protected routes', async ({ page }) => {
    // Login first
    await page.goto('/signin');
    await page.getByLabel(/email/i).fill('test@example.com');
    await page.getByLabel(/password/i).fill('Password123!');
    await page.getByRole('button', { name: /sign in/i }).click();

    // Access protected route
    await page.goto('/home');
    await expect(page).toHaveURL('/home');
  });
});

CRUD Operation Tests

test.describe('Title Management', () => {
  test.beforeEach(async ({ page }) => {
    // Login as creator
    await loginAsCreator(page);
  });

  test('should create a new title', async ({ page }) => {
    await page.goto('/titles/new');

    await page.getByLabel(/title name/i).fill('Test Title');
    await page.getByLabel(/synopsis/i).fill('A test synopsis...');
    // ... fill other fields

    await page.getByRole('button', { name: /save/i }).click();

    await expect(page.getByText(/title created/i)).toBeVisible();
  });

  test('should edit an existing title', async ({ page }) => {
    await page.goto('/titles');
    await page.getByText('Test Title').click();
    await page.getByRole('button', { name: /edit/i }).click();

    await page.getByLabel(/title name/i).fill('Updated Title');
    await page.getByRole('button', { name: /save/i }).click();

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

  test('should delete a title', async ({ page }) => {
    await page.goto('/titles');
    await page.getByText('Test Title').click();
    await page.getByRole('button', { name: /delete/i }).click();
    await page.getByRole('button', { name: /confirm/i }).click();

    await expect(page.getByText('Test Title')).not.toBeVisible();
  });
});

Environment-Specific Testing

Staging Tests

Run tests against staging environment:

TEST_ENV=staging npm run test:e2e

Considerations:

  • Use test accounts (not production data)
  • Tests may take longer (network latency)
  • Some tests may need adjustment for staging data

Production Tests

Run read-only tests against production:

TEST_ENV=production npm run test:e2e:production

CRITICAL: Production tests must be READ-ONLY:

  • NO signup tests (creates real accounts)
  • NO data modification tests
  • Only test public pages and read operations

Safe production tests:

  • Page load verification
  • Public route accessibility
  • Static content presence

Test Reports

Console Output

Running E2E tests...

Dashboard Tests
  auth.e2e.ts
    ✓ should show signup form (1.2s)
    ✓ should validate required fields (0.8s)
    ✓ should redirect to signin for protected routes (0.5s)
    ✗ should complete OAuth flow (timeout)

  comps.e2e.ts
    ✓ should show comps navigator (1.5s)
    ✓ should search for comps (2.3s)

Summary
  Tests: 5 passed, 1 failed
  Duration: 8.3s

Failed Tests:
  - auth.e2e.ts: should complete OAuth flow
    Error: Timeout waiting for OAuth callback

HTML Report

After test run:

npm run test:e2e:report
# Opens browser with detailed report

Slack Notification

{
  "text": "E2E Test Results",
  "attachments": [
    {
      "color": "warning",
      "fields": [
        {"title": "Passed", "value": "5", "short": true},
        {"title": "Failed", "value": "1", "short": true},
        {"title": "Duration", "value": "8.3s", "short": true},
        {"title": "Environment", "value": "local", "short": true}
      ]
    }
  ]
}

Debugging Tests

Interactive Mode

# Open Playwright UI
npm run test:e2e:ui

# Run specific test in debug mode
npx playwright test -g "should show signup form" --debug

Trace Viewer

# Enable trace for all tests
npx playwright test --trace on

# View trace
npx playwright show-trace test-results/auth-should-show-signup-form/trace.zip

Screenshots and Videos

Test artifacts are saved automatically on failure:

  • test-results/[test-name]/screenshot.png
  • test-results/[test-name]/video.webm

Tips

  • Flaky tests: Add test.retry(2) for network-dependent tests
  • Slow tests: Use test.slow() for long operations
  • Test isolation: Each test should start with clean state
  • Selectors: Prefer getByRole, getByLabel, getByText over CSS selectors
  • Timeouts: Increase for slow operations with { timeout: 10000 }
  • Skip: Use test.skip() for temporarily broken tests

Test Helpers

Create shared helpers in tests/helpers/:

// tests/helpers/auth.ts
export async function loginAsCreator(page: Page) {
  await page.goto('/signin');
  await page.getByLabel(/email/i).fill(process.env.TEST_CREATOR_EMAIL!);
  await page.getByLabel(/password/i).fill(process.env.TEST_CREATOR_PASSWORD!);
  await page.getByRole('button', { name: /sign in/i }).click();
  await expect(page).toHaveURL('/home');
}

export async function loginAsBuyer(page: Page) {
  await page.goto('/buyers/signin');
  await page.getByLabel(/email/i).fill(process.env.TEST_BUYER_EMAIL!);
  await page.getByLabel(/password/i).fill(process.env.TEST_BUYER_PASSWORD!);
  await page.getByRole('button', { name: /sign in/i }).click();
  await expect(page).toHaveURL('/buyers/home');
}

Related Skills

  • /deploy-staging - Deploy to staging before running tests
  • /pr-production - Create production PR after tests pass
  • /health-check - Quick verification of app health