I have use the jest mock
jest.mock('i18next', () => ({
use: () => this,
init: () => { },
t: k => k
}));
Didn't resolve the issue. I am getting TypeError: Cannot read property 'use' of undefined
But if I use require module instead import for i18next will be fine
const i18next = require('i18next'); // works
import i18next from 'i18next'; // will fail jest test with TypeError: Cannot read property 'use' of undefined
And tried to google the solution and cannot find a solution works for me.
import i18next from 'i18next'
import languageDetector from "i18next-browser-languagedetector";
import { languageData } from './language.resources';
export class Translation {
private static _instance: Translation;
isInitialized : boolean = false;
private resources = languageData;
private detectOptions = {
order: ['navigator', 'localStorage', 'sessionStorage', 'cookie', 'htmlTag', 'path', 'subdomain'],
lookupLocalStorage: 'lng'
}
constructor() {
}
setLanguageResources(data) {
this.resources = data;
}
initi18n() {
i18next
.use(languageDetector)
.init({
resources: this.resources,
fallbackLng: 'en-US',
detection: this.detectOptions,
debug: true,
returnEmptyString: false,
ns: [
'translation',
'validation',
'error'
],
});
this.isInitialized = true;
}
get i18nInstance() {
return i18next;
}
translate(key : string) {
return i18next.t(key);
}
static getInstance() {
if(this._instance) {
return this._instance;
}
this._instance = new Translation();
this._instance.initi18n();
return this._instance;
}
}
Test spec file
import * as i18next from 'i18next';
import { Translation } from './translation.utility';
describe('Translation', () => {
jest.mock('i18next', () => ({
use: () => this,
init: () => { },
t: k => k
}));
it('should create an instance', () => {
expect(new Translation()).toBeTruthy();
});
it('should test setResource', () => {
let translate = new Translation();
translate.setLanguageResources({});
expect(translate["resources"]).toEqual({})
});
it('should test new Translation singleton object', () => {
let translate = new Translation();
translate.setLanguageResources({});
expect(translate["resources"]).toEqual({})
translate = Translation.getInstance();
expect(translate.isInitialized).toEqual(true);
});
it('should test singleton', () => {
let translate = Translation.getInstance();
translate.setLanguageResources({});
expect(translate.isInitialized).toEqual(false);
expect(translate["resources"]).toEqual({})
});
xit('should test init i18next', () => {
let translate = new Translation();
translate.i18nInstance;
expect(translate.translate("")).toBeDefined();
});
})
jest.config.js file
module.exports = {
name: "translation",
preset: "../../jest.config.js",
setupFilesAfterEnv: ["<rootDir>/src/test-setup.ts"],
globals: {
"ts-jest": {
tsConfig: "<rootDir>/tsconfig.spec.json",
stringifyContentPathRegex: "\\.(html|svg)$",
astTransformers: [
"jest-preset-angular/build/InlineFilesTransformer",
"jest-preset-angular/build/StripStylesTransformer",
],
},
},
coverageDirectory: "../../coverage/libs/translation",
snapshotSerializers: [
"jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js",
"jest-preset-angular/build/AngularSnapshotSerializer.js",
"jest-preset-angular/build/HTMLCommentSerializer.js",
],
};
tsconfig.lib.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"target": "es2015",
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"module": "commonjs",
"types": [],
"lib": ["dom", "es2018"]
},
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"enableResourceInlining": true
},
"exclude": ["src/test-setup.ts", "**/*.spec.ts"],
"include": ["**/*.ts"]
}
I was able to fix a similar issue by changing how I mocked i18n
.
Here's what I used:
jest.mock('../../src/i18n', () => ({
__esModule: true,
use: () => {},
init: () => {},
default: {
t: (k) => k,
},
}));
In my case, I was importing i18next
within my src/i18n.ts
file, so that's why I mocked it with that string. You may be able to use
i18next
instead of '../../src/i18n'
.
Hope this helps.