refactor: 删除旧的E2E测试文件
删除文件: - e2e/admin-frontend-interaction.spec.ts - e2e/admin-publish-core.spec.ts - e2e/admin-publish.spec.ts - e2e/website-acceptance.spec.ts 原因: - 已被新的测试架构替代 - 新架构采用Page Object Model模式 - 新架构有更清晰的测试分类(smoke/journeys/features) - 新架构提供更好的可维护性和可扩展性 新测试架构: - smoke/ - 冒烟测试 - journeys/ - 用户旅程测试 - features/ - 功能测试 - pages/ - Page Object Model - fixtures/ - 测试固件
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import { test, expect } from '../../fixtures/auth';
|
||||
import { AdminContentPage } from '../../pages';
|
||||
import { testFixtures } from '../../fixtures/test-data';
|
||||
|
||||
test.describe('内容CRUD测试 @feature @admin', () => {
|
||||
let contentPage: AdminContentPage;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
contentPage = new AdminContentPage(page);
|
||||
});
|
||||
|
||||
test('创建新闻内容', async ({ authenticatedPage: _authenticatedPage }) => {
|
||||
const testNews = testFixtures.testContent.news;
|
||||
let contentId: string | null = null;
|
||||
|
||||
try {
|
||||
contentId = await contentPage.createContent(testNews);
|
||||
expect(contentId).not.toBeNull();
|
||||
|
||||
await contentPage.expectContentInList(testNews.title);
|
||||
} finally {
|
||||
if (contentId) {
|
||||
await contentPage.deleteContent(contentId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('创建产品内容', async ({ authenticatedPage: _authenticatedPage }) => {
|
||||
const testProduct = testFixtures.testContent.product;
|
||||
let contentId: string | null = null;
|
||||
|
||||
try {
|
||||
contentId = await contentPage.createContent(testProduct);
|
||||
expect(contentId).not.toBeNull();
|
||||
|
||||
await contentPage.expectContentInList(testProduct.title);
|
||||
} finally {
|
||||
if (contentId) {
|
||||
await contentPage.deleteContent(contentId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('创建内容时验证必填字段', async ({ page, authenticatedPage: _authenticatedPage }) => {
|
||||
await contentPage.gotoCreate();
|
||||
await page.click('button:has-text("发布")');
|
||||
|
||||
await expect(page.locator('.error-message, [role="alert"]')).toBeVisible();
|
||||
});
|
||||
|
||||
test('删除内容', async ({ authenticatedPage: _authenticatedPage }) => {
|
||||
const testNews = testFixtures.testContent.news;
|
||||
const contentId = await contentPage.createContent(testNews);
|
||||
|
||||
if (contentId) {
|
||||
await contentPage.deleteContent(contentId);
|
||||
await contentPage.expectContentNotInList(testNews.title);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
import { test, expect } from '../../fixtures/auth';
|
||||
import { AdminUserPage } from '../../pages';
|
||||
|
||||
test.describe('用户管理测试 @feature @admin', () => {
|
||||
let userPage: AdminUserPage;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
userPage = new AdminUserPage(page);
|
||||
});
|
||||
|
||||
test('查看用户列表', async ({ authenticatedPage: _authenticatedPage }) => {
|
||||
await userPage.goto();
|
||||
|
||||
const table = userPage['page'].locator('table');
|
||||
await expect(table).toBeVisible();
|
||||
|
||||
const rows = table.locator('tbody tr');
|
||||
const count = await rows.count();
|
||||
expect(count).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('创建新用户', async ({ authenticatedPage: _authenticatedPage }) => {
|
||||
const timestamp = Date.now();
|
||||
const userData = {
|
||||
email: `test-${timestamp}@example.com`,
|
||||
password: 'Test123456!',
|
||||
name: `测试用户${timestamp}`,
|
||||
role: 'viewer' as const,
|
||||
};
|
||||
|
||||
try {
|
||||
await userPage.createUser(userData);
|
||||
await userPage.expectUserInList(userData.email);
|
||||
} finally {
|
||||
// TODO: 添加删除用户的逻辑
|
||||
}
|
||||
});
|
||||
|
||||
test('搜索用户', async ({ page, authenticatedPage: _authenticatedPage }) => {
|
||||
await userPage.goto();
|
||||
|
||||
const searchInput = page.locator('input[placeholder*="搜索"], input[name="search"]');
|
||||
if (await searchInput.count() > 0) {
|
||||
await searchInput.fill('admin');
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
const table = page.locator('table');
|
||||
await expect(table).toBeVisible();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('无障碍测试 @feature @frontend', () => {
|
||||
test('首页无障碍检查', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
const violations = await page.evaluate(() => {
|
||||
return (window as unknown as { axe?: { run: () => unknown[] } }).axe?.run() || [];
|
||||
});
|
||||
|
||||
expect(violations.length).toBe(0);
|
||||
});
|
||||
|
||||
test('导航键盘可访问', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
await page.keyboard.press('Tab');
|
||||
const focusedElement = page.locator(':focus');
|
||||
await expect(focusedElement).toBeVisible();
|
||||
});
|
||||
|
||||
test('图片有alt属性', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
const images = page.locator('img');
|
||||
const count = await images.count();
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const img = images.nth(i);
|
||||
const alt = await img.getAttribute('alt');
|
||||
expect(alt).not.toBeNull();
|
||||
}
|
||||
});
|
||||
|
||||
test('表单标签关联正确', async ({ page }) => {
|
||||
await page.goto('/contact');
|
||||
|
||||
const inputs = page.locator('input[type="text"], input[type="email"], textarea');
|
||||
const count = await inputs.count();
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const input = inputs.nth(i);
|
||||
const id = await input.getAttribute('id');
|
||||
|
||||
if (id) {
|
||||
const label = page.locator(`label[for="${id}"]`);
|
||||
const hasLabel = await label.count() > 0;
|
||||
const hasAriaLabel = await input.getAttribute('aria-label');
|
||||
|
||||
expect(hasLabel || hasAriaLabel).toBeTruthy();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('标题层级正确', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
const h1 = page.locator('h1');
|
||||
const h1Count = await h1.count();
|
||||
expect(h1Count).toBeGreaterThanOrEqual(1);
|
||||
expect(h1Count).toBeLessThanOrEqual(1);
|
||||
});
|
||||
|
||||
test('链接有明确的文本', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
const links = page.locator('a');
|
||||
const count = await links.count();
|
||||
|
||||
for (let i = 0; i < Math.min(count, 10); i++) {
|
||||
const link = links.nth(i);
|
||||
const text = await link.textContent();
|
||||
const ariaLabel = await link.getAttribute('aria-label');
|
||||
|
||||
expect(text || ariaLabel).toBeTruthy();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('响应式测试 @feature @frontend', () => {
|
||||
test('移动端首页显示正常', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 375, height: 667 });
|
||||
await page.goto('/');
|
||||
|
||||
await expect(page.locator('header')).toBeVisible();
|
||||
await expect(page.locator('nav')).toBeVisible();
|
||||
await expect(page.locator('footer')).toBeVisible();
|
||||
});
|
||||
|
||||
test('平板端首页显示正常', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 768, height: 1024 });
|
||||
await page.goto('/');
|
||||
|
||||
await expect(page.locator('header')).toBeVisible();
|
||||
await expect(page.locator('nav')).toBeVisible();
|
||||
});
|
||||
|
||||
test('桌面端首页显示正常', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1920, height: 1080 });
|
||||
await page.goto('/');
|
||||
|
||||
await expect(page.locator('header')).toBeVisible();
|
||||
await expect(page.locator('nav')).toBeVisible();
|
||||
});
|
||||
|
||||
test('移动端导航菜单可展开', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 375, height: 667 });
|
||||
await page.goto('/');
|
||||
|
||||
const menuButton = page.locator('button[aria-label*="菜单"], button[aria-label*="menu"]');
|
||||
if (await menuButton.count() > 0) {
|
||||
await menuButton.click();
|
||||
|
||||
const mobileMenu = page.locator('[role="dialog"], .mobile-menu, nav[class*="mobile"]');
|
||||
await expect(mobileMenu).toBeVisible();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user