← スキル一覧に戻る

webapp-testing
by Mohamedgad1983
application make to managment for family Shaael
⭐ 0🍴 0📅 2026年1月25日
SKILL.md
name: webapp-testing description: Test local web applications using Playwright for UI verification, debugging, screenshot capture, and end-to-end testing. Use when testing web apps, verifying UI behavior, or capturing screenshots of running applications.
Webapp Testing Skill
Purpose
Test local and deployed web applications using Playwright for comprehensive UI verification, debugging, and automated testing.
Setup
Install Playwright
npm init playwright@latest
# or
pnpm create playwright
Project Structure
tests/
├── e2e/
│ ├── auth.spec.ts
│ ├── dashboard.spec.ts
│ └── orders.spec.ts
├── fixtures/
│ └── test-data.ts
└── playwright.config.ts
Configuration
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests/e2e',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
{ name: 'mobile', use: { ...devices['iPhone 14'] } },
],
webServer: {
command: 'npm run dev',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
},
});
Test Patterns
Authentication Tests
import { test, expect } from '@playwright/test';
test.describe('Authentication', () => {
test('should login successfully', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Password').fill('password123');
await page.getByRole('button', { name: 'Sign In' }).click();
await expect(page).toHaveURL('/dashboard');
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
});
test('should show error for invalid credentials', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('invalid@example.com');
await page.getByLabel('Password').fill('wrongpassword');
await page.getByRole('button', { name: 'Sign In' }).click();
await expect(page.getByText('Invalid credentials')).toBeVisible();
});
test('should logout successfully', async ({ page }) => {
// Login first
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Password').fill('password123');
await page.getByRole('button', { name: 'Sign In' }).click();
// Logout
await page.getByRole('button', { name: 'Logout' }).click();
await expect(page).toHaveURL('/login');
});
});
Dashboard Tests
test.describe('Dashboard', () => {
test.beforeEach(async ({ page }) => {
// Login before each test
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Password').fill('password123');
await page.getByRole('button', { name: 'Sign In' }).click();
});
test('should display stats cards', async ({ page }) => {
await expect(page.getByTestId('stats-card-sales')).toBeVisible();
await expect(page.getByTestId('stats-card-orders')).toBeVisible();
await expect(page.getByTestId('stats-card-customers')).toBeVisible();
});
test('should filter data by date range', async ({ page }) => {
await page.getByRole('button', { name: 'Date Range' }).click();
await page.getByRole('option', { name: 'Last 7 days' }).click();
// Wait for data to reload
await page.waitForResponse(resp => resp.url().includes('/api/stats'));
await expect(page.getByTestId('stats-card-sales')).toContainText('$');
});
test('should navigate to orders page', async ({ page }) => {
await page.getByRole('link', { name: 'Orders' }).click();
await expect(page).toHaveURL('/orders');
});
});
Form Tests
test.describe('Order Form', () => {
test('should create a new order', async ({ page }) => {
await page.goto('/orders/new');
// Fill form
await page.getByLabel('Customer Name').fill('John Doe');
await page.getByLabel('Phone').fill('+1234567890');
await page.getByRole('combobox', { name: 'Product' }).click();
await page.getByRole('option', { name: 'Pizza Margherita' }).click();
await page.getByLabel('Quantity').fill('2');
// Submit
await page.getByRole('button', { name: 'Create Order' }).click();
// Verify success
await expect(page.getByText('Order created successfully')).toBeVisible();
});
test('should validate required fields', async ({ page }) => {
await page.goto('/orders/new');
await page.getByRole('button', { name: 'Create Order' }).click();
await expect(page.getByText('Customer name is required')).toBeVisible();
});
});
Table Tests
test.describe('Orders Table', () => {
test('should sort by column', async ({ page }) => {
await page.goto('/orders');
// Click on Date column to sort
await page.getByRole('columnheader', { name: 'Date' }).click();
// Verify sort indicator
await expect(page.getByRole('columnheader', { name: 'Date' }))
.toHaveAttribute('aria-sort', 'ascending');
});
test('should paginate results', async ({ page }) => {
await page.goto('/orders');
await page.getByRole('button', { name: 'Next' }).click();
await expect(page.getByText('Page 2')).toBeVisible();
});
test('should search orders', async ({ page }) => {
await page.goto('/orders');
await page.getByPlaceholder('Search orders...').fill('ORD-001');
await page.keyboard.press('Enter');
await expect(page.getByText('ORD-001')).toBeVisible();
});
});
Screenshot Capture
test('capture dashboard screenshot', async ({ page }) => {
await page.goto('/dashboard');
await page.waitForLoadState('networkidle');
// Full page screenshot
await page.screenshot({
path: 'screenshots/dashboard-full.png',
fullPage: true
});
// Element screenshot
await page.getByTestId('sales-chart').screenshot({
path: 'screenshots/sales-chart.png'
});
});
Visual Regression
test('visual regression - dashboard', async ({ page }) => {
await page.goto('/dashboard');
await expect(page).toHaveScreenshot('dashboard.png', {
maxDiffPixels: 100,
});
});
Mobile Testing
test.describe('Mobile', () => {
test.use({ viewport: { width: 375, height: 667 } });
test('should show mobile menu', async ({ page }) => {
await page.goto('/dashboard');
await page.getByRole('button', { name: 'Menu' }).click();
await expect(page.getByRole('navigation')).toBeVisible();
});
});
API Mocking
test('should handle API errors gracefully', async ({ page }) => {
// Mock API to return error
await page.route('**/api/orders', route => {
route.fulfill({
status: 500,
body: JSON.stringify({ error: 'Server error' }),
});
});
await page.goto('/orders');
await expect(page.getByText('Failed to load orders')).toBeVisible();
});
Running Tests
# Run all tests
npx playwright test
# Run specific test file
npx playwright test tests/e2e/dashboard.spec.ts
# Run in headed mode (see browser)
npx playwright test --headed
# Run with UI mode
npx playwright test --ui
# Generate report
npx playwright show-report
Instructions
- Identify test scenarios: What user flows need testing?
- Set up test fixtures: Create reusable login, data setup
- Write tests: Use page object pattern for maintainability
- Add screenshots: Capture visual state for debugging
- Run in CI: Add to GitHub Actions or similar
- Review report: Analyze failures and fix
スコア
総合スコア
50/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
レビュー
💬
レビュー機能は近日公開予定です