Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

120 рядки
5.3 KiB

  1. import type { Locator, Page, Route } from '@playwright/test'
  2. import { expect, test } from './fixtures'
  3. type RoleRecord = {
  4. id: string
  5. code: string
  6. name: string
  7. shortName: string
  8. description: string
  9. enabled: boolean
  10. builtIn: boolean
  11. isSuperAdmin: boolean
  12. dataScopeCode: string
  13. departmentScopeIds: string[]
  14. linkedUserCount: number
  15. permissionCount: number
  16. sortOrder: number
  17. version: number
  18. }
  19. const json = (route: Route, data: unknown) => route.fulfill({
  20. status: 200,
  21. contentType: 'application/json',
  22. body: JSON.stringify({ code: 0, message: '成功', data, timestamp: Date.now(), requestId: 'role-form-regression' }),
  23. })
  24. const fillFormItem = (dialog: Locator, label: string, value: string) => dialog
  25. .locator('.el-form-item')
  26. .filter({ hasText: label })
  27. .first()
  28. .locator('input, textarea')
  29. .first()
  30. .fill(value)
  31. async function mockRoleApi(page: Page, submitted: Array<Record<string, unknown>>) {
  32. const roles: RoleRecord[] = [{
  33. id: '1', code: 'admin', name: '管理员', shortName: '管', description: '系统管理员',
  34. enabled: true, builtIn: true, isSuperAdmin: true, dataScopeCode: 'ALL', departmentScopeIds: [],
  35. linkedUserCount: 1, permissionCount: 30, sortOrder: 10, version: 1,
  36. }]
  37. await page.route(/\/api\/(?:auth|tran)\//, async (route) => {
  38. const url = new URL(route.request().url())
  39. const path = url.pathname
  40. const method = route.request().method()
  41. if (path.endsWith('/auth/me')) return json(route, {
  42. userId: '1', username: 'admin', displayName: '系统管理员', departmentId: '100', departmentName: '数字车间',
  43. activeRoleId: '1', roles, authorizationMode: 'SINGLE_ACTIVE', mustChangePassword: false,
  44. permissions: ['system.roles', 'system.roles.create', 'system.roles.update', 'system.roles.delete'],
  45. })
  46. if (path.endsWith('/roles/all')) return json(route, roles)
  47. if (path.endsWith('/roles/stats')) return json(route, {
  48. total: roles.length,
  49. enabled: roles.filter((role) => role.enabled).length,
  50. builtIn: roles.filter((role) => role.builtIn).length,
  51. assignedUsers: roles.reduce((total, role) => total + role.linkedUserCount, 0),
  52. })
  53. if (path.endsWith('/departments/tree')) return json(route, [])
  54. if (path.endsWith('/roles') && method === 'POST') {
  55. const body = route.request().postDataJSON() as Record<string, unknown>
  56. submitted.push(body)
  57. const created: RoleRecord = {
  58. id: '2', code: String(body.code), name: String(body.name), shortName: String(body.shortName ?? ''),
  59. description: String(body.description ?? ''), enabled: true, builtIn: false, isSuperAdmin: false,
  60. dataScopeCode: String(body.dataScope), departmentScopeIds: [], linkedUserCount: 0, permissionCount: 0,
  61. sortOrder: Number(body.sortOrder), version: 1,
  62. }
  63. roles.push(created)
  64. return json(route, created)
  65. }
  66. if (/\/roles\/2$/.test(path) && method === 'PUT') {
  67. const body = route.request().postDataJSON() as Record<string, unknown>
  68. submitted.push(body)
  69. Object.assign(roles[1]!, {
  70. name: String(body.name), shortName: String(body.shortName ?? ''), description: String(body.description ?? ''),
  71. dataScopeCode: String(body.dataScope), version: roles[1]!.version + 1,
  72. })
  73. return json(route, roles[1])
  74. }
  75. if (path.endsWith('/system-config/public')) return json(route, { systemName: '数字车间' })
  76. if (path.endsWith('/auth/ping')) return json(route, { service: 'ut-auth', status: 'UP' })
  77. if (path.endsWith('/tran/ping')) return json(route, { service: 'ut-tran', status: 'UP' })
  78. return json(route, {})
  79. })
  80. await page.addInitScript(() => {
  81. window.sessionStorage.setItem('unreal-tran:web:access-token:v1', 'role-form-regression-token')
  82. })
  83. }
  84. test('角色表单保留空简称、提供清晰提示,并在校验失败时提示用户', async ({ page }) => {
  85. const submitted: Array<Record<string, unknown>> = []
  86. await mockRoleApi(page, submitted)
  87. await page.goto('/system/roles')
  88. await page.getByRole('button', { name: '新增角色', exact: true }).click()
  89. let dialog = page.locator('.el-dialog:visible')
  90. const shortInput = dialog.getByPlaceholder('请输入界面简称,如:审核')
  91. await expect(shortInput).toBeVisible()
  92. await fillFormItem(dialog, '角色名称', '测试角色')
  93. await fillFormItem(dialog, '角色编码', `a${'1'.repeat(48)}`)
  94. await dialog.getByRole('button', { name: '创建角色' }).click()
  95. await expect(page.locator('.el-message').filter({ hasText: '请检查表单中的错误项' })).toBeVisible()
  96. expect(submitted).toHaveLength(0)
  97. await fillFormItem(dialog, '角色编码', 'test_role')
  98. await dialog.getByRole('button', { name: '创建角色' }).click()
  99. await expect(dialog).toBeHidden()
  100. expect(submitted[0]).toMatchObject({ name: '测试角色', code: 'test_role', shortName: '' })
  101. const createdRow = page.locator('.roles-table .el-table__row').filter({ hasText: '测试角色' })
  102. await createdRow.getByRole('button', { name: '编辑' }).click()
  103. dialog = page.locator('.el-dialog:visible')
  104. await expect(dialog.getByPlaceholder('请输入界面简称,如:审核')).toHaveValue('')
  105. await dialog.getByRole('button', { name: '保存修改' }).click()
  106. await expect(dialog).toBeHidden()
  107. expect(submitted[1]).toMatchObject({ name: '测试角色', code: 'test_role', shortName: '' })
  108. })