TypeError: _vm.t is not a function error in Jest Vue 2 - vue.js

I am using Vue 2 with vue-i18n-composable plugin for translations. I am getting below error in Jest test
[Vue warn]: Error in render: "TypeError: _vm.t is not a function"
found in
---> <Bilingual>
<Root>
console.error node_modules/vue/dist/vue.runtime.common.dev.js:1884
I tried everything on the internet. Nothing fixed this. Can you please help?
Below are the things what I've tried so far
1.
const $t = () => {}
const wrapper = shallowMount(Bilingual,{
mocks:{ $t }
})
expect(wrapper.exists()).toBe(true)
describe("Bilingual", () => {
it("Bilingual component exists", () => {
const wrapper = shallowMount(Bilingual, {
mocks: {
$t: (msg) => msg
}
})
expect(wrapper.exists()).toBe(true)
})
})
import VueTestUtils from '#vue/test-utils';
VueTestUtils.config.mocks.$t = key => key;
I am getting below error for the 3rd try
TypeError: Cannot read property 'config' of undefined
const i18n = createI18n({
messages: {
en: en,
dutch: dutch
},
fallbackLocale: variables.DEFAULT_LANGUAGE,
locale: variables.DEFAULT_LANGUAGE
})
describe("Bilingual", () => {
it("renders successfully", () => {
const wrapper = shallowMount(Bilingual,{
i18n
})
expect(wrapper.exists()).toBe(true)
})
})
Can you please help
Bilingual.vue component file
<template>
<div>
<div>
{{ t('SAVE', 'en') }}
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from '#vue/composition-api'
import { useI18n } from 'vue-i18n-composable'
export default defineComponent({
name: 'Bilingual',
setup() {
const { t } = useI18n()
return {
t
}
},
})
</script>
<style lang="scss" scoped></style>
main.ts
import { createI18n } from 'vue-i18n-composable'
const i18n = createI18n({
messages: {
en: en,
dutch: dutch
},
fallbackLocale: variables.DEFAULT_LANGUAGE,
locale: variables.DEFAULT_LANGUAGE
})
app.mount('#app')
const app = createApp({
// eslint-disable-next-line
render: (h: (arg0: VueConstructor<Vue>) => any) => h(App),
i18n,
router,
store
})

Related

TypeError: Cannot read property 'type' of null - testing vue component with async functions

I am testing a component ComponentA.spec.js but I am getting TypeError: Cannot read property 'type' of null. It works if I get rid of the await keyword in the getData() function in the ComponentA. I am mocking the getData api call in my test but still it doesn't work.
This is the full stack
TypeError: C:[Privacy]\unknown: Cannot read property 'type' of null
at assert (node_modules/#babel/types/lib/asserts/generated/index.js:284:112)
at Object.assertIdentifier (node_modules/#babel/types/lib/asserts/generated/index.js:373:3)
at new CatchEntry (node_modules/regenerator-transform/lib/leap.js:93:5)
at Emitter.Ep.explodeStatement (node_modules/regenerator-transform/lib/emit.js:535:36)
at node_modules/regenerator-transform/lib/emit.js:323:12
at Array.forEach (<anonymous>)
at Emitter.Ep.explodeStatement (node_modules/regenerator-transform/lib/emit.js:322:22)
at Emitter.Ep.explode (node_modules/regenerator-transform/lib/emit.js:280:40)
This is Component A that i am trying to create tests for
<template>
<div class="d-flex flex-row">
<component-b />
<component-c />
</div>
</template>
<script>
import ComponentB from './ComponentB';
import ComponentC from './ComponentC';
import { getData } from 'apis';
export default {
name: 'component-a',
components: {
ComponentB,
ComponentC,
},
async created() {
await this.getData();
},
methods: {
// This function is the culprit
async getData() {
try {
const response = await getData();
} catch {
//
}
},
},
};
</script>
This is my ComponentA.spec.js file
import Vuetify from 'vuetify';
import ComponentA from 'components/ComponentA';
import { createLocalVue, shallowMount, mount } from '#vue/test-utils';
jest.mock('shared/apis', () => {
const data = require('../fixedData/data.json');
return {
getData: jest.fn().mockResolvedValue(data),
};
});
const localVue = createLocalVue();
let vuetify;
function createShallowWrapper(options = {}) {
return shallowMount(ComponentA, {
localVue,
vuetify,
...options,
});
}
beforeEach(() => {
vuetify = new Vuetify();
});
describe('ComponentA', () => {
describe('component creation', () => {
test('testing', () => {
const wrapper = createShallowWrapper();
expect(wrapper).toMatchSnapshot();
});
});
});
Adding exception variable (e) to my catch in the getData function in ComponentA fixed it.

Jest : TypeError: Cannot read property 'variable' of undefined

I am testing though Jest on the Vue 2.x, nuxtjs and #nuxtjs/composition-api.
However, the state value in the components has undefined value when testing though jest
List.spec.js
import Vue from 'vue';
import Vuetify from 'vuetify';
import { createLocalVue, shallowMount } from '#vue/test-utils';
import List from '#/components/home/list.vue';
Vue.use(Vuetify);
describe('List.vue', () => {
const localVue = createLocalVue();
let vuetify;
const $t = () => {};
const localePath = () => {};
beforeEach(() => {
vuetify = new Vuetify();
localVue.use(vuetify);
});
const mockOrder = [
{
coardshare: {
cs_id: 123,
},
},
{
talkboard: {
cs_id: 123,
},
},
];
it('11111', () => {
const wrapper = shallowMount(List, {
localVue,
vuetify,
propsData: { data: mockOrder },
mocks: { $t, localePath },
data() {
return {
data: mockOrder,
};
},
});
expect(wrapper.html()).toMatchSnapshot();
const title = wrapper.find('.v-card__title > span');
expect(title.text()).toBe('Foobar');
});
});
List.vue
<template>
...
<div v-for="item in state.data.talkboard" :key="item.cs_id">
<ListItem :item="item"></ListItem>
</div>
...
</template>
<script>
import { reactive, onMounted, useContext } from '#nuxtjs/composition-api';
import axios from 'axios';
import Header from './header';
import ListItem from './list-item.vue';
export default {
name: 'ListHome',
components: {
Header,
ListItem,
},
setup() {
const state = reactive({
data: [],
});
const { store } = useContext();
const fatch = async () => {
....
};
onMounted(fatch);
return {
state,
fatch,
};
},
};
</script>
error message
TypeError: Cannot read property 'data' of undefined
I am testing though Jest on the Vue 2.x, nuxtjs and #nuxtjs/composition-api.
However, the state value in the components has undefined value when testing though jest
why error on this ?? because of composition API that define the state with reactive() function ??
In your test file maybe you can try something like this:
it('11111', () => {
const wrapper = shallowMount(List, {
localVue,
vuetify,
propsData: { data: mockOrder },
mocks: { $t, localePath },
data: () => {
return {
data: mockOrder,
};
},
});

How to call a namespaced Vuex action in Nuxt

I am building an app using NUXT js. I am also using the store module mode because using classic mode returned some depreciation issue.
The PROBLEM is I get [vuex] unknown mutation type: mobilenav/showmobilenav error in my console.
so below are my stores
store/index.js
export const state = () => ({
})
export const mutations = ({
})
export const actions = ({
})
export const getters = ({
})
store/mobilenav.js
export const state = () => ({
mobilenav: false
})
export const mutations = () => ({
showmobilenav(state) {
state.mobilenav = true;
},
hidemobilenav(state) {
state.mobilenav = false;
}
})
export const getters = () => ({
ismobilenavvisible(state) {
return state.dropdown;
}
})
the VUE file that calls the mutation
<template>
<div class="bb" #click="showsidenav">
<img src="~/assets/svg/burgerbar.svg" alt="" />
</div>
</template>
<script>
export default {
methods: {
showsidenav() {
this.$store.commit("mobilenav/showmobilenav");
console.log("sidenav shown");
},
},
}
</script>
<style scoped>
</style>
Here is a more detailed example on how to write it.
/store/modules/custom_module.js
const state = () => ({
test: 'default test'
})
const mutations = {
SET_TEST: (state, newName) => {
state.test = newName
},
}
const actions = {
actionSetTest({ commit }, newName) {
commit('SET_TEST', newName)
},
}
export const myCustomModule = {
namespaced: true,
state,
mutations,
actions,
}
/store/index.js
import { myCustomModule } from './modules/custom_module'
export default {
modules: {
'custom': myCustomModule,
},
}
/pages/test.vue
<template>
<div>
<button #click="actionSetTest('updated test')">Test the vuex action</button>
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
methods: {
...mapActions('custom', ['actionSetTest']),
}
</script>

Vue: Test utils vue composition - root.$route

Versions
Test utils
1.0.3
Vue
2.6.11
Vue router
3.20
Vue compsotion API
1.0.0-beta.8
I have some difficulties developing a component test because of root.$route.
In the component, I have a watch, which will be aware when the route changes, in order to change some variables of the component.
My component
<script>
export default {
setup ( _, { root }) {
// behavior
...
watch( () => root.$route,
({ query, meta }) => {
foo = 'bar';
}, {
immediate: true
});
}
};
</script>
My test
import { shallowMount, createLocalVue } from '#vue/test-utils';
import VueCompositionAPI from '#vue/composition-api';
import Component from '#/components/bundles/layout/Component';
import router from '#/router/';
const localVue = createLocalVue();
localVue.use( VueCompositionAPI );
localVue.use( router );
describe( 'Component', () => {
it( 'Insert', () => {
const wrapper = shallowMount( Component, {
mocks: {
$t: () => ({})
},
localVue,
router
});
console.log( wrapper.html() );
});
});
Error
TypeError: Cannot destructure property 'query' of 'undefined' as it is undefined.
I've tried to mock the router, but without effect.
I tried in the following ways:
1:
...
describe( 'Component', () => {
it( 'Insert', () => {
const wrapper = shallowMount( Component, {
mocks: {
$t: () => ({}),
$route: { query: '', meta: '' }
},
localVue,
router
});
console.log( wrapper.html() );
});
});
2:
import router from '#/router/';
jest.mock( '#/router/', () => ({
currentRoute: {
meta: {},
query: {}
},
push: jest.fn( () => Promise.resolve() )
}) );
Some help?

Unknown custom element: - did you register the component correctly? error on with <nuxt /> component in default.vue Jest

I'm trying to write tests for default.vue file which has the following code:
default.vue
<template>
<div>
<top-nav :class="isSticky ? 'fixed-top stickyAnimate' : ''" />
<main>
<nuxt />
</main>
<footer />
</div>
</template>
<script>
import TopNav from '../components/TopNav.vue';
import Footer from '../components/Footer.vue';
import StickyNavMixin from '../mixins/stickyNavMixin';
export default {
components: {
TopNav,
Footer,
},
mixins: [StickyNavMixin],
data() {
return {
loading: true,
};
},
mounted() {
if (!window.location.hash) {
this.loading = false;
}
},
};
</script>
then my test look like this
default.spec.js
import { createLocalVue, shallowMount } from '#vue/test-utils';
import BootstrapVue from 'bootstrap-vue';
import StickyNavMixin from '../mixins/stickyNavMixin';
import Default from '../layouts/default.vue';
import TopNav from '../components/TopNav.vue';
import Footer from '../components/Footer.vue';
const localVue = createLocalVue();
localVue.use(BootstrapVue);
localVue.mixin(StickyNavMixin);
describe('Default', () => {
let wrapper;
beforeEach(() => {
wrapper = shallowMount(Default, {
localVue,
});
});
test('is a Vue instance', () => {
expect(wrapper.isVueInstance()).toBeTruthy();
});
test('has navbar component', () => {
expect(wrapper.find(TopNav).exists()).toBe(true);
});
});
When I ran this test, I get error says:
[Vue warn]: Unknown custom element: - did you register the component correctly? For
recursive components, make sure to provide the "name" option.found in --->
Please guide me to a right direction. Thank you in advance!
I figured out how to get past that error. I had to just stub it out of the wrapper. You don't have to import Nuxt, just string 'nuxt' will replace it as a stubbed element in the wrapper:
describe('DefaultLayout', () => {
let wrapper;
afterEach(() => {
wrapper.destroy();
});
/** mount **/
test('is a Vue instance', () => {
wrapper = mount(DefaultLayout, {
localVue,
stubs: ['nuxt'],
});
expect(wrapper.isVueInstance()).toBeTruthy();
});
/** shallowMount **/
test('is a Vue instance', () => {
wrapper = shallowMount(DefaultLayout, {
localVue,
stubs: ['nuxt', 'top-nav', 'footer'],
});
expect(wrapper.isVueInstance()).toBeTruthy();
// expect(wrapper.html()).toBe('<div>'); => this is to debug see below for output
});
});
//DEBUG
"<div><top-nav-stub class=\"\"></top-nav-stub> <main><nuxt-stub></nuxt-stub> .
</main> <footer-stub></footer-stub></div>"