@webex/plugin-meetings 3.0.0-bnr.5 → 3.0.0-stream-classes.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. package/README.md +46 -8
  2. package/dist/annotation/annotation.types.js +7 -0
  3. package/dist/annotation/annotation.types.js.map +1 -0
  4. package/dist/annotation/constants.js +49 -0
  5. package/dist/annotation/constants.js.map +1 -0
  6. package/dist/annotation/index.js +342 -0
  7. package/dist/annotation/index.js.map +1 -0
  8. package/dist/breakouts/breakout.js +70 -32
  9. package/dist/breakouts/breakout.js.map +1 -1
  10. package/dist/breakouts/events.js +45 -0
  11. package/dist/breakouts/events.js.map +1 -0
  12. package/dist/breakouts/index.js +422 -217
  13. package/dist/breakouts/index.js.map +1 -1
  14. package/dist/breakouts/utils.js +12 -1
  15. package/dist/breakouts/utils.js.map +1 -1
  16. package/dist/common/errors/webex-errors.js +3 -2
  17. package/dist/common/errors/webex-errors.js.map +1 -1
  18. package/dist/common/logs/logger-proxy.js +1 -1
  19. package/dist/common/logs/logger-proxy.js.map +1 -1
  20. package/dist/common/logs/request.d.ts +1 -1
  21. package/dist/common/queue.js +24 -9
  22. package/dist/common/queue.js.map +1 -1
  23. package/dist/config.js +1 -7
  24. package/dist/config.js.map +1 -1
  25. package/dist/constants.js +118 -24
  26. package/dist/constants.js.map +1 -1
  27. package/dist/controls-options-manager/enums.js +2 -0
  28. package/dist/controls-options-manager/enums.js.map +1 -1
  29. package/dist/controls-options-manager/index.js +19 -14
  30. package/dist/controls-options-manager/index.js.map +1 -1
  31. package/dist/controls-options-manager/types.js.map +1 -1
  32. package/dist/controls-options-manager/util.js +80 -11
  33. package/dist/controls-options-manager/util.js.map +1 -1
  34. package/dist/index.js +62 -20
  35. package/dist/index.js.map +1 -1
  36. package/dist/interpretation/collection.js +23 -0
  37. package/dist/interpretation/collection.js.map +1 -0
  38. package/dist/interpretation/index.js +366 -0
  39. package/dist/interpretation/index.js.map +1 -0
  40. package/dist/interpretation/siLanguage.js +25 -0
  41. package/dist/interpretation/siLanguage.js.map +1 -0
  42. package/dist/locus-info/controlsUtils.js +71 -1
  43. package/dist/locus-info/controlsUtils.js.map +1 -1
  44. package/dist/locus-info/index.js +305 -57
  45. package/dist/locus-info/index.js.map +1 -1
  46. package/dist/locus-info/infoUtils.js +7 -1
  47. package/dist/locus-info/infoUtils.js.map +1 -1
  48. package/dist/locus-info/mediaSharesUtils.js +43 -1
  49. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  50. package/dist/locus-info/parser.js +219 -63
  51. package/dist/locus-info/parser.js.map +1 -1
  52. package/dist/locus-info/selfUtils.js +44 -22
  53. package/dist/locus-info/selfUtils.js.map +1 -1
  54. package/dist/media/index.js +57 -104
  55. package/dist/media/index.js.map +1 -1
  56. package/dist/media/properties.js +60 -121
  57. package/dist/media/properties.js.map +1 -1
  58. package/dist/meeting/in-meeting-actions.js +61 -3
  59. package/dist/meeting/in-meeting-actions.js.map +1 -1
  60. package/dist/meeting/index.js +2530 -2534
  61. package/dist/meeting/index.js.map +1 -1
  62. package/dist/meeting/locusMediaRequest.js +292 -0
  63. package/dist/meeting/locusMediaRequest.js.map +1 -0
  64. package/dist/meeting/muteState.js +125 -205
  65. package/dist/meeting/muteState.js.map +1 -1
  66. package/dist/meeting/request.js +150 -150
  67. package/dist/meeting/request.js.map +1 -1
  68. package/dist/meeting/util.js +568 -438
  69. package/dist/meeting/util.js.map +1 -1
  70. package/dist/meeting-info/index.js +48 -7
  71. package/dist/meeting-info/index.js.map +1 -1
  72. package/dist/meeting-info/meeting-info-v2.js +94 -38
  73. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  74. package/dist/meeting-info/utilv2.js +4 -2
  75. package/dist/meeting-info/utilv2.js.map +1 -1
  76. package/dist/meetings/index.d.ts +0 -2
  77. package/dist/meetings/index.js +260 -85
  78. package/dist/meetings/index.js.map +1 -1
  79. package/dist/meetings/meetings.types.js +7 -0
  80. package/dist/meetings/meetings.types.js.map +1 -0
  81. package/dist/meetings/util.js +42 -7
  82. package/dist/meetings/util.js.map +1 -1
  83. package/dist/member/index.d.ts +2 -0
  84. package/dist/member/index.js +26 -0
  85. package/dist/member/index.js.map +1 -1
  86. package/dist/member/member.types.d.ts +11 -0
  87. package/dist/member/member.types.js +18 -0
  88. package/dist/member/member.types.js.map +1 -0
  89. package/dist/member/types.js +11 -1
  90. package/dist/member/types.js.map +1 -1
  91. package/dist/member/util.js +60 -23
  92. package/dist/member/util.js.map +1 -1
  93. package/dist/members/index.js +4 -1
  94. package/dist/members/index.js.map +1 -1
  95. package/dist/members/request.js +75 -45
  96. package/dist/members/request.js.map +1 -1
  97. package/dist/members/util.js +308 -317
  98. package/dist/members/util.js.map +1 -1
  99. package/dist/metrics/config.js +1 -3
  100. package/dist/metrics/config.js.map +1 -1
  101. package/dist/metrics/constants.js +1 -0
  102. package/dist/metrics/constants.js.map +1 -1
  103. package/dist/metrics/index.d.ts +1 -1
  104. package/dist/metrics/index.js +1 -451
  105. package/dist/metrics/index.js.map +1 -1
  106. package/dist/multistream/mediaRequestManager.js +136 -40
  107. package/dist/multistream/mediaRequestManager.js.map +1 -1
  108. package/dist/multistream/receiveSlot.js.map +1 -1
  109. package/dist/multistream/receiveSlotManager.js +4 -4
  110. package/dist/multistream/receiveSlotManager.js.map +1 -1
  111. package/dist/multistream/remoteMedia.js.map +1 -1
  112. package/dist/multistream/remoteMediaGroup.js +60 -3
  113. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  114. package/dist/multistream/remoteMediaManager.js +36 -0
  115. package/dist/multistream/remoteMediaManager.js.map +1 -1
  116. package/dist/multistream/sendSlotManager.js +233 -0
  117. package/dist/multistream/sendSlotManager.js.map +1 -0
  118. package/dist/reachability/index.js +18 -3
  119. package/dist/reachability/index.js.map +1 -1
  120. package/dist/reachability/request.js +5 -3
  121. package/dist/reachability/request.js.map +1 -1
  122. package/dist/reconnection-manager/index.js +181 -153
  123. package/dist/reconnection-manager/index.js.map +1 -1
  124. package/dist/recording-controller/index.js +21 -2
  125. package/dist/recording-controller/index.js.map +1 -1
  126. package/dist/recording-controller/util.js +9 -8
  127. package/dist/recording-controller/util.js.map +1 -1
  128. package/dist/roap/index.js +25 -32
  129. package/dist/roap/index.js.map +1 -1
  130. package/dist/roap/request.js +42 -51
  131. package/dist/roap/request.js.map +1 -1
  132. package/dist/roap/turnDiscovery.js +97 -38
  133. package/dist/roap/turnDiscovery.js.map +1 -1
  134. package/dist/rtcMetrics/constants.js +12 -0
  135. package/dist/rtcMetrics/constants.js.map +1 -0
  136. package/dist/rtcMetrics/index.js +117 -0
  137. package/dist/rtcMetrics/index.js.map +1 -0
  138. package/dist/statsAnalyzer/index.js +0 -1
  139. package/dist/statsAnalyzer/index.js.map +1 -1
  140. package/dist/types/annotation/annotation.types.d.ts +43 -0
  141. package/dist/types/annotation/constants.d.ts +31 -0
  142. package/dist/types/annotation/index.d.ts +124 -0
  143. package/dist/types/breakouts/events.d.ts +2 -0
  144. package/dist/types/breakouts/utils.d.ts +7 -0
  145. package/dist/types/common/errors/webex-errors.d.ts +1 -1
  146. package/dist/types/config.d.ts +0 -6
  147. package/dist/types/constants.d.ts +51 -21
  148. package/dist/types/controls-options-manager/enums.d.ts +2 -0
  149. package/dist/types/controls-options-manager/index.d.ts +1 -1
  150. package/dist/types/controls-options-manager/types.d.ts +7 -1
  151. package/dist/types/index.d.ts +1 -1
  152. package/dist/types/interpretation/collection.d.ts +5 -0
  153. package/dist/types/interpretation/index.d.ts +5 -0
  154. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  155. package/dist/types/locus-info/index.d.ts +39 -1
  156. package/dist/types/media/index.d.ts +2 -0
  157. package/dist/types/media/properties.d.ts +16 -38
  158. package/dist/types/meeting/in-meeting-actions.d.ts +46 -2
  159. package/dist/types/meeting/index.d.ts +179 -379
  160. package/dist/types/meeting/locusMediaRequest.d.ts +70 -0
  161. package/dist/types/meeting/muteState.d.ts +39 -40
  162. package/dist/types/meeting/request.d.ts +25 -26
  163. package/dist/types/meeting/util.d.ts +74 -1
  164. package/dist/types/meeting-info/meeting-info-v2.d.ts +14 -3
  165. package/dist/types/meetings/index.d.ts +49 -1
  166. package/dist/types/meetings/meetings.types.d.ts +4 -0
  167. package/dist/types/member/index.d.ts +2 -0
  168. package/dist/types/members/request.d.ts +56 -11
  169. package/dist/types/members/util.d.ts +209 -1
  170. package/dist/types/metrics/config.d.ts +26 -2
  171. package/dist/types/metrics/constants.d.ts +1 -0
  172. package/dist/types/metrics/index.d.ts +17 -0
  173. package/dist/types/multistream/mediaRequestManager.d.ts +27 -10
  174. package/dist/types/multistream/receiveSlot.d.ts +3 -3
  175. package/dist/types/multistream/remoteMedia.d.ts +2 -2
  176. package/dist/types/multistream/remoteMediaManager.d.ts +14 -0
  177. package/dist/types/roap/request.d.ts +6 -8
  178. package/dist/types/roap/turnDiscovery.d.ts +18 -1
  179. package/package.json +21 -20
  180. package/src/annotation/annotation.types.ts +50 -0
  181. package/src/annotation/constants.ts +36 -0
  182. package/src/annotation/index.ts +328 -0
  183. package/src/breakouts/README.md +3 -2
  184. package/src/breakouts/breakout.ts +62 -27
  185. package/src/breakouts/events.ts +56 -0
  186. package/src/breakouts/index.ts +244 -64
  187. package/src/breakouts/utils.ts +13 -0
  188. package/src/common/errors/webex-errors.ts +6 -2
  189. package/src/common/logs/logger-proxy.ts +1 -1
  190. package/src/common/queue.ts +22 -8
  191. package/src/config.ts +0 -6
  192. package/src/constants.ts +111 -19
  193. package/src/controls-options-manager/enums.ts +2 -0
  194. package/src/controls-options-manager/index.ts +13 -10
  195. package/src/controls-options-manager/types.ts +10 -0
  196. package/src/controls-options-manager/util.ts +82 -11
  197. package/src/index.ts +18 -11
  198. package/src/interpretation/README.md +60 -0
  199. package/src/interpretation/collection.ts +19 -0
  200. package/src/interpretation/index.ts +332 -0
  201. package/src/interpretation/siLanguage.ts +18 -0
  202. package/src/locus-info/controlsUtils.ts +81 -0
  203. package/src/locus-info/index.ts +318 -57
  204. package/src/locus-info/infoUtils.ts +10 -2
  205. package/src/locus-info/mediaSharesUtils.ts +48 -0
  206. package/src/locus-info/parser.ts +224 -39
  207. package/src/locus-info/selfUtils.ts +32 -20
  208. package/src/media/index.ts +94 -108
  209. package/src/media/properties.ts +69 -109
  210. package/src/meeting/in-meeting-actions.ts +120 -4
  211. package/src/meeting/index.ts +1967 -2120
  212. package/src/meeting/locusMediaRequest.ts +314 -0
  213. package/src/meeting/muteState.ts +119 -194
  214. package/src/meeting/request.ts +122 -115
  215. package/src/meeting/util.ts +549 -413
  216. package/src/meeting-info/index.ts +54 -8
  217. package/src/meeting-info/meeting-info-v2.ts +89 -24
  218. package/src/meeting-info/utilv2.ts +6 -2
  219. package/src/meetings/index.ts +247 -87
  220. package/src/meetings/meetings.types.ts +12 -0
  221. package/src/meetings/util.ts +47 -12
  222. package/src/member/index.ts +28 -1
  223. package/src/member/types.ts +14 -0
  224. package/src/member/util.ts +75 -26
  225. package/src/members/index.ts +7 -1
  226. package/src/members/request.ts +61 -21
  227. package/src/members/util.ts +316 -326
  228. package/src/metrics/constants.ts +1 -0
  229. package/src/metrics/index.ts +1 -474
  230. package/src/multistream/mediaRequestManager.ts +183 -67
  231. package/src/multistream/receiveSlot.ts +4 -4
  232. package/src/multistream/receiveSlotManager.ts +4 -4
  233. package/src/multistream/remoteMedia.ts +2 -2
  234. package/src/multistream/remoteMediaGroup.ts +59 -0
  235. package/src/multistream/remoteMediaManager.ts +33 -0
  236. package/src/multistream/sendSlotManager.ts +170 -0
  237. package/src/reachability/index.ts +15 -4
  238. package/src/reachability/request.ts +7 -3
  239. package/src/reconnection-manager/index.ts +36 -29
  240. package/src/recording-controller/index.ts +20 -3
  241. package/src/recording-controller/util.ts +26 -9
  242. package/src/roap/index.ts +25 -30
  243. package/src/roap/request.ts +44 -51
  244. package/src/roap/turnDiscovery.ts +51 -25
  245. package/src/rtcMetrics/constants.ts +3 -0
  246. package/src/rtcMetrics/index.ts +100 -0
  247. package/src/statsAnalyzer/index.ts +0 -1
  248. package/test/integration/spec/converged-space-meetings.js +60 -3
  249. package/test/integration/spec/journey.js +336 -259
  250. package/test/integration/spec/space-meeting.js +76 -3
  251. package/test/unit/spec/annotation/index.ts +418 -0
  252. package/test/unit/spec/breakouts/breakout.ts +85 -26
  253. package/test/unit/spec/breakouts/events.ts +89 -0
  254. package/test/unit/spec/breakouts/index.ts +636 -98
  255. package/test/unit/spec/breakouts/utils.js +19 -1
  256. package/test/unit/spec/common/queue.js +31 -2
  257. package/test/unit/spec/controls-options-manager/index.js +8 -1
  258. package/test/unit/spec/controls-options-manager/util.js +576 -397
  259. package/test/unit/spec/fixture/locus.js +1 -0
  260. package/test/unit/spec/interpretation/collection.ts +15 -0
  261. package/test/unit/spec/interpretation/index.ts +589 -0
  262. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  263. package/test/unit/spec/locus-info/controlsUtils.js +195 -1
  264. package/test/unit/spec/locus-info/index.js +950 -45
  265. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  266. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  267. package/test/unit/spec/locus-info/parser.js +62 -22
  268. package/test/unit/spec/locus-info/selfConstant.js +19 -0
  269. package/test/unit/spec/locus-info/selfUtils.js +131 -26
  270. package/test/unit/spec/media/index.ts +82 -79
  271. package/test/unit/spec/meeting/in-meeting-actions.ts +60 -2
  272. package/test/unit/spec/meeting/index.js +3208 -1734
  273. package/test/unit/spec/meeting/locusMediaRequest.ts +443 -0
  274. package/test/unit/spec/meeting/muteState.js +328 -417
  275. package/test/unit/spec/meeting/request.js +393 -48
  276. package/test/unit/spec/meeting/utils.js +552 -76
  277. package/test/unit/spec/meeting-info/index.js +181 -0
  278. package/test/unit/spec/meeting-info/meetinginfov2.js +258 -20
  279. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  280. package/test/unit/spec/meetings/index.js +631 -145
  281. package/test/unit/spec/meetings/utils.js +164 -9
  282. package/test/unit/spec/member/index.js +44 -14
  283. package/test/unit/spec/member/util.js +296 -155
  284. package/test/unit/spec/members/index.js +23 -3
  285. package/test/unit/spec/members/request.js +167 -35
  286. package/test/unit/spec/metrics/index.js +1 -50
  287. package/test/unit/spec/multistream/mediaRequestManager.ts +366 -8
  288. package/test/unit/spec/multistream/receiveSlot.ts +1 -1
  289. package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
  290. package/test/unit/spec/multistream/remoteMediaManager.ts +123 -0
  291. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  292. package/test/unit/spec/reachability/index.ts +66 -5
  293. package/test/unit/spec/reachability/request.js +3 -1
  294. package/test/unit/spec/reconnection-manager/index.js +55 -5
  295. package/test/unit/spec/recording-controller/index.js +294 -218
  296. package/test/unit/spec/recording-controller/util.js +223 -96
  297. package/test/unit/spec/roap/index.ts +21 -48
  298. package/test/unit/spec/roap/request.ts +74 -60
  299. package/test/unit/spec/roap/turnDiscovery.ts +30 -6
  300. package/test/unit/spec/rtcMetrics/index.ts +68 -0
  301. package/test/utils/integrationTestUtils.js +46 -0
  302. package/test/utils/testUtils.js +0 -60
  303. package/src/metrics/config.ts +0 -487
@@ -1,23 +1,32 @@
1
1
  import sinon from 'sinon';
2
2
  import {assert} from '@webex/test-helper-chai';
3
+ import Meetings from '@webex/plugin-meetings';
3
4
  import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
4
5
  import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
5
6
  import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
6
7
  import Metrics from '@webex/plugin-meetings/src/metrics/index';
8
+ import {SELF_POLICY} from '@webex/plugin-meetings/src/constants';
7
9
  import {DISPLAY_HINTS} from '@webex/plugin-meetings/src/constants';
10
+ import MockWebex from '@webex/test-helper-mock-webex';
8
11
 
9
12
  describe('plugin-meetings', () => {
13
+ let webex;
10
14
  describe('Meeting utils function', () => {
11
15
  const sandbox = sinon.createSandbox();
12
16
  const meeting = {};
13
17
 
14
18
  beforeEach(() => {
15
- Metrics.postEvent = sinon.stub();
19
+ webex = new MockWebex({
20
+ children: {
21
+ meetings: Meetings,
22
+ },
23
+ });
16
24
  const logger = {
17
25
  info: sandbox.stub(),
18
26
  log: sandbox.stub(),
19
27
  error: sandbox.stub(),
20
28
  warn: sandbox.stub(),
29
+ debug: sandbox.stub(),
21
30
  };
22
31
 
23
32
  LoggerConfig.set({
@@ -26,42 +35,41 @@ describe('plugin-meetings', () => {
26
35
  });
27
36
  LoggerProxy.set(logger);
28
37
 
29
- meeting.closeLocalStream = sinon.stub().returns(Promise.resolve());
30
- meeting.closeLocalShare = sinon.stub().returns(Promise.resolve());
31
- meeting.closeRemoteTracks = sinon.stub().returns(Promise.resolve());
38
+ meeting.cleanupLocalStreams = sinon.stub().returns(Promise.resolve());
39
+ meeting.closeRemoteStreams = sinon.stub().returns(Promise.resolve());
32
40
  meeting.closePeerConnections = sinon.stub().returns(Promise.resolve());
33
41
 
34
- meeting.unsetLocalVideoTrack = sinon.stub();
35
- meeting.unsetLocalShareTrack = sinon.stub();
36
- meeting.unsetRemoteTracks = sinon.stub();
42
+ meeting.unsetRemoteStreams = sinon.stub();
37
43
  meeting.unsetPeerConnections = sinon.stub();
38
44
  meeting.reconnectionManager = {cleanUp: sinon.stub()};
39
45
  meeting.stopKeepAlive = sinon.stub();
40
46
  meeting.updateLLMConnection = sinon.stub();
41
47
  meeting.breakouts = {cleanUp: sinon.stub()};
48
+ meeting.annotaion = {cleanUp: sinon.stub()};
49
+ meeting.getWebexObject = sinon.stub().returns(webex);
50
+ meeting.simultaneousInterpretation = {cleanUp: sinon.stub()};
51
+ meeting.trigger = sinon.stub();
42
52
  });
43
53
 
44
54
  afterEach(() => {
45
55
  sandbox.restore();
56
+ sinon.restore();
46
57
  });
47
58
 
48
59
  describe('#cleanup', () => {
49
60
  it('do clean up on meeting object', async () => {
50
61
  await MeetingUtil.cleanUp(meeting);
51
- assert.calledOnce(meeting.closeLocalStream);
52
- assert.calledOnce(meeting.closeLocalStream);
53
- assert.calledOnce(meeting.closeLocalShare);
54
- assert.calledOnce(meeting.closeRemoteTracks);
62
+ assert.calledOnce(meeting.cleanupLocalStreams);
63
+ assert.calledOnce(meeting.closeRemoteStreams);
55
64
  assert.calledOnce(meeting.closePeerConnections);
56
65
 
57
- assert.calledOnce(meeting.unsetLocalVideoTrack);
58
- assert.calledOnce(meeting.unsetLocalShareTrack);
59
- assert.calledOnce(meeting.unsetRemoteTracks);
66
+ assert.calledOnce(meeting.unsetRemoteStreams);
60
67
  assert.calledOnce(meeting.unsetPeerConnections);
61
68
  assert.calledOnce(meeting.reconnectionManager.cleanUp);
62
69
  assert.calledOnce(meeting.stopKeepAlive);
63
70
  assert.calledOnce(meeting.updateLLMConnection);
64
71
  assert.calledOnce(meeting.breakouts.cleanUp);
72
+ assert.calledOnce(meeting.simultaneousInterpretation.cleanUp);
65
73
  });
66
74
  });
67
75
 
@@ -70,10 +78,8 @@ describe('plugin-meetings', () => {
70
78
  deviceId: 'device-1',
71
79
  });
72
80
 
73
- const mockTrack = {
74
- underlyingTrack: {
75
- getSettings: fakeDevice,
76
- },
81
+ const mockStream = {
82
+ getSettings: fakeDevice,
77
83
  };
78
84
 
79
85
  it('#log - should log [info, warn, error, log] to console', () => {
@@ -91,27 +97,27 @@ describe('plugin-meetings', () => {
91
97
  });
92
98
 
93
99
  describe('#handleAudioLogging', () => {
94
- it('should not log if called without track', () => {
100
+ it('should not log if called without stream', () => {
95
101
  MeetingUtil.handleAudioLogging();
96
102
  assert(!LoggerProxy.logger.log.called, 'log not called');
97
103
  });
98
104
 
99
- it('should log audioTrack settings', () => {
105
+ it('should log audioStream settings', () => {
100
106
  assert(MeetingUtil.handleAudioLogging, 'method is defined');
101
- MeetingUtil.handleAudioLogging(mockTrack);
107
+ MeetingUtil.handleAudioLogging(mockStream);
102
108
  assert(LoggerProxy.logger.log.called, 'log called');
103
109
  });
104
110
  });
105
111
 
106
112
  describe('#handleVideoLogging', () => {
107
- it('should not log if called without track', () => {
113
+ it('should not log if called without stream', () => {
108
114
  MeetingUtil.handleVideoLogging(null);
109
115
  assert(!LoggerProxy.logger.log.called, 'log not called');
110
116
  });
111
117
 
112
- it('should log videoTrack settings', () => {
118
+ it('should log videoStream settings', () => {
113
119
  assert(MeetingUtil.handleVideoLogging, 'method is defined');
114
- MeetingUtil.handleVideoLogging(mockTrack);
120
+ MeetingUtil.handleVideoLogging(mockStream);
115
121
  assert(LoggerProxy.logger.log.called, 'log called');
116
122
  });
117
123
  });
@@ -132,51 +138,217 @@ describe('plugin-meetings', () => {
132
138
  });
133
139
  });
134
140
 
135
- describe('remoteUpdateAudioVideo', () => {
136
- it('#Should call meetingRequest.remoteAudioVideoToggle with correct parameters (multistream)', async () => {
141
+ describe('addSequence', () => {
142
+ it('should add the sequence object to a request body', () => {
143
+ const body = {};
144
+
145
+ MeetingUtil.addSequence(
146
+ {
147
+ locusInfo: {
148
+ sequence: 'sequence',
149
+ },
150
+ },
151
+ body
152
+ );
153
+
154
+ assert.deepEqual(body, {
155
+ sequence: 'sequence',
156
+ });
157
+ });
158
+
159
+ it('should work with an undefined meeting', () => {
160
+ const body = {};
161
+
162
+ MeetingUtil.addSequence(undefined, body);
163
+
164
+ assert.deepEqual(body, {});
165
+ });
166
+
167
+ it('should work with an undefined locusInfo', () => {
168
+ const body = {};
169
+
170
+ MeetingUtil.addSequence({}, body);
171
+
172
+ assert.deepEqual(body, {});
173
+ });
174
+
175
+ it('should work with an undefined sequence', () => {
176
+ const body = {};
177
+
178
+ MeetingUtil.addSequence({locusInfo: {}}, body);
179
+
180
+ assert.deepEqual(body, {});
181
+ });
182
+ });
183
+
184
+ describe('updateLocusWithDelta', () => {
185
+ it('should call handleLocusDelta with the new delta locus', () => {
137
186
  const meeting = {
138
- correlationId: 'correlation id',
139
- isMultistream: true,
140
- mediaId: '12345',
141
- meetingJoinUrl: 'meetingJoinUrl',
142
- locusUrl: 'locusUrl',
143
- deviceUrl: 'some device url',
144
- selfId: 'self id',
145
- meetingRequest: {
146
- remoteAudioVideoToggle: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
187
+ locusInfo: {
188
+ handleLocusDelta: sinon.stub(),
147
189
  },
148
190
  };
149
191
 
150
- await MeetingUtil.remoteUpdateAudioVideo(true, false, meeting);
192
+ const originalResponse = {
193
+ body: {
194
+ locus: 'locus',
195
+ },
196
+ };
151
197
 
152
- assert.calledOnce(meeting.meetingRequest.remoteAudioVideoToggle);
153
- const parameter = meeting.meetingRequest.remoteAudioVideoToggle.getCall(0).args[0];
198
+ const response = MeetingUtil.updateLocusWithDelta(meeting, originalResponse);
154
199
 
155
- assert.equal(parameter.locusUrl, 'locusUrl');
156
- assert.equal(parameter.selfId, 'self id');
157
- assert.equal(parameter.correlationId, 'correlation id');
158
- assert.equal(parameter.deviceUrl, 'some device url');
159
- assert.deepEqual(parameter.localMedias, [
160
- {localSdp: '{"audioMuted":true,"videoMuted":false}', mediaId: '12345'},
161
- ]);
162
- assert.equal(parameter.preferTranscoding, false);
200
+ assert.deepEqual(response, originalResponse);
201
+ assert.calledOnceWithExactly(meeting.locusInfo.handleLocusDelta, 'locus', meeting);
202
+ });
203
+
204
+ it('should handle locus being missing from the response', () => {
205
+ const meeting = {
206
+ locusInfo: {
207
+ handleLocusDelta: sinon.stub(),
208
+ },
209
+ };
210
+
211
+ const originalResponse = {
212
+ body: {},
213
+ };
214
+
215
+ const response = MeetingUtil.updateLocusWithDelta(meeting, originalResponse);
216
+
217
+ assert.deepEqual(response, originalResponse);
218
+ assert.notCalled(meeting.locusInfo.handleLocusDelta);
219
+ });
220
+
221
+ it('should work with an undefined meeting', () => {
222
+ const originalResponse = {
223
+ body: {
224
+ locus: 'locus',
225
+ },
226
+ };
227
+
228
+ const response = MeetingUtil.updateLocusWithDelta(undefined, originalResponse);
229
+ assert.deepEqual(response, originalResponse);
230
+ });
231
+ });
232
+
233
+ describe('generateLocusDeltaRequest', () => {
234
+ it('generates the correct wrapper function', async () => {
235
+ const updateLocusWithDeltaSpy = sinon.spy(MeetingUtil, 'updateLocusWithDelta');
236
+ const addSequenceSpy = sinon.spy(MeetingUtil, 'addSequence');
237
+
238
+ const meeting = {
239
+ request: sinon.stub().returns(Promise.resolve('result')),
240
+ };
241
+
242
+ const locusDeltaRequest = MeetingUtil.generateLocusDeltaRequest(meeting);
243
+
244
+ const options = {
245
+ some: 'option',
246
+ body: {},
247
+ };
248
+
249
+ let result = await locusDeltaRequest(options);
250
+
251
+ assert.equal(result, 'result');
252
+ assert.calledOnceWithExactly(updateLocusWithDeltaSpy, meeting, 'result');
253
+ assert.calledOnceWithExactly(addSequenceSpy, meeting, options.body);
254
+
255
+ updateLocusWithDeltaSpy.resetHistory();
256
+ addSequenceSpy.resetHistory();
257
+
258
+ // body missing from options
259
+ result = await locusDeltaRequest({});
260
+ assert.equal(result, 'result');
261
+ assert.calledOnceWithExactly(updateLocusWithDeltaSpy, meeting, 'result');
262
+ assert.calledOnceWithExactly(addSequenceSpy, meeting, options.body);
263
+
264
+ // meeting disappears so the WeakRef returns undefined
265
+ sinon.stub(WeakRef.prototype, 'deref').returns(undefined);
266
+
267
+ result = await locusDeltaRequest(options);
268
+ assert.equal(result, undefined);
269
+
270
+ WeakRef.prototype.deref.restore();
271
+ });
272
+
273
+ it('calls generateBuildLocusDeltaRequestOptions as expected', () => {
274
+ const generateBuildLocusDeltaRequestOptionsSpy = sinon.spy(
275
+ MeetingUtil,
276
+ 'generateBuildLocusDeltaRequestOptions'
277
+ );
278
+
279
+ const meeting = {};
280
+
281
+ MeetingUtil.generateLocusDeltaRequest(meeting);
282
+
283
+ assert.calledOnceWithExactly(generateBuildLocusDeltaRequestOptionsSpy, meeting);
284
+ });
285
+ });
286
+
287
+ describe('selfSupportsFeature', () => {
288
+ it('returns true if there are no user policies', () => {
289
+ assert.equal(
290
+ MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_ANNOTATION, undefined),
291
+ true
292
+ );
293
+ });
294
+
295
+ it('returns true if policy is true', () => {
296
+ assert.equal(
297
+ MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_ANNOTATION, {
298
+ [SELF_POLICY.SUPPORT_ANNOTATION]: true,
299
+ }),
300
+ true
301
+ );
163
302
  });
164
303
 
165
- it('#Should call meetingRequest.remoteAudioVideoToggle with preferTranscoding:true for non multistream connections', async () => {
304
+ it('returns false if policy is false', () => {
305
+ assert.equal(
306
+ MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_ANNOTATION, {
307
+ [SELF_POLICY.SUPPORT_ANNOTATION]: false,
308
+ }),
309
+ false
310
+ );
311
+ });
312
+ });
313
+
314
+ describe('remoteUpdateAudioVideo', () => {
315
+ it('#Should call meetingRequest.locusMediaRequest with correct parameters', async () => {
166
316
  const meeting = {
167
- isMultistream: false,
317
+ id: 'meeting-id',
168
318
  mediaId: '12345',
169
- meetingRequest: {
170
- remoteAudioVideoToggle: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
319
+ selfUrl: 'self url',
320
+ locusInfo: {
321
+ sequence: {},
171
322
  },
323
+ locusMediaRequest: {
324
+ send: sinon.stub().resolves({body: {}, headers: {}}),
325
+ },
326
+ getWebexObject: sinon.stub().returns(webex),
172
327
  };
173
328
 
174
- await MeetingUtil.remoteUpdateAudioVideo(true, false, meeting);
329
+ await MeetingUtil.remoteUpdateAudioVideo(meeting, true, false);
330
+
331
+ assert.calledOnceWithExactly(meeting.locusMediaRequest.send, {
332
+ mediaId: '12345',
333
+ muteOptions: {
334
+ audioMuted: true,
335
+ videoMuted: false,
336
+ },
337
+ selfUrl: 'self url',
338
+ sequence: {},
339
+ type: 'LocalMute',
340
+ ipVersion: 0,
341
+ });
175
342
 
176
- assert.calledOnce(meeting.meetingRequest.remoteAudioVideoToggle);
177
- const parameter = meeting.meetingRequest.remoteAudioVideoToggle.getCall(0).args[0];
343
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
344
+ name: 'client.locus.media.request',
345
+ options: {meetingId: meeting.id},
346
+ });
178
347
 
179
- assert.equal(parameter.preferTranscoding, true);
348
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
349
+ name: 'client.locus.media.response',
350
+ options: {meetingId: meeting.id},
351
+ });
180
352
  });
181
353
  });
182
354
 
@@ -186,8 +358,16 @@ describe('plugin-meetings', () => {
186
358
  meetingJoinUrl: 'meetingJoinUrl',
187
359
  locusUrl: 'locusUrl',
188
360
  meetingRequest: {
189
- joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
361
+ joinMeeting: sinon.stub().returns(
362
+ Promise.resolve({
363
+ body: {mediaConnections: 'mediaConnections'},
364
+ headers: {
365
+ trackingid: 'trackingId',
366
+ },
367
+ })
368
+ ),
190
369
  },
370
+ getWebexObject: sinon.stub().returns(webex),
191
371
  };
192
372
 
193
373
  MeetingUtil.parseLocusJoin = sinon.stub();
@@ -198,6 +378,25 @@ describe('plugin-meetings', () => {
198
378
 
199
379
  assert.equal(parameter.inviteeAddress, 'meetingJoinUrl');
200
380
  assert.equal(parameter.preferTranscoding, true);
381
+
382
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
383
+ name: 'client.locus.join.request',
384
+ options: {meetingId: meeting.id},
385
+ });
386
+
387
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
388
+ name: 'client.locus.join.response',
389
+ payload: {
390
+ trigger: 'loci-update',
391
+ identifiers: {
392
+ trackingId: 'trackingId',
393
+ },
394
+ },
395
+ options: {
396
+ meetingId: meeting.id,
397
+ mediaConnections: 'mediaConnections',
398
+ },
399
+ });
201
400
  });
202
401
 
203
402
  it('#Should call meetingRequest.joinMeeting with breakoutsSupported=true when passed in as true', async () => {
@@ -205,6 +404,7 @@ describe('plugin-meetings', () => {
205
404
  meetingRequest: {
206
405
  joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
207
406
  },
407
+ getWebexObject: sinon.stub().returns(webex),
208
408
  };
209
409
 
210
410
  MeetingUtil.parseLocusJoin = sinon.stub();
@@ -218,6 +418,46 @@ describe('plugin-meetings', () => {
218
418
  assert.equal(parameter.breakoutsSupported, true);
219
419
  });
220
420
 
421
+ it('#Should call meetingRequest.joinMeeting with liveAnnotationSupported=true when passed in as true', async () => {
422
+ const meeting = {
423
+ meetingRequest: {
424
+ joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
425
+ },
426
+ getWebexObject: sinon.stub().returns(webex),
427
+ };
428
+
429
+ MeetingUtil.parseLocusJoin = sinon.stub();
430
+ await MeetingUtil.joinMeeting(meeting, {
431
+ liveAnnotationSupported: true,
432
+ });
433
+
434
+ assert.calledOnce(meeting.meetingRequest.joinMeeting);
435
+ const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
436
+
437
+ assert.equal(parameter.liveAnnotationSupported, true);
438
+ });
439
+
440
+ it('#Should call meetingRequest.joinMeeting with locale=en_UK, deviceCapabilities=["TEST"] when they are passed in as those values', async () => {
441
+ const meeting = {
442
+ meetingRequest: {
443
+ joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
444
+ },
445
+ getWebexObject: sinon.stub().returns(webex),
446
+ };
447
+
448
+ MeetingUtil.parseLocusJoin = sinon.stub();
449
+ await MeetingUtil.joinMeeting(meeting, {
450
+ locale: 'en_UK',
451
+ deviceCapabilities: ['TEST'],
452
+ });
453
+
454
+ assert.calledOnce(meeting.meetingRequest.joinMeeting);
455
+ const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
456
+
457
+ assert.equal(parameter.locale, 'en_UK');
458
+ assert.deepEqual(parameter.deviceCapabilities, ['TEST']);
459
+ });
460
+
221
461
  it('#Should call meetingRequest.joinMeeting with preferTranscoding=false when multistream is enabled', async () => {
222
462
  const meeting = {
223
463
  isMultistream: true,
@@ -226,6 +466,7 @@ describe('plugin-meetings', () => {
226
466
  meetingRequest: {
227
467
  joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
228
468
  },
469
+ getWebexObject: sinon.stub().returns(webex),
229
470
  };
230
471
 
231
472
  MeetingUtil.parseLocusJoin = sinon.stub();
@@ -245,6 +486,7 @@ describe('plugin-meetings', () => {
245
486
  meetingRequest: {
246
487
  joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
247
488
  },
489
+ getWebexObject: sinon.stub().returns(webex),
248
490
  };
249
491
 
250
492
  MeetingUtil.parseLocusJoin = sinon.stub();
@@ -263,6 +505,7 @@ describe('plugin-meetings', () => {
263
505
  meetingRequest: {
264
506
  joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
265
507
  },
508
+ getWebexObject: sinon.stub().returns(webex),
266
509
  };
267
510
 
268
511
  MeetingUtil.parseLocusJoin = sinon.stub();
@@ -276,6 +519,43 @@ describe('plugin-meetings', () => {
276
519
  });
277
520
  });
278
521
 
522
+ describe('joinMeetingOptions', () => {
523
+ it('sends client events correctly', async () => {
524
+ MeetingUtil.joinMeeting = sinon.stub().rejects({});
525
+ MeetingUtil.isPinOrGuest = sinon.stub().returns(true);
526
+ const meeting = {
527
+ id: 'meeting-id',
528
+ mediaId: '12345',
529
+ selfUrl: 'self url',
530
+ locusInfo: {
531
+ sequence: {},
532
+ },
533
+ locusMediaRequest: {
534
+ send: sinon.stub().resolves({body: {}, headers: {}}),
535
+ },
536
+ getWebexObject: sinon.stub().returns(webex),
537
+ };
538
+
539
+ try {
540
+ await MeetingUtil.joinMeetingOptions(meeting, {pin: true});
541
+
542
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
543
+ name: 'client.pin.collected',
544
+ options: {
545
+ meetingId: meeting.id,
546
+ },
547
+ });
548
+ } catch (err) {
549
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
550
+ name: 'client.pin.prompt',
551
+ options: {
552
+ meetingId: meeting.id,
553
+ },
554
+ });
555
+ }
556
+ });
557
+ });
558
+
279
559
  describe('getUserDisplayHintsFromLocusInfo', () => {
280
560
  it('returns display hints', () => {
281
561
  assert.deepEqual(MeetingUtil.getUserDisplayHintsFromLocusInfo(), []);
@@ -364,6 +644,13 @@ describe('plugin-meetings', () => {
364
644
  });
365
645
  });
366
646
 
647
+ describe('canShareWhiteBoard', () => {
648
+ it('works as expected', () => {
649
+ assert.deepEqual(MeetingUtil.canShareWhiteBoard(['SHARE_WHITEBOARD']), true);
650
+ assert.deepEqual(MeetingUtil.canShareWhiteBoard([]), false);
651
+ });
652
+ });
653
+
367
654
  describe('bothLeaveAndEndMeetingAvailable', () => {
368
655
  it('works as expected', () => {
369
656
  assert.deepEqual(
@@ -426,27 +713,6 @@ describe('plugin-meetings', () => {
426
713
  });
427
714
  });
428
715
 
429
- describe('reactions', () => {
430
- describe('canEnableReactions', () => {
431
- [
432
- [null, DISPLAY_HINTS.ENABLE_REACTIONS, true],
433
- [null, DISPLAY_HINTS.DISABLE_REACTIONS, false],
434
- [null, undefined, null],
435
- ].forEach(() => ([originalValue, displayHint, expected]) => {
436
- assert.deepEqual(MeetingUtil.canEnableReactions(originalValue, [displayHint]), expected);
437
- });
438
- });
439
- describe('canEnableReactions', () => {
440
- [
441
- [null, DISPLAY_HINTS.REACTIONS_ACTIVE, true],
442
- [null, DISPLAY_HINTS.REACTIONS_INACTIVE, false],
443
- [null, undefined, null],
444
- ].forEach(([originalValue, displayHint, expected]) => {
445
- assert.deepEqual(MeetingUtil.canSendReactions(originalValue, [displayHint]), expected);
446
- });
447
- });
448
- });
449
-
450
716
  describe('canManageBreakout', () => {
451
717
  it('works as expected', () => {
452
718
  assert.deepEqual(MeetingUtil.canManageBreakout(['BREAKOUT_MANAGEMENT']), true);
@@ -454,6 +720,33 @@ describe('plugin-meetings', () => {
454
720
  });
455
721
  });
456
722
 
723
+ describe('canBroadcastMessageToBreakout', () => {
724
+ it('works as expected', () => {
725
+ assert.deepEqual(
726
+ MeetingUtil.canBroadcastMessageToBreakout(['BROADCAST_MESSAGE_TO_BREAKOUT'], {
727
+ [SELF_POLICY.SUPPORT_BROADCAST_MESSAGE]: true,
728
+ }),
729
+ true
730
+ );
731
+ assert.deepEqual(
732
+ MeetingUtil.canBroadcastMessageToBreakout([], {
733
+ [SELF_POLICY.SUPPORT_BROADCAST_MESSAGE]: true,
734
+ }),
735
+ false
736
+ );
737
+ assert.deepEqual(
738
+ MeetingUtil.canBroadcastMessageToBreakout(['BROADCAST_MESSAGE_TO_BREAKOUT'], {
739
+ [SELF_POLICY.SUPPORT_BROADCAST_MESSAGE]: false,
740
+ }),
741
+ false
742
+ );
743
+ assert.deepEqual(
744
+ MeetingUtil.canBroadcastMessageToBreakout(['BROADCAST_MESSAGE_TO_BREAKOUT'], undefined),
745
+ false
746
+ );
747
+ });
748
+ });
749
+
457
750
  describe('isSuppressBreakoutSupport', () => {
458
751
  it('works as expected', () => {
459
752
  assert.deepEqual(
@@ -487,5 +780,188 @@ describe('plugin-meetings', () => {
487
780
  assert.deepEqual(MeetingUtil.isBreakoutPreassignmentsEnabled([]), true);
488
781
  });
489
782
  });
783
+
784
+ describe('parseInterpretationInfo', () => {
785
+ let meetingInfo = {};
786
+ beforeEach(() => {
787
+ meeting.simultaneousInterpretation = {
788
+ updateMeetingSIEnabled: sinon.stub(),
789
+ updateHostSIEnabled: sinon.stub(),
790
+ updateInterpretation: sinon.stub(),
791
+ siLanguages: [],
792
+ };
793
+ });
794
+ it('should update simultaneous interpretation settings with SI and host enabled', () => {
795
+ meetingInfo.turnOnSimultaneousInterpretation = true;
796
+ meetingInfo.meetingSiteSetting = {
797
+ enableHostInterpreterControlSI: true,
798
+ };
799
+ meetingInfo.simultaneousInterpretation = {
800
+ currentSIInterpreter: true,
801
+ siLanguages: [
802
+ {languageCode: 'en', languageGroupId: 1},
803
+ {languageCode: 'es', languageGroupId: 2},
804
+ ],
805
+ };
806
+
807
+ MeetingUtil.parseInterpretationInfo(meeting, meetingInfo);
808
+ assert.calledWith(meeting.simultaneousInterpretation.updateMeetingSIEnabled, true, true);
809
+ assert.calledWith(meeting.simultaneousInterpretation.updateHostSIEnabled, true);
810
+ assert.calledWith(meeting.simultaneousInterpretation.updateInterpretation, {
811
+ siLanguages: [
812
+ {languageName: 'en', languageCode: 1},
813
+ {languageName: 'es', languageCode: 2},
814
+ ],
815
+ });
816
+ });
817
+
818
+ it('should update simultaneous interpretation settings with host SI disabled', () => {
819
+ meetingInfo.meetingSiteSetting.enableHostInterpreterControlSI = false;
820
+ meetingInfo.simultaneousInterpretation.currentSIInterpreter = false;
821
+ MeetingUtil.parseInterpretationInfo(meeting, meetingInfo);
822
+ assert.calledWith(meeting.simultaneousInterpretation.updateMeetingSIEnabled, true, false);
823
+ assert.calledWith(meeting.simultaneousInterpretation.updateHostSIEnabled, false);
824
+ assert.calledWith(meeting.simultaneousInterpretation.updateInterpretation, {
825
+ siLanguages: [
826
+ {languageName: 'en', languageCode: 1},
827
+ {languageName: 'es', languageCode: 2},
828
+ ],
829
+ });
830
+ });
831
+ it('should update simultaneous interpretation settings with SI disabled', () => {
832
+ meetingInfo.turnOnSimultaneousInterpretation = false;
833
+ MeetingUtil.parseInterpretationInfo(meeting, meetingInfo);
834
+ assert.calledWith(meeting.simultaneousInterpretation.updateMeetingSIEnabled, false, false);
835
+ assert.calledWith(meeting.simultaneousInterpretation.updateHostSIEnabled, false);
836
+ });
837
+
838
+ it('should not update simultaneous interpretation settings for invalid input', () => {
839
+ // Call the function with invalid inputs
840
+ MeetingUtil.parseInterpretationInfo(null, null);
841
+
842
+ // Ensure that the update functions are not called
843
+ assert.notCalled(meeting.simultaneousInterpretation.updateMeetingSIEnabled);
844
+ assert.notCalled(meeting.simultaneousInterpretation.updateHostSIEnabled);
845
+ assert.notCalled(meeting.simultaneousInterpretation.updateInterpretation);
846
+ });
847
+ });
848
+
849
+ describe('prepareLeaveMeetingOptions', () => {
850
+ it('works as expected', () => {
851
+ const meeting = {
852
+ locusUrl: 'locusUrl',
853
+ selfId: 'selfId',
854
+ correlationId: 'correlationId',
855
+ resourceId: 'resourceId',
856
+ deviceUrl: 'deviceUrl',
857
+ };
858
+
859
+ const leaveOptions = MeetingUtil.prepareLeaveMeetingOptions(meeting, {
860
+ selfId: 'bob',
861
+ foo: 'bar',
862
+ });
863
+
864
+ assert.deepEqual(leaveOptions, {
865
+ correlationId: 'correlationId',
866
+ deviceUrl: 'deviceUrl',
867
+ foo: 'bar',
868
+ locusUrl: 'locusUrl',
869
+ resourceId: 'resourceId',
870
+ selfId: 'bob',
871
+ });
872
+ });
873
+ });
874
+
875
+ describe('leaveMeeting', () => {
876
+ it('calls prepareLeaveMeetingOptions as expected', () => {
877
+ const meeting = {
878
+ locusUrl: 'locusUrl',
879
+ selfId: 'selfId',
880
+ correlationId: 'correlationId',
881
+ resourceId: 'resourceId',
882
+ deviceUrl: 'deviceUrl',
883
+ locusInfo: {parsedLocus: {}},
884
+ meetingRequest: {
885
+ leaveMeeting: () => Promise.resolve(),
886
+ },
887
+ };
888
+
889
+ const prepareLeaveMeetingOptionsSpy = sinon.spy(MeetingUtil, 'prepareLeaveMeetingOptions');
890
+
891
+ MeetingUtil.leaveMeeting(meeting, {foo: 'bar'});
892
+
893
+ assert.calledOnce(prepareLeaveMeetingOptionsSpy);
894
+ assert.deepEqual(prepareLeaveMeetingOptionsSpy.getCall(0).args[0], meeting);
895
+ assert.deepEqual(prepareLeaveMeetingOptionsSpy.getCall(0).args[1], {foo: 'bar'});
896
+ });
897
+ });
898
+
899
+ describe('buildLeaveFetchRequestOptions', () => {
900
+ it('calls expected functions', () => {
901
+ const buildLeaveMeetingRequestOptionsSpy = sinon.stub();
902
+
903
+ const meeting = {
904
+ locusUrl: 'locusUrl',
905
+ selfId: 'selfId',
906
+ correlationId: 'correlationId',
907
+ resourceId: 'resourceId',
908
+ deviceUrl: 'deviceUrl',
909
+ meetingRequest: {
910
+ leaveMeeting: () => Promise.resolve(),
911
+ buildLeaveMeetingRequestOptions: buildLeaveMeetingRequestOptionsSpy,
912
+ },
913
+ };
914
+
915
+ const prepareLeaveMeetingOptionsSpy = sinon.spy(MeetingUtil, 'prepareLeaveMeetingOptions');
916
+
917
+ const options = MeetingUtil.buildLeaveFetchRequestOptions(meeting, {foo: 'bar'});
918
+
919
+ assert.calledOnce(prepareLeaveMeetingOptionsSpy);
920
+ assert.deepEqual(prepareLeaveMeetingOptionsSpy.getCall(0).args[0], meeting);
921
+ assert.deepEqual(prepareLeaveMeetingOptionsSpy.getCall(0).args[1], {foo: 'bar'});
922
+
923
+ assert.calledOnce(buildLeaveMeetingRequestOptionsSpy);
924
+ assert.deepEqual(buildLeaveMeetingRequestOptionsSpy.getCall(0).args[0], {
925
+ correlationId: 'correlationId',
926
+ deviceUrl: 'deviceUrl',
927
+ foo: 'bar',
928
+ locusUrl: 'locusUrl',
929
+ resourceId: 'resourceId',
930
+ selfId: 'selfId',
931
+ });
932
+ });
933
+ });
934
+
935
+ describe('generateBuildLocusDeltaRequestOptions', () => {
936
+ it('generates the correct wrapper function', async () => {
937
+ const addSequenceSpy = sinon.spy(MeetingUtil, 'addSequence');
938
+
939
+ const meeting = {locusInfo: {sequence: 123}};
940
+
941
+ const buildLocusDeltaRequestOptions =
942
+ MeetingUtil.generateBuildLocusDeltaRequestOptions(meeting);
943
+
944
+ let result = buildLocusDeltaRequestOptions({
945
+ some: 'option',
946
+ body: {},
947
+ });
948
+ assert.deepEqual(result, {some: 'option', body: {sequence: 123}});
949
+ assert.calledOnceWithExactly(addSequenceSpy, meeting, {sequence: 123});
950
+
951
+ addSequenceSpy.resetHistory();
952
+
953
+ // body missing from options
954
+ result = buildLocusDeltaRequestOptions({});
955
+ assert.deepEqual(result, {body: {sequence: 123}});
956
+ assert.calledOnceWithExactly(addSequenceSpy, meeting, {sequence: 123});
957
+
958
+ // meeting disappears so the WeakRef returns undefined
959
+ sinon.stub(WeakRef.prototype, 'deref').returns(undefined);
960
+
961
+ const input = {foo: 'bar'};
962
+ result = buildLocusDeltaRequestOptions(input);
963
+ assert.equal(result, input);
964
+ });
965
+ });
490
966
  });
491
967
  });