/** * 视觉测试认证辅助 * * 提供登录辅助函数与 storageState 持久化能力, * 避免每个视觉测试用例都重复走登录流程。 */ import type { Page } from "@playwright/test" import { STORAGE_STATE_DIR, type UserRole } from "../visual.config" /** 测试账号配置(可通过环境变量覆盖) */ export const TEST_ACCOUNTS: Record = { admin: { email: process.env.VISUAL_ADMIN_EMAIL ?? "admin@xiaoxue.edu.cn", password: process.env.VISUAL_ADMIN_PASSWORD ?? "123456", }, teacher: { email: process.env.VISUAL_TEACHER_EMAIL ?? "admin@xiaoxue.edu.cn", password: process.env.VISUAL_TEACHER_PASSWORD ?? "123456", }, student: { email: process.env.VISUAL_STUDENT_EMAIL ?? "admin@xiaoxue.edu.cn", password: process.env.VISUAL_STUDENT_PASSWORD ?? "123456", }, } /** 角色对应的 storageState 文件路径(相对项目根) */ export function storageStatePath(role: UserRole): string { return `${STORAGE_STATE_DIR}/${role}.json` } /** * 在页面上执行登录流程 * * 走真实的 UI 登录流程,以便 next-auth cookie 写入浏览器上下文。 */ export async function loginByUI(page: Page, role: UserRole): Promise { const { email, password } = TEST_ACCOUNTS[role] await page.goto("/login") await page.getByLabel("Email").fill(email) await page.getByLabel("Password").fill(password) await page.getByRole("button", { name: "Sign In with Email" }).click() // 等待离开登录页 await page.waitForURL((url) => !url.pathname.startsWith("/login"), { timeout: 30000 }) } /** * 设置认证状态 * * 若已存在该角色的 storageState 文件,则直接复用; * 否则走 UI 登录流程并保存 storageState 以便后续复用。 * * @param page Playwright Page 实例 * @param role 角色 */ export async function setupAuthState(page: Page, role: UserRole): Promise { // Playwright 在 project 配置里通过 storageState 注入更高效, // 这里提供运行时降级方案:直接走 UI 登录。 await loginByUI(page, role) }