adapt-authoring-lang 1.0.8 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
on: push
|
|
3
|
+
jobs:
|
|
4
|
+
default:
|
|
5
|
+
runs-on: ubuntu-latest
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
steps:
|
|
9
|
+
- uses: actions/checkout@master
|
|
10
|
+
- uses: actions/setup-node@master
|
|
11
|
+
with:
|
|
12
|
+
node-version: 'lts/*'
|
|
13
|
+
cache: 'npm'
|
|
14
|
+
- run: npm ci
|
|
15
|
+
- run: npm test
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adapt-authoring-lang",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Localisation for the Adapt authoring tool",
|
|
5
5
|
"homepage": "https://github.com/taylortom/adapt-authoring-lang",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -9,10 +9,26 @@
|
|
|
9
9
|
"bin": {
|
|
10
10
|
"at-langcheck": "./bin/check.js"
|
|
11
11
|
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "node --test tests/*.spec.js"
|
|
14
|
+
},
|
|
12
15
|
"repository": "github:adapt-security/adapt-authoring-lang",
|
|
13
16
|
"dependencies": {
|
|
17
|
+
"adapt-authoring-core": "^1.7.0",
|
|
14
18
|
"glob": "^13.0.0"
|
|
15
19
|
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"adapt-authoring-auth": "^1.0.7",
|
|
22
|
+
"adapt-authoring-server": "^1.2.1"
|
|
23
|
+
},
|
|
24
|
+
"peerDependenciesMeta": {
|
|
25
|
+
"adapt-authoring-auth": {
|
|
26
|
+
"optional": true
|
|
27
|
+
},
|
|
28
|
+
"adapt-authoring-server": {
|
|
29
|
+
"optional": true
|
|
30
|
+
}
|
|
31
|
+
},
|
|
16
32
|
"devDependencies": {
|
|
17
33
|
"@semantic-release/git": "^10.0.1",
|
|
18
34
|
"conventional-changelog-eslint": "^6.0.0",
|
|
@@ -35,7 +51,15 @@
|
|
|
35
51
|
],
|
|
36
52
|
"@semantic-release/npm",
|
|
37
53
|
"@semantic-release/github",
|
|
38
|
-
|
|
54
|
+
[
|
|
55
|
+
"@semantic-release/git",
|
|
56
|
+
{
|
|
57
|
+
"assets": [
|
|
58
|
+
"package.json"
|
|
59
|
+
],
|
|
60
|
+
"message": "Chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
61
|
+
}
|
|
62
|
+
]
|
|
39
63
|
]
|
|
40
64
|
}
|
|
41
65
|
}
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
import { describe, it, mock, before, beforeEach } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import LangModule from '../lib/LangModule.js'
|
|
4
|
+
|
|
5
|
+
describe('LangModule', () => {
|
|
6
|
+
let instance
|
|
7
|
+
|
|
8
|
+
before(() => {
|
|
9
|
+
// Create a minimal mock for AbstractModule dependencies
|
|
10
|
+
instance = new LangModule()
|
|
11
|
+
// Mock the required app structure
|
|
12
|
+
instance.app = {
|
|
13
|
+
name: 'test-app',
|
|
14
|
+
dependencies: {},
|
|
15
|
+
errors: {
|
|
16
|
+
UNKNOWN_LANG: { setData: (data) => ({ data }) }
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// Mock log method
|
|
20
|
+
instance.log = () => {}
|
|
21
|
+
// Mock getConfig method
|
|
22
|
+
instance.getConfig = (key) => {
|
|
23
|
+
if (key === 'defaultLang') return 'en'
|
|
24
|
+
return undefined
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
describe('#supportedLanguages', () => {
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
instance.phrases = {}
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('should return empty array when no phrases loaded', () => {
|
|
34
|
+
assert.deepEqual(instance.supportedLanguages, [])
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('should return array of language keys', () => {
|
|
38
|
+
instance.phrases = {
|
|
39
|
+
en: { 'app.test': 'Test' },
|
|
40
|
+
fr: { 'app.test': 'Test FR' }
|
|
41
|
+
}
|
|
42
|
+
assert.deepEqual(instance.supportedLanguages, ['en', 'fr'])
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('should return single language', () => {
|
|
46
|
+
instance.phrases = {
|
|
47
|
+
de: { 'app.test': 'Test DE' }
|
|
48
|
+
}
|
|
49
|
+
assert.deepEqual(instance.supportedLanguages, ['de'])
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
describe('#storeStrings()', () => {
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
instance.phrases = {}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('should store string with language prefix', () => {
|
|
59
|
+
instance.storeStrings('en.app.test', 'Test Value')
|
|
60
|
+
assert.equal(instance.phrases.en['app.test'], 'Test Value')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('should create language key if not exists', () => {
|
|
64
|
+
instance.storeStrings('fr.app.hello', 'Bonjour')
|
|
65
|
+
assert.ok(instance.phrases.fr)
|
|
66
|
+
assert.equal(instance.phrases.fr['app.hello'], 'Bonjour')
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('should store multiple strings for same language', () => {
|
|
70
|
+
instance.storeStrings('en.app.test1', 'Value 1')
|
|
71
|
+
instance.storeStrings('en.app.test2', 'Value 2')
|
|
72
|
+
assert.equal(instance.phrases.en['app.test1'], 'Value 1')
|
|
73
|
+
assert.equal(instance.phrases.en['app.test2'], 'Value 2')
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('should handle nested keys with dots', () => {
|
|
77
|
+
instance.storeStrings('en.app.nested.key', 'Nested Value')
|
|
78
|
+
assert.equal(instance.phrases.en['app.nested.key'], 'Nested Value')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('should overwrite existing key', () => {
|
|
82
|
+
instance.storeStrings('en.app.test', 'Original')
|
|
83
|
+
instance.storeStrings('en.app.test', 'Updated')
|
|
84
|
+
assert.equal(instance.phrases.en['app.test'], 'Updated')
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
describe('#translate()', () => {
|
|
89
|
+
beforeEach(() => {
|
|
90
|
+
instance.phrases = {
|
|
91
|
+
en: {
|
|
92
|
+
'app.simple': 'Simple text',
|
|
93
|
+
'app.withdata': 'Hello $' + '{name}',
|
|
94
|
+
'app.multiple': 'User $' + '{user} has $' + '{count} items',
|
|
95
|
+
'app.array': 'Items: $' + '{items}',
|
|
96
|
+
'app.arraymap': 'Names: $map{users:name:, }',
|
|
97
|
+
'error.TEST_ERROR': 'Test error message'
|
|
98
|
+
},
|
|
99
|
+
fr: {
|
|
100
|
+
'app.simple': 'Texte simple',
|
|
101
|
+
'app.withdata': 'Bonjour $' + '{name}'
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('should return simple translated string', () => {
|
|
107
|
+
const result = instance.translate('en', 'app.simple')
|
|
108
|
+
assert.equal(result, 'Simple text')
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
it('should return string in specified language', () => {
|
|
112
|
+
const result = instance.translate('fr', 'app.simple')
|
|
113
|
+
assert.equal(result, 'Texte simple')
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('should return key if translation not found', () => {
|
|
117
|
+
const result = instance.translate('en', 'app.missing')
|
|
118
|
+
assert.equal(result, 'app.missing')
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it('should use default language if lang not provided as string', () => {
|
|
122
|
+
const result = instance.translate(null, 'app.simple')
|
|
123
|
+
assert.equal(result, 'Simple text')
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('should replace single placeholder with data', () => {
|
|
127
|
+
const result = instance.translate('en', 'app.withdata', { name: 'John' })
|
|
128
|
+
assert.equal(result, 'Hello John')
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it('should replace multiple placeholders with data', () => {
|
|
132
|
+
const result = instance.translate('en', 'app.multiple', { user: 'Alice', count: 5 })
|
|
133
|
+
assert.equal(result, 'User Alice has 5 items')
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
it('should handle missing data gracefully', () => {
|
|
137
|
+
const result = instance.translate('en', 'app.withdata', {})
|
|
138
|
+
assert.equal(result, 'Hello $' + '{name}')
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it('should replace array placeholders', () => {
|
|
142
|
+
const result = instance.translate('en', 'app.array', { items: ['a', 'b', 'c'] })
|
|
143
|
+
assert.ok(result.includes('a'))
|
|
144
|
+
assert.ok(result.includes('b'))
|
|
145
|
+
assert.ok(result.includes('c'))
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('should handle $map syntax with arrays of objects', () => {
|
|
149
|
+
const users = [
|
|
150
|
+
{ name: 'Alice', age: 30 },
|
|
151
|
+
{ name: 'Bob', age: 25 }
|
|
152
|
+
]
|
|
153
|
+
const result = instance.translate('en', 'app.arraymap', { users })
|
|
154
|
+
assert.equal(result, 'Names: Alice, Bob')
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('should translate error objects by calling translateError', () => {
|
|
158
|
+
const mockError = {
|
|
159
|
+
constructor: { name: 'AdaptError' },
|
|
160
|
+
code: 'TEST_ERROR',
|
|
161
|
+
data: {}
|
|
162
|
+
}
|
|
163
|
+
const result = instance.translate('en', mockError)
|
|
164
|
+
assert.equal(result, 'Test error message')
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
it('should use default language when lang is a number', () => {
|
|
168
|
+
const result = instance.translate(42, 'app.simple')
|
|
169
|
+
assert.equal(result, 'Simple text')
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
it('should use default language when lang is undefined', () => {
|
|
173
|
+
const result = instance.translate(undefined, 'app.simple')
|
|
174
|
+
assert.equal(result, 'Simple text')
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it('should return key when language exists but key is missing', () => {
|
|
178
|
+
const result = instance.translate('fr', 'app.missing')
|
|
179
|
+
assert.equal(result, 'app.missing')
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('should return key when language does not exist', () => {
|
|
183
|
+
const result = instance.translate('de', 'app.simple')
|
|
184
|
+
assert.equal(result, 'app.simple')
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
it('should translate error values in data via translateError', () => {
|
|
188
|
+
instance.phrases.en['app.status'] = 'Status: $' + '{err}'
|
|
189
|
+
instance.phrases.en['error.INNER'] = 'inner error'
|
|
190
|
+
const innerError = {
|
|
191
|
+
constructor: { name: 'AdaptError' },
|
|
192
|
+
code: 'INNER',
|
|
193
|
+
data: {}
|
|
194
|
+
}
|
|
195
|
+
const result = instance.translate('en', 'app.status', { err: innerError })
|
|
196
|
+
assert.equal(result, 'Status: inner error')
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
it('should translate error values inside arrays in data', () => {
|
|
200
|
+
instance.phrases.en['app.errors'] = 'Errors: $' + '{errs}'
|
|
201
|
+
instance.phrases.en['error.E1'] = 'err one'
|
|
202
|
+
instance.phrases.en['error.E2'] = 'err two'
|
|
203
|
+
const errs = [
|
|
204
|
+
{ constructor: { name: 'AdaptError' }, code: 'E1', data: {} },
|
|
205
|
+
{ constructor: { name: 'AdaptError' }, code: 'E2', data: {} }
|
|
206
|
+
]
|
|
207
|
+
const result = instance.translate('en', 'app.errors', { errs })
|
|
208
|
+
assert.ok(result.includes('err one'))
|
|
209
|
+
assert.ok(result.includes('err two'))
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
it('should handle $map with multiple attributes', () => {
|
|
213
|
+
instance.phrases.en['app.userinfo'] = 'Users: $map{users:name,age: | }'
|
|
214
|
+
const users = [
|
|
215
|
+
{ name: 'Alice', age: 30 },
|
|
216
|
+
{ name: 'Bob', age: 25 }
|
|
217
|
+
]
|
|
218
|
+
const result = instance.translate('en', 'app.userinfo', { users })
|
|
219
|
+
assert.equal(result, 'Users: Alice,30 | Bob,25')
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('should handle $map with missing attribute by keeping attribute name', () => {
|
|
223
|
+
instance.phrases.en['app.userinfo'] = 'Users: $map{users:missing:, }'
|
|
224
|
+
const users = [{ name: 'Alice' }, { name: 'Bob' }]
|
|
225
|
+
const result = instance.translate('en', 'app.userinfo', { users })
|
|
226
|
+
assert.equal(result, 'Users: missing, missing')
|
|
227
|
+
})
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
describe('#translateError()', () => {
|
|
231
|
+
beforeEach(() => {
|
|
232
|
+
instance.phrases = {
|
|
233
|
+
en: {
|
|
234
|
+
'error.TEST_CODE': 'Error: $' + '{message}',
|
|
235
|
+
'error.SIMPLE': 'Simple error'
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
it('should translate error with code', () => {
|
|
241
|
+
const error = {
|
|
242
|
+
constructor: { name: 'AdaptError' },
|
|
243
|
+
code: 'SIMPLE',
|
|
244
|
+
data: {}
|
|
245
|
+
}
|
|
246
|
+
const result = instance.translateError('en', error)
|
|
247
|
+
assert.equal(result, 'Simple error')
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it('should translate error with data', () => {
|
|
251
|
+
const error = {
|
|
252
|
+
constructor: { name: 'TestError' },
|
|
253
|
+
code: 'TEST_CODE',
|
|
254
|
+
data: { message: 'Something went wrong' }
|
|
255
|
+
}
|
|
256
|
+
const result = instance.translateError('en', error)
|
|
257
|
+
assert.equal(result, 'Error: Something went wrong')
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
it('should return non-error values unchanged', () => {
|
|
261
|
+
const result = instance.translateError('en', 'just a string')
|
|
262
|
+
assert.equal(result, 'just a string')
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
it('should return null unchanged', () => {
|
|
266
|
+
const result = instance.translateError('en', null)
|
|
267
|
+
assert.equal(result, null)
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
it('should return undefined unchanged', () => {
|
|
271
|
+
const result = instance.translateError('en', undefined)
|
|
272
|
+
assert.equal(result, undefined)
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
it('should return number values unchanged', () => {
|
|
276
|
+
const result = instance.translateError('en', 42)
|
|
277
|
+
assert.equal(result, 42)
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
it('should use error object itself as data when data is missing', () => {
|
|
281
|
+
instance.phrases.en['error.NO_DATA'] = 'Code: $' + '{code}'
|
|
282
|
+
const error = {
|
|
283
|
+
constructor: { name: 'AdaptError' },
|
|
284
|
+
code: 'NO_DATA'
|
|
285
|
+
}
|
|
286
|
+
const result = instance.translateError('en', error)
|
|
287
|
+
assert.equal(result, 'Code: NO_DATA')
|
|
288
|
+
})
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
describe('#addTranslationUtils()', () => {
|
|
292
|
+
beforeEach(() => {
|
|
293
|
+
instance.phrases = {
|
|
294
|
+
en: { 'app.hello': 'Hello' },
|
|
295
|
+
fr: { 'app.hello': 'Bonjour' }
|
|
296
|
+
}
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
it('should add translate function to the request object', () => {
|
|
300
|
+
const req = {
|
|
301
|
+
acceptsLanguages: () => 'en'
|
|
302
|
+
}
|
|
303
|
+
const res = {}
|
|
304
|
+
const next = mock.fn()
|
|
305
|
+
instance.addTranslationUtils(req, res, next)
|
|
306
|
+
assert.equal(typeof req.translate, 'function')
|
|
307
|
+
assert.equal(next.mock.callCount(), 1)
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
it('should bind translate to the accepted language', () => {
|
|
311
|
+
const req = {
|
|
312
|
+
acceptsLanguages: () => 'fr'
|
|
313
|
+
}
|
|
314
|
+
const res = {}
|
|
315
|
+
const next = mock.fn()
|
|
316
|
+
instance.addTranslationUtils(req, res, next)
|
|
317
|
+
const result = req.translate('app.hello')
|
|
318
|
+
assert.equal(result, 'Bonjour')
|
|
319
|
+
})
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
describe('#requestHandler()', () => {
|
|
323
|
+
beforeEach(() => {
|
|
324
|
+
instance.phrases = {
|
|
325
|
+
en: { 'app.hello': 'Hello' },
|
|
326
|
+
fr: { 'app.hello': 'Bonjour' }
|
|
327
|
+
}
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
it('should respond with phrases for the requested language', () => {
|
|
331
|
+
const req = {
|
|
332
|
+
params: { lang: 'en' },
|
|
333
|
+
acceptsLanguages: () => 'en'
|
|
334
|
+
}
|
|
335
|
+
let jsonData
|
|
336
|
+
const res = { json: (data) => { jsonData = data } }
|
|
337
|
+
const next = mock.fn()
|
|
338
|
+
instance.requestHandler(req, res, next)
|
|
339
|
+
assert.deepEqual(jsonData, { 'app.hello': 'Hello' })
|
|
340
|
+
assert.equal(next.mock.callCount(), 0)
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
it('should fall back to browser language when no lang param', () => {
|
|
344
|
+
const req = {
|
|
345
|
+
params: {},
|
|
346
|
+
acceptsLanguages: () => 'fr'
|
|
347
|
+
}
|
|
348
|
+
let jsonData
|
|
349
|
+
const res = { json: (data) => { jsonData = data } }
|
|
350
|
+
const next = mock.fn()
|
|
351
|
+
instance.requestHandler(req, res, next)
|
|
352
|
+
assert.deepEqual(jsonData, { 'app.hello': 'Bonjour' })
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
it('should call next with error for unknown language', () => {
|
|
356
|
+
const req = {
|
|
357
|
+
params: { lang: 'de' },
|
|
358
|
+
acceptsLanguages: () => false
|
|
359
|
+
}
|
|
360
|
+
const res = {}
|
|
361
|
+
const next = mock.fn()
|
|
362
|
+
instance.requestHandler(req, res, next)
|
|
363
|
+
assert.equal(next.mock.callCount(), 1)
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
it('should call next with error when no language is accepted', () => {
|
|
367
|
+
const req = {
|
|
368
|
+
params: {},
|
|
369
|
+
acceptsLanguages: () => false
|
|
370
|
+
}
|
|
371
|
+
const res = {}
|
|
372
|
+
const next = mock.fn()
|
|
373
|
+
instance.requestHandler(req, res, next)
|
|
374
|
+
assert.equal(next.mock.callCount(), 1)
|
|
375
|
+
})
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
describe('#getPhrasesForLang()', () => {
|
|
379
|
+
// Note: This method has quirky behavior and doesn't match the actual phrases structure.
|
|
380
|
+
// The method expects keys like 'lang.key' but actual structure is { lang: { key: value } }.
|
|
381
|
+
// Tests document the actual behavior even though it may not be the intended behavior.
|
|
382
|
+
|
|
383
|
+
it('should return undefined when phrases structure does not match expected format', () => {
|
|
384
|
+
// The current structure is { lang: { key: value } }
|
|
385
|
+
// but getPhrasesForLang expects keys like 'lang.key'
|
|
386
|
+
instance.phrases = {
|
|
387
|
+
en: {
|
|
388
|
+
'app.test1': 'Test 1',
|
|
389
|
+
'app.test2': 'Test 2'
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
const result = instance.getPhrasesForLang('en')
|
|
393
|
+
// Returns undefined because the structure doesn't match what the method expects
|
|
394
|
+
assert.equal(result, undefined)
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
it('should work with flat key structure if provided', () => {
|
|
398
|
+
// If phrases were structured as expected by this method
|
|
399
|
+
instance.phrases = {
|
|
400
|
+
'en.app.test1': 'Test 1',
|
|
401
|
+
'en.app.test2': 'Test 2',
|
|
402
|
+
'en.error.ERR1': 'Error 1',
|
|
403
|
+
'fr.app.test': 'Test FR'
|
|
404
|
+
}
|
|
405
|
+
const result = instance.getPhrasesForLang('en')
|
|
406
|
+
assert.ok(result)
|
|
407
|
+
assert.equal(Object.keys(result).length, 3)
|
|
408
|
+
assert.equal(result['app.test1'], 'Test 1')
|
|
409
|
+
assert.equal(result['app.test2'], 'Test 2')
|
|
410
|
+
assert.equal(result['error.ERR1'], 'Error 1')
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
it('should return undefined for language with only one phrase', () => {
|
|
414
|
+
// Method only returns phrases when there are more than one (line 111 in LangModule.js)
|
|
415
|
+
// This is the actual behavior, even if it seems arbitrary
|
|
416
|
+
instance.phrases = {
|
|
417
|
+
'en.app.test': 'Test'
|
|
418
|
+
}
|
|
419
|
+
const result = instance.getPhrasesForLang('en')
|
|
420
|
+
assert.equal(result, undefined)
|
|
421
|
+
})
|
|
422
|
+
|
|
423
|
+
it('should return undefined for non-existent language', () => {
|
|
424
|
+
instance.phrases = {
|
|
425
|
+
'en.app.test1': 'Test 1',
|
|
426
|
+
'en.app.test2': 'Test 2'
|
|
427
|
+
}
|
|
428
|
+
const result = instance.getPhrasesForLang('de')
|
|
429
|
+
assert.equal(result, undefined)
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
it('should return undefined when phrases is empty', () => {
|
|
433
|
+
instance.phrases = {}
|
|
434
|
+
const result = instance.getPhrasesForLang('en')
|
|
435
|
+
assert.equal(result, undefined)
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
it('should exclude phrases from other languages', () => {
|
|
439
|
+
instance.phrases = {
|
|
440
|
+
'en.app.test1': 'Test 1',
|
|
441
|
+
'en.app.test2': 'Test 2',
|
|
442
|
+
'fr.app.test1': 'Test FR'
|
|
443
|
+
}
|
|
444
|
+
const result = instance.getPhrasesForLang('en')
|
|
445
|
+
assert.ok(result)
|
|
446
|
+
assert.equal(Object.keys(result).length, 2)
|
|
447
|
+
assert.equal(result['app.test1'], 'Test 1')
|
|
448
|
+
assert.equal(result['fr.app.test1'], undefined)
|
|
449
|
+
})
|
|
450
|
+
})
|
|
451
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock AbstractModule for testing purposes
|
|
3
|
+
* This is a minimal implementation that provides the structure needed for tests
|
|
4
|
+
*/
|
|
5
|
+
class AbstractModule {
|
|
6
|
+
constructor () {
|
|
7
|
+
this.app = null
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
log () {}
|
|
11
|
+
getConfig () {}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { AbstractModule }
|