关于 E2E Testing (Frontend)
面向使用 Playwright 的项目的前端端到端测试技能,涵盖页面对象、选择器、后端测试数据准备和无障碍审计。README 指出当前测试覆盖有限。
主要功能
- 01使用 Playwright 运行测试
- 02组织可复用的页面对象
- 03优先使用语义选择器
- 04通过 API 或数据播种准备后端数据
- 05使用 axe-core 检查无障碍问题
适用场景
- 01测试登录等前端流程
- 02为浏览器测试准备后端数据
- 03检查页面的无障碍违规项
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ exceptionless/ exceptionless --skill e2e-testing-(frontend)安装后在 Claude Code 中输入/e2e-testing-(frontend)确认已加载。
详细介绍
E2E 测试(前端)
**注意:**目前 E2E 测试的覆盖范围有限,这是一个有待改进的方面。
运行测试
npx playwright install # First time only
npm run test:e2e
页面对象模型
为可复用的页面交互创建页面对象:
// e2e/pages/login-page.ts
import { type Page, type Locator, expect } from '@playwright/test';
export class LoginPage {
readonly page: Page;
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
readonly errorMessage: Locator;
constructor(page: Page) {
this.page = page;
this.emailInput = page.getByLabel('Email');
this.passwordInput = page.getByLabel('Password');
this.submitButton = page.getByRole('button', { name: /log in/i });
this.errorMessage = page.getByRole('alert');
}
async goto() {
await this.page.goto('/login');
}
async login(email: string, password: string) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
async expectError(message: string) {
await expect(this.errorMessage).toContainText(message);
}
}
在测试中使用页面对象
// e2e/auth/login.spec.ts
import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/login-page';
test.describe('Login', () => {
test('successful login redirects to dashboard', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login('[email protected]', 'password123');
await expect(page).toHaveURL('/');
});
test('invalid credentials shows error', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login('[email protected]', 'wrongpassword');
await loginPage.expectError('Invalid email or password');
});
});
选择器优先级
-
优先使用语义选择器:
page.getByRole('button', { name: /submit/i }); page.getByLabel('Email address'); page.getByText('Welcome back'); -
回退到测试 ID:
page.getByTestId('stack-trace'); -
避免依赖实现细节:
// ❌ Avoid CSS classes and IDs page.locator('.btn-primary');
后端数据设置
E2E 测试针对完整的 Aspire 堆栈运行。后端使用与 backend-testing 相同的 AppWebHostFactory 基础设施。
对于需要特定数据的测试,请考虑:
- 在 beforeEach 中调用 API — 使用 Playwright 的请求上下文设置数据
- 测试专用端点 — 创建
/api/test/*端点来管理测试数据 - 数据库播种 — 在运行测试前填充所需数据
- Aspire 编排 — 测试启动时,Elasticsearch 和 Redis 已完成预配置
test.beforeEach(async ({ request }) => {
// Set up test data via API
await request.post('/api/test/seed', {
data: { scenario: 'events-with-errors' }
});
});
test.afterEach(async ({ request }) => {
await request.delete('/api/test/cleanup');
});
**注意:**测试期间,后端服务使用内存实现。有关测试基础设施的配置方式,请参阅 AppWebHostFactory。
无障碍审计
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test('login page has no accessibility violations', async ({ page }) => {
await page.goto('/login');
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
请参阅 accessibility 了解 WCAG 指南。
评论
支持 Markdown