VueJS - Unit testing with vue-test-utils gives error - TypeError: _vm.$t is not a function
Asked Answered
F

5

25

Relatively new to Vuejs and testing its components. Using vue-test-utils and jest for testing. Getting following error test log

The .vue file consists of template, component and styling. Below is the part of the SignupLayout.vue that gets error -

<style lang="sass">
@import '../stylesheets/colors'
html[path="/signup"], html[path="/login"]
  height: 100%
  background-image: url("../assets/background.jpg")
  background-size: cover
  background-position: center
  background-repeat: no-repeat
  overflow: hidden

  #signup-layout
    #change-language-button
      .lang-menu
        color: $alto

</style>

Test File -

import Vue from 'vue';
import Vuex from 'vuex'
import SignupLayout from '../src/components/SignupLayout.vue';
import { mount, shallow, createLocalVue } from '@vue/test-utils';

const localVue = createLocalVue()

localVue.use(Vuex)

jest.resetModules()

describe('Signup.test.js', () => {
    let cmp
    let actions
    let store
    let getters
    let state

    beforeEach(() => {


        state = {
            email: '[email protected]'
        }
 
        getters = {
            CURRENT_USER_EMAIL: state => state.email
        }

        store = new Vuex.Store({
            getters
        })


    })

    it('has received ["Login"] as the title property', () => {
        cmp = shallow(SignupLayout, {
            store,
            localVue,
            propsData: {
                title: ['Login']
            },
            data: {
                email: '[email protected]'
            }
        })
        cmp.update()
        expect(cmp.vm.title).toEqual(['Login'])
    })


})

Confused as to what has $t got to do with sass. Any help would be appreciated. Stuck here for a while now. Let me know if more details needed. Thanks in advance

Fissionable answered 14/2, 2018 at 14:51 Comment(0)
T
9

The error isn't in the <style> tag because Jest will compile your Vue component and extract the JS code. So you can ignore the line error for now (I'm not sure how to fix it).

But based on your error message, the problem seems to be related to the use of vue i18n and you're missing it when declaring your Vue component in the test file. Try adding these lines to your test file:

import i18n from 'path-to-your-i18n-file'

// ...

cmp = shallow(SignupLayout, {
  store,
  localVue,
  propsData: {
      title: ['Login']
  },
  data: {
      email: '[email protected]'
  },
  i18n // <- add the i18n object here
})
Trumaine answered 14/2, 2018 at 17:2 Comment(0)
A
26
const $t = () => {}

shallow(Component, {
 mocks:{ $t }
})

This way you dont have to load the whole i18n library. You can even spy on the function with Sinon or jest.fn() if using Jest.

Accept answered 15/3, 2018 at 16:30 Comment(2)
+1 it works, thx. But can you clarify what are you doing exactly. Аs I understand you are makking $t an arrow functionArc
Creating a mock of $t as a plain function in the this context of the mounted test component.Accept
T
9

The error isn't in the <style> tag because Jest will compile your Vue component and extract the JS code. So you can ignore the line error for now (I'm not sure how to fix it).

But based on your error message, the problem seems to be related to the use of vue i18n and you're missing it when declaring your Vue component in the test file. Try adding these lines to your test file:

import i18n from 'path-to-your-i18n-file'

// ...

cmp = shallow(SignupLayout, {
  store,
  localVue,
  propsData: {
      title: ['Login']
  },
  data: {
      email: '[email protected]'
  },
  i18n // <- add the i18n object here
})
Trumaine answered 14/2, 2018 at 17:2 Comment(0)
P
4

Another way to mock the i18n library is mock it in a separate js file

import VueTestUtils from '@vue/test-utils';
VueTestUtils.config.mocks.$t = key => key;

and add it in Jest configuration

 "setupFiles": ["<rootDir>/setup.js"]

so if you have more components with resource imports you don't need to mock it separately.

Pretension answered 4/3, 2019 at 5:21 Comment(0)
G
1

Currently in Vue 3 you could try, helped in my case:

import { config } from '@vue/test-utils';

config.global.mocks.$t = phrase => phrase;

because

config structure at the moment

Gasholder answered 13/1, 2022 at 5:39 Comment(0)
P
0

You can also mock it globally as follow:

// jest.config.js
{
  // ...
  setupFiles: ['<rootDir>/__tests__/setup.ts'],
}

// __tests__/setup.ts
import Vue, { PluginObject } from 'vue';
import Vuetify from 'vuetify';

const i18nMockPlugin: PluginObject<Vue> = {
  // called by Vue.use(MyPlugin)
  install(Vue) {
    Vue.prototype.$t = function (key: string, _opts: any) {
      return key;
    };
  },
};

Vue.use(Vuetify);
Vue.use(i18nMockPlugin); // mock i18n

Porridge answered 31/1, 2023 at 9:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.