vue-i18n
vue-i18n copied to clipboard
How to properly mock/stub/plugin vue-i18n with Vitest, Vue3, Typescript ?
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:
-
test/vitest/__tests__/NotifyComponent.test.ts
-
test/vitest/__tests__/demo/NotifyComponent.vue
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
- [X] Read the Contributing Guidelines
- [X] Read the Documentation
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Check that this is a concrete bug. For Q&A open a GitHub Discussion
- [X] The provided reproduction is a minimal reproducible example of the bug.
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
@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()
})
})