✅(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:
14
.github/workflows/people.yml
vendored
14
.github/workflows/people.yml
vendored
@@ -58,24 +58,30 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test-front-desk:
|
||||
test-front:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: src/frontend/apps/desk
|
||||
working-directory: src/frontend/
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '18.x'
|
||||
cache: 'yarn'
|
||||
cache-dependency-path: src/frontend/yarn.lock
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Test Desk App
|
||||
run: yarn test
|
||||
|
||||
- name: Test App
|
||||
run: yarn app:test
|
||||
|
||||
- name: Test Translations
|
||||
run: yarn i18n:test
|
||||
|
||||
lint-front:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
"e2e:test": "yarn APP_E2E run test",
|
||||
"lint": "yarn APP_DESK run lint && yarn APP_E2E run lint",
|
||||
"i18n:extract": "yarn I18N run extract-translation",
|
||||
"i18n:deploy": "yarn I18N run format-deploy"
|
||||
"i18n:deploy": "yarn I18N run format-deploy",
|
||||
"i18n:test": "yarn I18N run test"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/node": "20.11.16",
|
||||
|
||||
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"]
|
||||
}
|
||||
@@ -2295,6 +2295,14 @@
|
||||
dependencies:
|
||||
"@types/istanbul-lib-report" "*"
|
||||
|
||||
"@types/jest@29.5.11":
|
||||
version "29.5.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.11.tgz#0c13aa0da7d0929f078ab080ae5d4ced80fa2f2c"
|
||||
integrity sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==
|
||||
dependencies:
|
||||
expect "^29.0.0"
|
||||
pretty-format "^29.0.0"
|
||||
|
||||
"@types/jest@29.5.12":
|
||||
version "29.5.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544"
|
||||
@@ -2327,7 +2335,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
|
||||
integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==
|
||||
|
||||
"@types/node@*", "@types/node@20.11.16":
|
||||
"@types/node@*", "@types/node@20.11.16", "@types/node@20.11.6":
|
||||
version "20.11.16"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.16.tgz#4411f79411514eb8e2926f036c86c9f0e4ec6708"
|
||||
integrity sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==
|
||||
@@ -2984,6 +2992,13 @@ browserslist@^4.22.2:
|
||||
node-releases "^2.0.14"
|
||||
update-browserslist-db "^1.0.13"
|
||||
|
||||
bs-logger@0.x:
|
||||
version "0.2.6"
|
||||
resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8"
|
||||
integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==
|
||||
dependencies:
|
||||
fast-json-stable-stringify "2.x"
|
||||
|
||||
bser@2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
|
||||
@@ -4141,7 +4156,7 @@ fast-glob@^3.2.9, fast-glob@^3.3.1, fast-glob@^3.3.2:
|
||||
merge2 "^1.3.0"
|
||||
micromatch "^4.0.4"
|
||||
|
||||
fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0:
|
||||
fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
||||
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
||||
@@ -5455,7 +5470,7 @@ jest-snapshot@^29.7.0:
|
||||
pretty-format "^29.7.0"
|
||||
semver "^7.5.3"
|
||||
|
||||
jest-util@^29.7.0:
|
||||
jest-util@^29.0.0, jest-util@^29.7.0:
|
||||
version "29.7.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc"
|
||||
integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==
|
||||
@@ -5749,6 +5764,11 @@ lodash.isequal@^4.5.0:
|
||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
|
||||
|
||||
lodash.memoize@4.x:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==
|
||||
|
||||
lodash.merge@^4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
@@ -5807,7 +5827,7 @@ make-dir@^4.0.0:
|
||||
dependencies:
|
||||
semver "^7.5.3"
|
||||
|
||||
make-error@^1.1.1:
|
||||
make-error@1.x, make-error@^1.1.1:
|
||||
version "1.3.6"
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
||||
@@ -7291,6 +7311,20 @@ ts-api-utils@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331"
|
||||
integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==
|
||||
|
||||
ts-jest@29.1.2:
|
||||
version "29.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.2.tgz#7613d8c81c43c8cb312c6904027257e814c40e09"
|
||||
integrity sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==
|
||||
dependencies:
|
||||
bs-logger "0.x"
|
||||
fast-json-stable-stringify "2.x"
|
||||
jest-util "^29.0.0"
|
||||
json5 "^2.2.3"
|
||||
lodash.memoize "4.x"
|
||||
make-error "1.x"
|
||||
semver "^7.5.3"
|
||||
yargs-parser "^21.0.1"
|
||||
|
||||
ts-node@10.9.2:
|
||||
version "10.9.2"
|
||||
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f"
|
||||
@@ -7797,7 +7831,7 @@ yallist@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yargs-parser@^21.1.1:
|
||||
yargs-parser@^21.0.1, yargs-parser@^21.1.1:
|
||||
version "21.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
|
||||
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
|
||||
|
||||
Reference in New Issue
Block a user