0
votes

We are using vuejs, typescript, vuex and jest. We are currently using test-utils to mock the store.

But I cannot find out how to mock a call to this.$parent.$on

Here is one of our components (very simplified):

AnalysisList.ts:

import Component from 'vue-class-component'
import {Getter} from 'vuex-class'
import {UserVO} from '@/valueObjects/UserVO'
import {Vue} from 'vue-property-decorator'

@Component
export default class AnalysisList extends Vue {

    @Getter('getCurrentUser') private currentUser: UserVO

    private searchString = ''



    public mounted() {
        this.$parent.$on('resetAnalyses', this.reset)

    }

    public reset() {
        this.searchString = ''
    }

}

AnalysisList.vue:

<template lang="pug">
    text test
</template>

<script lang="ts" src="./AnalysisList.ts">
</script>

AnalysisList.spec.ts:

import {shallowMount} from '@vue/test-utils'
import AnalysisList from '@/components/analysis/AnalysisList'
import Vuex from 'vuex'
import {Vue} from 'vue-property-decorator'
import VueRouter from 'vue-router'

Vue.use(Vuex)
Vue.use(VueRouter)

describe('AnalysisList.vue', () => {
    const store = new Vuex.Store(    {
        modules: {
            user: {
                state: {currentUser: 'test'},
                getters: {
                    getCurrentUser: (state: any) => state.currentUser,
                },
            },
        },
    })
    it('minimum test', (done) => {
        const wrapper = shallowMount(AnalysisList, {store})
        done()
    })
})

When I run the test, I have the following error message, because $parent is not mocked:

  TypeError: Cannot read property '$on' of undefined
  at VueComponent.mounted (src/components/analysis/AnalysisList/AnalysisList.vue:73:20)
  at callHook (node_modules/vue/dist/vue.runtime.common.js:2919:21)
  at mountComponent (node_modules/vue/dist/vue.runtime.common.js:2800:5)
  at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.js:7997:10)
  at mount (node_modules/@vue/test-utils/dist/vue-test-utils.js:5381:8)
  at shallowMount (node_modules/@vue/test-utils/dist/vue-test-utils.js:5414:10)
  at Object.done (tests/unit/AnalysisList.spec.ts:20:53)

If I try to add a new property to shallowMount parameter:

    const wrapper = shallowMount(AnalysisList, {store, parent: {$on: ()=>{}}})

I obtain a type error:

TS2345: Argument of type 'VueConstructor<Vue>' is not assignable to parameter of type 'FunctionalComponentOptions<Record<string, any>, PropsDefinition<Record<string, any>>>'.   Property 'functional' is missing in type 'VueConstructor<Vue>'.

Do you have any clue to help me mock this.$parent.$on ? Thanks.

1

1 Answers

1
votes

I got the same issue with vue-test-utils and Jest (under the Vue, Vuex and Typescript environment)

For me, createLocalVue() of vue-test-utils library fixed the issue. This function creates a local copy of Vue to use when mounting the component. Installing plugins on this copy of Vue prevents polluting the original Vue copy. (https://vue-test-utils.vuejs.org/api/options.html#localvue)

Adding this to my test file fixed the issue:

const EventBus = new Vue();

const GlobalPlugins = {
  install(v) {
    // Event bus
    v.prototype.$bus = EventBus;
  },
};

// create a local instance of the global bus
const localVue = createLocalVue();
localVue.use(GlobalPlugins);

Hope this helps others, thanks :)