@webex/plugin-meetings 3.7.0 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (351) hide show
  1. package/dist/annotation/annotation.types.d.ts +42 -0
  2. package/dist/annotation/constants.d.ts +31 -0
  3. package/dist/annotation/index.d.ts +117 -0
  4. package/dist/annotation/index.js +17 -0
  5. package/dist/annotation/index.js.map +1 -1
  6. package/dist/breakouts/breakout.d.ts +8 -0
  7. package/dist/breakouts/breakout.js +1 -1
  8. package/dist/breakouts/collection.d.ts +5 -0
  9. package/dist/breakouts/edit-lock-error.d.ts +15 -0
  10. package/dist/breakouts/events.d.ts +8 -0
  11. package/dist/breakouts/index.d.ts +5 -0
  12. package/dist/breakouts/index.js +1 -1
  13. package/dist/breakouts/request.d.ts +22 -0
  14. package/dist/breakouts/utils.d.ts +15 -0
  15. package/dist/common/browser-detection.d.ts +9 -0
  16. package/dist/common/collection.d.ts +48 -0
  17. package/dist/common/config.d.ts +2 -0
  18. package/dist/common/errors/captcha-error.d.ts +15 -0
  19. package/dist/common/errors/intent-to-join.d.ts +16 -0
  20. package/dist/common/errors/join-forbidden-error.js +52 -0
  21. package/dist/common/errors/join-forbidden-error.js.map +1 -0
  22. package/dist/common/errors/join-meeting.d.ts +17 -0
  23. package/dist/common/errors/{webinar-registration-error.js → join-webinar-error.js} +12 -12
  24. package/dist/common/errors/join-webinar-error.js.map +1 -0
  25. package/dist/common/errors/media.d.ts +15 -0
  26. package/dist/common/errors/multistream-not-supported-error.js +53 -0
  27. package/dist/common/errors/multistream-not-supported-error.js.map +1 -0
  28. package/dist/common/errors/no-meeting-info.d.ts +14 -0
  29. package/dist/common/errors/parameter.d.ts +15 -0
  30. package/dist/common/errors/password-error.d.ts +15 -0
  31. package/dist/common/errors/permission.d.ts +14 -0
  32. package/dist/common/errors/reclaim-host-role-error.js +149 -0
  33. package/dist/common/errors/reclaim-host-role-error.js.map +1 -0
  34. package/dist/common/errors/reclaim-host-role-errors.d.ts +60 -0
  35. package/dist/common/errors/reconnection-in-progress.d.ts +9 -0
  36. package/dist/common/errors/reconnection-in-progress.js +33 -0
  37. package/dist/common/errors/reconnection-in-progress.js.map +1 -0
  38. package/dist/common/errors/reconnection.d.ts +15 -0
  39. package/dist/common/errors/stats.d.ts +15 -0
  40. package/dist/common/errors/webex-errors.d.ts +93 -0
  41. package/dist/common/errors/webex-meetings-error.d.ts +20 -0
  42. package/dist/common/events/events-scope.d.ts +17 -0
  43. package/dist/common/events/events.d.ts +12 -0
  44. package/dist/common/events/trigger-proxy.d.ts +2 -0
  45. package/dist/common/events/util.d.ts +2 -0
  46. package/dist/common/logs/logger-config.d.ts +2 -0
  47. package/dist/common/logs/logger-proxy.d.ts +2 -0
  48. package/dist/common/logs/request.d.ts +36 -0
  49. package/dist/common/queue.d.ts +34 -0
  50. package/dist/config.d.ts +72 -0
  51. package/dist/config.js +2 -1
  52. package/dist/config.js.map +1 -1
  53. package/dist/constants.d.ts +1088 -0
  54. package/dist/constants.js +68 -6
  55. package/dist/constants.js.map +1 -1
  56. package/dist/controls-options-manager/constants.d.ts +4 -0
  57. package/dist/controls-options-manager/enums.d.ts +15 -0
  58. package/dist/controls-options-manager/index.d.ts +136 -0
  59. package/dist/controls-options-manager/types.d.ts +43 -0
  60. package/dist/controls-options-manager/util.d.ts +1 -0
  61. package/dist/index.d.ts +7 -0
  62. package/dist/index.js +16 -11
  63. package/dist/index.js.map +1 -1
  64. package/dist/interceptors/index.d.ts +2 -0
  65. package/dist/interceptors/locusRetry.d.ts +27 -0
  66. package/dist/interpretation/collection.d.ts +5 -0
  67. package/dist/interpretation/index.d.ts +5 -0
  68. package/dist/interpretation/index.js +1 -1
  69. package/dist/interpretation/siLanguage.d.ts +5 -0
  70. package/dist/interpretation/siLanguage.js +1 -1
  71. package/dist/locus-info/controlsUtils.d.ts +2 -0
  72. package/dist/locus-info/embeddedAppsUtils.d.ts +2 -0
  73. package/dist/locus-info/fullState.d.ts +2 -0
  74. package/dist/locus-info/hostUtils.d.ts +2 -0
  75. package/dist/locus-info/index.d.ts +322 -0
  76. package/dist/locus-info/index.js +14 -3
  77. package/dist/locus-info/index.js.map +1 -1
  78. package/dist/locus-info/infoUtils.d.ts +2 -0
  79. package/dist/locus-info/mediaSharesUtils.d.ts +2 -0
  80. package/dist/locus-info/parser.d.ts +272 -0
  81. package/dist/locus-info/selfUtils.d.ts +2 -0
  82. package/dist/locus-info/selfUtils.js +35 -17
  83. package/dist/locus-info/selfUtils.js.map +1 -1
  84. package/dist/media/MediaConnectionAwaiter.js +1 -0
  85. package/dist/media/MediaConnectionAwaiter.js.map +1 -1
  86. package/dist/media/index.d.ts +34 -0
  87. package/dist/media/properties.d.ts +93 -0
  88. package/dist/media/properties.js +30 -16
  89. package/dist/media/properties.js.map +1 -1
  90. package/dist/media/util.d.ts +2 -0
  91. package/dist/mediaQualityMetrics/config.d.ts +241 -0
  92. package/dist/mediaQualityMetrics/config.js +502 -0
  93. package/dist/mediaQualityMetrics/config.js.map +1 -0
  94. package/dist/meeting/brbState.js +167 -0
  95. package/dist/meeting/brbState.js.map +1 -0
  96. package/dist/meeting/effectsState.js +260 -0
  97. package/dist/meeting/effectsState.js.map +1 -0
  98. package/dist/meeting/in-meeting-actions.d.ts +167 -0
  99. package/dist/meeting/in-meeting-actions.js +13 -1
  100. package/dist/meeting/in-meeting-actions.js.map +1 -1
  101. package/dist/meeting/index.d.ts +1825 -0
  102. package/dist/meeting/index.js +1331 -1051
  103. package/dist/meeting/index.js.map +1 -1
  104. package/dist/meeting/locusMediaRequest.d.ts +74 -0
  105. package/dist/meeting/locusMediaRequest.js +11 -6
  106. package/dist/meeting/locusMediaRequest.js.map +1 -1
  107. package/dist/meeting/muteState.d.ts +178 -0
  108. package/dist/meeting/muteState.js +1 -6
  109. package/dist/meeting/muteState.js.map +1 -1
  110. package/dist/meeting/request.d.ts +295 -0
  111. package/dist/meeting/request.js +51 -29
  112. package/dist/meeting/request.js.map +1 -1
  113. package/dist/meeting/request.type.d.ts +11 -0
  114. package/dist/meeting/request.type.js.map +1 -1
  115. package/dist/meeting/state.d.ts +9 -0
  116. package/dist/meeting/util.d.ts +119 -0
  117. package/dist/meeting/util.js +103 -67
  118. package/dist/meeting/util.js.map +1 -1
  119. package/dist/meeting/voicea-meeting.d.ts +16 -0
  120. package/dist/meeting-info/collection.d.ts +20 -0
  121. package/dist/meeting-info/index.d.ts +69 -0
  122. package/dist/meeting-info/meeting-info-v2.d.ts +123 -0
  123. package/dist/meeting-info/meeting-info-v2.js +115 -45
  124. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  125. package/dist/meeting-info/request.d.ts +22 -0
  126. package/dist/meeting-info/util.d.ts +2 -0
  127. package/dist/meeting-info/utilv2.d.ts +2 -0
  128. package/dist/meeting-info/utilv2.js +6 -2
  129. package/dist/meeting-info/utilv2.js.map +1 -1
  130. package/dist/meetings/collection.d.ts +40 -0
  131. package/dist/meetings/index.d.ts +390 -0
  132. package/dist/meetings/index.js +107 -55
  133. package/dist/meetings/index.js.map +1 -1
  134. package/dist/meetings/meetings.types.d.ts +4 -0
  135. package/dist/meetings/meetings.types.js +2 -0
  136. package/dist/meetings/meetings.types.js.map +1 -1
  137. package/dist/meetings/request.d.ts +27 -0
  138. package/dist/meetings/util.d.ts +18 -0
  139. package/dist/meetings/util.js +1 -1
  140. package/dist/meetings/util.js.map +1 -1
  141. package/dist/member/index.d.ts +160 -0
  142. package/dist/member/index.js +9 -0
  143. package/dist/member/index.js.map +1 -1
  144. package/dist/member/member.types.js +17 -0
  145. package/dist/member/member.types.js.map +1 -0
  146. package/dist/member/types.d.ts +32 -0
  147. package/dist/member/types.js.map +1 -1
  148. package/dist/member/util.d.ts +2 -0
  149. package/dist/member/util.js +39 -28
  150. package/dist/member/util.js.map +1 -1
  151. package/dist/members/collection.d.ts +29 -0
  152. package/dist/members/index.d.ts +353 -0
  153. package/dist/members/request.d.ts +114 -0
  154. package/dist/members/types.d.ts +25 -0
  155. package/dist/members/util.d.ts +215 -0
  156. package/dist/members/util.js +4 -2
  157. package/dist/members/util.js.map +1 -1
  158. package/dist/metrics/config.js +276 -0
  159. package/dist/metrics/config.js.map +1 -0
  160. package/dist/metrics/constants.d.ts +70 -0
  161. package/dist/metrics/constants.js +6 -1
  162. package/dist/metrics/constants.js.map +1 -1
  163. package/dist/metrics/index.d.ts +45 -0
  164. package/dist/multistream/mediaRequestManager.d.ts +119 -0
  165. package/dist/multistream/receiveSlot.d.ts +68 -0
  166. package/dist/multistream/receiveSlotManager.d.ts +56 -0
  167. package/dist/multistream/remoteMedia.d.ts +72 -0
  168. package/dist/multistream/remoteMedia.js +30 -15
  169. package/dist/multistream/remoteMedia.js.map +1 -1
  170. package/dist/multistream/remoteMediaGroup.d.ts +49 -0
  171. package/dist/multistream/remoteMediaManager.d.ts +300 -0
  172. package/dist/multistream/sendSlotManager.d.ts +69 -0
  173. package/dist/multistream/sendSlotManager.js +24 -0
  174. package/dist/multistream/sendSlotManager.js.map +1 -1
  175. package/dist/networkQualityMonitor/index.d.ts +70 -0
  176. package/dist/networkQualityMonitor/index.js +13 -19
  177. package/dist/networkQualityMonitor/index.js.map +1 -1
  178. package/dist/peer-connection-manager/index.js +671 -0
  179. package/dist/peer-connection-manager/index.js.map +1 -0
  180. package/dist/peer-connection-manager/util.js +109 -0
  181. package/dist/peer-connection-manager/util.js.map +1 -0
  182. package/dist/personal-meeting-room/index.d.ts +47 -0
  183. package/dist/personal-meeting-room/request.d.ts +14 -0
  184. package/dist/personal-meeting-room/util.d.ts +2 -0
  185. package/dist/reachability/clusterReachability.d.ts +109 -0
  186. package/dist/reachability/clusterReachability.js +12 -15
  187. package/dist/reachability/clusterReachability.js.map +1 -1
  188. package/dist/reachability/index.d.ts +105 -0
  189. package/dist/reachability/index.js +461 -136
  190. package/dist/reachability/index.js.map +1 -1
  191. package/dist/reachability/reachability.types.js +7 -0
  192. package/dist/reachability/reachability.types.js.map +1 -0
  193. package/dist/reachability/request.d.ts +39 -0
  194. package/dist/reachability/request.js +21 -8
  195. package/dist/reachability/request.js.map +1 -1
  196. package/dist/reachability/util.d.ts +8 -0
  197. package/dist/reactions/constants.d.ts +3 -0
  198. package/dist/reactions/reactions.d.ts +4 -0
  199. package/dist/reactions/reactions.type.d.ts +52 -0
  200. package/dist/reconnection-manager/index.d.ts +136 -0
  201. package/dist/recording-controller/enums.d.ts +7 -0
  202. package/dist/recording-controller/enums.js +8 -4
  203. package/dist/recording-controller/enums.js.map +1 -1
  204. package/dist/recording-controller/index.d.ts +207 -0
  205. package/dist/recording-controller/index.js +18 -9
  206. package/dist/recording-controller/index.js.map +1 -1
  207. package/dist/recording-controller/util.d.ts +14 -0
  208. package/dist/recording-controller/util.js +13 -9
  209. package/dist/recording-controller/util.js.map +1 -1
  210. package/dist/roap/collection.js +62 -0
  211. package/dist/roap/collection.js.map +1 -0
  212. package/dist/roap/handler.js +275 -0
  213. package/dist/roap/handler.js.map +1 -0
  214. package/dist/roap/index.d.ts +86 -0
  215. package/dist/roap/index.js +15 -15
  216. package/dist/roap/index.js.map +1 -1
  217. package/dist/roap/request.d.ts +39 -0
  218. package/dist/roap/request.js +45 -79
  219. package/dist/roap/request.js.map +1 -1
  220. package/dist/roap/state.js +126 -0
  221. package/dist/roap/state.js.map +1 -0
  222. package/dist/roap/turnDiscovery.d.ts +155 -0
  223. package/dist/roap/turnDiscovery.js +3 -6
  224. package/dist/roap/turnDiscovery.js.map +1 -1
  225. package/dist/roap/util.js +75 -0
  226. package/dist/roap/util.js.map +1 -0
  227. package/dist/rtcMetrics/constants.d.ts +4 -0
  228. package/dist/rtcMetrics/index.d.ts +61 -0
  229. package/dist/statsAnalyzer/global.d.ts +36 -0
  230. package/dist/statsAnalyzer/global.js +126 -0
  231. package/dist/statsAnalyzer/global.js.map +1 -0
  232. package/dist/statsAnalyzer/index.d.ts +217 -0
  233. package/dist/statsAnalyzer/index.js +1013 -0
  234. package/dist/statsAnalyzer/index.js.map +1 -0
  235. package/dist/statsAnalyzer/mqaUtil.d.ts +48 -0
  236. package/dist/statsAnalyzer/mqaUtil.js +179 -0
  237. package/dist/statsAnalyzer/mqaUtil.js.map +1 -0
  238. package/dist/transcription/index.d.ts +64 -0
  239. package/dist/types/annotation/index.d.ts +5 -0
  240. package/dist/types/common/errors/join-forbidden-error.d.ts +15 -0
  241. package/dist/types/common/errors/{webinar-registration-error.d.ts → join-webinar-error.d.ts} +2 -2
  242. package/dist/types/common/errors/multistream-not-supported-error.d.ts +17 -0
  243. package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
  244. package/dist/types/config.d.ts +1 -0
  245. package/dist/types/constants.d.ts +53 -1
  246. package/dist/types/index.d.ts +3 -3
  247. package/dist/types/locus-info/index.d.ts +2 -1
  248. package/dist/types/mediaQualityMetrics/config.d.ts +241 -0
  249. package/dist/types/meeting/brbState.d.ts +54 -0
  250. package/dist/types/meeting/in-meeting-actions.d.ts +12 -0
  251. package/dist/types/meeting/index.d.ts +64 -14
  252. package/dist/types/meeting/locusMediaRequest.d.ts +6 -3
  253. package/dist/types/meeting/request.d.ts +14 -3
  254. package/dist/types/meeting/request.type.d.ts +6 -0
  255. package/dist/types/meeting/util.d.ts +3 -3
  256. package/dist/types/meeting-info/meeting-info-v2.d.ts +30 -5
  257. package/dist/types/meetings/index.d.ts +20 -2
  258. package/dist/types/meetings/meetings.types.d.ts +8 -0
  259. package/dist/types/member/index.d.ts +1 -0
  260. package/dist/types/member/types.d.ts +7 -0
  261. package/dist/types/members/util.d.ts +2 -0
  262. package/dist/types/metrics/constants.d.ts +6 -1
  263. package/dist/types/multistream/sendSlotManager.d.ts +8 -1
  264. package/dist/types/reachability/clusterReachability.d.ts +1 -10
  265. package/dist/types/reachability/index.d.ts +83 -36
  266. package/dist/types/reachability/reachability.types.d.ts +64 -0
  267. package/dist/types/reachability/request.d.ts +5 -1
  268. package/dist/types/recording-controller/enums.d.ts +5 -2
  269. package/dist/types/recording-controller/index.d.ts +1 -0
  270. package/dist/types/recording-controller/util.d.ts +2 -1
  271. package/dist/types/roap/request.d.ts +1 -13
  272. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  273. package/dist/types/statsAnalyzer/index.d.ts +217 -0
  274. package/dist/types/statsAnalyzer/mqaUtil.d.ts +48 -0
  275. package/dist/webinar/collection.d.ts +16 -0
  276. package/dist/webinar/index.d.ts +5 -0
  277. package/dist/webinar/index.js +390 -7
  278. package/dist/webinar/index.js.map +1 -1
  279. package/package.json +23 -22
  280. package/src/annotation/index.ts +16 -0
  281. package/src/common/errors/join-forbidden-error.ts +26 -0
  282. package/src/common/errors/join-webinar-error.ts +24 -0
  283. package/src/common/errors/multistream-not-supported-error.ts +30 -0
  284. package/src/config.ts +1 -0
  285. package/src/constants.ts +61 -3
  286. package/src/index.ts +5 -3
  287. package/src/locus-info/index.ts +20 -3
  288. package/src/locus-info/selfUtils.ts +24 -6
  289. package/src/media/MediaConnectionAwaiter.ts +2 -0
  290. package/src/media/properties.ts +34 -13
  291. package/src/meeting/brbState.ts +169 -0
  292. package/src/meeting/in-meeting-actions.ts +25 -0
  293. package/src/meeting/index.ts +443 -87
  294. package/src/meeting/locusMediaRequest.ts +11 -8
  295. package/src/meeting/muteState.ts +1 -6
  296. package/src/meeting/request.ts +30 -12
  297. package/src/meeting/request.type.ts +7 -0
  298. package/src/meeting/util.ts +32 -13
  299. package/src/meeting-info/meeting-info-v2.ts +83 -12
  300. package/src/meeting-info/utilv2.ts +17 -3
  301. package/src/meetings/index.ts +79 -20
  302. package/src/meetings/meetings.types.ts +10 -0
  303. package/src/meetings/util.ts +2 -1
  304. package/src/member/index.ts +9 -0
  305. package/src/member/types.ts +8 -0
  306. package/src/member/util.ts +34 -24
  307. package/src/members/util.ts +1 -0
  308. package/src/metrics/constants.ts +6 -1
  309. package/src/multistream/remoteMedia.ts +28 -15
  310. package/src/multistream/sendSlotManager.ts +31 -0
  311. package/src/reachability/clusterReachability.ts +5 -15
  312. package/src/reachability/index.ts +311 -75
  313. package/src/reachability/reachability.types.ts +85 -0
  314. package/src/reachability/request.ts +55 -31
  315. package/src/recording-controller/enums.ts +5 -2
  316. package/src/recording-controller/index.ts +17 -4
  317. package/src/recording-controller/util.ts +20 -5
  318. package/src/roap/index.ts +14 -13
  319. package/src/roap/request.ts +30 -44
  320. package/src/roap/turnDiscovery.ts +2 -4
  321. package/src/webinar/index.ts +235 -9
  322. package/test/unit/spec/annotation/index.ts +46 -1
  323. package/test/unit/spec/locus-info/index.js +292 -60
  324. package/test/unit/spec/locus-info/selfConstant.js +7 -0
  325. package/test/unit/spec/locus-info/selfUtils.js +101 -1
  326. package/test/unit/spec/media/properties.ts +15 -0
  327. package/test/unit/spec/meeting/brbState.ts +114 -0
  328. package/test/unit/spec/meeting/in-meeting-actions.ts +15 -1
  329. package/test/unit/spec/meeting/index.js +851 -107
  330. package/test/unit/spec/meeting/locusMediaRequest.ts +18 -11
  331. package/test/unit/spec/meeting/muteState.js +0 -24
  332. package/test/unit/spec/meeting/request.js +3 -26
  333. package/test/unit/spec/meeting/utils.js +73 -28
  334. package/test/unit/spec/meeting-info/meetinginfov2.js +46 -4
  335. package/test/unit/spec/meeting-info/utilv2.js +26 -0
  336. package/test/unit/spec/meetings/index.js +159 -18
  337. package/test/unit/spec/meetings/utils.js +10 -0
  338. package/test/unit/spec/member/util.js +52 -11
  339. package/test/unit/spec/members/utils.js +95 -0
  340. package/test/unit/spec/multistream/remoteMedia.ts +11 -7
  341. package/test/unit/spec/reachability/clusterReachability.ts +7 -0
  342. package/test/unit/spec/reachability/index.ts +383 -9
  343. package/test/unit/spec/reachability/request.js +48 -12
  344. package/test/unit/spec/recording-controller/index.js +61 -5
  345. package/test/unit/spec/recording-controller/util.js +39 -3
  346. package/test/unit/spec/roap/index.ts +48 -1
  347. package/test/unit/spec/roap/request.ts +51 -109
  348. package/test/unit/spec/roap/turnDiscovery.ts +202 -147
  349. package/test/unit/spec/webinar/index.ts +504 -0
  350. package/dist/common/errors/webinar-registration-error.js.map +0 -1
  351. package/src/common/errors/webinar-registration-error.ts +0 -27
@@ -38,21 +38,25 @@ describe('TurnDiscovery', () => {
38
38
  mediaId: 'fake media id',
39
39
  locusUrl: `https://locus-a.wbx2.com/locus/api/v1/loci/${FAKE_LOCUS_ID}`,
40
40
  roapSeq: -1,
41
- audio:{
41
+ audio: {
42
42
  isLocallyMuted: () => true,
43
43
  },
44
- video:{
44
+ video: {
45
45
  isLocallyMuted: () => false,
46
46
  },
47
47
  setRoapSeq: sinon.fake((newSeq) => {
48
48
  testMeeting.roapSeq = newSeq;
49
49
  }),
50
50
  updateMediaConnections: sinon.stub(),
51
- webex: {meetings: {reachability: {
52
- isAnyPublicClusterReachable: () => Promise.resolve(false),
53
- }}},
51
+ webex: {
52
+ meetings: {
53
+ reachability: {
54
+ isAnyPublicClusterReachable: () => Promise.resolve(false),
55
+ },
56
+ },
57
+ },
54
58
  isMultistream: false,
55
- locusMediaRequest: { fake: true },
59
+ locusMediaRequest: {fake: true},
56
60
  };
57
61
  });
58
62
 
@@ -78,13 +82,15 @@ describe('TurnDiscovery', () => {
78
82
  },
79
83
  locusSelfUrl: testMeeting.selfUrl,
80
84
  mediaId: expectedMediaId,
81
- meetingId: testMeeting.id,
85
+ isMultistream: testMeeting.isMultistream,
82
86
  locusMediaRequest: testMeeting.locusMediaRequest,
83
87
  };
84
88
 
85
89
  if (messageType === 'TURN_DISCOVERY_REQUEST') {
86
- expectedSendRoapArgs.ipVersion = 0;
87
- expectedSendRoapArgs.roapMessage.headers = ['includeAnswerInHttpResponse', 'noOkInTransaction'];
90
+ expectedSendRoapArgs.roapMessage.headers = [
91
+ 'includeAnswerInHttpResponse',
92
+ 'noOkInTransaction',
93
+ ];
88
94
  }
89
95
 
90
96
  assert.calledWith(mockRoapRequest.sendRoap, expectedSendRoapArgs);
@@ -121,7 +127,12 @@ describe('TurnDiscovery', () => {
121
127
  });
122
128
 
123
129
  // checks that OK roap message was sent or not sent and that the result is as expected
124
- const checkResult = async (resultPromise, expectedRoapMessageSent, expectedResult, expectedSkipReason?: string) => {
130
+ const checkResult = async (
131
+ resultPromise,
132
+ expectedRoapMessageSent,
133
+ expectedResult,
134
+ expectedSkipReason?: string
135
+ ) => {
125
136
  let turnServerInfo, turnDiscoverySkippedReason;
126
137
 
127
138
  if (expectedRoapMessageSent === 'OK') {
@@ -261,9 +272,11 @@ describe('TurnDiscovery', () => {
261
272
  },
262
273
  ],
263
274
  };
264
- mockRoapRequest.sendRoap = sinon.fake.returns(new Promise((resolve) => {
265
- sendRoapPromiseResolve = resolve;
266
- }));
275
+ mockRoapRequest.sendRoap = sinon.fake.returns(
276
+ new Promise((resolve) => {
277
+ sendRoapPromiseResolve = resolve;
278
+ })
279
+ );
267
280
 
268
281
  const td = new TurnDiscovery(mockRoapRequest);
269
282
  const result = td.doTurnDiscovery(testMeeting, false);
@@ -302,7 +315,12 @@ describe('TurnDiscovery', () => {
302
315
  // @ts-ignore
303
316
  mockRoapRequest.sendRoap.resetHistory();
304
317
 
305
- await checkResult(result, undefined, undefined, 'failure: Unexpected token o in JSON at position 1');
318
+ await checkResult(
319
+ result,
320
+ undefined,
321
+ undefined,
322
+ 'failure: Unexpected token o in JSON at position 1'
323
+ );
306
324
  checkFailureMetricsSent();
307
325
  });
308
326
 
@@ -366,7 +384,12 @@ describe('TurnDiscovery', () => {
366
384
  // @ts-ignore
367
385
  mockRoapRequest.sendRoap.resetHistory();
368
386
 
369
- await checkResult(result, undefined, undefined, 'failure: TURN_DISCOVERY_RESPONSE in http response has unexpected messageType: {"seq":"0","messageType":"ERROR"}');
387
+ await checkResult(
388
+ result,
389
+ undefined,
390
+ undefined,
391
+ 'failure: TURN_DISCOVERY_RESPONSE in http response has unexpected messageType: {"seq":"0","messageType":"ERROR"}'
392
+ );
370
393
  });
371
394
  });
372
395
  });
@@ -534,7 +557,10 @@ describe('TurnDiscovery', () => {
534
557
  const {turnServerInfo, turnDiscoverySkippedReason} = await promise;
535
558
 
536
559
  assert.isUndefined(turnServerInfo);
537
- assert.equal(turnDiscoverySkippedReason, 'failure: Timed out waiting for TURN_DISCOVERY_RESPONSE');
560
+ assert.equal(
561
+ turnDiscoverySkippedReason,
562
+ 'failure: Timed out waiting for TURN_DISCOVERY_RESPONSE'
563
+ );
538
564
  checkFailureMetricsSent();
539
565
  });
540
566
 
@@ -559,7 +585,10 @@ describe('TurnDiscovery', () => {
559
585
  const {turnServerInfo, turnDiscoverySkippedReason} = await turnDiscoveryPromise;
560
586
 
561
587
  assert.isUndefined(turnServerInfo);
562
- assert.equal(turnDiscoverySkippedReason, `failure: TURN_DISCOVERY_RESPONSE from test missing some headers: ["x-cisco-turn-url=${FAKE_TURN_URL}","x-cisco-turn-username=${FAKE_TURN_USERNAME}"]`);
588
+ assert.equal(
589
+ turnDiscoverySkippedReason,
590
+ `failure: TURN_DISCOVERY_RESPONSE from test missing some headers: ["x-cisco-turn-url=${FAKE_TURN_URL}","x-cisco-turn-username=${FAKE_TURN_USERNAME}"]`
591
+ );
563
592
  checkFailureMetricsSent();
564
593
  });
565
594
 
@@ -576,7 +605,10 @@ describe('TurnDiscovery', () => {
576
605
  const {turnServerInfo, turnDiscoverySkippedReason} = await turnDiscoveryPromise;
577
606
 
578
607
  assert.isUndefined(turnServerInfo);
579
- assert.equal(turnDiscoverySkippedReason, 'failure: TURN_DISCOVERY_RESPONSE from test missing some headers: undefined');
608
+ assert.equal(
609
+ turnDiscoverySkippedReason,
610
+ 'failure: TURN_DISCOVERY_RESPONSE from test missing some headers: undefined'
611
+ );
580
612
  checkFailureMetricsSent();
581
613
  });
582
614
 
@@ -596,7 +628,10 @@ describe('TurnDiscovery', () => {
596
628
  const {turnServerInfo, turnDiscoverySkippedReason} = await turnDiscoveryPromise;
597
629
 
598
630
  assert.isUndefined(turnServerInfo);
599
- assert.equal(turnDiscoverySkippedReason, 'failure: TURN_DISCOVERY_RESPONSE from test missing some headers: []');
631
+ assert.equal(
632
+ turnDiscoverySkippedReason,
633
+ 'failure: TURN_DISCOVERY_RESPONSE from test missing some headers: []'
634
+ );
600
635
  checkFailureMetricsSent();
601
636
  });
602
637
 
@@ -646,17 +681,21 @@ describe('TurnDiscovery', () => {
646
681
  {isAnyPublicClusterReachable: true, expectedIsSkipped: true},
647
682
  {isAnyPublicClusterReachable: false, expectedIsSkipped: false},
648
683
  ].forEach(({isAnyPublicClusterReachable, expectedIsSkipped}) => {
649
- it(`returns ${expectedIsSkipped} when isAnyPublicClusterReachable() returns ${isAnyPublicClusterReachable ? 'true' : 'false'}`, async () => {
650
- sinon.stub(testMeeting.webex.meetings.reachability, 'isAnyPublicClusterReachable').resolves(isAnyPublicClusterReachable);
684
+ it(`returns ${expectedIsSkipped} when isAnyPublicClusterReachable() returns ${
685
+ isAnyPublicClusterReachable ? 'true' : 'false'
686
+ }`, async () => {
687
+ sinon
688
+ .stub(testMeeting.webex.meetings.reachability, 'isAnyPublicClusterReachable')
689
+ .resolves(isAnyPublicClusterReachable);
651
690
 
652
691
  const td = new TurnDiscovery(mockRoapRequest);
653
692
 
654
693
  const isSkipped = await td.isSkipped(testMeeting);
655
694
 
656
695
  assert.equal(isSkipped, expectedIsSkipped);
657
- })
658
- })
659
- })
696
+ });
697
+ });
698
+ });
660
699
 
661
700
  describe('handleTurnDiscoveryResponse', () => {
662
701
  it("doesn't do anything if turn discovery was not started", () => {
@@ -664,14 +703,17 @@ describe('TurnDiscovery', () => {
664
703
 
665
704
  // there is not much we can check, but we mainly want to make
666
705
  // sure that it doesn't crash
667
- td.handleTurnDiscoveryResponse({
668
- messageType: 'TURN_DISCOVERY_RESPONSE',
669
- headers: [
670
- `x-cisco-turn-url=${FAKE_TURN_URL}`,
671
- `x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
672
- `x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
673
- ],
674
- }, 'from test');
706
+ td.handleTurnDiscoveryResponse(
707
+ {
708
+ messageType: 'TURN_DISCOVERY_RESPONSE',
709
+ headers: [
710
+ `x-cisco-turn-url=${FAKE_TURN_URL}`,
711
+ `x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
712
+ `x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
713
+ ],
714
+ },
715
+ 'from test'
716
+ );
675
717
 
676
718
  assert.notCalled(mockRoapRequest.sendRoap);
677
719
  });
@@ -743,9 +785,11 @@ describe('TurnDiscovery', () => {
743
785
  let promiseResolve;
744
786
 
745
787
  // set it up so that doTurnDiscovery doesn't complete
746
- mockRoapRequest.sendRoap = sinon.fake.returns(new Promise((resolve) => {
747
- promiseResolve = resolve;
748
- }));
788
+ mockRoapRequest.sendRoap = sinon.fake.returns(
789
+ new Promise((resolve) => {
790
+ promiseResolve = resolve;
791
+ })
792
+ );
749
793
  td.doTurnDiscovery(testMeeting, false, true);
750
794
 
751
795
  // now call generateTurnDiscoveryRequestMessage
@@ -775,19 +819,19 @@ describe('TurnDiscovery', () => {
775
819
  `x-cisco-turn-url=${FAKE_TURN_URL}`,
776
820
  `x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
777
821
  `x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
778
- 'noOkInTransaction'
822
+ 'noOkInTransaction',
779
823
  ],
780
- }
824
+ };
781
825
 
782
826
  td = new TurnDiscovery(mockRoapRequest);
783
827
  });
784
828
 
785
829
  // checks if another TURN discovery can be started without any problem
786
830
  const checkNextTurnDiscovery = async () => {
787
- // after each test check that another TURN discovery can be started without any problems
788
- const secondMessage = await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
831
+ // after each test check that another TURN discovery can be started without any problems
832
+ const secondMessage = await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
789
833
 
790
- assert.isDefined(secondMessage.roapMessage);
834
+ assert.isDefined(secondMessage.roapMessage);
791
835
  };
792
836
 
793
837
  it('works as expected when called with undefined httpResponse', async () => {
@@ -804,8 +848,14 @@ describe('TurnDiscovery', () => {
804
848
  [
805
849
  {testCase: 'is missing mediaConnections', httpResponse: {}},
806
850
  {testCase: 'is missing mediaConnections[0]', httpResponse: {mediaConnections: []}},
807
- {testCase: 'is missing mediaConnections[0].remoteSdp', httpResponse: {mediaConnections: [{}]}},
808
- {testCase: 'is missing roapMesssage in mediaConnections[0].remoteSdp', httpResponse: {mediaConnections: [{remoteSdp: JSON.stringify({something: "whatever"})}]}},
851
+ {
852
+ testCase: 'is missing mediaConnections[0].remoteSdp',
853
+ httpResponse: {mediaConnections: [{}]},
854
+ },
855
+ {
856
+ testCase: 'is missing roapMesssage in mediaConnections[0].remoteSdp',
857
+ httpResponse: {mediaConnections: [{remoteSdp: JSON.stringify({something: 'whatever'})}]},
858
+ },
809
859
  ].forEach(({testCase, httpResponse}) => {
810
860
  it(`handles httpResponse that ${testCase}`, async () => {
811
861
  await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
@@ -817,145 +867,150 @@ describe('TurnDiscovery', () => {
817
867
  turnDiscoverySkippedReason: 'missing http response',
818
868
  });
819
869
  });
820
- });
821
-
822
- it('handles httpResponse with invalid JSON in mediaConnections[0].remoteSdp', async () => {
823
- await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
870
+ });
824
871
 
825
- const result = await td.handleTurnDiscoveryHttpResponse(testMeeting, {mediaConnections: [{remoteSdp: 'not a json'}]});
872
+ it('handles httpResponse with invalid JSON in mediaConnections[0].remoteSdp', async () => {
873
+ await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
826
874
 
827
- assert.deepEqual(result, {
828
- turnServerInfo: undefined,
829
- turnDiscoverySkippedReason: 'failure: Unexpected token o in JSON at position 1',
830
- });
875
+ const result = await td.handleTurnDiscoveryHttpResponse(testMeeting, {
876
+ mediaConnections: [{remoteSdp: 'not a json'}],
831
877
  });
832
878
 
833
- it('fails when called before generateTurnDiscoveryRequestMessage() was called', async () => {
834
- const httpResponse = {mediaConnections: [{remoteSdp: JSON.stringify({roapMessage})}]};
835
- await assert.isRejected(td.handleTurnDiscoveryHttpResponse(testMeeting, httpResponse),
836
- 'handleTurnDiscoveryHttpResponse() called before generateTurnDiscoveryRequestMessage()');
879
+ assert.deepEqual(result, {
880
+ turnServerInfo: undefined,
881
+ turnDiscoverySkippedReason: 'failure: Unexpected token o in JSON at position 1',
837
882
  });
883
+ });
838
884
 
839
- it('works as expected when called with valid httpResponse', async () => {
840
- const httpResponse = {mediaConnections: [{remoteSdp: JSON.stringify({roapMessage})}]};
885
+ it('fails when called before generateTurnDiscoveryRequestMessage() was called', async () => {
886
+ const httpResponse = {mediaConnections: [{remoteSdp: JSON.stringify({roapMessage})}]};
887
+ await assert.isRejected(
888
+ td.handleTurnDiscoveryHttpResponse(testMeeting, httpResponse),
889
+ 'handleTurnDiscoveryHttpResponse() called before generateTurnDiscoveryRequestMessage()'
890
+ );
891
+ });
841
892
 
842
- // we spy on handleTurnDiscoveryResponse and check that it's called so that we don't have to repeat
843
- // all the edge case tests here, they're already covered in other tests that call handleTurnDiscoveryResponse
844
- const handleTurnDiscoveryResponseSpy = sinon.spy(td, 'handleTurnDiscoveryResponse');
893
+ it('works as expected when called with valid httpResponse', async () => {
894
+ const httpResponse = {mediaConnections: [{remoteSdp: JSON.stringify({roapMessage})}]};
845
895
 
846
- await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
847
- const result = await td.handleTurnDiscoveryHttpResponse(testMeeting, httpResponse);
896
+ // we spy on handleTurnDiscoveryResponse and check that it's called so that we don't have to repeat
897
+ // all the edge case tests here, they're already covered in other tests that call handleTurnDiscoveryResponse
898
+ const handleTurnDiscoveryResponseSpy = sinon.spy(td, 'handleTurnDiscoveryResponse');
848
899
 
849
- assert.deepEqual(result, {
850
- turnServerInfo: {
851
- url: FAKE_TURN_URL,
852
- username: FAKE_TURN_USERNAME,
853
- password: FAKE_TURN_PASSWORD,
854
- },
855
- turnDiscoverySkippedReason: undefined,
856
- });
900
+ await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
901
+ const result = await td.handleTurnDiscoveryHttpResponse(testMeeting, httpResponse);
857
902
 
858
- assert.calledOnceWithExactly(handleTurnDiscoveryResponseSpy, roapMessage, 'in http response');
903
+ assert.deepEqual(result, {
904
+ turnServerInfo: {
905
+ url: FAKE_TURN_URL,
906
+ username: FAKE_TURN_USERNAME,
907
+ password: FAKE_TURN_PASSWORD,
908
+ },
909
+ turnDiscoverySkippedReason: undefined,
859
910
  });
860
911
 
861
- it('works as expected when httpResponse is missing some headers', async () => {
862
- roapMessage.headers = [
863
- `x-cisco-turn-url=${FAKE_TURN_URL}`, // missing headers for username and password
864
- ];
912
+ assert.calledOnceWithExactly(handleTurnDiscoveryResponseSpy, roapMessage, 'in http response');
913
+ });
865
914
 
866
- const httpResponse = {mediaConnections: [{remoteSdp: JSON.stringify({roapMessage})}]};
915
+ it('works as expected when httpResponse is missing some headers', async () => {
916
+ roapMessage.headers = [
917
+ `x-cisco-turn-url=${FAKE_TURN_URL}`, // missing headers for username and password
918
+ ];
867
919
 
868
- // we spy on handleTurnDiscoveryResponse and check that it's called so that we don't have to repeat
869
- // all the edge case tests here, they're already covered in other tests that call handleTurnDiscoveryResponse
870
- // we test just this 1 edge case here to confirm that when handleTurnDiscoveryResponse rejects, we get the correct result
871
- const handleTurnDiscoveryResponseSpy = sinon.spy(td, 'handleTurnDiscoveryResponse');
920
+ const httpResponse = {mediaConnections: [{remoteSdp: JSON.stringify({roapMessage})}]};
872
921
 
873
- await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
874
- const result = await td.handleTurnDiscoveryHttpResponse(testMeeting, httpResponse);
922
+ // we spy on handleTurnDiscoveryResponse and check that it's called so that we don't have to repeat
923
+ // all the edge case tests here, they're already covered in other tests that call handleTurnDiscoveryResponse
924
+ // we test just this 1 edge case here to confirm that when handleTurnDiscoveryResponse rejects, we get the correct result
925
+ const handleTurnDiscoveryResponseSpy = sinon.spy(td, 'handleTurnDiscoveryResponse');
875
926
 
876
- assert.deepEqual(result, {
877
- turnServerInfo: undefined,
878
- turnDiscoverySkippedReason: 'failure: TURN_DISCOVERY_RESPONSE in http response missing some headers: ["x-cisco-turn-url=turns:fakeTurnServer.com:443?transport=tcp"]',
879
- });
880
- assert.calledOnceWithExactly(handleTurnDiscoveryResponseSpy, roapMessage, 'in http response');
927
+ await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
928
+ const result = await td.handleTurnDiscoveryHttpResponse(testMeeting, httpResponse);
881
929
 
882
- checkNextTurnDiscovery();
930
+ assert.deepEqual(result, {
931
+ turnServerInfo: undefined,
932
+ turnDiscoverySkippedReason:
933
+ 'failure: TURN_DISCOVERY_RESPONSE in http response missing some headers: ["x-cisco-turn-url=turns:fakeTurnServer.com:443?transport=tcp"]',
883
934
  });
935
+ assert.calledOnceWithExactly(handleTurnDiscoveryResponseSpy, roapMessage, 'in http response');
884
936
 
885
- it('sends OK when required', async () => {
886
- roapMessage.headers = [
887
- `x-cisco-turn-url=${FAKE_TURN_URL}`,
888
- `x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
889
- `x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
890
- // noOkInTransaction is missing
891
- ];
892
- const httpResponse = {mediaConnections: [{remoteSdp: JSON.stringify({roapMessage})}]};
937
+ checkNextTurnDiscovery();
938
+ });
893
939
 
894
- await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
895
- const result = await td.handleTurnDiscoveryHttpResponse(testMeeting, httpResponse);
940
+ it('sends OK when required', async () => {
941
+ roapMessage.headers = [
942
+ `x-cisco-turn-url=${FAKE_TURN_URL}`,
943
+ `x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
944
+ `x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
945
+ // noOkInTransaction is missing
946
+ ];
947
+ const httpResponse = {mediaConnections: [{remoteSdp: JSON.stringify({roapMessage})}]};
896
948
 
897
- assert.deepEqual(result, {
898
- turnServerInfo: {
899
- url: FAKE_TURN_URL,
900
- username: FAKE_TURN_USERNAME,
901
- password: FAKE_TURN_PASSWORD,
902
- },
903
- turnDiscoverySkippedReason: undefined,
904
- });
949
+ await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
950
+ const result = await td.handleTurnDiscoveryHttpResponse(testMeeting, httpResponse);
905
951
 
906
- // check that OK was sent along with the metric for it
907
- await checkRoapMessageSent('OK', 0);
952
+ assert.deepEqual(result, {
953
+ turnServerInfo: {
954
+ url: FAKE_TURN_URL,
955
+ username: FAKE_TURN_USERNAME,
956
+ password: FAKE_TURN_PASSWORD,
957
+ },
958
+ turnDiscoverySkippedReason: undefined,
959
+ });
908
960
 
909
- assert.calledWith(
910
- Metrics.sendBehavioralMetric,
911
- BEHAVIORAL_METRICS.TURN_DISCOVERY_REQUIRES_OK,
912
- sinon.match({
913
- correlation_id: testMeeting.correlationId,
914
- locus_id: FAKE_LOCUS_ID,
915
- })
916
- );
961
+ // check that OK was sent along with the metric for it
962
+ await checkRoapMessageSent('OK', 0);
917
963
 
918
- checkNextTurnDiscovery();
919
- });
964
+ assert.calledWith(
965
+ Metrics.sendBehavioralMetric,
966
+ BEHAVIORAL_METRICS.TURN_DISCOVERY_REQUIRES_OK,
967
+ sinon.match({
968
+ correlation_id: testMeeting.correlationId,
969
+ locus_id: FAKE_LOCUS_ID,
970
+ })
971
+ );
920
972
 
921
- describe('abort', () => {
922
- it('allows starting a new TURN discovery', async () => {
923
- let result;
973
+ checkNextTurnDiscovery();
974
+ });
924
975
 
925
- // this mock is required for doTurnDiscovery() to work
926
- mockRoapRequest.sendRoap = sinon.fake.resolves({
927
- mediaConnections: [
928
- {
929
- mediaId: '464ff97f-4bda-466a-ad06-3a22184a2274',
930
- remoteSdp: `{"roapMessage": {"messageType":"TURN_DISCOVERY_RESPONSE","seq":"0","headers": ["x-cisco-turn-url=${FAKE_TURN_URL}","x-cisco-turn-username=${FAKE_TURN_USERNAME}","x-cisco-turn-password=${FAKE_TURN_PASSWORD}", "noOkInTransaction"]}}`,
931
- },
932
- ],
933
- });
976
+ describe('abort', () => {
977
+ it('allows starting a new TURN discovery', async () => {
978
+ let result;
934
979
 
935
- result = await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
936
- assert.isDefined(result.roapMessage);
980
+ // this mock is required for doTurnDiscovery() to work
981
+ mockRoapRequest.sendRoap = sinon.fake.resolves({
982
+ mediaConnections: [
983
+ {
984
+ mediaId: '464ff97f-4bda-466a-ad06-3a22184a2274',
985
+ remoteSdp: `{"roapMessage": {"messageType":"TURN_DISCOVERY_RESPONSE","seq":"0","headers": ["x-cisco-turn-url=${FAKE_TURN_URL}","x-cisco-turn-username=${FAKE_TURN_USERNAME}","x-cisco-turn-password=${FAKE_TURN_PASSWORD}", "noOkInTransaction"]}}`,
986
+ },
987
+ ],
988
+ });
937
989
 
938
- td.abort();
990
+ result = await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
991
+ assert.isDefined(result.roapMessage);
939
992
 
940
- result = await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
941
- assert.isDefined(result.roapMessage);
993
+ td.abort();
942
994
 
943
- td.abort();
995
+ result = await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
996
+ assert.isDefined(result.roapMessage);
944
997
 
945
- // check also that doTurnDiscovery() works after abort()
946
- result = await td.doTurnDiscovery(testMeeting, false);
947
- });
998
+ td.abort();
999
+
1000
+ // check also that doTurnDiscovery() works after abort()
1001
+ result = await td.doTurnDiscovery(testMeeting, false);
1002
+ });
948
1003
 
949
- it('does nothing when called outside of a TURN discovery', async () => {
950
- let result;
1004
+ it('does nothing when called outside of a TURN discovery', async () => {
1005
+ let result;
951
1006
 
952
- // call abort() without any other calls before it - it should do nothing
953
- // there is not much we can check, so afterwards we just check that we can start a new TURN discovery
954
- td.abort();
1007
+ // call abort() without any other calls before it - it should do nothing
1008
+ // there is not much we can check, so afterwards we just check that we can start a new TURN discovery
1009
+ td.abort();
955
1010
 
956
- result = await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
957
- assert.isDefined(result.roapMessage);
958
- });
1011
+ result = await td.generateTurnDiscoveryRequestMessage(testMeeting, true);
1012
+ assert.isDefined(result.roapMessage);
959
1013
  });
1014
+ });
960
1015
  });
961
1016
  });