vue jest router wrong route

Viewed 618

I'm currently writing unit tests for our vue components. I have the problem that if a test resulted in a router $router.push, the router object in jest will still have the same route as wrapper.vm.$route.name that the test before resulted in.

I tried everything I could think of to reset it after each test, but without success. Maybe you have an idea. Here is my code:

import {
// @ts-ignore
createLocalVue, RouterLinkStub, mount, enableAutoDestroy,
} from '@vue/test-utils';
import VueRouter from 'vue-router';
import Vuex from 'vuex';
import Component from '../../../components/account/Password.vue';
import routes from '../../../router/index';
import CustomerModuleStore, { CustomerModule } from '../../../store/modules/CustomerModule';
import Constants from '../../../constants';

jest.mock('../../../store/modules/CustomerModule');

const localVue = createLocalVue();
localVue.use(Vuex);
localVue.use(VueRouter);

let customerModule: CustomerModuleStore;

enableAutoDestroy(afterEach);

describe('Password.vue', () => {
    const router = new VueRouter({
        routes: routes.options.routes,
    });

    function mountStore() {
        const store = new Vuex.Store({});
        customerModule = new CustomerModule({ store, name: 'customer' });
        customerModule.changePassword = jest.fn().mockImplementation(() => Promise.resolve());

        return mount(Component, {
            provide: {
                customerModule,
            },
            localVue,
            store,
            router,
            stubs: { 'router-link': RouterLinkStub },
            attachToDocument: true,
        });
    }

    describe('Test component initialisation', () => {
        let wrapper;

        beforeEach(() => {
            wrapper = mountStore();
        });

        it('is a Vue instance', () => {
            expect(wrapper.isVueInstance()).toBeTruthy();
        });

        it('should render with the router', () => {
            expect(wrapper.element).toBeDefined();
        });
    });

    it('redirects to correct route', async () => {
        const submitButton = wrapper.find({ ref: 'submitButton' });
        expect(submitButton.attributes().disabled).toBe('disabled');

        // method content excluded for readability (fills inputs and triggers change event)
        fillFormWithValidData(wrapper);

        await wrapper.vm.$nextTick();

        submitButton.trigger('click');

        await wrapper.vm.$nextTick();

        // this.$router.push({ name: 'Home' }); got executed in component
        expect(wrapper.vm.$route.name).toBe('Home');
    });

    describe('Test error response functionality', () => {
        let wrapper;

        beforeEach(() => {
            wrapper = mountStore();
        });

        test('button is enabled if all data is valid by default', async () => {
            const submitButton = wrapper.find({ ref: 'submitButton' });
            expect(submitButton.attributes().disabled).toBe('disabled');

            // method content excluded for readability (fills inputs and triggers change event)
            fillFormWithValidData(wrapper);

            await wrapper.vm.$nextTick();

            submitButton.trigger('click');

            await wrapper.vm.$nextTick();

            // this.$router.push({ name: 'Home' }); did not get executed in component
            // but test fails since $route.name is still 'Home'
            expect(wrapper.vm.$route.name).not.toBe('Home');
        });
    });
});
1 Answers

In order to run each test from the suit in clean environment you need to create wrapper and router before each test, and destroy wrapper after each test.

So instead of this:

beforeEach(() => {
  wrapper = mountStore();
});

You need this:

beforeEach(() => {
  const router = new VueRouter({
    mode: "abstract"
  });
  wrapper = mountStore(router);
});

And you pass your new router to mountStore function

Related