@webex/plugin-meetings 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/config.d.ts +1 -0
  4. package/dist/config.js +2 -1
  5. package/dist/config.js.map +1 -1
  6. package/dist/constants.d.ts +5 -4
  7. package/dist/constants.js +8 -4
  8. package/dist/constants.js.map +1 -1
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.js +6 -0
  11. package/dist/index.js.map +1 -1
  12. package/dist/interpretation/index.js +16 -2
  13. package/dist/interpretation/index.js.map +1 -1
  14. package/dist/interpretation/siLanguage.js +1 -1
  15. package/dist/locus-info/mediaSharesUtils.js +15 -1
  16. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  17. package/dist/locus-info/selfUtils.js +5 -0
  18. package/dist/locus-info/selfUtils.js.map +1 -1
  19. package/dist/media/MediaConnectionAwaiter.d.ts +61 -0
  20. package/dist/media/MediaConnectionAwaiter.js +163 -0
  21. package/dist/media/MediaConnectionAwaiter.js.map +1 -0
  22. package/dist/media/index.js +4 -1
  23. package/dist/media/index.js.map +1 -1
  24. package/dist/media/properties.js +4 -24
  25. package/dist/media/properties.js.map +1 -1
  26. package/dist/meeting/index.d.ts +26 -7
  27. package/dist/meeting/index.js +893 -677
  28. package/dist/meeting/index.js.map +1 -1
  29. package/dist/meeting/muteState.d.ts +2 -8
  30. package/dist/meeting/muteState.js +37 -25
  31. package/dist/meeting/muteState.js.map +1 -1
  32. package/dist/meeting/request.d.ts +3 -0
  33. package/dist/meeting/request.js +32 -23
  34. package/dist/meeting/request.js.map +1 -1
  35. package/dist/meeting/util.js +1 -0
  36. package/dist/meeting/util.js.map +1 -1
  37. package/dist/meeting-info/utilv2.js +4 -1
  38. package/dist/meeting-info/utilv2.js.map +1 -1
  39. package/dist/meetings/index.d.ts +8 -0
  40. package/dist/meetings/index.js +20 -0
  41. package/dist/meetings/index.js.map +1 -1
  42. package/dist/multistream/mediaRequestManager.d.ts +2 -1
  43. package/dist/multistream/mediaRequestManager.js +1 -1
  44. package/dist/multistream/mediaRequestManager.js.map +1 -1
  45. package/dist/multistream/remoteMediaGroup.d.ts +2 -0
  46. package/dist/multistream/remoteMediaGroup.js +16 -2
  47. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  48. package/dist/multistream/remoteMediaManager.d.ts +15 -0
  49. package/dist/multistream/remoteMediaManager.js +179 -65
  50. package/dist/multistream/remoteMediaManager.js.map +1 -1
  51. package/dist/multistream/sendSlotManager.d.ts +9 -1
  52. package/dist/multistream/sendSlotManager.js +22 -0
  53. package/dist/multistream/sendSlotManager.js.map +1 -1
  54. package/dist/reachability/clusterReachability.d.ts +1 -0
  55. package/dist/reachability/clusterReachability.js +29 -15
  56. package/dist/reachability/clusterReachability.js.map +1 -1
  57. package/dist/reachability/index.d.ts +4 -0
  58. package/dist/reachability/index.js +18 -2
  59. package/dist/reachability/index.js.map +1 -1
  60. package/dist/reachability/request.js +12 -10
  61. package/dist/reachability/request.js.map +1 -1
  62. package/dist/reachability/util.d.ts +7 -0
  63. package/dist/reachability/util.js +19 -0
  64. package/dist/reachability/util.js.map +1 -1
  65. package/dist/reconnection-manager/index.js +2 -1
  66. package/dist/reconnection-manager/index.js.map +1 -1
  67. package/dist/roap/index.d.ts +10 -2
  68. package/dist/roap/index.js +15 -0
  69. package/dist/roap/index.js.map +1 -1
  70. package/dist/roap/request.js +3 -3
  71. package/dist/roap/request.js.map +1 -1
  72. package/dist/roap/turnDiscovery.d.ts +64 -17
  73. package/dist/roap/turnDiscovery.js +307 -126
  74. package/dist/roap/turnDiscovery.js.map +1 -1
  75. package/dist/statsAnalyzer/index.js +53 -30
  76. package/dist/statsAnalyzer/index.js.map +1 -1
  77. package/dist/webinar/index.js +1 -1
  78. package/package.json +22 -22
  79. package/src/config.ts +1 -0
  80. package/src/constants.ts +7 -3
  81. package/src/index.ts +1 -0
  82. package/src/interpretation/index.ts +18 -1
  83. package/src/locus-info/mediaSharesUtils.ts +16 -0
  84. package/src/locus-info/selfUtils.ts +5 -0
  85. package/src/media/MediaConnectionAwaiter.ts +174 -0
  86. package/src/media/index.ts +3 -1
  87. package/src/media/properties.ts +6 -31
  88. package/src/meeting/index.ts +321 -106
  89. package/src/meeting/muteState.ts +34 -20
  90. package/src/meeting/request.ts +18 -2
  91. package/src/meeting/util.ts +1 -0
  92. package/src/meeting-info/utilv2.ts +2 -1
  93. package/src/meetings/index.ts +18 -0
  94. package/src/multistream/mediaRequestManager.ts +4 -1
  95. package/src/multistream/remoteMediaGroup.ts +19 -0
  96. package/src/multistream/remoteMediaManager.ts +101 -16
  97. package/src/multistream/sendSlotManager.ts +28 -0
  98. package/src/reachability/clusterReachability.ts +20 -5
  99. package/src/reachability/index.ts +24 -1
  100. package/src/reachability/request.ts +15 -11
  101. package/src/reachability/util.ts +21 -0
  102. package/src/reconnection-manager/index.ts +1 -1
  103. package/src/roap/index.ts +25 -3
  104. package/src/roap/request.ts +3 -3
  105. package/src/roap/turnDiscovery.ts +244 -78
  106. package/src/statsAnalyzer/index.ts +63 -27
  107. package/test/integration/spec/journey.js +14 -14
  108. package/test/integration/spec/space-meeting.js +1 -1
  109. package/test/unit/spec/interpretation/index.ts +39 -3
  110. package/test/unit/spec/locus-info/index.js +28 -19
  111. package/test/unit/spec/locus-info/mediaSharesUtils.ts +9 -0
  112. package/test/unit/spec/locus-info/selfUtils.js +42 -12
  113. package/test/unit/spec/media/MediaConnectionAwaiter.ts +344 -0
  114. package/test/unit/spec/media/index.ts +89 -78
  115. package/test/unit/spec/media/properties.ts +16 -70
  116. package/test/unit/spec/meeting/index.js +638 -139
  117. package/test/unit/spec/meeting/muteState.js +219 -67
  118. package/test/unit/spec/meeting/request.js +21 -0
  119. package/test/unit/spec/meeting/utils.js +6 -1
  120. package/test/unit/spec/meeting-info/utilv2.js +6 -0
  121. package/test/unit/spec/meetings/index.js +40 -20
  122. package/test/unit/spec/multistream/mediaRequestManager.ts +20 -2
  123. package/test/unit/spec/multistream/remoteMediaGroup.ts +79 -1
  124. package/test/unit/spec/multistream/remoteMediaManager.ts +199 -1
  125. package/test/unit/spec/multistream/sendSlotManager.ts +50 -18
  126. package/test/unit/spec/reachability/clusterReachability.ts +86 -22
  127. package/test/unit/spec/reachability/index.ts +197 -60
  128. package/test/unit/spec/reachability/request.js +15 -7
  129. package/test/unit/spec/reachability/util.ts +32 -2
  130. package/test/unit/spec/reconnection-manager/index.js +28 -0
  131. package/test/unit/spec/roap/index.ts +61 -6
  132. package/test/unit/spec/roap/turnDiscovery.ts +298 -16
  133. package/test/unit/spec/stats-analyzer/index.js +179 -0
  134. package/dist/member/member.types.d.ts +0 -11
  135. package/dist/member/member.types.js +0 -17
  136. package/dist/member/member.types.js.map +0 -1
  137. package/src/member/member.types.ts +0 -13
  138. /package/test/unit/spec/locus-info/{lib/selfConstant.js → selfConstant.js} +0 -0
@@ -0,0 +1,344 @@
1
+ import {assert} from '@webex/test-helper-chai';
2
+ import sinon from 'sinon';
3
+ import {ConnectionState, Event} from '@webex/internal-media-core';
4
+ import testUtils from '../../../utils/testUtils';
5
+ import {ICE_AND_DTLS_CONNECTION_TIMEOUT} from '@webex/plugin-meetings/src/constants';
6
+ import MediaConnectionAwaiter from '../../../../src/media/MediaConnectionAwaiter';
7
+
8
+ describe('MediaConnectionAwaiter', () => {
9
+ let mediaConnectionAwaiter;
10
+ let mockMC;
11
+ let clock;
12
+
13
+ beforeEach(() => {
14
+ clock = sinon.useFakeTimers();
15
+
16
+ mockMC = {
17
+ getStats: sinon.stub().resolves([]),
18
+ on: sinon.stub(),
19
+ off: sinon.stub(),
20
+ getConnectionState: sinon.stub().returns(ConnectionState.New),
21
+ getIceGatheringState: sinon.stub().returns('new'),
22
+ };
23
+
24
+ mediaConnectionAwaiter = new MediaConnectionAwaiter({
25
+ webrtcMediaConnection: mockMC,
26
+ });
27
+ });
28
+
29
+ afterEach(() => {
30
+ clock.restore();
31
+ sinon.restore();
32
+ });
33
+
34
+ describe('waitForMediaConnectionConnected', () => {
35
+ it('resolves immediately if connection state is connected', async () => {
36
+ mockMC.getConnectionState.returns(ConnectionState.Connected);
37
+
38
+ await mediaConnectionAwaiter.waitForMediaConnectionConnected();
39
+
40
+ assert.neverCalledWith(mockMC.on);
41
+ });
42
+
43
+ it('rejects after timeout if ice state is not connected', async () => {
44
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
45
+ mockMC.getIceGatheringState.returns('gathering');
46
+
47
+ let promiseResolved = false;
48
+ let promiseRejected = false;
49
+
50
+ mediaConnectionAwaiter
51
+ .waitForMediaConnectionConnected()
52
+ .then(() => {
53
+ promiseResolved = true;
54
+ })
55
+ .catch(() => {
56
+ promiseRejected = true;
57
+ });
58
+
59
+ await testUtils.flushPromises();
60
+ assert.equal(promiseResolved, false);
61
+ assert.equal(promiseRejected, false);
62
+
63
+ // check the right listener was registered
64
+ assert.calledTwice(mockMC.on);
65
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
66
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
67
+ const listener = mockMC.on.getCall(1).args[1];
68
+
69
+ mockMC.getIceGatheringState.returns('complete');
70
+ listener();
71
+
72
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
73
+ await testUtils.flushPromises();
74
+
75
+ assert.equal(promiseResolved, false);
76
+ assert.equal(promiseRejected, true);
77
+
78
+ assert.calledTwice(mockMC.off);
79
+ });
80
+
81
+ it('resolves after timeout if connection state reach connected/completed', async () => {
82
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
83
+ mockMC.getIceGatheringState.returns('gathering');
84
+
85
+ let promiseResolved = false;
86
+ let promiseRejected = false;
87
+
88
+ mediaConnectionAwaiter
89
+ .waitForMediaConnectionConnected()
90
+ .then(() => {
91
+ promiseResolved = true;
92
+ })
93
+ .catch(() => {
94
+ promiseRejected = true;
95
+ });
96
+
97
+ await testUtils.flushPromises();
98
+ assert.equal(promiseResolved, false);
99
+ assert.equal(promiseRejected, false);
100
+
101
+ // check the right listener was registered
102
+ assert.calledTwice(mockMC.on);
103
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
104
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
105
+
106
+ mockMC.getConnectionState.returns(ConnectionState.Connected);
107
+
108
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
109
+ await testUtils.flushPromises();
110
+
111
+ assert.equal(promiseResolved, true);
112
+ assert.equal(promiseRejected, false);
113
+
114
+ assert.calledTwice(mockMC.off);
115
+ });
116
+
117
+ it(`resolves when media connection reaches "connected" state`, async () => {
118
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
119
+ mockMC.getIceGatheringState.returns('gathering');
120
+
121
+ const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
122
+
123
+ let promiseResolved = false;
124
+ let promiseRejected = false;
125
+
126
+ mediaConnectionAwaiter
127
+ .waitForMediaConnectionConnected()
128
+ .then(() => {
129
+ promiseResolved = true;
130
+ })
131
+ .catch(() => {
132
+ promiseRejected = true;
133
+ });
134
+
135
+ await testUtils.flushPromises();
136
+ assert.equal(promiseResolved, false);
137
+ assert.equal(promiseRejected, false);
138
+
139
+ // check the right listener was registered
140
+ assert.calledTwice(mockMC.on);
141
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
142
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
143
+ const listener = mockMC.on.getCall(0).args[1];
144
+
145
+ // call the listener and pretend we are now connected
146
+ mockMC.getConnectionState.returns(ConnectionState.Connected);
147
+ listener();
148
+ await testUtils.flushPromises();
149
+
150
+ assert.equal(promiseResolved, true);
151
+ assert.equal(promiseRejected, false);
152
+
153
+ // check that listener was removed
154
+ assert.calledTwice(mockMC.off);
155
+
156
+ assert.calledOnce(clearTimeoutSpy);
157
+ });
158
+
159
+ it(`ice gathering state update to "gathering" state does not update timer`, async () => {
160
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
161
+ mockMC.getIceGatheringState.returns('new');
162
+
163
+ const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
164
+
165
+ let promiseResolved = false;
166
+ let promiseRejected = false;
167
+
168
+ mediaConnectionAwaiter
169
+ .waitForMediaConnectionConnected()
170
+ .then(() => {
171
+ promiseResolved = true;
172
+ })
173
+ .catch(() => {
174
+ promiseRejected = true;
175
+ });
176
+
177
+ await testUtils.flushPromises();
178
+ assert.equal(promiseResolved, false);
179
+ assert.equal(promiseRejected, false);
180
+
181
+ // check the right listener was registered
182
+ assert.calledTwice(mockMC.on);
183
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
184
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
185
+ const listener = mockMC.on.getCall(1).args[1];
186
+
187
+ // call the listener and pretend we are now connected
188
+ mockMC.getIceGatheringState.returns('gathering');
189
+ listener();
190
+
191
+ mockMC.getConnectionState.returns(ConnectionState.Connected);
192
+
193
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
194
+ await testUtils.flushPromises();
195
+
196
+ assert.equal(promiseResolved, true);
197
+ assert.equal(promiseRejected, false);
198
+
199
+ // check that listener was removed
200
+ assert.calledTwice(mockMC.off);
201
+
202
+ assert.neverCalledWith(clearTimeoutSpy);
203
+ });
204
+
205
+ it(`ice gathering update to 'complete' state restarts the timer`, async () => {
206
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
207
+ mockMC.getIceGatheringState.returns('new');
208
+
209
+ const setTimeoutSpy = sinon.spy(clock, 'setTimeout');
210
+ const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
211
+
212
+ let promiseResolved = false;
213
+ let promiseRejected = false;
214
+
215
+ mediaConnectionAwaiter
216
+ .waitForMediaConnectionConnected()
217
+ .then(() => {
218
+ promiseResolved = true;
219
+ })
220
+ .catch(() => {
221
+ promiseRejected = true;
222
+ });
223
+
224
+ await testUtils.flushPromises();
225
+ assert.equal(promiseResolved, false);
226
+ assert.equal(promiseRejected, false);
227
+
228
+ assert.calledOnce(setTimeoutSpy);
229
+
230
+ // check the right listener was registered
231
+ assert.calledTwice(mockMC.on);
232
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
233
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
234
+ const listener = mockMC.on.getCall(1).args[1];
235
+
236
+ // call the listener and pretend we are now connected
237
+ mockMC.getIceGatheringState.returns('complete');
238
+ listener();
239
+
240
+ assert.calledOnce(clearTimeoutSpy);
241
+ assert.calledTwice(setTimeoutSpy);
242
+
243
+ mockMC.getConnectionState.returns(ConnectionState.Connected);
244
+
245
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
246
+ await testUtils.flushPromises();
247
+
248
+ assert.equal(promiseResolved, true);
249
+ assert.equal(promiseRejected, false);
250
+
251
+ // check that listener was removed
252
+ assert.calledTwice(mockMC.off);
253
+ });
254
+
255
+ it(`reject with restart timer once if gathering state is not complete`, async () => {
256
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
257
+ mockMC.getIceGatheringState.returns('new');
258
+
259
+ const setTimeoutSpy = sinon.spy(clock, 'setTimeout');
260
+ const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
261
+
262
+ let promiseResolved = false;
263
+ let promiseRejected = false;
264
+
265
+ mediaConnectionAwaiter
266
+ .waitForMediaConnectionConnected()
267
+ .then(() => {
268
+ promiseResolved = true;
269
+ })
270
+ .catch(() => {
271
+ promiseRejected = true;
272
+ });
273
+
274
+ await testUtils.flushPromises();
275
+ assert.equal(promiseResolved, false);
276
+ assert.equal(promiseRejected, false);
277
+
278
+ // check the right listener was registered
279
+ assert.calledTwice(mockMC.on);
280
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
281
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
282
+
283
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT * 2);
284
+ await testUtils.flushPromises();
285
+
286
+ assert.equal(promiseResolved, false);
287
+ assert.equal(promiseRejected, true);
288
+
289
+ // check that listener was removed
290
+ assert.calledTwice(mockMC.off);
291
+
292
+ assert.calledOnce(clearTimeoutSpy);
293
+ assert.calledTwice(setTimeoutSpy);
294
+ });
295
+
296
+ it(`resolves gathering and connection state complete right after`, async () => {
297
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
298
+ mockMC.getIceGatheringState.returns('new');
299
+
300
+ const setTimeoutSpy = sinon.spy(clock, 'setTimeout');
301
+ const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
302
+
303
+ let promiseResolved = false;
304
+ let promiseRejected = false;
305
+
306
+ mediaConnectionAwaiter
307
+ .waitForMediaConnectionConnected()
308
+ .then(() => {
309
+ promiseResolved = true;
310
+ })
311
+ .catch(() => {
312
+ promiseRejected = true;
313
+ });
314
+
315
+ await testUtils.flushPromises();
316
+ assert.equal(promiseResolved, false);
317
+ assert.equal(promiseRejected, false);
318
+
319
+ // check the right listener was registered
320
+ assert.calledTwice(mockMC.on);
321
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
322
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
323
+ const connectionStateListener = mockMC.on.getCall(0).args[1];
324
+ const iceGatheringListener = mockMC.on.getCall(1).args[1];
325
+
326
+ mockMC.getIceGatheringState.returns('complete');
327
+ iceGatheringListener();
328
+
329
+ mockMC.getConnectionState.returns(ConnectionState.Connected);
330
+ connectionStateListener();
331
+
332
+ await testUtils.flushPromises();
333
+
334
+ assert.equal(promiseResolved, true);
335
+ assert.equal(promiseRejected, false);
336
+
337
+ // check that listener was removed
338
+ assert.calledTwice(mockMC.off);
339
+
340
+ assert.calledTwice(clearTimeoutSpy);
341
+ assert.calledTwice(setTimeoutSpy);
342
+ });
343
+ });
344
+ });
@@ -170,37 +170,15 @@ describe('createMediaConnection', () => {
170
170
  );
171
171
  });
172
172
 
173
- it('passes empty ICE servers array to MultistreamRoapMediaConnection if turnServerInfo is undefined (multistream enabled)', () => {
174
- const multistreamRoapMediaConnectionConstructorStub = sinon
175
- .stub(internalMediaModule, 'MultistreamRoapMediaConnection')
176
- .returns(fakeRoapMediaConnection);
177
-
178
- Media.createMediaConnection(true, 'debug string', webex, 'meeting id', 'correlationId', {
179
- mediaProperties: {
180
- mediaDirection: {
181
- sendAudio: true,
182
- sendVideo: true,
183
- sendShare: false,
184
- receiveAudio: true,
185
- receiveVideo: true,
186
- receiveShare: true,
187
- },
188
- },
189
- });
190
- assert.calledOnce(multistreamRoapMediaConnectionConstructorStub);
191
- assert.calledWith(
192
- multistreamRoapMediaConnectionConstructorStub,
193
- {
194
- iceServers: [],
195
- },
196
- 'meeting id'
197
- );
198
-
199
- it('does not pass bundlePolicy to MultistreamRoapMediaConnection if bundlePolicy is undefined', () => {
173
+ [
174
+ {testCase: 'turnServerInfo is undefined', turnServerInfo: undefined},
175
+ {testCase: 'turnServerInfo.url is empty string', turnServerInfo: {url: '', username: 'turn username', password: 'turn password'}},
176
+ ].forEach(({testCase, turnServerInfo}) => {
177
+ it(`passes empty ICE servers array to MultistreamRoapMediaConnection if ${testCase} (multistream enabled)`, () => {
200
178
  const multistreamRoapMediaConnectionConstructorStub = sinon
201
179
  .stub(internalMediaModule, 'MultistreamRoapMediaConnection')
202
180
  .returns(fakeRoapMediaConnection);
203
-
181
+
204
182
  Media.createMediaConnection(true, 'debug string', webex, 'meeting id', 'correlationId', {
205
183
  mediaProperties: {
206
184
  mediaDirection: {
@@ -212,7 +190,7 @@ describe('createMediaConnection', () => {
212
190
  receiveShare: true,
213
191
  },
214
192
  },
215
- bundlePolicy: undefined,
193
+ turnServerInfo,
216
194
  });
217
195
  assert.calledOnce(multistreamRoapMediaConnectionConstructorStub);
218
196
  assert.calledWith(
@@ -221,75 +199,108 @@ describe('createMediaConnection', () => {
221
199
  iceServers: [],
222
200
  },
223
201
  'meeting id'
224
- );
202
+ );
225
203
  });
226
204
  });
227
-
228
- it('passes empty ICE servers array to RoapMediaConnection if turnServerInfo is undefined (multistream disabled)', () => {
229
- const roapMediaConnectionConstructorStub = sinon
230
- .stub(internalMediaModule, 'RoapMediaConnection')
205
+
206
+ it('does not pass bundlePolicy to MultistreamRoapMediaConnection if bundlePolicy is undefined', () => {
207
+ const multistreamRoapMediaConnectionConstructorStub = sinon
208
+ .stub(internalMediaModule, 'MultistreamRoapMediaConnection')
231
209
  .returns(fakeRoapMediaConnection);
232
210
 
233
- StaticConfig.set({bandwidth: {audio: 123, video: 456, startBitrate: 999}});
234
-
235
- const ENABLE_EXTMAP = false;
236
- const ENABLE_RTX = true;
237
-
238
- Media.createMediaConnection(false, 'some debug id', webex, 'meeting id', 'correlationId', {
211
+ Media.createMediaConnection(true, 'debug string', webex, 'meeting id', 'correlationId', {
239
212
  mediaProperties: {
240
213
  mediaDirection: {
241
214
  sendAudio: true,
242
215
  sendVideo: true,
243
- sendShare: true,
216
+ sendShare: false,
244
217
  receiveAudio: true,
245
218
  receiveVideo: true,
246
219
  receiveShare: true,
247
220
  },
248
- audioStream: fakeAudioStream,
249
- videoStream: null,
250
- shareVideoStream: fakeShareVideoStream,
251
- shareAudioStream: fakeShareAudioStream,
252
221
  },
253
- remoteQualityLevel: 'HIGH',
254
- enableRtx: ENABLE_RTX,
255
- enableExtmap: ENABLE_EXTMAP,
256
- turnServerInfo: undefined,
222
+ bundlePolicy: undefined,
257
223
  });
258
- assert.calledOnce(roapMediaConnectionConstructorStub);
224
+ assert.calledOnce(multistreamRoapMediaConnectionConstructorStub);
259
225
  assert.calledWith(
260
- roapMediaConnectionConstructorStub,
226
+ multistreamRoapMediaConnectionConstructorStub,
261
227
  {
262
228
  iceServers: [],
263
- skipInactiveTransceivers: false,
264
- requireH264: true,
265
- sdpMunging: {
266
- convertPort9to0: false,
267
- addContentSlides: true,
268
- bandwidthLimits: {
269
- audio: 123,
270
- video: 456,
229
+ },
230
+ 'meeting id'
231
+ );
232
+ });
233
+
234
+ [
235
+ {testCase: 'turnServerInfo is undefined', turnServerInfo: undefined},
236
+ {testCase: 'turnServerInfo.url is empty string', turnServerInfo: {url: '', username: 'turn username', password: 'turn password'}},
237
+ ].forEach(({testCase, turnServerInfo}) => {
238
+ it(`passes empty ICE servers array to RoapMediaConnection if ${testCase} (multistream disabled)`, () => {
239
+ const roapMediaConnectionConstructorStub = sinon
240
+ .stub(internalMediaModule, 'RoapMediaConnection')
241
+ .returns(fakeRoapMediaConnection);
242
+
243
+ StaticConfig.set({bandwidth: {audio: 123, video: 456, startBitrate: 999}});
244
+
245
+ const ENABLE_EXTMAP = false;
246
+ const ENABLE_RTX = true;
247
+
248
+ Media.createMediaConnection(false, 'some debug id', webex, 'meeting id', 'correlationId', {
249
+ mediaProperties: {
250
+ mediaDirection: {
251
+ sendAudio: true,
252
+ sendVideo: true,
253
+ sendShare: true,
254
+ receiveAudio: true,
255
+ receiveVideo: true,
256
+ receiveShare: true,
271
257
  },
272
- startBitrate: 999,
273
- periodicKeyframes: 20,
274
- disableExtmap: !ENABLE_EXTMAP,
275
- disableRtx: !ENABLE_RTX,
258
+ audioStream: fakeAudioStream,
259
+ videoStream: null,
260
+ shareVideoStream: fakeShareVideoStream,
261
+ shareAudioStream: fakeShareAudioStream,
276
262
  },
277
- },
278
- {
279
- localTracks: {
280
- audio: fakeTrack,
281
- video: undefined,
282
- screenShareVideo: fakeTrack,
283
- screenShareAudio: fakeTrack,
263
+ remoteQualityLevel: 'HIGH',
264
+ enableRtx: ENABLE_RTX,
265
+ enableExtmap: ENABLE_EXTMAP,
266
+ turnServerInfo,
267
+ });
268
+ assert.calledOnce(roapMediaConnectionConstructorStub);
269
+ assert.calledWith(
270
+ roapMediaConnectionConstructorStub,
271
+ {
272
+ iceServers: [],
273
+ skipInactiveTransceivers: false,
274
+ requireH264: true,
275
+ sdpMunging: {
276
+ convertPort9to0: false,
277
+ addContentSlides: true,
278
+ bandwidthLimits: {
279
+ audio: 123,
280
+ video: 456,
281
+ },
282
+ startBitrate: 999,
283
+ periodicKeyframes: 20,
284
+ disableExtmap: !ENABLE_EXTMAP,
285
+ disableRtx: !ENABLE_RTX,
286
+ },
284
287
  },
285
- direction: {
286
- audio: 'sendrecv',
287
- video: 'sendrecv',
288
- screenShareVideo: 'sendrecv',
288
+ {
289
+ localTracks: {
290
+ audio: fakeTrack,
291
+ video: undefined,
292
+ screenShareVideo: fakeTrack,
293
+ screenShareAudio: fakeTrack,
294
+ },
295
+ direction: {
296
+ audio: 'sendrecv',
297
+ video: 'sendrecv',
298
+ screenShareVideo: 'sendrecv',
299
+ },
300
+ remoteQualityLevel: 'HIGH',
289
301
  },
290
- remoteQualityLevel: 'HIGH',
291
- },
292
- 'some debug id'
293
- );
302
+ 'some debug id'
303
+ );
304
+ });
294
305
  });
295
306
  });
@@ -1,11 +1,10 @@
1
1
  import {assert} from '@webex/test-helper-chai';
2
2
  import sinon from 'sinon';
3
- import {ConnectionState, Event} from '@webex/internal-media-core';
3
+ import {ConnectionState} from '@webex/internal-media-core';
4
4
  import MediaProperties from '@webex/plugin-meetings/src/media/properties';
5
- import MediaUtil from '@webex/plugin-meetings/src/media/util';
6
5
  import testUtils from '../../../utils/testUtils';
7
- import {ICE_AND_DTLS_CONNECTION_TIMEOUT} from '@webex/plugin-meetings/src/constants';
8
6
  import {Defer} from '@webex/common';
7
+ import MediaConnectionAwaiter from '../../../../src/media/MediaConnectionAwaiter';
9
8
 
10
9
  describe('MediaProperties', () => {
11
10
  let mediaProperties;
@@ -31,80 +30,27 @@ describe('MediaProperties', () => {
31
30
  sinon.restore();
32
31
  });
33
32
  describe('waitForMediaConnectionConnected', () => {
34
- it('resolves immediately if ice state is connected', async () => {
35
- await mediaProperties.waitForMediaConnectionConnected();
36
- });
37
- it('rejects after timeout if ice state does not reach connected/completed', async () => {
38
- mockMC.getConnectionState.returns(ConnectionState.Connecting);
39
-
40
- let promiseResolved = false;
41
- let promiseRejected = false;
42
-
43
- mediaProperties
44
- .waitForMediaConnectionConnected()
45
- .then(() => {
46
- promiseResolved = true;
47
- })
48
- .catch(() => {
49
- promiseRejected = true;
50
- });
51
-
52
- assert.equal(promiseResolved, false);
53
- assert.equal(promiseRejected, false);
54
-
55
- await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
56
- await testUtils.flushPromises();
33
+ it('resolves if media connection is connected', async () => {
34
+ const waitForMediaConnectionConnectedResult = new Defer();
57
35
 
58
- assert.equal(promiseResolved, false);
59
- assert.equal(promiseRejected, true);
36
+ sinon
37
+ .stub(MediaConnectionAwaiter.prototype, 'waitForMediaConnectionConnected')
38
+ .returns(waitForMediaConnectionConnectedResult.promise);
60
39
 
61
- // check that listener was registered and removed
62
- assert.calledOnce(mockMC.on);
63
- assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
64
- const listener = mockMC.on.getCall(0).args[1];
40
+ waitForMediaConnectionConnectedResult.resolve();
65
41
 
66
- assert.calledOnce(mockMC.off);
67
- assert.calledWith(mockMC.off, Event.CONNECTION_STATE_CHANGED, listener);
42
+ await mediaProperties.waitForMediaConnectionConnected();
68
43
  });
44
+ it('rejects if media connection is not connected', async () => {
45
+ const waitForMediaConnectionConnectedResult = new Defer();
69
46
 
70
- it(`resolves when media connection reaches "connected" state`, async () => {
71
- mockMC.getConnectionState.returns(ConnectionState.Connecting);
72
-
73
- const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
74
-
75
- let promiseResolved = false;
76
- let promiseRejected = false;
77
-
78
- mediaProperties
79
- .waitForMediaConnectionConnected()
80
- .then(() => {
81
- promiseResolved = true;
82
- })
83
- .catch(() => {
84
- promiseRejected = true;
85
- });
86
-
87
- assert.equal(promiseResolved, false);
88
- assert.equal(promiseRejected, false);
89
-
90
- // check the right listener was registered
91
- assert.calledOnce(mockMC.on);
92
- assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
93
- const listener = mockMC.on.getCall(0).args[1];
94
-
95
- // call the listener and pretend we are now connected
96
- mockMC.getConnectionState.returns(ConnectionState.Connected);
97
- listener();
98
- await testUtils.flushPromises();
99
-
100
- assert.equal(promiseResolved, true);
101
- assert.equal(promiseRejected, false);
47
+ sinon
48
+ .stub(MediaConnectionAwaiter.prototype, 'waitForMediaConnectionConnected')
49
+ .returns(waitForMediaConnectionConnectedResult.promise);
102
50
 
103
- // check that listener was removed
104
- assert.calledOnce(mockMC.off);
105
- assert.calledWith(mockMC.off, Event.CONNECTION_STATE_CHANGED, listener);
51
+ waitForMediaConnectionConnectedResult.reject();
106
52
 
107
- assert.calledOnce(clearTimeoutSpy);
53
+ await assert.isRejected(mediaProperties.waitForMediaConnectionConnected());
108
54
  });
109
55
  });
110
56