@webex/contact-center 3.12.0-next.158 → 3.12.0-next.159

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.
Files changed (41) hide show
  1. package/ai-docs/contact-center-spec.md +3 -0
  2. package/dist/cc.js +10 -2
  3. package/dist/cc.js.map +1 -1
  4. package/dist/services/ApiAiAssistant.js +18 -0
  5. package/dist/services/ApiAiAssistant.js.map +1 -1
  6. package/dist/services/WebCallingService.js +10 -2
  7. package/dist/services/WebCallingService.js.map +1 -1
  8. package/dist/services/constants.js +11 -1
  9. package/dist/services/constants.js.map +1 -1
  10. package/dist/services/core/Utils.js +21 -1
  11. package/dist/services/core/Utils.js.map +1 -1
  12. package/dist/services/core/aqm-reqs.js +7 -15
  13. package/dist/services/core/aqm-reqs.js.map +1 -1
  14. package/dist/services/core/constants.js +9 -1
  15. package/dist/services/core/constants.js.map +1 -1
  16. package/dist/services/core/websocket/WebSocketManager.js +17 -1
  17. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  18. package/dist/types/services/ApiAiAssistant.d.ts +9 -0
  19. package/dist/types/services/constants.d.ts +9 -0
  20. package/dist/types/services/core/Utils.d.ts +8 -0
  21. package/dist/types/services/core/constants.d.ts +7 -0
  22. package/dist/webex.js +1 -1
  23. package/package.json +1 -1
  24. package/src/cc.ts +15 -2
  25. package/src/services/ApiAiAssistant.ts +24 -0
  26. package/src/services/WebCallingService.ts +16 -2
  27. package/src/services/ai-docs/services-spec.md +8 -1
  28. package/src/services/constants.ts +10 -0
  29. package/src/services/core/Utils.ts +24 -0
  30. package/src/services/core/ai-docs/core-spec.md +23 -13
  31. package/src/services/core/aqm-reqs.ts +6 -15
  32. package/src/services/core/constants.ts +8 -0
  33. package/src/services/core/websocket/WebSocketManager.ts +26 -2
  34. package/test/unit/spec/cc.ts +21 -0
  35. package/test/unit/spec/services/ApiAiAssistant.ts +13 -0
  36. package/test/unit/spec/services/WebCallingService.ts +38 -0
  37. package/test/unit/spec/services/core/Utils.ts +22 -0
  38. package/test/unit/spec/services/core/aqm-reqs.ts +29 -0
  39. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +64 -14
  40. package/umd/contact-center.min.js +2 -2
  41. package/umd/contact-center.min.js.map +1 -1
@@ -94,7 +94,9 @@ describe('WebSocketManager', () => {
94
94
  };
95
95
 
96
96
  global.Worker = jest.fn(() => mockWorker) as any;
97
- global.WebSocket = MockWebSocket as any;
97
+ global.WebSocket = jest.fn(function (this: any, ...args: any[]) {
98
+ return new MockWebSocket(...(args as []));
99
+ }) as any;
98
100
 
99
101
  global.Blob = function (content: any[], options: any) {
100
102
  return {content, options};
@@ -119,10 +121,58 @@ describe('WebSocketManager', () => {
119
121
  expect(webSocketManager).toBeDefined();
120
122
  });
121
123
 
124
+ describe('webSocketUrl validation', () => {
125
+ it('rejects a non-wss webSocketUrl and does not construct a socket', async () => {
126
+ const subscribeResponse = {
127
+ body: {
128
+ webSocketUrl: 'http://fake-url.cisco.com',
129
+ },
130
+ };
131
+
132
+ (mockWebex.request as jest.Mock).mockResolvedValueOnce(subscribeResponse);
133
+
134
+ await expect(
135
+ webSocketManager.initWebSocket({body: fakeSubscribeRequest, resource: SUBSCRIBE_API})
136
+ ).rejects.toBeDefined();
137
+
138
+ expect(global.WebSocket).not.toHaveBeenCalled();
139
+ });
140
+
141
+ it('rejects a wss webSocketUrl with a non-allow-listed host and does not construct a socket', async () => {
142
+ const subscribeResponse = {
143
+ body: {
144
+ webSocketUrl: 'wss://evil.attacker.com',
145
+ },
146
+ };
147
+
148
+ (mockWebex.request as jest.Mock).mockResolvedValueOnce(subscribeResponse);
149
+
150
+ await expect(
151
+ webSocketManager.initWebSocket({body: fakeSubscribeRequest, resource: SUBSCRIBE_API})
152
+ ).rejects.toBeDefined();
153
+
154
+ expect(global.WebSocket).not.toHaveBeenCalled();
155
+ });
156
+
157
+ it('connects for a valid wss allow-listed webSocketUrl', async () => {
158
+ const subscribeResponse = {
159
+ body: {
160
+ webSocketUrl: 'wss://notifs.wxcc-us1.cisco.com',
161
+ },
162
+ };
163
+
164
+ (mockWebex.request as jest.Mock).mockResolvedValueOnce(subscribeResponse);
165
+
166
+ await webSocketManager.initWebSocket({body: fakeSubscribeRequest, resource: SUBSCRIBE_API});
167
+
168
+ expect(global.WebSocket).toHaveBeenCalledWith('wss://notifs.wxcc-us1.cisco.com');
169
+ });
170
+ });
171
+
122
172
  it('should register and connect to WebSocket with X-ORGANIZATION-ID header for INT environment', async () => {
123
173
  const subscribeResponse = {
124
174
  body: {
125
- webSocketUrl: 'wss://fake-url',
175
+ webSocketUrl: 'wss://fake-url.cisco.com',
126
176
  },
127
177
  };
128
178
 
@@ -144,7 +194,7 @@ describe('WebSocketManager', () => {
144
194
  it('should connect rtd websocket', async () => {
145
195
  const subscribeResponse = {
146
196
  body: {
147
- webSocketUrl: 'wss://fake-url',
197
+ webSocketUrl: 'wss://fake-url.cisco.com',
148
198
  },
149
199
  };
150
200
 
@@ -167,7 +217,7 @@ describe('WebSocketManager', () => {
167
217
  it('should register and connect to WebSocket without X-ORGANIZATION-ID header for production environment', async () => {
168
218
  const subscribeResponse = {
169
219
  body: {
170
- webSocketUrl: 'wss://fake-url',
220
+ webSocketUrl: 'wss://fake-url.cisco.com',
171
221
  },
172
222
  };
173
223
  // Mock production environment (services.isIntegrationEnvironment returns false)
@@ -196,7 +246,7 @@ it('should register and connect to WebSocket without X-ORGANIZATION-ID header fo
196
246
  it('should not send X-ORGANIZATION-ID header when services.isIntegrationEnvironment is not available', async () => {
197
247
  const subscribeResponse = {
198
248
  body: {
199
- webSocketUrl: 'wss://fake-url',
249
+ webSocketUrl: 'wss://fake-url.cisco.com',
200
250
  },
201
251
  };
202
252
 
@@ -245,7 +295,7 @@ it('should register and connect to WebSocket without X-ORGANIZATION-ID header fo
245
295
  it('should close WebSocket connection', async () => {
246
296
  const subscribeResponse = {
247
297
  body: {
248
- webSocketUrl: 'wss://fake-url',
298
+ webSocketUrl: 'wss://fake-url.cisco.com',
249
299
  },
250
300
  };
251
301
 
@@ -262,7 +312,7 @@ it('should register and connect to WebSocket without X-ORGANIZATION-ID header fo
262
312
  it('should handle WebSocket keepalive messages', async () => {
263
313
  const subscribeResponse = {
264
314
  body: {
265
- webSocketUrl: 'wss://fake-url',
315
+ webSocketUrl: 'wss://fake-url.cisco.com',
266
316
  },
267
317
  };
268
318
 
@@ -286,7 +336,7 @@ it('should register and connect to WebSocket without X-ORGANIZATION-ID header fo
286
336
  it('should handle WebSocket close due to network issue', async () => {
287
337
  const subscribeResponse = {
288
338
  body: {
289
- webSocketUrl: 'wss://fake-url',
339
+ webSocketUrl: 'wss://fake-url.cisco.com',
290
340
  },
291
341
  };
292
342
 
@@ -333,7 +383,7 @@ it('should register and connect to WebSocket without X-ORGANIZATION-ID header fo
333
383
  it('should handle WebSocket error event', async () => {
334
384
  const subscribeResponse = {
335
385
  body: {
336
- webSocketUrl: 'wss://fake-url',
386
+ webSocketUrl: 'wss://fake-url.cisco.com',
337
387
  },
338
388
  };
339
389
 
@@ -353,7 +403,7 @@ it('should register and connect to WebSocket without X-ORGANIZATION-ID header fo
353
403
  it('should handle WebSocket message event with AGENT_MULTI_LOGIN', async () => {
354
404
  const subscribeResponse = {
355
405
  body: {
356
- webSocketUrl: 'wss://fake-url',
406
+ webSocketUrl: 'wss://fake-url.cisco.com',
357
407
  },
358
408
  };
359
409
 
@@ -376,7 +426,7 @@ it('should register and connect to WebSocket without X-ORGANIZATION-ID header fo
376
426
  it('should handle WebSocket message event with Welcome', async () => {
377
427
  const subscribeResponse = {
378
428
  body: {
379
- webSocketUrl: 'wss://fake-url',
429
+ webSocketUrl: 'wss://fake-url.cisco.com',
380
430
  },
381
431
  };
382
432
 
@@ -395,7 +445,7 @@ it('should register and connect to WebSocket without X-ORGANIZATION-ID header fo
395
445
  it('should handle WebSocket close with forceCloseWebSocketOnTimeout', async () => {
396
446
  const subscribeResponse = {
397
447
  body: {
398
- webSocketUrl: 'wss://fake-url',
448
+ webSocketUrl: 'wss://fake-url.cisco.com',
399
449
  },
400
450
  };
401
451
 
@@ -430,7 +480,7 @@ it('should register and connect to WebSocket without X-ORGANIZATION-ID header fo
430
480
  it('should handle WebSocket close without reconnect', async () => {
431
481
  const subscribeResponse = {
432
482
  body: {
433
- webSocketUrl: 'wss://fake-url',
483
+ webSocketUrl: 'wss://fake-url.cisco.com',
434
484
  },
435
485
  };
436
486
 
@@ -460,7 +510,7 @@ it('should register and connect to WebSocket without X-ORGANIZATION-ID header fo
460
510
  it('should handle WebSocket close with clean close', async () => {
461
511
  const subscribeResponse = {
462
512
  body: {
463
- webSocketUrl: 'wss://fake-url',
513
+ webSocketUrl: 'wss://fake-url.cisco.com',
464
514
  },
465
515
  };
466
516