@webex/plugin-meetings 3.3.1-next.16 → 3.3.1-next.17

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.
@@ -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
+ });
@@ -2216,7 +2216,7 @@ describe('plugin-meetings', () => {
2216
2216
  turnDiscoverySkippedReason: undefined,
2217
2217
  });
2218
2218
  meeting.meetingState = 'ACTIVE';
2219
- meeting.mediaProperties.waitForMediaConnectionConnected.rejects(new Error('fake error'));
2219
+ meeting.mediaProperties.waitForMediaConnectionConnected.rejects({iceConnected: false});
2220
2220
 
2221
2221
  const forceRtcMetricsSend = sinon.stub().resolves();
2222
2222
  const closeMediaConnectionStub = sinon.stub();
@@ -2240,12 +2240,12 @@ describe('plugin-meetings', () => {
2240
2240
  assert.calledTwice(generateClientErrorCodeForIceFailureStub);
2241
2241
  assert.calledWith(generateClientErrorCodeForIceFailureStub, {
2242
2242
  signalingState: 'unknown',
2243
- iceConnectionState: 'unknown',
2243
+ iceConnected: false,
2244
2244
  turnServerUsed: false,
2245
2245
  });
2246
2246
  assert.calledWith(generateClientErrorCodeForIceFailureStub, {
2247
2247
  signalingState: 'unknown',
2248
- iceConnectionState: 'unknown',
2248
+ iceConnected: false,
2249
2249
  turnServerUsed: true,
2250
2250
  });
2251
2251
 
@@ -2440,7 +2440,7 @@ describe('plugin-meetings', () => {
2440
2440
  assert.calledOnce(generateClientErrorCodeForIceFailureStub);
2441
2441
  assert.calledWith(generateClientErrorCodeForIceFailureStub, {
2442
2442
  signalingState: 'unknown',
2443
- iceConnectionState: 'unknown',
2443
+ iceConnected: undefined,
2444
2444
  turnServerUsed: false,
2445
2445
  });
2446
2446
 
@@ -2715,7 +2715,7 @@ describe('plugin-meetings', () => {
2715
2715
  turnDiscoverySkippedReason: undefined,
2716
2716
  });
2717
2717
  meeting.meetingState = 'ACTIVE';
2718
- meeting.mediaProperties.waitForMediaConnectionConnected.rejects(new Error('fake error'));
2718
+ meeting.mediaProperties.waitForMediaConnectionConnected.rejects({iceConnected: false});
2719
2719
 
2720
2720
  const forceRtcMetricsSend = sinon.stub().resolves();
2721
2721
  const closeMediaConnectionStub = sinon.stub();
@@ -3058,7 +3058,7 @@ describe('plugin-meetings', () => {
3058
3058
 
3059
3059
  meeting.meetingState = 'ACTIVE';
3060
3060
  meeting.mediaProperties.waitForMediaConnectionConnected.rejects(
3061
- new Error('fake error')
3061
+ {iceConnected: false}
3062
3062
  );
3063
3063
 
3064
3064
  let errorThrown = false;
@@ -3073,7 +3073,7 @@ describe('plugin-meetings', () => {
3073
3073
 
3074
3074
  assert.calledOnceWithExactly(generateClientErrorCodeForIceFailureStub, {
3075
3075
  signalingState: 'unknown',
3076
- iceConnectionState: 'unknown',
3076
+ iceConnected: false,
3077
3077
  turnServerUsed: true,
3078
3078
  });
3079
3079
 
@@ -7079,6 +7079,10 @@ describe('plugin-meetings', () => {
7079
7079
  id: 'stream',
7080
7080
  getTracks: () => [{id: 'track', addEventListener: sinon.stub()}],
7081
7081
  };
7082
+ const simulateConnectionStateChange = (newState) => {
7083
+ meeting.mediaProperties.webrtcMediaConnection.getConnectionState = sinon.stub().returns(newState);
7084
+ eventListeners[Event.PEER_CONNECTION_STATE_CHANGED]();
7085
+ }
7082
7086
 
7083
7087
  beforeEach(() => {
7084
7088
  eventListeners = {};
@@ -7088,6 +7092,7 @@ describe('plugin-meetings', () => {
7088
7092
  on: sinon.stub().callsFake((event, listener) => {
7089
7093
  eventListeners[event] = listener;
7090
7094
  }),
7095
+ getConnectionState: sinon.stub().returns(ConnectionState.New),
7091
7096
  };
7092
7097
  MediaUtil.createMediaStream.returns(fakeStream);
7093
7098
  });
@@ -7099,7 +7104,8 @@ describe('plugin-meetings', () => {
7099
7104
  assert.isFunction(eventListeners[Event.ROAP_FAILURE]);
7100
7105
  assert.isFunction(eventListeners[Event.ROAP_MESSAGE_TO_SEND]);
7101
7106
  assert.isFunction(eventListeners[Event.REMOTE_TRACK_ADDED]);
7102
- assert.isFunction(eventListeners[Event.CONNECTION_STATE_CHANGED]);
7107
+ assert.isFunction(eventListeners[Event.PEER_CONNECTION_STATE_CHANGED]);
7108
+ assert.isFunction(eventListeners[Event.ICE_CONNECTION_STATE_CHANGED]);
7103
7109
  });
7104
7110
 
7105
7111
  it('should trigger a media:ready event when REMOTE_TRACK_ADDED is fired', () => {
@@ -7139,9 +7145,8 @@ describe('plugin-meetings', () => {
7139
7145
  it('sends client.ice.start correctly when hasMediaConnectionConnectedAtLeastOnce = true', () => {
7140
7146
  meeting.hasMediaConnectionConnectedAtLeastOnce = true;
7141
7147
  meeting.setupMediaConnectionListeners();
7142
- eventListeners[Event.CONNECTION_STATE_CHANGED]({
7143
- state: 'Connecting',
7144
- });
7148
+
7149
+ simulateConnectionStateChange(ConnectionState.Connecting);
7145
7150
 
7146
7151
  assert.notCalled(webex.internal.newMetrics.submitClientEvent);
7147
7152
  });
@@ -7149,9 +7154,8 @@ describe('plugin-meetings', () => {
7149
7154
  it('sends client.ice.start correctly when hasMediaConnectionConnectedAtLeastOnce = false', () => {
7150
7155
  meeting.hasMediaConnectionConnectedAtLeastOnce = false;
7151
7156
  meeting.setupMediaConnectionListeners();
7152
- eventListeners[Event.CONNECTION_STATE_CHANGED]({
7153
- state: 'Connecting',
7154
- });
7157
+
7158
+ simulateConnectionStateChange(ConnectionState.Connecting);
7155
7159
 
7156
7160
  assert.calledOnce(webex.internal.newMetrics.submitClientEvent);
7157
7161
  assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
@@ -7177,6 +7181,7 @@ describe('plugin-meetings', () => {
7177
7181
  on: sinon.stub().callsFake((event, listener) => {
7178
7182
  eventListeners[event] = listener;
7179
7183
  }),
7184
+ getConnectionState: sinon.stub().returns(ConnectionState.Connected),
7180
7185
  };
7181
7186
  };
7182
7187
 
@@ -7230,9 +7235,7 @@ describe('plugin-meetings', () => {
7230
7235
  assert.equal(meeting.hasMediaConnectionConnectedAtLeastOnce, false);
7231
7236
 
7232
7237
  // simulate first connection success
7233
- eventListeners[Event.CONNECTION_STATE_CHANGED]({
7234
- state: 'Connected',
7235
- });
7238
+ simulateConnectionStateChange(ConnectionState.Connected);
7236
7239
  checkExpectedSpies({
7237
7240
  icePhase: 'JOIN_MEETING_FINAL',
7238
7241
  setNetworkStatusCallParams: [NETWORK_STATUS.CONNECTED],
@@ -7242,12 +7245,9 @@ describe('plugin-meetings', () => {
7242
7245
  // now simulate short connection loss, client.ice.end is not sent a second time as hasMediaConnectionConnectedAtLeastOnce = true
7243
7246
  resetSpies();
7244
7247
 
7245
- eventListeners[Event.CONNECTION_STATE_CHANGED]({
7246
- state: 'Disconnected',
7247
- });
7248
- eventListeners[Event.CONNECTION_STATE_CHANGED]({
7249
- state: 'Connected',
7250
- });
7248
+ simulateConnectionStateChange(ConnectionState.Disconnected);
7249
+
7250
+ simulateConnectionStateChange(ConnectionState.Connected);
7251
7251
 
7252
7252
  checkExpectedSpies({
7253
7253
  setNetworkStatusCallParams: [NETWORK_STATUS.DISCONNECTED, NETWORK_STATUS.CONNECTED],
@@ -7255,12 +7255,9 @@ describe('plugin-meetings', () => {
7255
7255
 
7256
7256
  resetSpies();
7257
7257
 
7258
- eventListeners[Event.CONNECTION_STATE_CHANGED]({
7259
- state: 'Disconnected',
7260
- });
7261
- eventListeners[Event.CONNECTION_STATE_CHANGED]({
7262
- state: 'Connected',
7263
- });
7258
+ simulateConnectionStateChange(ConnectionState.Disconnected);
7259
+
7260
+ simulateConnectionStateChange(ConnectionState.Connected);
7264
7261
  });
7265
7262
  });
7266
7263
 
@@ -7282,9 +7279,8 @@ describe('plugin-meetings', () => {
7282
7279
 
7283
7280
  const mockDisconnectedEvent = () => {
7284
7281
  meeting.setupMediaConnectionListeners();
7285
- eventListeners[Event.CONNECTION_STATE_CHANGED]({
7286
- state: 'Disconnected',
7287
- });
7282
+
7283
+ simulateConnectionStateChange(ConnectionState.Disconnected);
7288
7284
  };
7289
7285
 
7290
7286
  const checkBehavioralMetricSent = (hasMediaConnectionConnectedAtLeastOnce = false) => {
@@ -7348,9 +7344,8 @@ describe('plugin-meetings', () => {
7348
7344
  describe('CONNECTION_STATE_CHANGED event when state = "Failed"', () => {
7349
7345
  const mockFailedEvent = () => {
7350
7346
  meeting.setupMediaConnectionListeners();
7351
- eventListeners[Event.CONNECTION_STATE_CHANGED]({
7352
- state: 'Failed',
7353
- });
7347
+
7348
+ simulateConnectionStateChange(ConnectionState.Failed);
7354
7349
  };
7355
7350
 
7356
7351
  const checkBehavioralMetricSent = (hasMediaConnectionConnectedAtLeastOnce = false) => {