system-user.spec.ts 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import { test, expect, type Page } from '@playwright/test'
  2. // 测试账号配置
  3. const TEST_USERNAME = process.env.TEST_USERNAME || 'admin'
  4. const TEST_PASSWORD = process.env.TEST_PASSWORD || '123456'
  5. // 生成唯一的用户名
  6. const generateUsername = () => `test_${Date.now()}`
  7. // data-id 选择器辅助函数
  8. const byDataId = (id: string) => `[data-id="${id}"]`
  9. test.describe('系统用户管理 CRUD 测试', () => {
  10. // 登录辅助函数
  11. async function login(page: Page) {
  12. await page.goto('/login')
  13. await page.evaluate(() => {
  14. localStorage.clear()
  15. document.cookie.split(';').forEach((c) => {
  16. document.cookie = c.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`)
  17. })
  18. })
  19. await page.reload()
  20. await page.getByPlaceholder('用户名').fill(TEST_USERNAME)
  21. await page.getByPlaceholder('密码').fill(TEST_PASSWORD)
  22. await page.getByRole('button', { name: '登录' }).click()
  23. await expect(page).not.toHaveURL(/\/login/, { timeout: 15000 })
  24. }
  25. test('用户管理页面正确显示', async ({ page }) => {
  26. await login(page)
  27. await page.goto('/system/user')
  28. // 验证页面元素
  29. await expect(page.locator(byDataId('btn-add'))).toBeVisible()
  30. await expect(page.locator(byDataId('btn-search'))).toBeVisible()
  31. await expect(page.locator(byDataId('btn-reset'))).toBeVisible()
  32. await expect(page.locator(byDataId('user-table'))).toBeVisible()
  33. // 验证表头
  34. await expect(page.locator('thead').getByText('ID')).toBeVisible()
  35. await expect(page.locator('thead').getByText('用户名')).toBeVisible()
  36. await expect(page.locator('thead').getByText('昵称')).toBeVisible()
  37. await expect(page.locator('thead').getByText('角色')).toBeVisible()
  38. await expect(page.locator('thead').getByText('状态')).toBeVisible()
  39. })
  40. test('查询和重置功能', async ({ page }) => {
  41. await login(page)
  42. await page.goto('/system/user')
  43. // 等待表格加载
  44. await expect(page.locator(byDataId('user-table'))).toBeVisible()
  45. // 输入搜索关键词
  46. await page.locator(byDataId('search-keyword')).fill('admin')
  47. // 点击查询按钮
  48. await page.locator(byDataId('btn-search')).click()
  49. await page.waitForTimeout(500)
  50. // 表格应该仍然可见
  51. await expect(page.locator(byDataId('user-table'))).toBeVisible()
  52. // 点击重置按钮
  53. await page.locator(byDataId('btn-reset')).click()
  54. await page.waitForTimeout(500)
  55. // 验证输入框被清空
  56. await expect(page.locator(byDataId('search-keyword'))).toHaveValue('')
  57. // 表格应该仍然可见
  58. await expect(page.locator(byDataId('user-table'))).toBeVisible()
  59. })
  60. test('新增用户完整流程', async ({ page }) => {
  61. await login(page)
  62. await page.goto('/system/user')
  63. const username = generateUsername()
  64. const nickname = `测试用户_${Date.now()}`
  65. // 点击新增按钮
  66. await page.locator(byDataId('btn-add')).click()
  67. // 验证抽屉打开
  68. const drawer = page.locator(byDataId('user-drawer'))
  69. await expect(drawer).toBeVisible()
  70. await expect(page.locator('.el-drawer__title')).toContainText('新增用户')
  71. // 填写表单
  72. await drawer.locator(byDataId('input-username')).fill(username)
  73. await drawer.locator(byDataId('input-nickname')).fill(nickname)
  74. await drawer.locator(byDataId('input-password')).fill('Test123456')
  75. // 等待提交按钮可用后点击
  76. const submitBtn = page.locator(byDataId('btn-submit'))
  77. await expect(submitBtn).toBeEnabled()
  78. await submitBtn.click()
  79. // 等待成功消息或抽屉关闭
  80. const successPromise = page
  81. .locator('.el-message--success')
  82. .waitFor({ timeout: 10000 })
  83. .catch(() => null)
  84. const drawerClosePromise = expect(drawer).not.toBeVisible({ timeout: 10000 })
  85. await Promise.race([successPromise, drawerClosePromise])
  86. // 如果抽屉关闭了,说明操作已完成
  87. await expect(drawer).not.toBeVisible({ timeout: 5000 })
  88. })
  89. test('编辑用户功能', async ({ page }) => {
  90. await login(page)
  91. await page.goto('/system/user')
  92. // 等待表格加载
  93. await expect(page.locator(byDataId('user-table'))).toBeVisible()
  94. await page.waitForTimeout(1000)
  95. // 点击第一行的编辑按钮
  96. const editBtn = page.locator(byDataId('btn-edit')).first()
  97. // 等待数据加载
  98. await expect(editBtn).toBeVisible({ timeout: 10000 })
  99. await editBtn.click()
  100. // 验证抽屉打开
  101. const drawer = page.locator(byDataId('user-drawer'))
  102. await expect(drawer).toBeVisible()
  103. await expect(page.locator('.el-drawer__title')).toContainText('编辑用户')
  104. // 修改昵称
  105. const nicknameInput = drawer.locator(byDataId('input-nickname'))
  106. await nicknameInput.clear()
  107. await nicknameInput.fill(`编辑测试_${Date.now()}`)
  108. // 等待提交按钮可用后点击
  109. const submitBtn = page.locator(byDataId('btn-submit'))
  110. await expect(submitBtn).toBeEnabled()
  111. await submitBtn.click()
  112. // 验证抽屉关闭
  113. await expect(drawer).not.toBeVisible({ timeout: 15000 })
  114. })
  115. test('删除用户功能', async ({ page }) => {
  116. await login(page)
  117. await page.goto('/system/user')
  118. // 等待表格加载
  119. await expect(page.locator(byDataId('user-table'))).toBeVisible()
  120. await page.waitForTimeout(1000)
  121. // 找到第一个删除按钮并点击
  122. const deleteBtn = page.locator(byDataId('btn-delete')).first()
  123. // 确保有数据可以删除
  124. await expect(deleteBtn).toBeVisible({ timeout: 10000 })
  125. await deleteBtn.click()
  126. // 确认删除对话框出现
  127. await expect(page.locator('.el-message-box')).toBeVisible()
  128. await page.locator('.el-message-box').getByRole('button', { name: '确定' }).click()
  129. // 等待确认对话框关闭
  130. await expect(page.locator('.el-message-box')).not.toBeVisible({ timeout: 10000 })
  131. // 验证表格仍然可见
  132. await expect(page.locator(byDataId('user-table'))).toBeVisible()
  133. })
  134. test('新增用户表单验证', async ({ page }) => {
  135. await login(page)
  136. await page.goto('/system/user')
  137. // 点击新增按钮
  138. await page.locator(byDataId('btn-add')).click()
  139. await expect(page.locator(byDataId('user-drawer'))).toBeVisible()
  140. // 直接点击确定,不填写任何内容
  141. await page.locator(byDataId('btn-submit')).click()
  142. // 验证显示验证错误
  143. const drawer = page.locator(byDataId('user-drawer'))
  144. await expect(drawer.getByText('请输入用户名')).toBeVisible()
  145. await expect(drawer.getByText('请输入密码')).toBeVisible()
  146. })
  147. test('取消新增用户', async ({ page }) => {
  148. await login(page)
  149. await page.goto('/system/user')
  150. // 点击新增按钮
  151. await page.locator(byDataId('btn-add')).click()
  152. const drawer = page.locator(byDataId('user-drawer'))
  153. await expect(drawer).toBeVisible()
  154. // 填写部分内容
  155. await drawer.locator(byDataId('input-username')).fill('test_cancel')
  156. // 点击取消
  157. await page.locator(byDataId('btn-cancel')).click()
  158. // 验证抽屉关闭
  159. await expect(drawer).not.toBeVisible()
  160. })
  161. test('从侧边栏导航到用户管理', async ({ page }) => {
  162. await login(page)
  163. // 展开系统管理菜单
  164. await page.getByText('系统管理').first().click()
  165. await page.waitForTimeout(300)
  166. // 点击用户管理菜单项
  167. await page.getByText('用户管理').first().click()
  168. // 验证跳转到用户管理页面
  169. await expect(page).toHaveURL(/\/system\/user/)
  170. await expect(page.locator(byDataId('btn-add'))).toBeVisible()
  171. })
  172. test('状态筛选功能', async ({ page }) => {
  173. await login(page)
  174. await page.goto('/system/user')
  175. // 等待表格加载
  176. await expect(page.locator(byDataId('user-table'))).toBeVisible()
  177. // 选择启用状态
  178. await page.locator(byDataId('search-status')).click()
  179. await page.getByText('启用').click()
  180. // 点击查询
  181. await page.locator(byDataId('btn-search')).click()
  182. await page.waitForTimeout(500)
  183. // 表格应该仍然可见
  184. await expect(page.locator(byDataId('user-table'))).toBeVisible()
  185. // 选择禁用状态
  186. await page.locator(byDataId('search-status')).click()
  187. await page.getByText('禁用').click()
  188. // 点击查询
  189. await page.locator(byDataId('btn-search')).click()
  190. await page.waitForTimeout(500)
  191. // 表格应该仍然可见
  192. await expect(page.locator(byDataId('user-table'))).toBeVisible()
  193. })
  194. })