123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- import { mockI18nTimeout, 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请求超时时正确处理', () => {
- mockI18nTimeout('zh');
-
- cy.window().then((win) => {
- Object.defineProperty(win.navigator, 'language', {
- value: 'zh-CN',
- writable: false
- });
- });
-
- loginPage.visit();
-
- // 验证加载状态显示
- cy.contains('加载多语言资源中...').should('be.visible');
-
- // 等待超时请求(这里我们不会真的等30秒,而是验证请求被发起)
- cy.wait('@getI18nZHTimeout', { timeout: 5000 }).then((interception) => {
- // 验证请求确实被发起
- expect(interception.request.url).to.include('/dr/api/v1/pub/trans/zh/zh.js');
- });
-
- // 由于实际测试中不会等待30秒,我们模拟超时后的状态
- // 在真实场景中,这会触发错误处理
- });
- it('模拟真实超时场景的错误处理', () => {
- // 设置一个较短的延迟来模拟超时,然后返回错误
- cy.intercept('GET', '/dr/api/v1/pub/trans/en/en.js', (req) => {
- // 模拟网络超时错误
- req.reply({
- statusCode: 408, // Request Timeout
- body: {
- message: 'Request Timeout',
- error: 'The request timed out'
- }
- });
- }).as('getI18nENTimeoutError');
-
- cy.window().then((win) => {
- Object.defineProperty(win.navigator, 'language', {
- value: 'en-US',
- writable: false
- });
- });
-
- loginPage.visit();
-
- cy.wait('@getI18nENTimeoutError');
-
- // 验证超时错误的处理
- 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('验证超时后重新加载的成功恢复', () => {
- // 首先模拟超时错误
- cy.intercept('GET', '/dr/api/v1/pub/trans/zh/zh.js', (req) => {
- req.reply({
- statusCode: 408,
- body: { message: 'Request Timeout' }
- });
- }).as('getI18nZHTimeoutFirst');
-
- cy.window().then((win) => {
- Object.defineProperty(win.navigator, 'language', {
- value: 'zh-CN',
- writable: false
- });
- });
-
- loginPage.visit();
-
- cy.wait('@getI18nZHTimeoutFirst');
-
- // 验证超时错误显示
- cy.contains('多语言资源加载失败').should('be.visible');
- cy.contains('重新加载').should('be.visible');
-
- // 设置成功的mock用于重新加载
- cy.intercept('GET', '/dr/api/v1/pub/trans/zh/zh.js', (req) => {
- req.reply({
- statusCode: 200,
- body: {
- greeting: '你好,世界!',
- patient: '患者管理',
- register: '注册'
- }
- });
- }).as('getI18nZHSuccess');
-
- // 点击重新加载
- cy.contains('重新加载').click();
-
- cy.wait('@getI18nZHSuccess');
-
- // 验证成功恢复
- cy.contains('多语言资源加载失败').should('not.exist');
- cy.get('body').should('contain', '患者管理');
-
- // 验证Redux状态恢复正常
- cy.window().its('store').invoke('getState').then((state) => {
- expect(state.i18n.loading).to.be.false;
- expect(state.i18n.error).to.be.null;
- expect(state.i18n.currentLocale).to.equal('zh');
- expect(state.i18n.messages).to.have.property('patient', '患者管理');
- });
- });
- it('验证慢网络环境下的用户体验', () => {
- // 模拟慢网络,但不超时
- cy.intercept('GET', '/dr/api/v1/pub/trans/en/en.js', (req) => {
- req.reply({
- delay: 3000, // 3秒延迟,模拟慢网络
- statusCode: 200,
- body: {
- greeting: 'Hello, world!',
- patient: 'Patient Management'
- }
- });
- }).as('getI18nENSlow');
-
- cy.window().then((win) => {
- Object.defineProperty(win.navigator, 'language', {
- value: 'en-US',
- writable: false
- });
- });
-
- loginPage.visit();
-
- // 验证加载状态持续显示
- cy.contains('加载多语言资源中...').should('be.visible');
-
- // 验证加载状态的样式
- 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.wait('@getI18nENSlow');
-
- // 验证最终成功加载
- cy.contains('加载多语言资源中...').should('not.exist');
- cy.get('body').should('contain', 'Patient Management');
- });
- it('验证多次超时重试的行为', () => {
- let retryCount = 0;
-
- // 设置动态mock,前两次超时,第三次成功
- cy.intercept('GET', '/dr/api/v1/pub/trans/zh/zh.js', (req) => {
- retryCount++;
- if (retryCount <= 2) {
- req.reply({
- statusCode: 408,
- body: { message: 'Request Timeout' }
- });
- } else {
- req.reply({
- statusCode: 200,
- body: {
- greeting: '你好,世界!',
- patient: '患者管理'
- }
- });
- }
- }).as('getI18nZHRetry');
-
- cy.window().then((win) => {
- Object.defineProperty(win.navigator, 'language', {
- value: 'zh-CN',
- writable: false
- });
- });
-
- loginPage.visit();
-
- // 第一次超时
- cy.wait('@getI18nZHRetry');
- cy.contains('多语言资源加载失败').should('be.visible');
-
- // 第一次重试,仍然超时
- cy.contains('重新加载').click();
- cy.wait('@getI18nZHRetry');
- cy.contains('多语言资源加载失败').should('be.visible');
-
- // 第二次重试,成功
- cy.contains('重新加载').click();
- cy.wait('@getI18nZHRetry');
-
- // 验证最终成功
- cy.contains('多语言资源加载失败').should('not.exist');
- cy.get('body').should('contain', '患者管理');
- });
- it('验证超时错误的详细信息显示', () => {
- cy.intercept('GET', '/dr/api/v1/pub/trans/en/en.js', (req) => {
- req.reply({
- statusCode: 408,
- body: {
- message: 'Request Timeout',
- error: 'The server did not respond within the expected time',
- code: 'TIMEOUT_ERROR'
- }
- });
- }).as('getI18nENTimeoutDetail');
-
- cy.window().then((win) => {
- Object.defineProperty(win.navigator, 'language', {
- value: 'en-US',
- writable: false
- });
- });
-
- loginPage.visit();
-
- cy.wait('@getI18nENTimeoutDetail');
-
- // 验证错误信息显示
- 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.error).to.include('Failed to load i18n messages');
- });
- });
- it('验证超时场景下其他功能不受影响', () => {
- cy.intercept('GET', '/dr/api/v1/pub/trans/zh/zh.js', (req) => {
- req.reply({
- statusCode: 408,
- body: { message: 'Request Timeout' }
- });
- }).as('getI18nZHTimeoutIsolated');
-
- cy.window().then((win) => {
- Object.defineProperty(win.navigator, 'language', {
- value: 'zh-CN',
- writable: false
- });
- });
-
- loginPage.visit();
-
- cy.wait('@getI18nZHTimeoutIsolated');
-
- // 验证超时错误显示
- cy.contains('多语言资源加载失败').should('be.visible');
-
- // 验证页面基本结构仍然存在
- 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;
- expect(state.i18n.messages).to.deep.equal({});
- });
- });
- it('验证网络恢复后的自动重试机制', () => {
- // 注意:这个测试模拟的是用户手动重试,而不是自动重试
- // 因为我们的实现中没有自动重试机制
-
- cy.intercept('GET', '/dr/api/v1/pub/trans/en/en.js', (req) => {
- req.reply({
- statusCode: 408,
- body: { message: 'Request Timeout' }
- });
- }).as('getI18nENNetworkDown');
-
- cy.window().then((win) => {
- Object.defineProperty(win.navigator, 'language', {
- value: 'en-US',
- writable: false
- });
- });
-
- loginPage.visit();
-
- cy.wait('@getI18nENNetworkDown');
-
- // 验证网络问题时的错误显示
- cy.contains('多语言资源加载失败').should('be.visible');
- cy.contains('重新加载').should('be.visible');
-
- // 模拟网络恢复
- cy.intercept('GET', '/dr/api/v1/pub/trans/en/en.js', (req) => {
- req.reply({
- statusCode: 200,
- body: {
- greeting: 'Hello, world!',
- patient: 'Patient Management'
- }
- });
- }).as('getI18nENNetworkUp');
-
- // 用户手动重试
- cy.contains('重新加载').click();
-
- cy.wait('@getI18nENNetworkUp');
-
- // 验证网络恢复后成功加载
- cy.contains('多语言资源加载失败').should('not.exist');
- cy.get('body').should('contain', 'Patient Management');
- });
- });
|