Skip to main content

web-testing

Web testing patterns and best practices using Playwright for automated testing

ソース情報

リポジトリ
code-yeongyu/sisyphus-private
ソースの最終更新活動
2025年10月20日 01:49
検出された SKILL.md の言語
英語
スター
17
フォーク
2

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
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
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る