history-enter-exam-unexposed.cy.ts 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /**
  2. * 测试文件: 进入检查 - History双击进入检查(未曝光)
  3. * 场景: 从History双击未曝光任务,系统应进入检查界面
  4. *
  5. * 路径分析:
  6. * - POM: LoginPage, MainPage, HistoryPage, ExamPage
  7. * - Mock:
  8. * - mockLoginSuccess() - 登录成功
  9. * - mockFetchHistoryDataWithUnlocked() - 获取History列表
  10. * - mockGetStudyDetailsUnexposed() - 获取未曝光检查详情
  11. * - 规格:
  12. * ✓ 登录成功
  13. * ✓ 导航到History列表
  14. * ✓ History列表显示至少2条记录
  15. * ✓ 双击第一条未曝光记录
  16. * ✓ 系统加载任务详细信息(未曝光状态)
  17. * ✓ 进入检查界面(businessFlow: 'exam')
  18. * ✓ 验证Redux状态正确
  19. * ✓ 验证界面元素可见
  20. *
  21. * @see docs/测试/进入检查功能测试方案.md - 场景3
  22. */
  23. import { mockLoginSuccess } from '../../support/mock/handlers/user';
  24. import { mockFetchHistoryDataWithUnlocked } from '../../support/mock/handlers/worklist';
  25. import { mockGetStudyDetailsUnexposed } from '../../support/mock/handlers/study';
  26. import LoginPage from '../../support/pageObjects/LoginPage';
  27. import MainPage from '../../support/pageObjects/MainPage';
  28. import HistoryPage from '../../support/pageObjects/HistoryPage';
  29. import ExamPage from '../../support/pageObjects/ExamPage';
  30. describe('进入检查:History双击进入检查(未曝光)', () => {
  31. const loginPage = new LoginPage();
  32. const mainPage = new MainPage();
  33. const historyPage = new HistoryPage();
  34. const examPage = new ExamPage();
  35. beforeEach(() => {
  36. // 设置所有必要的Mock
  37. mockLoginSuccess();
  38. mockFetchHistoryDataWithUnlocked();
  39. // 使用第一条History记录的StudyID
  40. mockGetStudyDetailsUnexposed('HIST20250912001');
  41. });
  42. it('应该通过双击History未曝光条目进入检查界面', () => {
  43. /**
  44. * Given: 用户已登录
  45. * 步骤1(前置): 打开登录界面,完成登录
  46. */
  47. loginPage.visit();
  48. loginPage.getUsernameInput().should('be.visible');
  49. loginPage.login('admin', '123456');
  50. // 等待登录成功
  51. cy.wait('@loginSuccess');
  52. cy.contains('登录成功').should('be.visible', { timeout: 10000 });
  53. /**
  54. * When: 导航到History
  55. * 步骤1: 打开 History
  56. */
  57. mainPage.clickPatientManagementButton();
  58. mainPage.clickHistorylistButton();
  59. /**
  60. * Then: 系统加载History任务信息
  61. * 步骤2(前置): 验证History列表加载
  62. */
  63. cy.wait('@getHistoryUnlocked').then((interception) => {
  64. expect(interception.response?.statusCode).to.eq(200);
  65. });
  66. // 验证History列表显示(至少2条记录)
  67. historyPage.getTable().should('be.visible');
  68. historyPage.getTable().find('tr').should('have.length.at.least', 2);
  69. /**
  70. * When: 用户双击第一条未曝光任务
  71. * 步骤2: 双击任务条目
  72. */
  73. historyPage.findTableAndDoubleClickFirstRow();
  74. /**
  75. * Then: 系统加载任务详细信息(未曝光状态)
  76. * 步骤3: 验证API调用和返回数据
  77. */
  78. cy.wait('@getStudyDetailsUnexposed').then((interception) => {
  79. expect(interception.response?.statusCode).to.eq(200);
  80. // 验证返回的数据包含未曝光的检查信息
  81. const studyData = interception.response?.body.data;
  82. expect(studyData).to.have.property('study_id');
  83. expect(studyData).to.have.property('series');
  84. expect(studyData.series).to.be.an('array');
  85. // 验证所有images的expose_status为'Unexposed'
  86. studyData.series.forEach((series: any) => {
  87. series.images.forEach((image: any) => {
  88. expect(image.expose_status).to.eq('Unexposed');
  89. });
  90. });
  91. });
  92. /**
  93. * Then: 验证Redux状态 - examWorksCache
  94. * 步骤4: 验证任务数据已缓存
  95. */
  96. cy.window()
  97. .its('store')
  98. .invoke('getState')
  99. .its('examWorksCache')
  100. .its('works')
  101. .should('have.length', 1)
  102. .its(0)
  103. .should('have.property', 'StudyID', 'HIST20250912001');
  104. /**
  105. * Then: 验证Redux状态 - businessFlow
  106. * 步骤5: 验证进入检查流程(exam模式)
  107. */
  108. cy.window()
  109. .its('store')
  110. .invoke('getState')
  111. .its('businessFlow')
  112. .its('currentFlow')
  113. .should('eq', 'exam');
  114. /**
  115. * Then: 验证检查界面元素可见
  116. * 步骤6: 验证目标界面加载
  117. */
  118. examPage.verifyExamPageLoaded();
  119. examPage.getToolbar().should('be.visible');
  120. examPage.getContentArea().should('be.visible');
  121. });
  122. it('应该在Redux中正确保存任务的Views数据', () => {
  123. /**
  124. * 这个测试用例专注于验证数据转换的正确性
  125. */
  126. loginPage.visit();
  127. loginPage.login('admin', '123456');
  128. cy.wait('@loginSuccess');
  129. mainPage.clickPatientManagementButton();
  130. mainPage.clickHistorylistButton();
  131. cy.wait('@getHistoryUnlocked');
  132. historyPage.findTableAndDoubleClickFirstRow();
  133. cy.wait('@getStudyDetailsUnexposed');
  134. /**
  135. * 验证Views数组被正确构建
  136. */
  137. cy.window()
  138. .its('store')
  139. .invoke('getState')
  140. .its('examWorksCache')
  141. .its('works')
  142. .its(0)
  143. .its('Views')
  144. .should('be.an', 'array')
  145. .should('have.length.greaterThan', 0)
  146. .then((views: any[]) => {
  147. // 验证每个View包含必要的属性
  148. views.forEach((view) => {
  149. expect(view).to.have.property('view_id');
  150. expect(view).to.have.property('view_description');
  151. expect(view).to.have.property('expose_status', 'Unexposed');
  152. expect(view).to.have.property('study_id');
  153. expect(view).to.have.property('series_instance_uid');
  154. });
  155. });
  156. });
  157. it('应该正确从History进入检查流程', () => {
  158. /**
  159. * 验证从History进入检查的完整流程
  160. */
  161. loginPage.visit();
  162. loginPage.login('admin', '123456');
  163. cy.wait('@loginSuccess');
  164. mainPage.clickPatientManagementButton();
  165. mainPage.clickHistorylistButton();
  166. cy.wait('@getHistoryUnlocked');
  167. // 验证History记录的状态
  168. cy.window()
  169. .its('store')
  170. .invoke('getState')
  171. .its('historyEntities')
  172. .its('data')
  173. .should('have.length.greaterThan', 0)
  174. .its(0)
  175. .should('have.property', 'study_status', 'Completed');
  176. historyPage.findTableAndDoubleClickFirstRow();
  177. cy.wait('@getStudyDetailsUnexposed');
  178. // 验证进入检查流程后,businessFlow正确
  179. cy.window()
  180. .its('store')
  181. .invoke('getState')
  182. .its('businessFlow')
  183. .its('currentFlow')
  184. .should('eq', 'exam');
  185. // 验证examWorksCache包含从History加载的数据
  186. cy.window()
  187. .its('store')
  188. .invoke('getState')
  189. .its('examWorksCache')
  190. .its('works')
  191. .its(0)
  192. .should('have.property', 'StudyID', 'HIST20250912001');
  193. });
  194. });