@webex/contact-center 3.12.0-task-refactor.12 → 3.12.0-webex-services-ready.1
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.
- package/dist/cc.js +32 -0
- package/dist/cc.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/metrics/behavioral-events.js +49 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +10 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/UserPreference.js +427 -0
- package/dist/services/UserPreference.js.map +1 -0
- package/dist/services/config/constants.js +22 -1
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/types.js +20 -0
- package/dist/services/config/types.js.map +1 -1
- package/dist/types/cc.d.ts +31 -0
- package/dist/types/index.d.ts +10 -1
- package/dist/types/metrics/constants.d.ts +8 -0
- package/dist/types/services/UserPreference.d.ts +118 -0
- package/dist/types/services/config/constants.d.ts +21 -0
- package/dist/types/services/config/types.d.ts +48 -0
- package/dist/types.js.map +1 -1
- package/dist/webex.js +1 -1
- package/package.json +9 -9
- package/src/cc.ts +33 -0
- package/src/index.ts +9 -0
- package/src/metrics/behavioral-events.ts +50 -0
- package/src/metrics/constants.ts +10 -0
- package/src/services/UserPreference.ts +509 -0
- package/src/services/config/constants.ts +24 -0
- package/src/services/config/types.ts +52 -0
- package/src/types.ts +9 -2
- package/test/unit/spec/cc.ts +1 -6
- package/test/unit/spec/services/UserPreference.ts +401 -0
- package/test/unit/spec/services/core/Utils.ts +1 -1
- package/test/unit/spec/services/core/websocket/WebSocketManager.ts +1 -0
- package/test/unit/spec/services/task/TaskManager.ts +143 -2316
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import {expect} from '@jest/globals';
|
|
2
|
+
import UserPreference from '../../../../src/services/UserPreference';
|
|
3
|
+
import {HTTP_METHODS, WebexSDK, IHttpResponse} from '../../../../src/types';
|
|
4
|
+
import {METRIC_EVENT_NAMES} from '../../../../src/metrics/constants';
|
|
5
|
+
import WebexRequest from '../../../../src/services/core/WebexRequest';
|
|
6
|
+
import MetricsManager from '../../../../src/metrics/MetricsManager';
|
|
7
|
+
import LoggerProxy from '../../../../src/logger-proxy';
|
|
8
|
+
|
|
9
|
+
jest.mock('../../../../src/metrics/MetricsManager');
|
|
10
|
+
jest.mock('../../../../src/logger-proxy');
|
|
11
|
+
|
|
12
|
+
describe('UserPreference', () => {
|
|
13
|
+
let userPreferenceAPI: UserPreference;
|
|
14
|
+
let mockWebex: WebexSDK;
|
|
15
|
+
let mockMetricsManager: jest.Mocked<MetricsManager>;
|
|
16
|
+
|
|
17
|
+
const mockGetUserId = jest.fn().mockReturnValue('test-user-id');
|
|
18
|
+
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
jest.clearAllMocks();
|
|
21
|
+
(WebexRequest as any).instance = undefined;
|
|
22
|
+
|
|
23
|
+
mockWebex = {
|
|
24
|
+
credentials: {
|
|
25
|
+
getOrgId: jest.fn().mockReturnValue('test-org-id'),
|
|
26
|
+
},
|
|
27
|
+
request: jest.fn(),
|
|
28
|
+
internal: {
|
|
29
|
+
newMetrics: {
|
|
30
|
+
submitBehavioralEvent: jest.fn(),
|
|
31
|
+
submitOperationalEvent: jest.fn(),
|
|
32
|
+
submitBusinessEvent: jest.fn(),
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
ready: true,
|
|
36
|
+
once: jest.fn(),
|
|
37
|
+
} as unknown as WebexSDK;
|
|
38
|
+
|
|
39
|
+
mockMetricsManager = {
|
|
40
|
+
trackEvent: jest.fn(),
|
|
41
|
+
timeEvent: jest.fn(),
|
|
42
|
+
} as unknown as jest.Mocked<MetricsManager>;
|
|
43
|
+
(MetricsManager.getInstance as jest.Mock).mockReturnValue(mockMetricsManager);
|
|
44
|
+
|
|
45
|
+
userPreferenceAPI = new UserPreference(mockWebex, mockGetUserId);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('constructor', () => {
|
|
49
|
+
it('should initialize with all required dependencies', () => {
|
|
50
|
+
expect(WebexRequest.getInstance({webex: mockWebex})).toBeDefined();
|
|
51
|
+
expect(MetricsManager.getInstance).toHaveBeenCalledWith({webex: mockWebex});
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe('getUserPreference', () => {
|
|
56
|
+
const mockPreference = {
|
|
57
|
+
id: 'pref-123',
|
|
58
|
+
organizationId: 'test-org-id',
|
|
59
|
+
userId: 'test-user-id',
|
|
60
|
+
preferences: {e911Reminder: true},
|
|
61
|
+
createdTime: 1234567890,
|
|
62
|
+
lastUpdatedTime: 1234567890,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const mockResponse: IHttpResponse = {
|
|
66
|
+
statusCode: 200,
|
|
67
|
+
method: 'GET',
|
|
68
|
+
url: '/organization/test-org-id/user-preference/test-user-id',
|
|
69
|
+
headers: {} as any,
|
|
70
|
+
body: mockPreference,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
beforeEach(() => {
|
|
74
|
+
jest.spyOn(Date, 'now').mockReturnValue(1000);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
afterEach(() => {
|
|
78
|
+
jest.restoreAllMocks();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('should fetch user preferences successfully with default userId', async () => {
|
|
82
|
+
(mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
|
|
83
|
+
|
|
84
|
+
const result = await userPreferenceAPI.getUserPreference();
|
|
85
|
+
|
|
86
|
+
expect(mockWebex.request).toHaveBeenCalledWith({
|
|
87
|
+
service: 'wcc-api-gateway',
|
|
88
|
+
resource: 'organization/test-org-id/user-preference/test-user-id',
|
|
89
|
+
method: HTTP_METHODS.GET,
|
|
90
|
+
body: undefined,
|
|
91
|
+
});
|
|
92
|
+
expect(result).toEqual(mockPreference);
|
|
93
|
+
expect(mockMetricsManager.timeEvent).toHaveBeenCalledWith(
|
|
94
|
+
METRIC_EVENT_NAMES.USER_PREFERENCE_GET_SUCCESS
|
|
95
|
+
);
|
|
96
|
+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
|
|
97
|
+
METRIC_EVENT_NAMES.USER_PREFERENCE_GET_SUCCESS,
|
|
98
|
+
expect.objectContaining({
|
|
99
|
+
orgId: 'test-org-id',
|
|
100
|
+
userId: 'test-user-id',
|
|
101
|
+
statusCode: 200,
|
|
102
|
+
}),
|
|
103
|
+
['behavioral', 'operational']
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should fetch user preferences for a specific userId', async () => {
|
|
108
|
+
(mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
|
|
109
|
+
|
|
110
|
+
const result = await userPreferenceAPI.getUserPreference({userId: 'specific-user-id'});
|
|
111
|
+
|
|
112
|
+
expect(mockWebex.request).toHaveBeenCalledWith({
|
|
113
|
+
service: 'wcc-api-gateway',
|
|
114
|
+
resource: 'organization/test-org-id/user-preference/specific-user-id',
|
|
115
|
+
method: HTTP_METHODS.GET,
|
|
116
|
+
body: undefined,
|
|
117
|
+
});
|
|
118
|
+
expect(result).toEqual(mockPreference);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('should fetch user preferences with pagination parameters', async () => {
|
|
122
|
+
(mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
|
|
123
|
+
|
|
124
|
+
const result = await userPreferenceAPI.getUserPreference({page: 1, pageSize: 50});
|
|
125
|
+
|
|
126
|
+
expect(mockWebex.request).toHaveBeenCalledWith({
|
|
127
|
+
service: 'wcc-api-gateway',
|
|
128
|
+
resource: 'organization/test-org-id/user-preference/test-user-id?page=1&pageSize=50',
|
|
129
|
+
method: HTTP_METHODS.GET,
|
|
130
|
+
body: undefined,
|
|
131
|
+
});
|
|
132
|
+
expect(result).toEqual(mockPreference);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should throw error when userId is not available', async () => {
|
|
136
|
+
mockGetUserId.mockReturnValueOnce('');
|
|
137
|
+
|
|
138
|
+
await expect(userPreferenceAPI.getUserPreference()).rejects.toThrow(
|
|
139
|
+
'UserPreference: userId is not available.'
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
expect(mockMetricsManager.trackEvent).not.toHaveBeenCalled();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('should handle API errors', async () => {
|
|
146
|
+
const mockError = new Error('API call failed');
|
|
147
|
+
(mockWebex.request as jest.Mock).mockRejectedValue(mockError);
|
|
148
|
+
|
|
149
|
+
await expect(userPreferenceAPI.getUserPreference()).rejects.toThrow('API call failed');
|
|
150
|
+
|
|
151
|
+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
|
|
152
|
+
METRIC_EVENT_NAMES.USER_PREFERENCE_GET_FAILED,
|
|
153
|
+
expect.objectContaining({
|
|
154
|
+
error: 'API call failed',
|
|
155
|
+
}),
|
|
156
|
+
['behavioral', 'operational']
|
|
157
|
+
);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe('createUserPreference', () => {
|
|
162
|
+
const mockCreateRequest = {
|
|
163
|
+
userId: 'test-user-id',
|
|
164
|
+
desktopPreference: '{}',
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const mockCreatedPreference = {
|
|
168
|
+
id: 'pref-123',
|
|
169
|
+
organizationId: 'test-org-id',
|
|
170
|
+
userId: 'test-user-id',
|
|
171
|
+
preferences: {e911Reminder: true},
|
|
172
|
+
createdTime: 1234567890,
|
|
173
|
+
lastUpdatedTime: 1234567890,
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const mockResponse: IHttpResponse = {
|
|
177
|
+
statusCode: 201,
|
|
178
|
+
method: 'POST',
|
|
179
|
+
url: '/organization/test-org-id/user-preference',
|
|
180
|
+
headers: {} as any,
|
|
181
|
+
body: mockCreatedPreference,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
beforeEach(() => {
|
|
185
|
+
jest.spyOn(Date, 'now').mockReturnValue(1000);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
afterEach(() => {
|
|
189
|
+
jest.restoreAllMocks();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('should create user preferences successfully', async () => {
|
|
193
|
+
(mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
|
|
194
|
+
|
|
195
|
+
const result = await userPreferenceAPI.createUserPreference(mockCreateRequest);
|
|
196
|
+
|
|
197
|
+
expect(mockWebex.request).toHaveBeenCalledWith({
|
|
198
|
+
service: 'wcc-api-gateway',
|
|
199
|
+
resource: 'organization/test-org-id/user-preference',
|
|
200
|
+
method: HTTP_METHODS.POST,
|
|
201
|
+
body: mockCreateRequest,
|
|
202
|
+
});
|
|
203
|
+
expect(result).toEqual(mockCreatedPreference);
|
|
204
|
+
expect(mockMetricsManager.timeEvent).toHaveBeenCalledWith(
|
|
205
|
+
METRIC_EVENT_NAMES.USER_PREFERENCE_CREATE_SUCCESS
|
|
206
|
+
);
|
|
207
|
+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
|
|
208
|
+
METRIC_EVENT_NAMES.USER_PREFERENCE_CREATE_SUCCESS,
|
|
209
|
+
expect.objectContaining({
|
|
210
|
+
orgId: 'test-org-id',
|
|
211
|
+
userId: 'test-user-id',
|
|
212
|
+
statusCode: 201,
|
|
213
|
+
}),
|
|
214
|
+
['behavioral', 'operational']
|
|
215
|
+
);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('should throw error when userId is missing in request', async () => {
|
|
219
|
+
const invalidRequest = {
|
|
220
|
+
userId: '',
|
|
221
|
+
desktopPreference: '{}',
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
await expect(userPreferenceAPI.createUserPreference(invalidRequest)).rejects.toThrow(
|
|
225
|
+
'UserPreference: userId is required to create user preferences.'
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
expect(mockMetricsManager.trackEvent).not.toHaveBeenCalled();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('should handle API errors', async () => {
|
|
232
|
+
const mockError = new Error('API call failed');
|
|
233
|
+
(mockWebex.request as jest.Mock).mockRejectedValue(mockError);
|
|
234
|
+
|
|
235
|
+
await expect(userPreferenceAPI.createUserPreference(mockCreateRequest)).rejects.toThrow(
|
|
236
|
+
'API call failed'
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
|
|
240
|
+
METRIC_EVENT_NAMES.USER_PREFERENCE_CREATE_FAILED,
|
|
241
|
+
expect.objectContaining({
|
|
242
|
+
error: 'API call failed',
|
|
243
|
+
}),
|
|
244
|
+
['behavioral', 'operational']
|
|
245
|
+
);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
describe('updateUserPreference', () => {
|
|
250
|
+
const mockUpdateRequest = {
|
|
251
|
+
desktopPreference: '{}',
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const mockUpdatedPreference = {
|
|
255
|
+
id: 'pref-123',
|
|
256
|
+
organizationId: 'test-org-id',
|
|
257
|
+
userId: 'test-user-id',
|
|
258
|
+
preferences: {e911Reminder: false},
|
|
259
|
+
createdTime: 1234567890,
|
|
260
|
+
lastUpdatedTime: 1234567899,
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const mockResponse: IHttpResponse = {
|
|
264
|
+
statusCode: 200,
|
|
265
|
+
method: 'PUT',
|
|
266
|
+
url: '/organization/test-org-id/user-preference/test-user-id',
|
|
267
|
+
headers: {} as any,
|
|
268
|
+
body: mockUpdatedPreference,
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
beforeEach(() => {
|
|
272
|
+
jest.spyOn(Date, 'now').mockReturnValue(1000);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
afterEach(() => {
|
|
276
|
+
jest.restoreAllMocks();
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('should update user preferences successfully', async () => {
|
|
280
|
+
(mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
|
|
281
|
+
|
|
282
|
+
const result = await userPreferenceAPI.updateUserPreference(
|
|
283
|
+
'test-user-id',
|
|
284
|
+
mockUpdateRequest
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
expect(mockWebex.request).toHaveBeenCalledWith({
|
|
288
|
+
service: 'wcc-api-gateway',
|
|
289
|
+
resource: 'organization/test-org-id/user-preference/test-user-id',
|
|
290
|
+
method: HTTP_METHODS.PUT,
|
|
291
|
+
body: mockUpdateRequest,
|
|
292
|
+
});
|
|
293
|
+
expect(result).toEqual(mockUpdatedPreference);
|
|
294
|
+
expect(mockMetricsManager.timeEvent).toHaveBeenCalledWith(
|
|
295
|
+
METRIC_EVENT_NAMES.USER_PREFERENCE_UPDATE_SUCCESS
|
|
296
|
+
);
|
|
297
|
+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
|
|
298
|
+
METRIC_EVENT_NAMES.USER_PREFERENCE_UPDATE_SUCCESS,
|
|
299
|
+
expect.objectContaining({
|
|
300
|
+
orgId: 'test-org-id',
|
|
301
|
+
userId: 'test-user-id',
|
|
302
|
+
statusCode: 200,
|
|
303
|
+
}),
|
|
304
|
+
['behavioral', 'operational']
|
|
305
|
+
);
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('should throw error when userId is missing', async () => {
|
|
309
|
+
await expect(userPreferenceAPI.updateUserPreference('', mockUpdateRequest)).rejects.toThrow(
|
|
310
|
+
'UserPreference: userId is required to update user preferences.'
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
expect(mockMetricsManager.trackEvent).not.toHaveBeenCalled();
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('should handle API errors', async () => {
|
|
317
|
+
const mockError = new Error('API call failed');
|
|
318
|
+
(mockWebex.request as jest.Mock).mockRejectedValue(mockError);
|
|
319
|
+
|
|
320
|
+
await expect(
|
|
321
|
+
userPreferenceAPI.updateUserPreference('test-user-id', mockUpdateRequest)
|
|
322
|
+
).rejects.toThrow('API call failed');
|
|
323
|
+
|
|
324
|
+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
|
|
325
|
+
METRIC_EVENT_NAMES.USER_PREFERENCE_UPDATE_FAILED,
|
|
326
|
+
expect.objectContaining({
|
|
327
|
+
error: 'API call failed',
|
|
328
|
+
}),
|
|
329
|
+
['behavioral', 'operational']
|
|
330
|
+
);
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
describe('deleteUserPreference', () => {
|
|
335
|
+
const mockResponse: IHttpResponse = {
|
|
336
|
+
statusCode: 204,
|
|
337
|
+
method: 'DELETE',
|
|
338
|
+
url: '/organization/test-org-id/user-preference/test-user-id',
|
|
339
|
+
headers: {} as any,
|
|
340
|
+
body: null,
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
beforeEach(() => {
|
|
344
|
+
jest.spyOn(Date, 'now').mockReturnValue(1000);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
afterEach(() => {
|
|
348
|
+
jest.restoreAllMocks();
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it('should delete user preferences successfully', async () => {
|
|
352
|
+
(mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
|
|
353
|
+
|
|
354
|
+
await userPreferenceAPI.deleteUserPreference('test-user-id');
|
|
355
|
+
|
|
356
|
+
expect(mockWebex.request).toHaveBeenCalledWith({
|
|
357
|
+
service: 'wcc-api-gateway',
|
|
358
|
+
resource: 'organization/test-org-id/user-preference/test-user-id',
|
|
359
|
+
method: HTTP_METHODS.DELETE,
|
|
360
|
+
body: undefined,
|
|
361
|
+
});
|
|
362
|
+
expect(mockMetricsManager.timeEvent).toHaveBeenCalledWith(
|
|
363
|
+
METRIC_EVENT_NAMES.USER_PREFERENCE_DELETE_SUCCESS
|
|
364
|
+
);
|
|
365
|
+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
|
|
366
|
+
METRIC_EVENT_NAMES.USER_PREFERENCE_DELETE_SUCCESS,
|
|
367
|
+
expect.objectContaining({
|
|
368
|
+
orgId: 'test-org-id',
|
|
369
|
+
userId: 'test-user-id',
|
|
370
|
+
statusCode: 204,
|
|
371
|
+
}),
|
|
372
|
+
['behavioral', 'operational']
|
|
373
|
+
);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it('should throw error when userId is missing', async () => {
|
|
377
|
+
await expect(userPreferenceAPI.deleteUserPreference('')).rejects.toThrow(
|
|
378
|
+
'UserPreference: userId is required to delete user preferences.'
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
expect(mockMetricsManager.trackEvent).not.toHaveBeenCalled();
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it('should handle API errors', async () => {
|
|
385
|
+
const mockError = new Error('API call failed');
|
|
386
|
+
(mockWebex.request as jest.Mock).mockRejectedValue(mockError);
|
|
387
|
+
|
|
388
|
+
await expect(userPreferenceAPI.deleteUserPreference('test-user-id')).rejects.toThrow(
|
|
389
|
+
'API call failed'
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
|
|
393
|
+
METRIC_EVENT_NAMES.USER_PREFERENCE_DELETE_FAILED,
|
|
394
|
+
expect.objectContaining({
|
|
395
|
+
error: 'API call failed',
|
|
396
|
+
}),
|
|
397
|
+
['behavioral', 'operational']
|
|
398
|
+
);
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
});
|
|
@@ -865,7 +865,7 @@ describe('Utils', () => {
|
|
|
865
865
|
};
|
|
866
866
|
|
|
867
867
|
const result = Utils.calculateDestAgentId(interaction, currentAgentId);
|
|
868
|
-
expect(result).
|
|
868
|
+
expect(result).toBe('');
|
|
869
869
|
});
|
|
870
870
|
|
|
871
871
|
it('should handle CBT scenario when phone number is not a direct participant key', () => {
|