Token导航 LogoToken导航

Agent Skill · 研究检索

ui-testing(用户界面测试)

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

ui-testing 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为操作浏览器;许可证为 MIT,暂无第三方扫描结果,按安装量在研究检索类的 73,675 个 Skill 里排第 60,488。

总安装 367周安装 15GitHub Stars 127下载 119核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

复制提示词发给支持本地命令或 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

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

用于自动化或辅助执行用户界面测试用例。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。适合验证组件渲染、交互逻辑和视觉输出。可生成测试脚本或分析现有测试覆盖情况。需结合具体测试框架和宿主环境实施。

ui-testing 属于研究检索类 Skill,可作为该场景下的辅助能力补充。适用于保障 UI 变更后的稳定性与兼容性。

来源仓库内路径:skills/ui-testing

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/anton-abyzov/specweave --skill ui-testing;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要操作浏览器,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

ui-testing 怎么安装?

在终端执行 npx skills add https://github.com/anton-abyzov/specweave --skill ui-testing。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

ui-testing 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

ui-testing 需要什么权限?

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

ui-testing 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

ui-testing 用的人多吗?

公开数据是累计安装 367 次,近一周安装 15 次,下载 119 次,GitHub 127 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

ui-testing 安全吗?

没有查到第三方扫描结果,安全性无法从公开资料判断,安装前请自行审查源码、依赖和命令行为。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。

先想清楚的地方

  • 没有第三方扫描结果,安全性只能靠自己读源码判断。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 要求有安全扫描结论才肯安装的团队。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
ui-testing

用户界面测试 · 本页

367127操作浏览器MIT未收录

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

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"

平台分布

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