reset-generator.cy.ts 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. import LoginPage from '../../support/pageObjects/LoginPage';
  2. import MainPage from '../../support/pageObjects/MainPage';
  3. import ExamPage from '../../support/pageObjects/ExamPage';
  4. import WorklistPage from '../../support/pageObjects/WorklistPage';
  5. import {
  6. mockResetDeviceSuccess,
  7. mockResetDeviceFail,
  8. mockResetDeviceNetworkError,
  9. mockResetDeviceDelay,
  10. } from '../../support/mock/handlers/device';
  11. import {
  12. mockI18nSuccess,
  13. mockGetLanguageListSuccess,
  14. mockAllRequiredAPIs,
  15. } from '../../support/mock/handlers/i18n';
  16. import { mockLoginSuccess } from '../../support/mock/handlers/user';
  17. import { mockGetStudyDetails } from '../../support/mock/handlers/study';
  18. import { mockFetchTwoWorks } from '../../support/mock/handlers/worklist';
  19. import { mockGetQuotaSuccess } from '../../support/mock/handlers/quota';
  20. import { mockGetAprDetailsComplete, mockGetViewDetailComplete, mockGetBodyPartHuman } from '../../support/mock/handlers/protocol';
  21. describe('重置高压发生器功能测试', () => {
  22. const loginPage = new LoginPage();
  23. const mainPage = new MainPage();
  24. const examPage = new ExamPage();
  25. const worklistPage = new WorklistPage();
  26. beforeEach(() => {
  27. // Mock多语言资源和必要的API
  28. mockI18nSuccess('zh_CN');
  29. mockGetLanguageListSuccess();
  30. mockAllRequiredAPIs('zh_CN');
  31. // Mock登录成功响应
  32. mockLoginSuccess();
  33. // Mock 进入worklist后得到两个数据
  34. mockFetchTwoWorks();
  35. // Mock得到配额成功
  36. mockGetQuotaSuccess();
  37. // Mock获取检查详情
  38. mockGetStudyDetails('20250912135259444');
  39. // Mock获取APR详情
  40. mockGetAprDetailsComplete();
  41. // Mock获取View详情
  42. mockGetViewDetailComplete();
  43. // Mock获取身体部位列表
  44. mockGetBodyPartHuman();
  45. // 登录系统
  46. loginPage.visit();
  47. loginPage.login('admin', '123456');
  48. // 等待页面渲染和路由跳转
  49. cy.wait(1500);
  50. // 验证登录成功:登录页面元素不再存在
  51. loginPage.getUsernameInput().should('not.exist');
  52. loginPage.getPasswordInput().should('not.exist');
  53. loginPage.getSubmitButton().should('not.exist');
  54. // 导航到工作列表
  55. // mainPage.clickPatientManagementButton(); //默认展开,不需要点击使之展开
  56. mainPage.clickWorklistButton();
  57. // 双击第一行进入检查页面
  58. worklistPage.findTableAndDoubleClickFirstRow();
  59. cy.wait(3000);
  60. // 验证已进入检查页面
  61. cy.get('[data-testid="exam-page"]').should('exist');
  62. });
  63. describe('TC-RESET-01: 成功重置设备', () => {
  64. it('应该成功重置高压发生器并更新UI状态', () => {
  65. // 1. Mock设备重置API成功响应
  66. mockResetDeviceSuccess();
  67. // 2. 验证按钮初始状态为可用
  68. examPage.verifyResetButtonEnabled();
  69. // 3. 验证初始Redux状态
  70. examPage.verifyDeviceStatus('idle');
  71. // 4. 点击RESET按钮
  72. examPage.clickResetGenerator();
  73. // 5. 验证按钮变为禁用状态(loading)
  74. examPage.verifyResetButtonDisabled();
  75. // 6. 等待API调用完成
  76. cy.wait('@resetDevice').then((interception) => {
  77. // 验证请求体
  78. expect(interception.request.body).to.deep.include({
  79. deviceUri: 'DIOS/DEVICE/Generator',
  80. reqName: 'RESET',
  81. });
  82. // 验证响应
  83. expect(interception.response?.statusCode).to.eq(200);
  84. expect(interception.response?.body.code).to.eq('0x000000');
  85. });
  86. // 7. 验证按钮恢复为可用状态
  87. examPage.verifyResetButtonEnabled();
  88. // 8. 验证Redux状态更新为'succeeded'
  89. examPage.verifyDeviceStatus('succeeded');
  90. // 9. 验证无错误信息
  91. examPage.verifyDeviceError(null);
  92. });
  93. });
  94. describe('TC-RESET-02: API失败处理', () => {
  95. it('应该正确处理设备重置失败', () => {
  96. // 1. Mock设备重置API失败响应
  97. mockResetDeviceFail('0x010001', '设备通信失败');
  98. // 2. 点击RESET按钮
  99. examPage.clickResetGenerator();
  100. // 3. 等待API调用完成
  101. cy.wait('@resetDeviceFail').then((interception) => {
  102. // 验证响应包含错误信息
  103. expect(interception.response?.body.code).to.eq('0x010001');
  104. expect(interception.response?.body.description).to.eq('设备通信失败');
  105. });
  106. // 4. 验证Redux状态更新为'failed'
  107. examPage.verifyDeviceStatus('failed');
  108. // 5. 验证错误信息存储到state.error
  109. cy.window()
  110. .its('store')
  111. .invoke('getState')
  112. .its('device')
  113. .its('error')
  114. .should('exist');
  115. // 6. 验证按钮恢复可用
  116. examPage.verifyResetButtonEnabled();
  117. // 7. 验证控制台输出错误日志
  118. cy.window().then((win) => {
  119. cy.spy(win.console, 'error');
  120. });
  121. });
  122. });
  123. describe('TC-RESET-03: 按钮禁用状态管理', () => {
  124. it('应该在loading期间正确管理按钮状态', () => {
  125. // 1. Mock设备重置API延迟响应(2秒)
  126. mockResetDeviceDelay(2000);
  127. // 2. 验证初始Redux状态
  128. examPage.verifyDeviceStatus('idle');
  129. // 3. 点击RESET按钮
  130. examPage.clickResetGenerator();
  131. // 4. 验证按钮立即禁用
  132. examPage.verifyResetButtonDisabled();
  133. // 5. 验证Redux状态变为loading
  134. examPage.verifyDeviceStatus('loading');
  135. // 6. 等待1秒,验证按钮仍然禁用
  136. cy.wait(1000);
  137. examPage.verifyResetButtonDisabled();
  138. examPage.verifyDeviceStatus('loading');
  139. // 7. 等待API响应完成
  140. cy.wait('@resetDeviceDelay');
  141. // 8. 验证按钮恢复可用
  142. examPage.verifyResetButtonEnabled();
  143. // 9. 验证Redux状态更新为'succeeded'
  144. examPage.verifyDeviceStatus('succeeded');
  145. });
  146. });
  147. describe('TC-RESET-04: 网络错误处理', () => {
  148. it('应该正确处理网络异常', () => {
  149. // 1. Mock网络错误
  150. mockResetDeviceNetworkError();
  151. // 2. 点击RESET按钮
  152. examPage.clickResetGenerator();
  153. // 3. 等待错误发生
  154. cy.wait('@resetDeviceNetworkError');
  155. // 4. 验证Redux状态更新为'failed'
  156. examPage.verifyDeviceStatus('failed');
  157. // 5. 验证错误信息被捕获
  158. cy.window()
  159. .its('store')
  160. .invoke('getState')
  161. .its('device')
  162. .its('error')
  163. .should('exist');
  164. // 6. 验证按钮恢复可用
  165. examPage.verifyResetButtonEnabled();
  166. // 7. 验证用户可以重试
  167. mockResetDeviceSuccess();
  168. examPage.clickResetGenerator();
  169. cy.wait('@resetDevice');
  170. examPage.verifyDeviceStatus('succeeded');
  171. });
  172. });
  173. describe('TC-RESET-05: 防止重复点击', () => {
  174. it('应该防止loading时重复点击', () => {
  175. // 1. Mock设备重置API延迟响应(3秒)
  176. let requestCount = 0;
  177. cy.intercept('POST', '**/auth/device/action', (req) => {
  178. if (req.body.reqName === 'RESET') {
  179. requestCount++;
  180. req.reply({
  181. statusCode: 200,
  182. body: {
  183. code: '0x000000',
  184. description: 'Success',
  185. data: {},
  186. },
  187. delay: 3000,
  188. });
  189. }
  190. }).as('resetDeviceMultiple');
  191. // 2. 点击RESET按钮
  192. examPage.clickResetGenerator();
  193. // 3. 验证按钮禁用
  194. examPage.verifyResetButtonDisabled();
  195. // 4. 立即再次尝试点击按钮(应该无效)
  196. examPage.getResetGeneratorButton().click({ force: true });
  197. // 5. 等待1秒后再次尝试点击
  198. cy.wait(1000);
  199. examPage.getResetGeneratorButton().click({ force: true });
  200. // 6. 等待第一次请求完成
  201. cy.wait('@resetDeviceMultiple');
  202. // 7. 验证只发送了一次API请求
  203. cy.wrap(null).then(() => {
  204. expect(requestCount).to.eq(1);
  205. });
  206. // 8. 验证完成后可以再次点击
  207. examPage.verifyResetButtonEnabled();
  208. // 重新mock成功响应
  209. mockResetDeviceSuccess();
  210. examPage.clickResetGenerator();
  211. cy.wait('@resetDevice');
  212. examPage.verifyDeviceStatus('succeeded');
  213. });
  214. });
  215. });