kazupon / vue-i18n

:globe_with_meridians: Internationalization plugin for Vue.js
https://kazupon.github.io/vue-i18n/
MIT License
7.28k stars 861 forks source link

How to properly mock/stub/plugin vue-i18n with Vitest, Vue3, Typescript ? #1630

Open cmcleese opened 1 year ago

cmcleese commented 1 year ago

Reporting a bug?

I have Vue 3 components that do not pass test and always fail with the error: TypeError: $setup.t is not a function

// component.vue

<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
const { t } = useI18n();

</script>

<template>
  <p>{{ t('my.text.here') }} </p>
</template>
// setup-file.ts

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

import { createI18n } from 'vue-i18n';
const i18n = createI18n({});
config.global.plugins = [i18n];
// vitest.config.ts
export default defineConfig({
  test: {
    setupFiles: 'test/vitest/setup-file.ts',
   }
});

Expected behavior

Defining the global plugin should work.

Even trying to manually mock t doesnt work:

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

import { createI18n } from 'vue-i18n';
const i18n = createI18n({});
const { t } = i18n.global;

config.global.mocks = {
  t: (key) => key,
//  t: t
};

Reproduction

I am using Quasar for rapid scaffolding but should not matter. Clone repo: https://github.com/cmcleese/quasar-vuei18n-vitest

Simply run in cmd: vitest

Test & component:

System Info

* win10x64

* "vue": "^3.0.0",
* "vue-i18n": "^9.2.2",
* "typescript": "^4.5.4",
* "@vue/test-utils": "^2.0.0",
* "vitest": "^0.15.0",
* "@vitest/ui": "^0.15.0"

Screenshot

No response

Additional context

No response

Validations

cmcleese commented 1 year ago

The results are always the same. Error:

FAIL  test/vitest/__tests__/MainComponent.test.ts > Main > renders the main component
TypeError: $setup.t is not a function
andredewaard commented 1 year ago

@cmcleese did you found a solution for this?

Edit: This seems to work for me, also for the vue-router composition api.

let router: Router
let i18n: I18n

beforeEach(async() => {
  i18n = createI18n({
    locale: 'en',
    fallbackLocale: 'en',
    legacy: false,
    messages
  })

  router = createRouter({
    history: createWebHistory(),
    routes: routes
  })

  router.push('/')
  await router.isReady()
})

describe('Testing login view', async () => {

  it.only('should render', () => {
    const wrapper = mount(LoginView, {
      global: {
        plugins: [i18n, router],
      }
    })
    wrapper.isVisible()
  })

})