@webex/plugin-meetings 3.3.1-next.3 → 3.3.1-next.31

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 (108) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +7 -2
  3. package/dist/breakouts/index.js.map +1 -1
  4. package/dist/constants.js +12 -2
  5. package/dist/constants.js.map +1 -1
  6. package/dist/interpretation/index.js +1 -1
  7. package/dist/interpretation/siLanguage.js +1 -1
  8. package/dist/media/MediaConnectionAwaiter.js +68 -13
  9. package/dist/media/MediaConnectionAwaiter.js.map +1 -1
  10. package/dist/mediaQualityMetrics/config.js +16 -6
  11. package/dist/mediaQualityMetrics/config.js.map +1 -1
  12. package/dist/meeting/connectionStateHandler.js +67 -0
  13. package/dist/meeting/connectionStateHandler.js.map +1 -0
  14. package/dist/meeting/index.js +242 -133
  15. package/dist/meeting/index.js.map +1 -1
  16. package/dist/meeting/locusMediaRequest.js +7 -0
  17. package/dist/meeting/locusMediaRequest.js.map +1 -1
  18. package/dist/meeting/util.js +1 -0
  19. package/dist/meeting/util.js.map +1 -1
  20. package/dist/meeting-info/index.js +4 -4
  21. package/dist/meeting-info/index.js.map +1 -1
  22. package/dist/meeting-info/meeting-info-v2.js +2 -2
  23. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  24. package/dist/meeting-info/util.js +17 -17
  25. package/dist/meeting-info/util.js.map +1 -1
  26. package/dist/meeting-info/utilv2.js +16 -16
  27. package/dist/meeting-info/utilv2.js.map +1 -1
  28. package/dist/meetings/collection.js +1 -1
  29. package/dist/meetings/collection.js.map +1 -1
  30. package/dist/meetings/index.js +37 -33
  31. package/dist/meetings/index.js.map +1 -1
  32. package/dist/meetings/meetings.types.js +8 -0
  33. package/dist/meetings/meetings.types.js.map +1 -1
  34. package/dist/meetings/util.js +3 -2
  35. package/dist/meetings/util.js.map +1 -1
  36. package/dist/metrics/constants.js +2 -1
  37. package/dist/metrics/constants.js.map +1 -1
  38. package/dist/metrics/index.js +57 -0
  39. package/dist/metrics/index.js.map +1 -1
  40. package/dist/personal-meeting-room/index.js +1 -1
  41. package/dist/personal-meeting-room/index.js.map +1 -1
  42. package/dist/reachability/clusterReachability.js +108 -53
  43. package/dist/reachability/clusterReachability.js.map +1 -1
  44. package/dist/reachability/index.js +415 -56
  45. package/dist/reachability/index.js.map +1 -1
  46. package/dist/statsAnalyzer/index.js +81 -27
  47. package/dist/statsAnalyzer/index.js.map +1 -1
  48. package/dist/statsAnalyzer/mqaUtil.js +36 -10
  49. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  50. package/dist/types/constants.d.ts +11 -0
  51. package/dist/types/media/MediaConnectionAwaiter.d.ts +24 -4
  52. package/dist/types/mediaQualityMetrics/config.d.ts +11 -0
  53. package/dist/types/meeting/connectionStateHandler.d.ts +30 -0
  54. package/dist/types/meeting/index.d.ts +13 -3
  55. package/dist/types/meeting/locusMediaRequest.d.ts +2 -0
  56. package/dist/types/meeting-info/index.d.ts +3 -2
  57. package/dist/types/meeting-info/meeting-info-v2.d.ts +3 -2
  58. package/dist/types/meeting-info/util.d.ts +5 -4
  59. package/dist/types/meeting-info/utilv2.d.ts +3 -2
  60. package/dist/types/meetings/collection.d.ts +3 -2
  61. package/dist/types/meetings/index.d.ts +4 -3
  62. package/dist/types/meetings/meetings.types.d.ts +9 -0
  63. package/dist/types/metrics/constants.d.ts +1 -0
  64. package/dist/types/metrics/index.d.ts +15 -0
  65. package/dist/types/reachability/clusterReachability.d.ts +31 -3
  66. package/dist/types/reachability/index.d.ts +93 -2
  67. package/dist/types/statsAnalyzer/index.d.ts +15 -6
  68. package/dist/types/statsAnalyzer/mqaUtil.d.ts +17 -4
  69. package/dist/webinar/index.js +1 -1
  70. package/package.json +23 -23
  71. package/src/breakouts/index.ts +7 -1
  72. package/src/constants.ts +13 -0
  73. package/src/media/MediaConnectionAwaiter.ts +86 -11
  74. package/src/mediaQualityMetrics/config.ts +14 -3
  75. package/src/meeting/connectionStateHandler.ts +65 -0
  76. package/src/meeting/index.ts +166 -63
  77. package/src/meeting/locusMediaRequest.ts +5 -0
  78. package/src/meeting/util.ts +1 -0
  79. package/src/meeting-info/index.ts +9 -6
  80. package/src/meeting-info/meeting-info-v2.ts +4 -4
  81. package/src/meeting-info/util.ts +23 -28
  82. package/src/meeting-info/utilv2.ts +18 -24
  83. package/src/meetings/collection.ts +3 -3
  84. package/src/meetings/index.ts +39 -40
  85. package/src/meetings/meetings.types.ts +11 -0
  86. package/src/meetings/util.ts +5 -4
  87. package/src/metrics/constants.ts +1 -0
  88. package/src/metrics/index.ts +44 -0
  89. package/src/personal-meeting-room/index.ts +2 -2
  90. package/src/reachability/clusterReachability.ts +86 -25
  91. package/src/reachability/index.ts +316 -27
  92. package/src/statsAnalyzer/index.ts +85 -24
  93. package/src/statsAnalyzer/mqaUtil.ts +55 -7
  94. package/test/unit/spec/breakouts/index.ts +51 -32
  95. package/test/unit/spec/media/MediaConnectionAwaiter.ts +131 -32
  96. package/test/unit/spec/meeting/connectionStateHandler.ts +102 -0
  97. package/test/unit/spec/meeting/index.js +323 -56
  98. package/test/unit/spec/meeting/locusMediaRequest.ts +7 -0
  99. package/test/unit/spec/meeting-info/index.js +4 -4
  100. package/test/unit/spec/meeting-info/meetinginfov2.js +24 -28
  101. package/test/unit/spec/meeting-info/request.js +2 -2
  102. package/test/unit/spec/meeting-info/utilv2.js +41 -49
  103. package/test/unit/spec/meetings/index.js +14 -0
  104. package/test/unit/spec/metrics/index.js +126 -0
  105. package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -2
  106. package/test/unit/spec/reachability/clusterReachability.ts +116 -22
  107. package/test/unit/spec/reachability/index.ts +1153 -84
  108. package/test/unit/spec/stats-analyzer/index.js +647 -319
@@ -19,6 +19,8 @@ describe('MediaConnectionAwaiter', () => {
19
19
  off: sinon.stub(),
20
20
  getConnectionState: sinon.stub().returns(ConnectionState.New),
21
21
  getIceGatheringState: sinon.stub().returns('new'),
22
+ getIceConnectionState: sinon.stub().returns('new'),
23
+ getPeerConnectionState: sinon.stub().returns('new'),
22
24
  };
23
25
 
24
26
  mediaConnectionAwaiter = new MediaConnectionAwaiter({
@@ -52,8 +54,11 @@ describe('MediaConnectionAwaiter', () => {
52
54
  .then(() => {
53
55
  promiseResolved = true;
54
56
  })
55
- .catch(() => {
57
+ .catch((error) => {
56
58
  promiseRejected = true;
59
+
60
+ const {iceConnected} = error;
61
+ assert.equal(iceConnected, false);
57
62
  });
58
63
 
59
64
  await testUtils.flushPromises();
@@ -61,21 +66,109 @@ describe('MediaConnectionAwaiter', () => {
61
66
  assert.equal(promiseRejected, false);
62
67
 
63
68
  // 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];
69
+ assert.calledThrice(mockMC.on);
70
+ assert.equal(mockMC.on.getCall(0).args[0], Event.PEER_CONNECTION_STATE_CHANGED);
71
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_CONNECTION_STATE_CHANGED);
72
+ assert.equal(mockMC.on.getCall(2).args[0], Event.ICE_GATHERING_STATE_CHANGED);
73
+ const iceGatheringListener = mockMC.on.getCall(2).args[1];
74
+
75
+ mockMC.getIceGatheringState.returns('complete');
76
+ iceGatheringListener();
77
+
78
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
79
+ await testUtils.flushPromises();
80
+
81
+ assert.equal(promiseResolved, false);
82
+ assert.equal(promiseRejected, true);
83
+
84
+ assert.calledThrice(mockMC.off);
85
+ });
86
+
87
+ it('rejects immediately if ice state is FAILED', async () => {
88
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
89
+ mockMC.getIceGatheringState.returns('gathering');
90
+
91
+ let promiseResolved = false;
92
+ let promiseRejected = false;
93
+
94
+ mediaConnectionAwaiter
95
+ .waitForMediaConnectionConnected()
96
+ .then(() => {
97
+ promiseResolved = true;
98
+ })
99
+ .catch((error) => {
100
+ promiseRejected = true;
101
+
102
+ const {iceConnected} = error;
103
+ assert.equal(iceConnected, false);
104
+ });
105
+
106
+ await testUtils.flushPromises();
107
+ assert.equal(promiseResolved, false);
108
+ assert.equal(promiseRejected, false);
68
109
 
110
+ // check the right listener was registered
111
+ assert.calledThrice(mockMC.on);
112
+ assert.equal(mockMC.on.getCall(0).args[0], Event.PEER_CONNECTION_STATE_CHANGED);
113
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_CONNECTION_STATE_CHANGED);
114
+ assert.equal(mockMC.on.getCall(2).args[0], Event.ICE_GATHERING_STATE_CHANGED);
115
+ const iceConnectionListener = mockMC.on.getCall(1).args[1];
116
+
117
+ mockMC.getConnectionState.returns(ConnectionState.Failed);
118
+ iceConnectionListener();
119
+
120
+ await testUtils.flushPromises();
121
+
122
+ assert.equal(promiseResolved, false);
123
+ assert.equal(promiseRejected, true);
124
+
125
+ assert.calledThrice(mockMC.off);
126
+ });
127
+
128
+ it('rejects after timeout if dtls state is not connected', async () => {
129
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
130
+ mockMC.getIceGatheringState.returns('gathering');
131
+
132
+ let promiseResolved = false;
133
+ let promiseRejected = false;
134
+
135
+ mediaConnectionAwaiter
136
+ .waitForMediaConnectionConnected()
137
+ .then(() => {
138
+ promiseResolved = true;
139
+ })
140
+ .catch((error) => {
141
+ promiseRejected = true;
142
+
143
+ const {iceConnected} = error;
144
+ assert.equal(iceConnected, false);
145
+ });
146
+
147
+ await testUtils.flushPromises();
148
+ assert.equal(promiseResolved, false);
149
+ assert.equal(promiseRejected, false);
150
+
151
+ // check the right listener was registered
152
+ assert.calledThrice(mockMC.on);
153
+ assert.equal(mockMC.on.getCall(0).args[0], Event.PEER_CONNECTION_STATE_CHANGED);
154
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_CONNECTION_STATE_CHANGED);
155
+ assert.equal(mockMC.on.getCall(2).args[0], Event.ICE_GATHERING_STATE_CHANGED);
156
+ const listener = mockMC.on.getCall(1).args[1];
157
+ const iceConnectionListener = mockMC.on.getCall(1).args[1];
158
+
69
159
  mockMC.getIceGatheringState.returns('complete');
70
160
  listener();
71
161
 
162
+ mockMC.getIceConnectionState.returns('connected');
163
+ iceConnectionListener();
164
+
72
165
  await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
73
166
  await testUtils.flushPromises();
74
167
 
75
168
  assert.equal(promiseResolved, false);
76
169
  assert.equal(promiseRejected, true);
77
170
 
78
- assert.calledTwice(mockMC.off);
171
+ assert.calledThrice(mockMC.off);
79
172
  });
80
173
 
81
174
  it('resolves after timeout if connection state reach connected/completed', async () => {
@@ -99,9 +192,10 @@ describe('MediaConnectionAwaiter', () => {
99
192
  assert.equal(promiseRejected, false);
100
193
 
101
194
  // 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);
195
+ assert.calledThrice(mockMC.on);
196
+ assert.equal(mockMC.on.getCall(0).args[0], Event.PEER_CONNECTION_STATE_CHANGED);
197
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_CONNECTION_STATE_CHANGED);
198
+ assert.equal(mockMC.on.getCall(2).args[0], Event.ICE_GATHERING_STATE_CHANGED);
105
199
 
106
200
  mockMC.getConnectionState.returns(ConnectionState.Connected);
107
201
 
@@ -111,7 +205,7 @@ describe('MediaConnectionAwaiter', () => {
111
205
  assert.equal(promiseResolved, true);
112
206
  assert.equal(promiseRejected, false);
113
207
 
114
- assert.calledTwice(mockMC.off);
208
+ assert.calledThrice(mockMC.off);
115
209
  });
116
210
 
117
211
  it(`resolves when media connection reaches "connected" state`, async () => {
@@ -137,9 +231,10 @@ describe('MediaConnectionAwaiter', () => {
137
231
  assert.equal(promiseRejected, false);
138
232
 
139
233
  // 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);
234
+ assert.calledThrice(mockMC.on);
235
+ assert.equal(mockMC.on.getCall(0).args[0], Event.PEER_CONNECTION_STATE_CHANGED);
236
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_CONNECTION_STATE_CHANGED);
237
+ assert.equal(mockMC.on.getCall(2).args[0], Event.ICE_GATHERING_STATE_CHANGED);
143
238
  const listener = mockMC.on.getCall(0).args[1];
144
239
 
145
240
  // call the listener and pretend we are now connected
@@ -151,7 +246,7 @@ describe('MediaConnectionAwaiter', () => {
151
246
  assert.equal(promiseRejected, false);
152
247
 
153
248
  // check that listener was removed
154
- assert.calledTwice(mockMC.off);
249
+ assert.calledThrice(mockMC.off);
155
250
 
156
251
  assert.calledOnce(clearTimeoutSpy);
157
252
  });
@@ -179,9 +274,10 @@ describe('MediaConnectionAwaiter', () => {
179
274
  assert.equal(promiseRejected, false);
180
275
 
181
276
  // 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);
277
+ assert.calledThrice(mockMC.on);
278
+ assert.equal(mockMC.on.getCall(0).args[0], Event.PEER_CONNECTION_STATE_CHANGED);
279
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_CONNECTION_STATE_CHANGED);
280
+ assert.equal(mockMC.on.getCall(2).args[0], Event.ICE_GATHERING_STATE_CHANGED);
185
281
  const listener = mockMC.on.getCall(1).args[1];
186
282
 
187
283
  // call the listener and pretend we are now connected
@@ -197,7 +293,7 @@ describe('MediaConnectionAwaiter', () => {
197
293
  assert.equal(promiseRejected, false);
198
294
 
199
295
  // check that listener was removed
200
- assert.calledTwice(mockMC.off);
296
+ assert.calledThrice(mockMC.off);
201
297
 
202
298
  assert.neverCalledWith(clearTimeoutSpy);
203
299
  });
@@ -228,10 +324,11 @@ describe('MediaConnectionAwaiter', () => {
228
324
  assert.calledOnce(setTimeoutSpy);
229
325
 
230
326
  // 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];
327
+ assert.calledThrice(mockMC.on);
328
+ assert.equal(mockMC.on.getCall(0).args[0], Event.PEER_CONNECTION_STATE_CHANGED);
329
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_CONNECTION_STATE_CHANGED);
330
+ assert.equal(mockMC.on.getCall(2).args[0], Event.ICE_GATHERING_STATE_CHANGED);
331
+ const listener = mockMC.on.getCall(2).args[1];
235
332
 
236
333
  // call the listener and pretend we are now connected
237
334
  mockMC.getIceGatheringState.returns('complete');
@@ -249,7 +346,7 @@ describe('MediaConnectionAwaiter', () => {
249
346
  assert.equal(promiseRejected, false);
250
347
 
251
348
  // check that listener was removed
252
- assert.calledTwice(mockMC.off);
349
+ assert.calledThrice(mockMC.off);
253
350
  });
254
351
 
255
352
  it(`reject with restart timer once if gathering state is not complete`, async () => {
@@ -276,9 +373,10 @@ describe('MediaConnectionAwaiter', () => {
276
373
  assert.equal(promiseRejected, false);
277
374
 
278
375
  // 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);
376
+ assert.calledThrice(mockMC.on);
377
+ assert.equal(mockMC.on.getCall(0).args[0], Event.PEER_CONNECTION_STATE_CHANGED);
378
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_CONNECTION_STATE_CHANGED);
379
+ assert.equal(mockMC.on.getCall(2).args[0], Event.ICE_GATHERING_STATE_CHANGED);
282
380
 
283
381
  await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT * 2);
284
382
  await testUtils.flushPromises();
@@ -287,7 +385,7 @@ describe('MediaConnectionAwaiter', () => {
287
385
  assert.equal(promiseRejected, true);
288
386
 
289
387
  // check that listener was removed
290
- assert.calledTwice(mockMC.off);
388
+ assert.calledThrice(mockMC.off);
291
389
 
292
390
  assert.calledOnce(clearTimeoutSpy);
293
391
  assert.calledTwice(setTimeoutSpy);
@@ -317,11 +415,12 @@ describe('MediaConnectionAwaiter', () => {
317
415
  assert.equal(promiseRejected, false);
318
416
 
319
417
  // 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);
418
+ assert.calledThrice(mockMC.on);
419
+ assert.equal(mockMC.on.getCall(0).args[0], Event.PEER_CONNECTION_STATE_CHANGED);
420
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_CONNECTION_STATE_CHANGED);
421
+ assert.equal(mockMC.on.getCall(2).args[0], Event.ICE_GATHERING_STATE_CHANGED);
323
422
  const connectionStateListener = mockMC.on.getCall(0).args[1];
324
- const iceGatheringListener = mockMC.on.getCall(1).args[1];
423
+ const iceGatheringListener = mockMC.on.getCall(2).args[1];
325
424
 
326
425
  mockMC.getIceGatheringState.returns('complete');
327
426
  iceGatheringListener();
@@ -335,7 +434,7 @@ describe('MediaConnectionAwaiter', () => {
335
434
  assert.equal(promiseRejected, false);
336
435
 
337
436
  // check that listener was removed
338
- assert.calledTwice(mockMC.off);
437
+ assert.calledThrice(mockMC.off);
339
438
 
340
439
  assert.calledTwice(clearTimeoutSpy);
341
440
  assert.calledTwice(setTimeoutSpy);
@@ -0,0 +1,102 @@
1
+ import sinon from 'sinon';
2
+ import {assert} from '@webex/test-helper-chai';
3
+ import {
4
+ ConnectionStateHandler,
5
+ ConnectionStateEvent,
6
+ } from '@webex/plugin-meetings/src/meeting/connectionStateHandler';
7
+ import {Event, ConnectionState} from '@webex/internal-media-core';
8
+
9
+ describe('ConnectionStateHandler', () => {
10
+ let connectionStateHandler: ConnectionStateHandler;
11
+ let mockMC;
12
+
13
+ beforeEach(() => {
14
+ mockMC = {
15
+ on: sinon.stub(),
16
+ off: sinon.stub(),
17
+ getConnectionState: sinon.stub().returns(ConnectionState.Connecting),
18
+ };
19
+
20
+ connectionStateHandler = new ConnectionStateHandler(mockMC);
21
+ });
22
+
23
+ describe('ConnectionStateChangedEvent', () => {
24
+ it('should emit a stateChanged event when the peer connection state changes', () => {
25
+ const spy = sinon.spy(connectionStateHandler, 'emit');
26
+
27
+ // check the right listener was registered
28
+ assert.calledTwice(mockMC.on);
29
+ assert.equal(mockMC.on.getCall(0).args[0], Event.PEER_CONNECTION_STATE_CHANGED);
30
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_CONNECTION_STATE_CHANGED);
31
+ const listener = mockMC.on.getCall(0).args[1];
32
+
33
+ listener();
34
+
35
+ assert.calledOnce(spy);
36
+ assert.calledOnceWithExactly(
37
+ connectionStateHandler.emit,
38
+ {
39
+ file: 'connectionStateHandler',
40
+ function: 'handleConnectionStateChange',
41
+ },
42
+ ConnectionStateEvent.stateChanged,
43
+ {
44
+ state: ConnectionState.Connecting,
45
+ }
46
+ );
47
+ });
48
+
49
+ it('should emit a stateChanged event when the ice connection state changes', () => {
50
+ const spy = sinon.spy(connectionStateHandler, 'emit');
51
+
52
+ // check the right listener was registered
53
+ assert.calledTwice(mockMC.on);
54
+ assert.equal(mockMC.on.getCall(0).args[0], Event.PEER_CONNECTION_STATE_CHANGED);
55
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_CONNECTION_STATE_CHANGED);
56
+ const listener = mockMC.on.getCall(1).args[1];
57
+
58
+ listener();
59
+
60
+ assert.calledOnce(spy);
61
+ assert.calledOnceWithExactly(
62
+ connectionStateHandler.emit,
63
+ {
64
+ file: 'connectionStateHandler',
65
+ function: 'handleConnectionStateChange',
66
+ },
67
+ ConnectionStateEvent.stateChanged,
68
+ {
69
+ state: ConnectionState.Connecting,
70
+ }
71
+ );
72
+ });
73
+
74
+ it('should emit a stateChanged event only once when overall connection state does not change', () => {
75
+ const spy = sinon.spy(connectionStateHandler, 'emit');
76
+
77
+ // check the right listener was registered
78
+ assert.calledTwice(mockMC.on);
79
+ assert.equal(mockMC.on.getCall(0).args[0], Event.PEER_CONNECTION_STATE_CHANGED);
80
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_CONNECTION_STATE_CHANGED);
81
+ const peerConnectionListener = mockMC.on.getCall(0).args[1];
82
+ const iceConnectionListener = mockMC.on.getCall(1).args[1];
83
+
84
+ peerConnectionListener();
85
+
86
+ iceConnectionListener();
87
+
88
+ assert.calledOnce(spy);
89
+ assert.calledOnceWithExactly(
90
+ connectionStateHandler.emit,
91
+ {
92
+ file: 'connectionStateHandler',
93
+ function: 'handleConnectionStateChange',
94
+ },
95
+ ConnectionStateEvent.stateChanged,
96
+ {
97
+ state: ConnectionState.Connecting,
98
+ }
99
+ );
100
+ });
101
+ });
102
+ });