Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
eyadsibai avatar

E2e Testing

  • 59 installs
  • 7 repo stars
  • Updated January 15, 2026
  • eyadsibai/ltk

Helps with testing & qa tasks.

About

e2e-testing is a Claude Code skill for testing & qa. It helps solo builders move faster with AI-assisted development.

  • e2e-testing
  • Testing & QA
  • AI-coding skill

E2e Testing by the numbers

  • 59 all-time installs (skills.sh)
  • Ranked #1,165 of 2,153 Testing & QA skills by installs in the Skillselion catalog
  • Data as of Jul 30, 2026 (Skillselion catalog sync)
npx skills add https://github.com/eyadsibai/ltk --skill e2e-testing

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs59
repo stars7
Last updatedJanuary 15, 2026
Repositoryeyadsibai/ltk

What it does

Helps with testing & qa tasks.

Files

SKILL.mdMarkdownGitHub ↗

E2E Testing Patterns

Build reliable, fast, and maintainable end-to-end test suites with Playwright and Cypress.

What to Test with E2E

Good for:

  • Critical user journeys (login, checkout, signup)
  • Complex interactions (drag-and-drop, multi-step forms)
  • Cross-browser compatibility
  • Real API integration

Not for:

  • Unit-level logic (use unit tests)
  • API contracts (use integration tests)
  • Edge cases (too slow)

Playwright Configuration

// playwright.config.ts
export default defineConfig({
    testDir: './e2e',
    timeout: 30000,
    fullyParallel: true,
    retries: process.env.CI ? 2 : 0,
    use: {
        baseURL: 'http://localhost:3000',
        trace: 'on-first-retry',
        screenshot: 'only-on-failure',
    },
    projects: [
        { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
        { name: 'mobile', use: { ...devices['iPhone 13'] } },
    ],
});

Page Object Model

export class LoginPage {
    readonly page: Page;
    readonly emailInput: Locator;
    readonly loginButton: Locator;

    constructor(page: Page) {
        this.page = page;
        this.emailInput = page.getByLabel('Email');
        this.loginButton = page.getByRole('button', { name: 'Login' });
    }

    async login(email: string, password: string) {
        await this.emailInput.fill(email);
        await this.page.getByLabel('Password').fill(password);
        await this.loginButton.click();
    }
}

Waiting Strategies

// Bad: Fixed timeouts
await page.waitForTimeout(3000);  // Flaky!

// Good: Wait for conditions
await expect(page.getByText('Welcome')).toBeVisible();
await page.waitForURL('/dashboard');

// Wait for API response
const responsePromise = page.waitForResponse(
    r => r.url().includes('/api/users') && r.status() === 200
);
await page.click('button');
await responsePromise;

Network Mocking

test('displays error when API fails', async ({ page }) => {
    await page.route('**/api/users', route => {
        route.fulfill({
            status: 500,
            body: JSON.stringify({ error: 'Server Error' }),
        });
    });

    await page.goto('/users');
    await expect(page.getByText('Failed to load')).toBeVisible();
});

Visual Regression

test('homepage looks correct', async ({ page }) => {
    await page.goto('/');
    await expect(page).toHaveScreenshot('homepage.png', {
        fullPage: true,
        maxDiffPixels: 100,
    });
});

Accessibility Testing

import AxeBuilder from '@axe-core/playwright';

test('no accessibility violations', async ({ page }) => {
    await page.goto('/');
    const results = await new AxeBuilder({ page }).analyze();
    expect(results.violations).toEqual([]);
});

Best Practices

1. Use Data Attributes: data-testid for stable selectors 2. Test User Behavior: Click, type, see - not implementation 3. Keep Tests Independent: Each test runs in isolation 4. Clean Up Test Data: Create and destroy per test 5. Use Page Objects: Encapsulate page logic 6. Optimize for Speed: Mock when possible, parallel execution

Bad vs Good Selectors

// Bad
cy.get('.btn.btn-primary.submit-button').click();
cy.get('div > form > div:nth-child(2) > input').type('text');

// Good
cy.getByRole('button', { name: 'Submit' }).click();
cy.get('[data-testid="email-input"]').type('user@example.com');

Debugging

# Headed mode
npx playwright test --headed

# Debug mode (step through)
npx playwright test --debug

# Trace viewer
npx playwright show-trace trace.zip

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.