library-picturebook-activity/frontend/e2e/leai/auth-api.spec.ts
En 922f650365 feat: 添加乐读派(leai)集成模块及E2E测试基础设施
后端:
- 新增 leai 模块:认证、Webhook、数据同步、定时对账
- 新增 LeaiConfig/RestTemplateConfig/SchedulingConfig 配置
- 新增 FlywayRepairConfig 处理迁移修复
- 新增 V5__leai_integration.sql 迁移脚本
- 扩展所有实体类添加 tenantId 等字段
- 更新 SecurityConfig 放行 leai 公开接口
- 添加 application-test.yml 测试环境配置

前端:
- 添加乐读派认证 API (public.ts)
- 优化 Generating.vue 生成页
- 添加 Playwright E2E 测试配置及依赖
- 添加测试 fixtures、utils、mock-h5.html
- 添加 leai 模块完整 E2E 测试套件

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 21:52:32 +08:00

116 lines
3.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { test, expect } from '../fixtures/auth.fixture'
/**
* P0: 认证 API 测试
*
* 测试 LeaiAuthController 的三个接口:
* - GET /leai-auth/tokeniframe 主入口)
* - GET /leai-auth302 重定向)
* - GET /leai-auth/refresh-tokenToken 刷新)
*/
const API_BASE = process.env.API_BASE_URL || 'http://localhost:8580/api'
test.describe('乐读派认证 API', () => {
test.describe('GET /leai-auth/token', () => {
test('未登录 — 返回 401', async ({ request }) => {
const resp = await request.get(`${API_BASE}/leai-auth/token`)
expect(resp.status()).toBe(401)
})
test('已登录 — 返回 token + orgId + h5Url + phone', async ({ authedApi }) => {
const resp = await authedApi.get(`${API_BASE}/leai-auth/token`)
expect(resp.status()).toBe(200)
const json = await resp.json()
expect(json.code).toBe(200)
expect(json.data).toBeDefined()
const data = json.data
expect(data).toHaveProperty('token')
expect(data).toHaveProperty('orgId')
expect(data).toHaveProperty('h5Url')
expect(data).toHaveProperty('phone')
expect(data.token).toBeTruthy()
expect(data.orgId).toBeTruthy()
expect(data.h5Url).toContain('http')
})
test('返回的 token 为非空字符串', async ({ authedApi }) => {
const resp = await authedApi.get(`${API_BASE}/leai-auth/token`)
const json = await resp.json()
expect(typeof json.data.token).toBe('string')
expect(json.data.token.length).toBeGreaterThan(10)
})
})
test.describe('GET /leai-auth/refresh-token', () => {
test('未登录 — 返回 401', async ({ request }) => {
const resp = await request.get(`${API_BASE}/leai-auth/refresh-token`)
expect(resp.status()).toBe(401)
})
test('已登录 — 刷新成功', async ({ authedApi }) => {
const resp = await authedApi.get(`${API_BASE}/leai-auth/refresh-token`)
expect(resp.status()).toBe(200)
const json = await resp.json()
expect(json.code).toBe(200)
expect(json.data).toHaveProperty('token')
expect(json.data).toHaveProperty('orgId')
expect(json.data).toHaveProperty('phone')
})
test('连续两次刷新返回不同 token', async ({ authedApi }) => {
const resp1 = await authedApi.get(`${API_BASE}/leai-auth/refresh-token`)
const json1 = await resp1.json()
// 短暂等待确保时间戳不同
await new Promise((r) => setTimeout(r, 100))
const resp2 = await authedApi.get(`${API_BASE}/leai-auth/refresh-token`)
const json2 = await resp2.json()
expect(json1.data.token).toBeTruthy()
expect(json2.data.token).toBeTruthy()
// 两次 token 应不同(每次换新 session
expect(json1.data.token).not.toBe(json2.data.token)
})
})
test.describe('GET /leai-auth302 重定向)', () => {
test('未登录 — 返回 401', async ({ request }) => {
const resp = await request.get(`${API_BASE}/leai-auth`, {
maxRedirects: 0,
})
// 可能是 401 或 302 到登录页
expect([302, 401]).toContain(resp.status())
})
test('已登录 — 302 重定向到 H5', async ({ authedApi }) => {
const resp = await authedApi.get(`${API_BASE}/leai-auth`, {
maxRedirects: 0,
})
expect(resp.status()).toBe(302)
const location = resp.headers()['location']
expect(location).toBeDefined()
expect(location).toContain('token=')
expect(location).toContain('orgId=')
expect(location).toContain('phone=')
})
test('带 returnPath — 重定向 URL 包含 returnPath', async ({ authedApi }) => {
const resp = await authedApi.get(`${API_BASE}/leai-auth?returnPath=/edit-info/test123`, {
maxRedirects: 0,
})
expect(resp.status()).toBe(302)
const location = resp.headers()['location']
expect(location).toContain('returnPath=')
expect(location).toContain('edit-info')
})
})
})