|
- import type { Page, Route } from '@playwright/test'
-
- import { captureScreenshot, expect, test } from './fixtures'
-
- const profile = {
- user: {
- id: '1',
- username: 'admin',
- displayName: '系统管理员',
- departmentId: '10',
- departmentName: '信息中心',
- mustChangePassword: false,
- version: 3,
- },
- activeRoleId: '100',
- activeRole: { id: '100', code: 'admin', name: '管理员' },
- roles: [
- {
- id: '100',
- code: 'admin',
- name: '管理员',
- shortName: '管',
- status: 1,
- builtIn: 1,
- isSuperAdmin: 1,
- dataScopeCode: 'ALL',
- },
- ],
- permissions: ['dashboard.view'],
- authorizationMode: 'SINGLE_ACTIVE',
- loginTime: 1786387200,
- } as const
-
- const envelope = (data: unknown, requestId: string) => JSON.stringify({
- code: 200,
- message: '成功',
- data,
- timestamp: '2026-08-11T10:00:00+08:00',
- requestId,
- })
-
- const fulfillJson = (route: Route, data: unknown, requestId: string, status = 200) => route.fulfill({
- status,
- contentType: 'application/json',
- body: envelope(data, requestId),
- })
-
- const prepareAuthenticatedProfile = async (page: Page) => {
- await page.addInitScript(() => {
- sessionStorage.setItem('unreal-tran:web:access-token:v1', 'contract-access-token')
- })
- await page.route('**/api/auth/v1/auth/me', (route) => fulfillJson(route, profile, 'ute2e-profile-me'))
- await page.route('**/api/auth/v1/menus/navigation', (route) => fulfillJson(route, [], 'ute2e-profile-menu'))
- }
-
- test.describe('平台账号与个人中心', () => {
- test('页头精简且账号菜单仅保留个人中心和退出登录', async ({ page }, testInfo) => {
- await prepareAuthenticatedProfile(page)
- await page.goto('/profile')
-
- const header = page.locator('.platform-header')
- await expect(header).toBeVisible()
- expect((await header.boundingBox())?.height).toBeLessThanOrEqual(62)
- await expect(header).not.toContainText('Maintenance Digital Workshop')
-
- await page.getByRole('button', { name: '账号菜单:系统管理员' }).click()
- const dropdown = page.locator('.user-dropdown:visible')
- await expect(dropdown).toBeVisible()
- await expect(dropdown.locator('.el-dropdown-menu__item')).toHaveCount(2)
- await expect(dropdown.getByText('个人中心', { exact: true })).toBeVisible()
- await expect(dropdown.getByText('退出登录', { exact: true })).toBeVisible()
- await expect(dropdown).not.toContainText('修改密码')
- await expect(dropdown).not.toContainText('角色切换')
- await page.keyboard.press('Escape')
- await captureScreenshot(page, testInfo, 'profile-header-account-menu')
- })
-
- test('个人中心展示真实资料并通过接口修改密码', async ({ page }, testInfo) => {
- await prepareAuthenticatedProfile(page)
- let passwordRequest: Record<string, unknown> | null = null
- await page.route('**/api/auth/v1/auth/password', async (route) => {
- passwordRequest = route.request().postDataJSON() as Record<string, unknown>
- await fulfillJson(route, { reauthenticationRequired: false }, 'ute2e-profile-password')
- })
- await page.goto('/profile')
-
- await expect(page.getByRole('heading', { name: '个人中心' })).toBeVisible()
- await expect(page.getByText('系统管理员 · admin', { exact: true })).toBeVisible()
- const descriptions = page.locator('.profile-descriptions')
- await expect(descriptions).toHaveClass(/el-descriptions/)
- await expect(descriptions.locator('.el-descriptions__table')).toBeVisible()
- await expect(descriptions).toContainText('信息中心')
- await expect(descriptions).toContainText('管理员')
- const columnWidths = await page.locator('.profile-grid > .system-panel').evaluateAll((panels) => panels.map((panel) => panel.getBoundingClientRect().width))
- expect(columnWidths).toHaveLength(2)
- expect(Math.abs(columnWidths[0]! - columnWidths[1]!)).toBeLessThanOrEqual(1)
-
- const currentPassword = page.locator('input[name="currentPassword"]')
- const newPassword = page.locator('input[name="newPassword"]')
- const confirmPassword = page.locator('input[name="confirmPassword"]')
- await expect(currentPassword).toHaveAttribute('placeholder', '请输入当前密码')
- await expect(newPassword).toHaveAttribute('placeholder', '请输入符合全部规则的新密码')
- await expect(confirmPassword).toHaveAttribute('placeholder', '请再次输入新密码')
- await currentPassword.fill('Current-Password-1')
- await expect(page.locator('.profile-password .password-requirements .is-unmet')).toHaveCount(5)
- await newPassword.fill('Updated-Password-2')
- await expect(page.locator('.profile-password .password-requirements .is-met')).toHaveCount(5)
- await confirmPassword.fill('Updated-Password-2')
- const passwordToggles = page.locator('.profile-password .el-input__password')
- await expect(passwordToggles).toHaveCount(3)
- await expect(passwordToggles.locator('svg')).toHaveCount(3)
- await passwordToggles.first().click()
- await expect(currentPassword).toHaveAttribute('type', 'text')
- await passwordToggles.first().click()
- await expect(currentPassword).toHaveAttribute('type', 'password')
- await page.getByRole('button', { name: '修改密码' }).click()
- await expect.poll(() => passwordRequest).toEqual({
- oldPassword: 'Current-Password-1',
- newPassword: 'Updated-Password-2',
- })
- await expect(page.getByText('密码修改成功', { exact: true })).toBeVisible()
- await expect(currentPassword).toHaveValue('')
- await expect(newPassword).toHaveValue('')
- await expect(confirmPassword).toHaveValue('')
- await captureScreenshot(page, testInfo, 'profile-information-and-password')
-
- await page.setViewportSize({ width: 375, height: 812 })
- await expect(descriptions).toBeVisible()
- const hasHorizontalOverflow = await page.locator('.profile-page').evaluate((element) => element.scrollWidth > element.clientWidth + 1)
- expect(hasHorizontalOverflow).toBe(false)
- await captureScreenshot(page, testInfo, 'profile-mobile-descriptions')
- })
-
- test('首次强制改密复用相同的五项密码规则', async ({ page }, testInfo) => {
- await page.addInitScript(() => {
- sessionStorage.setItem('unreal-tran:web:access-token:v1', 'contract-access-token')
- })
- let mustChangePassword = true
- let passwordChanged = false
- await page.route('**/api/auth/v1/auth/me', (route) => {
- if (passwordChanged) {
- return route.fulfill({
- status: 403,
- contentType: 'application/json',
- body: JSON.stringify({
- code: 40302,
- message: '首次登录必须先修改密码',
- data: null,
- timestamp: '2026-08-11T10:00:00+08:00',
- requestId: 'ute2e-forced-password-stale-me',
- }),
- })
- }
- return fulfillJson(route, {
- ...profile,
- user: { ...profile.user, mustChangePassword },
- mustChangePassword,
- }, 'ute2e-forced-password-me')
- })
- await page.route('**/api/auth/v1/menus/navigation', (route) => fulfillJson(route, [], 'ute2e-forced-password-menu'))
- let passwordRequest: Record<string, unknown> | null = null
- await page.route('**/api/auth/v1/auth/initial-password', async (route) => {
- passwordRequest = route.request().postDataJSON() as Record<string, unknown>
- mustChangePassword = false
- passwordChanged = true
- await fulfillJson(route, {
- accessToken: 'fresh-access-token',
- refreshToken: 'fresh-refresh-token',
- tokenType: 'Bearer',
- accessExpiresTime: 1786177800,
- refreshExpiresTime: 1786780800,
- user: {
- ...profile,
- user: { ...profile.user, mustChangePassword: false },
- mustChangePassword: false,
- },
- }, 'ute2e-forced-password-change')
- })
-
- await page.goto('/change-password')
- await expect(page.getByRole('heading', { name: '首次登录修改密码' })).toBeVisible()
- const inputs = page.locator('.password-card input')
- await expect(inputs).toHaveCount(2)
- const newPassword = inputs.nth(0)
- const confirmation = inputs.nth(1)
- const submit = page.getByRole('button', { name: '确认修改并登录' })
- await expect(page.getByLabel('当前密码')).toHaveCount(0)
- await expect(page.locator('.password-requirements .is-unmet')).toHaveCount(5)
- await newPassword.fill('MissingCategories')
- await confirmation.fill('MissingCategories')
- await expect(submit).toBeDisabled()
- await newPassword.fill('Forced#Change8')
- await confirmation.fill('Forced#Change8')
- await expect(page.locator('.password-requirements .is-met')).toHaveCount(5)
- await expect(submit).toBeEnabled()
- await captureScreenshot(page, testInfo, 'forced-password-requirements')
- await submit.click()
- await expect.poll(() => passwordRequest).toEqual({
- newPassword: 'Forced#Change8',
- })
- await expect(page).toHaveURL(/\/dashboard/)
- await expect(page.getByText('首次登录必须先修改密码')).toHaveCount(0)
- })
- })
|