Files
wenzi/frontend/e2e-admin/tests/admin.spec.ts

133 lines
5.0 KiB
TypeScript
Raw 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, type Page } from '@playwright/test'
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const evidenceDir = process.env.E2E_EVIDENCE_DIR
? path.resolve(process.env.E2E_EVIDENCE_DIR)
: path.resolve(__dirname, '../../../evidence/run-unknown')
const ensureDir = (dir: string) => {
fs.mkdirSync(dir, { recursive: true })
}
const appendLog = (filePath: string, line: string) => {
ensureDir(path.dirname(filePath))
fs.appendFileSync(filePath, `${line}\n`, { encoding: 'utf8' })
}
const consoleLogPath = path.join(evidenceDir, 'e2e/console.log')
const networkLogPath = path.join(evidenceDir, 'e2e/network.log')
const logConsole = (type: string, text: string) => {
appendLog(consoleLogPath, `[${new Date().toISOString()}] ${type}: ${text}`)
}
const logNetwork = (line: string) => {
appendLog(networkLogPath, `[${new Date().toISOString()}] ${line}`)
}
const attachUnauthorizedTracker = (page: Page) => {
const unauthorizedApiResponses: string[] = []
page.on('response', (res) => {
const status = res.status()
const url = res.url()
if (url.includes('/api/') && (status === 401 || status === 403)) {
unauthorizedApiResponses.push(`${status} ${res.request().method()} ${url}`)
}
})
return unauthorizedApiResponses
}
// 稳定性修复:统一等待应用真正可交互,替代固定 sleep。
const waitForAdminReady = async (page: Page) => {
await page.waitForLoadState('domcontentloaded')
await expect(page.locator('#app')).toBeAttached({ timeout: 15000 })
await expect(page.getByText('Mosquito Admin')).toBeVisible({ timeout: 15000 })
await expect(page.getByText('演示模式', { exact: true })).toBeVisible({ timeout: 15000 })
}
test.describe.serial('Admin E2E (real backend)', () => {
test.beforeEach(async ({ page }) => {
// 每个测试前清理localStorage确保测试状态干净
// 但为了 demo 模式正常工作,需要预置演示用户信息
await page.addInitScript(() => {
localStorage.clear()
// 预置演示模式超级管理员用户信息(用于 demo 模式权限加载)
const demoUser = {
id: 'demo-super-admin',
name: '超级管理员',
email: 'demo@mosquito.com',
role: 'super_admin'
}
localStorage.setItem('mosquito_user', JSON.stringify(demoUser))
localStorage.setItem('mosquito_token', 'demo_token_' + Date.now())
localStorage.setItem('userRole', 'super_admin')
})
page.on('console', (msg) => logConsole(msg.type(), msg.text()))
page.on('pageerror', (err) => logConsole('pageerror', err.message))
page.on('requestfailed', (req) => {
logNetwork(`requestfailed ${req.method()} ${req.url()} ${req.failure()?.errorText ?? ''}`)
})
page.on('response', (res) => {
const url = res.url()
if (url.includes('/api/')) {
logNetwork(`response ${res.status()} ${res.request().method()} ${url}`)
}
})
})
test('dashboard renders correctly', async ({ page }) => {
const unauthorizedApiResponses = attachUnauthorizedTracker(page)
await page.goto('/')
await waitForAdminReady(page)
// 路由配置: / 重定向到 /dashboard
await expect(page).toHaveURL(/\/dashboard/)
// P0修复管理台正常页面出现401/403时必须失败避免“页面壳子存在即通过”。
expect(unauthorizedApiResponses, `dashboard出现未授权API响应: ${unauthorizedApiResponses.join(' | ')}`).toEqual([])
console.log('✅ Dashboard页面加载成功')
})
test('users page loads', async ({ page }) => {
const unauthorizedApiResponses = attachUnauthorizedTracker(page)
await page.goto('/users')
await waitForAdminReady(page)
// 等待页面URL变为/users
await expect(page).toHaveURL(/\/users/, { timeout: 15000 })
// 检查页面没有重定向到403说明有权限访问
await expect(page).not.toHaveURL(/\/403/)
// 检查页面是否显示用户相关内容(可能有多种方式渲染)
// 尝试查找"用户管理"标题使用heading role更精确
// 强断言:页面必须包含用户相关内容
await expect(
page.getByRole('heading', { name: '用户管理' }),
'用户管理页面应包含用户相关内容'
).toBeVisible({ timeout: 10000 })
// P0修复用户管理页若出现401/403必须显式失败。
expect(unauthorizedApiResponses, `users页出现未授权API响应: ${unauthorizedApiResponses.join(' | ')}`).toEqual([])
console.log('✅ 用户页面加载成功')
})
test('forbidden page loads', async ({ page }) => {
await page.goto('/403')
await waitForAdminReady(page)
// 稳定性修复:校验 403 页关键文案,避免仅检查 #app 导致“假通过”。
await expect(page.getByText('403')).toBeVisible({ timeout: 15000 })
await expect(page).toHaveURL(/\/403/)
console.log('✅ 403页面加载成功')
})
})