I'm new to vitest, and my project has only a few test files to try to learn from. I've looked for help in the online help and don't find any references to what I need. There's no reference to a setup function that I could see.
I have a function I want to test with vitest. It needs to be passed the translation function t which I get from useI18n().
I tried to insert a simple statement in the test module after the imports.
{ t, d, locale } = useI18n()
with multiple variations trying const and let and so on. Nothing worked.
I got an error that says that the statement needs to be in a setup function.
SyntaxError: Must be called at the top of a
setup function
I found a sample setup function in the project and tried to incorporate that. I finally got the syntax acceptable by using
const setupi18n = () => (
{ t, d, locale } = useI18n()
);
Then it seemed that I need to call that in a beforeEach function so I tried:
let t;
beforeEach(() => {
{ t } = setupi18n()
});
I get
Error: Parse failure: Unexpected token (24:10)
Contents of line 24: { t } = setupi18n()
where 24:10 is the "=".
What technique and syntax do I need to use to be able to extract t from useI18n in a test file?
Simple code file to test, date.strings.js:
const singular = (t) => ({
days: t("day"),
hours: t("hour"),
minutes: t("minute"),
seconds: t("second"),
});
const pluralize = (num, str, t) => (num === 1 ? `${num} ${singular(t)[str]}` : `${num} ${str}`);
My current attempt at date.strings.vitest.spec.js (trying tao's suggestions in comments):
import { describe, expect, it, vi } from "vitest";
import { useI18n } from "vue-i18n";
import * as Strings from "./date.strings";
// const setupi18n = () => (
// { t, d, locale } = useI18n();
// );
vi.mock("vue-i18n");
useI18n.mockReturnValue({
t: (tKey) => tKey,
});
describe("pluralize", () => {
let t;
beforeEach(() => {
{ t } = setupi18n()
});
it("strings", () => {
expect(Strings.pluralize(3, "days", t).toBe("3 days"));
expect(Strings.pluralize(1, "days", t).toBe("1 day"));
});
});
which gets me:
FAIL src/common/date.strings.vitest.spec.js [ src/common/date.strings.vitest.spec.js ]
Error: Parse failure: Unexpected token (19:10)
Contents of line 19: { t } = setupi18n()
❯ ssrTransform node_modules/vite/dist/node/chunks/dep-689425f3.js:48653:15
❯ doTransform node_modules/vite/dist/node/chunks/dep-689425f3.js:50065:17
Without the beforeEach block I am just told that t is undefined. The error message is also strange because it claims that the erroneous code is on line 19 when it is actually on line 17. Does the test runner reformat the code before it runs?
I may just give up and modify a Vue page to try outputting the strings, with the benefit of knowing how to access t in actual Vue code.
Defining a minimal test component (so we can get t
in its setup
and pass it to pluralize
) seems to do the trick:
import { mount } from '@vue/test-utils'
import { describe, expect, test } from 'vitest'
import { defineComponent } from 'vue'
import { pluralize } from './date.strings'
import { createI18n } from 'vue-i18n'
import { useI18n } from 'vue-i18n'
const i18n = createI18n({
legacy: false,
locale: 'en',
messages: {
en: {
day: 'day',
hour: 'hour',
minute: 'minute',
second: 'second'
}
}
})
const PluralizeComponent = defineComponent({
props: {
value: {
type: Number,
default: 0
},
unit: {
type: String,
default: ''
}
},
setup: () => ({
pluralize,
t: useI18n().t
}),
template: `
<div v-text="pluralize(value, unit, t)" />
`
})
/**
* @vitest-environment jsdom
*/
describe('date.strings', () => {
test.each([
[3, 'days', '3 days'],
[1, 'days', '1 day']
])('pluralizes', (value, unit, expected) => {
const wrapper = mount(PluralizeComponent, {
props: { value, unit },
global: {
plugins: [i18n]
}
})
expect(wrapper.text()).toBe(expected)
})
})
See it working1.
1 - To run tests, click the Codesandbox devtools icon in the left bar and then find Tasks > test
in the menu: