I am using Vue JS with @vue/test-utils and jest. For my tests I am calling:
let localVue = createLocalVue();
vueMount(MyComponent, { localVue: localVue, options });
The problem is, I am referencing libraries which does stuff like this:
import Vue from 'vue'
import Msal from 'vue-msal'
//...
Vue.use(Msal, {...});
The Vue.use() registers some global stuff on the prototype, etc. For testing purposes, I need this to start fresh each test. The only thing I could think of is to use mockImplementation() with jest on the Vue object. But I am not quite sure how I could accomplish that, if at all possible.
Is there any way to do this? Thanks!
It took me a while, but here is how I solved this...
let setupComplete = false;
let setupFailure = false;
let testContext = {};
function resetTestContext() {
Object.keys(testContext).forEach(function(key) { delete testContext[key]; });
}
function createTestContext(configureTestContext) {
beforeEach(() => {
jest.isolateModules(() => {
setupFailure = true;
jest.unmock('vue');
resetTestContext();
testContext.vueTestUtils = require('@vue/test-utils');
testContext.vue = testContext.vueTestUtils.createLocalVue();
jest.doMock('vue', () => testContext.vue);
testContext.vuetify = require('vuetify');
testContext.vue.use(testContext.vuetify);
testContext.vuetifyInstance = new testContext.vuetify();
if (configureTestContext) {
configureTestContext(testContext);
}
setupComplete = true;
setupFailure = false;
});
});
afterEach(() => {
setupComplete = false;
resetTestContext();
jest.resetModules();
setupFailure = false;
});
return testContext;
},
What made this possible was the jest.isolateModules() method. With this approach, Vue and it's prototype, and also Vuetify, are completely recreated and brand new with each test case.
For it to work, the test spec and the library containing the utility above may not 'import' Vue or any module which depends on Vue. Instead, it needs to be required in the configureTestContext() function or in the test case itself.
My test specs look like this:
import createTestContext from '@/scripts/createTestContext'
describe('sample', () => {
const testContext = createTestContext(function configureTestContext(testContext)
{
testContext.vueDependency = require('@/scripts/vueDependency').default;
});
test('demo', () => {
// I added a helper to more easily do this in the test context...
const sample = testContext.vueTestUtils.mount(require('@/components/Sample').default, {
localVue: testContext.vue,
vuetify: testContext.vuetifyInstance
});
expect(testContext.vueDependency.doSomething(sample)).toBe(true);
expect(sample.isVueInstance()).toBeTruthy();
});
});