From 43048cdc066852ef2550264e6018bfae9dce3cf5 Mon Sep 17 00:00:00 2001 From: leiyun Date: Sat, 29 Aug 2026 12:12:54 +0800 Subject: [PATCH] =?UTF-8?q?test:=20=E8=A1=A5=E5=85=85=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E4=B8=8E=E6=99=BA=E8=83=BD=E4=BD=93=E5=9B=9E=E5=BD=92=E8=A6=86?= =?UTF-8?q?=E7=9B=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/auth-navigation.spec.ts | 46 ++++++++++++++++++++++++ tests/iam-lifecycle.spec.ts | 2 +- tests/password-profile-lifecycle.spec.ts | 2 +- tests/zentao-auth-859-861-864.spec.ts | 21 +++++++++-- 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/tests/auth-navigation.spec.ts b/tests/auth-navigation.spec.ts index 0233a42..63e6d1a 100644 --- a/tests/auth-navigation.spec.ts +++ b/tests/auth-navigation.spec.ts @@ -138,6 +138,52 @@ test('管理员可以登录、进入个人菜单并安全退出', async ({ page await expect(page.getByRole('heading', { name: '登录数字人平台', exact: true })).toBeVisible() }) +test('智能体配置未保存时取消退出应保留完整登录态', async ({ page }) => { + await loginAsAdmin(page) + await page.goto('/agents/manage') + + const configure = page.getByRole('button', { name: '配置', exact: true }).first() + await expect(configure).toBeVisible() + await configure.click() + await expect(page).toHaveURL(/\/agents\/[^/?]+(?:\?|$)/) + + const tabs = page.getByRole('navigation', { name: '配置分区' }) + await tabs.getByRole('button', { name: /^身份设置/ }).click() + const prompt = page.locator('.detail-body:visible .identity-editor textarea') + await expect(prompt).toBeVisible() + await prompt.fill(`${await prompt.inputValue()} 临时未保存内容`) + await expect(page.getByText('有未保存的修改', { exact: true })).toBeVisible() + + let logoutRequests = 0 + page.on('request', (request) => { + if (request.method() === 'POST' && new URL(request.url()).pathname.endsWith('/auth/logout')) logoutRequests += 1 + }) + + const detailUrl = page.url() + await page.locator('.user-menu-trigger').click() + await page.getByRole('menuitem', { name: /退出登录/ }).click() + await confirmMessageBox(page, '退出登录') + const unsavedDialog = page.getByRole('dialog', { name: '未保存的修改' }) + await expect(unsavedDialog).toBeVisible() + await unsavedDialog.getByRole('button', { name: '返回继续编辑' }).click() + + await expect(page).toHaveURL(detailUrl) + await expect(page.locator('.app-shell')).toBeVisible() + await expect(page.locator('#main-sidebar')).toBeVisible() + await expect(page.locator('.user-menu-trigger')).not.toContainText('当前用户') + await expect(page.getByText('有未保存的修改', { exact: true })).toBeVisible() + expect(logoutRequests, '取消离开时不应调用注销接口').toBe(0) + + // 再次退出并明确放弃改动,验证正常退出链路仍然可用。 + await page.locator('.user-menu-trigger').click() + await page.getByRole('menuitem', { name: /退出登录/ }).click() + await confirmMessageBox(page, '退出登录') + await page.getByRole('dialog', { name: '未保存的修改' }) + .getByRole('button', { name: '放弃修改并离开' }).click() + await expect(page).toHaveURL(/\/login(?:\?|$)/) + expect(logoutRequests, '确认离开后应且仅应注销一次').toBe(1) +}) + test('兼容入口和未知地址重定向到正式路由', async ({ page }) => { await loginAsAdmin(page) diff --git a/tests/iam-lifecycle.spec.ts b/tests/iam-lifecycle.spec.ts index 6778a2a..bde2c39 100644 --- a/tests/iam-lifecycle.spec.ts +++ b/tests/iam-lifecycle.spec.ts @@ -190,7 +190,7 @@ test('IAM 真实生命周期:部门、角色、用户、授权、首次改密 await page.getByPlaceholder('请输入新密码').fill(data.finalPassword) await page.getByPlaceholder('请再次输入').fill(data.finalPassword) await captureScreenshot(page, testInfo, '05-initial-password-form', [page.locator('input[type="password"]')]) - await page.getByRole('button', { name: '保存并进入平台' }).click() + await page.getByRole('button', { name: '保存新密码并进入平台' }).click() await expect(page).toHaveURL(/\/overview(?:\?|$)/) await expect(page.locator('.user-menu-trigger')).toContainText(data.editedDisplayName) await captureScreenshot(page, testInfo, '06-student-login-success') diff --git a/tests/password-profile-lifecycle.spec.ts b/tests/password-profile-lifecycle.spec.ts index a807ef5..959b90b 100644 --- a/tests/password-profile-lifecycle.spec.ts +++ b/tests/password-profile-lifecycle.spec.ts @@ -279,7 +279,7 @@ async function completeInitialPasswordInBrowser( response.request().method() === 'PUT' && new URL(response.url()).pathname === '/api/auth/v1/auth/initial-password' )) - await page.getByRole('button', { name: '保存并进入平台' }).click() + await page.getByRole('button', { name: '保存新密码并进入平台' }).click() const response = await changedResponsePromise assertStatus(response, 200, '浏览器完成首次改密') await expect(page).toHaveURL(/\/overview(?:\?|$)/) diff --git a/tests/zentao-auth-859-861-864.spec.ts b/tests/zentao-auth-859-861-864.spec.ts index 97053f9..609efb0 100644 --- a/tests/zentao-auth-859-861-864.spec.ts +++ b/tests/zentao-auth-859-861-864.spec.ts @@ -112,16 +112,33 @@ test('861:首次改密两次输入不一致时立即显示字段提示且不 await seedSession(page) const mocked = await mockAuth(page, { me: 'forced' }) await page.goto('/change-password') + await expect(page.getByText('首次登录安全验证', { exact: true })).toBeVisible() + await expect(page.getByRole('heading', { name: '请先设置新密码' })).toBeVisible() + await expect(page.getByText('为保护账号安全,初始密码不可继续使用。此步骤仅需完成一次。')).toBeVisible() const inputs = page.locator('input[autocomplete="new-password"]') await inputs.nth(0).fill('Strong#Password8') await inputs.nth(1).fill('Different#Pass9') + await expect(page.locator('.password-requirements .is-passed')).toHaveCount(4) await expect(page.getByText('两次输入的新密码不一致', { exact: true })).toBeVisible() - await expect(page.getByRole('button', { name: '保存并进入平台' })).toBeDisabled() + await expect(page.getByRole('button', { name: '保存新密码并进入平台' })).toBeDisabled() expect(mocked.initialPasswordRequests()).toBe(0) await captureScreenshot(page, testInfo, '861-initial-password-mismatch', [inputs]) }) +test('首次登录改密页在 375px 窄屏保持可读且无横向滚动', async ({ page }, testInfo) => { + await page.setViewportSize({ width: 375, height: 812 }) + await seedSession(page) + await mockAuth(page, { me: 'forced' }) + await page.goto('/change-password') + + await expect(page.getByRole('heading', { name: '请先设置新密码' })).toBeVisible() + await expect(page.getByText('首次登录 · 安全设置', { exact: true })).toBeVisible() + const horizontalOverflow = await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth) + expect(horizontalOverflow).toBeLessThanOrEqual(1) + await captureScreenshot(page, testInfo, 'initial-password-mobile-375', [page.locator('input[autocomplete="new-password"]')]) +}) + test('864:首次改密期间账号停用后仅显示一次固定登录提示且不刷新令牌', async ({ page }, testInfo) => { await seedSession(page, true) const mocked = await mockAuth(page, { me: 'forced', initialPassword401: true }) @@ -129,7 +146,7 @@ test('864:首次改密期间账号停用后仅显示一次固定登录提示 const inputs = page.locator('input[autocomplete="new-password"]') await inputs.nth(0).fill('Strong#Password8') await inputs.nth(1).fill('Strong#Password8') - await page.getByRole('button', { name: '保存并进入平台' }).click() + await page.getByRole('button', { name: '保存新密码并进入平台' }).click() await expect(page).toHaveURL(/\/login\?redirect=/) await expect(page.locator('#login-error')).toHaveText('账号、密码或登录身份不匹配')