From 33a2dd454fa103decd30426facdaf4cf9eb73109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?= Date: Fri, 13 Mar 2026 11:38:00 +0800 Subject: [PATCH] feat: integrate test history recording into test execution --- e2e/global-setup.ts | 53 +++++++++++++++++++++++++-------- e2e/global-teardown.ts | 24 +++++++++++++++ e2e/playwright.config.tiered.ts | 1 + e2e/src/utils/test-history.ts | 4 +-- 4 files changed, 67 insertions(+), 15 deletions(-) create mode 100644 e2e/global-teardown.ts diff --git a/e2e/global-setup.ts b/e2e/global-setup.ts index 47f8f43..53319d0 100644 --- a/e2e/global-setup.ts +++ b/e2e/global-setup.ts @@ -1,25 +1,52 @@ import { chromium, FullConfig } from '@playwright/test'; import { getEnvironment } from './src/config/environments'; +import { TestHistoryManager } from './src/utils/test-history'; const env = getEnvironment(); +const historyManager = new TestHistoryManager(); async function globalSetup(config: FullConfig) { + console.log('🚀 开始E2E测试全局设置...'); + console.log('📍 Base URL:', env.baseURL); + const browser = await chromium.launch(); const page = await browser.newPage(); - // 登录并保存认证状态 - await page.goto(`${env.baseURL}/admin/login`); - await page.locator('#email').fill('admin@novalon.cn'); - await page.locator('#password').fill('admin123456'); - await page.locator('button[type="submit"]').click(); - - // 等待登录成功 - await page.waitForURL(/\/admin(?!\/login)/); - - // 保存认证状态 - await page.context().storageState({ path: '.auth/admin.json' }); - - await browser.close(); + try { + console.log('📝 访问登录页面...'); + await page.goto(`${env.baseURL}/admin/login`, { waitUntil: 'networkidle' }); + + console.log('🔑 填写登录信息...'); + await page.locator('#email').fill('admin@novalon.cn'); + await page.locator('#password').fill('admin123456'); + + console.log('🖱️ 点击登录按钮...'); + await page.locator('button[type="submit"]').click(); + + console.log('⏳ 等待登录成功...'); + console.log('🔍 当前URL:', page.url()); + + try { + await page.waitForURL(/\/admin(?!\/login)/, { timeout: 15000 }); + console.log('✅ 登录成功,当前URL:', page.url()); + } catch (error) { + console.log('❌ 登录超时,当前URL:', page.url()); + console.log('📸 截图保存...'); + await page.screenshot({ path: 'test-results/login-failure.png' }); + throw error; + } + + console.log('💾 保存认证状态...'); + await page.context().storageState({ path: '.auth/admin.json' }); + + console.log('✅ 全局设置完成'); + } catch (error) { + console.error('❌ 全局设置失败:', error); + await page.screenshot({ path: 'test-results/setup-error.png' }); + throw error; + } finally { + await browser.close(); + } } export default globalSetup; diff --git a/e2e/global-teardown.ts b/e2e/global-teardown.ts new file mode 100644 index 0000000..a591550 --- /dev/null +++ b/e2e/global-teardown.ts @@ -0,0 +1,24 @@ +import { TestHistoryManager } from './src/utils/test-history'; + +const historyManager = new TestHistoryManager(); + +export async function globalTeardown(config: any, result: any) { + console.log('📊 记录测试执行历史...'); + + for (const suite of result.suites) { + for (const spec of suite.suites) { + for (const test of spec.tests) { + const testId = `${spec.file}::${test.title}`; + historyManager.recordExecution( + testId, + spec.file, + test.title, + test.results[0]?.duration || 0, + test.results[0]?.status === 'passed' + ); + } + } + } + + console.log('✅ 历史记录完成'); +} \ No newline at end of file diff --git a/e2e/playwright.config.tiered.ts b/e2e/playwright.config.tiered.ts index 82c452d..e7508e3 100644 --- a/e2e/playwright.config.tiered.ts +++ b/e2e/playwright.config.tiered.ts @@ -2,6 +2,7 @@ import { defineConfig, devices } from '@playwright/test'; import { getEnvironment } from './src/config/environments'; import { getMobileDevices } from './src/utils/devices'; import { getTestTier, TEST_TIERS } from './src/config/test-tiers'; +import globalSetup from './global-setup'; const env = getEnvironment(); diff --git a/e2e/src/utils/test-history.ts b/e2e/src/utils/test-history.ts index 7f98a38..185403b 100644 --- a/e2e/src/utils/test-history.ts +++ b/e2e/src/utils/test-history.ts @@ -1,5 +1,5 @@ -import fs from 'fs'; -import path from 'path'; +import * as fs from 'fs'; +import * as path from 'path'; interface TestExecutionRecord { testId: string;