| name | playwright-ui-testing |
| description | Playwright browser automation, visual regression testing, accessibility testing, and E2E workflow validation for CIA platform |
| license | Apache-2.0 |
Playwright UI Testing
Purpose
This skill provides guidance for implementing comprehensive UI testing using Playwright, including browser automation, visual regression testing, accessibility validation, and end-to-end workflow testing for the CIA platform.
When to Use
✅ Use this skill when:
- Writing end-to-end UI tests
- Automating browser interactions
- Performing visual regression testing
- Validating accessibility (WCAG)
- Testing across multiple browsers
- Capturing screenshots for documentation
- Testing responsive layouts
- Validating user workflows
❌ Don't use this skill for:
- Unit testing (use unit-testing-patterns)
- API testing (use integration-testing)
- Performance testing (use code-quality-checks)
- Security testing (use secure-code-review)
Patterns & Examples
Basic Playwright Test Structure
const { test, expect } = require('@playwright/test');
test.describe('Politician Search', () => {
test.beforeEach(async ({ page }) => {
await page.goto('https://localhost:28443/cia/');
await page.waitForLoadState('networkidle');
});
test('should search politicians by name', async ({ page }) => {
await page.fill('[aria-label="Search politicians"]', 'Andersson');
await page.click('button:has-text("Search")');
await page.waitForSelector('.politician-card');
const results = await page.locator('.politician-card').all();
expect(results.length).toBeGreaterThan(0);
for (const result of results) {
const name = await result.locator('.politician-name').textContent();
expect(name.toLowerCase()).toContain('andersson');
}
});
test('should filter by political party', async ({ page }) => {
await page.selectOption('[aria-label="Filter by party"]', 'S');
await page.waitForSelector('.politician-card');
const partyBadges = await page.locator('.party-badge').allTextContents();
partyBadges.forEach(badge => {
expect(badge).toBe('S');
});
});
test('should display politician details', async ({ page }) => {
await page.click('.politician-card:first-child');
await expect(page.locator('h1.politician-name')).toBeVisible();
await expect(page.locator('.risk-score')).toBeVisible();
await expect(page.locator('.voting-history')).toBeVisible();
const riskScore = await page.locator('.risk-score').textContent();
expect(parseFloat(riskScore)).toBeGreaterThanOrEqual(0);
expect(parseFloat(riskScore)).toBeLessThanOrEqual(100);
});
});
Accessibility Testing with Playwright
const { test, expect } = require('@playwright/test');
const { injectAxe, checkA11y, getViolations } = require('axe-playwright');
test.describe('Accessibility Compliance', () => {
test('homepage should have no accessibility violations', async ({ page }) => {
await page.goto('https://localhost:28443/cia/');
await injectAxe(page);
await checkA11y(page, null, {
detailedReport: true,
detailedReportOptions: {
html: true
},
axeOptions: {
runOnly: {
type: 'tag',
values: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa']
}
}
});
});
test('politician detail page keyboard navigation', async ({ page }) => {
await page.goto('https://localhost:28443/cia/politician/123');
await page.keyboard.press();
focused = page.( ..);
([, , ]).(focused);
page..();
skipLink = page.();
(skipLink).();
page.();
(page.()).();
page..();
(page.())..();
});
(, ({ page }) => {
page.();
(page.()).();
(page.()).();
(page.()).();
(page.()).();
});
});
Visual Regression Testing
const { test, expect } = require('@playwright/test');
test.describe('Visual Regression', () => {
test('homepage matches baseline', async ({ page }) => {
await page.goto('https://localhost:28443/cia/');
await page.waitForLoadState('networkidle');
await expect(page).toHaveScreenshot('homepage.png', {
fullPage: true,
maxDiffPixels: 100
});
});
test('risk dashboard layout', async ({ page }) => {
await page.goto('https://localhost:28443/cia/dashboard/risk');
await page.waitForSelector('canvas.chart-canvas');
await page.waitForTimeout(1000);
await expect(page).toHaveScreenshot('risk-dashboard.png', {
maxDiffPixelRatio: 0.05
});
});
test(, ({ page }) => {
page.({ : , : });
page.();
(page).();
});
(, ({ page }) => {
page.({ : , : });
page.();
(page).();
});
});
Cross-Browser Testing Configuration
const { defineConfig, devices } = require('@playwright/test');
module.exports = defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: [
['html'],
['junit', { outputFile: 'test-results/junit.xml' }]
],
use: {
baseURL: 'https://localhost:28443',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
ignoreHTTPSErrors: true
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] }
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] }
},
{
name: ,
: { ...devices[] }
},
{
: ,
: { ...devices[] }
},
{
: ,
: { ...devices[] }
}
],
: {
: ,
: ,
: * ,
: !process..
}
});
GitHub Actions Integration
name: Playwright Tests
on: [push, pull_request]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v4
if: always()
with:
name:
ISMS Compliance Mapping
ISO 27001:2022 Annex A Controls
A.8.29 - Testing in development and acceptance
- Automated UI testing validates functionality
- Security testing integrated in test suite
- Test results documented and reviewed
A.8.31 - Separation of development, test and production
- Tests run against test environment
- Production credentials never used in tests
CIS Controls v8
Control 16: Application Software Security
- 16.10: Apply automated testing tools
- 16.11: Use standard security configurations
Hack23 ISMS Policy References
References
Playwright Documentation
CIA Documentation
Remember
- Test real user workflows: Not just individual features
- Cross-browser testing: Test on Chrome, Firefox, Safari
- Accessibility is mandatory: Integrate axe-core checks
- Visual regression: Catch unintended UI changes
- Parallel execution: Speed up test runs
- CI/CD integration: Run tests on every commit
- Test data cleanup: Maintain test isolation