@webex/plugin-meetings 3.6.0-next.16 → 3.6.0-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/meeting/index.js +167 -130
- package/dist/meeting/index.js.map +1 -1
- package/dist/types/meeting/index.d.ts +1 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +3 -3
- package/src/meeting/index.ts +19 -0
- package/test/unit/spec/meeting/index.js +51 -18
|
@@ -1400,6 +1400,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1400
1400
|
* @returns {Promise<void>}
|
|
1401
1401
|
*/
|
|
1402
1402
|
private cleanUpBeforeRetryWithTurnServer;
|
|
1403
|
+
private cleanUpBeforeReconnection;
|
|
1403
1404
|
/**
|
|
1404
1405
|
* Creates an instance of LocusMediaRequest for this meeting - it is needed for doing any calls
|
|
1405
1406
|
* to Locus /media API (these are used for sending Roap messages and updating audio/video mute status).
|
package/dist/webinar/index.js
CHANGED
package/package.json
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@webex/eslint-config-legacy": "0.0.0",
|
|
44
44
|
"@webex/jest-config-legacy": "0.0.0",
|
|
45
45
|
"@webex/legacy-tools": "0.0.0",
|
|
46
|
-
"@webex/plugin-meetings": "3.6.0-next.
|
|
46
|
+
"@webex/plugin-meetings": "3.6.0-next.17",
|
|
47
47
|
"@webex/plugin-rooms": "3.6.0-next.8",
|
|
48
48
|
"@webex/test-helper-chai": "3.6.0-next.4",
|
|
49
49
|
"@webex/test-helper-mocha": "3.6.0-next.4",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"@webex/internal-plugin-metrics": "3.6.0-next.4",
|
|
71
71
|
"@webex/internal-plugin-support": "3.6.0-next.8",
|
|
72
72
|
"@webex/internal-plugin-user": "3.6.0-next.4",
|
|
73
|
-
"@webex/internal-plugin-voicea": "3.6.0-next.
|
|
73
|
+
"@webex/internal-plugin-voicea": "3.6.0-next.17",
|
|
74
74
|
"@webex/media-helpers": "3.6.0-next.4",
|
|
75
75
|
"@webex/plugin-people": "3.6.0-next.6",
|
|
76
76
|
"@webex/plugin-rooms": "3.6.0-next.8",
|
|
@@ -91,5 +91,5 @@
|
|
|
91
91
|
"//": [
|
|
92
92
|
"TODO: upgrade jwt-decode when moving to node 18"
|
|
93
93
|
],
|
|
94
|
-
"version": "3.6.0-next.
|
|
94
|
+
"version": "3.6.0-next.17"
|
|
95
95
|
}
|
package/src/meeting/index.ts
CHANGED
|
@@ -4904,6 +4904,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4904
4904
|
);
|
|
4905
4905
|
}
|
|
4906
4906
|
|
|
4907
|
+
this.cleanUpBeforeReconnection();
|
|
4908
|
+
|
|
4907
4909
|
return this.reconnectionManager
|
|
4908
4910
|
.reconnect(options, async () => {
|
|
4909
4911
|
await this.waitForRemoteSDPAnswer();
|
|
@@ -7032,6 +7034,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7032
7034
|
}
|
|
7033
7035
|
}
|
|
7034
7036
|
|
|
7037
|
+
private async cleanUpBeforeReconnection(): Promise<void> {
|
|
7038
|
+
try {
|
|
7039
|
+
// when media fails, we want to upload a webrtc dump to see whats going on
|
|
7040
|
+
// this function is async, but returns once the stats have been gathered
|
|
7041
|
+
await this.forceSendStatsReport({callFrom: 'cleanUpBeforeReconnection'});
|
|
7042
|
+
|
|
7043
|
+
if (this.statsAnalyzer) {
|
|
7044
|
+
await this.statsAnalyzer.stopAnalyzer();
|
|
7045
|
+
}
|
|
7046
|
+
} catch (error) {
|
|
7047
|
+
LoggerProxy.logger.error(
|
|
7048
|
+
'Meeting:index#cleanUpBeforeReconnection --> Error during cleanup: ',
|
|
7049
|
+
error
|
|
7050
|
+
);
|
|
7051
|
+
}
|
|
7052
|
+
}
|
|
7053
|
+
|
|
7035
7054
|
/**
|
|
7036
7055
|
* Creates an instance of LocusMediaRequest for this meeting - it is needed for doing any calls
|
|
7037
7056
|
* to Locus /media API (these are used for sending Roap messages and updating audio/video mute status).
|
|
@@ -377,7 +377,10 @@ describe('plugin-meetings', () => {
|
|
|
377
377
|
}
|
|
378
378
|
);
|
|
379
379
|
assert.equal(newMeeting.correlationId, newMeeting.id);
|
|
380
|
-
assert.deepEqual(newMeeting.callStateForMetrics, {
|
|
380
|
+
assert.deepEqual(newMeeting.callStateForMetrics, {
|
|
381
|
+
correlationId: newMeeting.id,
|
|
382
|
+
sessionCorrelationId: '',
|
|
383
|
+
});
|
|
381
384
|
});
|
|
382
385
|
|
|
383
386
|
it('correlationId can be provided in callStateForMetrics', () => {
|
|
@@ -3808,12 +3811,12 @@ describe('plugin-meetings', () => {
|
|
|
3808
3811
|
id: 'fake locus from mocked join request',
|
|
3809
3812
|
locusUrl: 'fake locus url',
|
|
3810
3813
|
mediaId: 'fake media id',
|
|
3811
|
-
})
|
|
3814
|
+
});
|
|
3812
3815
|
sinon.stub(meeting.meetingRequest, 'joinMeeting').resolves({
|
|
3813
3816
|
headers: {
|
|
3814
3817
|
trackingid: 'fake tracking id',
|
|
3815
|
-
}
|
|
3816
|
-
})
|
|
3818
|
+
},
|
|
3819
|
+
});
|
|
3817
3820
|
await meeting.join({enableMultistream: isMultistream});
|
|
3818
3821
|
});
|
|
3819
3822
|
|
|
@@ -4006,7 +4009,10 @@ describe('plugin-meetings', () => {
|
|
|
4006
4009
|
assert.notCalled(
|
|
4007
4010
|
meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream
|
|
4008
4011
|
);
|
|
4009
|
-
assert.throws(
|
|
4012
|
+
assert.throws(
|
|
4013
|
+
meeting.publishStreams(localStreams),
|
|
4014
|
+
`Attempted to publish microphone stream with ended readyState, correlationId=${meeting.correlationId}`
|
|
4015
|
+
);
|
|
4010
4016
|
} else {
|
|
4011
4017
|
assert.calledOnceWithExactly(
|
|
4012
4018
|
meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream,
|
|
@@ -4019,7 +4025,10 @@ describe('plugin-meetings', () => {
|
|
|
4019
4025
|
assert.notCalled(
|
|
4020
4026
|
meeting.sendSlotManager.getSlot(MediaType.VideoMain).publishStream
|
|
4021
4027
|
);
|
|
4022
|
-
assert.throws(
|
|
4028
|
+
assert.throws(
|
|
4029
|
+
meeting.publishStreams(localStreams),
|
|
4030
|
+
`Attempted to publish camera stream with ended readyState, correlationId=${meeting.correlationId}`
|
|
4031
|
+
);
|
|
4023
4032
|
} else {
|
|
4024
4033
|
assert.calledOnceWithExactly(
|
|
4025
4034
|
meeting.sendSlotManager.getSlot(MediaType.VideoMain).publishStream,
|
|
@@ -4032,7 +4041,10 @@ describe('plugin-meetings', () => {
|
|
|
4032
4041
|
assert.notCalled(
|
|
4033
4042
|
meeting.sendSlotManager.getSlot(MediaType.AudioSlides).publishStream
|
|
4034
4043
|
);
|
|
4035
|
-
assert.throws(
|
|
4044
|
+
assert.throws(
|
|
4045
|
+
meeting.publishStreams(localStreams),
|
|
4046
|
+
`Attempted to publish screenShare audio stream with ended readyState, correlationId=${meeting.correlationId}`
|
|
4047
|
+
);
|
|
4036
4048
|
} else {
|
|
4037
4049
|
assert.calledOnceWithExactly(
|
|
4038
4050
|
meeting.sendSlotManager.getSlot(MediaType.AudioSlides).publishStream,
|
|
@@ -4045,7 +4057,10 @@ describe('plugin-meetings', () => {
|
|
|
4045
4057
|
assert.notCalled(
|
|
4046
4058
|
meeting.sendSlotManager.getSlot(MediaType.VideoSlides).publishStream
|
|
4047
4059
|
);
|
|
4048
|
-
assert.throws(
|
|
4060
|
+
assert.throws(
|
|
4061
|
+
meeting.publishStreams(localStreams),
|
|
4062
|
+
`Attempted to publish screenShare video stream with ended readyState, correlationId=${meeting.correlationId}`
|
|
4063
|
+
);
|
|
4049
4064
|
} else {
|
|
4050
4065
|
assert.calledOnceWithExactly(
|
|
4051
4066
|
meeting.sendSlotManager.getSlot(MediaType.VideoSlides).publishStream,
|
|
@@ -4340,14 +4355,14 @@ describe('plugin-meetings', () => {
|
|
|
4340
4355
|
const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
|
|
4341
4356
|
await meeting.addMedia({audioEnabled: false});
|
|
4342
4357
|
//calling handleDeviceLogging with audioEnaled as true adn videoEnabled as false
|
|
4343
|
-
assert.calledWith(handleDeviceLoggingSpy,false,true);
|
|
4358
|
+
assert.calledWith(handleDeviceLoggingSpy, false, true);
|
|
4344
4359
|
});
|
|
4345
4360
|
|
|
4346
4361
|
it('addMedia() works correctly when video is disabled with no streams to publish', async () => {
|
|
4347
4362
|
const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
|
|
4348
4363
|
await meeting.addMedia({videoEnabled: false});
|
|
4349
4364
|
//calling handleDeviceLogging audioEnabled as true videoEnabled as false
|
|
4350
|
-
assert.calledWith(handleDeviceLoggingSpy,true,false);
|
|
4365
|
+
assert.calledWith(handleDeviceLoggingSpy, true, false);
|
|
4351
4366
|
});
|
|
4352
4367
|
|
|
4353
4368
|
it('addMedia() works correctly when video is disabled with no streams to publish', async () => {
|
|
@@ -4416,12 +4431,11 @@ describe('plugin-meetings', () => {
|
|
|
4416
4431
|
assert.calledTwice(locusMediaRequestStub);
|
|
4417
4432
|
});
|
|
4418
4433
|
|
|
4419
|
-
|
|
4420
4434
|
it('addMedia() works correctly when both shareAudio and shareVideo is disabled with no streams publish', async () => {
|
|
4421
4435
|
const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
|
|
4422
4436
|
await meeting.addMedia({shareAudioEnabled: false, shareVideoEnabled: false});
|
|
4423
4437
|
//calling handleDeviceLogging with audioEnabled true and videoEnabled as true
|
|
4424
|
-
assert.calledWith(handleDeviceLoggingSpy,true,true);
|
|
4438
|
+
assert.calledWith(handleDeviceLoggingSpy, true, true);
|
|
4425
4439
|
});
|
|
4426
4440
|
|
|
4427
4441
|
describe('publishStreams()/unpublishStreams() calls', () => {
|
|
@@ -6998,7 +7012,10 @@ describe('plugin-meetings', () => {
|
|
|
6998
7012
|
assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
|
|
6999
7013
|
meeting.setCorrelationId(uuid1);
|
|
7000
7014
|
assert.equal(meeting.correlationId, uuid1);
|
|
7001
|
-
assert.deepEqual(meeting.callStateForMetrics, {
|
|
7015
|
+
assert.deepEqual(meeting.callStateForMetrics, {
|
|
7016
|
+
correlationId: uuid1,
|
|
7017
|
+
sessionCorrelationId: '',
|
|
7018
|
+
});
|
|
7002
7019
|
});
|
|
7003
7020
|
});
|
|
7004
7021
|
|
|
@@ -7670,11 +7687,11 @@ describe('plugin-meetings', () => {
|
|
|
7670
7687
|
id: 'stream',
|
|
7671
7688
|
getTracks: () => [{id: 'track', addEventListener: sinon.stub()}],
|
|
7672
7689
|
};
|
|
7673
|
-
const simulateConnectionStateChange = (newState) => {
|
|
7690
|
+
const simulateConnectionStateChange = async (newState) => {
|
|
7674
7691
|
meeting.mediaProperties.webrtcMediaConnection.getConnectionState = sinon
|
|
7675
7692
|
.stub()
|
|
7676
7693
|
.returns(newState);
|
|
7677
|
-
eventListeners[MediaConnectionEventNames.PEER_CONNECTION_STATE_CHANGED]();
|
|
7694
|
+
await eventListeners[MediaConnectionEventNames.PEER_CONNECTION_STATE_CHANGED]();
|
|
7678
7695
|
};
|
|
7679
7696
|
|
|
7680
7697
|
beforeEach(() => {
|
|
@@ -7930,7 +7947,7 @@ describe('plugin-meetings', () => {
|
|
|
7930
7947
|
meeting.reconnectionManager = new ReconnectionManager(meeting);
|
|
7931
7948
|
meeting.reconnectionManager.iceReconnected = sinon.stub().returns(undefined);
|
|
7932
7949
|
meeting.setNetworkStatus = sinon.stub().returns(undefined);
|
|
7933
|
-
meeting.statsAnalyzer = {startAnalyzer: sinon.stub()};
|
|
7950
|
+
meeting.statsAnalyzer = {startAnalyzer: sinon.stub(), stopAnalyzer: sinon.stub()};
|
|
7934
7951
|
meeting.mediaProperties.webrtcMediaConnection = {
|
|
7935
7952
|
// mock the on() method and store all the listeners
|
|
7936
7953
|
on: sinon.stub().callsFake((event, listener) => {
|
|
@@ -8005,10 +8022,10 @@ describe('plugin-meetings', () => {
|
|
|
8005
8022
|
});
|
|
8006
8023
|
|
|
8007
8024
|
describe('CONNECTION_STATE_CHANGED event when state = "Failed"', () => {
|
|
8008
|
-
const mockFailedEvent = () => {
|
|
8025
|
+
const mockFailedEvent = async () => {
|
|
8009
8026
|
meeting.setupMediaConnectionListeners();
|
|
8010
8027
|
|
|
8011
|
-
simulateConnectionStateChange(ConnectionState.Failed);
|
|
8028
|
+
await simulateConnectionStateChange(ConnectionState.Failed);
|
|
8012
8029
|
};
|
|
8013
8030
|
|
|
8014
8031
|
const checkBehavioralMetricSent = (hasMediaConnectionConnectedAtLeastOnce = false) => {
|
|
@@ -8038,6 +8055,22 @@ describe('plugin-meetings', () => {
|
|
|
8038
8055
|
assert.notCalled(webex.internal.newMetrics.submitClientEvent);
|
|
8039
8056
|
checkBehavioralMetricSent(true);
|
|
8040
8057
|
});
|
|
8058
|
+
|
|
8059
|
+
it('stop stats analyzer during reconnection ', async () => {
|
|
8060
|
+
meeting.hasMediaConnectionConnectedAtLeastOnce = true;
|
|
8061
|
+
meeting.statsAnalyzer.stopAnalyzer = sinon.stub().resolves();
|
|
8062
|
+
meeting.reconnectionManager = {
|
|
8063
|
+
reconnect: sinon.stub().resolves(),
|
|
8064
|
+
resetReconnectionTimer: () => {}
|
|
8065
|
+
};
|
|
8066
|
+
meeting.currentMediaStatus = {
|
|
8067
|
+
video: true
|
|
8068
|
+
};
|
|
8069
|
+
|
|
8070
|
+
await mockFailedEvent();
|
|
8071
|
+
|
|
8072
|
+
assert.calledOnce(meeting.statsAnalyzer.stopAnalyzer);
|
|
8073
|
+
});
|
|
8041
8074
|
});
|
|
8042
8075
|
|
|
8043
8076
|
describe('should send correct metrics for ROAP_FAILURE event', () => {
|