Skip to main content

web-testing

Web testing patterns and best practices using Playwright for automated testing

Informations de source

Dépôt
code-yeongyu/sisyphus-private
Dernière activité de la source
20 octobre 2025 à 01:49
Langue détectée de SKILL.md
anglais
Étoiles
17
Forks
2

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
web-testing
description
Web testing patterns and best practices using Playwright for automated testing
# Web Testing with Playwright This skill covers comprehensive web testing patterns using Playwright, including test structure, assertions, mocking, and best practices for reliable automated testing. ## Test Structure ### Basic Test Organization ```javascript import { test, expect } from '@playwright/test'; test.describe('User Authentication', () => { test.beforeEach(async ({ page }) => { await page.goto('https://example.com/login'); }); test('should login with valid credentials', async ({ page }) => { const username = 'testuser@example.com'; const password = 'SecurePass123'; await page.fill('input[name="email"]', username); await page.fill('input[name="password"]', password); await page.click('button[type="submit"]'); await expect(page).toHaveURL(/.*dashboard/); await expect(page.locator('.welcome-message')).toBeVisible(); }); test('should show error with invalid credentials', async ({ page }) => { await page.fill('input[name="email"]', 'wrong@example.com'); await page.fill('input[name="password"]', 'wrongpass'); await page.click('button[type="submit"]'); await expect(page.locator('.error-message')).toContainText('Invalid credentials'); }); }); ``` ### Test Hooks and Lifecycle ```javascript import { test } from '@playwright/test'; test.describe('E-commerce Checkout', () => { test.beforeAll(async ({ browser }) => { console.log('Setting up test database'); }); test.beforeEach(async ({ page }) => { await page.goto('https://example.com'); await page.fill('input[name="email"]', 'test@example.com'); await page.fill('input[name="password"]', 'password123'); await page.click('button[type="submit"]'); }); test.afterEach(async ({ page }) => { await page.click('[data-testid="clear-cart"]'); }); test.afterAll(async () => { console.log('Cleaning up test database'); }); test('should add item to cart', async ({ page }) => { await page.click('[data-product-id="123"]'); await page.click('button:has-text("Add to Cart")'); await expect(page.locator('.cart-count')).toHaveText('1'); }); }); ``` ### Parameterized Tests ```javascript import { test, expect } from '@playwright/test'; const testData = [ { input: 'john@example.com', expected: true }, { input: 'invalid-email', expected: false }, { input: 'another@test.co.uk', expected: true }, { input: '@nodomain.com', expected: false } ]; testData.forEach(({ input, expected }) => { test(`should validate email: ${input}`, async ({ page }) => { await page.goto('https://example.com/signup'); await page.fill('input[name="email"]', input); await page.click('button[type="submit"]'); if (expected) { await expect(page.locator('.error-message')).not.toBeVisible(); } else { await expect(page.locator('.error-message')).toBeVisible(); } }); }); ``` ### Test Fixtures ```javascript import { test as base, expect } from '@playwright/test'; const test = base.extend({ authenticatedPage: async ({ page }, use) => { await page.goto('https://example.com/login'); await page.fill('input[name="email"]', 'test@example.com'); await page.fill('input[name="password"]', 'password123'); await page.click('button[type="submit"]'); await page.waitForURL('**/dashboard'); await use(page); await page.click('[data-testid="logout"]'); } }); test('should access protected resource', async ({ authenticatedPage }) => { await authenticatedPage.goto('https://example.com/profile'); await expect(authenticatedPage.locator('h1')).toContainText('My Profile'); }); ``` ## Assertions ### Element Visibility Assertions ```javascript import { test, expect } from '@playwright/test'; test('element visibility checks', async ({ page }) => { await page.goto('https://example.com'); await expect(page.locator('.header')).toBeVisible(); await expect(page.locator('.modal')).toBeHidden(); await expect(page.locator('.hidden-div')).toBeAttached(); await expect(page.locator('.removed-element')).not.toBeAttached(); }); ``` ### Text Content Assertions ```javascript test('text content checks', async ({ page }) => { await page.goto('https://example.com'); await expect(page.locator('h1')).toHaveText('Welcome'); await expect(page.locator('.description')).toContainText('product'); await expect(page.locator('.price')).toHaveText(/\$\d+\.\d{2}/); await expect(page.locator('.item-title')).toHaveText([ 'Item 1', 'Item 2', 'Item 3' ]); }); ``` ### Attribute and State Assertions ```javascript test('attribute and state checks', async ({ page }) => { await page.goto('https://example.com/form'); await expect(page.locator('input[name="email"]')).toHaveAttribute('type', 'email'); await expect(page.locator('.button')).toHaveClass(/primary/); await expect(page.locator('.list-item')).toHaveCount(5); await expect(page.locator('input[name="username"]')).toHaveValue('john.doe'); await expect(page.locator('input[type="checkbox"]')).toBeChecked(); await expect(page.locator('input[type="checkbox"]')).not.toBeChecked(); await expect(page.locator('button[type="submit"]')).toBeEnabled(); await expect(page.locator('button.disabled')).toBeDisabled(); await expect(page.locator('input[name="email"]')).toBeEditable(); }); ``` ### URL and Page Assertions ```javascript test('URL and page checks', async ({ page }) => { await page.goto('https://example.com/products'); await expect(page).toHaveURL('https://example.com/products'); await expect(page).toHaveURL(/.*products/); await expect(page).toHaveTitle('Products - Example Store'); await expect(page).toHaveTitle(/Products/); }); ``` ### Custom Assertions ```javascript test('custom assertions', async ({ page }) => { await page.goto('https://example.com/cart'); const cartTotal = await page.locator('.cart-total').textContent(); expect(parseFloat(cartTotal.replace('$', ''))).toBeGreaterThan(0); await expect.soft(page.locator('.item')).toHaveCount(3); await expect.soft(page.locator('.discount-badge')).toBeVisible(); const element = page.locator('.product'); await expect(element).toBeVisible(); await expect(element).toContainText('Special Offer'); await expect(element).toHaveClass('highlighted'); }); ``` ## Mocking ### Network Request Interception ```javascript import { test, expect } from '@playwright/test'; test('mock API response', async ({ page }) => { await page.route('**/api/products', route => { route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify([ { id: 1, name: 'Mocked Product 1', price: 19.99 }, { id: 2, name: 'Mocked Product 2', price: 29.99 } ]) }); }); await page.goto('https://example.com/products'); await expect(page.locator('.product').first()).toContainText('Mocked Product 1'); }); ``` ### Conditional Mocking ```javascript test('conditional network mocking', async ({ page }) => { await page.route('**/api/**', route => { const url = route.request().url(); if (url.includes('/api/slow-endpoint')) { route.fulfill({ status: 200, body: JSON.stringify({ data: 'fast response' }) }); } else if (url.includes('/api/error-prone')) { route.fulfill({ status: 500 }); } else { route.continue(); } }); await page.goto('https://example.com'); }); ``` ### Request Modification ```javascript test('modify outgoing requests', async ({ page }) => { await page.route('**/api/data', route => { const headers = { ...route.request().headers(), 'Authorization': 'Bearer mock-token-123' }; route.continue({ headers }); }); await page.goto('https://example.com/dashboard'); }); ``` ### Response Delays ```javascript test('simulate slow network', async ({ page }) => { await page.route('**/api/products', async route => { await new Promise(resolve => setTimeout(resolve, 3000)); await route.fulfill({ status: 200, body: JSON.stringify({ products: [] }) }); }); await page.goto('https://example.com/products'); await expect(page.locator('.loading-spinner')).toBeVisible(); }); ``` ## Best Practices ### Reliable Selectors ```javascript // GOOD: Use test IDs
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub