Best way to mock/stub vue-i18n translations in a vue3 component when using Vitest

Viewed 1037

I have started to replace Jest with Vitest for my unit test library in my Vue 3 App.

I am trying to write unit test for a component that uses the vue-i18n library to translate text within it but when I try to mount this component in my test file, it fails with the error:

ReferenceError: t is not defined

What is the proper way to stub/mock t from import { useI18n } from 'vue-i18n' when writing tests using the vitest library?

Note since upgrading from Vue2 to Vue3 this does not work:

const wrapper = shallowMount(MyComponent, {
  global: {
    mocks: {
      $t: () => {}
    }
  }
})

Here is a list of some notable package versions:

"vue": "^3.2.31",
"vue-i18n": "^9.2.0-beta.14",
"vite": "^2.9.0",
"vitest": "^0.10.2"

Thanks!

3 Answers
import { createI18n } from 'vue-i18n';

describe('xxx', () => {
   it('yyy', () => {
      const i18n = createI18n({
         messages: {
            gb: {},
            nl: {},
            ...
         }
      });
      
      const wrapper = mount(YourComponent, {
         global: {
            plugins: [i18n]
         }
      });
   }
})

I suppose you want to mock this globally, no need to put same code in every test suite.

// vitest.config.ts
import { mergeConfig } from 'vite';
import { defineConfig } from 'vitest/config';
import viteConfig from './vite.config';

export default defineConfig(
    mergeConfig(viteConfig, { // extending app vite config
        test: {
            setupFiles: ['tests/unit.setup.ts'],
            environment: 'jsdom',
        }
    })
);
// tests/unit.setup.ts
import { config } from "@vue/test-utils"

config.global.mocks = {
  $t: tKey => tKey; // just return translation key
};

Panos Vakalopoulos’s answer worked for me.

And the code could be run globally.

See https://test-utils.vuejs.org/migration/#no-more-createlocalvue

// vite.config.ts
export default defineConfig(
    // add config for test
    test: {
        environment: 'jsdom',
        setupFiles: 'vitest.setup.ts',
    }
);

// vitest.setup.ts'
import { config } from '@vue/test-utils'
import { createI18n } from 'vue-i18n'
const i18n = createI18n()
config.global.plugins = [i18n]
// YourComponent.vue
<div id="app">
    <p>{{ t("message.hello") }}</p>
</div>

<script lang="ts" setup>
    import { useI18n } from 'vue-i18n'
    const { t } = useI18n()
</script>
// component_test.ts
describe('xxx', () => {
    it('yyy', () => {
        const wrapper = mount(YourComponent);
    }
})

Note that if you use global config as $t, Luckylooke's answer would work.

// YourComponent.vue
<div id="app">
    <p>{{ $t("message.hello") }}</p>
</div>
// tests/unit.setup.ts
import { config } from "@vue/test-utils"

config.global.mocks = {
    $t: tKey => tKey; // just return translation key
};
Related