@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
@@ -6,6 +6,7 @@ import sinon from 'sinon';
6
6
  import MockWebex from '@webex/test-helper-mock-webex';
7
7
  import testUtils from '../../../utils/testUtils';
8
8
  import BreakoutEditLockedError from '@webex/plugin-meetings/src/breakouts/edit-lock-error';
9
+ import breakoutEvent from '../../../../src/breakouts/events';
9
10
 
10
11
  const getBOResponse = (status: string) => {
11
12
  return {
@@ -53,7 +54,12 @@ const getBOResponseWithEditLockInfo = (status: string, withOutToken?: boolean) =
53
54
  locusUrl: 'locusUrl',
54
55
  mainGroupId: 'mainGroupId',
55
56
  mainSessionId: 'mainSessionId',
56
- editlock: {state: "LOCKED", ttl: 30, userId: "cc5d452f-04b6-4876-a4c3-28ca21982c6a", token: withOutToken ? '' : 'token1'},
57
+ editlock: {
58
+ state: 'LOCKED',
59
+ ttl: 30,
60
+ userId: 'cc5d452f-04b6-4876-a4c3-28ca21982c6a',
61
+ token: withOutToken ? '' : 'token1',
62
+ },
57
63
  groups: [
58
64
  {
59
65
  sessions: [
@@ -89,6 +95,8 @@ describe('plugin-meetings', () => {
89
95
  breakouts.locusUrl = 'locusUrl';
90
96
  breakouts.breakoutServiceUrl = 'breakoutServiceUrl';
91
97
  webex.request = sinon.stub().returns(Promise.resolve('REQUEST_RETURN_VALUE'));
98
+ webex.meetings = {};
99
+ webex.meetings.getMeetingByType = sinon.stub();
92
100
  });
93
101
 
94
102
  describe('#initialize', () => {
@@ -96,19 +104,59 @@ describe('plugin-meetings', () => {
96
104
  assert.equal(breakouts.namespace, 'Meetings');
97
105
  });
98
106
 
99
- it('emits BREAKOUTS_CLOSING event when the status is CLOSING', () => {
100
- let called = false;
101
- breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.BREAKOUTS_CLOSING, () => {
102
- called = true;
107
+ it('emits BREAKOUTS_CLOSING event when the breakoutStatus is CLOSING', () => {
108
+ const checkIsCalled = (prev, deps) => {
109
+ breakouts.set(prev);
110
+ const breakoutClosingHandler = sinon.stub();
111
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.BREAKOUTS_CLOSING, breakoutClosingHandler);
112
+ assert.notCalled(breakoutClosingHandler);
113
+ breakouts.set(deps);
114
+ assert.calledOnce(breakoutClosingHandler);
115
+ }
116
+
117
+ checkIsCalled({sessionType: BREAKOUTS.SESSION_TYPES.MAIN, groups: undefined, status: undefined}, {
118
+ sessionType: BREAKOUTS.SESSION_TYPES.MAIN,
119
+ groups: [{status: BREAKOUTS.STATUS.CLOSING}],
120
+ status: undefined
121
+ });
122
+
123
+ checkIsCalled({sessionType: BREAKOUTS.SESSION_TYPES.MAIN, groups: [{status: BREAKOUTS.STATUS.OPEN}], status: undefined}, {
124
+ sessionType: BREAKOUTS.SESSION_TYPES.MAIN,
125
+ groups: [{status: BREAKOUTS.STATUS.CLOSING}],
126
+ status: undefined
127
+ });
128
+
129
+ checkIsCalled({sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT, groups: undefined, status: undefined}, {
130
+ sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT,
131
+ groups: undefined,
132
+ status: BREAKOUTS.STATUS.CLOSING
103
133
  });
104
134
 
105
- breakouts.set('status', 'something');
135
+ checkIsCalled({sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT, groups: undefined, status: BREAKOUTS.STATUS.OPEN}, {
136
+ sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT,
137
+ groups: undefined,
138
+ status: BREAKOUTS.STATUS.CLOSING
139
+ });
106
140
 
107
- assert.isFalse(called);
141
+ });
108
142
 
109
- breakouts.set({status: BREAKOUTS.STATUS.CLOSING});
143
+ it('should not emits BREAKOUTS_CLOSING event when just sessionType changed from BREAKOUT to MAIN', () => {
144
+ breakouts.set({
145
+ sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT,
146
+ groups: undefined,
147
+ status: BREAKOUTS.STATUS.CLOSING
148
+ });
110
149
 
111
- assert.isTrue(called);
150
+ const breakoutClosingHandler = sinon.stub();
151
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.BREAKOUTS_CLOSING, breakoutClosingHandler);
152
+
153
+ breakouts.set({
154
+ sessionType: BREAKOUTS.SESSION_TYPES.MAIN,
155
+ groups: [{status: BREAKOUTS.STATUS.CLOSING}],
156
+ status: undefined
157
+ });
158
+
159
+ assert.notCalled(breakoutClosingHandler);
112
160
  });
113
161
 
114
162
  it('debounces querying rosters on add', () => {
@@ -117,6 +165,64 @@ describe('plugin-meetings', () => {
117
165
 
118
166
  assert.calledOnceWithExactly(breakouts.debouncedQueryRosters);
119
167
  });
168
+
169
+ it('call triggerReturnToMainEvent correctly when requested breakout add', () => {
170
+ breakouts.triggerReturnToMainEvent = sinon.stub();
171
+ breakouts.breakouts.add({sessionId: 'session1', sessionType: 'MAIN'});
172
+ assert.calledOnceWithExactly(breakouts.triggerReturnToMainEvent, breakouts.breakouts.get('session1'));
173
+ });
174
+
175
+ it('call triggerReturnToMainEvent correctly when breakout requestedLastModifiedTime change', () => {
176
+ breakouts.breakouts.add({sessionId: 'session1', sessionType: 'MAIN'});
177
+ breakouts.triggerReturnToMainEvent = sinon.stub();
178
+ breakouts.breakouts.get('session1').set({requestedLastModifiedTime: "2023-05-09T17:16:01.000Z"});
179
+ assert.calledOnceWithExactly(breakouts.triggerReturnToMainEvent, breakouts.breakouts.get('session1'));
180
+ });
181
+
182
+ it('call queryPreAssignments correctly when should query preAssignments is true', () => {
183
+ breakouts.queryPreAssignments = sinon.stub();
184
+ breakouts.set({
185
+ canManageBreakouts: true,
186
+ enableBreakoutSession: true,
187
+ hasBreakoutPreAssignments: true,
188
+ });
189
+ assert.calledThrice(breakouts.queryPreAssignments);
190
+ });
191
+ });
192
+
193
+ describe('#listenToCurrentSessionTypeChange', () => {
194
+ it('triggers leave breakout event when sessionType changed from SESSION to MAIN', () => {
195
+ const handler = sinon.stub();
196
+ breakouts.currentBreakoutSession.set({sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT})
197
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
198
+ breakouts.currentBreakoutSession.set({sessionType: BREAKOUTS.SESSION_TYPES.MAIN});
199
+
200
+ assert.calledOnceWithExactly(handler);
201
+
202
+ breakouts.stopListening(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
203
+ });
204
+
205
+ it('should not triggers leave breakout event when sessionType changed from undefined to MAIN', () => {
206
+ const handler = sinon.stub();
207
+ breakouts.currentBreakoutSession.set({sessionType: undefined})
208
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
209
+ breakouts.currentBreakoutSession.set({sessionType: BREAKOUTS.SESSION_TYPES.MAIN});
210
+
211
+ assert.notCalled(handler);
212
+
213
+ breakouts.stopListening(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
214
+ });
215
+
216
+ it('should not triggers leave breakout event when sessionType changed from MAIN to SESSION', () => {
217
+ const handler = sinon.stub();
218
+ breakouts.currentBreakoutSession.set({sessionType: BREAKOUTS.SESSION_TYPES.MAIN})
219
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
220
+ breakouts.currentBreakoutSession.set({sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT});
221
+
222
+ assert.notCalled(handler);
223
+
224
+ breakouts.stopListening(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
225
+ });
120
226
  });
121
227
 
122
228
  describe('#listenToBroadcastMessages', () => {
@@ -176,6 +282,33 @@ describe('plugin-meetings', () => {
176
282
  });
177
283
  });
178
284
 
285
+ describe('#listenToBreakoutHelp', () => {
286
+ it('triggers ask for help event when a help received', () => {
287
+ const call = webex.internal.mercury.on.getCall(1);
288
+ const callback = call.args[1];
289
+
290
+ assert.equal(call.args[0], 'event:breakout.help');
291
+
292
+ let data;
293
+
294
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.ASK_FOR_HELP, (eventData) => {
295
+ data = eventData;
296
+ });
297
+
298
+ callback({
299
+ data: {
300
+ participant: 'participant',
301
+ sessionId: 'sessionId'
302
+ },
303
+ });
304
+
305
+ assert.deepEqual(data, {
306
+ participant: 'participant',
307
+ sessionId: 'sessionId',
308
+ });
309
+ });
310
+ });
311
+
179
312
  describe('#updateBreakout', () => {
180
313
  it('updates the current breakout session', () => {
181
314
  breakouts.updateBreakout({
@@ -215,6 +348,87 @@ describe('plugin-meetings', () => {
215
348
  assert.equal(breakouts.currentBreakoutSession.assignedCurrent, false);
216
349
  assert.equal(breakouts.currentBreakoutSession.requested, false);
217
350
  });
351
+
352
+ it('update the startTime correctly when no attribute startTime exists on params', () => {
353
+ breakouts.updateBreakout({
354
+ startTime: "startTime"
355
+ })
356
+ assert.equal(breakouts.startTime, 'startTime');
357
+
358
+ breakouts.updateBreakout({})
359
+ assert.equal(breakouts.startTime, undefined);
360
+ });
361
+
362
+ it('update the status correctly when no attribute status exists on params', () => {
363
+ breakouts.updateBreakout({
364
+ status: 'CLOSING'
365
+ })
366
+ assert.equal(breakouts.status, 'CLOSING');
367
+
368
+ breakouts.updateBreakout({})
369
+ assert.equal(breakouts.status, undefined);
370
+ });
371
+
372
+ it('call clearBreakouts if current breakout is not in-progress', () => {
373
+ breakouts.clearBreakouts = sinon.stub();
374
+ breakouts.updateBreakout({status: 'CLOSED'})
375
+ assert.calledOnce(breakouts.clearBreakouts);
376
+ });
377
+
378
+ it('updates the current breakout session, call onBreakoutJoinResponse when session changed', () => {
379
+ breakouts.webex.meetings = {
380
+ getMeetingByType: sinon.stub().returns({
381
+ id: 'meeting-id'
382
+ })
383
+ };
384
+ breakoutEvent.onBreakoutJoinResponse = sinon.stub();
385
+ breakouts.currentBreakoutSession.sessionId = "sessionId-old";
386
+ breakouts.updateBreakout({
387
+ sessionId: 'sessionId-new',
388
+ groupId: 'groupId',
389
+ sessionType: 'sessionType',
390
+ url: 'url',
391
+ name: 'name',
392
+ allowBackToMain: true,
393
+ delayCloseTime: 10,
394
+ enableBreakoutSession: true,
395
+ startTime: 'startTime',
396
+ status: 'active',
397
+ locusUrl: 'locusUrl',
398
+ breakoutMoveId: 'breakoutMoveId',
399
+ });
400
+
401
+ assert.calledOnce(breakoutEvent.onBreakoutJoinResponse);
402
+
403
+ });
404
+
405
+ it('updates the current breakout session, not call onBreakoutJoinResponse when session no changed', () => {
406
+ breakouts.webex.meetings = {
407
+ getMeetingByType: sinon.stub().returns({
408
+ id: 'meeting-id'
409
+ })
410
+ };
411
+ breakoutEvent.onBreakoutJoinResponse = sinon.stub();
412
+ breakouts.currentBreakoutSession.sessionId = "sessionId";
413
+ breakouts.currentBreakoutSession.groupId = "groupId";
414
+ breakouts.updateBreakout({
415
+ sessionId: 'sessionId',
416
+ groupId: 'groupId',
417
+ sessionType: 'sessionType',
418
+ url: 'url',
419
+ name: 'name',
420
+ allowBackToMain: true,
421
+ delayCloseTime: 10,
422
+ enableBreakoutSession: true,
423
+ startTime: 'startTime',
424
+ status: 'active',
425
+ locusUrl: 'locusUrl',
426
+ breakoutMoveId: 'breakoutMoveId',
427
+ });
428
+
429
+ assert.notCalled(breakoutEvent.onBreakoutJoinResponse);
430
+
431
+ });
218
432
  });
219
433
 
220
434
  describe('#updateBreakoutSessions', () => {
@@ -235,7 +449,7 @@ describe('plugin-meetings', () => {
235
449
 
236
450
  it('works', () => {
237
451
  breakouts.set('url', 'url');
238
-
452
+ breakouts.set('sessionType', BREAKOUTS.SESSION_TYPES.MAIN);
239
453
  const payload = {
240
454
  breakoutSessions: {
241
455
  active: [{sessionId: 'sessionId1'}],
@@ -254,6 +468,26 @@ describe('plugin-meetings', () => {
254
468
  checkBreakout(breakouts.breakouts.get('sessionId4'), 'sessionId4', 'assignedCurrent');
255
469
  checkBreakout(breakouts.breakouts.get('sessionId5'), 'sessionId5', 'requested');
256
470
  });
471
+
472
+ it('set requestedLastModifiedTime correctly', () => {
473
+ const payload = {
474
+ breakoutSessions: {
475
+ assigned: [{sessionId: 'sessionId1'}],
476
+ requested: [{sessionId: 'sessionId2', modifiedAt: "2023-05-09T17:16:01.000Z"}],
477
+ },
478
+ };
479
+
480
+ breakouts.updateBreakoutSessions(payload);
481
+ assert.equal(breakouts.breakouts.get('sessionId1').requestedLastModifiedTime, undefined)
482
+ assert.equal(breakouts.breakouts.get('sessionId2').requestedLastModifiedTime, "2023-05-09T17:16:01.000Z")
483
+ });
484
+
485
+ it('not update breakout sessions when breakouts is closing', () => {
486
+ breakouts.set('status', 'CLOSING');
487
+ breakouts.breakouts.set = sinon.stub();
488
+ breakouts.updateBreakoutSessions({breakoutSessions: {}});
489
+ assert.notCalled(breakouts.breakouts.set);
490
+ });
257
491
  });
258
492
 
259
493
  describe('#locusUrlUpdate', () => {
@@ -264,6 +498,18 @@ describe('plugin-meetings', () => {
264
498
  });
265
499
  });
266
500
 
501
+ describe('#updateCanManageBreakouts', () => {
502
+ it('update canManageBreakouts', () => {
503
+ breakouts.updateCanManageBreakouts(true);
504
+
505
+ assert.equal(breakouts.canManageBreakouts, true);
506
+
507
+ breakouts.updateCanManageBreakouts(false);
508
+
509
+ assert.equal(breakouts.canManageBreakouts, false);
510
+ });
511
+ });
512
+
267
513
  describe('#cleanUp', () => {
268
514
  it('stops listening', () => {
269
515
  breakouts.stopListening = sinon.stub();
@@ -302,6 +548,112 @@ describe('plugin-meetings', () => {
302
548
  });
303
549
  });
304
550
 
551
+ describe('#breakoutGroupId', () => {
552
+ it('return empty breakout group id for managing breakouts if no data', () => {
553
+ assert.equal(breakouts.breakoutGroupId, '');
554
+ breakouts.set('manageGroups', []);
555
+ assert.equal(breakouts.breakoutGroupId, '');
556
+ breakouts.set('manageGroups', [{name: 'test'}]);
557
+ assert.equal(breakouts.breakoutGroupId, undefined);
558
+ });
559
+ it('return the group id if has id in manageGroups', () => {
560
+ breakouts.set('manageGroups', [{id: 'groupId1'}]);
561
+ assert.equal(breakouts.breakoutGroupId, 'groupId1');
562
+ });
563
+ it('return empty group id if group status is CLOSED', () => {
564
+ breakouts.set('manageGroups', [{id: 'groupId1', status: 'CLOSED'}]);
565
+ assert.equal(breakouts.breakoutGroupId, '');
566
+ });
567
+ });
568
+
569
+ describe('#shouldQueryPreAssignments', () => {
570
+ it('returns should query preAssignments depends on status', () => {
571
+ assert.equal(breakouts.shouldQueryPreAssignments, false);
572
+ breakouts.set('canManageBreakouts', true);
573
+ assert.equal(breakouts.shouldQueryPreAssignments, false);
574
+ breakouts.set('enableBreakoutSession', true);
575
+ assert.equal(breakouts.shouldQueryPreAssignments, false);
576
+ breakouts.set('hasBreakoutPreAssignments', true);
577
+ assert.equal(breakouts.shouldQueryPreAssignments, true);
578
+ });
579
+ });
580
+
581
+ describe('#breakoutStatus', () => {
582
+ it('return status from groups with session type', () => {
583
+ breakouts.set('groups', [{status: "OPEN"}]);
584
+ breakouts.set('status', "CLOSED");
585
+ breakouts.set('sessionType', BREAKOUTS.SESSION_TYPES.MAIN);
586
+
587
+ assert.equal(breakouts.breakoutStatus, "OPEN")
588
+
589
+ breakouts.set('sessionType', BREAKOUTS.SESSION_TYPES.BREAKOUT);
590
+
591
+ assert.equal(breakouts.breakoutStatus, "CLOSED")
592
+ });
593
+ });
594
+
595
+ describe('#_setManageGroups', () => {
596
+ it('do nothing if breakout info is empty', () => {
597
+ breakouts._setManageGroups();
598
+ assert.equal(breakouts.manageGroups, undefined);
599
+ breakouts._setManageGroups({body: null});
600
+ assert.equal(breakouts.manageGroups, undefined);
601
+ breakouts._setManageGroups({body: {groups: null}});
602
+ assert.equal(breakouts.manageGroups, undefined);
603
+ });
604
+ it('set the groups into manageGroups if has groups in side breakout info', () => {
605
+ breakouts._setManageGroups({body: {groups: [{id: 'groupId1'}]}});
606
+ assert.deepEqual(breakouts.manageGroups, [{id: 'groupId1'}]);
607
+ });
608
+ });
609
+
610
+ describe('#isBreakoutInProgress', () => {
611
+ it('return breakout is in progress depends on the status(groups/breakouts)', () => {
612
+ breakouts.set('groups', [{status: 'CLOSING'}]);
613
+
614
+ assert.equal(breakouts.isBreakoutInProgress(), true)
615
+
616
+ breakouts.set('groups', undefined);
617
+ breakouts.set('status', 'OPEN');
618
+
619
+ assert.equal(breakouts.isBreakoutInProgress(), true);
620
+
621
+ breakouts.set('groups', [{status: 'CLOSED'}]);
622
+
623
+ assert.equal(breakouts.isBreakoutInProgress(), false);
624
+
625
+ breakouts.set('groups', undefined);
626
+ breakouts.set('status', 'CLOSED');
627
+
628
+ assert.equal(breakouts.isBreakoutInProgress(), false);
629
+
630
+ breakouts.set('status', undefined);
631
+
632
+ assert.equal(breakouts.isBreakoutInProgress(), false);
633
+ });
634
+ });
635
+
636
+ describe('#isBreakoutIClosing', () => {
637
+ it('return breakout is closing depends the status(groups/breakouts)', () => {
638
+ breakouts.set('groups', [{status: 'CLOSING'}]);
639
+
640
+ assert.equal(breakouts.isBreakoutIClosing(), true);
641
+
642
+ breakouts.set('groups', undefined);
643
+ breakouts.set('status', 'CLOSING');
644
+
645
+ assert.equal(breakouts.isBreakoutIClosing(), true);
646
+
647
+ breakouts.set('status', undefined);
648
+
649
+ assert.equal(breakouts.isBreakoutIClosing(), false);
650
+
651
+ breakouts.set('groups', [{status: 'OPEN'}]);
652
+
653
+ assert.equal(breakouts.isBreakoutIClosing(), false);
654
+ });
655
+ });
656
+
305
657
  describe('#queryRosters', () => {
306
658
  it('makes the expected query', async () => {
307
659
  webex.request.returns(
@@ -369,6 +721,22 @@ describe('plugin-meetings', () => {
369
721
  });
370
722
  });
371
723
 
724
+ describe('#clearBreakouts', () => {
725
+ it('call reset to clear breakouts', () => {
726
+ breakouts.set('breakouts', [{id: 'session1'}]);
727
+ breakouts.breakouts.reset = sinon.stub();
728
+ breakouts.clearBreakouts();
729
+ assert.calledWith(breakouts.breakouts.reset);
730
+ });
731
+
732
+ it('do nothing if breakouts already is empty', () => {
733
+ breakouts.set('breakouts', []);
734
+ breakouts.breakouts.reset = sinon.stub();
735
+ breakouts.clearBreakouts();
736
+ assert.notCalled(breakouts.breakouts.reset);
737
+ });
738
+ });
739
+
372
740
  describe('#getMainSession', () => {
373
741
  it('returns main session as expect', () => {
374
742
  breakouts.updateBreakout({
@@ -389,9 +757,9 @@ describe('plugin-meetings', () => {
389
757
  active: [{sessionId: 'sessionId1'}],
390
758
  },
391
759
  };
392
- breakouts.updateBreakoutSessions(payload);
393
760
 
394
761
  breakouts.set('sessionType', BREAKOUTS.SESSION_TYPES.MAIN);
762
+ breakouts.updateBreakoutSessions(payload);
395
763
  let result = breakouts.getMainSession();
396
764
  assert.equal(result.sessionId, 'sessionId');
397
765
 
@@ -438,18 +806,19 @@ describe('plugin-meetings', () => {
438
806
  });
439
807
 
440
808
  describe('#toggleBreakout', () => {
809
+ const mockEnableResponse = {
810
+ body: {
811
+ sessionId: 'sessionId',
812
+ groupId: 'groupId',
813
+ name: 'name',
814
+ current: true,
815
+ sessionType: 'sessionType',
816
+ url: 'url',
817
+ },
818
+ };
441
819
  it('enableBreakoutSession is undefined, run enableBreakouts then toggleBreakout', async () => {
442
820
  breakouts.enableBreakoutSession = undefined;
443
- breakouts.enableBreakouts = sinon.stub().resolves({
444
- body: {
445
- sessionId: 'sessionId',
446
- groupId: 'groupId',
447
- name: 'name',
448
- current: true,
449
- sessionType: 'sessionType',
450
- url: 'url',
451
- },
452
- });
821
+ breakouts.enableBreakouts = sinon.stub().resolves(mockEnableResponse);
453
822
  breakouts.updateBreakout = sinon.stub().resolves();
454
823
  breakouts.doToggleBreakout = sinon.stub().resolves();
455
824
 
@@ -466,6 +835,25 @@ describe('plugin-meetings', () => {
466
835
  assert.calledOnceWithExactly(breakouts.doToggleBreakout, false);
467
836
  });
468
837
 
838
+ it('first time enable breakouts, call updateBreakout to set initial params', async () => {
839
+ breakouts.enableBreakoutSession = undefined;
840
+ breakouts.enableBreakouts = sinon.stub().resolves(mockEnableResponse);
841
+ breakouts.updateBreakout = sinon.stub().resolves();
842
+ breakouts.doToggleBreakout = sinon.stub();
843
+
844
+ await breakouts.toggleBreakout(true);
845
+ assert.calledOnceWithExactly(breakouts.updateBreakout, {
846
+ sessionId: 'sessionId',
847
+ groupId: 'groupId',
848
+ name: 'name',
849
+ current: true,
850
+ sessionType: 'sessionType',
851
+ url: 'url',
852
+ });
853
+
854
+ assert.notCalled(breakouts.doToggleBreakout);
855
+ });
856
+
469
857
  it('enableBreakoutSession is exist, run toggleBreakout', async () => {
470
858
  breakouts.enableBreakoutSession = true;
471
859
  breakouts.doToggleBreakout = sinon.stub().resolves();
@@ -532,6 +920,12 @@ describe('plugin-meetings', () => {
532
920
 
533
921
  describe('#update', () => {
534
922
  it('makes the request as expected', async () => {
923
+ const mockedReturnBody = getBOResponse('OPEN');
924
+ webex.request.returns(
925
+ Promise.resolve({
926
+ body: mockedReturnBody,
927
+ })
928
+ );
535
929
  breakouts.editLock = {
536
930
  token: 'token1',
537
931
  };
@@ -539,6 +933,7 @@ describe('plugin-meetings', () => {
539
933
  id: 'groupId',
540
934
  sessions: [{name: 'Session 1'}],
541
935
  };
936
+ breakouts._setManageGroups = sinon.stub();
542
937
  const result = await breakouts.update(params);
543
938
  assert.calledOnceWithExactly(webex.request, {
544
939
  method: 'PUT',
@@ -548,6 +943,29 @@ describe('plugin-meetings', () => {
548
943
  groups: [params],
549
944
  },
550
945
  });
946
+ assert.calledOnceWithExactly(breakouts._setManageGroups, {
947
+ body: mockedReturnBody,
948
+ });
949
+ });
950
+ it('makes the request as expected when unlockEdit is true', async () => {
951
+ breakouts.editLock = {
952
+ token: 'token1',
953
+ };
954
+ const params = {
955
+ id: 'groupId',
956
+ sessions: [{name: 'Session 1'}],
957
+ };
958
+ breakouts._clearEditLockInfo = sinon.stub();
959
+ const result = await breakouts.update(params, true);
960
+ assert.calledOnceWithExactly(webex.request, {
961
+ method: 'PUT',
962
+ uri: 'url',
963
+ body: {
964
+ editlock: {token: 'token1', refresh: false},
965
+ groups: [params],
966
+ },
967
+ });
968
+ assert.calledOnceWithExactly(breakouts._clearEditLockInfo);
551
969
  });
552
970
  it('throw error if missing id in params', async () => {
553
971
  const params = {
@@ -580,7 +998,7 @@ describe('plugin-meetings', () => {
580
998
  );
581
999
  assert.calledOnceWithExactly(
582
1000
  LoggerProxy.logger.info,
583
- 'Breakouts#update --> Edit lock token mismatch',
1001
+ 'Breakouts#update --> Edit lock token mismatch'
584
1002
  );
585
1003
  });
586
1004
 
@@ -607,15 +1025,13 @@ describe('plugin-meetings', () => {
607
1025
 
608
1026
  assert.calledOnceWithExactly(
609
1027
  LoggerProxy.logger.info,
610
- 'Breakouts#update --> Not authorized to interact with edit lock',
1028
+ 'Breakouts#update --> Not authorized to interact with edit lock'
611
1029
  );
612
1030
  });
613
1031
 
614
1032
  it('rejects when other unknow error', async () => {
615
1033
  const mockError = new Error('something wrong');
616
- webex.request.returns(
617
- Promise.reject(mockError)
618
- );
1034
+ webex.request.returns(Promise.reject(mockError));
619
1035
  LoggerProxy.logger.info = sinon.stub();
620
1036
 
621
1037
  const params = {
@@ -623,24 +1039,21 @@ describe('plugin-meetings', () => {
623
1039
  sessions: [{name: 'Session 1'}],
624
1040
  };
625
1041
 
626
- await assert.isRejected(
627
- breakouts.update(params),
628
- mockError,
629
- 'something wrong'
630
- );
1042
+ await assert.isRejected(breakouts.update(params), mockError, 'something wrong');
631
1043
 
632
1044
  assert.calledOnceWithExactly(
633
1045
  LoggerProxy.logger.info,
634
- 'Breakouts#update --> something wrong',
1046
+ 'Breakouts#update --> something wrong'
635
1047
  );
636
1048
  });
637
1049
  });
638
1050
 
639
1051
  describe('#start', () => {
640
1052
  it('should start breakout sessions', async () => {
1053
+ const mockedReturnBody = getBOResponse('OPEN');
641
1054
  webex.request.returns(
642
1055
  Promise.resolve({
643
- body: getBOResponse('OPEN'),
1056
+ body: mockedReturnBody,
644
1057
  })
645
1058
  );
646
1059
 
@@ -648,6 +1061,7 @@ describe('plugin-meetings', () => {
648
1061
  await breakouts.getBreakout();
649
1062
 
650
1063
  const result = await breakouts.start();
1064
+ breakouts._setManageGroups = sinon.stub();
651
1065
  await breakouts.start({id: 'id', someOtherParam: 'someOtherParam'});
652
1066
 
653
1067
  const arg = webex.request.getCall(1).args[0];
@@ -661,7 +1075,6 @@ describe('plugin-meetings', () => {
661
1075
  action: 'START',
662
1076
  allowBackToMain: false,
663
1077
  allowToJoinLater: false,
664
- duration: BREAKOUTS.DEFAULT_DURATION,
665
1078
  });
666
1079
  assert.deepEqual(argObj2, {
667
1080
  id: 'id',
@@ -669,9 +1082,9 @@ describe('plugin-meetings', () => {
669
1082
  allowBackToMain: false,
670
1083
  allowToJoinLater: false,
671
1084
  someOtherParam: 'someOtherParam',
672
- duration: BREAKOUTS.DEFAULT_DURATION,
673
1085
  });
674
- assert.deepEqual(result, {body: getBOResponse('OPEN')});
1086
+ assert.deepEqual(result, {body: mockedReturnBody});
1087
+ assert.calledWithExactly(breakouts._setManageGroups, {body: mockedReturnBody})
675
1088
  });
676
1089
 
677
1090
  it('rejects when edit lock token mismatch', async () => {
@@ -705,6 +1118,8 @@ describe('plugin-meetings', () => {
705
1118
  await breakouts.getBreakout();
706
1119
 
707
1120
  const result = await breakouts.end();
1121
+
1122
+ breakouts._setManageGroups = sinon.stub();
708
1123
  await breakouts.end({id: 'id', someOtherParam: 'someOtherParam'});
709
1124
  const arg = webex.request.getCall(1).args[0];
710
1125
  const argObj1 = arg.body.groups[0];
@@ -720,6 +1135,7 @@ describe('plugin-meetings', () => {
720
1135
  someOtherParam: 'someOtherParam',
721
1136
  });
722
1137
  assert.deepEqual(result, {body: getBOResponse('CLOSING')});
1138
+ assert.calledOnceWithExactly(breakouts._setManageGroups, {body: getBOResponse('CLOSING')});
723
1139
  });
724
1140
 
725
1141
  it('rejects when edit lock token mismatch', async () => {
@@ -750,6 +1166,8 @@ describe('plugin-meetings', () => {
750
1166
 
751
1167
  breakouts.set('url', 'url');
752
1168
  const result = await breakouts.getBreakout();
1169
+
1170
+ breakouts._setManageGroups = sinon.stub();
753
1171
  await breakouts.getBreakout(true);
754
1172
  const arg1 = webex.request.getCall(0).args[0];
755
1173
  const arg2 = webex.request.getCall(1).args[0];
@@ -758,8 +1176,22 @@ describe('plugin-meetings', () => {
758
1176
  assert.equal(arg2.uri, 'url?editlock=true');
759
1177
  assert.equal(arg1.method, 'GET');
760
1178
  assert.deepEqual(result, {body: getBOResponse('PENDING')});
761
- assert.deepEqual(breakouts.groups, result.body.groups);
1179
+ assert.deepEqual(breakouts.manageGroups, result.body.groups);
762
1180
  assert.equal(breakouts.breakoutGroupId, 'groupId');
1181
+ assert.calledOnceWithExactly(breakouts._setManageGroups, {body: getBOResponse('PENDING')});
1182
+ });
1183
+
1184
+ it('breakoutGroupId should be empty if it is CLOSED group', async () => {
1185
+ webex.request.returns(
1186
+ Promise.resolve({
1187
+ body: getBOResponse('CLOSED'),
1188
+ })
1189
+ );
1190
+
1191
+ breakouts.set('url', 'url');
1192
+ await breakouts.getBreakout();
1193
+
1194
+ assert.equal(breakouts.breakoutGroupId, '');
763
1195
  });
764
1196
 
765
1197
  it('should call keep alive when response with edit lock info', async () => {
@@ -831,6 +1263,7 @@ describe('plugin-meetings', () => {
831
1263
  })
832
1264
  );
833
1265
 
1266
+ breakouts._setManageGroups = sinon.stub();
834
1267
  const result = await breakouts.clearSessions();
835
1268
  assert.calledOnceWithExactly(webex.request, {
836
1269
  method: 'PUT',
@@ -844,7 +1277,17 @@ describe('plugin-meetings', () => {
844
1277
  },
845
1278
  });
846
1279
 
847
- assert.equal(breakouts.groups[0].status, 'CLOSE');
1280
+ assert.calledOnceWithExactly(breakouts._setManageGroups, {
1281
+ body: {
1282
+ groups: [
1283
+ {
1284
+ id: '455556a4-37cd-4baa-89bc-8730581a1cc0',
1285
+ status: 'CLOSE',
1286
+ type: 'BREAKOUT',
1287
+ },
1288
+ ],
1289
+ },
1290
+ });
848
1291
  });
849
1292
 
850
1293
  it('rejects when edit lock token mismatch', async () => {
@@ -868,7 +1311,7 @@ describe('plugin-meetings', () => {
868
1311
  describe('create', () => {
869
1312
  it('response not include groups info', async () => {
870
1313
  const sessions = [{name: 'session1', anyoneCanJoin: true}];
871
- const result = await breakouts.create(sessions);
1314
+ const result = await breakouts.create({sessions});
872
1315
 
873
1316
  assert.equal(result, 'REQUEST_RETURN_VALUE');
874
1317
  });
@@ -890,9 +1333,9 @@ describe('plugin-meetings', () => {
890
1333
  })
891
1334
  );
892
1335
 
893
- const result = await breakouts.create(sessions);
1336
+ const result = await breakouts.create({sessions});
894
1337
 
895
- assert.equal(breakouts.groups[0].id, '455556a4-37cd-4baa-89bc-8730581a1cc0');
1338
+ assert.equal(breakouts.manageGroups[0].id, '455556a4-37cd-4baa-89bc-8730581a1cc0');
896
1339
  });
897
1340
 
898
1341
  it('rejects when edit lock token mismatch', async () => {
@@ -908,7 +1351,7 @@ describe('plugin-meetings', () => {
908
1351
  );
909
1352
 
910
1353
  await assert.isRejected(
911
- breakouts.create(sessions),
1354
+ breakouts.create({sessions}),
912
1355
  BreakoutEditLockedError,
913
1356
  'Edit lock token mismatch'
914
1357
  );
@@ -937,6 +1380,38 @@ describe('plugin-meetings', () => {
937
1380
  });
938
1381
  });
939
1382
 
1383
+ describe('hasBreakoutLocked', () => {
1384
+ it('has breakout locked is true', async () => {
1385
+ breakouts.editLock = {
1386
+ ttl: 30,
1387
+ token: 'token',
1388
+ state: 'LOCKED',
1389
+ };
1390
+
1391
+ assert.equal(breakouts.hasBreakoutLocked(), true);
1392
+ });
1393
+
1394
+ it('breakout locked by others', async () => {
1395
+ breakouts.editLock = {
1396
+ ttl: 30,
1397
+ token: '',
1398
+ state: 'LOCKED',
1399
+ };
1400
+
1401
+ assert.equal(breakouts.hasBreakoutLocked(), false);
1402
+ });
1403
+
1404
+ it('breakout not locked', async () => {
1405
+ breakouts.editLock = {
1406
+ ttl: 30,
1407
+ token: '',
1408
+ state: 'UNLOCKED',
1409
+ };
1410
+
1411
+ assert.equal(breakouts.hasBreakoutLocked(), false);
1412
+ });
1413
+ });
1414
+
940
1415
  describe('lockBreakout', () => {
941
1416
  it('lock breakout is true', async () => {
942
1417
  breakouts.editLock = {
@@ -987,7 +1462,6 @@ describe('plugin-meetings', () => {
987
1462
  });
988
1463
 
989
1464
  it('do not call unLock if edit lock info not exist ', async () => {
990
-
991
1465
  breakouts.unLockEditBreakout();
992
1466
  assert.notCalled(webex.request);
993
1467
  });
@@ -1138,65 +1612,80 @@ describe('plugin-meetings', () => {
1138
1612
  assert.calledOnceWithExactly(breakouts.assign, params);
1139
1613
  assert.equal(result, 'ASSIGN_RETURN_VALUE');
1140
1614
  });
1615
+
1616
+ it('called with editlock', async () => {
1617
+ breakouts.request = sinon.stub().returns(Promise.resolve('ASSIGN_RETURN_VALUE'));
1618
+ breakouts.editLock = {
1619
+ token: 'token1',
1620
+ };
1621
+ const params = [{id: 'sessionId', emails: ['111@cisco.com'], memberIds: []}];
1622
+ await breakouts.assign(params);
1623
+ const args = breakouts.request.getCall(0).args[0];
1624
+ expect(args).to.be.an('object', {
1625
+ method: 'PUT',
1626
+ uri: 'url',
1627
+ body: {
1628
+ editlock: {token: 'token1', refresh: true},
1629
+ groups: {
1630
+ id: 'sessionId',
1631
+ sessions: [
1632
+ {
1633
+ id: 'sessionId',
1634
+ assigned: [],
1635
+ assignedEmails: ['111@cisco.com'],
1636
+ anyoneCanJoin: false,
1637
+ },
1638
+ ],
1639
+ },
1640
+ },
1641
+ });
1642
+ });
1141
1643
  });
1142
1644
 
1143
- describe('queryPreAssignments', () => {
1645
+ describe('#queryPreAssignments', () => {
1144
1646
  it('makes the expected query', async () => {
1647
+ const mockPreAssignments = [
1648
+ {
1649
+ sessions: [
1650
+ {
1651
+ name: 'Breakout session 1',
1652
+ assignedEmails: ['aa@aa.com', 'bb@bb.com', 'cc@cc.com'],
1653
+ anyoneCanJoin: false,
1654
+ },
1655
+ {
1656
+ name: 'Breakout session 2',
1657
+ anyoneCanJoin: false,
1658
+ },
1659
+ {
1660
+ name: 'Breakout session 3',
1661
+ assignedEmails: ['cc@cc.com'],
1662
+ anyoneCanJoin: false,
1663
+ },
1664
+ ],
1665
+ unassignedInvitees: {
1666
+ emails: ['dd@dd.com'],
1667
+ },
1668
+ type: 'BREAKOUT',
1669
+ },
1670
+ ];
1145
1671
  webex.request.returns(
1146
1672
  Promise.resolve({
1147
1673
  body: {
1148
- "groups": [
1149
- {
1150
- "sessions": [
1151
- {
1152
- "name": "Breakout session 1",
1153
- "assignedEmails": [
1154
- "a@a.com",
1155
- "b@b.com",
1156
- "jial2@cisco.com"
1157
- ],
1158
- "anyoneCanJoin": false
1159
- },
1160
- {
1161
- "name": "Breakout session 2",
1162
- "anyoneCanJoin": false
1163
- },
1164
- {
1165
- "name": "Breakout session 3",
1166
- "assignedEmails": [
1167
- "c@c.com"
1168
- ],
1169
- "anyoneCanJoin": false
1170
- }
1171
- ],
1172
- "unassignedInvitees": {
1173
- "emails": [
1174
- "d@d.com"
1175
- ]
1176
- },
1177
- "type": "BREAKOUT"
1178
- }
1179
- ]
1180
- }
1674
+ groups: mockPreAssignments,
1675
+ },
1181
1676
  })
1182
1677
  );
1183
- breakouts.shouldFetchPreassignments = false;
1184
- const result = await breakouts.queryPreAssignments();
1185
- const arg = webex.request.getCall(0).args[0];
1186
- assert.equal(arg.uri, 'url/preassignments');
1187
- assert.equal(breakouts.groups[0].unassignedInvitees.emails[0],'d@d.com');
1188
- assert.equal(breakouts.groups[0].sessions[0].name,'Breakout session 1');
1189
- assert.equal(breakouts.groups[0].sessions[0].anyoneCanJoin,false);
1190
- assert.equal(breakouts.groups[0].sessions[0].assignedEmails.toString(), ["a@a.com", "b@b.com", "jial2@cisco.com"].toString());
1191
- assert.equal(breakouts.groups[0].sessions[1].name,'Breakout session 2');
1192
- assert.equal(breakouts.groups[0].sessions[1].anyoneCanJoin,false);
1193
- assert.equal(breakouts.groups[0].sessions[1].assignedEmails, undefined);
1194
- assert.equal(breakouts.groups[0].sessions[2].name,'Breakout session 3');
1195
- assert.equal(breakouts.groups[0].sessions[2].anyoneCanJoin,false);
1196
- assert.equal(breakouts.groups[0].sessions[2].assignedEmails[0], 'c@c.com');
1197
- assert.equal(breakouts.groups[0].unassignedInvitees.emails[0],'d@d.com');
1198
- assert.equal(breakouts.groups[0].type,'BREAKOUT');
1199
- assert.equal(breakouts.shouldFetchPreassignments, true);
1678
+ breakouts.set('locusUrl', 'test');
1679
+
1680
+ await breakouts.queryPreAssignments();
1681
+ assert.calledOnceWithExactly(webex.request, {
1682
+ uri: 'url/preassignments',
1683
+ qs: {
1684
+ locusUrl: 'dGVzdA==',
1685
+ }
1686
+ });
1687
+
1688
+ assert.deepEqual(breakouts.preAssignments, mockPreAssignments);
1200
1689
  });
1201
1690
 
1202
1691
  it('rejects when no pre-assignments created for this meeting', async () => {
@@ -1204,20 +1693,35 @@ describe('plugin-meetings', () => {
1204
1693
  statusCode: 404,
1205
1694
  body: {
1206
1695
  errorCode: 201404004,
1207
- message: 'No pre-assignments created for this meeting'
1696
+ message: 'No pre-assignments created for this meeting',
1208
1697
  },
1209
1698
  };
1210
1699
  webex.request.rejects(response);
1211
1700
  LoggerProxy.logger.error = sinon.stub();
1212
- const result = await breakouts.queryPreAssignments();
1701
+ const result = await breakouts.queryPreAssignments({enableBreakoutSession: true, hasBreakoutPreAssignments: true});
1213
1702
  await testUtils.flushPromises();
1214
1703
  assert.calledOnceWithExactly(
1215
1704
  LoggerProxy.logger.error,
1216
1705
  'Meeting:breakouts#queryPreAssignments failed',
1217
1706
  response
1218
1707
  );
1219
- });
1220
- });
1708
+ });
1709
+
1710
+ it('fail when no correct params', () => {
1711
+
1712
+ assert.deepEqual(breakouts.queryPreAssignments(undefined), undefined);
1713
+
1714
+ assert.deepEqual(breakouts.queryPreAssignments({}), undefined);
1715
+
1716
+ assert.deepEqual(breakouts.queryPreAssignments({ enableBreakoutSession: true, hasBreakoutPreAssignments: false }), undefined);
1717
+
1718
+ assert.deepEqual(breakouts.queryPreAssignments({ enableBreakoutSession: false, hasBreakoutPreAssignments: true }), undefined);
1719
+
1720
+ assert.deepEqual(breakouts.queryPreAssignments({ enableBreakoutSession: false, hasBreakoutPreAssignments: false }), undefined);
1721
+
1722
+ });
1723
+
1724
+ });
1221
1725
 
1222
1726
  describe('#dynamicAssign', () => {
1223
1727
  it('should make a PUT request with correct body and return the result', async () => {
@@ -1248,5 +1752,39 @@ describe('plugin-meetings', () => {
1248
1752
  });
1249
1753
  });
1250
1754
 
1755
+ describe('#triggerReturnToMainEvent', () => {
1756
+ const checkTrigger = ({breakout, shouldTrigger}) => {
1757
+ breakouts.trigger = sinon.stub();
1758
+ breakouts.triggerReturnToMainEvent(breakout);
1759
+ if (shouldTrigger) {
1760
+ assert.calledOnceWithExactly(breakouts.trigger, BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN);
1761
+ } else {
1762
+ assert.notCalled(breakouts.trigger);
1763
+ }
1764
+ }
1765
+ it('should trigger ASK_RETURN_TO_MAIN event correctly', () => {
1766
+ const breakout = {
1767
+ isMain: true,
1768
+ requested: true
1769
+ };
1770
+ checkTrigger({breakout, shouldTrigger: true})
1771
+ });
1772
+
1773
+ it('should not trigger ASK_RETURN_TO_MAIN event when sessionType is not MAIN', () => {
1774
+ const breakout = {
1775
+ isMain: false,
1776
+ requested: true
1777
+ };
1778
+ checkTrigger({breakout, shouldTrigger: false});
1779
+ });
1780
+
1781
+ it('should not trigger ASK_RETURN_TO_MAIN event when session is not requested', () => {
1782
+ const breakout = {
1783
+ isMain: true,
1784
+ requested: false
1785
+ };
1786
+ checkTrigger({breakout, shouldTrigger: false})
1787
+ });
1788
+ });
1251
1789
  });
1252
1790
  });