@w3-commons/js-build-resources 0.0.1-security → 1.0.4

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.

Potentially problematic release.


This version of @w3-commons/js-build-resources might be problematic. Click here for more details.

Files changed (98) hide show
  1. package/package.json +9 -3
  2. package/settings-service/.eslintrc.js +4 -0
  3. package/settings-service/.node-version +1 -0
  4. package/settings-service/.prettierrc +6 -0
  5. package/settings-service/.whitesource +15 -0
  6. package/settings-service/LICENSE +4 -0
  7. package/settings-service/README.md +50 -0
  8. package/settings-service/build.yml +56 -0
  9. package/settings-service/collectCodeCoverage.js +9 -0
  10. package/settings-service/db/cassandra/Dockerfile +3 -0
  11. package/settings-service/db/cassandra/createkeyspace.dev.cql +4 -0
  12. package/settings-service/db/cassandra/createkeyspace.dev.sh +3 -0
  13. package/settings-service/db/cassandra/schema_001.cql +15 -0
  14. package/settings-service/db/cassandra/schema_002.cql +8 -0
  15. package/settings-service/db/cassandra/schema_003.cql +10 -0
  16. package/settings-service/db/cassandra/schema_004.cql +1 -0
  17. package/settings-service/db/cassandra/schema_005.cql +39 -0
  18. package/settings-service/db/cassandra/schema_006.cql +255 -0
  19. package/settings-service/db/cassandra/schema_007.cql +40 -0
  20. package/settings-service/db/cassandra/schema_008.cql +2 -0
  21. package/settings-service/db/cassandra/schema_009.cql +143 -0
  22. package/settings-service/db/cassandra/schema_010.cql +143 -0
  23. package/settings-service/db/cassandra/schema_011.cql +2 -0
  24. package/settings-service/db/cassandra/schema_012.cql +8 -0
  25. package/settings-service/jest.config.fn.js +3 -0
  26. package/settings-service/jest.config.it.js +3 -0
  27. package/settings-service/jest.config.js +14 -0
  28. package/settings-service/jest.config.unit.js +19 -0
  29. package/settings-service/jest.setup.js +11 -0
  30. package/settings-service/package-lock.json +11772 -0
  31. package/settings-service/package.json +101 -0
  32. package/settings-service/scripts/run-fn-tests.sh +3 -0
  33. package/settings-service/sonar-project.properties +3 -0
  34. package/settings-service/src/__tests__/functional/controller/ApiKeyController.fn.ts +132 -0
  35. package/settings-service/src/__tests__/functional/middleware/AuthMiddlewareNextGenSSO.fn.ts +82 -0
  36. package/settings-service/src/__tests__/functional/repo/settingsRepo.fn.ts +302 -0
  37. package/settings-service/src/__tests__/functional/unified-profile/unified-profile.fn.ts +66 -0
  38. package/settings-service/src/__tests__/integration/repo/ApiKeyRepo.it.ts +43 -0
  39. package/settings-service/src/__tests__/integration/repo/settingsRepo.it.ts +142 -0
  40. package/settings-service/src/__tests__/integration/unified-profile/unified-profile.it.ts +31 -0
  41. package/settings-service/src/__tests__/unit/ErrResponse.ts +4 -0
  42. package/settings-service/src/__tests__/unit/JWTResponse.ts +18 -0
  43. package/settings-service/src/__tests__/unit/bluepagesResponse.ts +25 -0
  44. package/settings-service/src/__tests__/unit/controller/ApiKeyController.spec.ts +217 -0
  45. package/settings-service/src/__tests__/unit/controller/AppSettingsController.spec.ts +133 -0
  46. package/settings-service/src/__tests__/unit/controller/UserSettingsController.spec.ts +328 -0
  47. package/settings-service/src/__tests__/unit/controller/getAllSettings.spec.ts +83 -0
  48. package/settings-service/src/__tests__/unit/middleware/AuthMiddlewareNextGenSSO.spec.ts +282 -0
  49. package/settings-service/src/__tests__/unit/middleware/AuthenticationMiddleware.spec.ts +494 -0
  50. package/settings-service/src/__tests__/unit/repo/ApiKeyRepo.spec.ts +194 -0
  51. package/settings-service/src/__tests__/unit/repo/getAllSettings.spec.ts +100 -0
  52. package/settings-service/src/__tests__/unit/repo/getUserSettingsRepo.spec.ts +249 -0
  53. package/settings-service/src/__tests__/unit/repo/settingsRepo.spec.ts +614 -0
  54. package/settings-service/src/__tests__/unit/unified-profile/UnifiedProfileClient.spec.ts +31 -0
  55. package/settings-service/src/__tests__/unit/unified-profile/unifiedProfileUtils.spec.ts +36 -0
  56. package/settings-service/src/__tests__/utils/test-utils.ts +41 -0
  57. package/settings-service/src/config/config.ts +190 -0
  58. package/settings-service/src/controller/ApiKeyController.ts +114 -0
  59. package/settings-service/src/controller/AppSettingsController.ts +137 -0
  60. package/settings-service/src/controller/UserSettingsController.ts +202 -0
  61. package/settings-service/src/helpers/commons.ts +69 -0
  62. package/settings-service/src/logger/logger.ts +17 -0
  63. package/settings-service/src/middleware/AuthenticationMiddleware.ts +486 -0
  64. package/settings-service/src/middleware/AuthenticationMiddlewareFactory.ts +10 -0
  65. package/settings-service/src/repo/ApiKeyRepo.ts +135 -0
  66. package/settings-service/src/repo/ApiKeyRepoFactory.ts +10 -0
  67. package/settings-service/src/repo/CassandraClient.ts +33 -0
  68. package/settings-service/src/repo/CassandraClientFactory.ts +11 -0
  69. package/settings-service/src/repo/apiKeyQueries.ts +64 -0
  70. package/settings-service/src/repo/cassandraDBHelpers.ts +119 -0
  71. package/settings-service/src/repo/settingsRepo.ts +388 -0
  72. package/settings-service/src/repo/settingsRepoFactory.ts +10 -0
  73. package/settings-service/src/repo/settingsRepoQueries.ts +62 -0
  74. package/settings-service/src/routes/apiKeyRoutes.ts +27 -0
  75. package/settings-service/src/routes/appSettingsRoutes.ts +30 -0
  76. package/settings-service/src/routes/healthCheck.ts +10 -0
  77. package/settings-service/src/routes/swagger.ts +8 -0
  78. package/settings-service/src/routes/userSettingsRoutes.ts +30 -0
  79. package/settings-service/src/server.ts +77 -0
  80. package/settings-service/src/swagger.json +732 -0
  81. package/settings-service/src/types/ApiKey.ts +19 -0
  82. package/settings-service/src/types/IRequest.ts +9 -0
  83. package/settings-service/src/types/IRequestAuthorization.ts +5 -0
  84. package/settings-service/src/types/IRouteOptions.ts +5 -0
  85. package/settings-service/src/types/QueryResultsTypes.ts +6 -0
  86. package/settings-service/src/types/UserSettingsControllerTypes.ts +5 -0
  87. package/settings-service/src/types/W3IdUser.ts +36 -0
  88. package/settings-service/src/types/settingsRepoTypes.ts +61 -0
  89. package/settings-service/src/types/unifiedProfileTypes.ts +10 -0
  90. package/settings-service/src/unified-profile/UnifiedProfileClient.ts +29 -0
  91. package/settings-service/src/unified-profile/UnifiedProfileClientFactory.ts +10 -0
  92. package/settings-service/src/unified-profile/unifiedProfileUtils.ts +22 -0
  93. package/settings-service/src/util/downloadCassandra.ts +34 -0
  94. package/settings-service/src/util/isocodeMapper.ts +22 -0
  95. package/settings-service/src/util/languages.ts +1457 -0
  96. package/settings-service/test_resources/mockApiKeyDBResult.json +8 -0
  97. package/settings-service/tsconfig.json +40 -0
  98. package/README.md +0 -5
@@ -0,0 +1,614 @@
1
+ import { AppSettingsResponse } from 'types/settingsRepoTypes';
2
+ import { ProfileResponse } from 'types/unifiedProfileTypes';
3
+ import { SettingsRepoFactory } from '../../../repo/settingsRepoFactory';
4
+ import { cassandraDBHelpers } from '../../../repo/cassandraDBHelpers';
5
+ import { SettingsRepo } from '../../../repo/settingsRepo';
6
+ import * as UP from '../../../unified-profile/unifiedProfileUtils';
7
+ import { INVALID_APP_ID, TEST_APP_ID, TEST_USER_ID } from '../../utils/test-utils';
8
+
9
+ jest.mock('../../../unified-profile/unifiedProfileUtils');
10
+
11
+ let settingsRepo: SettingsRepo;
12
+
13
+ beforeAll(() => {
14
+ settingsRepo = SettingsRepoFactory.accessOrCreateSingleton();
15
+ });
16
+
17
+ const USER_ID = 'AAABBBCCC';
18
+ const INVALID_USER_ID = 'BBBCCCDDD';
19
+ const APP_ID = 'test';
20
+ const SETTING_NAME = 'theme';
21
+ const SETTING_VALUE = 'dark';
22
+ const SETTING_OPTIONS = ['true', 'false'];
23
+ const SETTING_DEFAULT = 'false';
24
+
25
+ export const languageAppSettings = {
26
+ secondaryLanguages: {
27
+ options: ['en', 'fr', 'sk'],
28
+ setting_type: 'array',
29
+ default: null,
30
+ deprecated_values: null,
31
+ },
32
+ primaryLanguage: {
33
+ options: ['en', 'fr', 'sk'],
34
+ setting_type: 'string',
35
+ default: 'en',
36
+ deprecated_values: null,
37
+ },
38
+ };
39
+
40
+ describe('get settings using userID and appID', () => {
41
+ afterEach(() => {
42
+ jest.clearAllMocks();
43
+ });
44
+ it('should return empty set while fetching invalid user_id (no app data)', async () => {
45
+ const mockResultSet: any = {
46
+ rows: [],
47
+ };
48
+ const appSettingsSpy = jest.spyOn(settingsRepo, 'getAppSettings').mockResolvedValueOnce({});
49
+ cassandraDBHelpers.execute = jest.fn().mockResolvedValueOnce(mockResultSet);
50
+ expect(await settingsRepo.getUserSettings(INVALID_USER_ID, APP_ID)).toEqual({});
51
+ expect(appSettingsSpy).toHaveBeenCalled();
52
+ });
53
+
54
+ it('should return settings when using valid user_id', async () => {
55
+ const dbRecords = [
56
+ { user_id: USER_ID, app_id: APP_ID, setting_name: SETTING_NAME, setting_value: SETTING_VALUE },
57
+ ];
58
+ const mockResultSet: any = {
59
+ rows: dbRecords,
60
+ };
61
+ const mockEmptyResultSet: any = {
62
+ rows: [],
63
+ };
64
+ cassandraDBHelpers.execute = jest.fn().mockReturnValueOnce(
65
+ new Promise((resolve) => {
66
+ resolve(mockResultSet);
67
+ }),
68
+ );
69
+ const mockValue = {};
70
+ mockValue[SETTING_NAME] = { default: SETTING_DEFAULT, options: [SETTING_VALUE] };
71
+ const appSettingsSpy = jest
72
+ .spyOn(settingsRepo, 'getAppSettings')
73
+ .mockResolvedValueOnce(mockValue)
74
+ .mockResolvedValueOnce(mockValue);
75
+ let usersSettings = await settingsRepo.getUserSettings(USER_ID, APP_ID);
76
+ expect(usersSettings).toBeDefined();
77
+ expect(usersSettings[SETTING_NAME]).toEqual(SETTING_VALUE);
78
+ expect(appSettingsSpy).toHaveBeenCalledTimes(1);
79
+
80
+ cassandraDBHelpers.execute = jest.fn().mockReturnValueOnce(
81
+ new Promise((resolve) => {
82
+ resolve(mockEmptyResultSet);
83
+ }),
84
+ );
85
+ jest.clearAllMocks();
86
+ usersSettings = await settingsRepo.getUserSettings(USER_ID, APP_ID);
87
+ expect(usersSettings).toBeDefined();
88
+ expect(usersSettings[SETTING_NAME]).toEqual(SETTING_DEFAULT);
89
+ expect(appSettingsSpy).toHaveBeenCalledTimes(1);
90
+ });
91
+ it('should not return settings where name is null', async () => {
92
+ const dbRecords = [
93
+ { user_id: USER_ID, app_id: APP_ID, setting_name: null, setting_value: SETTING_VALUE },
94
+ ];
95
+ const mockResultSet: any = {
96
+ rows: dbRecords,
97
+ };
98
+ const appSettingsSpy = jest.spyOn(settingsRepo, 'getAppSettings').mockResolvedValueOnce({});
99
+ cassandraDBHelpers.execute = jest.fn().mockReturnValueOnce(
100
+ new Promise((resolve) => {
101
+ resolve(mockResultSet);
102
+ }),
103
+ );
104
+ const usersSettings = await settingsRepo.getUserSettings(USER_ID, APP_ID);
105
+ expect(usersSettings).toBeDefined();
106
+ expect(usersSettings).toEqual({});
107
+ expect(appSettingsSpy).toHaveBeenCalledTimes(1);
108
+ });
109
+ it('should throw an error if the database errors out', async () => {
110
+ const appSettingsSpy = jest.spyOn(settingsRepo, 'getAppSettings').mockResolvedValueOnce({});
111
+ cassandraDBHelpers.execute = jest.fn().mockReturnValueOnce(Promise.reject(new Error('database error')));
112
+ expect(settingsRepo.getUserSettings(INVALID_USER_ID, APP_ID)).rejects.toEqual(
113
+ Error(`Error while reading getUserSettings`),
114
+ );
115
+ expect(appSettingsSpy).toHaveBeenCalledTimes(1);
116
+ });
117
+ });
118
+
119
+ describe('update settings using userID and appID', () => {
120
+ it('should return true if call works', async () => {
121
+ const mockResultSet: any = {
122
+ rows: [{ user_id: USER_ID, app_id: APP_ID, setting_name: SETTING_NAME, setting_value: SETTING_VALUE }],
123
+ };
124
+ cassandraDBHelpers.batch = jest.fn().mockReturnValueOnce(
125
+ new Promise((resolve) => {
126
+ resolve(mockResultSet);
127
+ }),
128
+ );
129
+ const response = await settingsRepo.updateUserSettings(USER_ID, APP_ID, SETTING_NAME, SETTING_VALUE);
130
+ expect(response).toBeDefined();
131
+ expect(response).toEqual(true);
132
+ });
133
+ it('should throw an error if the database errors out', async () => {
134
+ cassandraDBHelpers.batch = jest.fn().mockImplementationOnce(() => {
135
+ throw new Error('error from db');
136
+ });
137
+ expect(
138
+ settingsRepo.updateUserSettings(INVALID_USER_ID, APP_ID, SETTING_NAME, SETTING_VALUE),
139
+ ).rejects.toEqual(Error(`error from db`));
140
+ });
141
+ });
142
+
143
+ describe('delete settings using userID', () => {
144
+ const mockResultSet: any = {
145
+ rows: [{ user_id: USER_ID, app_id: APP_ID, setting_name: null, setting_value: SETTING_VALUE }],
146
+ };
147
+ it('should return true', async () => {
148
+ cassandraDBHelpers.execute = jest.fn().mockResolvedValueOnce(mockResultSet);
149
+ cassandraDBHelpers.batch = jest.fn().mockReturnValueOnce(
150
+ new Promise((resolve) => {
151
+ resolve(mockResultSet);
152
+ }),
153
+ );
154
+ const response = await settingsRepo.deleteUserSettings(USER_ID);
155
+ expect(response).toBeDefined();
156
+ expect(response).toEqual(true);
157
+ });
158
+ it('should throw an error if the database errors out', async () => {
159
+ cassandraDBHelpers.execute = jest.fn().mockResolvedValueOnce(mockResultSet);
160
+ cassandraDBHelpers.batch = jest.fn().mockImplementationOnce(() => {
161
+ throw new Error('database error');
162
+ });
163
+ expect(settingsRepo.deleteUserSettings(INVALID_USER_ID)).rejects.toEqual(Error('database error'));
164
+ });
165
+ });
166
+
167
+ describe('get app settings', () => {
168
+ it('should return empty object while fetching new app_id', async () => {
169
+ const mockResultSet: any = {
170
+ rows: [],
171
+ };
172
+
173
+ cassandraDBHelpers.execute = jest
174
+ .fn()
175
+ .mockResolvedValueOnce(mockResultSet)
176
+ .mockResolvedValueOnce(mockResultSet);
177
+ // expect(await settingsRepo.getAppSettings(INVALID_APP_ID, undefined)).toEqual({});
178
+
179
+ expect(await settingsRepo.getAppSettings(INVALID_APP_ID, SETTING_NAME)).toEqual({});
180
+ });
181
+
182
+ it('should return settings for valid app_id', async () => {
183
+ const dbRecords = [
184
+ {
185
+ app_id: APP_ID,
186
+ setting_name: SETTING_NAME,
187
+ setting_default: SETTING_DEFAULT,
188
+ setting_options: SETTING_OPTIONS,
189
+ setting_type: 'string',
190
+ },
191
+ {
192
+ app_id: APP_ID,
193
+ setting_name: null,
194
+ setting_options: SETTING_OPTIONS,
195
+ setting_type: null,
196
+ },
197
+ ];
198
+ const mockResultSet: any = {
199
+ rows: dbRecords,
200
+ };
201
+
202
+ cassandraDBHelpers.execute = jest
203
+ .fn()
204
+ .mockResolvedValueOnce(mockResultSet)
205
+ .mockResolvedValueOnce(mockResultSet);
206
+
207
+ let appSettings = await settingsRepo.getAppSettings(APP_ID, undefined);
208
+ expect(appSettings).toBeDefined();
209
+ expect(appSettings[SETTING_NAME]).toEqual({
210
+ default: SETTING_DEFAULT,
211
+ options: SETTING_OPTIONS,
212
+ setting_type: 'string',
213
+ });
214
+
215
+ appSettings = await settingsRepo.getAppSettings(APP_ID, SETTING_NAME);
216
+ expect(appSettings).toBeDefined();
217
+ expect(appSettings[SETTING_NAME]).toEqual({
218
+ default: SETTING_DEFAULT,
219
+ options: SETTING_OPTIONS,
220
+ setting_type: 'string',
221
+ });
222
+ });
223
+
224
+ it('should return deprecated_values for valid app_id with deprecated_values object', async () => {
225
+ const dbRecords = [
226
+ {
227
+ app_id: APP_ID,
228
+ setting_name: SETTING_NAME,
229
+ setting_default: SETTING_DEFAULT,
230
+ setting_options: SETTING_OPTIONS,
231
+ setting_type: 'string',
232
+ deprecated_values: '{ "oldValue": "newValue"}',
233
+ },
234
+ {
235
+ app_id: APP_ID,
236
+ setting_name: null,
237
+ setting_options: SETTING_OPTIONS,
238
+ setting_type: null,
239
+ },
240
+ ];
241
+ const mockResultSet: any = {
242
+ rows: dbRecords,
243
+ };
244
+ cassandraDBHelpers.execute = jest.fn().mockResolvedValueOnce(mockResultSet);
245
+
246
+ const appSettings = await settingsRepo.getAppSettings(APP_ID, undefined);
247
+ expect(appSettings).toBeDefined();
248
+ expect(appSettings[SETTING_NAME].deprecated_values).toEqual({ oldValue: 'newValue' });
249
+ });
250
+
251
+ it('should not return deprecated_values for valid app_id with no deprecated values', async () => {
252
+ const dbRecords = [
253
+ {
254
+ app_id: APP_ID,
255
+ setting_name: SETTING_NAME,
256
+ setting_default: SETTING_DEFAULT,
257
+ setting_options: SETTING_OPTIONS,
258
+ setting_type: 'string',
259
+ },
260
+ {
261
+ app_id: APP_ID,
262
+ setting_name: null,
263
+ setting_options: SETTING_OPTIONS,
264
+ setting_type: null,
265
+ },
266
+ ];
267
+ const mockResultSet: any = {
268
+ rows: dbRecords,
269
+ };
270
+ cassandraDBHelpers.execute = jest.fn().mockReturnValueOnce(
271
+ new Promise((resolve) => {
272
+ resolve(mockResultSet);
273
+ }),
274
+ );
275
+
276
+ const appSettings = await settingsRepo.getAppSettings(APP_ID, undefined);
277
+ expect(appSettings[SETTING_NAME].deprecated_values).toBeUndefined();
278
+ });
279
+
280
+ it('should throw an error if the database errors out', async () => {
281
+ cassandraDBHelpers.execute = jest.fn().mockReturnValueOnce(Promise.reject(new Error('database error')));
282
+ expect(settingsRepo.getAppSettings(APP_ID, SETTING_NAME)).rejects.toEqual(
283
+ Error(`Error while reading getAppSettings`),
284
+ );
285
+ });
286
+ });
287
+
288
+ describe('update app settings', () => {
289
+ it('should return true if call works', async () => {
290
+ const mockResultSet: any = {
291
+ rows: [],
292
+ };
293
+
294
+ cassandraDBHelpers.execute = jest
295
+ .fn()
296
+ .mockResolvedValueOnce(mockResultSet)
297
+ .mockResolvedValueOnce(mockResultSet);
298
+ let response = await settingsRepo.updateAppSettings({
299
+ appId: APP_ID,
300
+ settingName: SETTING_NAME,
301
+ settingOptions: SETTING_OPTIONS,
302
+ });
303
+ expect(response).toBeDefined();
304
+ expect(response).toEqual(true);
305
+ response = await settingsRepo.updateAppSettings({
306
+ appId: APP_ID,
307
+ settingName: SETTING_NAME,
308
+ settingDefault: SETTING_DEFAULT,
309
+ settingOptions: SETTING_OPTIONS,
310
+ });
311
+ expect(response).toBeDefined();
312
+ expect(response).toEqual(true);
313
+ });
314
+
315
+ it('should return true if call works and has deprecated_values', async () => {
316
+ const mockResultSet: any = {
317
+ rows: [],
318
+ };
319
+ cassandraDBHelpers.execute = jest
320
+ .fn()
321
+ .mockResolvedValueOnce(mockResultSet)
322
+ .mockResolvedValueOnce(mockResultSet);
323
+ let response = await settingsRepo.updateAppSettings({
324
+ appId: APP_ID,
325
+ settingName: SETTING_NAME,
326
+ settingOptions: SETTING_OPTIONS,
327
+ deprecatedValues: '{ "oldValue": "newValue"}',
328
+ });
329
+ expect(response).toBeDefined();
330
+ expect(response).toEqual(true);
331
+ response = await settingsRepo.updateAppSettings({
332
+ appId: APP_ID,
333
+ settingName: SETTING_NAME,
334
+ settingDefault: SETTING_DEFAULT,
335
+ settingOptions: SETTING_OPTIONS,
336
+ });
337
+ expect(response).toBeDefined();
338
+ expect(response).toEqual(true);
339
+ });
340
+
341
+ it('should throw an error if the database errors out', async () => {
342
+ cassandraDBHelpers.execute = jest.fn().mockReturnValueOnce(Promise.reject(new Error('database error')));
343
+ expect(
344
+ settingsRepo.updateAppSettings({
345
+ appId: APP_ID,
346
+ settingName: 'null',
347
+ settingOptions: SETTING_OPTIONS,
348
+ }),
349
+ ).rejects.toEqual(Error(`Error while updating AppSettings`));
350
+ });
351
+ });
352
+
353
+ describe('delete app settings', () => {
354
+ it('should return true', async () => {
355
+ const mockResultSet: any = {
356
+ rows: [],
357
+ };
358
+
359
+ cassandraDBHelpers.execute = jest.fn().mockReturnValueOnce(
360
+ new Promise((resolve) => {
361
+ resolve(mockResultSet);
362
+ }),
363
+ );
364
+ const response = await settingsRepo.deleteAppSettings(APP_ID, SETTING_NAME);
365
+ expect(response).toBeDefined();
366
+ expect(response).toEqual(true);
367
+ });
368
+ it('should throw an error if the database errors out', async () => {
369
+ cassandraDBHelpers.execute = jest.fn().mockReturnValueOnce(Promise.reject(new Error('database error')));
370
+ expect(settingsRepo.deleteAppSettings(APP_ID, '')).rejects.toEqual(
371
+ Error(`Error while deleting AppSettings`),
372
+ );
373
+ });
374
+ });
375
+
376
+ describe('checkValueIsValidOption', () => {
377
+ const optionsArray = ['en', 'sk'];
378
+
379
+ it('returns true with valid array of inputs', () => {
380
+ const updatedValue = ['en', 'sk'];
381
+ expect(settingsRepo.checkValueIsValidOption(updatedValue, optionsArray)).toBeTruthy();
382
+ });
383
+
384
+ it('returns true with valid input string', () => {
385
+ const updatedValue = 'sk';
386
+
387
+ expect(settingsRepo.checkValueIsValidOption([updatedValue], optionsArray)).toBeTruthy();
388
+ });
389
+
390
+ it('returns false with array containing invalid value', () => {
391
+ const updatedValue = ['br', 'en'];
392
+
393
+ expect(settingsRepo.checkValueIsValidOption(updatedValue, optionsArray)).toBeFalsy();
394
+ });
395
+
396
+ it('returns false with invalid string value', () => {
397
+ const updatedValue = 'br';
398
+
399
+ expect(settingsRepo.checkValueIsValidOption([updatedValue], optionsArray));
400
+ });
401
+ });
402
+
403
+ describe('getUserSettings array value tests', () => {
404
+ const mockValue: AppSettingsResponse = {};
405
+ mockValue.secondaryLanguages = {
406
+ default: '',
407
+ options: ['en', 'sk', 'fr'],
408
+ setting_type: 'array',
409
+ deprecated_values: null,
410
+ };
411
+
412
+ it('can retrieve a value and return it as array', async () => {
413
+ const dbRecords = [
414
+ { user_id: USER_ID, app_id: APP_ID, setting_name: 'secondaryLanguages', setting_value: 'sk,en,fr' },
415
+ ];
416
+ const mockResultSet: any = {
417
+ rows: dbRecords,
418
+ };
419
+ settingsRepo.getAppSettings = jest.fn().mockReturnValueOnce(mockValue);
420
+ cassandraDBHelpers.execute = jest.fn().mockReturnValueOnce(
421
+ new Promise((resolve) => {
422
+ resolve(mockResultSet);
423
+ }),
424
+ );
425
+
426
+ const userSettings = await settingsRepo.getUserSettings(USER_ID, APP_ID);
427
+
428
+ expect(userSettings.secondaryLanguages).toEqual(['sk', 'en', 'fr']);
429
+ });
430
+
431
+ it('will return default value if one value of array is not a valid option', async () => {
432
+ const dbRecords = [
433
+ { user_id: USER_ID, app_id: APP_ID, setting_name: 'secondaryLanguages', setting_value: 'br,en,fr' },
434
+ ];
435
+ const mockResultSet: any = {
436
+ rows: dbRecords,
437
+ };
438
+ settingsRepo.getAppSettings = jest.fn().mockReturnValueOnce(mockValue);
439
+ cassandraDBHelpers.execute = jest.fn().mockReturnValueOnce(
440
+ new Promise((resolve) => {
441
+ resolve(mockResultSet);
442
+ }),
443
+ );
444
+ const userSettings = await settingsRepo.getUserSettings(USER_ID, APP_ID);
445
+ expect(userSettings.secondaryLanguages).toStrictEqual([]);
446
+ });
447
+ });
448
+
449
+ describe('fetchAndMapUserSettings secondaryLanguages tests', () => {
450
+ afterEach(() => {
451
+ jest.clearAllMocks();
452
+ });
453
+
454
+ it('calls UP when there is no secondaryLanguages value stored in the db', async () => {
455
+ const settingsDBRows = [
456
+ {
457
+ user_id: USER_ID,
458
+ app_id: 'general',
459
+ setting_name: 'primaryLanguage',
460
+ setting_value: 'fr',
461
+ },
462
+ ];
463
+ const getUnifiedProfileSpy = jest.spyOn(UP, 'getUnifiedProfile').mockResolvedValueOnce({
464
+ content: {
465
+ languages: ['French (Belgium)', 'English'],
466
+ },
467
+ } as ProfileResponse);
468
+
469
+ jest.spyOn(settingsRepo, 'updateUserSettings').mockResolvedValueOnce(true);
470
+ const result = await settingsRepo.fetchAndMapLanguageValues({
471
+ userId: USER_ID,
472
+ appId: 'general',
473
+ result: { primaryLanguage: 'fr' },
474
+ filter: languageAppSettings,
475
+ settingsDBRows,
476
+ });
477
+
478
+ expect(getUnifiedProfileSpy).toHaveBeenCalledTimes(1);
479
+ expect(result).toMatchObject({ secondaryLanguages: ['en'] });
480
+ });
481
+ it('stores retrieved UP secondaryLanguages values in db', async () => {
482
+ const settingsDBRows = [
483
+ {
484
+ user_id: USER_ID,
485
+ app_id: 'general',
486
+ setting_name: 'primaryLanguage',
487
+ setting_value: 'fr',
488
+ },
489
+ ];
490
+ const getUnifiedProfileSpy = jest.spyOn(UP, 'getUnifiedProfile').mockResolvedValueOnce({
491
+ content: {
492
+ languages: ['French (Belgium)', 'English'],
493
+ },
494
+ } as ProfileResponse);
495
+
496
+ const updateSpy = jest.spyOn(settingsRepo, 'updateUserSettings').mockResolvedValueOnce(true);
497
+ await settingsRepo.fetchAndMapLanguageValues({
498
+ userId: USER_ID,
499
+ appId: 'general',
500
+ result: { primaryLanguage: 'fr' },
501
+ filter: languageAppSettings,
502
+ settingsDBRows,
503
+ });
504
+
505
+ expect(updateSpy).toHaveBeenCalledTimes(1);
506
+ expect(updateSpy).toHaveBeenCalledWith(USER_ID, 'general', 'secondaryLanguages', 'en');
507
+ expect(getUnifiedProfileSpy).toHaveBeenCalled();
508
+ });
509
+ it('stores empty string when no secondary languages retrieved from UP', async () => {
510
+ const settingsDBRows = [
511
+ {
512
+ user_id: USER_ID,
513
+ app_id: 'general',
514
+ setting_name: 'primaryLanguage',
515
+ setting_value: 'fr',
516
+ },
517
+ ];
518
+ jest.spyOn(UP, 'getUnifiedProfile').mockResolvedValueOnce({ content: {} } as ProfileResponse);
519
+
520
+ const updateSpy = jest.spyOn(settingsRepo, 'updateUserSettings').mockResolvedValueOnce(true);
521
+ await settingsRepo.fetchAndMapLanguageValues({
522
+ userId: USER_ID,
523
+ appId: 'general',
524
+ result: { primaryLanguage: 'fr' },
525
+ filter: languageAppSettings,
526
+ settingsDBRows,
527
+ });
528
+
529
+ expect(updateSpy).toHaveBeenCalledTimes(1);
530
+ expect(updateSpy).toHaveBeenCalledWith(USER_ID, 'general', 'secondaryLanguages', '');
531
+ });
532
+ it('does not set secondaryLanguages if value already exists in result', async () => {
533
+ const settingsDBRows = [
534
+ {
535
+ user_id: USER_ID,
536
+ app_id: 'general',
537
+ setting_name: 'secondaryLanguages',
538
+ setting_value: 'sk,fr',
539
+ },
540
+ ];
541
+ const UPSpy = jest.spyOn(UP, 'getUnifiedProfile');
542
+
543
+ const updateSpy = jest.spyOn(settingsRepo, 'updateUserSettings').mockResolvedValueOnce(true);
544
+ await settingsRepo.fetchAndMapLanguageValues({
545
+ userId: USER_ID,
546
+ appId: 'general',
547
+ result: { secondaryLanguages: 'sk,fr', primaryLanguage: 'en' },
548
+ filter: languageAppSettings,
549
+ settingsDBRows,
550
+ });
551
+
552
+ expect(UPSpy).not.toHaveBeenCalled();
553
+ expect(updateSpy).not.toHaveBeenCalled();
554
+ });
555
+ });
556
+
557
+ describe('transormAndUpdateDeprecatedValues', () => {
558
+ afterEach(() => {
559
+ jest.clearAllMocks();
560
+ });
561
+ it('returns new value if value argument was in deprecated list', () => {
562
+ const returnedValue = settingsRepo.transformAndUpdateDeprecatedValues(
563
+ { GBS: 'IBM Consulting' },
564
+ {
565
+ setting_value: 'GBS',
566
+ setting_name: 'secondaryBusinessUnits',
567
+ user_id: TEST_USER_ID,
568
+ app_id: TEST_APP_ID,
569
+ },
570
+ );
571
+
572
+ jest.spyOn(settingsRepo, 'updateUserSettings').mockResolvedValueOnce(true);
573
+
574
+ expect(returnedValue).toBe('IBM Consulting');
575
+ });
576
+
577
+ it('stores new value to db if old value in deprecated list', () => {
578
+ settingsRepo.transformAndUpdateDeprecatedValues(
579
+ { GBS: 'IBM Consulting' },
580
+ {
581
+ setting_value: 'GBS',
582
+ setting_name: 'secondaryBusinessUnits',
583
+ user_id: TEST_USER_ID,
584
+ app_id: TEST_APP_ID,
585
+ },
586
+ );
587
+
588
+ const updateSettingsSpy = jest.spyOn(settingsRepo, 'updateUserSettings').mockResolvedValueOnce(true);
589
+
590
+ expect(updateSettingsSpy).toHaveBeenCalledTimes(1);
591
+ expect(updateSettingsSpy).toHaveBeenCalledWith(
592
+ TEST_USER_ID,
593
+ TEST_APP_ID,
594
+ 'secondaryBusinessUnits',
595
+ 'IBM Consulting',
596
+ );
597
+ });
598
+
599
+ it('returns original value if value not in deprecated list', () => {
600
+ const returnedValue = settingsRepo.transformAndUpdateDeprecatedValues(
601
+ { GBS: 'IBM Consulting' },
602
+ {
603
+ setting_value: 'F&O',
604
+ setting_name: 'secondaryBusinessUnits',
605
+ user_id: TEST_USER_ID,
606
+ app_id: TEST_APP_ID,
607
+ },
608
+ );
609
+
610
+ jest.spyOn(settingsRepo, 'updateUserSettings').mockResolvedValueOnce(true);
611
+
612
+ expect(returnedValue).toBe('F&O');
613
+ });
614
+ });
@@ -0,0 +1,31 @@
1
+ import UnifiedProfileClient from '../../../unified-profile/UnifiedProfileClient';
2
+ import { ProfileResponse } from '../../../types/unifiedProfileTypes';
3
+
4
+ const TEST_PROFILE: ProfileResponse = {
5
+ content: { c: 'us', languages: ['en', 'fr'], preferredLanguage: 'English' },
6
+ };
7
+ const UP_CLIENT = new UnifiedProfileClient();
8
+ const TEST_USER_ID = '123456789';
9
+
10
+ describe('UnifiedProfileClient', () => {
11
+ it('getProfile should get user profile from Unified Profile', async () => {
12
+ const getSpy = jest.spyOn(UP_CLIENT.client, 'get').mockResolvedValueOnce({ data: TEST_PROFILE });
13
+
14
+ const resp = await UP_CLIENT.getProfile(TEST_USER_ID);
15
+
16
+ expect(getSpy).toHaveBeenCalled();
17
+ expect(resp).toBeDefined();
18
+ expect(resp?.content.c).toBe('us');
19
+ expect(resp?.content.languages).toStrictEqual(['en', 'fr']);
20
+ expect(resp?.content.preferredLanguage).toBe('English');
21
+ });
22
+
23
+ it('should return undefined if Error getting user profile', async () => {
24
+ const getSpy = jest.spyOn(UP_CLIENT.client, 'get').mockRejectedValueOnce(new Error());
25
+
26
+ const resp = await UP_CLIENT.getProfile(TEST_USER_ID);
27
+
28
+ expect(getSpy).toHaveBeenCalled();
29
+ expect(resp).toBeUndefined();
30
+ });
31
+ });
@@ -0,0 +1,36 @@
1
+ import UnifiedProfileClient from '../../../unified-profile/UnifiedProfileClient';
2
+ import { ProfileResponse } from '../../../types/unifiedProfileTypes';
3
+ import { getUnifiedProfile } from '../../../unified-profile/unifiedProfileUtils';
4
+
5
+ const TEST_USER_ID = '123456789';
6
+ const TEST_PROFILE: ProfileResponse = {
7
+ content: { c: 'us', languages: ['en', 'fr'], preferredLanguage: 'English' },
8
+ };
9
+
10
+ describe('getUnifiedProfileBackup', () => {
11
+ it('should call UnifiedProfileClient to get user isoCode', async () => {
12
+ const upGetSpy = jest
13
+ .spyOn(UnifiedProfileClient.prototype, 'getProfile')
14
+ .mockResolvedValueOnce(TEST_PROFILE);
15
+
16
+ const resp = await getUnifiedProfile(TEST_USER_ID);
17
+
18
+ expect(upGetSpy).toHaveBeenCalled();
19
+ expect(upGetSpy).toHaveBeenCalledWith(TEST_USER_ID);
20
+ expect(resp).toBeDefined();
21
+ expect(resp?.content.c).toBe('us');
22
+ expect(resp?.content.languages).toStrictEqual(['en', 'fr']);
23
+ expect(resp?.content.preferredLanguage).toBe('English');
24
+ });
25
+
26
+ it('should return undefined when getProfile returns undefined', async () => {
27
+ const upGetSpy = jest
28
+ .spyOn(UnifiedProfileClient.prototype, 'getProfile')
29
+ .mockResolvedValueOnce(undefined);
30
+
31
+ const resp = await getUnifiedProfile(TEST_USER_ID);
32
+
33
+ expect(upGetSpy).toHaveBeenCalled();
34
+ expect(resp).toBeUndefined();
35
+ });
36
+ });