Skip to content
This repository was archived by the owner on May 19, 2025. It is now read-only.

Commit 1eaf396

Browse files
bwttjP1X3L
andauthored
chore(conf): configure tests and improve i18n tooling (#285)
- reorg check utils and adding associated tests - activate test in ci - replace jest with vitest and adapt test code - add check.mjs file with its own check function and tests - update README --------- Signed-off-by: Paul-Xavier Ceccaldi <pix@wttj.co> Co-authored-by: Paul-Xavier Ceccaldi <pix@wttj.co>
1 parent b0a1206 commit 1eaf396

File tree

18 files changed

+914
-1239
lines changed

18 files changed

+914
-1239
lines changed

.circleci/config.yml

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ defaults: &defaults
44
parameters:
55
nodejs_base_image:
66
type: string
7-
default: 'cimg/node:18.18.0'
7+
default: 'cimg/node:20.11.0'
88
cache_version:
99
type: string
1010
default: v20
@@ -63,6 +63,18 @@ jobs:
6363
name: linter
6464
command: yarn lint
6565

66+
test:
67+
<<: *defaults
68+
docker:
69+
- image: << pipeline.parameters.nodejs_base_image >>
70+
environment:
71+
NODE_ENV: test
72+
steps:
73+
- *restore_repo
74+
- run:
75+
name: test
76+
command: yarn test --watch=false
77+
6678
release:
6779
<<: *defaults
6880
docker:
@@ -98,7 +110,15 @@ workflows:
98110
only: /.*/
99111
- lint:
100112
requires:
101-
- vulnerabilities_yarn
113+
- checkout
114+
filters:
115+
branches:
116+
only: /.*/
117+
tags:
118+
only: /.*/
119+
- test:
120+
requires:
121+
- checkout
102122
filters:
103123
branches:
104124
only: /.*/
@@ -108,6 +128,7 @@ workflows:
108128
context:
109129
- wttj-config
110130
requires:
131+
- test
111132
- vulnerabilities_yarn
112133
- lint
113134
filters:

.husky/pre-push

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
yarn lint && yarn test && yarn check:audit
1+
yarn lint && yarn test --watch=false && yarn check:audit

.tool-versions

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nodejs 20.11.0

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,36 @@ All notable changes to this project will be documented in this file. Dates are d
44

55
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
66

7+
#### [3.1.3](https://github.com/WTTJ/front-config/compare/3.1.3-beta.1...3.1.3)
8+
9+
- Fix tests [`#286`](https://github.com/WTTJ/front-config/pull/286)
10+
- chore: fix vulnerability [`c2bc427`](https://github.com/WTTJ/front-config/commit/c2bc4277a382f78a053037d1451c47475b2ff68d)
11+
- style: add precision to README [`effb2f0`](https://github.com/WTTJ/front-config/commit/effb2f0f6d5b5a37145e44c6dbe372d474194aae)
12+
13+
#### [3.1.3-beta.1](https://github.com/WTTJ/front-config/compare/3.1.3-beta.0...3.1.3-beta.1)
14+
15+
> 10 April 2025
16+
17+
- chore: release v3.1.3-beta.1 [`164aa8a`](https://github.com/WTTJ/front-config/commit/164aa8a9af4dc0a7bfdcee09abc8e361d7ecbf27)
18+
- fix: precommit hook import wrong file name [`ccde5ec`](https://github.com/WTTJ/front-config/commit/ccde5ec7011dacd201d45dd3efa663543c6edade)
19+
20+
#### [3.1.3-beta.0](https://github.com/WTTJ/front-config/compare/3.1.2...3.1.3-beta.0)
21+
22+
> 10 April 2025
23+
24+
- chore: update yarn audit [FRO-13] [`#281`](https://github.com/WTTJ/front-config/pull/281)
25+
- Fix(i18n): extend regex to handle optional id prefix [`#280`](https://github.com/WTTJ/front-config/pull/280)
26+
- fix: precommit no ignoring path_to_ignore option [`#279`](https://github.com/WTTJ/front-config/pull/279)
27+
- chore: replace jest with vitest and adapt test code [`b54a38d`](https://github.com/WTTJ/front-config/commit/b54a38df5b284621fb330c55cb09427ef8890cb7)
28+
- chore: merge check and sync utils [`d373e57`](https://github.com/WTTJ/front-config/commit/d373e571e38551b284a6d64cc474789148642a8a)
29+
- chore: add conf for vitest and mock fs with memfs [`91d15bc`](https://github.com/WTTJ/front-config/commit/91d15bc7db263523583ea568ad13b8612e377a0f)
30+
731
#### [3.1.2](https://github.com/WTTJ/front-config/compare/3.1.2-0...3.1.2)
832

33+
> 21 February 2025
34+
35+
- chore: release v3.1.2 [`1315712`](https://github.com/WTTJ/front-config/commit/13157121e6df5cda810c87b7ee60af73ea0d5a3d)
36+
937
#### [3.1.2-0](https://github.com/WTTJ/front-config/compare/3.1.1...3.1.2-0)
1038

1139
> 21 February 2025

__mocks__/fs.cjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// we can also use `import`, but then
2+
// every export should be explicitly defined
3+
4+
const { fs } = require('memfs')
5+
6+
module.exports = fs

__mocks__/fs/promises.cjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// we can also use `import`, but then
2+
// every export should be explicitly defined
3+
4+
const { fs } = require('memfs')
5+
module.exports = fs.promises

lib/i18n/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ Add the following code to your circleci configuration file and adapt it to your
6464
steps:
6565
- *restore_repo
6666
- *restore_node_modules
67+
- run:
68+
name: Check i18n translations between code and generated source locales (en-US by default)
69+
command: |
70+
node path_to_your_project/node_modules/wttj-config/lib/i18n/check.mjs
6771
- run:
6872
name: Download and install lokalise-cli v2
6973
command: |
@@ -76,7 +80,7 @@ Add the following code to your circleci configuration file and adapt it to your
7680
- run:
7781
name: Update source locales to lokalise via lokalise2
7882
command: |
79-
lokalise2 --token $LOKALISE_TOKEN --project-id $LOKALISE_PROJECT_ID file upload --file REPLACE_ME_WITH_LOCALES_DIR_PATH_VALUE/contextualized-en-US.json --lang-iso en-US --cleanup-mode
83+
lokalise2 --token $LOKALISE_TOKEN --project-id $LOKALISE_PROJECT_ID file upload --file REPLACE_ME_WITH_LOCALES_DIR_PATH_VALUE/contextualized-en-US.json --lang-iso en-US --cleanup-mode --convert-placeholders=false --replace-modified
8084
[…]
8185

8286
workflows:

lib/i18n/check.mjs

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,38 @@
11
import fs from 'fs'
2+
import { promisify } from 'util'
3+
import { exec } from 'child_process'
24

5+
// This file is meant to be used in the ci pipeline to check that
6+
// all the translations from the project are in sync with what has been
7+
// generated by the i18n:translate task
8+
// It slightly differs from what isTranslationTaskNeeded() which is used
9+
// in the pre-commit hook to check if the current commit adds new keys.
10+
// isTranslationTaskNeeded() does not check object equality
11+
12+
const execute = promisify(exec)
313
// get i18n config variables from package.json
414
const { config } = JSON.parse(fs.readFileSync('package.json'))
515

6-
export const isTranslationTaskNeeded = () => {
16+
await execute('yarn i18n:extract')
17+
18+
const hasEqualTempAndSourceLocales = () => {
719
const tempTranslations = JSON.parse(fs.readFileSync(`${config.i18n.locales_dir_path}/temp.json`))
8-
const tempKeys = Object.keys(tempTranslations)
20+
921
const sourceTranslations = JSON.parse(
1022
fs.readFileSync(`${config.i18n.locales_dir_path}/${config.i18n.default_language_filename}.json`)
1123
)
1224

13-
const idExists = id => Boolean(sourceTranslations[id])
14-
15-
if (tempKeys.length > 0 && !tempKeys.every(idExists)) {
16-
console.error('=============================================')
17-
console.error(
18-
'⚠️ This commit is going to be aborted because new translations have been found. Please add synced locales and check that everything is OK before commiting again'
19-
)
20-
console.error('=============================================')
21-
return true
22-
}
23-
return false
25+
return JSON.stringify(tempTranslations) === JSON.stringify(sourceTranslations)
26+
}
27+
28+
const isSynced = hasEqualTempAndSourceLocales()
29+
// remove temp.json file
30+
await execute(`rm -f ${config.i18n.locales_dir_path}/temp.json`)
31+
32+
if (isSynced) {
33+
process.exit(0)
34+
} else {
35+
// eslint-disable-next-line no-console
36+
console.error('please run yarn i18n:translate')
37+
process.exit(1)
2438
}

lib/i18n/check.test.mjs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { beforeEach, describe, expect, it, vi } from 'vitest'
2+
import { vol } from 'memfs'
3+
4+
beforeEach(() => {
5+
vi.resetModules()
6+
})
7+
8+
describe('isTranslationTaskNeeded', () => {
9+
const mockExit = vi.spyOn(process, 'exit').mockImplementation(vi.fn())
10+
vi.mock('child_process', () => ({
11+
exec: vi.fn((cmd, cb) => cb(null, 'mocked stdout', '')),
12+
}))
13+
14+
it('should return exit code 1 because temp.json has more keys than en-US.json', async () => {
15+
vol.fromJSON({
16+
'__mocks__/locales/temp.json': JSON.stringify({ a: 'foo', b: 'bar' }),
17+
'__mocks__/locales/en-US.json': JSON.stringify({ a: 'foo' }),
18+
})
19+
await import('./check.mjs')
20+
expect(mockExit).toHaveBeenCalledWith(1)
21+
})
22+
23+
it('should return exit code 0 because temp.json and en-US.json have the same keys', async () => {
24+
vol.fromJSON({
25+
'__mocks__/locales/temp.json': JSON.stringify({ a: 'foo', b: 'bar' }),
26+
'__mocks__/locales/en-US.json': JSON.stringify({ a: 'foo', b: 'bar' }),
27+
})
28+
await import('./check.mjs')
29+
expect(mockExit).toHaveBeenCalledWith(0)
30+
})
31+
32+
it('should return exit code 1 because temp.json has less keys than en-US.json', async () => {
33+
vol.fromJSON({
34+
'__mocks__/locales/temp.json': JSON.stringify({ a: 'foo' }),
35+
'__mocks__/locales/en-US.json': JSON.stringify({ a: 'foo', b: 'bar' }),
36+
})
37+
await import('./check.mjs')
38+
expect(mockExit).toHaveBeenCalledWith(1)
39+
})
40+
})

lib/i18n/precommit.mjs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import fs from 'fs'
1+
import { readFileSync } from 'node:fs'
22
import { promisify } from 'util'
33
import { exec } from 'child_process'
44

5-
import { isTranslationTaskNeeded } from './check.mjs'
5+
import { isTranslationTaskNeeded } from './sync-utils.mjs'
66

77
const execute = promisify(exec)
88

99
// get i18n config variables from package.json
10-
const { config } = JSON.parse(fs.readFileSync('package.json'))
10+
const { config } = JSON.parse(readFileSync('package.json'))
1111

1212
const excludeString = config.i18n.path_to_ignore ? `:^${config.i18n.path_to_ignore}` : ''
1313
const { stdout: stagedFilesNumber } = await execute(
@@ -38,6 +38,14 @@ const { stderr: extractError } = await execute(extractCommand)
3838
extractError && console.error(extractError)
3939

4040
if (isTranslationTaskNeeded()) {
41+
// eslint-disable-next-line no-console
42+
console.error('=============================================')
43+
// eslint-disable-next-line no-console
44+
console.error(
45+
'⚠️ This commit is going to be aborted because new translations have been found. Please add synced locales and check that everything is OK before commiting again'
46+
)
47+
// eslint-disable-next-line no-console
48+
console.error('=============================================')
4149
// translation script needs to be launched because temp file translations are new
4250
// eslint-disable-next-line no-console
4351
console.log('🛠 Translating')

0 commit comments

Comments
 (0)