worklist-enter-process-exposed.cy.ts 7.0 KB

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