admin-vue3/e2e/helpers/api-mocker.ts

277 lines
7.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import type { Page } from '@playwright/test'
import {
successResponse,
pageResponse,
loginSuccessData,
tenantData,
dictListSimpleData
} from '../fixtures/mock-data'
import { adminPermissionInfo, limitedPermissionInfo } from '../fixtures/permissions'
import { userList, getNextUserId, type MockUser } from '../fixtures/users'
/**
* API Mock 拦截器
* 使用 Playwright page.route() 集中拦截所有 /admin-api/** 请求
*
* 重要Playwright 路由按注册的逆序匹配(后注册 = 高优先级)
* 因此 fallback 必须先注册,具体路由后注册。
*/
interface MockOptions {
/** 使用受限权限而非管理员权限 */
limitedPermissions?: boolean
}
/**
* 设置所有 API Mock 路由
* 统一返回 { code: 0, data: ..., msg: '' } 格式
*/
export async function setupApiMocks(page: Page, options: MockOptions = {}) {
const permissionInfo = options.limitedPermissions
? limitedPermissionInfo
: adminPermissionInfo
// === Fallback 必须最先注册(优先级最低) ===
await page.route('**/admin-api/**', async (route) => {
const method = route.request().method()
// GET 请求返回空列表或 nullPOST/PUT/DELETE 返回 true
const data = method === 'GET' ? null : true
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(data))
})
})
// === 认证相关 ===
// 登录
await page.route('**/admin-api/system/auth/login', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(loginSuccessData))
})
})
// 获取权限信息
await page.route('**/admin-api/system/auth/get-permission-info', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(permissionInfo))
})
})
// 登出
await page.route('**/admin-api/system/auth/logout', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(true))
})
})
// 租户 - 根据名称获取ID
await page.route('**/admin-api/system/tenant/get-id-by-name*', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(tenantData.id))
})
})
// 租户 - 根据域名获取租户信息
await page.route('**/admin-api/system/tenant/get-by-website*', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(null))
})
})
// === 字典 ===
// 字典列表
await page.route('**/admin-api/system/dict-data/simple-list', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(dictListSimpleData))
})
})
// === 用户管理 CRUD ===
// 用户分页列表
await page.route('**/admin-api/system/user/page*', async (route) => {
const url = new URL(route.request().url())
const pageNo = parseInt(url.searchParams.get('pageNo') || '1')
const pageSize = parseInt(url.searchParams.get('pageSize') || '10')
const nickname = url.searchParams.get('nickname') || ''
let filtered = [...userList]
if (nickname) {
filtered = filtered.filter((u) => u.nickname.includes(nickname))
}
const start = (pageNo - 1) * pageSize
const paged = filtered.slice(start, start + pageSize)
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(pageResponse(paged, filtered.length))
})
})
// 用户详情
await page.route('**/admin-api/system/user/get?*', async (route) => {
const url = new URL(route.request().url())
const id = parseInt(url.searchParams.get('id') || '0')
const user = userList.find((u) => u.id === id)
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(user || null))
})
})
// 新增用户
await page.route('**/admin-api/system/user/create', async (route) => {
const newId = getNextUserId()
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(newId))
})
})
// 更新用户
await page.route('**/admin-api/system/user/update', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(true))
})
})
// 删除用户
await page.route('**/admin-api/system/user/delete*', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(true))
})
})
// === 部门 ===
await page.route('**/admin-api/system/dept/list-all-simple', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(
successResponse([
{ id: 100, name: '芋道源码', parentId: 0 },
{ id: 101, name: '研发部门', parentId: 100 },
{ id: 102, name: '测试部门', parentId: 100 },
{ id: 103, name: '运维部门', parentId: 100 }
])
)
})
})
// === 岗位 ===
await page.route('**/admin-api/system/post/list-all-simple', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(
successResponse([
{ id: 1, name: '董事长' },
{ id: 2, name: '项目经理' },
{ id: 4, name: '普通员工' }
])
)
})
})
// === 通知相关 ===
await page.route('**/admin-api/system/notify-message/get-unread-count', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(0))
})
})
}
/**
* 仅设置认证相关 Mock用于 auth.setup.ts
*/
export async function setupAuthMocks(page: Page) {
// === Fallback 必须最先注册(优先级最低) ===
await page.route('**/admin-api/**', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(null))
})
})
// 登录
await page.route('**/admin-api/system/auth/login', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(loginSuccessData))
})
})
// 权限信息
await page.route('**/admin-api/system/auth/get-permission-info', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(adminPermissionInfo))
})
})
// 租户 - 根据名称获取ID登录流程中调用
await page.route('**/admin-api/system/tenant/get-id-by-name*', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(tenantData.id))
})
})
// 租户 - 根据域名获取租户信息(登录页 onMounted 调用)
await page.route('**/admin-api/system/tenant/get-by-website*', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(null))
})
})
// 字典
await page.route('**/admin-api/system/dict-data/simple-list', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(dictListSimpleData))
})
})
// 通知
await page.route('**/admin-api/system/notify-message/get-unread-count', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(successResponse(0))
})
})
}