← Back to list

browser-testing
by CeamKrier
Browser-based tool to combine and format multiple files for optimal use with AI language models (ChatGPT, Claude, etc.).
⭐ 2🍴 0📅 Jan 17, 2026
SKILL.md
name: browser-testing description: Write browser-based tests using Playwright or similar tools for E2E testing, visual regression, and cross-browser compatibility. Use when adding automated UI tests or validating user flows.
Browser Testing
When to Use This Skill
Use when:
- Writing end-to-end tests
- Testing user workflows
- Validating cross-browser compatibility
- Implementing visual regression tests
Playwright Setup
Installation
pnpm add -D @playwright/test
npx playwright install
playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './e2e',
timeout: 30000,
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: 'http://localhost:5173',
trace: 'on-first-retry',
screenshot: 'only-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 13'] } },
],
webServer: {
command: 'pnpm dev',
url: 'http://localhost:5173',
reuseExistingServer: !process.env.CI,
},
});
Test Patterns
Basic Page Test
import { test, expect } from '@playwright/test';
test('homepage loads correctly', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveTitle(/My App/);
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
});
User Flow Test
test('user can upload and process files', async ({ page }) => {
await page.goto('/');
// Upload file
const fileInput = page.locator('input[type="file"]');
await fileInput.setInputFiles('./test-files/sample.txt');
// Wait for processing
await expect(page.getByText('Processing...')).toBeVisible();
await expect(page.getByText('Processing...')).not.toBeVisible();
// Verify result
await expect(page.getByTestId('file-tree')).toContainText('sample.txt');
});
Form Interaction
test('form submission works', async ({ page }) => {
await page.goto('/settings');
// Fill form
await page.getByLabel('Max file size').fill('64');
await page.getByLabel('Remove empty lines').check();
// Submit
await page.getByRole('button', { name: 'Save' }).click();
// Verify
await expect(page.getByText('Settings saved')).toBeVisible();
});
Locator Strategies
// Preferred: Role-based (accessible)
page.getByRole('button', { name: 'Submit' });
page.getByRole('textbox', { name: 'Email' });
page.getByRole('checkbox', { name: 'Remember me' });
// Label-based
page.getByLabel('Password');
// Text-based
page.getByText('Welcome');
page.getByText(/welcome/i); // Case insensitive
// Test ID (when others don't work)
page.getByTestId('submit-button');
// CSS selector (last resort)
page.locator('.submit-btn');
Assertions
// Visibility
await expect(element).toBeVisible();
await expect(element).toBeHidden();
// Content
await expect(element).toHaveText('Hello');
await expect(element).toContainText('Hello');
// Attributes
await expect(element).toHaveAttribute('disabled');
await expect(element).toHaveClass(/active/);
// Count
await expect(page.getByRole('listitem')).toHaveCount(5);
// URL
await expect(page).toHaveURL('/dashboard');
Visual Regression
test('component looks correct', async ({ page }) => {
await page.goto('/component-demo');
// Full page screenshot
await expect(page).toHaveScreenshot('full-page.png');
// Element screenshot
const card = page.getByTestId('card');
await expect(card).toHaveScreenshot('card.png');
});
Testing Patterns
Page Object Model
// pages/HomePage.ts
export class HomePage {
constructor(private page: Page) {}
async goto() {
await this.page.goto('/');
}
async uploadFile(filePath: string) {
await this.page.locator('input[type="file"]').setInputFiles(filePath);
}
get fileTree() {
return this.page.getByTestId('file-tree');
}
}
// tests/upload.spec.ts
test('upload flow', async ({ page }) => {
const homePage = new HomePage(page);
await homePage.goto();
await homePage.uploadFile('./test.txt');
await expect(homePage.fileTree).toBeVisible();
});
Fixtures
// fixtures.ts
import { test as base } from '@playwright/test';
export const test = base.extend<{ loggedInPage: Page }>({
loggedInPage: async ({ page }, use) => {
await page.goto('/login');
await page.fill('[name="email"]', 'test@example.com');
await page.fill('[name="password"]', 'password');
await page.click('button[type="submit"]');
await page.waitForURL('/dashboard');
await use(page);
},
});
Running Tests
# All tests
npx playwright test
# Specific file
npx playwright test upload.spec.ts
# Headed mode
npx playwright test --headed
# Debug mode
npx playwright test --debug
# Update snapshots
npx playwright test --update-snapshots
Score
Total Score
65/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
✓説明文
100文字以上の説明がある
+10
○人気
GitHub Stars 100以上
0/15
✓最近の活動
1ヶ月以内に更新
+10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
✓タグ
1つ以上のタグが設定されている
+5
Reviews
💬
Reviews coming soon

