如何使用玩笑来模拟window.navigator.language

时间:2018-10-18 07:09:35

标签: javascript reactjs testing jestjs

我正在尝试在jest单元测试中模拟浏览器中的window.navigator.language属性,以便可以测试页面上的内容使用的是正确的语言

我发现有人在网上使用此功能

Object.defineProperty(window.navigator, 'language', {value: 'es', configurable: true});

我已经将其设置在测试文件的顶部,并且可以在其中运行

但是,当我在单个测试中重新定义(并且人们设置为确保可配置性设置为true)时,它不会重新定义它,而只是使用旧值,有人知道肯定要更改它的方法吗?

beforeEach(() => {
    jest.clearAllMocks()
    Object.defineProperty(global.navigator, 'language', {value: 'es', configurable: true});
    wrapper = shallow(<Component {...props} />)
})

  it('should do thing 1', () => {
      Object.defineProperty(window.navigator, 'language', {value: 'de', configurable: true});
      expect(wrapper.state('currentLanguage')).toEqual('de')
    })

it('should do thing 2', () => {
  Object.defineProperty(window.navigator, 'language', {value: 'pt', configurable: true});
  expect(wrapper.state('currentLanguage')).toEqual('pt')
})

对于这些测试,并没有将语言更改为我设置的新语言,而是始终使用顶部的语言。

3 个答案:

答案 0 :(得分:2)

window.navigator and its properties是只读的,这就是为什么需要Object.defineProperty来设置window.navigator.language的原因。应该可以多次更改属性值。

问题在于该组件已在beforeEach中实例化,window.navigator.language的更改不会影响它。

手动使用Object.defineProperty来模拟属性将需要存储原始描述符并也手动对其进行恢复。可以使用jest.spyOn完成。 jest.clearAllMocks()对于手动间谍/嘲弄无济于事,对于Jest间谍来说可能不需要。

可能应该是:

let languageGetter;

beforeEach(() => {
  languageGetter = jest.spyOn(window.navigator, 'language', 'get')
})

it('should do thing 1', () => {
  languageGetter.mockReturnValue('de')
  wrapper = shallow(<Component {...props} />)
  expect(wrapper.state('currentLanguage')).toEqual('de')
})
...

答案 1 :(得分:2)

在 Estus Flask 的回答中添加一点,您还可以监视您的安装文件:

在 jest 配置文件中激活 setupFiles 功能:

setupFiles: ['./test/mock-data/globals.js']

然后在 globals.js 中监视 userAgent 或任何其他属性:

global.userAgent = jest.spyOn(navigator, 'userAgent', 'get');

最后在你的测试中模拟返回值:

describe('abc', () => {
  global.userAgent.mockReturnValue(
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4)\
           AppleWebKit/600.1.2 (KHTML, like Gecko)\
           Version/13.0.0 Safari/600.1.2'
  );
  test('123', async () => {
    const result = await fnThatCallsOrUseTheUserAgent();
    expect(result).toEqual('Something');
  });
});

答案 2 :(得分:0)

替代

jest 配置文件

setupFiles: ['./test/mock-data/globals.js']

globals.js

const navigator = { language: 'Chalcatongo Mixtec', ...anyOtherPropertiesYouNeed };

Object.defineProperty(window, 'navigator', {
   value: navigator,
   writable: true
});

然后你可以在你的个人测试设置中自由地改变