E2E_TEST_SERVER.md 6.98 KB

E2E 测试服务器配置说明

🌐 测试服务器信息

  • 测试服务器: http://oa-dev.onwall.cn
  • 访问方式: 通过 Vite 反向代理
  • 本地地址: http://localhost:5173
  • 代理前缀: /srv/

📝 配置说明

代理配置

.env.development:

# 反向代理配置
VITE_PROXY_PREFIX = /srv/
VITE_PROXY_TARGET = http://oa-dev.onwall.cn/

所有 /srv/* 的请求都会被代理到 http://oa-dev.onwall.cn/srv/*

Playwright 配置

playwright.config.js:

export default defineConfig({
  use: {
    // 使用本地开发服务器(通过代理访问)
    baseURL: 'http://localhost:5173',
  },

  // 自动启动本地开发服务器
  webServer: {
    command: 'pnpm dev',
    url: 'http://localhost:5173',
    reuseExistingServer: !process.env.CI,
    timeout: 120 * 1000,
  },
})

工作流程

Playwright 测试
    ↓
访问 http://localhost:5173/login
    ↓
Vite 开发服务器(localhost:5173)
    ↓
API 请求:/srv/api/login
    ↓
Vite 反向代理
    ↓
http://oa-dev.onwall.cn/srv/api/login

🔑 测试账号

测试手机号

13761653761

固定验证码

888888

⚠️ 重要:登录流程说明

必须遵循的步骤

测试服务器的登录接口有以下要求:

  1. 必须触发发送验证码接口

    • 不能直接输入手机号和验证码登录
    • 必须点击"发送验证码"按钮
    • 必须等待接口响应
  2. 接口响应后才可输入验证码

    • 等待按钮状态变化(倒计时开始)
    • 或等待 2 秒确保接口响应完成
  3. 验证码固定返回

    • 测试环境会自动返回 888888
    • 无需查看真实短信

正确的登录流程

// ✅ 正确流程
await page.goto('/login')

// 1. 输入手机号
await page.fill('input[name="phone"]', '13761653761')

// 2. 点击"发送验证码"按钮(触发接口)
await page.click('button:has-text("发送验证码")')

// 3. 等待接口响应(重要!)
await page.waitForTimeout(2000)

// 4. 输入验证码
await page.fill('input[name="code"]', '888888')

// 5. 点击登录
await page.click('button[type="submit"]')

错误的登录流程

// ❌ 错误流程(会失败)
await page.goto('/login')

// 1. 输入手机号
await page.fill('input[name="phone"]', '13761653761')

// 2. 直接输入验证码(未触发接口!)
await page.fill('input[name="code"]', '888888')

// 3. 点击登录
await page.click('button[type="submit"]')
// 结果:登录失败,因为没有触发发送验证码接口

🔧 实现代码

完整的登录函数

e2e/helpers/auth.js 中的 login() 函数已实现正确的流程:

export async function login(page, account = TEST_ACCOUNT) {
  // 1. 访问登录页
  await page.goto('/login')

  // 2. 输入手机号
  await page.fill('input[name="phone"]', account.phone)

  // 3. 点击"发送验证码"按钮
  const sendCodeButton = page.locator('button:has-text("发送验证码")')
  await sendCodeButton.click()

  // 4. 等待接口响应(重要!)
  await page.waitForTimeout(2000)

  // 5. 输入验证码
  await page.fill('input[name="code"]', account.code)

  // 6. 点击登录
  await page.click('button[type="submit"]')

  // 7. 等待登录成功
  await page.waitForURL(/\/(home|index)?/)
}

详细的日志输出

登录函数会输出详细的步骤日志:

🔐 开始登录流程...
 已访问登录页
 登录表单已加载
 已输入手机号: 13761653761
 发送验证码按钮已找到
 已点击发送验证码按钮,等待接口响应...
 短信接口已响应,按钮状态: 已禁用, 文本: "60s"
 已输入验证码: 888888
 已点击登录按钮,等待登录响应...
 登录成功(URL 已变化)
 登录流程完成!

🧪 运行测试

直接运行测试

# 运行所有 E2E 测试
pnpm test:e2e

# 运行认证测试
pnpm test:e2e e2e/auth.spec.js

# UI 模式(推荐)
pnpm test:e2e:ui

调试模式

# 有头模式(可以看到浏览器操作)
pnpm test:e2e --headed

# 调试模式(逐步执行)
pnpm test:e2e:debug

📊 验证接口触发

检查网络请求

在 Playwright Inspector 或浏览器开发者工具中可以看到:

1. GET /login
   - 加载登录页面

2. POST /api/send-sms
   Request: {
     phone: "13761653761"
   }
   Response: {
     code: 1,
     data: { success: true }
   }

3. POST /api/login
   Request: {
     phone: "13761653761",
     code: "888888"
   }
   Response: {
     code: 1,
     data: {
       token: "xxx",
       userId: "xxx"
     }
   }

确认接口已触发

在代码中可以通过以下方式确认:

// 监听网络请求
page.on('response', response => {
  if (response.url().includes('send-sms')) {
    console.log('✓ 发送短信接口已调用')
    console.log('状态:', response.status())
  }
})

// 等待接口响应
await page.waitForResponse('**/api/send-sms')

🐛 常见问题

1. 登录失败:接口未触发

原因: 没有点击"发送验证码"按钮或点击后立即输入验证码

解决: 确保使用 login() 函数,该函数会自动等待接口响应

2. 验证码错误

原因:

  • 未使用测试手机号 13761653761
  • 未触发发送验证码接口

解决:

  • 确保使用测试账号
  • 确保点击了"发送验证码"按钮
  • 等待 2 秒后再输入验证码

3. 按钮点击无效

原因: 按钮选择器不正确

解决: 使用多个备选选择器

const sendCodeButton = page
  .locator('button:has-text("发送验证码")')
  .or(page.locator('button:has-text("获取验证码")'))
  .or(page.locator('button:has-text("发送")'))
  .first()

🎯 最佳实践

1. 始终使用 login() 函数

// ✓ 正确
import { login } from './helpers/auth'

test('测试功能', async ({ page }) => {
  await login(page) // 自动处理所有细节
})

// ✗ 错误(可能遗漏步骤)
test('测试功能', async ({ page }) => {
  await page.goto('/login')
  await page.fill('input[name="phone"]', '13761653761')
  await page.click('button')
  // 可能失败,因为没有等待接口响应
})

2. 添加详细日志

test('调试登录流程', async ({ page }) => {
  // 监听所有网络请求
  page.on('request', request => {
    console.log('📤:', request.method(), request.url())
  })

  page.on('response', response => {
    console.log('📥:', response.status(), response.url())
  })

  await login(page)
})

3. 使用调试模式

# UI 模式可以看到每一步操作
pnpm test:e2e:ui

# 逐步执行
pnpm test:e2e:debug

📚 相关文档

🔗 链接