@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.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/media/MediaConnectionAwaiter.js +50 -13
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/meeting/connectionStateHandler.js +67 -0
- package/dist/meeting/connectionStateHandler.js.map +1 -0
- package/dist/meeting/index.js +46 -33
- package/dist/meeting/index.js.map +1 -1
- package/dist/types/media/MediaConnectionAwaiter.d.ts +18 -4
- package/dist/types/meeting/connectionStateHandler.d.ts +30 -0
- package/dist/types/meeting/index.d.ts +1 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/media/MediaConnectionAwaiter.ts +66 -11
- package/src/meeting/connectionStateHandler.ts +65 -0
- package/src/meeting/index.ts +19 -7
- package/test/unit/spec/media/MediaConnectionAwaiter.ts +90 -32
- package/test/unit/spec/meeting/connectionStateHandler.ts +102 -0
- package/test/unit/spec/meeting/index.js +30 -35
|
@@ -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(
|
|
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
|
-
|
|
2243
|
+
iceConnected: false,
|
|
2244
2244
|
turnServerUsed: false,
|
|
2245
2245
|
});
|
|
2246
2246
|
assert.calledWith(generateClientErrorCodeForIceFailureStub, {
|
|
2247
2247
|
signalingState: 'unknown',
|
|
2248
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
7143
|
-
|
|
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
|
-
|
|
7153
|
-
|
|
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
|
-
|
|
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
|
-
|
|
7246
|
-
|
|
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
|
-
|
|
7259
|
-
|
|
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
|
-
|
|
7286
|
-
|
|
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
|
-
|
|
7352
|
-
|
|
7353
|
-
});
|
|
7347
|
+
|
|
7348
|
+
simulateConnectionStateChange(ConnectionState.Failed);
|
|
7354
7349
|
};
|
|
7355
7350
|
|
|
7356
7351
|
const checkBehavioralMetricSent = (hasMediaConnectionConnectedAtLeastOnce = false) => {
|