@webex/plugin-meetings 3.1.0 → 3.3.0
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/common/errors/{reconnection-in-progress.js → reconnection-not-started.js} +27 -15
- package/dist/common/errors/reconnection-not-started.js.map +1 -0
- package/dist/constants.js +12 -3
- package/dist/constants.js.map +1 -1
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +7 -1
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +10 -0
- package/dist/locus-info/index.js.map +1 -1
- package/dist/media/properties.js +102 -57
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +6 -0
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +543 -467
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +27 -0
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/util.js +9 -16
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting/voicea-meeting.js +37 -49
- package/dist/meeting/voicea-meeting.js.map +1 -1
- package/dist/meeting-info/util.js +304 -267
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +334 -298
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/index.js +6 -27
- package/dist/meetings/index.js.map +1 -1
- package/dist/reachability/index.js +6 -0
- package/dist/reachability/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +138 -109
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/request.js +3 -27
- package/dist/roap/request.js.map +1 -1
- package/dist/statsAnalyzer/index.js +4 -0
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +3 -0
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/types/common/errors/reconnection-not-started.d.ts +13 -0
- package/dist/{constants.d.ts → types/constants.d.ts} +11 -2
- package/dist/types/index.d.ts +19 -0
- package/dist/{media → types/media}/properties.d.ts +26 -2
- package/dist/{meeting → types/meeting}/in-meeting-actions.d.ts +6 -0
- package/dist/{meeting → types/meeting}/index.d.ts +5 -6
- package/dist/{meeting → types/meeting}/locusMediaRequest.d.ts +1 -0
- package/dist/{meeting → types/meeting}/util.d.ts +3 -0
- package/dist/{meeting → types/meeting}/voicea-meeting.d.ts +3 -2
- package/dist/{meeting-info → types/meeting-info}/index.d.ts +1 -1
- package/dist/{meeting-info → types/meeting-info}/meeting-info-v2.d.ts +1 -1
- package/dist/types/meeting-info/util.d.ts +49 -0
- package/dist/types/meeting-info/utilv2.d.ts +65 -0
- package/dist/{meetings → types/meetings}/index.d.ts +1 -16
- package/dist/{reconnection-manager → types/reconnection-manager}/index.d.ts +4 -14
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/common/errors/reconnection-not-started.ts +25 -0
- package/src/constants.ts +12 -4
- package/src/index.ts +30 -0
- package/src/locus-info/controlsUtils.ts +11 -0
- package/src/locus-info/index.ts +16 -0
- package/src/media/properties.ts +67 -15
- package/src/meeting/in-meeting-actions.ts +12 -0
- package/src/meeting/index.ts +121 -98
- package/src/meeting/locusMediaRequest.ts +31 -0
- package/src/meeting/util.ts +9 -16
- package/src/meeting/voicea-meeting.ts +44 -46
- package/src/meeting-info/util.ts +241 -233
- package/src/meeting-info/utilv2.ts +250 -244
- package/src/meetings/index.ts +8 -25
- package/src/reachability/index.ts +3 -0
- package/src/reconnection-manager/index.ts +128 -105
- package/src/roap/request.ts +1 -24
- package/src/statsAnalyzer/index.ts +4 -0
- package/src/statsAnalyzer/mqaUtil.ts +5 -0
- package/test/unit/spec/locus-info/controlsUtils.js +20 -0
- package/test/unit/spec/locus-info/index.js +21 -0
- package/test/unit/spec/media/properties.ts +145 -140
- package/test/unit/spec/meeting/in-meeting-actions.ts +6 -0
- package/test/unit/spec/meeting/index.js +243 -97
- package/test/unit/spec/meeting/locusMediaRequest.ts +49 -0
- package/test/unit/spec/meeting/utils.js +3 -10
- package/test/unit/spec/meeting/voicea-meeting.ts +5 -14
- package/test/unit/spec/meetings/index.js +27 -8
- package/test/unit/spec/reconnection-manager/index.js +127 -39
- package/test/unit/spec/roap/request.ts +0 -37
- package/test/unit/spec/stats-analyzer/index.js +11 -0
- package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
- package/dist/common/errors/reconnection-in-progress.js.map +0 -1
- package/dist/index.d.ts +0 -7
- package/dist/meeting-info/util.d.ts +0 -2
- package/dist/meeting-info/utilv2.d.ts +0 -2
- package/src/common/errors/reconnection-in-progress.ts +0 -8
- /package/dist/{annotation → types/annotation}/annotation.types.d.ts +0 -0
- /package/dist/{annotation → types/annotation}/constants.d.ts +0 -0
- /package/dist/{annotation → types/annotation}/index.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/breakout.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/collection.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/edit-lock-error.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/events.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/index.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/request.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/utils.d.ts +0 -0
- /package/dist/{common → types/common}/browser-detection.d.ts +0 -0
- /package/dist/{common → types/common}/collection.d.ts +0 -0
- /package/dist/{common → types/common}/config.d.ts +0 -0
- /package/dist/{common → types/common}/errors/captcha-error.d.ts +0 -0
- /package/dist/{common → types/common}/errors/intent-to-join.d.ts +0 -0
- /package/dist/{common → types/common}/errors/join-meeting.d.ts +0 -0
- /package/dist/{common → types/common}/errors/media.d.ts +0 -0
- /package/dist/{common → types/common}/errors/no-meeting-info.d.ts +0 -0
- /package/dist/{common → types/common}/errors/parameter.d.ts +0 -0
- /package/dist/{common → types/common}/errors/password-error.d.ts +0 -0
- /package/dist/{common → types/common}/errors/permission.d.ts +0 -0
- /package/dist/{common → types/common}/errors/reclaim-host-role-errors.d.ts +0 -0
- /package/dist/{common → types/common}/errors/reconnection.d.ts +0 -0
- /package/dist/{common → types/common}/errors/stats.d.ts +0 -0
- /package/dist/{common → types/common}/errors/webex-errors.d.ts +0 -0
- /package/dist/{common → types/common}/errors/webex-meetings-error.d.ts +0 -0
- /package/dist/{common → types/common}/events/events-scope.d.ts +0 -0
- /package/dist/{common → types/common}/events/events.d.ts +0 -0
- /package/dist/{common → types/common}/events/trigger-proxy.d.ts +0 -0
- /package/dist/{common → types/common}/events/util.d.ts +0 -0
- /package/dist/{common → types/common}/logs/logger-config.d.ts +0 -0
- /package/dist/{common → types/common}/logs/logger-proxy.d.ts +0 -0
- /package/dist/{common → types/common}/logs/request.d.ts +0 -0
- /package/dist/{common → types/common}/queue.d.ts +0 -0
- /package/dist/{config.d.ts → types/config.d.ts} +0 -0
- /package/dist/{controls-options-manager → types/controls-options-manager}/constants.d.ts +0 -0
- /package/dist/{controls-options-manager → types/controls-options-manager}/enums.d.ts +0 -0
- /package/dist/{controls-options-manager → types/controls-options-manager}/index.d.ts +0 -0
- /package/dist/{controls-options-manager → types/controls-options-manager}/types.d.ts +0 -0
- /package/dist/{controls-options-manager → types/controls-options-manager}/util.d.ts +0 -0
- /package/dist/{interceptors → types/interceptors}/index.d.ts +0 -0
- /package/dist/{interceptors → types/interceptors}/locusRetry.d.ts +0 -0
- /package/dist/{interpretation → types/interpretation}/collection.d.ts +0 -0
- /package/dist/{interpretation → types/interpretation}/index.d.ts +0 -0
- /package/dist/{interpretation → types/interpretation}/siLanguage.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/controlsUtils.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/embeddedAppsUtils.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/fullState.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/hostUtils.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/index.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/infoUtils.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/mediaSharesUtils.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/parser.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/selfUtils.d.ts +0 -0
- /package/dist/{media → types/media}/MediaConnectionAwaiter.d.ts +0 -0
- /package/dist/{media → types/media}/index.d.ts +0 -0
- /package/dist/{media → types/media}/util.d.ts +0 -0
- /package/dist/{mediaQualityMetrics → types/mediaQualityMetrics}/config.d.ts +0 -0
- /package/dist/{meeting → types/meeting}/muteState.d.ts +0 -0
- /package/dist/{meeting → types/meeting}/request.d.ts +0 -0
- /package/dist/{meeting → types/meeting}/request.type.d.ts +0 -0
- /package/dist/{meeting → types/meeting}/state.d.ts +0 -0
- /package/dist/{meeting-info → types/meeting-info}/collection.d.ts +0 -0
- /package/dist/{meeting-info → types/meeting-info}/request.d.ts +0 -0
- /package/dist/{meetings → types/meetings}/collection.d.ts +0 -0
- /package/dist/{meetings → types/meetings}/meetings.types.d.ts +0 -0
- /package/dist/{meetings → types/meetings}/request.d.ts +0 -0
- /package/dist/{meetings → types/meetings}/util.d.ts +0 -0
- /package/dist/{member → types/member}/index.d.ts +0 -0
- /package/dist/{member → types/member}/types.d.ts +0 -0
- /package/dist/{member → types/member}/util.d.ts +0 -0
- /package/dist/{members → types/members}/collection.d.ts +0 -0
- /package/dist/{members → types/members}/index.d.ts +0 -0
- /package/dist/{members → types/members}/request.d.ts +0 -0
- /package/dist/{members → types/members}/types.d.ts +0 -0
- /package/dist/{members → types/members}/util.d.ts +0 -0
- /package/dist/{metrics → types/metrics}/constants.d.ts +0 -0
- /package/dist/{metrics → types/metrics}/index.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/mediaRequestManager.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/receiveSlot.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/receiveSlotManager.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/remoteMedia.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/remoteMediaGroup.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/remoteMediaManager.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/sendSlotManager.d.ts +0 -0
- /package/dist/{networkQualityMonitor → types/networkQualityMonitor}/index.d.ts +0 -0
- /package/dist/{personal-meeting-room → types/personal-meeting-room}/index.d.ts +0 -0
- /package/dist/{personal-meeting-room → types/personal-meeting-room}/request.d.ts +0 -0
- /package/dist/{personal-meeting-room → types/personal-meeting-room}/util.d.ts +0 -0
- /package/dist/{reachability → types/reachability}/clusterReachability.d.ts +0 -0
- /package/dist/{reachability → types/reachability}/index.d.ts +0 -0
- /package/dist/{reachability → types/reachability}/request.d.ts +0 -0
- /package/dist/{reachability → types/reachability}/util.d.ts +0 -0
- /package/dist/{reactions → types/reactions}/constants.d.ts +0 -0
- /package/dist/{reactions → types/reactions}/reactions.d.ts +0 -0
- /package/dist/{reactions → types/reactions}/reactions.type.d.ts +0 -0
- /package/dist/{recording-controller → types/recording-controller}/enums.d.ts +0 -0
- /package/dist/{recording-controller → types/recording-controller}/index.d.ts +0 -0
- /package/dist/{recording-controller → types/recording-controller}/util.d.ts +0 -0
- /package/dist/{roap → types/roap}/index.d.ts +0 -0
- /package/dist/{roap → types/roap}/request.d.ts +0 -0
- /package/dist/{roap → types/roap}/turnDiscovery.d.ts +0 -0
- /package/dist/{rtcMetrics → types/rtcMetrics}/constants.d.ts +0 -0
- /package/dist/{rtcMetrics → types/rtcMetrics}/index.d.ts +0 -0
- /package/dist/{statsAnalyzer → types/statsAnalyzer}/global.d.ts +0 -0
- /package/dist/{statsAnalyzer → types/statsAnalyzer}/index.d.ts +0 -0
- /package/dist/{statsAnalyzer → types/statsAnalyzer}/mqaUtil.d.ts +0 -0
- /package/dist/{transcription → types/transcription}/index.d.ts +0 -0
- /package/dist/{webinar → types/webinar}/collection.d.ts +0 -0
- /package/dist/{webinar → types/webinar}/index.d.ts +0 -0
|
@@ -106,6 +106,12 @@ describe('LocusMediaRequest.send()', () => {
|
|
|
106
106
|
},
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
+
mockWebex.internal = {
|
|
110
|
+
newMetrics: {
|
|
111
|
+
submitClientEvent: sinon.stub()
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
109
115
|
locusMediaRequest = new LocusMediaRequest({
|
|
110
116
|
device: {
|
|
111
117
|
url: 'deviceUrl',
|
|
@@ -113,6 +119,7 @@ describe('LocusMediaRequest.send()', () => {
|
|
|
113
119
|
regionCode: 'regionCode',
|
|
114
120
|
},
|
|
115
121
|
correlationId: 'correlationId',
|
|
122
|
+
meetingId: 'meetingId',
|
|
116
123
|
preferTranscoding: true,
|
|
117
124
|
}, {
|
|
118
125
|
parent: mockWebex,
|
|
@@ -134,6 +141,27 @@ describe('LocusMediaRequest.send()', () => {
|
|
|
134
141
|
await sendRoapMessage('OFFER');
|
|
135
142
|
|
|
136
143
|
webexRequestStub.resetHistory();
|
|
144
|
+
mockWebex.internal.newMetrics.submitClientEvent.resetHistory();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const checkMetrics = (expectedMetrics: boolean = true) => {
|
|
148
|
+
if (expectedMetrics) {
|
|
149
|
+
assert.calledWith(mockWebex.internal.newMetrics.submitClientEvent, {
|
|
150
|
+
name: 'client.locus.media.request',
|
|
151
|
+
options: {
|
|
152
|
+
meetingId: 'meetingId',
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
assert.calledWith(mockWebex.internal.newMetrics.submitClientEvent, {
|
|
157
|
+
name: 'client.locus.media.response',
|
|
158
|
+
options: {
|
|
159
|
+
meetingId: 'meetingId',
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
} else {
|
|
163
|
+
assert.notCalled(mockWebex.internal.newMetrics.submitClientEvent);
|
|
164
|
+
}
|
|
137
165
|
}
|
|
138
166
|
|
|
139
167
|
it('sends a roap message', async () => {
|
|
@@ -146,6 +174,21 @@ describe('LocusMediaRequest.send()', () => {
|
|
|
146
174
|
uri: 'fakeMeetingSelfUrl/media',
|
|
147
175
|
body: createExpectedRoapBody('OFFER', {audioMuted: true, videoMuted: true}),
|
|
148
176
|
});
|
|
177
|
+
|
|
178
|
+
checkMetrics();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('sends correct metric event when roap message fails', async () => {
|
|
182
|
+
webexRequestStub.rejects({code: 300, message: 'fake error'});
|
|
183
|
+
await assert.isRejected(sendRoapMessage('OFFER'));
|
|
184
|
+
|
|
185
|
+
assert.calledWith(mockWebex.internal.newMetrics.submitClientEvent, {
|
|
186
|
+
name: 'client.locus.media.response',
|
|
187
|
+
options: {
|
|
188
|
+
meetingId: 'meetingId',
|
|
189
|
+
rawError: {code: 300, message: 'fake error'},
|
|
190
|
+
},
|
|
191
|
+
});
|
|
149
192
|
});
|
|
150
193
|
|
|
151
194
|
it('sends a local mute request', async () => {
|
|
@@ -160,6 +203,8 @@ describe('LocusMediaRequest.send()', () => {
|
|
|
160
203
|
uri: 'fakeMeetingSelfUrl/media',
|
|
161
204
|
body: createExpectedLocalMuteBody({audioMuted: false, videoMuted: false}),
|
|
162
205
|
});
|
|
206
|
+
|
|
207
|
+
checkMetrics(false);
|
|
163
208
|
});
|
|
164
209
|
|
|
165
210
|
it('sends a local mute request with sequence', async () => {
|
|
@@ -207,6 +252,7 @@ describe('LocusMediaRequest.send()', () => {
|
|
|
207
252
|
body: createExpectedLocalMuteBody({audioMuted: false, videoMuted: true}),
|
|
208
253
|
});
|
|
209
254
|
|
|
255
|
+
checkMetrics(false);
|
|
210
256
|
});
|
|
211
257
|
|
|
212
258
|
it('sends a local mute request with the last audio/video mute values', async () => {
|
|
@@ -225,6 +271,7 @@ describe('LocusMediaRequest.send()', () => {
|
|
|
225
271
|
body: createExpectedLocalMuteBody({audioMuted: true, videoMuted: false}),
|
|
226
272
|
});
|
|
227
273
|
|
|
274
|
+
checkMetrics(false);
|
|
228
275
|
});
|
|
229
276
|
|
|
230
277
|
it('sends only roap when roap and local mute are requested', async () => {
|
|
@@ -242,6 +289,8 @@ describe('LocusMediaRequest.send()', () => {
|
|
|
242
289
|
uri: 'fakeMeetingSelfUrl/media',
|
|
243
290
|
body: createExpectedRoapBody('OFFER', {audioMuted: true, videoMuted: false}),
|
|
244
291
|
});
|
|
292
|
+
|
|
293
|
+
checkMetrics();
|
|
245
294
|
});
|
|
246
295
|
|
|
247
296
|
describe('queueing', () => {
|
|
@@ -370,16 +370,6 @@ describe('plugin-meetings', () => {
|
|
|
370
370
|
sequence: {},
|
|
371
371
|
type: 'LocalMute',
|
|
372
372
|
});
|
|
373
|
-
|
|
374
|
-
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
375
|
-
name: 'client.locus.media.request',
|
|
376
|
-
options: {meetingId: meeting.id},
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
380
|
-
name: 'client.locus.media.response',
|
|
381
|
-
options: {meetingId: meeting.id},
|
|
382
|
-
});
|
|
383
373
|
});
|
|
384
374
|
});
|
|
385
375
|
|
|
@@ -765,6 +755,9 @@ describe('plugin-meetings', () => {
|
|
|
765
755
|
{functionName: 'canStartTranscribing', displayHint: 'TRANSCRIPTION_CONTROL_START'},
|
|
766
756
|
{functionName: 'canStopTranscribing', displayHint: 'TRANSCRIPTION_CONTROL_STOP'},
|
|
767
757
|
{functionName: 'isClosedCaptionActive', displayHint: 'CAPTION_STATUS_ACTIVE'},
|
|
758
|
+
{functionName: 'canStartManualCaption', displayHint: 'MANUAL_CAPTION_START'},
|
|
759
|
+
{functionName: 'canStopManualCaption', displayHint: 'MANUAL_CAPTION_STOP'},
|
|
760
|
+
{functionName: 'isManualCaptionActive', displayHint: 'MANUAL_CAPTION_STATUS_ACTIVE'},
|
|
768
761
|
{functionName: 'isWebexAssistantActive', displayHint: 'WEBEX_ASSISTANT_STATUS_ACTIVE'},
|
|
769
762
|
{functionName: 'canViewCaptionPanel', displayHint: 'ENABLE_CAPTION_PANEL'},
|
|
770
763
|
{functionName: 'isRealTimeTranslationEnabled', displayHint: 'DISPLAY_REAL_TIME_TRANSLATION'},
|
|
@@ -101,14 +101,7 @@ describe('plugin-meetings', () => {
|
|
|
101
101
|
],
|
|
102
102
|
transcript_language_code: "en"
|
|
103
103
|
}
|
|
104
|
-
]
|
|
105
|
-
transcript: {
|
|
106
|
-
text: "Don't bother me talking I'm just going to get the transcript data that is interim and I needed if I keep talking, I get the interim data",
|
|
107
|
-
csis: [
|
|
108
|
-
1234867712
|
|
109
|
-
],
|
|
110
|
-
transcript_language_code: "en"
|
|
111
|
-
}
|
|
104
|
+
]
|
|
112
105
|
};
|
|
113
106
|
});
|
|
114
107
|
|
|
@@ -160,7 +153,6 @@ describe('plugin-meetings', () => {
|
|
|
160
153
|
it('should process new final captions correctly', () => {
|
|
161
154
|
let transcriptData = fakeMeeting.transcription;
|
|
162
155
|
let transcriptId = fakeVoiceaPayload.transcriptId;
|
|
163
|
-
delete fakeVoiceaPayload.transcripts;
|
|
164
156
|
|
|
165
157
|
// Assuming that processNewCaptions is a pure function that doesn't mutate the input but returns a new state
|
|
166
158
|
processNewCaptions({
|
|
@@ -169,7 +161,7 @@ describe('plugin-meetings', () => {
|
|
|
169
161
|
});
|
|
170
162
|
|
|
171
163
|
// Check if speaker details are cached if needed
|
|
172
|
-
const csisKey = fakeVoiceaPayload.
|
|
164
|
+
const csisKey = fakeVoiceaPayload.transcripts[0].csis[0];
|
|
173
165
|
const speaker = transcriptData.speakerProxy[csisKey];
|
|
174
166
|
expect(speaker).to.exist;
|
|
175
167
|
|
|
@@ -178,6 +170,7 @@ describe('plugin-meetings', () => {
|
|
|
178
170
|
|
|
179
171
|
//check if the interim caption is removed
|
|
180
172
|
const oldInterimCaption = transcriptData.captions.find(caption => caption.id === `${transcriptId}_${speaker.speakerId}`);
|
|
173
|
+
console.log(oldInterimCaption);
|
|
181
174
|
expect(oldInterimCaption).to.not.exist;
|
|
182
175
|
|
|
183
176
|
// Check the final caption data
|
|
@@ -186,8 +179,8 @@ describe('plugin-meetings', () => {
|
|
|
186
179
|
expect(newCaption).to.include({
|
|
187
180
|
id: transcriptId,
|
|
188
181
|
isFinal: fakeVoiceaPayload.isFinal,
|
|
189
|
-
text: fakeVoiceaPayload.
|
|
190
|
-
currentSpokenLanguage: fakeVoiceaPayload.
|
|
182
|
+
text: fakeVoiceaPayload.transcripts[0].text,
|
|
183
|
+
currentSpokenLanguage: fakeVoiceaPayload.transcripts[0].transcript_language_code,
|
|
191
184
|
});
|
|
192
185
|
|
|
193
186
|
// Check the speaker data in the new caption
|
|
@@ -197,7 +190,6 @@ describe('plugin-meetings', () => {
|
|
|
197
190
|
it('should process new interim captions correctly', () => {
|
|
198
191
|
let transcriptData = fakeMeeting.transcription;
|
|
199
192
|
let transcriptId = fakeVoiceaPayload.transcriptId;
|
|
200
|
-
delete fakeVoiceaPayload.transcript;
|
|
201
193
|
|
|
202
194
|
transcriptData.captions.splice(transcriptData.length - 1, 1);
|
|
203
195
|
fakeVoiceaPayload.isFinal = false;
|
|
@@ -232,7 +224,6 @@ describe('plugin-meetings', () => {
|
|
|
232
224
|
it('should process interim captions with an existing one correctly', () => {
|
|
233
225
|
let transcriptData = fakeMeeting.transcription;
|
|
234
226
|
let transcriptId = fakeVoiceaPayload.transcriptId;
|
|
235
|
-
delete fakeVoiceaPayload.transcript;
|
|
236
227
|
fakeVoiceaPayload.isFinal = false;
|
|
237
228
|
|
|
238
229
|
processNewCaptions({
|
|
@@ -513,13 +513,8 @@ describe('plugin-meetings', () => {
|
|
|
513
513
|
});
|
|
514
514
|
describe('#getAllMeetings', () => {
|
|
515
515
|
it('calls MeetingCollection to get all meetings with supplied options', () => {
|
|
516
|
-
webex.meetings.getAllMeetings(
|
|
517
|
-
test: test1,
|
|
518
|
-
});
|
|
516
|
+
webex.meetings.getAllMeetings();
|
|
519
517
|
assert.calledOnce(webex.meetings.meetingCollection.getAll);
|
|
520
|
-
assert.calledWith(webex.meetings.meetingCollection.getAll, {
|
|
521
|
-
test: test1,
|
|
522
|
-
});
|
|
523
518
|
});
|
|
524
519
|
});
|
|
525
520
|
});
|
|
@@ -1011,6 +1006,7 @@ describe('plugin-meetings', () => {
|
|
|
1011
1006
|
callBackInfo: {
|
|
1012
1007
|
callbackAddress: uri1,
|
|
1013
1008
|
},
|
|
1009
|
+
devices: [],
|
|
1014
1010
|
},
|
|
1015
1011
|
info: {
|
|
1016
1012
|
webExMeetingId,
|
|
@@ -1038,6 +1034,7 @@ describe('plugin-meetings', () => {
|
|
|
1038
1034
|
callBackInfo: {
|
|
1039
1035
|
callbackAddress: uri1,
|
|
1040
1036
|
},
|
|
1037
|
+
devices: [],
|
|
1041
1038
|
},
|
|
1042
1039
|
info: {
|
|
1043
1040
|
webExMeetingId,
|
|
@@ -1052,6 +1049,7 @@ describe('plugin-meetings', () => {
|
|
|
1052
1049
|
callBackInfo: {
|
|
1053
1050
|
callbackAddress: uri1,
|
|
1054
1051
|
},
|
|
1052
|
+
devices: [],
|
|
1055
1053
|
},
|
|
1056
1054
|
info: {
|
|
1057
1055
|
webExMeetingId,
|
|
@@ -1074,6 +1072,7 @@ describe('plugin-meetings', () => {
|
|
|
1074
1072
|
callBackInfo: {
|
|
1075
1073
|
callbackAddress: uri1,
|
|
1076
1074
|
},
|
|
1075
|
+
devices: [],
|
|
1077
1076
|
},
|
|
1078
1077
|
info: {
|
|
1079
1078
|
webExMeetingId,
|
|
@@ -1091,6 +1090,7 @@ describe('plugin-meetings', () => {
|
|
|
1091
1090
|
callBackInfo: {
|
|
1092
1091
|
callbackAddress: uri1,
|
|
1093
1092
|
},
|
|
1093
|
+
devices: [],
|
|
1094
1094
|
},
|
|
1095
1095
|
info: {
|
|
1096
1096
|
webExMeetingId,
|
|
@@ -1121,6 +1121,7 @@ describe('plugin-meetings', () => {
|
|
|
1121
1121
|
callBackInfo: {
|
|
1122
1122
|
callbackAddress: uri1,
|
|
1123
1123
|
},
|
|
1124
|
+
devices: [],
|
|
1124
1125
|
},
|
|
1125
1126
|
info: {
|
|
1126
1127
|
webExMeetingId,
|
|
@@ -1143,6 +1144,7 @@ describe('plugin-meetings', () => {
|
|
|
1143
1144
|
callBackInfo: {
|
|
1144
1145
|
callbackAddress: uri1,
|
|
1145
1146
|
},
|
|
1147
|
+
devices: [],
|
|
1146
1148
|
},
|
|
1147
1149
|
info: {
|
|
1148
1150
|
webExMeetingId,
|
|
@@ -1157,6 +1159,7 @@ describe('plugin-meetings', () => {
|
|
|
1157
1159
|
callbackInfo: {
|
|
1158
1160
|
callbackAddress: uri1,
|
|
1159
1161
|
},
|
|
1162
|
+
devices: [],
|
|
1160
1163
|
},
|
|
1161
1164
|
info: {
|
|
1162
1165
|
isUnifiedSpaceMeeting,
|
|
@@ -2299,6 +2302,7 @@ describe('plugin-meetings', () => {
|
|
|
2299
2302
|
sessionType: 'BREAKOUT',
|
|
2300
2303
|
};
|
|
2301
2304
|
newLocus.self.state = 'JOINED';
|
|
2305
|
+
newLocus.self.devices = [];
|
|
2302
2306
|
newLocus.fullState = {
|
|
2303
2307
|
active: true,
|
|
2304
2308
|
};
|
|
@@ -2315,7 +2319,7 @@ describe('plugin-meetings', () => {
|
|
|
2315
2319
|
sessionType: 'MAIN',
|
|
2316
2320
|
};
|
|
2317
2321
|
newLocus.self.state = 'JOINED';
|
|
2318
|
-
|
|
2322
|
+
newLocus.self.devices = [];
|
|
2319
2323
|
LoggerProxy.logger.log = sinon.stub();
|
|
2320
2324
|
const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
|
|
2321
2325
|
assert.equal(result, true);
|
|
@@ -2330,11 +2334,26 @@ describe('plugin-meetings', () => {
|
|
|
2330
2334
|
};
|
|
2331
2335
|
newLocus.self.state = 'LEFT';
|
|
2332
2336
|
newLocus.self.reason = 'MOVED';
|
|
2333
|
-
|
|
2337
|
+
newLocus.self.devices = [];
|
|
2334
2338
|
LoggerProxy.logger.log = sinon.stub();
|
|
2335
2339
|
const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
|
|
2336
2340
|
assert.equal(result, false);
|
|
2337
2341
|
});
|
|
2342
|
+
it('moved to lobby, return true', () => {
|
|
2343
|
+
newLocus.controls.breakout = {
|
|
2344
|
+
sessionType: 'MAIN',
|
|
2345
|
+
};
|
|
2346
|
+
newLocus.self.state = 'JOINED';
|
|
2347
|
+
newLocus.self.devices = [{
|
|
2348
|
+
intent: {
|
|
2349
|
+
reason: 'ON_HOLD_LOBBY',
|
|
2350
|
+
type: 'WAIT',
|
|
2351
|
+
}
|
|
2352
|
+
}];
|
|
2353
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
2354
|
+
const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
|
|
2355
|
+
assert.equal(result, true);
|
|
2356
|
+
});
|
|
2338
2357
|
});
|
|
2339
2358
|
|
|
2340
2359
|
describe('#getCorrespondingMeetingByLocus', () => {
|
|
@@ -2,11 +2,14 @@ import 'jsdom-global/register';
|
|
|
2
2
|
import chai from 'chai';
|
|
3
3
|
import chaiAsPromised from 'chai-as-promised';
|
|
4
4
|
import sinon from 'sinon';
|
|
5
|
+
import {Defer} from '@webex/common';
|
|
5
6
|
import ReconnectionManager from '@webex/plugin-meetings/src/reconnection-manager';
|
|
7
|
+
import ReconnectionNotStartedError from '@webex/plugin-meetings/src/common/errors/reconnection-not-started';
|
|
8
|
+
import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
|
|
9
|
+
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
6
10
|
import { RECONNECTION } from '../../../../src/constants';
|
|
7
11
|
import LoggerProxy from '../../../../src/common/logs/logger-proxy';
|
|
8
12
|
import LoggerConfig from '../../../../src/common/logs/logger-config';
|
|
9
|
-
|
|
10
13
|
const {assert} = chai;
|
|
11
14
|
|
|
12
15
|
chai.use(chaiAsPromised);
|
|
@@ -14,18 +17,15 @@ sinon.assert.expose(chai.assert, {prefix: ''});
|
|
|
14
17
|
|
|
15
18
|
describe('plugin-meetings', () => {
|
|
16
19
|
describe('ReconnectionManager.reconnect', () => {
|
|
17
|
-
const sandbox = sinon.createSandbox();
|
|
18
20
|
let fakeMediaConnection;
|
|
19
21
|
let fakeMeeting;
|
|
20
22
|
let loggerSpy;
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
beforeEach(() => {
|
|
23
25
|
LoggerConfig.set({ enable: false });
|
|
24
26
|
LoggerProxy.set();
|
|
25
|
-
loggerSpy =
|
|
26
|
-
});
|
|
27
|
+
loggerSpy = sinon.spy(LoggerProxy.logger, 'info');
|
|
27
28
|
|
|
28
|
-
beforeEach(() => {
|
|
29
29
|
fakeMediaConnection = {
|
|
30
30
|
initiateOffer: sinon.stub().resolves({}),
|
|
31
31
|
reconnect: sinon.stub().resolves({}),
|
|
@@ -33,6 +33,7 @@ describe('plugin-meetings', () => {
|
|
|
33
33
|
fakeMeeting = {
|
|
34
34
|
closePeerConnections: sinon.stub().resolves({}),
|
|
35
35
|
createMediaConnection: sinon.stub().returns(fakeMediaConnection),
|
|
36
|
+
correlationId: 'correlationId',
|
|
36
37
|
config: {
|
|
37
38
|
reconnection: {
|
|
38
39
|
enabled: true,
|
|
@@ -47,6 +48,7 @@ describe('plugin-meetings', () => {
|
|
|
47
48
|
},
|
|
48
49
|
},
|
|
49
50
|
},
|
|
51
|
+
locusUrl: 'test/id',
|
|
50
52
|
mediaProperties: {
|
|
51
53
|
unsetPeerConnection: sinon.stub(),
|
|
52
54
|
webrtcMediaConnection: fakeMediaConnection,
|
|
@@ -83,11 +85,16 @@ describe('plugin-meetings', () => {
|
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
87
|
},
|
|
88
|
+
trigger: sinon.stub(),
|
|
86
89
|
};
|
|
90
|
+
|
|
91
|
+
sinon.stub(TriggerProxy, 'trigger').returns(true);
|
|
92
|
+
sinon.stub(Metrics, 'sendBehavioralMetric');
|
|
87
93
|
});
|
|
88
94
|
|
|
89
95
|
afterEach(() => {
|
|
90
|
-
|
|
96
|
+
sinon.reset();
|
|
97
|
+
sinon.restore();
|
|
91
98
|
});
|
|
92
99
|
|
|
93
100
|
it('calls syncMeetings', async () => {
|
|
@@ -223,6 +230,99 @@ describe('plugin-meetings', () => {
|
|
|
223
230
|
});
|
|
224
231
|
}
|
|
225
232
|
});
|
|
233
|
+
|
|
234
|
+
it('sends the right metrics and events when succeeds', async () => {
|
|
235
|
+
const rm = new ReconnectionManager(fakeMeeting);
|
|
236
|
+
|
|
237
|
+
await rm.reconnect();
|
|
238
|
+
|
|
239
|
+
assert.calledWith(
|
|
240
|
+
TriggerProxy.trigger,
|
|
241
|
+
fakeMeeting,
|
|
242
|
+
{file: 'reconnection-manager/index', function: 'reconnect'},
|
|
243
|
+
'meeting:reconnectionSuccess'
|
|
244
|
+
);
|
|
245
|
+
assert.calledWithMatch(fakeMeeting.webex.internal.newMetrics.submitClientEvent, {
|
|
246
|
+
name: 'client.media.recovered',
|
|
247
|
+
payload: {
|
|
248
|
+
recoveredBy: 'new',
|
|
249
|
+
},
|
|
250
|
+
options: {
|
|
251
|
+
meetingId: fakeMeeting.id,
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
assert.equal(rm.status, RECONNECTION.STATE.DEFAULT_STATUS);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('sends the right metrics and events when fails', async () => {
|
|
258
|
+
const rm = new ReconnectionManager(fakeMeeting);
|
|
259
|
+
|
|
260
|
+
sinon.stub(rm, 'executeReconnection').rejects(new Error('fake error'));
|
|
261
|
+
|
|
262
|
+
await assert.isRejected(rm.reconnect());
|
|
263
|
+
|
|
264
|
+
assert.calledWith(
|
|
265
|
+
TriggerProxy.trigger,
|
|
266
|
+
fakeMeeting,
|
|
267
|
+
{file: 'reconnection-manager/index', function: 'reconnect'},
|
|
268
|
+
'meeting:reconnectionFailure'
|
|
269
|
+
);
|
|
270
|
+
assert.calledWithMatch(fakeMeeting.webex.internal.newMetrics.submitClientEvent, {
|
|
271
|
+
name: 'client.call.aborted',
|
|
272
|
+
payload: {
|
|
273
|
+
errors: [
|
|
274
|
+
{
|
|
275
|
+
category: 'expected',
|
|
276
|
+
errorCode: 2008,
|
|
277
|
+
fatal: true,
|
|
278
|
+
name: 'media-engine',
|
|
279
|
+
shownToUser: false,
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
},
|
|
283
|
+
options: {
|
|
284
|
+
meetingId: fakeMeeting.id,
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
assert.calledWith(Metrics.sendBehavioralMetric, 'js_sdk_meeting_reconnect_failures', {
|
|
288
|
+
correlation_id: fakeMeeting.correlationId,
|
|
289
|
+
locus_id: 'id',
|
|
290
|
+
reason: 'fake error',
|
|
291
|
+
stack: sinon.match.any,
|
|
292
|
+
});
|
|
293
|
+
assert.equal(rm.status, RECONNECTION.STATE.DEFAULT_STATUS);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('throws ReconnectionNotStartedError if reconnection is already in progress', async () => {
|
|
297
|
+
const rm = new ReconnectionManager(fakeMeeting);
|
|
298
|
+
const defer = new Defer();
|
|
299
|
+
|
|
300
|
+
sinon.stub(rm, 'executeReconnection').returns(defer.promise);
|
|
301
|
+
|
|
302
|
+
rm.reconnect();
|
|
303
|
+
|
|
304
|
+
try {
|
|
305
|
+
await rm.reconnect();
|
|
306
|
+
|
|
307
|
+
fail("rm.reconnect() should have thrown, but it hasn't");
|
|
308
|
+
} catch (e) {
|
|
309
|
+
assert.instanceOf(e, ReconnectionNotStartedError);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('throws ReconnectionNotStartedError if reconnection is disabled in config', async () => {
|
|
314
|
+
fakeMeeting.config.reconnection.enabled = false;
|
|
315
|
+
|
|
316
|
+
const rm = new ReconnectionManager(fakeMeeting);
|
|
317
|
+
|
|
318
|
+
try {
|
|
319
|
+
await rm.reconnect();
|
|
320
|
+
|
|
321
|
+
fail("rm.reconnect() should have thrown, but it hasn't");
|
|
322
|
+
} catch (e) {
|
|
323
|
+
assert.instanceOf(e, ReconnectionNotStartedError);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
226
326
|
});
|
|
227
327
|
|
|
228
328
|
/**
|
|
@@ -316,29 +416,41 @@ describe('plugin-meetings', () => {
|
|
|
316
416
|
|
|
317
417
|
describe('waitForIceReconnect()', () => {
|
|
318
418
|
describe('when ice is marked as not disconnected', () => {
|
|
419
|
+
let clock;
|
|
420
|
+
|
|
319
421
|
beforeEach(() => {
|
|
422
|
+
clock = sinon.useFakeTimers();
|
|
320
423
|
reconnectionManager.iceState.disconnected = false;
|
|
321
424
|
});
|
|
322
425
|
|
|
426
|
+
afterEach(() => {
|
|
427
|
+
clock.restore();
|
|
428
|
+
});
|
|
429
|
+
|
|
323
430
|
it('should set the disconnected state to true', () => {
|
|
324
|
-
reconnectionManager.waitForIceReconnect();
|
|
431
|
+
const promise = reconnectionManager.waitForIceReconnect();
|
|
325
432
|
|
|
326
433
|
assert.isTrue(reconnectionManager.iceState.disconnected);
|
|
434
|
+
|
|
435
|
+
// we let the timer expire
|
|
436
|
+
clock.tick(reconnectionManager.iceState.timeoutDuration);
|
|
437
|
+
assert.isRejected(promise);
|
|
327
438
|
});
|
|
328
439
|
|
|
329
|
-
it('should return a promise that rejects after a duration', (
|
|
330
|
-
|
|
440
|
+
it('should return a promise that rejects after a duration', async () => {
|
|
441
|
+
const promise = reconnectionManager.waitForIceReconnect();
|
|
331
442
|
|
|
332
|
-
|
|
333
|
-
|
|
443
|
+
// we let the timer expire
|
|
444
|
+
clock.tick(reconnectionManager.iceState.timeoutDuration);
|
|
445
|
+
assert.isRejected(promise);
|
|
334
446
|
});
|
|
335
447
|
|
|
336
|
-
it('should resolve
|
|
448
|
+
it('should resolve when ICE is reconnected', async () => {
|
|
337
449
|
const promise = reconnectionManager.waitForIceReconnect();
|
|
338
450
|
|
|
339
|
-
reconnectionManager.
|
|
451
|
+
reconnectionManager.iceReconnected();
|
|
340
452
|
|
|
341
|
-
|
|
453
|
+
await promise;
|
|
342
454
|
});
|
|
343
455
|
});
|
|
344
456
|
|
|
@@ -359,30 +471,6 @@ describe('plugin-meetings', () => {
|
|
|
359
471
|
});
|
|
360
472
|
});
|
|
361
473
|
|
|
362
|
-
describe('setStatus()', () => {
|
|
363
|
-
beforeEach(() => {
|
|
364
|
-
reconnectionManager.status = RECONNECTION.STATE.DEFAULT_STATUS;
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
it('should correctly change status to in progress', () => {
|
|
368
|
-
reconnectionManager.setStatus(RECONNECTION.STATE.IN_PROGRESS);
|
|
369
|
-
|
|
370
|
-
assert.equal(reconnectionManager.status, RECONNECTION.STATE.IN_PROGRESS);
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
it('should correctly change status to complete', () => {
|
|
374
|
-
reconnectionManager.setStatus(RECONNECTION.STATE.COMPLETE);
|
|
375
|
-
|
|
376
|
-
assert.equal(reconnectionManager.status, RECONNECTION.STATE.COMPLETE);
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
it('should correctly change status to failure', () => {
|
|
380
|
-
reconnectionManager.setStatus(RECONNECTION.STATE.FAILURE);
|
|
381
|
-
|
|
382
|
-
assert.equal(reconnectionManager.status, RECONNECTION.STATE.FAILURE);
|
|
383
|
-
});
|
|
384
|
-
});
|
|
385
|
-
|
|
386
474
|
describe('cleanUp()', () => {
|
|
387
475
|
it('should call reset and keep reference to meeting object', () => {
|
|
388
476
|
const resetSpy = sinon.spy(reconnectionManager, 'reset');
|
|
@@ -133,20 +133,6 @@ describe('plugin-meetings/roap', () => {
|
|
|
133
133
|
locusMediaRequest,
|
|
134
134
|
});
|
|
135
135
|
|
|
136
|
-
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
137
|
-
name: 'client.locus.media.request',
|
|
138
|
-
options: {
|
|
139
|
-
meetingId: 'meeting-id',
|
|
140
|
-
},
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
144
|
-
name: 'client.locus.media.response',
|
|
145
|
-
options: {
|
|
146
|
-
meetingId: 'meeting-id',
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
|
|
150
136
|
const requestParams = locusMediaRequest.send.getCall(0).args[0];
|
|
151
137
|
assert.deepEqual(requestParams, {
|
|
152
138
|
type: 'RoapMessage',
|
|
@@ -175,29 +161,6 @@ describe('plugin-meetings/roap', () => {
|
|
|
175
161
|
},
|
|
176
162
|
});
|
|
177
163
|
});
|
|
178
|
-
|
|
179
|
-
it('sends correct client event when fails', async () => {
|
|
180
|
-
const locusMediaRequest = {send: sinon.stub().rejects({code: 300, message: 'error'})};
|
|
181
|
-
try {
|
|
182
|
-
await roapRequest.sendRoap({
|
|
183
|
-
locusSelfUrl: locusUrl,
|
|
184
|
-
mediaId: 'mediaId',
|
|
185
|
-
roapMessage: {
|
|
186
|
-
seq: 'seq',
|
|
187
|
-
},
|
|
188
|
-
meetingId: 'meeting-id',
|
|
189
|
-
locusMediaRequest,
|
|
190
|
-
});
|
|
191
|
-
} catch (err) {
|
|
192
|
-
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
193
|
-
name: 'client.locus.media.response',
|
|
194
|
-
options: {
|
|
195
|
-
meetingId: 'meeting-id',
|
|
196
|
-
rawError: {code: 300, message: 'error'},
|
|
197
|
-
},
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
});
|
|
201
164
|
});
|
|
202
165
|
|
|
203
166
|
it('calls attachReachabilityData when sendRoap', async () => {
|