Skip to content
Back to skills

Configure Ux Testing

ASecurity

Check and configure UX testing infrastructure (Playwright, accessibility, visual regression)

  • 58 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added February 8, 2026
toolstypescriptgobashnodetestingdebugginggitci/cddocumentation

Works with

  • cli
  • mcp

Security analysis

A100/100

Scanned February 12, 2026

npx -y skills add laurigates/claude-plugins --skill configure-ux-testing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Configure Ux Testing?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Configure Ux Testing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/laurigates-configure-ux-testing/badge)](https://www.skillsdirectory.com/skills/laurigates-configure-ux-testing)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
model: haiku
created: 2025-12-16
modified: 2025-12-16
reviewed: 2025-12-16
description: Check and configure UX testing infrastructure (Playwright, accessibility, visual regression)
allowed-tools: Glob, Grep, Read, Write, Edit, Bash, AskUserQuestion, TodoWrite, WebSearch, WebFetch
argument-hint: "[--check-only] [--fix] [--a11y] [--visual]"
name: configure-ux-testing
---

# /configure:ux-testing

Check and configure UX testing infrastructure with Playwright as the primary tool for E2E, accessibility, and visual regression testing.

## Context

This command validates UX testing setup and optionally configures Playwright with accessibility and visual regression testing.

**UX Testing Stack:**
- **Playwright** - Cross-browser E2E testing (primary tool)
- **axe-core** - Automated accessibility testing (WCAG compliance)
- **Playwright screenshots** - Visual regression testing
- **Playwright MCP** - Browser automation via MCP integration

## Version Checking

**CRITICAL**: Before configuring UX testing tools, verify latest versions:

1. **@playwright/test**: Check [playwright.dev](https://playwright.dev/) or [npm](https://www.npmjs.com/package/@playwright/test)
2. **@axe-core/playwright**: Check [npm](https://www.npmjs.com/package/@axe-core/playwright)
3. **playwright MCP**: Check [npm](https://www.npmjs.com/package/@anthropic/mcp-server-playwright)

Use WebSearch or WebFetch to verify current versions before configuring UX testing infrastructure.

## Workflow

### Phase 1: Project Detection

Detect existing UX testing infrastructure:

| Indicator | Component | Status |
|-----------|-----------|--------|
| `playwright.config.*` | Playwright | Installed |
| `@axe-core/playwright` in package.json | Accessibility testing | Configured |
| `@playwright/test` in package.json | Playwright Test | Installed |
| `tests/e2e/` or `e2e/` directory | E2E tests | Present |
| `*.spec.ts` files with toHaveScreenshot | Visual regression | Configured |
| `.mcp.json` with playwright server | Playwright MCP | Configured |

### Phase 2: Current State Analysis

Check for complete UX testing setup:

**Playwright Core:**
- [ ] `@playwright/test` installed
- [ ] `playwright.config.ts` exists
- [ ] Browser projects configured (Chromium, Firefox, WebKit)
- [ ] Mobile viewports configured (optional)
- [ ] WebServer configuration for local dev
- [ ] Trace/screenshot/video on failure

**Accessibility Testing:**
- [ ] `@axe-core/playwright` installed
- [ ] Accessibility tests created
- [ ] WCAG level configured (A, AA, AAA)
- [ ] Custom rules/exceptions documented

**Visual Regression:**
- [ ] Screenshot assertions configured
- [ ] Snapshot directory configured
- [ ] Update workflow documented
- [ ] CI snapshot handling configured

**MCP Integration:**
- [ ] Playwright MCP server in `.mcp.json`
- [ ] Browser automation available to Claude

### Phase 3: Compliance Report

Generate formatted compliance report:

```
UX Testing Compliance Report
=============================
Project: [name]
Framework: Playwright

Playwright Core:
  @playwright/test        package.json               [✅ INSTALLED | ❌ MISSING]
  playwright.config.ts    configuration              [✅ EXISTS | ❌ MISSING]
  Desktop browsers        chromium, firefox, webkit  [✅ ALL | ⚠️ PARTIAL]
  Mobile viewports        iPhone, Pixel              [✅ CONFIGURED | ⏭️ OPTIONAL]
  WebServer config        auto-start dev server      [✅ CONFIGURED | ⚠️ MISSING]
  Trace on failure        debugging support          [✅ ENABLED | ⚠️ DISABLED]

Accessibility Testing:
  @axe-core/playwright    package.json               [✅ INSTALLED | ❌ MISSING]
  a11y test files         tests/a11y/                [✅ FOUND | ❌ NONE]
  WCAG level              AA (recommended)           [✅ CONFIGURED | ⚠️ NOT SET]
  Violations threshold    0 (strict)                 [✅ STRICT | ⚠️ LENIENT]

Visual Regression:
  Screenshot tests        toHaveScreenshot()         [✅ FOUND | ⏭️ OPTIONAL]
  Snapshot directory      __snapshots__              [✅ CONFIGURED | ⏭️ N/A]
  CI handling             GitHub Actions artifact    [✅ CONFIGURED | ⚠️ MISSING]

MCP Integration:
  Playwright MCP          .mcp.json                  [✅ CONFIGURED | ⏭️ OPTIONAL]

Overall: [X issues found]

Recommendations:
  - Install @axe-core/playwright for accessibility testing
  - Add mobile viewport configurations
  - Configure visual regression workflow
```

### Phase 4: Configuration (if --fix or user confirms)

#### Install Dependencies

```bash
# Core Playwright
bun add --dev @playwright/test

# Accessibility testing
bun add --dev @axe-core/playwright

# Install browsers
bunx playwright install
```

#### Create `playwright.config.ts`

```typescript
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', { open: 'never' }],
    ['json', { outputFile: 'test-results/results.json' }],
    ['junit', { outputFile: 'test-results/junit.xml' }],
  ],
  timeout: 30000,
  expect: {
    timeout: 5000,
    toHaveScreenshot: {
      maxDiffPixels: 100,
      threshold: 0.2,
    },
  },
  use: {
    baseURL: process.env.BASE_URL || 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
    actionTimeout: 10000,
    navigationTimeout: 30000,
  },
  projects: [
    // Desktop browsers
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
    // Mobile viewports
    {
      name: 'mobile-chrome',
      use: { ...devices['Pixel 5'] },
    },
    {
      name: 'mobile-safari',
      use: { ...devices['iPhone 13'] },
    },
    // Accessibility tests (single browser)
    {
      name: 'a11y',
      testMatch: /.*\.a11y\.spec\.ts/,
      use: { ...devices['Desktop Chrome'] },
    },
  ],
  webServer: {
    command: 'bun run dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
    timeout: 120000,
  },
});
```

#### Create Accessibility Test Helper

**Create `tests/e2e/helpers/a11y.ts`:**

```typescript
import { Page, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';

export interface A11yOptions {
  /** WCAG conformance level: 'wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa' */
  level?: 'wcag2a' | 'wcag2aa' | 'wcag21aa' | 'wcag22aa';
  /** Specific rules to include */
  includeRules?: string[];
  /** Specific rules to exclude */
  excludeRules?: string[];
  /** Selectors to exclude from analysis */
  excludeSelectors?: string[];
}

/**
 * Run accessibility scan on page and assert no violations
 */
export async function expectNoA11yViolations(
  page: Page,
  options: A11yOptions = {}
): Promise<void> {
  const {
    level = 'wcag21aa',
    includeRules = [],
    excludeRules = [],
    excludeSelectors = [],
  } = options;

  let builder = new AxeBuilder({ page })
    .withTags([level, 'best-practice']);

  if (includeRules.length > 0) {
    builder = builder.include(includeRules);
  }

  if (excludeRules.length > 0) {
    builder = builder.disableRules(excludeRules);
  }

  if (excludeSelectors.length > 0) {
    for (const selector of excludeSelectors) {
      builder = builder.exclude(selector);
    }
  }

  const results = await builder.analyze();

  // Format violations for readable output
  const violationSummary = results.violations.map((v) => ({
    rule: v.id,
    impact: v.impact,
    description: v.description,
    nodes: v.nodes.length,
    elements: v.nodes.map((n) => n.html).slice(0, 3),
  }));

  expect(
    results.violations,
    `Found ${results.violations.length} accessibility violation(s):\n${JSON.stringify(violationSummary, null, 2)}`
  ).toHaveLength(0);
}

/**
 * Run accessibility scan and return detailed report
 */
export async function getA11yReport(
  page: Page,
  options: A11yOptions = {}
): Promise<{
  violations: number;
  passes: number;
  incomplete: number;
  details: unknown;
}> {
  const { level = 'wcag21aa' } = options;

  const results = await new AxeBuilder({ page })
    .withTags([level, 'best-practice'])
    .analyze();

  return {
    violations: results.violations.length,
    passes: results.passes.length,
    incomplete: results.incomplete.length,
    details: results,
  };
}
```

#### Create Example Accessibility Test

**Create `tests/e2e/homepage.a11y.spec.ts`:**

```typescript
import { test, expect } from '@playwright/test';
import { expectNoA11yViolations, getA11yReport } from './helpers/a11y';

test.describe('Homepage Accessibility', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/');
  });

  test('should have no WCAG 2.1 AA violations', async ({ page }) => {
    await expectNoA11yViolations(page, {
      level: 'wcag21aa',
    });
  });

  test('should have no violations after interaction', async ({ page }) => {
    // Interact with page elements
    await page.getByRole('button', { name: /menu/i }).click();

    // Check accessibility after state change
    await expectNoA11yViolations(page);
  });

  test('should generate full accessibility report', async ({ page }) => {
    const report = await getA11yReport(page);

    console.log(`Accessibility Report:
      - Violations: ${report.violations}
      - Passes: ${report.passes}
      - Incomplete: ${report.incomplete}
    `);

    expect(report.violations).toBe(0);
  });
});

test.describe('Form Accessibility', () => {
  test('login form should be accessible', async ({ page }) => {
    await page.goto('/login');

    // Check form has proper labels
    await expect(page.getByLabel('Email')).toBeVisible();
    await expect(page.getByLabel('Password')).toBeVisible();

    // Check submit button is accessible
    await expect(page.getByRole('button', { name: /sign in/i })).toBeEnabled();

    // Run full a11y scan
    await expectNoA11yViolations(page);
  });
});
```

#### Create Visual Regression Test

**Create `tests/e2e/visual.spec.ts`:**

```typescript
import { test, expect } from '@playwright/test';

test.describe('Visual Regression', () => {
  test('homepage matches snapshot', async ({ page }) => {
    await page.goto('/');

    // Wait for dynamic content to load
    await page.waitForLoadState('networkidle');

    // Full page screenshot
    await expect(page).toHaveScreenshot('homepage.png', {
      fullPage: true,
    });
  });

  test('header matches snapshot', async ({ page }) => {
    await page.goto('/');

    // Component screenshot
    const header = page.locator('header');
    await expect(header).toHaveScreenshot('header.png');
  });

  test('responsive layouts match snapshots', async ({ page }) => {
    await page.goto('/');

    // Desktop
    await page.setViewportSize({ width: 1920, height: 1080 });
    await expect(page).toHaveScreenshot('homepage-desktop.png');

    // Tablet
    await page.setViewportSize({ width: 768, height: 1024 });
    await expect(page).toHaveScreenshot('homepage-tablet.png');

    // Mobile
    await page.setViewportSize({ width: 375, height: 667 });
    await expect(page).toHaveScreenshot('homepage-mobile.png');
  });

  test('dark mode matches snapshot', async ({ page }) => {
    await page.goto('/');

    // Enable dark mode (adjust selector for your app)
    await page.emulateMedia({ colorScheme: 'dark' });

    await expect(page).toHaveScreenshot('homepage-dark.png', {
      fullPage: true,
    });
  });
});
```

#### Add npm Scripts

**Update `package.json`:**

```json
{
  "scripts": {
    "test:e2e": "playwright test",
    "test:e2e:headed": "playwright test --headed",
    "test:e2e:debug": "playwright test --debug",
    "test:e2e:ui": "playwright test --ui",
    "test:a11y": "playwright test --project=a11y",
    "test:visual": "playwright test visual.spec.ts",
    "test:visual:update": "playwright test visual.spec.ts --update-snapshots",
    "playwright:codegen": "playwright codegen http://localhost:3000",
    "playwright:report": "playwright show-report"
  }
}
```

### Phase 5: MCP Integration (Optional)

**Add to `.mcp.json`:**

```json
{
  "mcpServers": {
    "playwright": {
      "command": "bunx",
      "args": ["-y", "@playwright/mcp@latest"]
    }
  }
}
```

This enables Claude to:
- Navigate and interact with web pages
- Take screenshots for visual debugging
- Fill forms and click elements
- Capture accessibility snapshots

### Phase 6: CI/CD Integration

**Create `.github/workflows/e2e.yml`:**

```yaml
name: E2E Tests

on:
  push:
    branches: [main]
  pull_request:

jobs:
  e2e:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Install dependencies
        run: bun install --frozen-lockfile

      - name: Install Playwright Browsers
        run: bunx playwright install --with-deps

      - name: Run E2E tests
        run: bunx playwright test

      - name: Upload test results
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30

      - name: Upload screenshots
        uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: test-screenshots
          path: test-results/
          retention-days: 7

  a11y:
    timeout-minutes: 30
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Install dependencies
        run: bun install --frozen-lockfile

      - name: Install Playwright Browsers
        run: bunx playwright install chromium --with-deps

      - name: Run accessibility tests
        run: bunx playwright test --project=a11y

      - name: Upload a11y report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: a11y-report
          path: playwright-report/
          retention-days: 30
```

### Phase 7: Standards Tracking

Update `.project-standards.yaml`:

```yaml
standards_version: "2025.1"
last_configured: "[timestamp]"
components:
  ux_testing: "2025.1"
  ux_testing_framework: "playwright"
  ux_testing_a11y: true
  ux_testing_a11y_level: "wcag21aa"
  ux_testing_visual: true
  ux_testing_mcp: true
```

### Phase 8: Updated Compliance Report

```
UX Testing Configuration Complete
===================================

Framework: Playwright
Accessibility: axe-core (WCAG 2.1 AA)
Visual: Screenshot comparisons

Configuration Applied:
  ✅ @playwright/test installed
  ✅ @axe-core/playwright installed
  ✅ playwright.config.ts created
  ✅ Desktop and mobile projects configured
  ✅ WebServer auto-start configured

Accessibility Testing:
  ✅ a11y helper functions created
  ✅ Example accessibility tests added
  ✅ WCAG 2.1 AA level configured

Visual Regression:
  ✅ Screenshot test examples created
  ✅ Responsive breakpoint tests included
  ✅ Dark mode test included

Scripts Added:
  ✅ bun run test:e2e (run all E2E tests)
  ✅ bun run test:a11y (accessibility only)
  ✅ bun run test:visual (visual regression)
  ✅ bun run test:visual:update (update snapshots)

CI/CD:
  ✅ GitHub Actions workflow created
  ✅ Parallel E2E and a11y jobs
  ✅ Artifact upload for reports

Next Steps:
  1. Start dev server:
     bun run dev

  2. Run E2E tests:
     bun run test:e2e

  3. Run accessibility scan:
     bun run test:a11y

  4. Update visual snapshots:
     bun run test:visual:update

  5. Open interactive UI:
     bun run test:e2e:ui

Documentation:
  - Playwright: https://playwright.dev
  - axe-core: https://www.deque.com/axe
  - Skill: playwright-testing, accessibility-implementation
```

## Flags

| Flag | Description |
|------|-------------|
| `--check-only` | Report status without offering fixes |
| `--fix` | Apply all fixes automatically without prompting |
| `--a11y` | Focus on accessibility testing configuration |
| `--visual` | Focus on visual regression testing configuration |

## Examples

```bash
# Check compliance and offer fixes
/configure:ux-testing

# Check only, no modifications
/configure:ux-testing --check-only

# Auto-fix all issues
/configure:ux-testing --fix

# Configure accessibility testing only
/configure:ux-testing --fix --a11y

# Configure visual regression only
/configure:ux-testing --fix --visual
```

## Error Handling

- **No package manager found**: Cannot install dependencies, provide manual steps
- **Dev server not configured**: Warn about manual baseURL configuration
- **Browsers not installed**: Prompt to run `bunx playwright install`
- **Existing config conflicts**: Preserve user config, suggest merge

## See Also

- `/configure:tests` - Unit and integration testing configuration
- `/configure:all` - Run all compliance checks
- **Skills**: `playwright-testing`, `accessibility-implementation`
- **Agents**: `ux-implementation` for implementing UX designs
- **Playwright documentation**: https://playwright.dev
- **axe-core documentation**: https://www.deque.com/axe

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.