reset-generator.cy.ts 7.9 KB

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