✅(i18n) install jest and add tests
We install Jest to test our i18n package. We tests: - the extraction of the translations on the Desk app fo crowdin - the formatings of the translations from crowdin to the app - we check that all the translations are present in the app We connect the tests to the CI.
This commit is contained in:
104
src/frontend/packages/i18n/__tests__/i18n.test.ts
Normal file
104
src/frontend/packages/i18n/__tests__/i18n.test.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { execSync } from 'child_process';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
describe('integration testing on i18n package', () => {
|
||||
afterAll(() => {
|
||||
fs.rmSync('./locales/tests', { recursive: true, force: true });
|
||||
});
|
||||
|
||||
test('cmd extract-translation:desk', () => {
|
||||
// To be sure the file is not here
|
||||
fs.rmSync('./locales/desk/translations-crowdin.json', {
|
||||
recursive: true,
|
||||
force: true,
|
||||
});
|
||||
expect(
|
||||
fs.existsSync('./locales/desk/translations-crowdin.json'),
|
||||
).toBeFalsy();
|
||||
|
||||
// Generate the file
|
||||
execSync('yarn extract-translation:desk');
|
||||
expect(
|
||||
fs.existsSync('./locales/desk/translations-crowdin.json'),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test('cmd format-deploy', () => {
|
||||
// To be sure the tests folder is not here
|
||||
fs.rmSync('./locales/tests', { recursive: true, force: true });
|
||||
expect(fs.existsSync('./locales/tests')).toBeFalsy();
|
||||
|
||||
// Generate english json file
|
||||
fs.mkdirSync('./locales/tests/en/', { recursive: true });
|
||||
fs.writeFileSync(
|
||||
'./locales/tests/en/translations.json',
|
||||
JSON.stringify({ test: { message: 'My test' } }),
|
||||
'utf8',
|
||||
);
|
||||
expect(fs.existsSync('./locales/tests/en/translations.json')).toBeTruthy();
|
||||
|
||||
fs.mkdirSync('./locales/tests/fr/', { recursive: true });
|
||||
fs.writeFileSync(
|
||||
'./locales/tests/fr/translations.json',
|
||||
JSON.stringify({ test: { message: 'Mon test' } }),
|
||||
'utf8',
|
||||
);
|
||||
expect(fs.existsSync('./locales/tests/fr/translations.json')).toBeTruthy();
|
||||
|
||||
// Execute format-deploy command
|
||||
const output = './locales/tests/translations.json';
|
||||
execSync(`node ./format-deploy.mjs --app=tests --output=${output}`);
|
||||
const json = JSON.parse(fs.readFileSync(output, 'utf8'));
|
||||
expect(json).toEqual({
|
||||
en: {
|
||||
translation: { test: 'My test' },
|
||||
},
|
||||
fr: {
|
||||
translation: { test: 'Mon test' },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('cmd format-deploy throws an error when translation file is not found', () => {
|
||||
// To be sure the tests folder is not here
|
||||
fs.rmSync('./locales/tests', { recursive: true, force: true });
|
||||
expect(fs.existsSync('./locales/tests')).toBeFalsy();
|
||||
|
||||
// Generate english json file
|
||||
fs.mkdirSync('./locales/tests/en/', { recursive: true });
|
||||
|
||||
// Execute format-deploy command
|
||||
const output = './locales/tests/translations.json';
|
||||
|
||||
const cmd = () => {
|
||||
execSync(`node ./format-deploy.mjs --app=tests --output=${output}`, {
|
||||
stdio: 'pipe',
|
||||
});
|
||||
};
|
||||
|
||||
expect(cmd).toThrow(
|
||||
`Error: File locales${path.sep}tests${path.sep}en${path.sep}translations.json not found!`,
|
||||
);
|
||||
});
|
||||
|
||||
test('cmd format-deploy throws an error when no translation to deploy', () => {
|
||||
// To be sure the tests folder is not here
|
||||
fs.rmSync('./locales/tests', { recursive: true, force: true });
|
||||
expect(fs.existsSync('./locales/tests')).toBeFalsy();
|
||||
|
||||
// Generate english json file
|
||||
fs.mkdirSync('./locales/tests/', { recursive: true });
|
||||
|
||||
// Execute format-deploy command
|
||||
const output = './locales/tests/translations.json';
|
||||
|
||||
const cmd = () => {
|
||||
execSync(`node ./format-deploy.mjs --app=tests --output=${output}`, {
|
||||
stdio: 'pipe',
|
||||
});
|
||||
};
|
||||
|
||||
expect(cmd).toThrow('Error: No translation to deploy');
|
||||
});
|
||||
});
|
||||
28
src/frontend/packages/i18n/__tests__/translations.test.ts
Normal file
28
src/frontend/packages/i18n/__tests__/translations.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { execSync } from 'child_process';
|
||||
import fs from 'fs';
|
||||
|
||||
describe('checks all the frontend translation are made', () => {
|
||||
it('checks missing translation. If this test fails, go to https://crowdin.com/', () => {
|
||||
// Extract the translations
|
||||
execSync(
|
||||
'yarn extract-translation:desk -c ./i18next-parser.config.jest.mjs',
|
||||
);
|
||||
const outputCrowdin = './locales/desk/translations-crowdin.json';
|
||||
const jsonCrowdin = JSON.parse(fs.readFileSync(outputCrowdin, 'utf8'));
|
||||
const listKeysCrowdin = Object.keys(jsonCrowdin).sort();
|
||||
|
||||
// Check the translations in the app Desk
|
||||
const outputDesk = '../../apps/desk/src/i18n/translations.json';
|
||||
const jsonDesk = JSON.parse(fs.readFileSync(outputDesk, 'utf8'));
|
||||
|
||||
// Our keys are in english, so we don't need to check the english translation
|
||||
Object.keys(jsonDesk)
|
||||
.filter((key) => key !== 'en')
|
||||
.forEach((key) => {
|
||||
const listKeysDesk = Object.keys(jsonDesk[key].translation).sort();
|
||||
expect(
|
||||
listKeysCrowdin.every((element) => listKeysDesk.includes(element)),
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -28,7 +28,7 @@ fs.readdirSync(folderPath).map((language) => {
|
||||
const pathTranslateFile = path.join(languagePath, path.sep, namefile);
|
||||
|
||||
if (!fs.existsSync(pathTranslateFile)) {
|
||||
return;
|
||||
throw new Error(`File ${pathTranslateFile} not found!`);
|
||||
}
|
||||
|
||||
const json = JSON.parse(fs.readFileSync(pathTranslateFile, "utf8"));
|
||||
@@ -43,6 +43,10 @@ fs.readdirSync(folderPath).map((language) => {
|
||||
};
|
||||
});
|
||||
|
||||
if (!Object.keys(jsonI18n).length) {
|
||||
throw new Error(`No translation to deploy`);
|
||||
}
|
||||
|
||||
// Write the file to the output
|
||||
fs.writeFileSync(output, JSON.stringify(jsonI18n), "utf8");
|
||||
|
||||
|
||||
7
src/frontend/packages/i18n/jest.config.ts
Normal file
7
src/frontend/packages/i18n/jest.config.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export default {
|
||||
rootDir: "./",
|
||||
testEnvironment: "node",
|
||||
transform: {
|
||||
"^.+\\.(ts)$": "ts-jest",
|
||||
},
|
||||
};
|
||||
@@ -6,10 +6,16 @@
|
||||
"extract-translation": "yarn extract-translation:desk",
|
||||
"extract-translation:desk": "yarn i18next ../../apps/desk/**/*.{ts,tsx} -c ./i18next-parser.config.mjs -o ./locales/desk/translations-crowdin.json",
|
||||
"format-deploy": "yarn format-deploy:desk",
|
||||
"format-deploy:desk": "node ./format-deploy.mjs --app=desk --output=../../apps/desk/src/i18n/translations.json"
|
||||
"format-deploy:desk": "node ./format-deploy.mjs --app=desk --output=../../apps/desk/src/i18n/translations.json",
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/jest": "29.5.11",
|
||||
"@types/node": "20.11.6",
|
||||
"i18next-parser": "8.8.0",
|
||||
"jest": "29.7.0",
|
||||
"ts-jest": "29.1.2",
|
||||
"typescript": "*",
|
||||
"yargs": "17.7.2"
|
||||
}
|
||||
}
|
||||
|
||||
21
src/frontend/packages/i18n/tsconfig.json
Normal file
21
src/frontend/packages/i18n/tsconfig.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
Reference in New Issue
Block a user