Frontend Testing by vanman2024/dev-lifecycle-marketplace
npx skills add https://github.com/vanman2024/dev-lifecycle-marketplace --skill 'Frontend Testing'关键:上方的描述字段控制 Claude 何时自动加载此技能。
为 React/Next.js 应用程序提供全面的前端测试模式,包括:
此技能中的所有代码示例和模板均遵循严格的安全规则:
关键: 参考 @docs/security/SECURITY-RULES.md
.gitignore 保护密钥使用 scripts/init-frontend-tests.sh 来设置全面的前端测试:
bash scripts/init-frontend-tests.sh [project-path]
这将:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
使用 scripts/run-component-tests.sh 来执行组件测试:
bash scripts/run-component-tests.sh [test-pattern] [options]
选项:
这将:
使用 scripts/run-visual-regression.sh 进行视觉测试:
bash scripts/run-visual-regression.sh [test-pattern] [update-snapshots]
这将:
使用 scripts/run-accessibility-tests.sh 进行 a11y 测试:
bash scripts/run-accessibility-tests.sh [test-pattern]
这将:
使用 scripts/run-performance-tests.sh 进行性能测试:
bash scripts/run-performance-tests.sh [url] [options]
这将:
使用 scripts/generate-coverage-report.sh 来聚合覆盖率:
bash scripts/generate-coverage-report.sh [output-dir]
这将:
import { render, screen, userEvent } from '@testing-library/react';
import { Button } from './Button';
test('renders and handles click', async () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click me</Button>);
const button = screen.getByRole('button', { name: /click me/i });
await userEvent.click(button);
expect(handleClick).toHaveBeenCalledTimes(1);
});
import { test, expect } from '@playwright/test';
test('homepage visual regression', async ({ page }) => {
await page.goto('http://localhost:3000');
await page.waitForLoadState('networkidle');
// 屏蔽动态内容
await page.locator('.timestamp').evaluate(el => el.style.visibility = 'hidden');
await expect(page).toHaveScreenshot('homepage.png');
});
import { test, expect } from '@playwright/test';
import { injectAxe, checkA11y } from 'axe-playwright';
test('form accessibility', async ({ page }) => {
await page.goto('http://localhost:3000/form');
await injectAxe(page);
await checkA11y(page, null, {
detailedReport: true,
detailedReportOptions: {
html: true
}
});
});
import { test } from '@playwright/test';
import { playAudit } from 'playwright-lighthouse';
test('homepage performance', async ({ page }) => {
await page.goto('http://localhost:3000');
await playAudit({
page,
thresholds: {
performance: 90,
accessibility: 90,
'best-practices': 90,
seo: 90,
'first-contentful-paint': 2000,
'largest-contentful-paint': 3000,
'cumulative-layout-shift': 0.1,
},
port: 9222,
});
});
tests/
├── unit/ # 组件单元测试
│ ├── Button.spec.tsx
│ └── Form.spec.tsx
├── integration/ # 组件集成测试
│ └── AuthFlow.spec.tsx
├── visual/ # 视觉回归测试
│ ├── homepage.spec.ts
│ └── dashboard.spec.ts
├── a11y/ # 可访问性测试
│ ├── navigation.spec.ts
│ └── forms.spec.ts
├── performance/ # 性能测试
│ └── critical-pages.spec.ts
└── utils/ # 测试工具
├── test-utils.ts
├── mock-factories.ts
└── test-helpers.ts
- name: Run Frontend Tests
run: |
npm run test:component -- --coverage
npm run test:visual
npm run test:a11y
npm run test:performance
- name: Upload Coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage/coverage-final.json
screen.debug() 打印 DOMscreen.logTestingPlaygroundURL() 获取选择器帮助--watch 运行以进行迭代调试test.only 专注于单个测试test('form submission', async () => {
render(<ContactForm />);
await userEvent.type(screen.getByLabelText(/name/i), 'John Doe');
await userEvent.type(screen.getByLabelText(/email/i), 'john@example.com');
await userEvent.click(screen.getByRole('button', { name: /submit/i }));
expect(await screen.findByText(/success/i)).toBeInTheDocument();
});
test('loads and displays data', async () => {
render(<UserProfile userId="123" />);
expect(screen.getByText(/loading/i)).toBeInTheDocument();
const userName = await screen.findByText(/john doe/i);
expect(userName).toBeInTheDocument();
});
test('displays error message', async () => {
server.use(
http.get('/api/user', () => {
return HttpResponse.json({ error: 'Not found' }, { status: 404 });
})
);
render(<UserProfile userId="999" />);
expect(await screen.findByText(/error/i)).toBeInTheDocument();
});
init-frontend-tests.sh 来设置基础设施每周安装次数
–
代码仓库
GitHub 星标数
2
首次出现时间
–
安全审计
CRITICAL: The description field above controls when Claude auto-loads this skill.
Provides comprehensive frontend testing patterns for React/Next.js applications including:
All code examples and templates in this skill follow strict security rules:
CRITICAL: Reference @docs/security/SECURITY-RULES.md
.gitignore protection for secretsUse scripts/init-frontend-tests.sh to set up comprehensive frontend testing:
bash scripts/init-frontend-tests.sh [project-path]
This will:
Use scripts/run-component-tests.sh to execute component tests:
bash scripts/run-component-tests.sh [test-pattern] [options]
Options:
This will:
Use scripts/run-visual-regression.sh for visual testing:
bash scripts/run-visual-regression.sh [test-pattern] [update-snapshots]
This will:
Use scripts/run-accessibility-tests.sh for a11y testing:
bash scripts/run-accessibility-tests.sh [test-pattern]
This will:
Use scripts/run-performance-tests.sh for performance testing:
bash scripts/run-performance-tests.sh [url] [options]
This will:
Use scripts/generate-coverage-report.sh to aggregate coverage:
bash scripts/generate-coverage-report.sh [output-dir]
This will:
import { render, screen, userEvent } from '@testing-library/react';
import { Button } from './Button';
test('renders and handles click', async () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click me</Button>);
const button = screen.getByRole('button', { name: /click me/i });
await userEvent.click(button);
expect(handleClick).toHaveBeenCalledTimes(1);
});
import { test, expect } from '@playwright/test';
test('homepage visual regression', async ({ page }) => {
await page.goto('http://localhost:3000');
await page.waitForLoadState('networkidle');
// Mask dynamic content
await page.locator('.timestamp').evaluate(el => el.style.visibility = 'hidden');
await expect(page).toHaveScreenshot('homepage.png');
});
import { test, expect } from '@playwright/test';
import { injectAxe, checkA11y } from 'axe-playwright';
test('form accessibility', async ({ page }) => {
await page.goto('http://localhost:3000/form');
await injectAxe(page);
await checkA11y(page, null, {
detailedReport: true,
detailedReportOptions: {
html: true
}
});
});
import { test } from '@playwright/test';
import { playAudit } from 'playwright-lighthouse';
test('homepage performance', async ({ page }) => {
await page.goto('http://localhost:3000');
await playAudit({
page,
thresholds: {
performance: 90,
accessibility: 90,
'best-practices': 90,
seo: 90,
'first-contentful-paint': 2000,
'largest-contentful-paint': 3000,
'cumulative-layout-shift': 0.1,
},
port: 9222,
});
});
tests/
├── unit/ # Component unit tests
│ ├── Button.spec.tsx
│ └── Form.spec.tsx
├── integration/ # Component integration tests
│ └── AuthFlow.spec.tsx
├── visual/ # Visual regression tests
│ ├── homepage.spec.ts
│ └── dashboard.spec.ts
├── a11y/ # Accessibility tests
│ ├── navigation.spec.ts
│ └── forms.spec.ts
├── performance/ # Performance tests
│ └── critical-pages.spec.ts
└── utils/ # Test utilities
├── test-utils.ts
├── mock-factories.ts
└── test-helpers.ts
- name: Run Frontend Tests
run: |
npm run test:component -- --coverage
npm run test:visual
npm run test:a11y
npm run test:performance
- name: Upload Coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage/coverage-final.json
screen.debug() to print DOMscreen.logTestingPlaygroundURL() for selector help--watch for iterative debuggingtest.only to focus on single testtest('form submission', async () => {
render(<ContactForm />);
await userEvent.type(screen.getByLabelText(/name/i), 'John Doe');
await userEvent.type(screen.getByLabelText(/email/i), 'john@example.com');
await userEvent.click(screen.getByRole('button', { name: /submit/i }));
expect(await screen.findByText(/success/i)).toBeInTheDocument();
});
test('loads and displays data', async () => {
render(<UserProfile userId="123" />);
expect(screen.getByText(/loading/i)).toBeInTheDocument();
const userName = await screen.findByText(/john doe/i);
expect(userName).toBeInTheDocument();
});
test('displays error message', async () => {
server.use(
http.get('/api/user', () => {
return HttpResponse.json({ error: 'Not found' }, { status: 404 });
})
);
render(<UserProfile userId="999" />);
expect(await screen.findByText(/error/i)).toBeInTheDocument();
});
init-frontend-tests.sh to set up infrastructureWeekly Installs
–
Repository
GitHub Stars
2
First Seen
–
Security Audits
Vue 3 调试指南:解决响应式、计算属性与监听器常见错误
11,400 周安装