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('验证中文翻译内容的正确性', () => { mockI18nSuccess('zh'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'zh-CN', writable: false }); }); loginPage.visit(); cy.wait('@getI18nZHSuccess'); // 验证Redux状态中的中文翻译 cy.window().its('store').invoke('getState').then((state) => { const messages = state.i18n.messages; // 验证基础翻译 expect(messages).to.have.property('greeting', '你好,世界!'); expect(messages).to.have.property('name', '张三'); expect(messages).to.have.property('patient', '患者管理'); expect(messages).to.have.property('register', '注册'); expect(messages).to.have.property('worklist', '任务清单'); // 验证嵌套键名翻译 expect(messages).to.have.property('worklist.operationPanel', '操作面板'); expect(messages).to.have.property('register.basicInfoPanel', '基本信息表单区域'); expect(messages).to.have.property('worklistTable.patientId', '患者编号'); expect(messages).to.have.property('worklistTable.name', '患者姓名'); // 验证表单字段翻译 expect(messages).to.have.property('register.patientId', '患者编号'); expect(messages).to.have.property('register.patientName', '患者姓名'); expect(messages).to.have.property('register.gender', '性别'); expect(messages).to.have.property('register.gender.male', '男'); expect(messages).to.have.property('register.gender.female', '女'); }); // 验证页面显示的中文内容 cy.get('body').should('contain', '患者管理'); }); it('验证英文翻译内容的正确性', () => { mockI18nSuccess('en'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'en-US', writable: false }); }); loginPage.visit(); cy.wait('@getI18nENSuccess'); // 验证Redux状态中的英文翻译 cy.window().its('store').invoke('getState').then((state) => { const messages = state.i18n.messages; // 验证基础翻译 expect(messages).to.have.property('greeting', 'Hello, world!'); expect(messages).to.have.property('name', 'John Doe'); expect(messages).to.have.property('patient', 'Patient Management'); expect(messages).to.have.property('register', 'Register'); expect(messages).to.have.property('worklist', 'Task List'); // 验证嵌套键名翻译 expect(messages).to.have.property('worklist.operationPanel', 'Operation Panel'); expect(messages).to.have.property('register.basicInfoPanel', 'Basic Information Form Area'); expect(messages).to.have.property('worklistTable.patientId', 'Patient ID'); expect(messages).to.have.property('worklistTable.name', 'Patient Name'); // 验证表单字段翻译 expect(messages).to.have.property('register.patientId', 'Patient ID'); expect(messages).to.have.property('register.patientName', 'Patient Name'); expect(messages).to.have.property('register.gender', 'Gender'); expect(messages).to.have.property('register.gender.male', 'Male'); expect(messages).to.have.property('register.gender.female', 'Female'); }); // 验证页面显示的英文内容 cy.get('body').should('contain', 'Patient Management'); }); it('验证中英文翻译的对应关系', () => { // 定义需要验证的关键翻译对 const translationPairs = [ { key: 'patient', zh: '患者管理', en: 'Patient Management' }, { key: 'register', zh: '注册', en: 'Register' }, { key: 'worklist', zh: '任务清单', en: 'Task List' }, { key: 'register.patientId', zh: '患者编号', en: 'Patient ID' }, { key: 'register.patientName', zh: '患者姓名', en: 'Patient Name' }, { key: 'register.gender.male', zh: '男', en: 'Male' }, { key: 'register.gender.female', zh: '女', en: 'Female' } ]; // 先验证中文 mockI18nSuccess('zh'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'zh-CN', writable: false }); }); loginPage.visit(); cy.wait('@getI18nZHSuccess'); cy.window().its('store').invoke('getState').then((zhState) => { const zhMessages = zhState.i18n.messages; // 验证中文翻译 translationPairs.forEach(({ key, zh }) => { expect(zhMessages).to.have.property(key, zh); }); }); // 再验证英文 mockI18nSuccess('en'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'en-US', writable: false }); }); loginPage.visit(); cy.wait('@getI18nENSuccess'); cy.window().its('store').invoke('getState').then((enState) => { const enMessages = enState.i18n.messages; // 验证英文翻译 translationPairs.forEach(({ key, en }) => { expect(enMessages).to.have.property(key, en); }); }); }); it('验证嵌套键名的正确解析', () => { mockI18nSuccess('zh'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'zh-CN', writable: false }); }); loginPage.visit(); cy.wait('@getI18nZHSuccess'); cy.window().its('store').invoke('getState').then((state) => { const messages = state.i18n.messages; // 验证多层嵌套的键名 expect(messages).to.have.property('worklist.operationPanel', '操作面板'); expect(messages).to.have.property('register.basicInfoPanel', '基本信息表单区域'); expect(messages).to.have.property('register.protocolListPanel', '待选择协议列表区域'); expect(messages).to.have.property('register.selectedProtocolListPanel', '已选择协议列表区域'); // 验证表格相关的嵌套键名 expect(messages).to.have.property('worklistTable.patientId', '患者编号'); expect(messages).to.have.property('worklistTable.name', '患者姓名'); expect(messages).to.have.property('worklistTable.birthDate', '出生日期'); expect(messages).to.have.property('worklistTable.gender', '性别'); // 验证表单字段的嵌套键名 expect(messages).to.have.property('register.patientId', '患者编号'); expect(messages).to.have.property('register.patientName', '患者姓名'); expect(messages).to.have.property('register.gender.male', '男'); expect(messages).to.have.property('register.gender.female', '女'); }); }); it('验证特殊字符和格式的处理', () => { // 创建包含特殊字符的mock数据 cy.intercept('GET', '/dr/api/v1/pub/trans/zh/zh.js', (req) => { req.reply({ statusCode: 200, body: { 'special.chars': '特殊字符:@#$%^&*()', 'unicode.emoji': '表情符号:😀 🎉 ✅ ❌', 'html.content': '粗体文本', 'quotes.single': "包含'单引号'的文本", 'quotes.double': '包含"双引号"的文本', 'newlines': '第一行\n第二行\n第三行', 'spaces': ' 前后有空格 ', 'numbers': '数字:123456789', 'mixed': '混合内容:123 ABC 中文 @#$ 😀' } }); }).as('getI18nZHSpecial'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'zh-CN', writable: false }); }); loginPage.visit(); cy.wait('@getI18nZHSpecial'); cy.window().its('store').invoke('getState').then((state) => { const messages = state.i18n.messages; // 验证特殊字符正确保存 expect(messages).to.have.property('special.chars', '特殊字符:@#$%^&*()'); expect(messages).to.have.property('unicode.emoji', '表情符号:😀 🎉 ✅ ❌'); expect(messages).to.have.property('html.content', '粗体文本'); expect(messages).to.have.property('quotes.single', "包含'单引号'的文本"); expect(messages).to.have.property('quotes.double', '包含"双引号"的文本'); expect(messages).to.have.property('newlines', '第一行\n第二行\n第三行'); expect(messages).to.have.property('spaces', ' 前后有空格 '); expect(messages).to.have.property('numbers', '数字:123456789'); expect(messages).to.have.property('mixed', '混合内容:123 ABC 中文 @#$ 😀'); }); }); it('验证翻译内容的完整性', () => { mockI18nSuccess('en'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'en-US', writable: false }); }); loginPage.visit(); cy.wait('@getI18nENSuccess'); cy.window().its('store').invoke('getState').then((state) => { const messages = state.i18n.messages; // 验证必要的翻译键都存在 const requiredKeys = [ 'greeting', 'name', 'patient', 'register', 'worklist', 'register.patientId', 'register.patientName', 'register.gender', 'register.gender.male', 'register.gender.female', 'worklistTable.patientId', 'worklistTable.name' ]; requiredKeys.forEach(key => { expect(messages).to.have.property(key); expect(messages[key]).to.be.a('string'); expect(messages[key]).to.not.be.empty; }); // 验证翻译内容不包含占位符或错误标记 Object.values(messages).forEach((value: any) => { expect(value).to.not.include('TODO'); expect(value).to.not.include('FIXME'); expect(value).to.not.include('{{'); expect(value).to.not.include('}}'); expect(value).to.not.include('[MISSING]'); }); }); }); it('验证翻译内容的一致性', () => { // 验证相同概念在不同上下文中的翻译一致性 mockI18nSuccess('zh'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'zh-CN', writable: false }); }); loginPage.visit(); cy.wait('@getI18nZHSuccess'); cy.window().its('store').invoke('getState').then((state) => { const messages = state.i18n.messages; // 验证"患者"相关翻译的一致性 expect(messages['register.patientId']).to.include('患者'); expect(messages['register.patientName']).to.include('患者'); expect(messages['worklistTable.patientId']).to.include('患者'); expect(messages['worklistTable.name']).to.include('患者'); // 验证性别翻译的一致性 expect(messages['register.gender.male']).to.equal('男'); expect(messages['register.gender.female']).to.equal('女'); }); }); it('验证翻译内容的长度和格式', () => { mockI18nSuccess('en'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'en-US', writable: false }); }); loginPage.visit(); cy.wait('@getI18nENSuccess'); cy.window().its('store').invoke('getState').then((state) => { const messages = state.i18n.messages; // 验证翻译内容的合理长度 Object.entries(messages).forEach(([key, value]: [string, any]) => { // 翻译内容不应该过长(假设最长不超过200字符) expect(value.length).to.be.lessThan(200); // 翻译内容不应该为空 expect(value.trim()).to.not.be.empty; // 验证特定键的格式 if (key.includes('placeholder')) { // placeholder应该以适当的提示开始 expect(value).to.match(/^(Enter|Please|Input)/i); } if (key.includes('button') || key === 'register' || key === 'print') { // 按钮文本应该是动词或动作词 expect(value).to.not.include('.'); expect(value.length).to.be.lessThan(50); } }); }); }); it('验证动态内容的翻译支持', () => { // 测试包含变量占位符的翻译(如果有的话) cy.intercept('GET', '/dr/api/v1/pub/trans/zh/zh.js', (req) => { req.reply({ statusCode: 200, body: { 'dynamic.welcome': '欢迎,{name}!', 'dynamic.count': '共有 {count} 个项目', 'dynamic.date': '日期:{date}', 'validation.required': '{field} 是必填项', 'validation.minLength': '{field} 至少需要 {min} 个字符' } }); }).as('getI18nZHDynamic'); cy.window().then((win) => { Object.defineProperty(win.navigator, 'language', { value: 'zh-CN', writable: false }); }); loginPage.visit(); cy.wait('@getI18nZHDynamic'); cy.window().its('store').invoke('getState').then((state) => { const messages = state.i18n.messages; // 验证动态内容的占位符格式正确 expect(messages).to.have.property('dynamic.welcome', '欢迎,{name}!'); expect(messages).to.have.property('dynamic.count', '共有 {count} 个项目'); expect(messages).to.have.property('dynamic.date', '日期:{date}'); expect(messages).to.have.property('validation.required', '{field} 是必填项'); expect(messages).to.have.property('validation.minLength', '{field} 至少需要 {min} 个字符'); // 验证占位符格式一致性 Object.values(messages).forEach((value: any) => { if (value.includes('{')) { // 确保占位符格式正确:{变量名} const placeholders = value.match(/\{[^}]+\}/g); if (placeholders) { placeholders.forEach((placeholder: string) => { expect(placeholder).to.match(/^\{[a-zA-Z][a-zA-Z0-9]*\}$/); }); } } }); }); }); });