Token导航 LogoToken导航

Agent Skill · 前端设计

component-testing(组件测试)

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

component-testing 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为操作浏览器;许可证为 MIT,第三方扫描已通过,按安装量在前端设计类的 10,216 个 Skill 里排第 6,651。

总安装 474周安装 19GitHub Stars 9下载 154核验 2026-05-01

安装说明

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

安装方式

通过对话安装

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

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

命令行安装

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

skills.shnpx skills
npx skills add https://github.com/adaptationio/skrillz --skill component-testing

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

使用 Playwright 实验性组件测试功能进行 UI 隔离测试。支持 React、Vue、Svelte 与 Solid 等多框架组件验证。可在 spec 文件中直接编写点击、输入等交互断言。需先执行 npm init playwright@latest 初始化项目。无需额外构建步骤即可对组件进行端到端行为测试。

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

上手步骤

4 步
  1. 1

    确认自己的宿主工具

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

  2. 2

    拿到安装命令

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

  3. 3

    安装后重启宿主

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

  4. 4

    按最小权限试用

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

常见问题

6 条

component-testing 怎么安装?

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

component-testing 支持哪些 AI 工具?

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

component-testing 需要什么权限?

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

component-testing 是免费的吗?

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

component-testing 用的人多吗?

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

component-testing 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

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

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

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

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
component-testing

组件测试 · 本页

4749操作浏览器MIT通过

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

SKILL.md 原文

Component Testing with Playwright

Test UI components in isolation using Playwright's experimental component testing feature. Supports React, Vue, Svelte, and Solid.

Quick Start

// Button.spec.tsx
import { test, expect } from '@playwright/experimental-ct-react';
import { Button } from './Button';

test('button click triggers callback', async ({ mount }) => {
  let clicked = false;

  const component = await mount(
    <Button onClick={() => clicked = true}>Click me</Button>
  );

  await component.click();
  expect(clicked).toBe(true);
});

Installation

React

npm init playwright@latest -- --ct
# Select React when prompted

Or manually:

npm install -D @playwright/experimental-ct-react

Vue

npm install -D @playwright/experimental-ct-vue

Svelte

npm install -D @playwright/experimental-ct-svelte

Configuration

playwright-ct.config.ts:

import { defineConfig, devices } from '@playwright/experimental-ct-react';

export default defineConfig({
  testDir: './src',
  testMatch: '**/*.spec.tsx',

  use: {
    ctPort: 3100,
    ctViteConfig: {
      // Custom Vite config for component tests
    },
  },

  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});

React Component Testing

Basic Mount

import { test, expect } from '@playwright/experimental-ct-react';
import { UserCard } from './UserCard';

test('displays user info', async ({ mount }) => {
  const component = await mount(
    <UserCard
      name="John Doe"
      email="john@example.com"
    />
  );

  await expect(component.getByText('John Doe')).toBeVisible();
  await expect(component.getByText('john@example.com')).toBeVisible();
});

With Props

test('button variants', async ({ mount }) => {
  // Primary variant
  const primary = await mount(<Button variant="primary">Save</Button>);
  await expect(primary).toHaveClass(/btn-primary/);

  // Secondary variant
  const secondary = await mount(<Button variant="secondary">Cancel</Button>);
  await expect(secondary).toHaveClass(/btn-secondary/);
});

With Event Handlers

test('form submission', async ({ mount }) => {
  const submittedData: any[] = [];

  const component = await mount(
    <ContactForm onSubmit={(data) => submittedData.push(data)} />
  );

  await component.getByLabel('Name').fill('John');
  await component.getByLabel('Email').fill('john@example.com');
  await component.getByRole('button', { name: 'Submit' }).click();

  expect(submittedData).toHaveLength(1);
  expect(submittedData[0]).toEqual({
    name: 'John',
    email: 'john@example.com',
  });
});

With Context Providers

// Create wrapper for providers
import { ThemeProvider } from './ThemeContext';

test('themed component', async ({ mount }) => {
  const component = await mount(
    <ThemeProvider theme="dark">
      <ThemedButton>Click</ThemedButton>
    </ThemeProvider>
  );

  await expect(component).toHaveClass(/dark-theme/);
});

With Slots/Children

test('card with custom content', async ({ mount }) => {
  const component = await mount(
    <Card>
      <CardHeader>Title</CardHeader>
      <CardBody>Content here</CardBody>
      <CardFooter>
        <Button>Action</Button>
      </CardFooter>
    </Card>
  );

  await expect(component.getByText('Title')).toBeVisible();
  await expect(component.getByText('Content here')).toBeVisible();
  await expect(component.getByRole('button')).toBeVisible();
});

Vue Component Testing

// Counter.spec.ts
import { test, expect } from '@playwright/experimental-ct-vue';
import Counter from './Counter.vue';

test('counter increments', async ({ mount }) => {
  const component = await mount(Counter, {
    props: {
      initialCount: 0,
    },
  });

  await expect(component.getByText('Count: 0')).toBeVisible();
  await component.getByRole('button', { name: '+' }).click();
  await expect(component.getByText('Count: 1')).toBeVisible();
});

With Slots

test('card with slots', async ({ mount }) => {
  const component = await mount(Card, {
    slots: {
      default: '<p>Card content</p>',
      header: '<h2>Card Title</h2>',
    },
  });

  await expect(component.getByText('Card Title')).toBeVisible();
  await expect(component.getByText('Card content')).toBeVisible();
});

With Vuex/Pinia

import { test, expect } from '@playwright/experimental-ct-vue';
import { createTestingPinia } from '@pinia/testing';
import UserProfile from './UserProfile.vue';

test('displays user from store', async ({ mount }) => {
  const component = await mount(UserProfile, {
    global: {
      plugins: [
        createTestingPinia({
          initialState: {
            user: { name: 'John', email: 'john@example.com' },
          },
        }),
      ],
    },
  });

  await expect(component.getByText('John')).toBeVisible();
});

Svelte Component Testing

// Button.spec.ts
import { test, expect } from '@playwright/experimental-ct-svelte';
import Button from './Button.svelte';

test('button emits click', async ({ mount }) => {
  let clicked = false;

  const component = await mount(Button, {
    props: {
      label: 'Click me',
    },
    on: {
      click: () => clicked = true,
    },
  });

  await component.click();
  expect(clicked).toBe(true);
});

Testing Patterns

Visual Regression

test('button visual states', async ({ mount }) => {
  const component = await mount(<Button>Click</Button>);

  // Default state
  await expect(component).toHaveScreenshot('button-default.png');

  // Hover state
  await component.hover();
  await expect(component).toHaveScreenshot('button-hover.png');

  // Focus state
  await component.focus();
  await expect(component).toHaveScreenshot('button-focus.png');
});

Accessibility

import AxeBuilder from '@axe-core/playwright';

test('button is accessible', async ({ mount, page }) => {
  await mount(<Button>Submit</Button>);

  const results = await new AxeBuilder({ page }).analyze();
  expect(results.violations).toEqual([]);
});

Responsive Behavior

test('responsive navigation', async ({ mount, page }) => {
  const component = await mount(<Navigation />);

  // Desktop - horizontal nav
  await page.setViewportSize({ width: 1280, height: 720 });
  await expect(component.locator('.nav-horizontal')).toBeVisible();

  // Mobile - hamburger menu
  await page.setViewportSize({ width: 375, height: 667 });
  await expect(component.locator('.hamburger-menu')).toBeVisible();
});

Loading States

test('async component states', async ({ mount }) => {
  const component = await mount(<DataTable dataUrl="/api/data" />);

  // Loading state
  await expect(component.getByText('Loading...')).toBeVisible();

  // Wait for data
  await expect(component.getByRole('table')).toBeVisible();
  await expect(component.getByText('Loading...')).not.toBeVisible();
});

Error States

test('error handling', async ({ mount, page }) => {
  // Mock failed API
  await page.route('**/api/data', route => {
    route.fulfill({ status: 500 });
  });

  const component = await mount(<DataTable dataUrl="/api/data" />);

  await expect(component.getByText(/error/i)).toBeVisible();
  await expect(component.getByRole('button', { name: 'Retry' })).toBeVisible();
});

Hooks and Fixtures

Before Each Test

import { test as base, expect } from '@playwright/experimental-ct-react';

const test = base.extend({
  autoMockApi: async ({ page }, use) => {
    await page.route('**/api/**', route => {
      route.fulfill({ status: 200, body: '{}' });
    });
    await use();
  },
});

test('component with mocked api', async ({ mount, autoMockApi }) => {
  const component = await mount(<ApiComponent />);
  // API calls are automatically mocked
});

Custom Mount

const test = base.extend({
  mountWithProviders: async ({ mount }, use) => {
    const wrappedMount = async (component: JSX.Element) => {
      return mount(
        <ThemeProvider>
          <AuthProvider>
            {component}
          </AuthProvider>
        </ThemeProvider>
      );
    };
    await use(wrappedMount);
  },
});

test('with providers', async ({ mountWithProviders }) => {
  const component = await mountWithProviders(<Dashboard />);
  // Component has access to theme and auth contexts
});

Running Tests

# Run all component tests
npx playwright test -c playwright-ct.config.ts

# Run specific test file
npx playwright test Button.spec.tsx -c playwright-ct.config.ts

# Run with UI mode
npx playwright test -c playwright-ct.config.ts --ui

# Update snapshots
npx playwright test -c playwright-ct.config.ts --update-snapshots

Best Practices

  1. Test behavior, not implementation - Focus on user interactions
  2. Keep components isolated - Mock external dependencies
  3. Test all states - Default, loading, error, empty, success
  4. Use semantic queries - getByRole, getByLabel over CSS selectors
  5. Combine with E2E - Component tests for logic, E2E for integration

References

  • references/react-patterns.md - React-specific testing patterns
  • references/vue-patterns.md - Vue-specific testing patterns

平台分布

Claude Code

25.64%
按下载量换算39

github-copilot

23.7%
按下载量换算36

neovate

17.28%
按下载量换算27

Antigravity

13.37%
按下载量换算21

kilo

7.24%
按下载量换算11

command-code

3.03%
按下载量换算5

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

操作浏览器

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

安装前确认

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

继续浏览同类 Skills