import { mockI18nError, mockI18nServerError, mockI18nNetworkError, mockAllRequiredAPIs } from '../../support/mock/handlers/i18n'; import LoginPage from '../../support/pageObjects/LoginPage'; describe('多语言资源错误处理测试', () => { const loginPage = new LoginPage(); beforeEach(() => { cy.clearAllSessionStorage(); cy.clearAllLocalStorage(); // Mock所有必要的API,避免影响页面加载 mockAllRequiredAPIs(); }); it('API返回404时显示错误提示并支持重新加载', () => { // 设置404错误mock mockI18nError('zh'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'zh-CN', writable: false }); }); loginPage.visit(); // 等待API调用失败 cy.wait('@getI18nZHError'); // 验证错误提示显示 cy.contains('多语言资源加载失败').should('be.visible'); cy.contains('重新加载').should('be.visible'); // 验证错误信息包含具体错误 cy.get('body').should('contain', 'Failed to load i18n messages'); // 测试重新加载按钮功能 // 重新设置成功的mock mockI18nError('zh'); // 再次设置错误mock来测试重试 cy.contains('重新加载').click(); // 验证再次发起API请求 cy.wait('@getI18nZHError'); // 验证错误提示仍然显示 cy.contains('多语言资源加载失败').should('be.visible'); }); it('API返回500服务器错误时正确处理', () => { mockI18nServerError('en'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'en-US', writable: false }); }); loginPage.visit(); cy.wait('@getI18nENServerError'); // 验证错误提示显示 cy.contains('多语言资源加载失败').should('be.visible'); cy.contains('重新加载').should('be.visible'); // 验证Redux状态正确 cy.window().its('store').invoke('getState').then((state) => { expect(state.i18n.loading).to.be.false; expect(state.i18n.error).to.not.be.null; expect(state.i18n.messages).to.deep.equal({}); }); }); it('网络连接错误时正确处理', () => { mockI18nNetworkError('zh'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'zh-CN', writable: false }); }); loginPage.visit(); cy.wait('@getI18nZHNetworkError'); // 验证错误提示显示 cy.contains('多语言资源加载失败').should('be.visible'); cy.contains('重新加载').should('be.visible'); }); it('验证错误状态下的用户体验', () => { mockI18nError('zh'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'zh-CN', writable: false }); }); loginPage.visit(); cy.wait('@getI18nZHError'); // 验证错误页面的样式和布局 cy.get('div').contains('多语言资源加载失败').should('be.visible') .parent().should('have.css', 'display', 'flex') .and('have.css', 'justify-content', 'center') .and('have.css', 'align-items', 'center'); // 验证重新加载按钮的样式 cy.contains('重新加载').should('be.visible') .and('have.css', 'margin-top', '16px') .and('have.css', 'padding', '8px 16px'); }); it('验证错误处理不影响其他功能', () => { mockI18nError('en'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'en-US', writable: false }); }); loginPage.visit(); cy.wait('@getI18nENError'); // 验证错误状态下页面基本结构仍然存在 cy.get('body').should('exist'); cy.get('div').should('exist'); // 验证Redux store的其他状态不受影响 cy.window().its('store').invoke('getState').then((state) => { // 验证其他slice的状态正常 expect(state.product).to.exist; expect(state.userInfo).to.exist; // i18n状态应该反映错误 expect(state.i18n.loading).to.be.false; expect(state.i18n.error).to.not.be.null; }); }); it('验证多次重新加载的行为', () => { let callCount = 0; // 设置动态mock,前两次失败,第三次成功 cy.intercept('GET', '/dr/api/v1/pub/trans/zh/zh.js', (req) => { callCount++; if (callCount <= 2) { req.reply({ statusCode: 404, body: { message: 'Not Found' } }); } else { req.reply({ statusCode: 200, body: { greeting: '你好,世界!', patient: '患者管理' } }); } }).as('getI18nZHDynamic'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'zh-CN', writable: false }); }); loginPage.visit(); // 第一次失败 cy.wait('@getI18nZHDynamic'); cy.contains('多语言资源加载失败').should('be.visible'); // 第一次重试,仍然失败 cy.contains('重新加载').click(); cy.wait('@getI18nZHDynamic'); cy.contains('多语言资源加载失败').should('be.visible'); // 第二次重试,成功 cy.contains('重新加载').click(); cy.wait('@getI18nZHDynamic'); // 验证成功加载 cy.contains('多语言资源加载失败').should('not.exist'); cy.get('body').should('contain', '患者管理'); }); });