@webex/contact-center 3.12.0-next.12 → 3.12.0-next.121

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 (307) hide show
  1. package/.sdd/manifest.json +884 -0
  2. package/AGENTS.md +94 -0
  3. package/ai-docs/ARCHITECTURE.md +168 -0
  4. package/ai-docs/CONTRACTS.md +51 -0
  5. package/ai-docs/GETTING_STARTED.md +168 -0
  6. package/ai-docs/GLOSSARY.md +43 -0
  7. package/ai-docs/README.md +138 -0
  8. package/ai-docs/REVIEW_CHECKLIST.md +41 -0
  9. package/ai-docs/RULES.md +444 -0
  10. package/ai-docs/SECURITY.md +52 -0
  11. package/ai-docs/SERVICE_STATE.md +48 -0
  12. package/ai-docs/SPEC_INDEX.md +65 -0
  13. package/ai-docs/adr/0001-spec-source-policy.md +55 -0
  14. package/ai-docs/adr/README.md +8 -0
  15. package/ai-docs/adr/_adr-template.md +31 -0
  16. package/ai-docs/contact-center-spec.md +359 -0
  17. package/ai-docs/features/consult-transfer-list-policy/spec/feature-spec.md +362 -0
  18. package/ai-docs/features/generated-spec-conformance-fidelity-remediation/spec/feature-spec.md +117 -0
  19. package/ai-docs/features/residual-warning-coverage-completion/spec/feature-spec.md +203 -0
  20. package/ai-docs/features/validator-code-fidelity-drift-fix/spec/feature-spec.md +315 -0
  21. package/ai-docs/patterns/event-driven-patterns.md +485 -0
  22. package/ai-docs/patterns/testing-patterns.md +480 -0
  23. package/ai-docs/patterns/typescript-patterns.md +365 -0
  24. package/ai-docs/templates/README.md +102 -0
  25. package/ai-docs/templates/documentation/create-agents-md.md +240 -0
  26. package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
  27. package/ai-docs/templates/existing-service/bug-fix.md +254 -0
  28. package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
  29. package/ai-docs/templates/new-method/00-master.md +80 -0
  30. package/ai-docs/templates/new-method/01-requirements.md +232 -0
  31. package/ai-docs/templates/new-method/02-implementation.md +295 -0
  32. package/ai-docs/templates/new-method/03-tests.md +201 -0
  33. package/ai-docs/templates/new-method/04-validation.md +141 -0
  34. package/ai-docs/templates/new-service/00-master.md +109 -0
  35. package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
  36. package/ai-docs/templates/new-service/02-code-generation.md +346 -0
  37. package/ai-docs/templates/new-service/03-integration.md +178 -0
  38. package/ai-docs/templates/new-service/04-test-generation.md +205 -0
  39. package/ai-docs/templates/new-service/05-validation.md +145 -0
  40. package/dist/cc.js +808 -40
  41. package/dist/cc.js.map +1 -1
  42. package/dist/config.js +13 -0
  43. package/dist/config.js.map +1 -1
  44. package/dist/constants.js +27 -3
  45. package/dist/constants.js.map +1 -1
  46. package/dist/index.js +20 -5
  47. package/dist/index.js.map +1 -1
  48. package/dist/metrics/MetricsManager.js +16 -0
  49. package/dist/metrics/MetricsManager.js.map +1 -1
  50. package/dist/metrics/behavioral-events.js +205 -0
  51. package/dist/metrics/behavioral-events.js.map +1 -1
  52. package/dist/metrics/constants.js +43 -4
  53. package/dist/metrics/constants.js.map +1 -1
  54. package/dist/services/AddressBook.js +18 -15
  55. package/dist/services/AddressBook.js.map +1 -1
  56. package/dist/services/AnswerCallOnWebexService.js +202 -0
  57. package/dist/services/AnswerCallOnWebexService.js.map +1 -0
  58. package/dist/services/ApiAiAssistant.js +153 -8
  59. package/dist/services/ApiAiAssistant.js.map +1 -1
  60. package/dist/services/EntryPoint.js +46 -68
  61. package/dist/services/EntryPoint.js.map +1 -1
  62. package/dist/services/Queue.js +27 -22
  63. package/dist/services/Queue.js.map +1 -1
  64. package/dist/services/UserPreference.js +427 -0
  65. package/dist/services/UserPreference.js.map +1 -0
  66. package/dist/services/WebexCrossClientService.js +222 -0
  67. package/dist/services/WebexCrossClientService.js.map +1 -0
  68. package/dist/services/WxAppTelephonyMercurySync.js +108 -0
  69. package/dist/services/WxAppTelephonyMercurySync.js.map +1 -0
  70. package/dist/services/config/Util.js +6 -3
  71. package/dist/services/config/Util.js.map +1 -1
  72. package/dist/services/config/constants.js +33 -8
  73. package/dist/services/config/constants.js.map +1 -1
  74. package/dist/services/config/types.js +53 -9
  75. package/dist/services/config/types.js.map +1 -1
  76. package/dist/services/core/Err.js.map +1 -1
  77. package/dist/services/core/Utils.js +107 -32
  78. package/dist/services/core/Utils.js.map +1 -1
  79. package/dist/services/core/WebexRequest.js +6 -2
  80. package/dist/services/core/WebexRequest.js.map +1 -1
  81. package/dist/services/core/aqm-reqs.js +28 -14
  82. package/dist/services/core/aqm-reqs.js.map +1 -1
  83. package/dist/services/core/types.js.map +1 -1
  84. package/dist/services/core/websocket/WebSocketManager.js +2 -1
  85. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  86. package/dist/services/core/websocket/types.js.map +1 -1
  87. package/dist/services/index.js +1 -1
  88. package/dist/services/index.js.map +1 -1
  89. package/dist/services/task/Task.js +754 -0
  90. package/dist/services/task/Task.js.map +1 -0
  91. package/dist/services/task/TaskFactory.js +49 -0
  92. package/dist/services/task/TaskFactory.js.map +1 -0
  93. package/dist/services/task/TaskManager.js +1053 -520
  94. package/dist/services/task/TaskManager.js.map +1 -1
  95. package/dist/services/task/TaskUtils.js +211 -27
  96. package/dist/services/task/TaskUtils.js.map +1 -1
  97. package/dist/services/task/WebexCallingUtils.js +70 -0
  98. package/dist/services/task/WebexCallingUtils.js.map +1 -0
  99. package/dist/services/task/constants.js +12 -2
  100. package/dist/services/task/constants.js.map +1 -1
  101. package/dist/services/task/contact.js +29 -0
  102. package/dist/services/task/contact.js.map +1 -1
  103. package/dist/services/task/dialer.js +78 -0
  104. package/dist/services/task/dialer.js.map +1 -1
  105. package/dist/services/task/digital/Digital.js +78 -0
  106. package/dist/services/task/digital/Digital.js.map +1 -0
  107. package/dist/services/task/state-machine/TaskStateMachine.js +954 -0
  108. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
  109. package/dist/services/task/state-machine/actions.js +572 -0
  110. package/dist/services/task/state-machine/actions.js.map +1 -0
  111. package/dist/services/task/state-machine/constants.js +161 -0
  112. package/dist/services/task/state-machine/constants.js.map +1 -0
  113. package/dist/services/task/state-machine/guards.js +379 -0
  114. package/dist/services/task/state-machine/guards.js.map +1 -0
  115. package/dist/services/task/state-machine/index.js +53 -0
  116. package/dist/services/task/state-machine/index.js.map +1 -0
  117. package/dist/services/task/state-machine/types.js +54 -0
  118. package/dist/services/task/state-machine/types.js.map +1 -0
  119. package/dist/services/task/state-machine/uiControlsComputer.js +703 -0
  120. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
  121. package/dist/services/task/taskDataNormalizer.js +99 -0
  122. package/dist/services/task/taskDataNormalizer.js.map +1 -0
  123. package/dist/services/task/types.js +228 -5
  124. package/dist/services/task/types.js.map +1 -1
  125. package/dist/services/task/voice/Voice.js +1447 -0
  126. package/dist/services/task/voice/Voice.js.map +1 -0
  127. package/dist/services/task/voice/WebRTC.js +152 -0
  128. package/dist/services/task/voice/WebRTC.js.map +1 -0
  129. package/dist/services/task/voice/wxAppVoiceMethods.js +354 -0
  130. package/dist/services/task/voice/wxAppVoiceMethods.js.map +1 -0
  131. package/dist/services/wxAppDiagnosticLogging.js +122 -0
  132. package/dist/services/wxAppDiagnosticLogging.js.map +1 -0
  133. package/dist/services/wxAppTelephonyUtils.js +19 -0
  134. package/dist/services/wxAppTelephonyUtils.js.map +1 -0
  135. package/dist/types/cc.d.ts +172 -5
  136. package/dist/types/config.d.ts +13 -0
  137. package/dist/types/constants.d.ts +25 -1
  138. package/dist/types/index.d.ts +24 -7
  139. package/dist/types/metrics/MetricsManager.d.ts +6 -0
  140. package/dist/types/metrics/constants.d.ts +38 -1
  141. package/dist/types/services/AddressBook.d.ts +2 -1
  142. package/dist/types/services/AnswerCallOnWebexService.d.ts +38 -0
  143. package/dist/types/services/ApiAiAssistant.d.ts +22 -4
  144. package/dist/types/services/EntryPoint.d.ts +7 -5
  145. package/dist/types/services/Queue.d.ts +5 -3
  146. package/dist/types/services/UserPreference.d.ts +118 -0
  147. package/dist/types/services/WebexCrossClientService.d.ts +32 -0
  148. package/dist/types/services/WxAppTelephonyMercurySync.d.ts +28 -0
  149. package/dist/types/services/config/constants.d.ts +29 -5
  150. package/dist/types/services/config/types.d.ts +184 -10
  151. package/dist/types/services/core/Err.d.ts +6 -0
  152. package/dist/types/services/core/Utils.d.ts +33 -13
  153. package/dist/types/services/core/WebexRequest.d.ts +1 -0
  154. package/dist/types/services/core/types.d.ts +2 -0
  155. package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -0
  156. package/dist/types/services/core/websocket/types.d.ts +1 -1
  157. package/dist/types/services/index.d.ts +1 -1
  158. package/dist/types/services/task/Task.d.ts +175 -0
  159. package/dist/types/services/task/TaskFactory.d.ts +13 -0
  160. package/dist/types/services/task/TaskUtils.d.ts +48 -2
  161. package/dist/types/services/task/WebexCallingUtils.d.ts +11 -0
  162. package/dist/types/services/task/constants.d.ts +10 -0
  163. package/dist/types/services/task/contact.d.ts +4 -0
  164. package/dist/types/services/task/dialer.d.ts +30 -0
  165. package/dist/types/services/task/digital/Digital.d.ts +22 -0
  166. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1356 -0
  167. package/dist/types/services/task/state-machine/actions.d.ts +10 -0
  168. package/dist/types/services/task/state-machine/constants.d.ts +107 -0
  169. package/dist/types/services/task/state-machine/guards.d.ts +103 -0
  170. package/dist/types/services/task/state-machine/index.d.ts +13 -0
  171. package/dist/types/services/task/state-machine/types.d.ts +277 -0
  172. package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
  173. package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
  174. package/dist/types/services/task/types.d.ts +680 -66
  175. package/dist/types/services/task/voice/Voice.d.ts +227 -0
  176. package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
  177. package/dist/types/services/task/voice/wxAppVoiceMethods.d.ts +55 -0
  178. package/dist/types/services/wxAppDiagnosticLogging.d.ts +51 -0
  179. package/dist/types/services/wxAppTelephonyUtils.d.ts +5 -0
  180. package/dist/types/types.d.ts +149 -8
  181. package/dist/types/utils/PageCache.d.ts +20 -3
  182. package/dist/types/webex.d.ts +1 -0
  183. package/dist/types.js +125 -4
  184. package/dist/types.js.map +1 -1
  185. package/dist/utils/PageCache.js +19 -5
  186. package/dist/utils/PageCache.js.map +1 -1
  187. package/dist/webex.js +14 -2
  188. package/dist/webex.js.map +1 -1
  189. package/package.json +16 -12
  190. package/src/cc.ts +986 -42
  191. package/src/config.ts +13 -0
  192. package/src/constants.ts +25 -1
  193. package/src/index.ts +25 -5
  194. package/src/metrics/MetricsManager.ts +16 -0
  195. package/src/metrics/ai-docs/AGENTS.md +350 -0
  196. package/src/metrics/ai-docs/ARCHITECTURE.md +338 -0
  197. package/src/metrics/ai-docs/metrics-spec.md +922 -0
  198. package/src/metrics/behavioral-events.ts +212 -0
  199. package/src/metrics/constants.ts +47 -4
  200. package/src/services/AddressBook.ts +17 -6
  201. package/src/services/AnswerCallOnWebexService.ts +239 -0
  202. package/src/services/ApiAiAssistant.ts +203 -8
  203. package/src/services/EntryPoint.ts +59 -60
  204. package/src/services/Queue.ts +29 -12
  205. package/src/services/UserPreference.ts +509 -0
  206. package/src/services/WebexCrossClientService.ts +293 -0
  207. package/src/services/WxAppTelephonyMercurySync.ts +142 -0
  208. package/src/services/agent/ai-docs/AGENTS.md +240 -0
  209. package/src/services/agent/ai-docs/ARCHITECTURE.md +304 -0
  210. package/src/services/agent/ai-docs/agent-spec.md +505 -0
  211. package/src/services/ai-docs/AGENTS.md +386 -0
  212. package/src/services/ai-docs/services-spec.md +497 -0
  213. package/src/services/config/Util.ts +6 -3
  214. package/src/services/config/ai-docs/AGENTS.md +255 -0
  215. package/src/services/config/ai-docs/ARCHITECTURE.md +426 -0
  216. package/src/services/config/ai-docs/config-spec.md +675 -0
  217. package/src/services/config/constants.ts +35 -7
  218. package/src/services/config/types.ts +186 -11
  219. package/src/services/core/Err.ts +3 -0
  220. package/src/services/core/Utils.ts +123 -37
  221. package/src/services/core/WebexRequest.ts +3 -1
  222. package/src/services/core/ai-docs/AGENTS.md +381 -0
  223. package/src/services/core/ai-docs/ARCHITECTURE.md +698 -0
  224. package/src/services/core/ai-docs/core-spec.md +787 -0
  225. package/src/services/core/aqm-reqs.ts +30 -15
  226. package/src/services/core/types.ts +2 -0
  227. package/src/services/core/websocket/WebSocketManager.ts +2 -0
  228. package/src/services/core/websocket/types.ts +1 -1
  229. package/src/services/index.ts +1 -1
  230. package/src/services/task/Task.ts +908 -0
  231. package/src/services/task/TaskFactory.ts +60 -0
  232. package/src/services/task/TaskManager.ts +1239 -608
  233. package/src/services/task/TaskUtils.ts +303 -25
  234. package/src/services/task/WebexCallingUtils.ts +136 -0
  235. package/src/services/task/ai-docs/AGENTS.md +457 -0
  236. package/src/services/task/ai-docs/ARCHITECTURE.md +595 -0
  237. package/src/services/task/ai-docs/task-spec.md +1470 -0
  238. package/src/services/task/constants.ts +10 -0
  239. package/src/services/task/contact.ts +30 -0
  240. package/src/services/task/dialer.ts +80 -0
  241. package/src/services/task/digital/Digital.ts +97 -0
  242. package/src/services/task/state-machine/TaskStateMachine.ts +1293 -0
  243. package/src/services/task/state-machine/actions.ts +741 -0
  244. package/src/services/task/state-machine/ai-docs/AGENTS.md +460 -0
  245. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1145 -0
  246. package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +2207 -0
  247. package/src/services/task/state-machine/constants.ts +172 -0
  248. package/src/services/task/state-machine/guards.ts +442 -0
  249. package/src/services/task/state-machine/index.ts +28 -0
  250. package/src/services/task/state-machine/types.ts +258 -0
  251. package/src/services/task/state-machine/uiControlsComputer.ts +1135 -0
  252. package/src/services/task/taskDataNormalizer.ts +137 -0
  253. package/src/services/task/types.ts +819 -70
  254. package/src/services/task/voice/Voice.ts +1809 -0
  255. package/src/services/task/voice/WebRTC.ts +191 -0
  256. package/src/services/task/voice/wxAppVoiceMethods.ts +516 -0
  257. package/src/services/wxAppDiagnosticLogging.ts +174 -0
  258. package/src/services/wxAppTelephonyUtils.ts +14 -0
  259. package/src/types.ts +199 -11
  260. package/src/utils/AGENTS.md +289 -0
  261. package/src/utils/PageCache.ts +38 -5
  262. package/src/utils/ai-docs/utils-spec.md +391 -0
  263. package/src/webex.js +2 -0
  264. package/test/unit/spec/cc.ts +1947 -124
  265. package/test/unit/spec/logger-proxy.ts +70 -0
  266. package/test/unit/spec/metrics/MetricsManager.ts +25 -0
  267. package/test/unit/spec/metrics/behavioral-events.ts +60 -0
  268. package/test/unit/spec/services/AddressBook.ts +37 -6
  269. package/test/unit/spec/services/AnswerCallOnWebexService.ts +264 -0
  270. package/test/unit/spec/services/ApiAiAssistant.ts +178 -20
  271. package/test/unit/spec/services/EntryPoint.ts +87 -40
  272. package/test/unit/spec/services/Queue.ts +123 -12
  273. package/test/unit/spec/services/UserPreference.ts +401 -0
  274. package/test/unit/spec/services/WebCallingService.ts +7 -1
  275. package/test/unit/spec/services/WebexCrossClientService.ts +467 -0
  276. package/test/unit/spec/services/WxAppTelephonyMercurySync.ts +136 -0
  277. package/test/unit/spec/services/config/Util.ts +85 -0
  278. package/test/unit/spec/services/config/index.ts +30 -30
  279. package/test/unit/spec/services/core/Utils.ts +425 -8
  280. package/test/unit/spec/services/core/WebexRequest.ts +3 -1
  281. package/test/unit/spec/services/core/aqm-reqs.ts +113 -1
  282. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +66 -40
  283. package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
  284. package/test/unit/spec/services/task/Task.ts +677 -0
  285. package/test/unit/spec/services/task/TaskFactory.ts +99 -0
  286. package/test/unit/spec/services/task/TaskManager.ts +1972 -1549
  287. package/test/unit/spec/services/task/TaskUtils.ts +235 -0
  288. package/test/unit/spec/services/task/WebexCallingUtils.ts +153 -0
  289. package/test/unit/spec/services/task/contact.ts +33 -0
  290. package/test/unit/spec/services/task/dialer.ts +190 -0
  291. package/test/unit/spec/services/task/digital/Digital.ts +105 -0
  292. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +3459 -0
  293. package/test/unit/spec/services/task/state-machine/guards.ts +839 -0
  294. package/test/unit/spec/services/task/state-machine/types.ts +18 -0
  295. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +3101 -0
  296. package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
  297. package/test/unit/spec/services/task/voice/Voice.ts +1903 -0
  298. package/test/unit/spec/services/task/voice/WebRTC.ts +235 -0
  299. package/test/unit/spec/services/task/voice/wxAppVoiceMethods.ts +603 -0
  300. package/test/unit/spec/services/wxAppDiagnosticLogging.ts +143 -0
  301. package/umd/contact-center.min.js +2 -2
  302. package/umd/contact-center.min.js.map +1 -1
  303. package/dist/services/task/index.js +0 -1525
  304. package/dist/services/task/index.js.map +0 -1
  305. package/dist/types/services/task/index.d.ts +0 -650
  306. package/src/services/task/index.ts +0 -1801
  307. package/test/unit/spec/services/task/index.ts +0 -2184
@@ -143,7 +143,8 @@ describe('Queue', () => {
143
143
 
144
144
  expect(mockWebex.request).toHaveBeenCalledWith({
145
145
  service: 'wcc-api-gateway',
146
- resource: '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100',
146
+ resource:
147
+ '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100&filter=queueType%3D%3DINBOUND%3BchannelType%3D%3DTELEPHONY%3Bactive%3D%3Dtrue&sort=name%2CASC&desktopProfileFilter=true&agentView=true&firstLevelView=true',
147
148
  method: HTTP_METHODS.GET,
148
149
  });
149
150
 
@@ -156,7 +157,7 @@ describe('Queue', () => {
156
157
  statusCode: 200,
157
158
  recordCount: 2,
158
159
  totalRecords: 2,
159
- isSearchRequest: false,
160
+ isSearchRequest: true,
160
161
  isFirstPage: true,
161
162
  },
162
163
  ['behavioral', 'operational']
@@ -168,14 +169,15 @@ describe('Queue', () => {
168
169
  orgId: 'test-org-id',
169
170
  page: 0,
170
171
  pageSize: 100,
171
- isSearchRequest: false,
172
+ isSearchRequest: true,
172
173
  }),
173
174
  });
174
175
  expect(LoggerProxy.log).toHaveBeenCalledWith('Making API request to fetch contact service queues', {
175
176
  module: 'Queue',
176
177
  method: 'getQueues',
177
178
  data: expect.objectContaining({
178
- resource: '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100',
179
+ resource:
180
+ '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100&filter=queueType%3D%3DINBOUND%3BchannelType%3D%3DTELEPHONY%3Bactive%3D%3Dtrue&sort=name%2CASC&desktopProfileFilter=true&agentView=true&firstLevelView=true',
179
181
  service: 'wcc-api-gateway',
180
182
  }),
181
183
  });
@@ -201,7 +203,7 @@ describe('Queue', () => {
201
203
 
202
204
  expect(mockWebex.request).toHaveBeenCalledWith({
203
205
  service: 'wcc-api-gateway',
204
- resource: '/organization/test-org-id/v2/contact-service-queue?page=1&pageSize=25&filter=queueType%3D%3D%22INBOUND%22&attributes=id%2Cname%2CqueueType&search=support&sortBy=name&sortOrder=desc&desktopProfileFilter=true&provisioningView=false&singleObjectResponse=true',
206
+ resource: '/organization/test-org-id/v2/contact-service-queue?page=1&pageSize=25&filter=queueType%3D%3D%22INBOUND%22&attributes=id%2Cname%2CqueueType&search=support&sort=name%2CDESC&desktopProfileFilter=true&provisioningView=false&singleObjectResponse=true&agentView=true&firstLevelView=true',
205
207
  method: HTTP_METHODS.GET,
206
208
  });
207
209
 
@@ -215,6 +217,108 @@ describe('Queue', () => {
215
217
  );
216
218
  });
217
219
 
220
+ it('should default sortOrder-only requests to name and bypass cache', async () => {
221
+ (mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
222
+
223
+ await queueAPI.getQueues({sortOrder: 'desc'});
224
+ await queueAPI.getQueues({sortOrder: 'desc'});
225
+
226
+ expect(mockWebex.request).toHaveBeenCalledTimes(2);
227
+ expect(mockWebex.request).toHaveBeenLastCalledWith({
228
+ service: 'wcc-api-gateway',
229
+ resource:
230
+ '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100&filter=queueType%3D%3DINBOUND%3BchannelType%3D%3DTELEPHONY%3Bactive%3D%3Dtrue&sort=name%2CDESC&desktopProfileFilter=true&agentView=true&firstLevelView=true',
231
+ method: HTTP_METHODS.GET,
232
+ });
233
+ });
234
+
235
+ it('should allow existing parameters to override the default queue policy', async () => {
236
+ (mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
237
+
238
+ const result = await queueAPI.getQueues({
239
+ page: 1,
240
+ pageSize: 25,
241
+ search: 'support',
242
+ filter: 'queueType==INBOUND;channelType==SOCIAL_CHANNEL;active==true',
243
+ });
244
+
245
+ expect(mockWebex.request).toHaveBeenCalledWith({
246
+ service: 'wcc-api-gateway',
247
+ resource:
248
+ '/organization/test-org-id/v2/contact-service-queue?page=1&pageSize=25&filter=queueType%3D%3DINBOUND%3BchannelType%3D%3DSOCIAL_CHANNEL%3Bactive%3D%3Dtrue&search=support&sort=name%2CASC&desktopProfileFilter=true&agentView=true&firstLevelView=true',
249
+ method: HTTP_METHODS.GET,
250
+ });
251
+ expect(result).toBe(mockResponse.body);
252
+ });
253
+
254
+ it('should preserve defaults when optional overrides are undefined', async () => {
255
+ (mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
256
+
257
+ await queueAPI.getQueues({
258
+ filter: undefined,
259
+ sortBy: undefined,
260
+ sortOrder: undefined,
261
+ desktopProfileFilter: undefined,
262
+ });
263
+
264
+ expect(mockWebex.request).toHaveBeenCalledWith({
265
+ service: 'wcc-api-gateway',
266
+ resource:
267
+ '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100&filter=queueType%3D%3DINBOUND%3BchannelType%3D%3DTELEPHONY%3Bactive%3D%3Dtrue&sort=name%2CASC&desktopProfileFilter=true&agentView=true&firstLevelView=true',
268
+ method: HTTP_METHODS.GET,
269
+ });
270
+ });
271
+
272
+ it('should preserve an explicit empty filter override', async () => {
273
+ (mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
274
+
275
+ await queueAPI.getQueues({filter: ''});
276
+
277
+ expect(mockWebex.request).toHaveBeenCalledWith({
278
+ service: 'wcc-api-gateway',
279
+ resource:
280
+ '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100&sort=name%2CASC&desktopProfileFilter=true&agentView=true&firstLevelView=true',
281
+ method: HTTP_METHODS.GET,
282
+ });
283
+ });
284
+
285
+ it('should bypass cache for the default queue policy', async () => {
286
+ (mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
287
+
288
+ await queueAPI.getQueues();
289
+ await queueAPI.getQueues();
290
+
291
+ expect(mockWebex.request).toHaveBeenCalledTimes(2);
292
+ expect(mockWebex.request).toHaveBeenLastCalledWith(
293
+ expect.objectContaining({
294
+ resource: expect.stringContaining('channelType%3D%3DTELEPHONY'),
295
+ })
296
+ );
297
+ });
298
+
299
+ it('should disable the internal agent views when desktop profile filtering is false', async () => {
300
+ (mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
301
+
302
+ await queueAPI.getQueues({
303
+ desktopProfileFilter: false,
304
+ provisioningView: false,
305
+ singleObjectResponse: false,
306
+ });
307
+ await queueAPI.getQueues({
308
+ desktopProfileFilter: false,
309
+ provisioningView: false,
310
+ singleObjectResponse: false,
311
+ });
312
+
313
+ expect(mockWebex.request).toHaveBeenCalledTimes(2);
314
+ expect(mockWebex.request).toHaveBeenLastCalledWith({
315
+ service: 'wcc-api-gateway',
316
+ resource:
317
+ '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100&filter=queueType%3D%3DINBOUND%3BchannelType%3D%3DTELEPHONY%3Bactive%3D%3Dtrue&sort=name%2CASC&desktopProfileFilter=false&provisioningView=false&singleObjectResponse=false&agentView=false&firstLevelView=false',
318
+ method: HTTP_METHODS.GET,
319
+ });
320
+ });
321
+
218
322
  it('should handle API errors and track metrics', async () => {
219
323
  (mockWebex.request as jest.Mock).mockRejectedValue(new Error('Internal Server Error'));
220
324
 
@@ -222,7 +326,8 @@ describe('Queue', () => {
222
326
 
223
327
  expect(mockWebex.request).toHaveBeenCalledWith({
224
328
  service: 'wcc-api-gateway',
225
- resource: '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100',
329
+ resource:
330
+ '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100&filter=queueType%3D%3DINBOUND%3BchannelType%3D%3DTELEPHONY%3Bactive%3D%3Dtrue&sort=name%2CASC&desktopProfileFilter=true&agentView=true&firstLevelView=true',
226
331
  method: HTTP_METHODS.GET,
227
332
  });
228
333
 
@@ -231,7 +336,7 @@ describe('Queue', () => {
231
336
  {
232
337
  orgId: 'test-org-id',
233
338
  error: 'Internal Server Error',
234
- isSearchRequest: false,
339
+ isSearchRequest: true,
235
340
  page: 0,
236
341
  pageSize: 100,
237
342
  },
@@ -243,7 +348,7 @@ describe('Queue', () => {
243
348
  data: expect.objectContaining({
244
349
  orgId: 'test-org-id',
245
350
  error: 'Internal Server Error',
246
- isSearchRequest: false,
351
+ isSearchRequest: true,
247
352
  page: 0,
248
353
  pageSize: 100,
249
354
  }),
@@ -253,13 +358,17 @@ describe('Queue', () => {
253
358
 
254
359
 
255
360
 
256
- it('should not track metrics for subsequent pages in simple pagination', async () => {
361
+ it('should track metrics for subsequent pages under the default filtered policy', async () => {
257
362
  (mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
258
363
 
259
364
  const result = await queueAPI.getQueues({page: 2});
260
365
  expect(result).toEqual(mockResponse.body);
261
366
 
262
- expect(mockMetricsManager.trackEvent).not.toHaveBeenCalled();
367
+ expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
368
+ METRIC_EVENT_NAMES.QUEUE_FETCH_SUCCESS,
369
+ expect.objectContaining({isSearchRequest: true, isFirstPage: false}),
370
+ ['behavioral', 'operational']
371
+ );
263
372
  });
264
373
 
265
374
  it('should track metrics for search requests on any page', async () => {
@@ -307,14 +416,16 @@ describe('Queue', () => {
307
416
  expect(result.meta.page).toBe(1);
308
417
  expect(mockWebex.request).toHaveBeenCalledWith({
309
418
  service: 'wcc-api-gateway',
310
- resource: '/organization/test-org-id/v2/contact-service-queue?page=1&pageSize=100',
419
+ resource:
420
+ '/organization/test-org-id/v2/contact-service-queue?page=1&pageSize=100&filter=queueType%3D%3DINBOUND%3BchannelType%3D%3DTELEPHONY%3Bactive%3D%3Dtrue&sort=name%2CASC&desktopProfileFilter=true&agentView=true&firstLevelView=true',
311
421
  method: HTTP_METHODS.GET,
312
422
  });
313
423
  expect(LoggerProxy.log).toHaveBeenCalledWith('Making API request to fetch contact service queues', {
314
424
  module: 'Queue',
315
425
  method: 'getQueues',
316
426
  data: expect.objectContaining({
317
- resource: '/organization/test-org-id/v2/contact-service-queue?page=1&pageSize=100',
427
+ resource:
428
+ '/organization/test-org-id/v2/contact-service-queue?page=1&pageSize=100&filter=queueType%3D%3DINBOUND%3BchannelType%3D%3DTELEPHONY%3Bactive%3D%3Dtrue&sort=name%2CASC&desktopProfileFilter=true&agentView=true&firstLevelView=true',
318
429
  service: 'wcc-api-gateway',
319
430
  }),
320
431
  });
@@ -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
+ });
@@ -200,11 +200,17 @@ describe('WebCallingService', () => {
200
200
 
201
201
  it('should reject if registration times out', async () => {
202
202
  line = callingClient.getLines().line1 as ILine;
203
+ jest.spyOn(global, 'setTimeout').mockImplementation(((handler: TimerHandler) => {
204
+ if (typeof handler === 'function') {
205
+ handler();
206
+ }
207
+ return 0 as unknown as NodeJS.Timeout;
208
+ }) as typeof setTimeout);
203
209
 
204
210
  const promise = webRTCCalling.registerWebCallingLine();
205
211
 
206
212
  await expect(promise).rejects.toThrow('WebCallingService Registration timed out');
207
- }, 20003); // Increased timeout to 20 seconds
213
+ });
208
214
 
209
215
  it('should handle incoming calls', async () => {
210
216
  line = callingClient.getLines().line1 as ILine;