From 79a66612bd292dd7014a04776c952cb3ef1e5bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?= Date: Thu, 9 Apr 2026 13:19:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=9B=E5=BB=BA=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E5=9B=BA=E4=BB=B6=E5=92=8C=E6=95=B0=E6=8D=AE=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增文件: - e2e/fixtures/test-data.ts - 测试数据固件 - e2e/fixtures/auth.ts - 认证固件 - e2e/fixtures/storage-state.ts - 存储状态固件 - e2e/fixtures/index.ts - 导出索引文件 功能特性: - 提供标准化的测试数据(新闻、产品、服务、案例) - 支持环境变量配置管理员账号 - 封装认证流程,简化测试编写 - 支持存储状态复用,提升测试效率 - 提供XSS等安全测试数据 技术说明: - 添加 ESLint 禁用注释,因为 Playwright fixture 的 use 函数不是 React Hook --- e2e/fixtures/auth.ts | 26 ++++++++++++++ e2e/fixtures/index.ts | 3 ++ e2e/fixtures/storage-state.ts | 29 +++++++++++++++ e2e/fixtures/test-data.ts | 68 +++++++++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 e2e/fixtures/auth.ts create mode 100644 e2e/fixtures/index.ts create mode 100644 e2e/fixtures/storage-state.ts create mode 100644 e2e/fixtures/test-data.ts diff --git a/e2e/fixtures/auth.ts b/e2e/fixtures/auth.ts new file mode 100644 index 0000000..f8a5976 --- /dev/null +++ b/e2e/fixtures/auth.ts @@ -0,0 +1,26 @@ +/* eslint-disable react-hooks/rules-of-hooks */ +import { test as base } from '@playwright/test'; +import { AdminLoginPage } from '../pages/AdminLoginPage'; +import { testFixtures } from './test-data'; + +type AuthFixtures = { + authenticatedPage: void; + adminLoginPage: AdminLoginPage; +}; + +export const test = base.extend({ + authenticatedPage: async ({ page }, use) => { + const loginPage = new AdminLoginPage(page); + await loginPage.goto(); + await loginPage.login(testFixtures.adminUser.email, testFixtures.adminUser.password); + await loginPage.expectLoginSuccess(); + + await use(); + }, + + adminLoginPage: async ({ page }, use) => { + await use(new AdminLoginPage(page)); + }, +}); + +export { expect } from '@playwright/test'; diff --git a/e2e/fixtures/index.ts b/e2e/fixtures/index.ts new file mode 100644 index 0000000..430ec52 --- /dev/null +++ b/e2e/fixtures/index.ts @@ -0,0 +1,3 @@ +export { testFixtures } from './test-data'; +export { test as authTest, expect } from './auth'; +export { test as storageStateTest } from './storage-state'; diff --git a/e2e/fixtures/storage-state.ts b/e2e/fixtures/storage-state.ts new file mode 100644 index 0000000..d996260 --- /dev/null +++ b/e2e/fixtures/storage-state.ts @@ -0,0 +1,29 @@ +/* eslint-disable react-hooks/rules-of-hooks */ +import { test as base } from '@playwright/test'; +import path from 'path'; + +const AUTH_FILE = path.join(__dirname, '../.auth/admin.json'); + +type StorageStateFixtures = { + adminStorageState: string; +}; + +export const test = base.extend({ + adminStorageState: async ({ browser }, use) => { + const context = await browser.newContext(); + const page = await context.newPage(); + + await page.goto('/admin/login'); + await page.fill('#email', process.env.ADMIN_EMAIL || 'admin@novalon.cn'); + await page.fill('#password', process.env.ADMIN_PASSWORD || 'admin123456'); + await page.click('button[type="submit"]'); + await page.waitForURL(/\/admin(?!\/login)/); + + await page.context().storageState({ path: AUTH_FILE }); + await context.close(); + + await use(AUTH_FILE); + }, +}); + +export { expect } from '@playwright/test'; diff --git a/e2e/fixtures/test-data.ts b/e2e/fixtures/test-data.ts new file mode 100644 index 0000000..d25834f --- /dev/null +++ b/e2e/fixtures/test-data.ts @@ -0,0 +1,68 @@ +export const testFixtures = { + adminUser: { + email: process.env.ADMIN_EMAIL || 'admin@novalon.cn', + password: process.env.ADMIN_PASSWORD || 'admin123456', + }, + + testContent: { + news: { + type: 'news' as const, + title: `测试新闻-${Date.now()}`, + slug: `test-news-${Date.now()}`, + excerpt: '这是一条测试新闻的摘要内容', + content: '

这是测试新闻的正文内容

', + category: '公司新闻', + tags: ['测试', '自动化'], + status: 'published' as const, + }, + product: { + type: 'product' as const, + title: `测试产品-${Date.now()}`, + slug: `test-product-${Date.now()}`, + excerpt: '这是一个测试产品的描述', + content: '

测试产品的详细介绍

', + category: '软件产品', + tags: ['产品', '测试'], + status: 'published' as const, + }, + service: { + type: 'service' as const, + title: `测试服务-${Date.now()}`, + slug: `test-service-${Date.now()}`, + excerpt: '这是一个测试服务的描述', + content: '

测试服务的详细介绍

', + category: '软件开发', + tags: ['服务', '测试'], + status: 'published' as const, + }, + case: { + type: 'case' as const, + title: `测试案例-${Date.now()}`, + slug: `test-case-${Date.now()}`, + excerpt: '这是一个测试案例的描述', + content: '

测试案例的详细介绍

', + category: '企业服务', + tags: ['案例', '测试'], + status: 'published' as const, + }, + }, + + invalidContent: { + empty: { + type: 'news' as const, + title: '', + slug: '', + content: '', + }, + xss: { + type: 'news' as const, + title: `XSS测试-${Date.now()}`, + slug: `xss-test-${Date.now()}`, + excerpt: '测试摘要', + content: '

测试内容

', + category: '安全测试', + tags: ['安全'], + status: 'published' as const, + }, + }, +};