Loading...
Loading...
Use when implementing end-to-end tests, using Playwright or Cypress, testing user journeys, debugging flaky tests, or asking about "E2E testing", "Playwright", "Cypress", "browser testing", "visual regression", "test automation"
npx skill4agent add eyadsibai/ltk e2e-testing// 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'] } },
],
});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();
}
}// 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;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();
});test('homepage looks correct', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot('homepage.png', {
fullPage: true,
maxDiffPixels: 100,
});
});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([]);
});data-testid// 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');# Headed mode
npx playwright test --headed
# Debug mode (step through)
npx playwright test --debug
# Trace viewer
npx playwright show-trace trace.zip