@webex/plugin-meetings 3.0.0-beta.34 → 3.0.0-beta.36
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/edit-lock-error.js +52 -0
- package/dist/breakouts/edit-lock-error.js.map +1 -0
- package/dist/breakouts/index.js +86 -2
- package/dist/breakouts/index.js.map +1 -1
- package/dist/constants.js +14 -2
- package/dist/constants.js.map +1 -1
- package/dist/media/index.js +4 -18
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +3 -3
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/index.js +194 -306
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +7 -2
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +135 -85
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +2 -2
- package/dist/meeting/util.js.map +1 -1
- package/dist/metrics/constants.js +0 -4
- package/dist/metrics/constants.js.map +1 -1
- package/dist/reachability/index.js +25 -17
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +12 -5
- package/dist/reachability/request.js.map +1 -1
- package/dist/reconnection-manager/index.js +1 -2
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/request.js +114 -83
- package/dist/roap/request.js.map +1 -1
- package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
- package/dist/types/constants.d.ts +13 -1
- package/dist/types/media/properties.d.ts +7 -6
- package/dist/types/meeting/index.d.ts +11 -36
- package/dist/types/meeting/request.d.ts +10 -0
- package/dist/types/metrics/constants.d.ts +0 -4
- package/dist/types/reachability/request.d.ts +5 -3
- package/dist/types/roap/request.d.ts +6 -3
- package/package.json +19 -19
- package/src/breakouts/README.md +8 -2
- package/src/breakouts/edit-lock-error.ts +25 -0
- package/src/breakouts/index.ts +73 -0
- package/src/constants.ts +13 -1
- package/src/media/index.ts +14 -24
- package/src/media/properties.ts +16 -10
- package/src/meeting/index.ts +122 -204
- package/src/meeting/muteState.ts +5 -5
- package/src/meeting/request.ts +35 -1
- package/src/meeting/util.ts +5 -4
- package/src/metrics/constants.ts +0 -4
- package/src/reachability/index.ts +12 -4
- package/src/reachability/request.ts +10 -5
- package/src/reconnection-manager/index.ts +1 -1
- package/src/roap/request.ts +93 -78
- package/test/integration/spec/converged-space-meetings.js +3 -3
- package/test/integration/spec/journey.js +3 -3
- package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
- package/test/unit/spec/breakouts/index.ts +92 -1
- package/test/unit/spec/media/index.ts +8 -6
- package/test/unit/spec/meeting/index.js +87 -114
- package/test/unit/spec/meeting/muteState.js +21 -22
- package/test/unit/spec/meeting/request.js +27 -0
- package/test/unit/spec/meeting/utils.js +3 -1
- package/test/unit/spec/reachability/index.ts +18 -7
- package/test/unit/spec/reachability/request.js +66 -0
- package/test/unit/spec/roap/request.ts +187 -84
- package/test/utils/testUtils.js +30 -25
- package/dist/meeting/effectsState.js +0 -262
- package/dist/meeting/effectsState.js.map +0 -1
- package/dist/types/meeting/effectsState.d.ts +0 -42
- package/src/meeting/effectsState.ts +0 -211
- package/test/unit/spec/meeting/effectsState.js +0 -285
package/src/meeting/request.ts
CHANGED
|
@@ -23,10 +23,10 @@ import {
|
|
|
23
23
|
PARTICIPANT,
|
|
24
24
|
PROVISIONAL_TYPE_DIAL_IN,
|
|
25
25
|
PROVISIONAL_TYPE_DIAL_OUT,
|
|
26
|
+
REACHABILITY,
|
|
26
27
|
SEND_DTMF_ENDPOINT,
|
|
27
28
|
_SLIDES_,
|
|
28
29
|
} from '../constants';
|
|
29
|
-
import {Reaction} from '../reactions/reactions.type';
|
|
30
30
|
import {SendReactionOptions, ToggleReactionsOptions} from './request.type';
|
|
31
31
|
|
|
32
32
|
/**
|
|
@@ -35,6 +35,11 @@ import {SendReactionOptions, ToggleReactionsOptions} from './request.type';
|
|
|
35
35
|
export default class MeetingRequest extends StatelessWebexPlugin {
|
|
36
36
|
changeVideoLayoutDebounced: any;
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Constructor
|
|
40
|
+
* @param {Object} attrs
|
|
41
|
+
* @param {Object} options
|
|
42
|
+
*/
|
|
38
43
|
constructor(attrs: any, options: any) {
|
|
39
44
|
super(attrs, options);
|
|
40
45
|
this.changeVideoLayoutDebounced = debounce(this.changeVideoLayout, 2000, {
|
|
@@ -43,6 +48,32 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
43
48
|
});
|
|
44
49
|
}
|
|
45
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Returns joinCookie from boundedStorage if present.
|
|
53
|
+
* @returns {Object} joinCookie
|
|
54
|
+
*/
|
|
55
|
+
private getJoinCookie = async () => {
|
|
56
|
+
// @ts-ignore
|
|
57
|
+
const joinCookieRaw = await this.webex.boundedStorage
|
|
58
|
+
.get(REACHABILITY.namespace, REACHABILITY.localStorageJoinCookie)
|
|
59
|
+
.catch(() => {});
|
|
60
|
+
|
|
61
|
+
if (joinCookieRaw) {
|
|
62
|
+
try {
|
|
63
|
+
const joinCookie = JSON.parse(joinCookieRaw);
|
|
64
|
+
if (joinCookie) {
|
|
65
|
+
return joinCookie;
|
|
66
|
+
}
|
|
67
|
+
} catch (e) {
|
|
68
|
+
LoggerProxy.logger.error(
|
|
69
|
+
`MeetingRequest#constructor --> Error in parsing join cookie data: ${e}`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return null;
|
|
75
|
+
};
|
|
76
|
+
|
|
46
77
|
/**
|
|
47
78
|
* Make a network request to join a meeting
|
|
48
79
|
* @param {Object} options
|
|
@@ -99,6 +130,8 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
99
130
|
|
|
100
131
|
let url = '';
|
|
101
132
|
|
|
133
|
+
const joinCookie = await this.getJoinCookie();
|
|
134
|
+
|
|
102
135
|
const body: any = {
|
|
103
136
|
asResourceOccupant,
|
|
104
137
|
device: {
|
|
@@ -115,6 +148,7 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
115
148
|
supportsNativeLobby: 1,
|
|
116
149
|
clientMediaPreferences: {
|
|
117
150
|
preferTranscoding: preferTranscoding ?? true,
|
|
151
|
+
joinCookie,
|
|
118
152
|
},
|
|
119
153
|
};
|
|
120
154
|
|
package/src/meeting/util.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {isEmpty} from 'lodash';
|
|
2
|
+
import {LocalCameraTrack, LocalMicrophoneTrack} from '@webex/internal-media-core';
|
|
2
3
|
|
|
3
4
|
import {MeetingNotActiveError, UserNotJoinedError} from '../common/errors/webex-errors';
|
|
4
5
|
import Metrics from '../metrics';
|
|
@@ -390,11 +391,11 @@ MeetingUtil.unlockMeeting = (actions, request, locusUrl) => {
|
|
|
390
391
|
return Promise.reject(new PermissionError('Unlock not allowed, due to joined property.'));
|
|
391
392
|
};
|
|
392
393
|
|
|
393
|
-
MeetingUtil.handleAudioLogging = (audioTrack) => {
|
|
394
|
+
MeetingUtil.handleAudioLogging = (audioTrack: LocalMicrophoneTrack | null) => {
|
|
394
395
|
const LOG_HEADER = 'MeetingUtil#handleAudioLogging -->';
|
|
395
396
|
|
|
396
397
|
if (audioTrack) {
|
|
397
|
-
const settings = audioTrack.getSettings();
|
|
398
|
+
const settings = audioTrack.underlyingTrack.getSettings();
|
|
398
399
|
const {deviceId} = settings;
|
|
399
400
|
|
|
400
401
|
LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${deviceId}`);
|
|
@@ -402,11 +403,11 @@ MeetingUtil.handleAudioLogging = (audioTrack) => {
|
|
|
402
403
|
}
|
|
403
404
|
};
|
|
404
405
|
|
|
405
|
-
MeetingUtil.handleVideoLogging = (videoTrack) => {
|
|
406
|
+
MeetingUtil.handleVideoLogging = (videoTrack: LocalCameraTrack | null) => {
|
|
406
407
|
const LOG_HEADER = 'MeetingUtil#handleVideoLogging -->';
|
|
407
408
|
|
|
408
409
|
if (videoTrack) {
|
|
409
|
-
const settings = videoTrack.getSettings();
|
|
410
|
+
const settings = videoTrack.underlyingTrack.getSettings();
|
|
410
411
|
const {deviceId} = settings;
|
|
411
412
|
|
|
412
413
|
LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${deviceId}`);
|
package/src/metrics/constants.ts
CHANGED
|
@@ -40,10 +40,6 @@ const BEHAVIORAL_METRICS = {
|
|
|
40
40
|
INVALID_ICE_CANDIDATE: 'js_sdk_invalid_ice_candidate',
|
|
41
41
|
UPLOAD_LOGS_FAILURE: 'js_sdk_upload_logs_failure',
|
|
42
42
|
RECEIVE_TRANSCRIPTION_FAILURE: 'js_sdk_receive_transcription_failure',
|
|
43
|
-
ENABLE_BNR_SUCCESS: 'js_sdk_enable_bnr_success',
|
|
44
|
-
ENABLE_BNR_FAILURE: 'js_sdk_enable_bnr_failure',
|
|
45
|
-
DISABLE_BNR_SUCCESS: 'js_sdk_disable_bnr_success',
|
|
46
|
-
DISABLE_BNR_FAILURE: 'js_sdk_disable_bnr_failure',
|
|
47
43
|
FETCH_MEETING_INFO_V1_SUCCESS: 'js_sdk_fetch_meeting_info_v1_success',
|
|
48
44
|
FETCH_MEETING_INFO_V1_FAILURE: 'js_sdk_fetch_meeting_info_v1_failure',
|
|
49
45
|
ADHOC_MEETING_SUCCESS: 'js_sdk_adhoc_meeting_success',
|
|
@@ -63,11 +63,13 @@ export default class Reachability {
|
|
|
63
63
|
|
|
64
64
|
// Remove stored reachability results to ensure no stale data
|
|
65
65
|
// @ts-ignore
|
|
66
|
-
await this.webex.boundedStorage.del(this.namespace, REACHABILITY.
|
|
66
|
+
await this.webex.boundedStorage.del(this.namespace, REACHABILITY.localStorageResult);
|
|
67
|
+
// @ts-ignore
|
|
68
|
+
await this.webex.boundedStorage.del(this.namespace, REACHABILITY.localStorageJoinCookie);
|
|
67
69
|
|
|
68
70
|
// Fetch clusters and measure latency
|
|
69
71
|
try {
|
|
70
|
-
const clusters = await this.reachabilityRequest.getClusters();
|
|
72
|
+
const {clusters, joinCookie} = await this.reachabilityRequest.getClusters();
|
|
71
73
|
|
|
72
74
|
// Perform Reachability Check
|
|
73
75
|
const results = await this.performReachabilityCheck(clusters);
|
|
@@ -75,9 +77,15 @@ export default class Reachability {
|
|
|
75
77
|
// @ts-ignore
|
|
76
78
|
await this.webex.boundedStorage.put(
|
|
77
79
|
this.namespace,
|
|
78
|
-
REACHABILITY.
|
|
80
|
+
REACHABILITY.localStorageResult,
|
|
79
81
|
JSON.stringify(results)
|
|
80
82
|
);
|
|
83
|
+
// @ts-ignore
|
|
84
|
+
await this.webex.boundedStorage.put(
|
|
85
|
+
this.namespace,
|
|
86
|
+
REACHABILITY.localStorageJoinCookie,
|
|
87
|
+
JSON.stringify(joinCookie)
|
|
88
|
+
);
|
|
81
89
|
|
|
82
90
|
LoggerProxy.logger.log(
|
|
83
91
|
'Reachability:index#gatherReachability --> Reachability checks completed'
|
|
@@ -103,7 +111,7 @@ export default class Reachability {
|
|
|
103
111
|
let reachable = false;
|
|
104
112
|
// @ts-ignore
|
|
105
113
|
const reachabilityData = await this.webex.boundedStorage
|
|
106
|
-
.get(this.namespace, REACHABILITY.
|
|
114
|
+
.get(this.namespace, REACHABILITY.localStorageResult)
|
|
107
115
|
.catch(() => {});
|
|
108
116
|
|
|
109
117
|
if (reachabilityData) {
|
|
@@ -28,21 +28,23 @@ class ReachabilityRequest {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
31
|
+
* Gets the cluster information
|
|
32
32
|
*
|
|
33
|
-
* @param {boolean} includeVideoMesh whether to include the video mesh clusters in the result or not
|
|
34
33
|
* @returns {Promise}
|
|
35
34
|
*/
|
|
36
|
-
getClusters = (): Promise<ClusterList> =>
|
|
35
|
+
getClusters = (): Promise<{clusters: ClusterList; joinCookie: any}> =>
|
|
37
36
|
this.webex
|
|
38
37
|
.request({
|
|
39
38
|
method: HTTP_VERBS.GET,
|
|
40
39
|
shouldRefreshAccessToken: false,
|
|
41
40
|
api: API.CALLIOPEDISCOVERY,
|
|
42
41
|
resource: RESOURCE.CLUSTERS,
|
|
42
|
+
qs: {
|
|
43
|
+
JCSupport: 1,
|
|
44
|
+
},
|
|
43
45
|
})
|
|
44
46
|
.then((res) => {
|
|
45
|
-
const {clusters} = res.body;
|
|
47
|
+
const {clusters, joinCookie} = res.body;
|
|
46
48
|
|
|
47
49
|
Object.keys(clusters).forEach((key) => {
|
|
48
50
|
clusters[key].isVideoMesh = res.body.clusterClasses?.hybridMedia?.includes(key);
|
|
@@ -52,7 +54,10 @@ class ReachabilityRequest {
|
|
|
52
54
|
`Reachability:request#getClusters --> get clusters successful:${JSON.stringify(clusters)}`
|
|
53
55
|
);
|
|
54
56
|
|
|
55
|
-
return
|
|
57
|
+
return {
|
|
58
|
+
clusters,
|
|
59
|
+
joinCookie,
|
|
60
|
+
};
|
|
56
61
|
});
|
|
57
62
|
|
|
58
63
|
/**
|
|
@@ -476,7 +476,7 @@ export default class ReconnectionManager {
|
|
|
476
476
|
|
|
477
477
|
if (wasSharing) {
|
|
478
478
|
// Stop the share streams if user tried to rejoin
|
|
479
|
-
|
|
479
|
+
this.meeting.setLocalShareTrack(null);
|
|
480
480
|
this.meeting.isSharing = false;
|
|
481
481
|
if (this.shareStatus === SHARE_STATUS.LOCAL_SHARE_ACTIVE) {
|
|
482
482
|
this.meeting.shareStatus = SHARE_STATUS.NO_SHARE;
|
package/src/roap/request.ts
CHANGED
|
@@ -12,14 +12,16 @@ import {eventType} from '../metrics/config';
|
|
|
12
12
|
*/
|
|
13
13
|
export default class RoapRequest extends StatelessWebexPlugin {
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* Returns reachability data.
|
|
16
16
|
* @param {Object} localSdp
|
|
17
|
-
* @returns {
|
|
17
|
+
* @returns {Object}
|
|
18
18
|
*/
|
|
19
|
-
async
|
|
19
|
+
async attachReachabilityData(localSdp) {
|
|
20
|
+
let joinCookie;
|
|
21
|
+
|
|
20
22
|
// @ts-ignore
|
|
21
23
|
const reachabilityData = await this.webex.boundedStorage
|
|
22
|
-
.get(REACHABILITY.namespace, REACHABILITY.
|
|
24
|
+
.get(REACHABILITY.namespace, REACHABILITY.localStorageResult)
|
|
23
25
|
.catch(() => {});
|
|
24
26
|
|
|
25
27
|
if (reachabilityData) {
|
|
@@ -37,7 +39,22 @@ export default class RoapRequest extends StatelessWebexPlugin {
|
|
|
37
39
|
}
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
const joinCookieRaw = await this.webex.boundedStorage
|
|
44
|
+
.get(REACHABILITY.namespace, REACHABILITY.localStorageJoinCookie)
|
|
45
|
+
.catch(() => {});
|
|
46
|
+
|
|
47
|
+
if (joinCookieRaw) {
|
|
48
|
+
try {
|
|
49
|
+
joinCookie = JSON.parse(joinCookieRaw);
|
|
50
|
+
} catch (e) {
|
|
51
|
+
LoggerProxy.logger.error(
|
|
52
|
+
`MeetingRequest#constructor --> Error in parsing join cookie data: ${e}`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return {localSdp, joinCookie};
|
|
41
58
|
}
|
|
42
59
|
|
|
43
60
|
/**
|
|
@@ -53,7 +70,7 @@ export default class RoapRequest extends StatelessWebexPlugin {
|
|
|
53
70
|
* @param {Boolean} options.preferTranscoding
|
|
54
71
|
* @returns {Promise} returns the response/failure of the request
|
|
55
72
|
*/
|
|
56
|
-
sendRoap(options: {
|
|
73
|
+
async sendRoap(options: {
|
|
57
74
|
roapMessage: any;
|
|
58
75
|
locusSelfUrl: string;
|
|
59
76
|
mediaId: string;
|
|
@@ -69,6 +86,14 @@ export default class RoapRequest extends StatelessWebexPlugin {
|
|
|
69
86
|
LoggerProxy.logger.info('Roap:request#sendRoap --> Race Condition /call mediaID not present');
|
|
70
87
|
}
|
|
71
88
|
|
|
89
|
+
const {localSdp: localSdpWithReachabilityData, joinCookie} = await this.attachReachabilityData({
|
|
90
|
+
roapMessage,
|
|
91
|
+
// eslint-disable-next-line no-warning-comments
|
|
92
|
+
// TODO: check whats the need for video and audiomute
|
|
93
|
+
audioMuted: !!options.audioMuted,
|
|
94
|
+
videoMuted: !!options.videoMuted,
|
|
95
|
+
});
|
|
96
|
+
|
|
72
97
|
const mediaUrl = `${locusSelfUrl}/${MEDIA}`;
|
|
73
98
|
// @ts-ignore
|
|
74
99
|
const deviceUrl = this.webex.internal.device.url;
|
|
@@ -79,79 +104,69 @@ export default class RoapRequest extends StatelessWebexPlugin {
|
|
|
79
104
|
|
|
80
105
|
Metrics.postEvent({event: eventType.MEDIA_REQUEST, meetingId});
|
|
81
106
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// @ts-ignore
|
|
98
|
-
deviceType: this.config.meetings.deviceType,
|
|
99
|
-
},
|
|
100
|
-
correlationId,
|
|
101
|
-
localMedias: [
|
|
102
|
-
{
|
|
103
|
-
localSdp: JSON.stringify(sdpWithReachability),
|
|
104
|
-
mediaId: options.mediaId,
|
|
105
|
-
},
|
|
106
|
-
],
|
|
107
|
-
clientMediaPreferences: {
|
|
108
|
-
preferTranscoding: options.preferTranscoding ?? true,
|
|
109
|
-
},
|
|
107
|
+
// @ts-ignore
|
|
108
|
+
return this.request({
|
|
109
|
+
uri: mediaUrl,
|
|
110
|
+
method: HTTP_VERBS.PUT,
|
|
111
|
+
body: {
|
|
112
|
+
device: {
|
|
113
|
+
url: deviceUrl,
|
|
114
|
+
// @ts-ignore
|
|
115
|
+
deviceType: this.config.meetings.deviceType,
|
|
116
|
+
},
|
|
117
|
+
correlationId,
|
|
118
|
+
localMedias: [
|
|
119
|
+
{
|
|
120
|
+
localSdp: JSON.stringify(localSdpWithReachabilityData),
|
|
121
|
+
mediaId: options.mediaId,
|
|
110
122
|
},
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
roapMessage,
|
|
149
|
-
null,
|
|
150
|
-
2
|
|
151
|
-
)} + '\\n mediaId:'${options.mediaId}`
|
|
152
|
-
);
|
|
153
|
-
throw err;
|
|
123
|
+
],
|
|
124
|
+
clientMediaPreferences: {
|
|
125
|
+
preferTranscoding: options.preferTranscoding ?? true,
|
|
126
|
+
joinCookie,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
})
|
|
130
|
+
.then((res) => {
|
|
131
|
+
Metrics.postEvent({event: eventType.MEDIA_RESPONSE, meetingId});
|
|
132
|
+
|
|
133
|
+
// always it will be the first mediaConnection Object
|
|
134
|
+
const mediaConnections =
|
|
135
|
+
res.body.mediaConnections &&
|
|
136
|
+
res.body.mediaConnections.length > 0 &&
|
|
137
|
+
res.body.mediaConnections[0];
|
|
138
|
+
|
|
139
|
+
LoggerProxy.logger.debug(
|
|
140
|
+
`Roap:request#sendRoap --> response:${JSON.stringify(
|
|
141
|
+
mediaConnections,
|
|
142
|
+
null,
|
|
143
|
+
2
|
|
144
|
+
)}'\n StatusCode:'${res.statusCode}`
|
|
145
|
+
);
|
|
146
|
+
const {locus} = res.body;
|
|
147
|
+
|
|
148
|
+
locus.roapSeq = options.roapMessage.seq;
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
locus,
|
|
152
|
+
...(mediaConnections && {mediaConnections: res.body.mediaConnections}),
|
|
153
|
+
};
|
|
154
|
+
})
|
|
155
|
+
.catch((err) => {
|
|
156
|
+
Metrics.postEvent({
|
|
157
|
+
event: eventType.MEDIA_RESPONSE,
|
|
158
|
+
meetingId,
|
|
159
|
+
data: {error: Metrics.parseLocusError(err, true)},
|
|
154
160
|
});
|
|
155
|
-
|
|
161
|
+
LoggerProxy.logger.error(`Roap:request#sendRoap --> Error:${JSON.stringify(err, null, 2)}`);
|
|
162
|
+
LoggerProxy.logger.error(
|
|
163
|
+
`Roap:request#sendRoapRequest --> errorBody:${JSON.stringify(
|
|
164
|
+
roapMessage,
|
|
165
|
+
null,
|
|
166
|
+
2
|
|
167
|
+
)} + '\\n mediaId:'${options.mediaId}`
|
|
168
|
+
);
|
|
169
|
+
throw err;
|
|
170
|
+
});
|
|
156
171
|
}
|
|
157
172
|
}
|
|
@@ -142,9 +142,9 @@ skipInNode(describe)('plugin-meetings', () => {
|
|
|
142
142
|
{scope: chris.meeting, event: 'media:negotiated'},
|
|
143
143
|
]);
|
|
144
144
|
|
|
145
|
-
const addMediaAlice = testUtils.addMedia(alice, {expectedMediaReadyTypes: ['local']});
|
|
146
|
-
const addMediaBob = testUtils.addMedia(bob, {expectedMediaReadyTypes: ['local']});
|
|
147
|
-
const addMediaChris = testUtils.addMedia(chris, {expectedMediaReadyTypes: ['local']});
|
|
145
|
+
const addMediaAlice = testUtils.addMedia(alice, {multistream: true, expectedMediaReadyTypes: ['local']});
|
|
146
|
+
const addMediaBob = testUtils.addMedia(bob, {multistream: true, expectedMediaReadyTypes: ['local']});
|
|
147
|
+
const addMediaChris = testUtils.addMedia(chris, {multistream: true, expectedMediaReadyTypes: ['local']});
|
|
148
148
|
|
|
149
149
|
await addMediaAlice;
|
|
150
150
|
await addMediaBob;
|
|
@@ -605,7 +605,7 @@ skipInNode(describe)('plugin-meetings', () => {
|
|
|
605
605
|
]).then(() => {
|
|
606
606
|
// TODO: Re-eanable Safari when screensharing issues have been resolved
|
|
607
607
|
if (!isBrowser('safari')) {
|
|
608
|
-
assert.equal(alice.meeting.mediaProperties.shareTrack.getConstraints().height, 720);
|
|
608
|
+
assert.equal(alice.meeting.mediaProperties.shareTrack.underlyingTrack.getConstraints().height, 720);
|
|
609
609
|
}
|
|
610
610
|
assert.equal(alice.meeting.isSharing, true);
|
|
611
611
|
assert.equal(alice.meeting.shareStatus, 'local_share_active');
|
|
@@ -646,7 +646,7 @@ skipInNode(describe)('plugin-meetings', () => {
|
|
|
646
646
|
// TODO: Re-eanable Safari when screensharing issues have been resolved
|
|
647
647
|
if (!isBrowser('safari')) {
|
|
648
648
|
assert.equal(
|
|
649
|
-
bob.meeting.mediaProperties.shareTrack.getConstraints().height,
|
|
649
|
+
bob.meeting.mediaProperties.shareTrack.underlyingTrack.getConstraints().height,
|
|
650
650
|
heightResolution
|
|
651
651
|
);
|
|
652
652
|
}
|
|
@@ -806,7 +806,7 @@ skipInNode(describe)('plugin-meetings', () => {
|
|
|
806
806
|
// TODO: Re-eanable Safari when screensharing issues have been resolved
|
|
807
807
|
if (!isBrowser('safari')) {
|
|
808
808
|
assert.equal(
|
|
809
|
-
bob.meeting.mediaProperties.shareTrack.getConstraints().height,
|
|
809
|
+
bob.meeting.mediaProperties.shareTrack.underlyingTrack.getConstraints().height,
|
|
810
810
|
heightResolution
|
|
811
811
|
);
|
|
812
812
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import BreakoutEditLockedError from '@webex/plugin-meetings/src/breakouts/edit-lock-error';
|
|
2
|
+
import {assert, expect} from '@webex/test-helper-chai';
|
|
3
|
+
import {ERROR_DICTIONARY} from '@webex/plugin-meetings/src/constants';
|
|
4
|
+
import {BREAKOUTS} from '@webex/plugin-meetings/src/constants';
|
|
5
|
+
|
|
6
|
+
describe('plugin-meetings', () => {
|
|
7
|
+
describe('edit-lock-error', () => {
|
|
8
|
+
it('check constructor paramter', () => {
|
|
9
|
+
const result = new BreakoutEditLockedError();
|
|
10
|
+
assert.equal(result.name, ERROR_DICTIONARY.BREAKOUT_EDIT.NAME);
|
|
11
|
+
assert.equal(result.sdkMessage, ERROR_DICTIONARY.BREAKOUT_EDIT.MESSAGE);
|
|
12
|
+
assert.equal(result.code, ERROR_DICTIONARY.BREAKOUT_EDIT.CODE);
|
|
13
|
+
assert.equal(result.error, null);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('check constructor paramter', () => {
|
|
17
|
+
const fakeError = {
|
|
18
|
+
body: {
|
|
19
|
+
"errorCode":BREAKOUTS.ERROR_CODE.EDIT_LOCK_TOKEN_MISMATCH,
|
|
20
|
+
"message":"Edit lock token mismatch"
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const result = new BreakoutEditLockedError('message', fakeError);
|
|
24
|
+
assert.equal(result.name, ERROR_DICTIONARY.BREAKOUT_EDIT.NAME);
|
|
25
|
+
assert.equal(result.sdkMessage, ERROR_DICTIONARY.BREAKOUT_EDIT.MESSAGE);
|
|
26
|
+
assert.equal(result.code, ERROR_DICTIONARY.BREAKOUT_EDIT.CODE);
|
|
27
|
+
assert.equal(result.error, fakeError);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -7,7 +7,7 @@ import {BREAKOUTS} from '@webex/plugin-meetings/src/constants';
|
|
|
7
7
|
import sinon from "sinon";
|
|
8
8
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
9
9
|
import testUtils from '../../../utils/testUtils';
|
|
10
|
-
|
|
10
|
+
import BreakoutEditLockedError from "@webex/plugin-meetings/src/breakouts/edit-lock-error";
|
|
11
11
|
|
|
12
12
|
describe('plugin-meetings', () => {
|
|
13
13
|
describe('Breakouts', () => {
|
|
@@ -460,5 +460,96 @@ describe('plugin-meetings', () => {
|
|
|
460
460
|
assert.equal(result, 'REQUEST_RETURN_VALUE');
|
|
461
461
|
});
|
|
462
462
|
});
|
|
463
|
+
|
|
464
|
+
describe('delete', () => {
|
|
465
|
+
it('makes the request as expected', async () => {
|
|
466
|
+
webex.request.returns(Promise.resolve({
|
|
467
|
+
body: {
|
|
468
|
+
groups: [{
|
|
469
|
+
id : "455556a4-37cd-4baa-89bc-8730581a1cc0",
|
|
470
|
+
status : "CLOSE",
|
|
471
|
+
type : "BREAKOUT",
|
|
472
|
+
}]
|
|
473
|
+
}
|
|
474
|
+
}));
|
|
475
|
+
|
|
476
|
+
const result = await breakouts.clearSessions();
|
|
477
|
+
assert.calledOnceWithExactly(webex.request, {
|
|
478
|
+
method: 'PUT',
|
|
479
|
+
uri: 'url',
|
|
480
|
+
body: {
|
|
481
|
+
groups: [
|
|
482
|
+
{
|
|
483
|
+
action: BREAKOUTS.ACTION_TYPES.DELETE,
|
|
484
|
+
},
|
|
485
|
+
],
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
assert.equal(breakouts.groups[0].status, "CLOSE")
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
it('rejects when edit lock token mismatch', async () => {
|
|
493
|
+
webex.request.returns(Promise.reject({
|
|
494
|
+
body: {
|
|
495
|
+
"errorCode":BREAKOUTS.ERROR_CODE.EDIT_LOCK_TOKEN_MISMATCH,
|
|
496
|
+
"message":"Edit lock token mismatch"
|
|
497
|
+
}
|
|
498
|
+
}));
|
|
499
|
+
|
|
500
|
+
await assert.isRejected(
|
|
501
|
+
breakouts.clearSessions(),
|
|
502
|
+
BreakoutEditLockedError,
|
|
503
|
+
'Edit lock token mismatch'
|
|
504
|
+
);
|
|
505
|
+
|
|
506
|
+
});
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
describe('create', () => {
|
|
510
|
+
it('response not include groups info', async () => {
|
|
511
|
+
const sessions = [{'name':'session1', "anyoneCanJoin" : true}];
|
|
512
|
+
const result = await breakouts.create(sessions);
|
|
513
|
+
|
|
514
|
+
assert.equal(result, 'REQUEST_RETURN_VALUE');
|
|
515
|
+
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
it('response include groups info', async () => {
|
|
519
|
+
const sessions = [{'name':'session1', "anyoneCanJoin" : true}];
|
|
520
|
+
|
|
521
|
+
webex.request.returns(Promise.resolve({
|
|
522
|
+
body: {
|
|
523
|
+
groups: [{
|
|
524
|
+
id : "455556a4-37cd-4baa-89bc-8730581a1cc0",
|
|
525
|
+
status : "PENDING",
|
|
526
|
+
type : "BREAKOUT",
|
|
527
|
+
}]
|
|
528
|
+
}
|
|
529
|
+
}));
|
|
530
|
+
|
|
531
|
+
const result = await breakouts.create(sessions);
|
|
532
|
+
|
|
533
|
+
assert.equal(breakouts.groups[0].id, "455556a4-37cd-4baa-89bc-8730581a1cc0")
|
|
534
|
+
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
it('rejects when edit lock token mismatch', async () => {
|
|
538
|
+
const sessions = [{'name':'session1', "anyoneCanJoin" : true}];
|
|
539
|
+
|
|
540
|
+
webex.request.returns(Promise.reject({
|
|
541
|
+
body: {
|
|
542
|
+
"errorCode":BREAKOUTS.ERROR_CODE.EDIT_LOCK_TOKEN_MISMATCH,
|
|
543
|
+
"message":"Edit lock token mismatch"
|
|
544
|
+
}
|
|
545
|
+
}));
|
|
546
|
+
|
|
547
|
+
await assert.isRejected(
|
|
548
|
+
breakouts.create(sessions),
|
|
549
|
+
BreakoutEditLockedError,
|
|
550
|
+
'Edit lock token mismatch'
|
|
551
|
+
);
|
|
552
|
+
});
|
|
553
|
+
});
|
|
463
554
|
});
|
|
464
555
|
});
|
|
@@ -10,9 +10,11 @@ describe('createMediaConnection', () => {
|
|
|
10
10
|
};
|
|
11
11
|
const fakeAudioTrack = {
|
|
12
12
|
id: 'audio track',
|
|
13
|
+
underlyingTrack: 'underlying audio track',
|
|
13
14
|
};
|
|
14
15
|
const fakeVideoTrack = {
|
|
15
16
|
id: 'video track',
|
|
17
|
+
underlyingTrack: 'underlying video track',
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
afterEach(() => {
|
|
@@ -80,9 +82,9 @@ describe('createMediaConnection', () => {
|
|
|
80
82
|
},
|
|
81
83
|
{
|
|
82
84
|
send: {
|
|
83
|
-
audio: fakeAudioTrack,
|
|
84
|
-
video: fakeVideoTrack,
|
|
85
|
-
screenShareVideo:
|
|
85
|
+
audio: fakeAudioTrack.underlyingTrack,
|
|
86
|
+
video: fakeVideoTrack.underlyingTrack,
|
|
87
|
+
screenShareVideo: undefined,
|
|
86
88
|
},
|
|
87
89
|
receive: {
|
|
88
90
|
audio: true,
|
|
@@ -190,9 +192,9 @@ describe('createMediaConnection', () => {
|
|
|
190
192
|
},
|
|
191
193
|
{
|
|
192
194
|
send: {
|
|
193
|
-
audio: fakeAudioTrack,
|
|
194
|
-
video:
|
|
195
|
-
screenShareVideo: fakeVideoTrack,
|
|
195
|
+
audio: fakeAudioTrack.underlyingTrack,
|
|
196
|
+
video: undefined,
|
|
197
|
+
screenShareVideo: fakeVideoTrack.underlyingTrack,
|
|
196
198
|
},
|
|
197
199
|
receive: {
|
|
198
200
|
audio: true,
|