import { mockI18nSuccess, 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('不支持的语言自动回退到英文', () => { // 设置英文mock,因为不支持的语言会回退到英文 mockI18nSuccess('en'); const unsupportedLanguages = [ 'fr-FR', // 法语 'de-DE', // 德语 'ja-JP', // 日语 'ko-KR', // 韩语 'es-ES', // 西班牙语 'it-IT', // 意大利语 'pt-BR', // 葡萄牙语 'ru-RU', // 俄语 'ar-SA', // 阿拉伯语 'hi-IN' // 印地语 ]; unsupportedLanguages.forEach((lang, index) => { mockI18nSuccess('en'); // 每次都重新设置英文mock cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: lang, writable: false }); }); loginPage.visit(); // 验证请求的是英文资源 cy.wait('@getI18nENSuccess'); // 验证显示英文内容 cy.get('body').should('contain', 'Patient Management'); // 验证Redux状态为英文 cy.window().its('store').invoke('getState').then((state) => { expect(state.i18n.currentLocale).to.equal('en'); expect(state.i18n.messages).to.have.property('patient', 'Patient Management'); }); // 清理,准备下一个测试 if (index < unsupportedLanguages.length - 1) { cy.clearAllSessionStorage(); cy.clearAllLocalStorage(); } }); }); it('无效的语言代码回退到英文', () => { mockI18nSuccess('en'); const invalidLanguages = [ 'invalid', 'xx-XX', '123', 'zh-INVALID', 'en-INVALID', '', null, undefined ]; invalidLanguages.forEach((lang, index) => { mockI18nSuccess('en'); cy.window().then((win) => { if (lang === null || lang === undefined) { // 模拟navigator.language为null或undefined的情况 Object.defineProperty(win.navigator, 'language', { value: lang, writable: false }); } else { Object.defineProperty(win.navigator, 'language', { value: lang, writable: false }); } }); loginPage.visit(); cy.wait('@getI18nENSuccess'); // 验证回退到英文 cy.get('body').should('contain', 'Patient Management'); cy.window().its('store').invoke('getState').then((state) => { expect(state.i18n.currentLocale).to.equal('en'); }); if (index < invalidLanguages.length - 1) { cy.clearAllSessionStorage(); cy.clearAllLocalStorage(); } }); }); it('浏览器不支持navigator.language时回退到英文', () => { mockI18nSuccess('en'); cy.window().then((win) => { // 模拟navigator.language不存在的情况 Object.defineProperty(win.navigator, 'language', { value: undefined, writable: false }); }); loginPage.visit(); cy.wait('@getI18nENSuccess'); // 验证回退到英文 cy.get('body').should('contain', 'Patient Management'); cy.window().its('store').invoke('getState').then((state) => { expect(state.i18n.currentLocale).to.equal('en'); expect(state.i18n.messages).to.have.property('patient', 'Patient Management'); }); }); it('验证语言回退的逻辑正确性', () => { // 测试语言检测和回退的完整逻辑 const testCases = [ // 支持的语言应该正常加载 { input: 'zh-CN', expected: 'zh', expectedText: '患者管理' }, { input: 'zh-TW', expected: 'zh', expectedText: '患者管理' }, { input: 'en-US', expected: 'en', expectedText: 'Patient Management' }, { input: 'en-GB', expected: 'en', expectedText: 'Patient Management' }, // 不支持的语言应该回退到英文 { input: 'fr-FR', expected: 'en', expectedText: 'Patient Management' }, { input: 'de-DE', expected: 'en', expectedText: 'Patient Management' }, { input: 'ja-JP', expected: 'en', expectedText: 'Patient Management' }, // 边界情况 { input: 'zh', expected: 'zh', expectedText: '患者管理' }, { input: 'en', expected: 'en', expectedText: 'Patient Management' }, { input: 'fr', expected: 'en', expectedText: 'Patient Management' } ]; testCases.forEach(({ input, expected, expectedText }, index) => { mockI18nSuccess(expected as 'zh' | 'en'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: input, writable: false }); }); loginPage.visit(); cy.wait(`@getI18n${expected.toUpperCase()}Success`); // 验证正确的语言内容显示 cy.get('body').should('contain', expectedText); // 验证Redux状态 cy.window().its('store').invoke('getState').then((state) => { expect(state.i18n.currentLocale).to.equal(expected); }); if (index < testCases.length - 1) { cy.clearAllSessionStorage(); cy.clearAllLocalStorage(); } }); }); it('验证回退语言的完整性', () => { mockI18nSuccess('en'); // 使用不支持的语言 cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'fr-FR', writable: false }); }); loginPage.visit(); cy.wait('@getI18nENSuccess'); // 验证回退到英文后,所有必要的翻译都存在 cy.window().its('store').invoke('getState').then((state) => { expect(state.i18n.currentLocale).to.equal('en'); expect(state.i18n.loading).to.be.false; expect(state.i18n.error).to.be.null; // 验证关键翻译存在 expect(state.i18n.messages).to.have.property('patient', 'Patient Management'); expect(state.i18n.messages).to.have.property('register', 'Register'); expect(state.i18n.messages).to.have.property('worklist', 'Task List'); expect(state.i18n.messages).to.have.property('register.patientId', 'Patient ID'); expect(state.i18n.messages).to.have.property('register.patientName', 'Patient Name'); }); // 验证页面显示正确 cy.get('body').should('contain', 'Patient Management'); }); it('验证多次语言回退的稳定性', () => { // 连续测试多个不支持的语言,验证每次都能正确回退 const unsupportedSequence = ['fr-FR', 'de-DE', 'ja-JP', 'ko-KR', 'es-ES']; unsupportedSequence.forEach((lang, index) => { mockI18nSuccess('en'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: lang, writable: false }); }); loginPage.visit(); cy.wait('@getI18nENSuccess'); // 每次都应该回退到英文 cy.get('body').should('contain', 'Patient Management'); cy.window().its('store').invoke('getState').then((state) => { expect(state.i18n.currentLocale).to.equal('en'); expect(state.i18n.loading).to.be.false; expect(state.i18n.error).to.be.null; }); if (index < unsupportedSequence.length - 1) { cy.clearAllSessionStorage(); cy.clearAllLocalStorage(); } }); }); it('验证语言回退时的请求参数', () => { mockI18nSuccess('en'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'fr-FR', // 不支持的语言 writable: false }); }); loginPage.visit(); // 验证请求的是英文资源,而不是法语资源 cy.wait('@getI18nENSuccess').then((interception) => { expect(interception.request.url).to.include('/dr/api/v1/pub/trans/en/en.js'); expect(interception.request.url).to.not.include('/dr/api/v1/pub/trans/fr/fr.js'); expect(interception.request.method).to.equal('GET'); }); }); it('验证回退语言加载失败时的处理', () => { // 模拟回退语言(英文)加载失败的情况 cy.intercept('GET', '/dr/api/v1/pub/trans/en/en.js', (req) => { req.reply({ statusCode: 404, body: { message: 'Not Found' } }); }).as('getI18nENError'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'fr-FR', // 不支持的语言,会回退到英文 writable: false }); }); loginPage.visit(); cy.wait('@getI18nENError'); // 验证即使回退语言加载失败,也能正确显示错误 cy.contains('多语言资源加载失败').should('be.visible'); cy.contains('重新加载').should('be.visible'); cy.window().its('store').invoke('getState').then((state) => { expect(state.i18n.loading).to.be.false; expect(state.i18n.error).to.not.be.null; // 注意:currentLocale可能仍然是'en',因为这是尝试加载的语言 expect(state.i18n.messages).to.deep.equal({}); }); }); it('验证语言回退不影响其他功能', () => { mockI18nSuccess('en'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'de-DE', // 不支持的语言 writable: false }); }); loginPage.visit(); cy.wait('@getI18nENSuccess'); // 验证语言回退后,其他Redux状态正常 cy.window().its('store').invoke('getState').then((state) => { // 验证其他slice的状态不受影响 expect(state.product).to.exist; expect(state.userInfo).to.exist; // i18n状态正确 expect(state.i18n.currentLocale).to.equal('en'); expect(state.i18n.loading).to.be.false; expect(state.i18n.error).to.be.null; }); // 验证页面正常渲染 cy.get('body').should('exist'); cy.get('body').should('contain', 'Patient Management'); }); });