Ver a proveniência

test: 覆盖系统管理改版

main
leiyun há 3 semanas
ascendente
cometimento
64fa6478aa
5 ficheiros alterados com 118 adições e 50 eliminações
  1. +13
    -11
      tests/system-crud.spec.ts
  2. +47
    -2
      tests/system-inline-statistics.spec.ts
  3. +5
    -13
      tests/system-pages.spec.ts
  4. +9
    -9
      tests/users-department-filter.spec.ts
  5. +44
    -15
      tests/zentao-system-ui-regression.spec.ts

+ 13
- 11
tests/system-crud.spec.ts Ver ficheiro

@@ -93,25 +93,27 @@ async function editAndSearchData(page: Page) {
await expect(roleCardByText(page, `${data.prefix} 已编辑`)).toBeVisible() await expect(roleCardByText(page, `${data.prefix} 已编辑`)).toBeVisible()


await page.goto('/system/departments') await page.goto('/system/departments')
await page.getByPlaceholder('请输入部门、编码、负责人或层级路径').fill(data.departmentCode)
await page.getByPlaceholder('请输入部门、编码或负责人').fill(data.departmentCode)
await page.getByRole('button', { name: '搜索', exact: true }).click() await page.getByRole('button', { name: '搜索', exact: true }).click()
await expect(tableRowByText(page, data.departmentName)).toBeVisible() await expect(tableRowByText(page, data.departmentName)).toBeVisible()
} }


async function grantPermission(page: Page) { async function grantPermission(page: Page) {
await page.goto('/system/permissions')
const roleButton = page.locator('.role-selector > button').filter({ hasText: data.roleName })
await page.goto('/system/roles')
await page.getByPlaceholder('请输入角色名称、编码或说明').fill(data.roleCode)
await page.getByRole('button', { name: '搜索', exact: true }).click()
const roleRow = roleCardByText(page, data.roleName)
await Promise.all([ await Promise.all([
page.waitForResponse((response) => response.request().method() === 'GET' && /\/permissions\/roles\/[^/?]+/.test(response.url()) && response.ok()), page.waitForResponse((response) => response.request().method() === 'GET' && /\/permissions\/roles\/[^/?]+/.test(response.url()) && response.ok()),
roleButton.click(),
roleRow.getByRole('button', { name: '配置权限' }).click(),
]) ])
await expect(roleButton).toHaveClass(/active/)
await expect(page.locator('.selected-role-copy h2')).toHaveText(data.roleName)
const drawer = page.locator('.role-permission-drawer')
await expect(drawer).toBeVisible()
await expect(drawer.locator('.role-permission-summary h3')).toHaveText(data.roleName)
const auditCode = page.locator('code').filter({ hasText: /^system\.audit$/ }) const auditCode = page.locator('code').filter({ hasText: /^system\.audit$/ })
const auditPermission = page.locator('.permission-item').filter({ has: auditCode })
await expect(auditPermission).toHaveAttribute('aria-checked', 'false')
await auditPermission.click()
const saveButton = page.getByRole('button', { name: '保存权限配置' })
const auditPermission = drawer.locator('.el-tree-node').filter({ has: auditCode }).last()
await auditPermission.locator('.el-checkbox').click()
const saveButton = drawer.getByRole('button', { name: '保存授权' })
await expect(saveButton).toBeEnabled() await expect(saveButton).toBeEnabled()
await saveButton.click() await saveButton.click()
await expect(page.getByText(/权限已保存|当前权限配置已保存/).last()).toBeVisible() await expect(page.getByText(/权限已保存|当前权限配置已保存/).last()).toBeVisible()
@@ -157,7 +159,7 @@ async function deleteRoleIfPresent(page: Page) {
async function deleteDepartmentIfPresent(page: Page) { async function deleteDepartmentIfPresent(page: Page) {
await dismissOverlays(page) await dismissOverlays(page)
await page.goto('/system/departments') await page.goto('/system/departments')
await page.getByPlaceholder('请输入部门、编码、负责人或层级路径').fill(data.departmentCode)
await page.getByPlaceholder('请输入部门、编码或负责人').fill(data.departmentCode)
await page.getByRole('button', { name: '搜索', exact: true }).click() await page.getByRole('button', { name: '搜索', exact: true }).click()
const row = tableRowByText(page, data.departmentName) const row = tableRowByText(page, data.departmentName)
if (!(await row.waitFor({ state: 'visible', timeout: 5_000 }).then(() => true).catch(() => false))) return false if (!(await row.waitFor({ state: 'visible', timeout: 5_000 }).then(() => true).catch(() => false))) return false


+ 47
- 2
tests/system-inline-statistics.spec.ts Ver ficheiro

@@ -31,19 +31,34 @@ const menus = [{
], ],
}] }]


const menuWrites: Array<Record<string, unknown>> = []

async function mockSystemPageApi(page: Page) { async function mockSystemPageApi(page: Page) {
await page.route(/\/api\/(?:auth|tran)\//, async (route) => { await page.route(/\/api\/(?:auth|tran)\//, async (route) => {
const path = new URL(route.request().url()).pathname const path = new URL(route.request().url()).pathname
if (path.endsWith('/auth/me')) return json(route, { if (path.endsWith('/auth/me')) return json(route, {
userId: '1', username: 'admin', displayName: '系统管理员', departmentId: '110', departmentName: '信息中心', userId: '1', username: 'admin', displayName: '系统管理员', departmentId: '110', departmentName: '信息中心',
activeRoleId: '1', roles, authorizationMode: 'SINGLE_ACTIVE', mustChangePassword: false, activeRoleId: '1', roles, authorizationMode: 'SINGLE_ACTIVE', mustChangePassword: false,
permissions: ['system.departments', 'system.roles', 'system.menus', 'system.permissions', 'system.departments.create', 'system.roles.create', 'system.roles.update', 'system.roles.delete', 'system.menus.update'],
permissions: ['system.departments', 'system.roles', 'system.menus', 'system.permissions', 'system.departments.create', 'system.roles.create', 'system.roles.update', 'system.roles.delete', 'system.menus.update', 'system.interfaces', 'system.config'],
}) })
if (path.endsWith('/departments/tree')) return json(route, departments) if (path.endsWith('/departments/tree')) return json(route, departments)
if (path.endsWith('/departments')) return json(route, { records: [departments[0], departments[0].children[0]], total: 2, page: 1, size: 10 })
if (path.endsWith('/departments/stats')) return json(route, { total: 2, enabled: 2, maxDepth: 2, assignedUsers: 4 }) if (path.endsWith('/departments/stats')) return json(route, { total: 2, enabled: 2, maxDepth: 2, assignedUsers: 4 })
if (path.endsWith('/roles/all')) return json(route, roles) if (path.endsWith('/roles/all')) return json(route, roles)
if (path.endsWith('/roles/stats')) return json(route, { total: 2, enabled: 2, builtIn: 2, assignedUsers: 4 }) if (path.endsWith('/roles/stats')) return json(route, { total: 2, enabled: 2, builtIn: 2, assignedUsers: 4 })
if (path.endsWith('/menus/configuration') && route.request().method() === 'PUT') {
const payload = route.request().postDataJSON() as Record<string, unknown>
menuWrites.push(payload)
const groups = payload.groups as Array<{ enabled?: boolean; items?: Array<{ enabled?: boolean }> }>
const saved = structuredClone(menus)
saved[0]!.enabled = groups[0]?.enabled ?? true
saved[0]!.children[0]!.enabled = groups[0]?.items?.[0]?.enabled ?? true
return json(route, saved)
}
if (path.endsWith('/menus/tree') || path.endsWith('/menus/navigation')) return json(route, menus) if (path.endsWith('/menus/tree') || path.endsWith('/menus/navigation')) return json(route, menus)
if (path.endsWith('/interfaces/stats')) return json(route, { total: 1, enabled: 1, disabled: 0, up: 1, down: 0 })
if (path.endsWith('/interfaces')) return json(route, { records: [{ id: '1', code: 'training', name: '训练服务', endpoint: '/api/tran/v1', transport: 'REST', dataMode: 'LOCAL', enabled: true, configStatus: 'READY', healthStatus: 'UP', version: 1 }], total: 1, page: 1, size: 10 })
if (path.endsWith('/system-config')) return json(route, { systemName: '某类装备维修实训数字车间', systemNameConfigured: true, version: 1 })
if (path.endsWith('/system-config/public')) return json(route, { systemName: '某类装备维修实训数字车间', logoConfigured: false, faviconConfigured: false }) if (path.endsWith('/system-config/public')) return json(route, { systemName: '某类装备维修实训数字车间', logoConfigured: false, faviconConfigured: false })
if (path.endsWith('/auth/ping')) return json(route, { service: 'ut-auth', status: 'UP' }) if (path.endsWith('/auth/ping')) return json(route, { service: 'ut-auth', status: 'UP' })
if (path.endsWith('/tran/ping')) return json(route, { service: 'ut-tran', status: 'UP' }) if (path.endsWith('/tran/ping')) return json(route, { service: 'ut-tran', status: 'UP' })
@@ -56,6 +71,7 @@ async function mockSystemPageApi(page: Page) {


test('部门、角色、菜单统计收进列表工具栏', async ({ page }, testInfo) => { test('部门、角色、菜单统计收进列表工具栏', async ({ page }, testInfo) => {
await mockSystemPageApi(page) await mockSystemPageApi(page)
menuWrites.length = 0


const cases = [ const cases = [
{ path: '/system/departments', testId: 'department-inline-statistics', removed: '.department-stats', texts: ['共 2 个部门', '启用 2', '2 级组织', '归属 4 人'] }, { path: '/system/departments', testId: 'department-inline-statistics', removed: '.department-stats', texts: ['共 2 个部门', '启用 2', '2 级组织', '归属 4 人'] },
@@ -69,9 +85,11 @@ test('部门、角色、菜单统计收进列表工具栏', async ({ page }, tes
await expect(statistics).toBeVisible() await expect(statistics).toBeVisible()
await expect(page.locator(item.removed)).toHaveCount(0) await expect(page.locator(item.removed)).toHaveCount(0)
for (const text of item.texts) await expect(statistics).toContainText(text) for (const text of item.texts) await expect(statistics).toContainText(text)
await expect(statistics).not.toContainText('当前')
await expect(statistics.locator('.is-danger')).toHaveCount(0) await expect(statistics.locator('.is-danger')).toHaveCount(0)
const toolbarHeight = await statistics.locator('xpath=ancestor::*[contains(@class, "system-list-toolbar")]').evaluate((toolbar) => toolbar.getBoundingClientRect().height) const toolbarHeight = await statistics.locator('xpath=ancestor::*[contains(@class, "system-list-toolbar")]').evaluate((toolbar) => toolbar.getBoundingClientRect().height)
expect(toolbarHeight).toBeLessThanOrEqual(64)
// 部门页同时保留左侧组织树,1280px 视口下工具条允许响应式换成两行。
expect(toolbarHeight).toBeLessThanOrEqual(120)
if (item.path === '/system/roles') { if (item.path === '/system/roles') {
const table = page.locator('.roles-table') const table = page.locator('.roles-table')
await expect(page.locator('.role-card')).toHaveCount(0) await expect(page.locator('.role-card')).toHaveCount(0)
@@ -88,6 +106,33 @@ test('部门、角色、菜单统计收进列表工具栏', async ({ page }, tes
expect(actionLayout.justifyContent).toBe('flex-start') expect(actionLayout.justifyContent).toBe('flex-start')
expect(actionLayout.columnGap).toBe('12px') expect(actionLayout.columnGap).toBe('12px')
} }
if (item.path === '/system/menus') {
const switchControl = page.getByRole('switch', { name: '用户管理状态' })
await expect(switchControl).toBeChecked()
await page.locator('.el-switch').filter({ has: switchControl }).click()
await page.getByRole('button', { name: '保存全部' }).click()
await expect.poll(() => menuWrites.length).toBe(1)
const groups = menuWrites[0]!.groups as Array<{ items: Array<{ enabled: boolean }> }>
expect(groups[0]!.items[0]!.enabled).toBe(false)
}
await captureScreenshot(page, testInfo, item.testId) await captureScreenshot(page, testInfo, item.testId)
} }
}) })

test('系统配置刷新与标题同行,接口列表不再显示装饰图标', async ({ page }, testInfo) => {
await mockSystemPageApi(page)
await page.goto('/system/config')
const header = page.locator('.system-config-form-header')
await expect(header.getByRole('button', { name: '刷新配置' })).toBeVisible()
await expect(page.locator('.content-action-bar')).toHaveCount(0)
const [titleBox, actionBox] = await Promise.all([
header.getByRole('heading', { name: '通用配置' }).boundingBox(),
header.getByRole('button', { name: '刷新配置' }).boundingBox(),
])
expect(Math.abs(titleBox!.y - actionBox!.y)).toBeLessThan(24)

await page.goto('/system/interfaces')
await expect(page.locator('.interface-identity > span')).toHaveCount(0)
await expect(page.locator('.interface-identity').first()).toContainText('训练服务')
await captureScreenshot(page, testInfo, 'system-config-and-interface-list')
})

+ 5
- 13
tests/system-pages.spec.ts Ver ficheiro

@@ -6,12 +6,11 @@ const pages = [
['/system/departments', '部门管理', 'system-departments', '.department-table .el-table__body-wrapper .el-table__row'], ['/system/departments', '部门管理', 'system-departments', '.department-table .el-table__body-wrapper .el-table__row'],
['/system/roles', '角色管理', 'system-roles', '.roles-table .el-table__body-wrapper .el-table__row'], ['/system/roles', '角色管理', 'system-roles', '.roles-table .el-table__body-wrapper .el-table__row'],
['/system/menus', '菜单管理', 'system-menus', '.menu-table-panel .el-table__body-wrapper .el-table__row'], ['/system/menus', '菜单管理', 'system-menus', '.menu-table-panel .el-table__body-wrapper .el-table__row'],
['/system/permissions', '权限管理', 'system-permissions', '.permission-group'],
['/system/audit', '审计日志', 'system-audit', '.el-table__body-wrapper .el-table__row'], ['/system/audit', '审计日志', 'system-audit', '.el-table__body-wrapper .el-table__row'],
['/system/interfaces', '平台服务配置', 'system-interfaces', '.interfaces-table .el-table__body-wrapper .el-table__row'], ['/system/interfaces', '平台服务配置', 'system-interfaces', '.interfaces-table .el-table__body-wrapper .el-table__row'],
] as const ] as const


test('系统管理七个页面均可加载', async ({ page }, testInfo) => {
test('系统管理页面均可加载且权限配置收口到角色抽屉', async ({ page }, testInfo) => {
await loginAsAdmin(page) await loginAsAdmin(page)


for (const [path, heading, screenshotLabel, readySelector] of pages) { for (const [path, heading, screenshotLabel, readySelector] of pages) {
@@ -57,6 +56,10 @@ test('系统管理七个页面均可加载', async ({ page }, testInfo) => {
await expect(page.locator('.role-statistics')).toHaveCount(0) await expect(page.locator('.role-statistics')).toHaveCount(0)
await expect(page.getByTestId('role-inline-statistics')).toContainText('个角色') await expect(page.getByTestId('role-inline-statistics')).toContainText('个角色')
await expect(page.getByTestId('role-inline-statistics')).toContainText('内置') await expect(page.getByTestId('role-inline-statistics')).toContainText('内置')
const permissionButton = page.locator('.roles-table .role-table-actions').first().getByRole('button', { name: '配置权限' })
await permissionButton.click()
await expect(page.locator('.role-permission-drawer')).toBeVisible()
await page.locator('.role-permission-drawer .el-drawer__close-btn').click()
} }
if (path === '/system/menus') { if (path === '/system/menus') {
await expect(page.locator('.menu-statistics')).toHaveCount(0) await expect(page.locator('.menu-statistics')).toHaveCount(0)
@@ -71,17 +74,6 @@ test('系统管理七个页面均可加载', async ({ page }, testInfo) => {
await expect(page.getByTestId('interface-inline-statistics')).toContainText('个服务') await expect(page.getByTestId('interface-inline-statistics')).toContainText('个服务')
await expect(page.locator('.system-pagination-total')).toBeVisible() await expect(page.locator('.system-pagination-total')).toBeVisible()
} }
if (path === '/system/permissions') {
const permissionCopies = page.locator('.permission-item .permission-copy')
await expect(permissionCopies.first()).toBeVisible()
expect(await permissionCopies.count()).toBeGreaterThan(20)
const incomplete = await permissionCopies.evaluateAll((items) => items.filter((item) => {
const title = item.querySelector('b')?.textContent?.trim()
const code = item.querySelector('code')?.textContent?.trim()
return !title || !code
}).length)
expect(incomplete).toBe(0)
}
await captureScreenshot(page, testInfo, screenshotLabel) await captureScreenshot(page, testInfo, screenshotLabel)
}) })
} }


+ 9
- 9
tests/users-department-filter.spec.ts Ver ficheiro

@@ -114,12 +114,13 @@ test('用户列表全局中文并支持部门树选择与再次点击取消', as
await expect(page.locator('.el-pagination__sizes')).toContainText('条/页') await expect(page.locator('.el-pagination__sizes')).toContainText('条/页')
await expect(page.locator('.el-pagination__jump')).toContainText('前往') await expect(page.locator('.el-pagination__jump')).toContainText('前往')
await expect(page.locator('.system-pagination-total')).toHaveText('共 4 条记录') await expect(page.locator('.system-pagination-total')).toHaveText('共 4 条记录')
await expect(page.locator('.department-filter-panel')).toBeVisible()
await expect(page.locator('.department-filter-panel.system-panel')).toBeVisible()
await expect(page.locator('.department-scope-panel')).toBeVisible()
await expect(page.locator('.department-scope-panel.system-panel')).toBeVisible()
await expect(page.locator('.user-list-main.system-panel.system-list-card')).toBeVisible() await expect(page.locator('.user-list-main.system-panel.system-list-card')).toBeVisible()
await expect(page.locator('.user-stats')).toHaveCount(0) await expect(page.locator('.user-stats')).toHaveCount(0)
const inlineStatistics = page.getByTestId('user-inline-statistics') const inlineStatistics = page.getByTestId('user-inline-statistics')
await expect(inlineStatistics).toContainText('当前 4 条,共 4 个账号')
await expect(inlineStatistics).toContainText('共 4 个账号')
await expect(inlineStatistics).not.toContainText('当前')
await expect(inlineStatistics).toContainText('正常 3') await expect(inlineStatistics).toContainText('正常 3')
await expect(inlineStatistics).toContainText('停用 1') await expect(inlineStatistics).toContainText('停用 1')
await expect(inlineStatistics).toContainText('待改密 1') await expect(inlineStatistics).toContainText('待改密 1')
@@ -153,7 +154,7 @@ test('用户列表全局中文并支持部门树选择与再次点击取消', as
expect(keywordWidth).toBeLessThanOrEqual(391) expect(keywordWidth).toBeLessThanOrEqual(391)


const panelsAreSeparate = await page.locator('.user-content-layout').evaluate((container) => { const panelsAreSeparate = await page.locator('.user-content-layout').evaluate((container) => {
const departmentPanel = container.querySelector('.department-filter-panel')
const departmentPanel = container.querySelector('.department-scope-panel')
const listPanel = container.querySelector('.user-list-main') const listPanel = container.querySelector('.user-list-main')
return departmentPanel !== listPanel return departmentPanel !== listPanel
&& departmentPanel?.parentElement === container && departmentPanel?.parentElement === container
@@ -162,7 +163,7 @@ test('用户列表全局中文并支持部门树选择与再次点击取消', as
expect(panelsAreSeparate).toBe(true) expect(panelsAreSeparate).toBe(true)


const normalFontSize = await page.locator('.users-table .el-table__body .cell').first().evaluate((element) => Number.parseFloat(getComputedStyle(element).fontSize)) const normalFontSize = await page.locator('.users-table .el-table__body .cell').first().evaluate((element) => Number.parseFloat(getComputedStyle(element).fontSize))
const hintFontSize = await page.locator('.department-filter-state').evaluate((element) => Number.parseFloat(getComputedStyle(element).fontSize))
const hintFontSize = await page.locator('.department-scope-node__name').first().evaluate((element) => Number.parseFloat(getComputedStyle(element).fontSize))
expect(normalFontSize).toBeGreaterThanOrEqual(14) expect(normalFontSize).toBeGreaterThanOrEqual(14)
expect(hintFontSize).toBeGreaterThanOrEqual(13) expect(hintFontSize).toBeGreaterThanOrEqual(13)


@@ -197,16 +198,15 @@ test('用户列表全局中文并支持部门树选择与再次点击取消', as
const disabledUserRow = page.locator('.users-table .el-table__row').filter({ hasText: '李教员' }) const disabledUserRow = page.locator('.users-table .el-table__row').filter({ hasText: '李教员' })
await expect(disabledUserRow.getByRole('button', { name: '启用' })).toHaveClass(/el-button--success/) await expect(disabledUserRow.getByRole('button', { name: '启用' })).toHaveClass(/el-button--success/)


const departmentNode = page.locator('.department-filter-tree .el-tree-node__content').filter({ hasText: '维修改研室' }).first()
const departmentNode = page.locator('.department-scope-tree .el-tree-node__content').filter({ hasText: '维修改研室' }).first()
await departmentNode.click() await departmentNode.click()
await expect(page.locator('.department-filter-state')).toContainText('已选择:维修改研室')
await expect(departmentNode.locator('xpath=..')).toHaveClass(/is-current/)
await expect.poll(() => requestedDepartments.at(-1)).toBe('200') await expect.poll(() => requestedDepartments.at(-1)).toBe('200')
await expect(page.locator('.users-table .el-table__body-wrapper .el-table__row')).toHaveCount(2) await expect(page.locator('.users-table .el-table__body-wrapper .el-table__row')).toHaveCount(2)
await captureScreenshot(page, testInfo, 'users-department-selected') await captureScreenshot(page, testInfo, 'users-department-selected')


await departmentNode.click() await departmentNode.click()
await expect(page.locator('.department-filter-state')).toContainText('当前显示全部部门')
await expect(page.locator('.department-filter-tree .el-tree-node.is-current')).toHaveCount(0)
await expect(page.locator('.department-scope-tree .el-tree-node.is-current')).toHaveCount(0)
await expect.poll(() => requestedDepartments.at(-1)).toBeNull() await expect.poll(() => requestedDepartments.at(-1)).toBeNull()
await expect(page.locator('.users-table .el-table__body-wrapper .el-table__row')).toHaveCount(4) await expect(page.locator('.users-table .el-table__body-wrapper .el-table__row')).toHaveCount(4)




+ 44
- 15
tests/zentao-system-ui-regression.spec.ts Ver ficheiro

@@ -49,11 +49,18 @@ async function mockSystemApi(page: Page) {
if (path.endsWith('/auth/me')) return json(route, { if (path.endsWith('/auth/me')) return json(route, {
userId: '1', username: 'admin', displayName: '系统管理员', departmentId: '100', departmentName: '数字车间', userId: '1', username: 'admin', displayName: '系统管理员', departmentId: '100', departmentName: '数字车间',
activeRoleId: '1', roles: [roles[1]], authorizationMode: 'SINGLE_ACTIVE', mustChangePassword: false, activeRoleId: '1', roles: [roles[1]], authorizationMode: 'SINGLE_ACTIVE', mustChangePassword: false,
permissions: ['system.departments', 'system.permissions', 'system.permissions.update'],
permissions: ['system.departments', 'system.departments.update', 'system.roles', 'system.permissions', 'system.permissions.update'],
}) })
if (path.endsWith('/departments/tree')) return json(route, departments) if (path.endsWith('/departments/tree')) return json(route, departments)
if (path.endsWith('/departments')) {
const keyword = new URL(route.request().url()).searchParams.get('keyword')?.trim() ?? ''
const records = keyword ? [] : [departments[0], departments[0].children[0]]
return json(route, { records, total: records.length, page: 1, size: 10 })
}
if (path.endsWith('/departments/stats')) return json(route, { total: 2, enabled: 2, maxDepth: 2, assignedUsers: 4 }) if (path.endsWith('/departments/stats')) return json(route, { total: 2, enabled: 2, maxDepth: 2, assignedUsers: 4 })
if (path.endsWith('/roles/all')) return json(route, roles) if (path.endsWith('/roles/all')) return json(route, roles)
if (path.endsWith('/roles/stats')) return json(route, { total: 2, enabled: 2, builtIn: 2, assignedUsers: 4 })
if (path.endsWith('/users')) return json(route, { records: [{ id: '20', username: 'teacher', displayName: '周教员', departmentId: '110', departmentName: '维修教研室', roleIds: ['10'], enabled: true }], total: 1, page: 1, size: 10 })
if (path.endsWith('/permissions/catalog')) return json(route, { sections: permissionSections }) if (path.endsWith('/permissions/catalog')) return json(route, { sections: permissionSections })
if (/\/permissions\/roles\/\d+$/.test(path)) return json(route, { permissionCodes: [], version: 1 }) if (/\/permissions\/roles\/\d+$/.test(path)) return json(route, { permissionCodes: [], version: 1 })
if (path.endsWith('/menus/navigation')) return json(route, []) if (path.endsWith('/menus/navigation')) return json(route, [])
@@ -82,27 +89,49 @@ test('Bug 850:无匹配部门时只保留工具栏重置入口', async ({ page
await captureScreenshot(page, testInfo, 'bug-850-empty-without-duplicate-reset') await captureScreenshot(page, testInfo, 'bug-850-empty-without-duplicate-reset')
}) })


test('Bug 853:权限操作栏在内容滚动过程中固定于可视区底部', async ({ page }, testInfo) => {
test('角色配置权限改为固定头尾的授权抽屉', async ({ page }, testInfo) => {
await mockSystemApi(page) await mockSystemApi(page)
await page.setViewportSize({ width: 1440, height: 760 }) await page.setViewportSize({ width: 1440, height: 760 })
await page.goto('/system/permissions')
await page.goto('/system/roles')
await page.locator('.roles-table .el-table__row').filter({ hasText: '教员' }).getByRole('button', { name: '配置权限' }).click()


const routeView = page.locator('.route-view')
const footer = page.locator('.permission-actions')
await expect(page.locator('.permission-group')).toHaveCount(permissionSections.length)
const drawer = page.locator('.role-permission-drawer')
const body = drawer.locator('.el-drawer__body')
const footer = drawer.locator('.el-drawer__footer')
await expect(drawer).toBeVisible()
await expect(drawer.locator('.role-permission-node.is-section')).toHaveCount(permissionSections.length)
await expect(footer).toBeVisible() await expect(footer).toBeVisible()


await routeView.evaluate((element) => { element.scrollTop = Math.round(element.scrollHeight * 0.45) })
await expect.poll(() => routeView.evaluate((element) => element.scrollTop)).toBeGreaterThan(100)
const scroll = drawer.locator('.role-permission-tree-scroll')
await scroll.evaluate((element) => { element.scrollTop = element.scrollHeight })
await expect.poll(() => scroll.evaluate((element) => element.scrollTop)).toBeGreaterThan(100)


const [routeBox, footerBox, position] = await Promise.all([
routeView.boundingBox(),
const [drawerBox, footerBox] = await Promise.all([
drawer.boundingBox(),
footer.boundingBox(), footer.boundingBox(),
footer.evaluate((element) => getComputedStyle(element).position),
]) ])
expect(routeBox).not.toBeNull()
expect(drawerBox).not.toBeNull()
expect(footerBox).not.toBeNull() expect(footerBox).not.toBeNull()
expect(position).toBe('sticky')
expect(Math.abs((routeBox!.y + routeBox!.height) - (footerBox!.y + footerBox!.height))).toBeLessThanOrEqual(20)
await captureScreenshot(page, testInfo, 'bug-853-sticky-permission-actions')
expect(Math.abs((drawerBox!.y + drawerBox!.height) - (footerBox!.y + footerBox!.height))).toBeLessThanOrEqual(2)
await captureScreenshot(page, testInfo, 'role-permission-drawer-fixed-actions')
})

test('编辑部门使用统一选人组件', async ({ page }, testInfo) => {
await mockSystemApi(page)
await page.setViewportSize({ width: 1440, height: 800 })
await page.goto('/system/departments')
const row = page.locator('.department-table .el-table__row').filter({ hasText: '维修教研室' })
await row.getByRole('button', { name: '编辑' }).click()
const editor = page.locator('.el-dialog:visible').filter({ hasText: '编辑部门' })
await expect(editor).toBeVisible()
await editor.getByRole('button', { name: '选择用户' }).click()
const picker = page.locator('.el-dialog:visible').filter({ hasText: '选择部门负责人' })
await expect(picker).toBeVisible()
await expect(picker.getByRole('button', { name: '搜索', exact: true })).toBeVisible()
await expect(picker.getByRole('button', { name: '重置筛选', exact: true })).toBeVisible()
expect((await picker.boundingBox())!.width).toBeGreaterThan(1000)
await picker.getByRole('button', { name: '选择', exact: true }).click()
await picker.getByRole('button', { name: '确认选择' }).click()
await expect(editor).toContainText('周教员')
await captureScreenshot(page, testInfo, 'department-editor-user-picker')
}) })

Carregando…
Cancelar
Guardar