123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- 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': '<strong>粗体文本</strong>',
- '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', '<strong>粗体文本</strong>');
- 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]*\}$/);
- });
- }
- }
- });
- });
- });
- });
|