disability-person-company-query-enhanced.spec.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. import { TIMEOUTS } from '../../utils/timeouts';
  2. import { test, expect } from '../../utils/test-setup';
  3. import { readFileSync } from 'fs';
  4. import { join, dirname } from 'path';
  5. import { fileURLToPath } from 'url';
  6. const __filename = fileURLToPath(import.meta.url);
  7. const __dirname = dirname(__filename);
  8. const testUsers = JSON.parse(readFileSync(join(__dirname, '../../fixtures/test-users.json'), 'utf-8'));
  9. /**
  10. * Story 15.3: 残疾人企业查询页面完善
  11. *
  12. * 验收标准:
  13. * 1. 页面包含"平台"筛选下拉框
  14. * 2. 平台下拉框包含所有可用平台选项
  15. * 3. 表格列与需求一致(姓名、性别、身份证号、残疾类别、残疾等级、所属企业、入职日期)
  16. * 4. 用户可以选择平台进行筛选
  17. * 5. 筛选后表格显示对应平台的残疾人信息
  18. * 6. 平台筛选与其他筛选条件可以组合使用
  19. * 7. 重置筛选条件功能正常工作
  20. */
  21. test.describe('残疾人企业查询页面功能测试', () => {
  22. const PAGE_PATH = '/admin/disability-person-company-query';
  23. test.beforeEach(async ({ adminLoginPage, page }) => {
  24. await adminLoginPage.goto();
  25. await adminLoginPage.login(testUsers.admin.username, testUsers.admin.password);
  26. await adminLoginPage.expectLoginSuccess();
  27. await page.goto(PAGE_PATH);
  28. // 等待页面加载完成
  29. await page.waitForSelector('[data-testid="disability-person-company-query"]', { timeout: TIMEOUTS.PAGE_LOAD });
  30. });
  31. test.describe('AC1: 页面包含平台筛选下拉框', () => {
  32. test('应该显示平台筛选条件', async ({ page }) => {
  33. console.debug('\n========== 测试:验证平台筛选条件存在 ==========');
  34. // 验证平台筛选 Label 存在 (使用 locator 精确定位)
  35. const platformLabel = page.locator('[data-testid="disability-person-company-query"]').getByText('平台', { exact: true });
  36. await expect(platformLabel).toBeVisible({ timeout: TIMEOUTS.ELEMENT_VISIBLE_SHORT });
  37. console.debug('✓ 平台筛选 Label 可见');
  38. // 验证平台筛选器组件存在
  39. const platformFilter = page.getByTestId('platform-filter');
  40. await expect(platformFilter).toBeVisible({ timeout: TIMEOUTS.ELEMENT_VISIBLE_SHORT });
  41. console.debug('✓ 平台筛选组件可见');
  42. console.debug('✅ 测试通过:平台筛选条件存在');
  43. });
  44. test('平台下拉框应该包含"全部平台"占位符', async ({ page }) => {
  45. console.debug('\n========== 测试:验证平台筛选占位符 ==========');
  46. const platformFilter = page.getByTestId('platform-filter');
  47. await expect(platformFilter).toBeVisible({ timeout: TIMEOUTS.ELEMENT_VISIBLE_SHORT });
  48. // 检查显示文本(Shadcn UI Select 在 generic 元素中显示占位符)
  49. const displayedText = await platformFilter.textContent();
  50. expect(displayedText).toContain('全部平台');
  51. console.debug('✓ 平台占位符文本正确:', displayedText);
  52. console.debug('✅ 测试通过:平台筛选占位符正确');
  53. });
  54. });
  55. test.describe('AC3: 表格列与需求一致', () => {
  56. test('表格应该包含所有必需的列', async ({ page }) => {
  57. console.debug('\n========== 测试:验证表格列定义 ==========');
  58. const table = page.getByTestId('results-table');
  59. await expect(table).toBeVisible();
  60. // 验证表头包含所有必需的列
  61. // 表格使用 cell role 而非 columnheader,所以使用 cell 来查找
  62. const expectedColumns = ['姓名', '性别', '身份证号', '残疾类别', '残疾等级', '所属企业', '入职日期'];
  63. for (const column of expectedColumns) {
  64. const header = table.getByRole('cell').filter({ hasText: column });
  65. await expect(header).toBeVisible();
  66. console.debug(`✓ 表格列可见: ${column}`);
  67. }
  68. // 验证列数量正确(获取第一行所有 cell)
  69. const firstRow = table.getByRole('row').first();
  70. const cells = firstRow.getByRole('cell');
  71. const cellCount = await cells.count();
  72. expect(cellCount).toBe(7);
  73. console.debug(`✓ 表格列总数正确: ${cellCount}`);
  74. console.debug('✅ 测试通过:表格列定义正确');
  75. });
  76. test('表格数据行应该包含所有字段', async ({ page }) => {
  77. console.debug('\n========== 测试:验证表格数据显示 ==========');
  78. const table = page.getByTestId('results-table');
  79. await expect(table).toBeVisible();
  80. // 等待数据加载
  81. await page.waitForTimeout(TIMEOUTS.SHORT);
  82. // 检查是否有数据
  83. const noDataRow = table.getByTestId('no-data-row');
  84. const hasData = await noDataRow.count() === 0;
  85. if (hasData) {
  86. // 获取第一行数据
  87. const firstRow = table.getByRole('row').nth(1); // 跳过表头
  88. const cells = firstRow.getByRole('cell');
  89. // 验证单元格数量
  90. const cellCount = await cells.count();
  91. expect(cellCount).toBe(7);
  92. console.debug(`✓ 数据行单元格数量正确: ${cellCount}`);
  93. // 验证入职日期格式(如果有数据)
  94. const joinDateCell = cells.nth(6); // 入职日期列
  95. const joinDateText = await joinDateCell.textContent();
  96. if (joinDateText && joinDateText !== '-') {
  97. // 验证日期格式 (例如:2026/1/20)
  98. const datePattern = /\d{4}\/\d{1,2}\/\d{1,2}/;
  99. expect(joinDateText).toMatch(datePattern);
  100. console.debug('✓ 入职日期格式正确:', joinDateText);
  101. }
  102. } else {
  103. console.debug('ℹ️ 当前无测试数据,跳过数据行验证');
  104. }
  105. console.debug('✅ 测试通过:表格数据显示正确');
  106. });
  107. });
  108. test.describe('AC4: 用户可以选择平台进行筛选', () => {
  109. test('应该能够选择平台筛选器', async ({ page }) => {
  110. console.debug('\n========== 测试:选择平台筛选器 ==========');
  111. const platformFilter = page.getByTestId('platform-filter');
  112. await expect(platformFilter).toBeVisible();
  113. // 点击平台筛选器打开下拉框
  114. await platformFilter.click();
  115. console.debug('✓ 平台筛选器已点击');
  116. // 等待下拉选项出现
  117. await page.waitForTimeout(TIMEOUTS.VERY_SHORT);
  118. // 检查是否有平台选项(如果有平台数据)
  119. const firstOption = page.getByRole('option').first();
  120. const hasOptions = await firstOption.count() > 0;
  121. if (hasOptions) {
  122. const optionText = await firstOption.textContent();
  123. console.debug('✓ 平台选项存在:', optionText);
  124. // 选择第一个平台
  125. await firstOption.click();
  126. console.debug('✓ 已选择平台');
  127. // 等待筛选生效
  128. await page.waitForTimeout(TIMEOUTS.VERY_SHORT);
  129. } else {
  130. console.debug('ℹ️ 当前无平台数据,跳过选项选择');
  131. }
  132. console.debug('✅ 测试通过:平台筛选器可交互');
  133. });
  134. });
  135. test.describe('AC5: 筛选后表格显示对应平台的残疾人信息', () => {
  136. test('选择平台后应该显示筛选结果', async ({ page }) => {
  137. console.debug('\n========== 测试:筛选结果验证 ==========');
  138. const platformFilter = page.getByTestId('platform-filter');
  139. const searchButton = page.getByTestId('search-button');
  140. const table = page.getByTestId('results-table');
  141. // 先获取初始行数
  142. await page.waitForTimeout(TIMEOUTS.SHORT);
  143. const initialRows = await table.getByRole('row').count();
  144. console.debug('初始数据行数:', initialRows);
  145. // 尝试选择平台
  146. await platformFilter.click();
  147. await page.waitForTimeout(TIMEOUTS.VERY_SHORT);
  148. const firstOption = page.getByRole('option').first();
  149. const hasOptions = await firstOption.count() > 0;
  150. if (hasOptions) {
  151. await firstOption.click();
  152. console.debug('✓ 已选择平台');
  153. // 点击查询按钮
  154. await searchButton.click();
  155. console.debug('✓ 查询按钮已点击');
  156. // 等待结果更新
  157. await page.waitForTimeout(TIMEOUTS.SHORT);
  158. // 验证表格仍然可见
  159. await expect(table).toBeVisible();
  160. console.debug('✓ 筛选后表格仍然可见');
  161. // 获取筛选后的行数
  162. const filteredRows = await table.getByRole('row').count();
  163. console.debug('筛选后数据行数:', filteredRows);
  164. } else {
  165. console.debug('ℹ️ 当前无平台数据,跳过筛选验证');
  166. }
  167. console.debug('✅ 测试通过:筛选功能正常工作');
  168. });
  169. });
  170. test.describe('AC6: 平台筛选与其他筛选条件组合使用', () => {
  171. test('平台筛选和性别筛选应该能组合使用', async ({ page }) => {
  172. console.debug('\n========== 测试:组合筛选验证 ==========');
  173. const platformFilter = page.getByTestId('platform-filter');
  174. const genderFilter = page.getByTestId('gender-filter');
  175. const searchButton = page.getByTestId('search-button');
  176. // 尝试设置组合筛选条件
  177. await platformFilter.click();
  178. await page.waitForTimeout(TIMEOUTS.VERY_SHORT);
  179. const hasPlatformOptions = await page.getByRole('option').count() > 0;
  180. if (hasPlatformOptions) {
  181. // 选择第一个平台
  182. await page.getByRole('option').first().click();
  183. console.debug('✓ 已选择平台');
  184. // 选择性别
  185. await genderFilter.click();
  186. await page.waitForTimeout(TIMEOUTS.VERY_SHORT);
  187. await page.getByRole('option', { name: '男' }).click();
  188. console.debug('✓ 已选择性别: 男');
  189. // 点击查询
  190. await searchButton.click();
  191. console.debug('✓ 查询按钮已点击');
  192. // 等待结果
  193. await page.waitForTimeout(TIMEOUTS.SHORT);
  194. console.debug('✅ 测试通过:组合筛选功能正常');
  195. } else {
  196. console.debug('ℹ️ 当前无平台数据,跳过组合筛选验证');
  197. }
  198. });
  199. });
  200. test.describe('AC7: 重置筛选条件功能', () => {
  201. test('点击重置按钮应该清空所有筛选条件', async ({ page }) => {
  202. console.debug('\n========== 测试:重置筛选条件 ==========');
  203. const platformFilter = page.getByTestId('platform-filter');
  204. const genderFilter = page.getByTestId('gender-filter');
  205. const resetButton = page.getByTestId('reset-button');
  206. // 先设置一些筛选条件
  207. await genderFilter.click();
  208. await page.waitForTimeout(TIMEOUTS.VERY_SHORT);
  209. await page.getByRole('option', { name: '女' }).click();
  210. console.debug('✓ 已选择性别: 女');
  211. await platformFilter.click();
  212. await page.waitForTimeout(TIMEOUTS.VERY_SHORT);
  213. const hasPlatformOptions = await page.getByRole('option').count() > 0;
  214. if (hasPlatformOptions) {
  215. await page.getByRole('option').first().click();
  216. console.debug('✓ 已选择平台');
  217. }
  218. // 点击重置按钮
  219. await resetButton.click();
  220. console.debug('✓ 重置按钮已点击');
  221. // 等待重置生效
  222. await page.waitForTimeout(TIMEOUTS.SHORT);
  223. // 验证性别筛选已重置(应该显示"全部")
  224. await genderFilter.click();
  225. await page.waitForTimeout(TIMEOUTS.VERY_SHORT);
  226. const allOption = page.getByRole('option', { name: '全部' });
  227. await expect(allOption).toHaveAttribute('data-state', 'checked');
  228. console.debug('✓ 性别筛选已重置');
  229. console.debug('✅ 测试通过:重置筛选条件功能正常');
  230. });
  231. });
  232. test.describe('导出数据功能验证', () => {
  233. test('导出按钮应该在有数据时可点击', async ({ page }) => {
  234. console.debug('\n========== 测试:导出功能验证 ==========');
  235. const exportButton = page.getByTestId('export-button');
  236. await expect(exportButton).toBeVisible();
  237. console.debug('✓ 导出按钮可见');
  238. // 等待数据加载
  239. await page.waitForTimeout(TIMEOUTS.SHORT);
  240. // 检查按钮状态
  241. const isDisabled = await exportButton.isDisabled();
  242. console.debug('导出按钮禁用状态:', isDisabled);
  243. console.debug('✅ 测试通过:导出功能正常');
  244. });
  245. });
  246. });