Search code examples
typescriptvue.jsunit-testingjestjsvue-i18n

How to make Vue i18n load translations from .json file in Unit Test?


Using vue-i18n (v8.25.0 with vue v2.6.14), until now I had all my translations in .ts files holding the JS objects:

import { LocaleMessages } from 'vue-i18n'

const translations: LocaleMessages = {
  en: {
    test: 'Test',
  },
}

export default translations

Now, in order to better manage the translations, I switched to using .json files for the translation objects and importing these json files in the code. So the en.json translation file is just

{
  "test": "Test"
}

and it is imported in a .ts file using

import { LocaleMessages } from 'vue-i18n'
import translation from './en.json'

const translations: LocaleMessages = {
  en: translation,
}

export default translations

Of course, I set "resolveJsonModule": true, in tsconfig.json to make the json-Import work.

This works when serving the application - so the translations are correctly loaded. But when executing unit tests using vue-cli-service test:unit, the translations are not loaded and the following warnings are logged: [vue-i18n] Cannot translate the value of keypath 'test'. Use the value of keypath as default.

This causes some unit tests to fail that assert that the English translated value is there. Until now, these tests ran successfully but since changing to json files, this no longer works.

I guess, somehow jest does not load the json imports correctly. Is there anything I need to adjust to make jest also load the json translation files in test runs (an "equivalent" to resolveJsonModule: true)?


Solution

  • By randomly trying out different stuff, I found a solution.

    I totally don't get it but here is what made it work:

    Using the default jest.config.js with the following contents

    module.exports = {
      preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel',
    }
    

    made the error appear (translations not being available in Unit Tests).

    But after adding the following two moduleFileExtensions, it suddenly worked again:

    module.exports = {
      preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel',
      moduleFileExtensions: [
        'js',
        'ts',
      ],
    }
    

    I totally don't get it since @vue/cli-plugin-unit-jest/presets/typescript-and-babel by itself includes @vue/cli-plugin-unit-jest/presets/typescript that defines

    moduleFileExtensions: ['ts', 'tsx'],
    

    and derives from @vue/cli-plugin-unit-jest/presets/default that defines

    moduleFileExtensions: [
        'js',
        'jsx',
        'json',
        // tell Jest to handle *.vue files
        'vue'
      ],
    

    (see here)

    But for whatever reason, adding the js and ts moduleFileExtensions explicitly to my own jest.config.js made it process json files again. It feels like a bug to me, though.