const { test, expect } = require('@playwright/test'); const testData = require('./fixtures/test-data'); const { cleanDatabase, seedExistingUser, disconnect } = require('./fixtures/database'); test.describe('认证流程', () => { test.beforeAll(async () => { await cleanDatabase(); await seedExistingUser(); }); test.afterAll(async () => { await cleanDatabase(); await disconnect(); }); test('注册新用户成功', async ({ page }) => { await page.goto('/'); // 点击「我的 XXX」卡片进入 auth 视图(未登录时) await page.locator('[data-action="open-characters"]').first().click(); await expect(page.locator('#auth')).toBeVisible(); // 切换到注册 tab await page.locator('.auth-tabs [data-tab="register"]').click(); // 等待注册表单的 fadeIn 动画完成 await expect(page.locator('[data-form="register"]')).toBeVisible(); await page.waitForTimeout(400); // 填写注册表单 await page.fill('[data-form="register"] [name="account"]', testData.users.newUser.account); await page.fill('[data-form="register"] [name="password"]', testData.users.newUser.password); await page.fill('[data-form="register"] [name="confirmPassword"]', testData.users.newUser.password); // 提交 await page.locator('[data-form="register"] button[type="submit"]').click(); // 注册成功后自动成为创作者,应跳转到创作者中心 await expect(page.locator('#creator-center')).toBeVisible({ timeout: 5000 }); }); test('重复注册同一账号失败', async ({ page }) => { await page.goto('/'); await page.locator('[data-action="open-characters"]').first().click(); await expect(page.locator('#auth')).toBeVisible(); await page.locator('.auth-tabs [data-tab="register"]').click(); // 等待注册表单的 fadeIn 动画完成 await expect(page.locator('[data-form="register"]')).toBeVisible(); await page.waitForTimeout(400); await page.fill('[data-form="register"] [name="account"]', testData.users.existing.account); await page.fill('[data-form="register"] [name="password"]', testData.users.existing.password); await page.fill('[data-form="register"] [name="confirmPassword"]', testData.users.existing.password); // 监听 dialog(错误信息通过 alert 弹出) const dialogPromise = page.waitForEvent('dialog'); await page.locator('[data-form="register"] button[type="submit"]').click(); const dialog = await dialogPromise; expect(dialog.message()).toContain('已注册'); await dialog.accept(); // 应仍停留在 auth 视图 await expect(page.locator('#auth')).toBeVisible(); }); test('登录已有用户成功', async ({ page }) => { await page.goto('/'); await page.locator('[data-action="open-characters"]').first().click(); await expect(page.locator('#auth')).toBeVisible(); // 默认在登录 tab await page.fill('[data-form="login"] [name="account"]', testData.users.existing.account); await page.fill('[data-form="login"] [name="password"]', testData.users.existing.password); await page.locator('[data-form="login"] button[type="submit"]').click(); // 登录成功后(existing 是创作者)应跳转到创作者中心 await expect(page.locator('#creator-center')).toBeVisible({ timeout: 5000 }); }); test('错误密码登录失败', async ({ page }) => { await page.goto('/'); await page.locator('[data-action="open-characters"]').first().click(); await expect(page.locator('#auth')).toBeVisible(); await page.fill('[data-form="login"] [name="account"]', testData.users.existing.account); await page.fill('[data-form="login"] [name="password"]', 'wrongpassword'); const dialogPromise = page.waitForEvent('dialog'); await page.locator('[data-form="login"] button[type="submit"]').click(); const dialog = await dialogPromise; expect(dialog.message()).toContain('账号或密码错误'); await dialog.accept(); // 应仍停留在 auth 视图 await expect(page.locator('#auth')).toBeVisible(); }); test('注册时密码不一致提示', async ({ page }) => { await page.goto('/'); await page.locator('[data-action="open-characters"]').first().click(); await expect(page.locator('#auth')).toBeVisible(); await page.locator('.auth-tabs [data-tab="register"]').click(); // 等待注册表单的 fadeIn 动画完成 await expect(page.locator('[data-form="register"]')).toBeVisible(); await page.waitForTimeout(400); await page.fill('[data-form="register"] [name="account"]', 'mismatch_user'); await page.fill('[data-form="register"] [name="password"]', 'password1'); await page.fill('[data-form="register"] [name="confirmPassword"]', 'password2'); // 密码不一致通过原生 setCustomValidity + reportValidity 提示(非 alert) await page.locator('[data-form="register"] button[type="submit"]').click(); // 验证 confirmPassword 字段的 validationMessage 包含「不一致」 const validationMessage = await page .locator('[data-form="register"] [name="confirmPassword"]') .evaluate((el) => el.validationMessage); expect(validationMessage).toContain('不一致'); // 应仍停留在 auth 视图 await expect(page.locator('#auth')).toBeVisible(); }); test('登出后回到首页', async ({ page }) => { // 先登录 await page.goto('/'); await page.locator('[data-action="open-characters"]').first().click(); await expect(page.locator('#auth')).toBeVisible(); await page.fill('[data-form="login"] [name="account"]', testData.users.existing.account); await page.fill('[data-form="login"] [name="password"]', testData.users.existing.password); await page.locator('[data-form="login"] button[type="submit"]').click(); await expect(page.locator('#creator-center')).toBeVisible({ timeout: 5000 }); // 切换到设置 tab(登出按钮在设置面板) await page.locator('[data-center-tab="settings"]').click(); await expect(page.locator('#center-settings')).toBeVisible(); // 点击登出 await page.locator('[data-action="logout"]').click(); // 应回到首页 await expect(page.locator('#landing')).toBeVisible(); }); test('登录态持久化(刷新页面后仍登录)', async ({ page }) => { // 先登录 await page.goto('/'); await page.locator('[data-action="open-characters"]').first().click(); await expect(page.locator('#auth')).toBeVisible(); await page.fill('[data-form="login"] [name="account"]', testData.users.existing.account); await page.fill('[data-form="login"] [name="password"]', testData.users.existing.password); await page.locator('[data-form="login"] button[type="submit"]').click(); await expect(page.locator('#creator-center')).toBeVisible({ timeout: 5000 }); // 刷新页面 await page.reload(); // 首页应可见,且卡片按钮文案应变化(不再是「登录 / 注册」) await expect(page.locator('#landing')).toBeVisible(); await expect(page.locator('#characters-btn')).not.toHaveText(/登录/); }); });