# Jest Common Usage Since JSTF (our frontend policy team) adds **SonarQube** for all FE projects recently. We have to get started with unit test for better code coverage in all projects. Any PR doesn't reach a goal of 60% coverage can't be merged.<br/> To reduce the pain and writing unit test in an efficient way, here are some common cases for `jest` and `vue-test-util`。 ### Jest Q: How to mock **window**?<br/> A: ```javascript // TODO ``` Q: If there are multiple test cases in a simular pattern, how do you test all of them?<br/> A: ```javascript const testCases = [ { input: 1, output: 1 }, { input: 2, output: 2 } ] it.each(testCases)('should return $output if input is $input', ({ input, output }) => { const fn = v => v expect(fn(input)).toBe(output) }) ``` Q: How to end up all promises in jest?<br/> A: ```javascript import flushPromises from 'flush-promises' it('should end all promises', async () => { anAsyncFunction() await flushPromises() // ... }) ``` Q: How to mock third party **ES Module**?<br/> A: ```javascript jest.mock('lodash-es', () => ({ uniqueId: jest.fn((prefix) => { let counter = 0 const getId = () => { counter++ return prefix + counter } return getId() }) })) ``` ### Vue Test Util Q: How to mock **router**?<br/> A: ```javascript // If your code has some router methods such as pop and replace, mock it with jest.fn is fine. const mockRouter = { push: jest.fn(), } const localVue = createLocalVue() const wrapper = shallowMount(Foo, { localVue, global: { mocks: { $router: mockRouter, }, }, }) ``` Q: How to mock **route**?<br/> A: ```javascript const mockRoute = { path: '/foo', } const localVue = createLocalVue() const wrapper = shallowMount(Foo, { localVue, global: { mocks: { $route: mockRoute, }, }, }) ``` Q: How to mock **next** function in **beforeRouteLeave**?<br/> A: Use a `jest.fn` to trigger call for `wrapper.vm`. ```javascript it('should trigger next function in some condition', () => { // ... const next = jest.fn() wrapper.beforeRouteLeave.call(wrapper.vm, to, from, next) expect(next).toHaveBeenCalledTimes(1) }) ``` Q: How to get/set **data** in **wrapper**?<br/> A: ```javascript it('should set hello to world', async () => { // set wrapper.setData({ hello: 'world', }) await wrapper.vm.$nextTick() // get expect(wrapper.vm.hello).toBe('world') }) ``` Q: How to mock `vue-i18n`?<br/> A: Add a locale object if you access the i18n object directly, and add `$t` for mocks for component to render i18n keys. ```javascript const localVue = createLocalVue() // If your code is invloved with i18n instance, mock it with fake object jest.mock('@/locales', () => ({ const locale = 'zh-CN' return { t: jest.fn(), locale, messages: { [locale]: {} } } })) const wrapper = shallowMount(Foo, { localVue, global: { mocks: { $t: jest.fn((key) => key), }, }, }) ``` Q: How to interfere with component methods?<br/> A: Use `spyOn` for specific instance methods before `shallowMount`. ```javascript it('should return "You\'re god damn right!"', () => { jest.spyOn(Foo.methods, 'youAreGodDamnRight').mockImplementation(() => 'You\'re god damn right!') const wrapper = shallowMount(Foo, { // ... }) expect(wrapper.vm.youAreGodDamnRight()).toBe('You\'re god damn right!') }) ``` Q: How to test a **dialog** called by **plugin method**?<br/> A: Because it's general to see that a dialog called by plugin method is a **Vue** instance seperated with our **App** instance, to access the instance, there is a hacky method. Take **bootstrap-vue** as example, we should realize what **DOM structure** the dialog is by reading the third party **repo** source code, get `__vue__` property in the dialog **DOM**, and then use `createWrapper` method to generate a new **wrapper**。 ```javascript const localVue = createLocalVue() localVue.use(BootstrapVue) it('should show bootstrap modal and interact with it', async () => { // ... // create modal wrapper in a hacky way // bootstrap vue modal spec: https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/modal/modal.spec.js const modalElement = document.querySelector('div.modal') const modal = createWrapper(modalElement.__vue__) expect(modal.exists()).toBeTruthy() const button = modal.find('button.btn-primary') await button.trigger('click') // ... }) ``` ###### tags: `Work` `JavaScript` `Jest` `Vue` `Vue2` `Unit Test`