From 3e6b2ac057d0bcf337d6423ba0e8bcc375038193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?= Date: Tue, 7 Apr 2026 10:17:47 +0800 Subject: [PATCH] =?UTF-8?q?feat(e2e):=20=E5=A2=9E=E5=BC=BA=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=90=AF=E5=8A=A8=E7=A8=B3=E5=AE=9A=E6=80=A7=E5=92=8C?= =?UTF-8?q?=E5=81=A5=E5=BA=B7=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化内容: 1. 增加服务启动超时时间 - 后端服务:60秒 -> 90秒 - 网关服务:60秒 -> 90秒 - 前端服务:60秒 -> 90秒 2. 改进健康检查逻辑 - 添加请求超时控制(5秒) - 后端服务:增加登录API连通性验证 - 网关服务:增加登录API连通性验证 - 确保服务真正可用后才继续 3. 增强服务状态监控 - 监控所有服务(后端、网关、前端) - 每30秒检查一次服务状态 - 发现异常立即报警 4. 添加综合验证机制 - 验证所有服务健康状态 - 验证网关到后端的连通性 - 确保整个链路可用 预期效果: - 提高服务启动成功率 - 及早发现服务问题 - 确保测试环境稳定 --- novalon-manage-web/e2e/global-setup.ts | 144 +++++++++++++++++++++++-- 1 file changed, 135 insertions(+), 9 deletions(-) diff --git a/novalon-manage-web/e2e/global-setup.ts b/novalon-manage-web/e2e/global-setup.ts index 8950036..891cc65 100644 --- a/novalon-manage-web/e2e/global-setup.ts +++ b/novalon-manage-web/e2e/global-setup.ts @@ -27,16 +27,51 @@ async function checkBackendHealth(): Promise { } } +async function checkGatewayHealth(): Promise { + try { + const response = await fetch('http://localhost:8080/actuator/health', { + signal: AbortSignal.timeout(5000) + } as any); + if (response.ok) { + const data = await response.json(); + return data.status === 'UP'; + } + return false; + } catch (error) { + return false; + } +} + +async function checkFrontendHealth(): Promise { + try { + const response = await fetch('http://localhost:3002', { + signal: AbortSignal.timeout(5000) + } as any); + return response.ok; + } catch (error) { + return false; + } +} + function startHealthMonitoring() { if (healthCheckInterval) { clearInterval(healthCheckInterval); } healthCheckInterval = setInterval(async () => { - const isHealthy = await checkBackendHealth(); - if (!isHealthy) { + const backendHealthy = await checkBackendHealth(); + const gatewayHealthy = await checkGatewayHealth(); + const frontendHealthy = await checkFrontendHealth(); + + if (!backendHealthy) { console.error('⚠️ 后端服务健康检查失败!'); } + if (!gatewayHealthy) { + console.error('⚠️ 网关服务健康检查失败!'); + } + if (!frontendHealthy) { + console.error('⚠️ 前端服务健康检查失败!'); + } }, 30000); } @@ -228,6 +263,9 @@ async function globalSetup(config: FullConfig) { console.log('⏳ 等待前端服务就绪...'); await waitForFrontendReady(); + console.log('🔍 验证所有服务连通性...'); + await verifyAllServices(); + console.log('🧹 清理测试数据...'); await cleanupTestData(); @@ -236,18 +274,86 @@ async function globalSetup(config: FullConfig) { console.log('✅ 全局测试环境设置完成'); } +async function verifyAllServices(): Promise { + console.log(' 验证后端服务...'); + const backendOk = await checkBackendHealth(); + if (!backendOk) { + throw new Error('❌ 后端服务验证失败'); + } + console.log(' ✅ 后端服务正常'); + + console.log(' 验证网关服务...'); + const gatewayOk = await checkGatewayHealth(); + if (!gatewayOk) { + throw new Error('❌ 网关服务验证失败'); + } + console.log(' ✅ 网关服务正常'); + + console.log(' 验证前端服务...'); + const frontendOk = await checkFrontendHealth(); + if (!frontendOk) { + throw new Error('❌ 前端服务验证失败'); + } + console.log(' ✅ 前端服务正常'); + + console.log(' 验证网关到后端的连通性...'); + try { + const response = await fetch('http://localhost:8080/api/auth/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ username: 'admin', password: 'admin123' }), + signal: AbortSignal.timeout(10000) as any + }); + + if (!response.ok) { + throw new Error(`网关到后端连通性验证失败,状态码: ${response.status}`); + } + + const data = await response.json(); + if (!data.token) { + throw new Error('网关到后端连通性验证失败,未返回token'); + } + + console.log(' ✅ 网关到后端连通性正常'); + } catch (error) { + throw new Error(`❌ 网关到后端连通性验证失败: ${error}`); + } + + console.log('✅ 所有服务验证通过'); +} + async function waitForBackendReady(): Promise { - const maxRetries = 60; + const maxRetries = 90; const retryInterval = 1000; for (let i = 0; i < maxRetries; i++) { try { - const response = await fetch('http://localhost:8084/actuator/health'); + const response = await fetch('http://localhost:8084/actuator/health', { + signal: AbortSignal.timeout(5000) as any + }); if (response.ok) { const data = await response.json(); if (data.status === 'UP') { console.log(`✅ 后端服务健康检查通过 (尝试 ${i + 1}/${maxRetries})`); - return; + + // 验证服务连通性:测试登录API + try { + const loginTest = await fetch('http://localhost:8084/api/auth/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ username: 'admin', password: 'admin123' }), + signal: AbortSignal.timeout(10000) as any + }); + + if (loginTest.ok) { + console.log('✅ 后端服务连通性验证通过(登录API可用)'); + return; + } else { + console.log(`⚠️ 后端服务连通性验证失败,状态码: ${loginTest.status}`); + } + } catch (error) { + console.log('⚠️ 后端服务连通性验证失败,继续等待...'); + } } } } catch (error) { @@ -263,17 +369,37 @@ async function waitForBackendReady(): Promise { } async function waitForGatewayReady(): Promise { - const maxRetries = 60; + const maxRetries = 90; const retryInterval = 1000; for (let i = 0; i < maxRetries; i++) { try { - const response = await fetch('http://localhost:8080/actuator/health'); + const response = await fetch('http://localhost:8080/actuator/health', { + signal: AbortSignal.timeout(5000) as any + }); if (response.ok) { const data = await response.json(); if (data.status === 'UP') { console.log(`✅ 网关服务健康检查通过 (尝试 ${i + 1}/${maxRetries})`); - return; + + // 验证网关连通性:通过网关测试登录API + try { + const loginTest = await fetch('http://localhost:8080/api/auth/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ username: 'admin', password: 'admin123' }), + signal: AbortSignal.timeout(10000) as any + }); + + if (loginTest.ok) { + console.log('✅ 网关服务连通性验证通过(登录API可用)'); + return; + } else { + console.log(`⚠️ 网关服务连通性验证失败,状态码: ${loginTest.status}`); + } + } catch (error) { + console.log('⚠️ 网关服务连通性验证失败,继续等待...'); + } } } } catch (error) { @@ -289,7 +415,7 @@ async function waitForGatewayReady(): Promise { } async function waitForFrontendReady(): Promise { - const maxRetries = 60; + const maxRetries = 90; const retryInterval = 1000; for (let i = 0; i < maxRetries; i++) {