i18n-error-handling.cy.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import { mockI18nError, mockI18nServerError, mockI18nNetworkError, mockAllRequiredAPIs } from '../../support/mock/handlers/i18n';
  2. import LoginPage from '../../support/pageObjects/LoginPage';
  3. describe('多语言资源错误处理测试', () => {
  4. const loginPage = new LoginPage();
  5. beforeEach(() => {
  6. cy.clearAllSessionStorage();
  7. cy.clearAllLocalStorage();
  8. // Mock所有必要的API,避免影响页面加载
  9. mockAllRequiredAPIs();
  10. });
  11. it('API返回404时显示错误提示并支持重新加载', () => {
  12. // 设置404错误mock
  13. mockI18nError('zh');
  14. cy.window().then((win) => {
  15. Object.defineProperty(win.navigator, 'language', {
  16. value: 'zh-CN',
  17. writable: false
  18. });
  19. });
  20. loginPage.visit();
  21. // 等待API调用失败
  22. cy.wait('@getI18nZHError');
  23. // 验证错误提示显示
  24. cy.contains('多语言资源加载失败').should('be.visible');
  25. cy.contains('重新加载').should('be.visible');
  26. // 验证错误信息包含具体错误
  27. cy.get('body').should('contain', 'Failed to load i18n messages');
  28. // 测试重新加载按钮功能
  29. // 重新设置成功的mock
  30. mockI18nError('zh'); // 再次设置错误mock来测试重试
  31. cy.contains('重新加载').click();
  32. // 验证再次发起API请求
  33. cy.wait('@getI18nZHError');
  34. // 验证错误提示仍然显示
  35. cy.contains('多语言资源加载失败').should('be.visible');
  36. });
  37. it('API返回500服务器错误时正确处理', () => {
  38. mockI18nServerError('en');
  39. cy.window().then((win) => {
  40. Object.defineProperty(win.navigator, 'language', {
  41. value: 'en-US',
  42. writable: false
  43. });
  44. });
  45. loginPage.visit();
  46. cy.wait('@getI18nENServerError');
  47. // 验证错误提示显示
  48. cy.contains('多语言资源加载失败').should('be.visible');
  49. cy.contains('重新加载').should('be.visible');
  50. // 验证Redux状态正确
  51. cy.window().its('store').invoke('getState').then((state) => {
  52. expect(state.i18n.loading).to.be.false;
  53. expect(state.i18n.error).to.not.be.null;
  54. expect(state.i18n.messages).to.deep.equal({});
  55. });
  56. });
  57. it('网络连接错误时正确处理', () => {
  58. mockI18nNetworkError('zh');
  59. cy.window().then((win) => {
  60. Object.defineProperty(win.navigator, 'language', {
  61. value: 'zh-CN',
  62. writable: false
  63. });
  64. });
  65. loginPage.visit();
  66. cy.wait('@getI18nZHNetworkError');
  67. // 验证错误提示显示
  68. cy.contains('多语言资源加载失败').should('be.visible');
  69. cy.contains('重新加载').should('be.visible');
  70. });
  71. it('验证错误状态下的用户体验', () => {
  72. mockI18nError('zh');
  73. cy.window().then((win) => {
  74. Object.defineProperty(win.navigator, 'language', {
  75. value: 'zh-CN',
  76. writable: false
  77. });
  78. });
  79. loginPage.visit();
  80. cy.wait('@getI18nZHError');
  81. // 验证错误页面的样式和布局
  82. cy.get('div').contains('多语言资源加载失败').should('be.visible')
  83. .parent().should('have.css', 'display', 'flex')
  84. .and('have.css', 'justify-content', 'center')
  85. .and('have.css', 'align-items', 'center');
  86. // 验证重新加载按钮的样式
  87. cy.contains('重新加载').should('be.visible')
  88. .and('have.css', 'margin-top', '16px')
  89. .and('have.css', 'padding', '8px 16px');
  90. });
  91. it('验证错误处理不影响其他功能', () => {
  92. mockI18nError('en');
  93. cy.window().then((win) => {
  94. Object.defineProperty(win.navigator, 'language', {
  95. value: 'en-US',
  96. writable: false
  97. });
  98. });
  99. loginPage.visit();
  100. cy.wait('@getI18nENError');
  101. // 验证错误状态下页面基本结构仍然存在
  102. cy.get('body').should('exist');
  103. cy.get('div').should('exist');
  104. // 验证Redux store的其他状态不受影响
  105. cy.window().its('store').invoke('getState').then((state) => {
  106. // 验证其他slice的状态正常
  107. expect(state.product).to.exist;
  108. expect(state.userInfo).to.exist;
  109. // i18n状态应该反映错误
  110. expect(state.i18n.loading).to.be.false;
  111. expect(state.i18n.error).to.not.be.null;
  112. });
  113. });
  114. it('验证多次重新加载的行为', () => {
  115. let callCount = 0;
  116. // 设置动态mock,前两次失败,第三次成功
  117. cy.intercept('GET', '/dr/api/v1/pub/trans/zh/zh.js', (req) => {
  118. callCount++;
  119. if (callCount <= 2) {
  120. req.reply({
  121. statusCode: 404,
  122. body: { message: 'Not Found' }
  123. });
  124. } else {
  125. req.reply({
  126. statusCode: 200,
  127. body: {
  128. greeting: '你好,世界!',
  129. patient: '患者管理'
  130. }
  131. });
  132. }
  133. }).as('getI18nZHDynamic');
  134. cy.window().then((win) => {
  135. Object.defineProperty(win.navigator, 'language', {
  136. value: 'zh-CN',
  137. writable: false
  138. });
  139. });
  140. loginPage.visit();
  141. // 第一次失败
  142. cy.wait('@getI18nZHDynamic');
  143. cy.contains('多语言资源加载失败').should('be.visible');
  144. // 第一次重试,仍然失败
  145. cy.contains('重新加载').click();
  146. cy.wait('@getI18nZHDynamic');
  147. cy.contains('多语言资源加载失败').should('be.visible');
  148. // 第二次重试,成功
  149. cy.contains('重新加载').click();
  150. cy.wait('@getI18nZHDynamic');
  151. // 验证成功加载
  152. cy.contains('多语言资源加载失败').should('not.exist');
  153. cy.get('body').should('contain', '患者管理');
  154. });
  155. });