Token导航 LogoToken导航TokenDH.com
研究检索操作浏览器github未标认证来源可访问clear审计未展示

ui-testing用户界面测试

Agent Skill

用于辅助界面设计、视觉规范、排版、配色、布局和交互体验优化。它适合让 Agent 根据产品场景整理页面结构、生成 UI 方案、检查视觉一致性或改进组件层级。使用时需要结合现有品牌、设计系统和用户任务,不应只堆装饰元素;涉及真实页面改动时,应通过截图或浏览器预览检查文本溢出、对齐和响应式表现。

总安装

367

周安装

15

GitHub Stars

127

下载量

119
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:ui-testing(用户界面测试)
来源仓库:https://github.com/anton-abyzov/specweave
仓库路径:skills/ui-testing
安装命令:
npx skills add https://github.com/anton-abyzov/specweave --skill ui-testing
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/anton-abyzov/specweave --skill ui-testing

简介

用于自动化或辅助执行用户界面测试用例。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

  • 适合验证组件渲染、交互逻辑和视觉输出。
  • 可生成测试脚本或分析现有测试覆盖情况。
  • 需结合具体测试框架和宿主环境实施。ui-testing 属于研究检索类 Skill,可作为该场景下的辅助能力补充。
  • 适用于保障 UI 变更后的稳定性与兼容性。

SKILL.md

UI Testing Skill

Expert in UI testing with Cypress and Testing Library. For deep Playwright expertise, see the e2e-playwright skill.

Framework Selection Guide

FrameworkBest ForKey Strength
PlaywrightE2E, cross-browserAuto-wait, multi-browser → Use e2e-playwright skill
CypressE2E, developer experienceTime-travel debugging, real-time reload
Testing LibraryComponent testsUser-centric queries, accessibility-first

1. Cypress (E2E Testing)

Why Cypress?

  • Developer-friendly API
  • Real-time reloading
  • Time-travel debugging
  • Screenshot/video recording
  • Stubbing and mocking built-in

Basic Test

describe('User Authentication', () => {
  it('should login with valid credentials', () => {
    cy.visit('/login');

    cy.get('input[name="email"]').type('user@example.com');
    cy.get('input[name="password"]').type('SecurePass123!');
    cy.get('button[type="submit"]').click();

    cy.url().should('include', '/dashboard');
    cy.get('h1').should('have.text', 'Welcome, User');
  });

  it('should show error with invalid credentials', () => {
    cy.visit('/login');

    cy.get('input[name="email"]').type('wrong@example.com');
    cy.get('input[name="password"]').type('WrongPass');
    cy.get('button[type="submit"]').click();

    cy.get('.error-message')
      .should('be.visible')
      .and('have.text', 'Invalid credentials');
  });
});

Custom Commands (Reusable Actions)

// cypress/support/commands.js
Cypress.Commands.add('login', (email, password) => {
  cy.visit('/login');
  cy.get('input[name="email"]').type(email);
  cy.get('input[name="password"]').type(password);
  cy.get('button[type="submit"]').click();
  cy.url().should('include', '/dashboard');
});

// Usage in tests
it('should display dashboard for logged-in user', () => {
  cy.login('user@example.com', 'SecurePass123!');
  cy.get('h1').should('have.text', 'Dashboard');
});

API Mocking with Intercept

it('should display mocked user data', () => {
  cy.intercept('GET', '/api/user', {
    statusCode: 200,
    body: {
      id: 1,
      name: 'Mock User',
      email: 'mock@example.com',
    },
  }).as('getUser');

  cy.visit('/profile');

  cy.wait('@getUser');
  cy.get('.user-name').should('have.text', 'Mock User');
});

3. React Testing Library (Component Tests)

Why Testing Library?

  • User-centric queries (accessibility-first)
  • Encourages best practices (testing behavior, not implementation)
  • Works with React, Vue, Svelte, Angular

Component Test Example

import { render, screen, fireEvent } from '@testing-library/react';
import { LoginForm } from './LoginForm';

describe('LoginForm', () => {
  it('should render email and password inputs', () => {
    render(<LoginForm />);

    expect(screen.getByLabelText('Email')).toBeInTheDocument();
    expect(screen.getByLabelText('Password')).toBeInTheDocument();
  });

  it('should call onSubmit with email and password', async () => {
    const handleSubmit = vi.fn();
    render(<LoginForm onSubmit={handleSubmit} />);

    // Type into inputs
    fireEvent.change(screen.getByLabelText('Email'), {
      target: { value: 'user@example.com' },
    });
    fireEvent.change(screen.getByLabelText('Password'), {
      target: { value: 'SecurePass123!' },
    });

    // Submit form
    fireEvent.click(screen.getByRole('button', { name: /login/i }));

    // Verify callback
    expect(handleSubmit).toHaveBeenCalledWith({
      email: 'user@example.com',
      password: 'SecurePass123!',
    });
  });

  it('should show validation error for invalid email', async () => {
    render(<LoginForm />);

    fireEvent.change(screen.getByLabelText('Email'), {
      target: { value: 'invalid-email' },
    });
    fireEvent.blur(screen.getByLabelText('Email'));

    expect(await screen.findByText('Invalid email format')).toBeInTheDocument();
  });
});

User-Centric Queries (Preferred)

// ✅ GOOD: Accessible queries (user-facing)
screen.getByRole('button', { name: /submit/i });
screen.getByLabelText('Email');
screen.getByPlaceholderText('Enter your email');
screen.getByText('Welcome');

// ❌ BAD: Implementation-detail queries (fragile)
screen.getByClassName('btn-primary'); // Changes when CSS changes
screen.getByTestId('submit-button'); // Not user-facing

Test Strategies

1. Testing Pyramid

         /\
        /  \  E2E (10%)
       /____\
      /      \  Integration (30%)
     /________\
    /          \  Unit (60%)
   /____________\

Unit Tests (60%):

  • Individual components in isolation
  • Fast, cheap, many tests
  • Mock external dependencies

Integration Tests (30%):

  • Multiple components working together
  • API integration, data flow
  • Moderate speed, moderate cost

E2E Tests (10%):

  • Full user journeys (login → checkout)
  • Slowest, most expensive
  • Critical paths only

2. Test Coverage Strategy

What to Test:

  • ✅ Happy paths (core user flows)
  • ✅ Error states (validation, API failures)
  • ✅ Edge cases (empty states, max limits)
  • ✅ Accessibility (keyboard navigation, screen readers)
  • ✅ Regression bugs (add test for each bug fix)

What NOT to Test:

  • ❌ Third-party libraries (assume they work)
  • ❌ Implementation details (internal state, CSS classes)
  • ❌ Trivial code (getters, setters)

3. Flakiness Mitigation

Common Causes of Flaky Tests:

  1. Race Conditions

Bad:

await page.click('button');
const text = await page.textContent('.result'); // May fail!

Good:

await page.click('button');
await page.waitForSelector('.result'); // Wait for element
const text = await page.textContent('.result');
  1. Non-Deterministic Data

Bad:

expect(page.locator('.user')).toHaveCount(5); // Depends on database state

Good:

// Mock API to return deterministic data
await page.route('**/api/users', (route) =>
  route.fulfill({
    body: JSON.stringify([{ id: 1, name: 'User 1' }, { id: 2, name: 'User 2' }]),
  })
);

expect(page.locator('.user')).toHaveCount(2); // Predictable
  1. Timing Issues

Bad:

await page.waitForTimeout(3000); // Arbitrary wait

Good:

await page.waitForSelector('.loaded'); // Wait for specific condition
await page.waitForLoadState('networkidle'); // Wait for network idle
  1. Test Interdependence

Bad:

test('create user', async () => {
  // Creates user in DB
});

test('login user', async () => {
  // Depends on previous test creating user
});

Good:

test.beforeEach(async () => {
  // Each test creates its own user
  await createTestUser();
});

test.afterEach(async () => {
  await cleanupTestUsers();
});

Accessibility Testing

1. Automated Accessibility Tests (axe-core)

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

test('should have no accessibility violations', async ({ page }) => {
  await page.goto('https://example.com');

  const accessibilityScanResults = await new AxeBuilder({ page }).analyze();

  expect(accessibilityScanResults.violations).toEqual([]);
});

2. Keyboard Navigation

test('should navigate form with keyboard', async ({ page }) => {
  await page.goto('/form');

  // Tab through form fields
  await page.keyboard.press('Tab');
  await expect(page.locator('input[name="email"]')).toBeFocused();

  await page.keyboard.press('Tab');
  await expect(page.locator('input[name="password"]')).toBeFocused();

  await page.keyboard.press('Tab');
  await expect(page.locator('button[type="submit"]')).toBeFocused();

  // Submit with Enter
  await page.keyboard.press('Enter');
  await expect(page).toHaveURL('**/dashboard');
});

3. Screen Reader Testing (aria-label, roles)

test('should have proper ARIA labels', async ({ page }) => {
  await page.goto('/login');

  // Verify accessible names
  await expect(page.getByRole('textbox', { name: 'Email' })).toBeVisible();
  await expect(page.getByRole('textbox', { name: 'Password' })).toBeVisible();
  await expect(page.getByRole('button', { name: 'Login' })).toBeVisible();

  // Verify error announcements (aria-live)
  await page.fill('input[name="email"]', 'invalid-email');
  await page.click('button[type="submit"]');

  const errorRegion = page.locator('[role="alert"]');
  await expect(errorRegion).toHaveText('Invalid email format');
});

CI/CD Integration

1. GitHub Actions (Playwright)

name: E2E Tests

on:
  push:
    branches: [main, develop]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install --with-deps

      - name: Run Playwright tests
        run: npx playwright test

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

2. Parallel Execution

// playwright.config.ts
export default defineConfig({
  workers: process.env.CI ? 2 : undefined, // Parallel in CI
  fullyParallel: true,
  retries: process.env.CI ? 2 : 0, // Retry flaky tests in CI
  reporter: process.env.CI ? 'github' : 'html',
});

3. Sharding (Large Test Suites)

# Split tests across 4 machines
npx playwright test --shard=1/4
npx playwright test --shard=2/4
npx playwright test --shard=3/4
npx playwright test --shard=4/4

Best Practices

1. Use Data Attributes for Stable Selectors

<!-- ✅ GOOD: Stable selector -->
<button data-testid="submit-button">Submit</button>

<!-- ❌ BAD: Fragile selectors -->
<button class="btn btn-primary">Submit</button> <!-- CSS changes break tests -->
// Test
await page.click('[data-testid="submit-button"]');

2. Test User Behavior, Not Implementation

Bad:

// Testing internal state
expect(component.state.isLoading).toBe(true);

Good:

// Testing visible UI
expect(screen.getByText('Loading...')).toBeInTheDocument();

3. Keep Tests Independent

// ✅ GOOD: Each test is independent
test.beforeEach(async ({ page }) => {
  await page.goto('/');
  await login(page, 'user@example.com', 'password');
});

test('test 1', async ({ page }) => {
  // Fresh state
});

test('test 2', async ({ page }) => {
  // Fresh state
});

4. Use Meaningful Assertions

Bad:

expect(true).toBe(true); // Useless assertion

Good:

await expect(page.locator('.success-message')).toHaveText(
  'Order placed successfully'
);

5. Avoid Hard-Coded Waits

Bad:

await page.waitForTimeout(5000); // Slow, brittle

Good:

await page.waitForSelector('.results'); // Wait for specific element
await expect(page.locator('.results')).toBeVisible(); // Built-in wait

Debugging Tests

1. Headed Mode (See Browser)

npx playwright test --headed
npx playwright test --headed --debug # Pause on each step

2. Screenshot on Failure

test.afterEach(async ({ page }, testInfo) => {
  if (testInfo.status !== 'passed') {
    await page.screenshot({ path: `failure-${testInfo.title}.png` });
  }
});

3. Trace Viewer (Time-Travel Debugging)

// playwright.config.ts
export default defineConfig({
  use: {
    trace: 'on-first-retry', // Record trace on retry
  },
});
# View trace
npx playwright show-trace trace.zip

4. Console Logs

page.on('console', (msg) => console.log('Browser log:', msg.text()));
page.on('pageerror', (error) => console.error('Page error:', error));

Common Patterns

1. Testing Forms

test('should validate form fields', async ({ page }) => {
  await page.goto('/form');

  // Empty submission (validation)
  await page.click('button[type="submit"]');
  await expect(page.locator('.email-error')).toHaveText('Email is required');

  // Invalid email
  await page.fill('input[name="email"]', 'invalid');
  await page.click('button[type="submit"]');
  await expect(page.locator('.email-error')).toHaveText('Invalid email format');

  // Valid submission
  await page.fill('input[name="email"]', 'user@example.com');
  await page.fill('input[name="password"]', 'SecurePass123!');
  await page.click('button[type="submit"]');
  await expect(page).toHaveURL('**/success');
});

2. Testing Modals

test('should open and close modal', async ({ page }) => {
  await page.goto('/');

  // Open modal
  await page.click('[data-testid="open-modal"]');
  await expect(page.locator('.modal')).toBeVisible();

  // Close with X button
  await page.click('.modal .close-button');
  await expect(page.locator('.modal')).not.toBeVisible();

  // Open again, close with Escape
  await page.click('[data-testid="open-modal"]');
  await page.keyboard.press('Escape');
  await expect(page.locator('.modal')).not.toBeVisible();
});

3. Testing Drag and Drop

test('should drag and drop items', async ({ page }) => {
  await page.goto('/kanban');

  const todoItem = page.locator('[data-testid="item-1"]');
  const doneColumn = page.locator('[data-testid="column-done"]');

  // Drag item from TODO to DONE
  await todoItem.dragTo(doneColumn);

  // Verify item moved
  await expect(doneColumn.locator('[data-testid="item-1"]')).toBeVisible();
});

Resources

Activation Keywords

Ask me about:

  • "How to write E2E tests with Playwright"
  • "Cypress test examples"
  • "React Testing Library best practices"
  • "Page Object Model for UI tests"
  • "Accessibility testing with axe-core"
  • "How to fix flaky tests"
  • "CI/CD integration for UI tests"
  • "Debugging Playwright tests"
  • "Test automation strategies"

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

30.42%
按下载量换算36

Antigravity

22.89%
按下载量换算27

Cursor

18%
按下载量换算21

Gemini CLI

12.73%
按下载量换算15

windsurf

9.27%
按下载量换算11

OpenCode

4.09%
按下载量换算5

安全审计

暂无安全审计结果可展示。

权限和风险

操作浏览器

该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills