|
- import type { Page } from '@playwright/test'
-
- import { captureScreenshot, expect, test } from './fixtures'
- import {
- chooseSelectOption,
- confirmMessageBox,
- dismissOverlays,
- fillFormItem,
- loginAsAdmin,
- roleCardByText,
- tableRowByText,
- visibleDialog,
- } from './helpers'
-
- const runToken = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`
- const upperToken = runToken.replace(/[^a-z0-9]/gi, '').toUpperCase().slice(-14)
- const lowerToken = runToken.replace(/[^a-z0-9]/gi, '').toLowerCase().slice(-18)
-
- const data = {
- prefix: `UTE2E-${upperToken}`,
- departmentName: `UTE2E-${upperToken}-部门`,
- departmentCode: `E2E_${upperToken}`.slice(0, 32),
- roleName: `UTE2E-${upperToken}-角色`,
- roleCode: `e2e_${lowerToken}`.slice(0, 48),
- roleShort: '测',
- userName: `e2e_${lowerToken}`.slice(0, 32),
- displayName: `UTE2E-${upperToken}-用户`,
- editedDisplayName: `UTE2E-${upperToken}-已编辑`,
- password: `Tmp@${upperToken}a1`,
- }
-
- async function createDepartment(page: Page) {
- await page.goto('/system/departments')
- await page.getByRole('button', { name: '新增部门', exact: true }).click()
- const dialog = visibleDialog(page)
- await fillFormItem(dialog, '部门名称', data.departmentName)
- await fillFormItem(dialog, '部门编码', data.departmentCode)
- await fillFormItem(dialog, '负责人', data.prefix)
- await fillFormItem(dialog, '部门职责', `${data.prefix} 自动化测试数据`)
- await dialog.getByRole('button', { name: '创建部门' }).click()
- await expect(tableRowByText(page, data.departmentName)).toBeVisible()
- }
-
- async function createRole(page: Page) {
- await page.goto('/system/roles')
- await page.getByRole('button', { name: '新增角色', exact: true }).click()
- const dialog = visibleDialog(page)
- await fillFormItem(dialog, '角色名称', data.roleName)
- await fillFormItem(dialog, '角色编码', data.roleCode)
- await fillFormItem(dialog, '界面简称', data.roleShort)
- await fillFormItem(dialog, '角色说明', `${data.prefix} 自动化角色`)
- await dialog.getByRole('button', { name: '创建角色' }).click()
- await expect(roleCardByText(page, data.roleName)).toBeVisible()
- }
-
- async function createUser(page: Page) {
- await page.goto('/system/users')
- await page.getByRole('button', { name: '新增用户', exact: true }).click()
- const dialog = visibleDialog(page)
- await fillFormItem(dialog, '姓名', data.displayName)
- await fillFormItem(dialog, '登录账号', data.userName)
- await chooseSelectOption(page, dialog, '所属部门', data.departmentName)
- await fillFormItem(dialog, '初始密码', data.password)
-
- const roleCheckbox = dialog.locator('.el-checkbox').filter({ hasText: data.roleName })
- await roleCheckbox.click()
- await chooseSelectOption(page, dialog, '登录默认身份', data.roleName)
- await dialog.getByRole('button', { name: '创建用户' }).click()
- await expect(tableRowByText(page, data.userName)).toBeVisible()
- }
-
- async function editAndSearchData(page: Page) {
- await page.goto('/system/users')
- await page.getByPlaceholder('请输入姓名、账号、部门或角色').fill(data.userName)
- await page.getByRole('button', { name: '搜索', exact: true }).click()
- const userRow = tableRowByText(page, data.userName)
- await expect(userRow).toBeVisible()
- await userRow.getByRole('button', { name: '编辑' }).click()
- const userDialog = visibleDialog(page)
- await fillFormItem(userDialog, '姓名', data.editedDisplayName)
- await userDialog.getByRole('button', { name: '保存修改' }).click()
- await expect(tableRowByText(page, data.editedDisplayName)).toBeVisible()
-
- await page.goto('/system/roles')
- await page.getByPlaceholder('请输入角色名称、编码或说明').fill(data.roleCode)
- await page.getByRole('button', { name: '搜索', exact: true }).click()
- const roleCard = roleCardByText(page, data.roleName)
- await expect(roleCard).toBeVisible()
- await roleCard.getByRole('button', { name: '编辑' }).click()
- const roleDialog = visibleDialog(page)
- await fillFormItem(roleDialog, '角色说明', `${data.prefix} 已编辑`)
- await roleDialog.getByRole('button', { name: '保存修改' }).click()
- await expect(roleCardByText(page, `${data.prefix} 已编辑`)).toBeVisible()
-
- await page.goto('/system/departments')
- await page.getByPlaceholder('请输入部门、编码、负责人或层级路径').fill(data.departmentCode)
- await page.getByRole('button', { name: '搜索', exact: true }).click()
- await expect(tableRowByText(page, data.departmentName)).toBeVisible()
- }
-
- async function grantPermission(page: Page) {
- await page.goto('/system/permissions')
- const roleButton = page.locator('.role-selector > button').filter({ hasText: data.roleName })
- await Promise.all([
- page.waitForResponse((response) => response.request().method() === 'GET' && /\/permissions\/roles\/[^/?]+/.test(response.url()) && response.ok()),
- roleButton.click(),
- ])
- await expect(roleButton).toHaveClass(/active/)
- await expect(page.locator('.selected-role-copy h2')).toHaveText(data.roleName)
- 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: '保存权限配置' })
- await expect(saveButton).toBeEnabled()
- await saveButton.click()
- await expect(page.getByText(/权限已保存|当前权限配置已保存/).last()).toBeVisible()
- }
-
- async function verifyAudit(page: Page) {
- await page.goto('/system/audit')
- const search = page.getByPlaceholder('请输入用户、模块、操作或地址')
- await search.fill(data.prefix)
- await page.getByRole('button', { name: '搜索', exact: true }).click()
- await expect.poll(async () => page.locator('.el-table__body-wrapper .el-table__row').count(), {
- message: '等待与本次唯一前缀相关的审计记录可见',
- timeout: 10_000,
- }).toBeGreaterThan(0)
- }
-
- async function deleteUserIfPresent(page: Page) {
- await dismissOverlays(page)
- await page.goto('/system/users')
- await page.getByPlaceholder('请输入姓名、账号、部门或角色').fill(data.userName)
- await page.getByRole('button', { name: '搜索', exact: true }).click()
- const row = tableRowByText(page, data.userName)
- if (!(await row.waitFor({ state: 'visible', timeout: 5_000 }).then(() => true).catch(() => false))) return false
- await row.getByRole('button', { name: '删除' }).click()
- await confirmMessageBox(page, '确认删除')
- await expect(row).toHaveCount(0)
- return true
- }
-
- async function deleteRoleIfPresent(page: Page) {
- await dismissOverlays(page)
- await page.goto('/system/roles')
- await page.getByPlaceholder('请输入角色名称、编码或说明').fill(data.roleCode)
- await page.getByRole('button', { name: '搜索', exact: true }).click()
- const card = roleCardByText(page, data.roleName)
- if (!(await card.waitFor({ state: 'visible', timeout: 5_000 }).then(() => true).catch(() => false))) return false
- await card.getByRole('button', { name: '删除' }).click()
- await confirmMessageBox(page, '删除角色')
- await expect(card).toHaveCount(0)
- return true
- }
-
- async function deleteDepartmentIfPresent(page: Page) {
- await dismissOverlays(page)
- await page.goto('/system/departments')
- await page.getByPlaceholder('请输入部门、编码、负责人或层级路径').fill(data.departmentCode)
- await page.getByRole('button', { name: '搜索', exact: true }).click()
- const row = tableRowByText(page, data.departmentName)
- if (!(await row.waitFor({ state: 'visible', timeout: 5_000 }).then(() => true).catch(() => false))) return false
- await row.getByRole('button', { name: '删除' }).click()
- const dialog = visibleDialog(page)
- await dialog.getByRole('button', { name: '确认删除并迁移' }).click()
- await expect(row).toHaveCount(0)
- return true
- }
-
- test('系统管理测试数据可创建、编辑、搜索、授权、审计并完整清理', async ({ page }, testInfo) => {
- await loginAsAdmin(page)
- let testFailure: unknown
-
- try {
- await test.step('创建测试部门', async () => {
- await createDepartment(page)
- await captureScreenshot(page, testInfo, 'crud-department-created')
- })
- await test.step('创建测试角色', async () => {
- await createRole(page)
- await captureScreenshot(page, testInfo, 'crud-role-created')
- })
- await test.step('创建测试用户', async () => {
- await createUser(page)
- await captureScreenshot(page, testInfo, 'crud-user-created')
- })
- await test.step('编辑并搜索测试数据', async () => {
- await editAndSearchData(page)
- await captureScreenshot(page, testInfo, 'crud-edit-search-success')
- })
- await test.step('配置角色权限', async () => {
- await grantPermission(page)
- await captureScreenshot(page, testInfo, 'crud-permission-saved')
- })
- await test.step('审计记录可检索', async () => {
- await verifyAudit(page)
- await captureScreenshot(page, testInfo, 'crud-audit-found')
- })
- } catch (error) {
- testFailure = error
- } finally {
- const cleanupErrors: unknown[] = []
- for (const [name, screenshotLabel, cleanup] of [
- ['用户', 'crud-user-deleted', deleteUserIfPresent],
- ['角色', 'crud-role-deleted', deleteRoleIfPresent],
- ['部门', 'crud-department-deleted', deleteDepartmentIfPresent],
- ] as const) {
- try {
- const deleted = await cleanup(page)
- if (!testFailure && deleted) await captureScreenshot(page, testInfo, screenshotLabel)
- } catch (error) {
- cleanupErrors.push(new Error(`${name}清理失败`, { cause: error }))
- }
- }
- if (testFailure || cleanupErrors.length) {
- throw new AggregateError(
- [testFailure, ...cleanupErrors].filter((error) => error !== undefined),
- cleanupErrors.length ? '系统管理 E2E 失败,且已执行全部清理步骤;请检查聚合错误。' : '系统管理 E2E 失败。',
- )
- }
- }
- })
|