@webex/plugin-meetings 3.0.0-beta.281 → 3.0.0-beta.282

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.
@@ -4,7 +4,7 @@ import {ConnectionState, Event} from '@webex/internal-media-core';
4
4
  import MediaProperties from '@webex/plugin-meetings/src/media/properties';
5
5
  import MediaUtil from '@webex/plugin-meetings/src/media/util';
6
6
  import testUtils from '../../../utils/testUtils';
7
- import {PC_BAIL_TIMEOUT} from '@webex/plugin-meetings/src/constants';
7
+ import {ICE_AND_DTLS_CONNECTION_TIMEOUT} from '@webex/plugin-meetings/src/constants';
8
8
  import {Defer} from '@webex/common';
9
9
 
10
10
  describe('MediaProperties', () => {
@@ -52,7 +52,7 @@ describe('MediaProperties', () => {
52
52
  assert.equal(promiseResolved, false);
53
53
  assert.equal(promiseRejected, false);
54
54
 
55
- await clock.tickAsync(PC_BAIL_TIMEOUT);
55
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
56
56
  await testUtils.flushPromises();
57
57
 
58
58
  assert.equal(promiseResolved, false);
@@ -25,12 +25,14 @@ import {
25
25
  _MEETING_ID_,
26
26
  MEETING_REMOVED_REASON,
27
27
  LOCUSINFO,
28
- PC_BAIL_TIMEOUT,
28
+ ICE_AND_DTLS_CONNECTION_TIMEOUT,
29
29
  DISPLAY_HINTS,
30
30
  SELF_POLICY,
31
31
  IP_VERSION,
32
32
  ERROR_DICTIONARY,
33
33
  NETWORK_STATUS,
34
+ ONLINE,
35
+ OFFLINE,
34
36
  } from '@webex/plugin-meetings/src/constants';
35
37
  import * as InternalMediaCoreModule from '@webex/internal-media-core';
36
38
  import {
@@ -105,6 +107,7 @@ import {
105
107
  } from '@webex/internal-plugin-metrics/src/call-diagnostic/config';
106
108
  import CallDiagnosticMetrics from '@webex/internal-plugin-metrics/src/call-diagnostic/call-diagnostic-metrics';
107
109
  import { ERROR_DESCRIPTIONS } from '@webex/internal-plugin-metrics/src/call-diagnostic/config';
110
+ import MeetingCollection from '@webex/plugin-meetings/src/meetings/collection';
108
111
 
109
112
 
110
113
  describe('plugin-meetings', () => {
@@ -1151,6 +1154,7 @@ describe('plugin-meetings', () => {
1151
1154
  meeting.roap.doTurnDiscovery = sinon
1152
1155
  .stub()
1153
1156
  .resolves({turnServerInfo: {}, turnDiscoverySkippedReason: undefined});
1157
+ meeting.waitForRemoteSDPAnswer = sinon.stub().resolves();
1154
1158
  });
1155
1159
 
1156
1160
  it('should have #addMedia', () => {
@@ -1324,6 +1328,61 @@ describe('plugin-meetings', () => {
1324
1328
  assert.isNull(meeting.mediaProperties.webrtcMediaConnection);
1325
1329
  });
1326
1330
 
1331
+ it('should send metrics and reset the statsAnalyzer to null if waitForRemoteSDPAnswer fails', async () => {
1332
+ meeting.meetingState = 'ACTIVE';
1333
+ meeting.webex.meetings.reachability = {
1334
+ getReachabilityMetrics: sinon.stub().resolves({
1335
+ someReachabilityMetric1: 'some value1',
1336
+ someReachabilityMetric2: 'some value2',
1337
+ }),
1338
+ };
1339
+
1340
+ meeting.waitForRemoteSDPAnswer = sinon.stub().rejects();
1341
+
1342
+ // set a statsAnalyzer on the meeting so that we can check that it gets reset to null
1343
+ meeting.statsAnalyzer = {stopAnalyzer: sinon.stub().resolves()};
1344
+
1345
+ const error = await assert.isRejected(meeting.addMedia());
1346
+
1347
+ assert.isNull(meeting.statsAnalyzer);
1348
+ assert(webex.internal.newMetrics.submitInternalEvent.calledTwice);
1349
+ assert.calledWith(webex.internal.newMetrics.submitInternalEvent.firstCall, {
1350
+ name: 'internal.client.add-media.turn-discovery.start',
1351
+ });
1352
+ assert.calledWith(webex.internal.newMetrics.submitInternalEvent.secondCall, {
1353
+ name: 'internal.client.add-media.turn-discovery.end',
1354
+ });
1355
+ assert(Metrics.sendBehavioralMetric.calledTwice);
1356
+ assert.calledWith(
1357
+ Metrics.sendBehavioralMetric.firstCall,
1358
+ BEHAVIORAL_METRICS.TURN_DISCOVERY_LATENCY,
1359
+ {
1360
+ correlation_id: meeting.correlationId,
1361
+ turnServerUsed: true,
1362
+ latency: undefined,
1363
+ }
1364
+ );
1365
+ assert.calledWith(
1366
+ Metrics.sendBehavioralMetric.secondCall,
1367
+ BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE,
1368
+ {
1369
+ correlation_id: meeting.correlationId,
1370
+ locus_id: meeting.locusUrl.split('/').pop(),
1371
+ reason: error.message,
1372
+ stack: error.stack,
1373
+ code: error.code,
1374
+ turnDiscoverySkippedReason: undefined,
1375
+ turnServerUsed: true,
1376
+ isMultistream: false,
1377
+ signalingState: 'unknown',
1378
+ connectionState: 'unknown',
1379
+ iceConnectionState: 'unknown',
1380
+ someReachabilityMetric1: 'some value1',
1381
+ someReachabilityMetric2: 'some value2',
1382
+ }
1383
+ );
1384
+ });
1385
+
1327
1386
  it('should include the peer connection properties correctly for multistream', async () => {
1328
1387
  meeting.meetingState = 'ACTIVE';
1329
1388
  // setup the mock to return an incomplete object - this will cause addMedia to fail
@@ -1606,10 +1665,7 @@ describe('plugin-meetings', () => {
1606
1665
  mediaSettings: {},
1607
1666
  });
1608
1667
 
1609
- await clock.tickAsync(
1610
- 4000 /* meetingState timer, hardcoded inside addMedia */ +
1611
- PC_BAIL_TIMEOUT /* connection state timer */
1612
- );
1668
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
1613
1669
  await testUtils.flushPromises();
1614
1670
 
1615
1671
  assert.exists(media);
@@ -2030,6 +2086,7 @@ describe('plugin-meetings', () => {
2030
2086
  let locusMediaRequestStub; // stub for /media requests to Locus
2031
2087
 
2032
2088
  const roapOfferMessage = {messageType: 'OFFER', sdp: 'sdp', seq: '1', tieBreaker: '123'};
2089
+ const roapOKMessage = {messageType: 'OK', seq: '1'};
2033
2090
 
2034
2091
  let expectedMediaConnectionConfig;
2035
2092
  let expectedDebugId;
@@ -2037,7 +2094,7 @@ describe('plugin-meetings', () => {
2037
2094
  let clock;
2038
2095
 
2039
2096
  beforeEach(() => {
2040
- clock = sinon.useFakeTimers();
2097
+ clock = sinon.useFakeTimers();
2041
2098
 
2042
2099
  sinon.stub(MeetingUtil, 'getIpVersion').returns(IP_VERSION.unknown);
2043
2100
 
@@ -2055,6 +2112,10 @@ describe('plugin-meetings', () => {
2055
2112
  meeting.roap.doTurnDiscovery = sinon
2056
2113
  .stub()
2057
2114
  .resolves({turnServerInfo: {}, turnDiscoverySkippedReason: 'reachability'});
2115
+ meeting.deferSDPAnswer = new Defer();
2116
+ meeting.deferSDPAnswer.resolve();
2117
+ meeting.webex.meetings.meetingCollection = new MeetingCollection();
2118
+ meeting.webex.meetings.meetingCollection.set(meeting);
2058
2119
 
2059
2120
  StaticConfig.set({bandwidth: {audio: 1234, video: 5678, startBitrate: 9876}});
2060
2121
 
@@ -2164,12 +2225,21 @@ describe('plugin-meetings', () => {
2164
2225
 
2165
2226
  // simulates a Roap offer being generated by the RoapMediaConnection
2166
2227
  const simulateRoapOffer = async () => {
2228
+ meeting.deferSDPAnswer = {resolve: sinon.stub()};
2167
2229
  const roapListener = getRoapListener();
2168
2230
 
2169
2231
  await roapListener({roapMessage: roapOfferMessage});
2170
2232
  await stableState();
2171
2233
  };
2172
2234
 
2235
+ // simulates a Roap OK being sent
2236
+ const simulateRoapOk = async () => {
2237
+ const roapListener = getRoapListener();
2238
+
2239
+ await roapListener({roapMessage: roapOKMessage});
2240
+ await stableState();
2241
+ };
2242
+
2173
2243
  const checkSdpOfferSent = ({audioMuted, videoMuted}) => {
2174
2244
  const {sdp, seq, tieBreaker} = roapOfferMessage;
2175
2245
 
@@ -2199,6 +2269,35 @@ describe('plugin-meetings', () => {
2199
2269
  });
2200
2270
  };
2201
2271
 
2272
+ const checkOkSent = ({audioMuted, videoMuted}) => {
2273
+ const {seq} = roapOKMessage;
2274
+
2275
+ assert.calledWith(locusMediaRequestStub, {
2276
+ method: 'PUT',
2277
+ uri: `${meeting.selfUrl}/media`,
2278
+ body: {
2279
+ device: {
2280
+ url: meeting.deviceUrl,
2281
+ deviceType: meeting.config.deviceType,
2282
+ countryCode: 'UK',
2283
+ regionCode: 'EU'
2284
+ },
2285
+ correlationId: meeting.correlationId,
2286
+ clientMediaPreferences: {
2287
+ preferTranscoding: !meeting.isMultistream,
2288
+ ipver: undefined,
2289
+ joinCookie: undefined
2290
+ },
2291
+ localMedias: [
2292
+ {
2293
+ localSdp: `{"audioMuted":${audioMuted},"videoMuted":${videoMuted},"roapMessage":{"messageType":"OK","version":"2","seq":"${seq}"}}`,
2294
+ mediaId: 'fake media id'
2295
+ },
2296
+ ],
2297
+ },
2298
+ });
2299
+ };
2300
+
2202
2301
  const checkLocalMuteSentToLocus = ({audioMuted, videoMuted}) => {
2203
2302
  assert.calledWith(locusMediaRequestStub, {
2204
2303
  method: 'PUT',
@@ -2279,6 +2378,7 @@ describe('plugin-meetings', () => {
2279
2378
  it('addMedia() works correctly when media is enabled without tracks to publish', async () => {
2280
2379
  await meeting.addMedia();
2281
2380
  await simulateRoapOffer();
2381
+ await simulateRoapOk();
2282
2382
 
2283
2383
  // check RoapMediaConnection was created correctly
2284
2384
  checkMediaConnectionCreated({
@@ -2301,14 +2401,17 @@ describe('plugin-meetings', () => {
2301
2401
 
2302
2402
  // and SDP offer was sent with the right audioMuted/videoMuted values
2303
2403
  checkSdpOfferSent({audioMuted: true, videoMuted: true});
2404
+ // check OK was sent with the right audioMuted/videoMuted values
2405
+ checkOkSent({audioMuted: true, videoMuted: true});
2304
2406
 
2305
- // and that it was the only /media request that was sent
2306
- assert.calledOnce(locusMediaRequestStub);
2407
+ // and that these were the only /media requests that were sent
2408
+ assert.calledTwice(locusMediaRequestStub);
2307
2409
  });
2308
2410
 
2309
2411
  it('addMedia() works correctly when media is enabled with streams to publish', async () => {
2310
2412
  await meeting.addMedia({localStreams: {microphone: fakeMicrophoneStream}});
2311
2413
  await simulateRoapOffer();
2414
+ await simulateRoapOk();
2312
2415
 
2313
2416
  // check RoapMediaConnection was created correctly
2314
2417
  checkMediaConnectionCreated({
@@ -2331,9 +2434,11 @@ describe('plugin-meetings', () => {
2331
2434
 
2332
2435
  // and SDP offer was sent with the right audioMuted/videoMuted values
2333
2436
  checkSdpOfferSent({audioMuted: false, videoMuted: true});
2437
+ // check OK was sent with the right audioMuted/videoMuted values
2438
+ checkOkSent({audioMuted: false, videoMuted: true});
2334
2439
 
2335
- // and no other local mute requests were sent to Locus
2336
- assert.calledOnce(locusMediaRequestStub);
2440
+ // and that these were the only /media requests that were sent
2441
+ assert.calledTwice(locusMediaRequestStub);
2337
2442
  });
2338
2443
 
2339
2444
  it('addMedia() works correctly when media is enabled with tracks to publish and track is muted', async () => {
@@ -2341,6 +2446,7 @@ describe('plugin-meetings', () => {
2341
2446
 
2342
2447
  await meeting.addMedia({localStreams: {microphone: fakeMicrophoneStream}});
2343
2448
  await simulateRoapOffer();
2449
+ await simulateRoapOk();
2344
2450
 
2345
2451
  // check RoapMediaConnection was created correctly
2346
2452
  checkMediaConnectionCreated({
@@ -2362,14 +2468,17 @@ describe('plugin-meetings', () => {
2362
2468
  });
2363
2469
  // and SDP offer was sent with the right audioMuted/videoMuted values
2364
2470
  checkSdpOfferSent({audioMuted: true, videoMuted: true});
2471
+ // check OK was sent with the right audioMuted/videoMuted values
2472
+ checkOkSent({audioMuted: true, videoMuted: true});
2365
2473
 
2366
- // and no other local mute requests were sent to Locus
2367
- assert.calledOnce(locusMediaRequestStub);
2474
+ // and that these were the only /media requests that were sent
2475
+ assert.calledTwice(locusMediaRequestStub);
2368
2476
  });
2369
2477
 
2370
2478
  it('addMedia() works correctly when media is disabled with tracks to publish', async () => {
2371
2479
  await meeting.addMedia({localStreams: {microphone: fakeMicrophoneStream}, audioEnabled: false});
2372
2480
  await simulateRoapOffer();
2481
+ await simulateRoapOk();
2373
2482
 
2374
2483
  // check RoapMediaConnection was created correctly
2375
2484
  checkMediaConnectionCreated({
@@ -2392,14 +2501,17 @@ describe('plugin-meetings', () => {
2392
2501
 
2393
2502
  // and SDP offer was sent with the right audioMuted/videoMuted values
2394
2503
  checkSdpOfferSent({audioMuted: true, videoMuted: true});
2504
+ // check OK was sent with the right audioMuted/videoMuted values
2505
+ checkOkSent({audioMuted: true, videoMuted: true});
2395
2506
 
2396
- // and no other local mute requests were sent to Locus
2397
- assert.calledOnce(locusMediaRequestStub);
2507
+ // and that these were the only /media requests that were sent
2508
+ assert.calledTwice(locusMediaRequestStub);
2398
2509
  });
2399
2510
 
2400
2511
  it('addMedia() works correctly when media is disabled with no tracks to publish', async () => {
2401
2512
  await meeting.addMedia({audioEnabled: false});
2402
2513
  await simulateRoapOffer();
2514
+ await simulateRoapOk();
2403
2515
 
2404
2516
  // check RoapMediaConnection was created correctly
2405
2517
  checkMediaConnectionCreated({
@@ -2422,15 +2534,18 @@ describe('plugin-meetings', () => {
2422
2534
 
2423
2535
  // and SDP offer was sent with the right audioMuted/videoMuted values
2424
2536
  checkSdpOfferSent({audioMuted: true, videoMuted: true});
2537
+ // check OK was sent with the right audioMuted/videoMuted values
2538
+ checkOkSent({audioMuted: true, videoMuted: true});
2425
2539
 
2426
- // and no other local mute requests were sent to Locus
2427
- assert.calledOnce(locusMediaRequestStub);
2540
+ // and that these were the only /media requests that were sent
2541
+ assert.calledTwice(locusMediaRequestStub);
2428
2542
  });
2429
2543
 
2430
2544
 
2431
2545
  it('addMedia() works correctly when video is disabled with no tracks to publish', async () => {
2432
2546
  await meeting.addMedia({videoEnabled: false});
2433
2547
  await simulateRoapOffer();
2548
+ await simulateRoapOk();
2434
2549
 
2435
2550
  // check RoapMediaConnection was created correctly
2436
2551
  checkMediaConnectionCreated({
@@ -2453,14 +2568,18 @@ describe('plugin-meetings', () => {
2453
2568
 
2454
2569
  // and SDP offer was sent with the right audioMuted/videoMuted values
2455
2570
  checkSdpOfferSent({audioMuted: true, videoMuted: true});
2571
+ // check OK was sent with the right audioMuted/videoMuted values
2572
+ checkOkSent({audioMuted: true, videoMuted: true});
2456
2573
 
2457
- // and no other local mute requests were sent to Locus
2458
- assert.calledOnce(locusMediaRequestStub);
2574
+ // and that these were the only /media requests that were sent
2575
+ assert.calledTwice(locusMediaRequestStub);
2459
2576
  });
2460
2577
 
2461
2578
  it('addMedia() works correctly when screen share is disabled with no tracks to publish', async () => {
2462
2579
  await meeting.addMedia({shareAudioEnabled: false, shareVideoEnabled: false});
2463
2580
  await simulateRoapOffer();
2581
+ await simulateRoapOk();
2582
+
2464
2583
 
2465
2584
  // check RoapMediaConnection was created correctly
2466
2585
  checkMediaConnectionCreated({
@@ -2483,9 +2602,11 @@ describe('plugin-meetings', () => {
2483
2602
 
2484
2603
  // and SDP offer was sent with the right audioMuted/videoMuted values
2485
2604
  checkSdpOfferSent({audioMuted: true, videoMuted: true});
2605
+ // check OK was sent with the right audioMuted/videoMuted values
2606
+ checkOkSent({audioMuted: true, videoMuted: true});
2486
2607
 
2487
- // and no other local mute requests were sent to Locus
2488
- assert.calledOnce(locusMediaRequestStub);
2608
+ // and that these were the only /media requests that were sent
2609
+ assert.calledTwice(locusMediaRequestStub);
2489
2610
  });
2490
2611
 
2491
2612
  describe('publishStreams()/unpublishStreams() calls', () => {
@@ -2497,6 +2618,7 @@ describe('plugin-meetings', () => {
2497
2618
  it(`first publishStreams() call while media is ${mediaEnabled ? 'enabled' : 'disabled'}`, async () => {
2498
2619
  await meeting.addMedia({audioEnabled: mediaEnabled});
2499
2620
  await simulateRoapOffer();
2621
+ await simulateRoapOk();
2500
2622
 
2501
2623
  resetHistory();
2502
2624
 
@@ -2532,6 +2654,7 @@ describe('plugin-meetings', () => {
2532
2654
  it(`second publishStreams() call while media is ${mediaEnabled ? 'enabled' : 'disabled'}`, async () => {
2533
2655
  await meeting.addMedia({audioEnabled: mediaEnabled});
2534
2656
  await simulateRoapOffer();
2657
+ await simulateRoapOk();
2535
2658
  await meeting.publishStreams({microphone: fakeMicrophoneStream});
2536
2659
  await stableState();
2537
2660
 
@@ -2573,6 +2696,7 @@ describe('plugin-meetings', () => {
2573
2696
  it(`unpublishStreams() call while media is ${mediaEnabled ? 'enabled' : 'disabled'}`, async () => {
2574
2697
  await meeting.addMedia({audioEnabled: mediaEnabled});
2575
2698
  await simulateRoapOffer();
2699
+ await simulateRoapOk();
2576
2700
  await meeting.publishStreams({microphone: fakeMicrophoneStream});
2577
2701
  await stableState();
2578
2702
 
@@ -2616,6 +2740,7 @@ describe('plugin-meetings', () => {
2616
2740
  const addMedia = async (enableMedia, stream) => {
2617
2741
  await meeting.addMedia({audioEnabled: enableMedia, localStreams: {microphone: stream}});
2618
2742
  await simulateRoapOffer();
2743
+ await simulateRoapOk();
2619
2744
 
2620
2745
  resetHistory();
2621
2746
  }
@@ -2650,8 +2775,14 @@ describe('plugin-meetings', () => {
2650
2775
  // check SDP offer was sent with the right audioMuted/videoMuted values
2651
2776
  checkSdpOfferSent({audioMuted: true, videoMuted: true});
2652
2777
 
2778
+ // simulate OK being sent in response to remote answer being received
2779
+ await simulateRoapOk();
2780
+
2781
+ // check OK was sent with the right audioMuted/videoMuted values
2782
+ checkOkSent({audioMuted: true, videoMuted: true});
2783
+
2653
2784
  // and no other local mute requests were sent to Locus
2654
- assert.calledOnce(locusMediaRequestStub);
2785
+ assert.calledTwice(locusMediaRequestStub);
2655
2786
  });
2656
2787
 
2657
2788
  it('updateMedia() enables media when nothing is published', async () => {
@@ -2668,8 +2799,14 @@ describe('plugin-meetings', () => {
2668
2799
  // check SDP offer was sent with the right audioMuted/videoMuted values
2669
2800
  checkSdpOfferSent({audioMuted: true, videoMuted: true});
2670
2801
 
2802
+ // simulate OK being sent in response to remote answer being received
2803
+ await simulateRoapOk();
2804
+
2805
+ // check OK was sent with the right audioMuted/videoMuted values
2806
+ checkOkSent({audioMuted: true, videoMuted: true});
2807
+
2671
2808
  // and no other local mute requests were sent to Locus
2672
- assert.calledOnce(locusMediaRequestStub);
2809
+ assert.calledTwice(locusMediaRequestStub);
2673
2810
  });
2674
2811
 
2675
2812
  it('updateMedia() disables media when stream is published', async () => {
@@ -2691,8 +2828,14 @@ describe('plugin-meetings', () => {
2691
2828
  // check SDP offer was sent with the right audioMuted/videoMuted values
2692
2829
  checkSdpOfferSent({audioMuted: true, videoMuted: true});
2693
2830
 
2831
+ // simulate OK being sent in response to remote answer being received
2832
+ await simulateRoapOk();
2833
+
2834
+ // check OK was sent with the right audioMuted/videoMuted values
2835
+ checkOkSent({audioMuted: true, videoMuted: true});
2836
+
2694
2837
  // and no other local mute requests were sent to Locus
2695
- assert.calledOnce(locusMediaRequestStub);
2838
+ assert.calledTwice(locusMediaRequestStub);
2696
2839
  });
2697
2840
 
2698
2841
  it('updateMedia() enables media when stream is published', async () => {
@@ -2714,8 +2857,14 @@ describe('plugin-meetings', () => {
2714
2857
  // check SDP offer was sent with the right audioMuted/videoMuted values
2715
2858
  checkSdpOfferSent({audioMuted: false, videoMuted: true});
2716
2859
 
2860
+ // simulate OK being sent in response to remote answer being received
2861
+ await simulateRoapOk();
2862
+
2863
+ // check OK was sent with the right audioMuted/videoMuted values
2864
+ checkOkSent({audioMuted: false, videoMuted: true});
2865
+
2717
2866
  // and no other local mute requests were sent to Locus
2718
- assert.calledOnce(locusMediaRequestStub);
2867
+ assert.calledTwice(locusMediaRequestStub);
2719
2868
  });
2720
2869
  });
2721
2870
 
@@ -2743,14 +2892,17 @@ describe('plugin-meetings', () => {
2743
2892
  assert.notCalled(locusMediaRequestStub);
2744
2893
  assert.notCalled(fakeRoapMediaConnection.update);
2745
2894
 
2746
- // now simulate roap offer
2895
+ // now simulate roap offer and ok
2747
2896
  await simulateRoapOffer();
2897
+ await simulateRoapOk();
2748
2898
 
2749
2899
  // it should be sent with the right mute status
2750
2900
  checkSdpOfferSent({audioMuted: mute, videoMuted: true});
2901
+ // check OK was sent with the right audioMuted/videoMuted values
2902
+ checkOkSent({audioMuted: mute, videoMuted: true});
2751
2903
 
2752
2904
  // nothing else should happen
2753
- assert.calledOnce(locusMediaRequestStub);
2905
+ assert.calledTwice(locusMediaRequestStub);
2754
2906
  assert.notCalled(fakeRoapMediaConnection.update);
2755
2907
  })
2756
2908
  );
@@ -5345,6 +5497,13 @@ describe('plugin-meetings', () => {
5345
5497
  });
5346
5498
 
5347
5499
  it('handles OK message correctly', () => {
5500
+ const clock = sinon.useFakeTimers();
5501
+ sinon.spy(clock, "clearTimeout");
5502
+ meeting.deferSDPAnswer = {
5503
+ resolve: sinon.stub(),
5504
+ };
5505
+ meeting.sdpResponseTimer = '1234';
5506
+
5348
5507
  eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
5349
5508
  roapMessage: {messageType: 'OK', seq: 1},
5350
5509
  });
@@ -5372,9 +5531,16 @@ describe('plugin-meetings', () => {
5372
5531
  latency: undefined,
5373
5532
  }
5374
5533
  );
5534
+
5535
+ assert.calledOnce(meeting.deferSDPAnswer.resolve)
5536
+ assert.calledOnce(clock.clearTimeout)
5537
+ assert.calledWith(clock.clearTimeout, '1234')
5538
+ assert.equal(meeting.sdpResponseTimer, undefined)
5375
5539
  });
5376
5540
 
5377
5541
  it('handles OFFER message correctly', () => {
5542
+ assert.equal(meeting.deferSDPAnswer, undefined);
5543
+
5378
5544
  eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
5379
5545
  roapMessage: {
5380
5546
  messageType: 'OFFER',
@@ -5398,6 +5564,8 @@ describe('plugin-meetings', () => {
5398
5564
  meeting,
5399
5565
  reconnect: false,
5400
5566
  });
5567
+
5568
+ assert.notEqual(meeting.deferSDPAnswer, undefined);
5401
5569
  });
5402
5570
 
5403
5571
  it('handles ANSWER message correctly', () => {
@@ -6351,6 +6519,18 @@ describe('plugin-meetings', () => {
6351
6519
  meeting.webex.internal.mercury.off = sinon.stub().returns(true);
6352
6520
  meeting.unsetPeerConnections();
6353
6521
  assert.calledOnce(meeting.mediaProperties.unsetPeerConnection);
6522
+ assert.notCalled(meeting.webex.internal.mercury.off);
6523
+ });
6524
+
6525
+ it('should unset the peer connections and turn off mercury listeners if config.reconnection.detection is true', () => {
6526
+ meeting.config.reconnection.detection = true;
6527
+ meeting.mediaProperties.unsetPeerConnection = sinon.stub().returns(true);
6528
+ meeting.webex.internal.mercury.off = sinon.stub().returns(true);
6529
+ meeting.unsetPeerConnections();
6530
+ assert.calledOnce(meeting.mediaProperties.unsetPeerConnection);
6531
+ assert.calledTwice(meeting.webex.internal.mercury.off);
6532
+ assert.calledWith(meeting.webex.internal.mercury.off.firstCall, ONLINE);
6533
+ assert.calledWith(meeting.webex.internal.mercury.off.secondCall, OFFLINE);
6354
6534
  });
6355
6535
  });
6356
6536