@webex/plugin-meetings 3.12.0-next.86 → 3.12.0-next.88
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/aiEnableRequest/index.js +1 -1
- 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 +18 -2
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/util.js +6 -0
- package/dist/meeting/util.js.map +1 -1
- package/dist/members/index.js +9 -2
- package/dist/members/index.js.map +1 -1
- package/dist/members/util.js +8 -1
- package/dist/members/util.js.map +1 -1
- package/dist/types/meeting/index.d.ts +6 -1
- package/dist/types/members/index.d.ts +3 -1
- package/dist/types/members/util.d.ts +1 -5
- package/dist/webinar/index.js +1 -1
- package/package.json +13 -13
- package/src/meeting/index.ts +21 -3
- package/src/meeting/util.ts +14 -3
- package/src/members/index.ts +11 -4
- package/src/members/util.ts +12 -4
- package/test/unit/spec/meeting/index.js +61 -0
- package/test/unit/spec/meeting/utils.js +75 -1
- package/test/unit/spec/members/index.js +61 -0
- package/test/unit/spec/members/request.js +37 -1
- package/test/unit/spec/members/utils.js +63 -0
package/package.json
CHANGED
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@webex/event-dictionary-ts": "^1.0.2181",
|
|
45
45
|
"@webex/jest-config-legacy": "0.0.0",
|
|
46
46
|
"@webex/legacy-tools": "0.0.0",
|
|
47
|
-
"@webex/plugin-rooms": "3.12.0-next.
|
|
47
|
+
"@webex/plugin-rooms": "3.12.0-next.29",
|
|
48
48
|
"@webex/test-helper-chai": "3.12.0-next.5",
|
|
49
49
|
"@webex/test-helper-mocha": "3.12.0-next.5",
|
|
50
50
|
"@webex/test-helper-mock-webex": "3.12.0-next.5",
|
|
@@ -63,20 +63,20 @@
|
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@webex/common": "3.12.0-next.5",
|
|
65
65
|
"@webex/internal-media-core": "2.26.1",
|
|
66
|
-
"@webex/internal-plugin-conversation": "3.12.0-next.
|
|
67
|
-
"@webex/internal-plugin-device": "3.12.0-next.
|
|
68
|
-
"@webex/internal-plugin-llm": "3.12.0-next.
|
|
69
|
-
"@webex/internal-plugin-mercury": "3.12.0-next.
|
|
70
|
-
"@webex/internal-plugin-metrics": "3.12.0-next.
|
|
71
|
-
"@webex/internal-plugin-support": "3.12.0-next.
|
|
72
|
-
"@webex/internal-plugin-user": "3.12.0-next.
|
|
73
|
-
"@webex/internal-plugin-voicea": "3.12.0-next.
|
|
66
|
+
"@webex/internal-plugin-conversation": "3.12.0-next.29",
|
|
67
|
+
"@webex/internal-plugin-device": "3.12.0-next.27",
|
|
68
|
+
"@webex/internal-plugin-llm": "3.12.0-next.31",
|
|
69
|
+
"@webex/internal-plugin-mercury": "3.12.0-next.28",
|
|
70
|
+
"@webex/internal-plugin-metrics": "3.12.0-next.27",
|
|
71
|
+
"@webex/internal-plugin-support": "3.12.0-next.29",
|
|
72
|
+
"@webex/internal-plugin-user": "3.12.0-next.28",
|
|
73
|
+
"@webex/internal-plugin-voicea": "3.12.0-next.31",
|
|
74
74
|
"@webex/media-helpers": "3.12.0-next.9",
|
|
75
|
-
"@webex/plugin-people": "3.12.0-next.
|
|
76
|
-
"@webex/plugin-rooms": "3.12.0-next.
|
|
75
|
+
"@webex/plugin-people": "3.12.0-next.28",
|
|
76
|
+
"@webex/plugin-rooms": "3.12.0-next.29",
|
|
77
77
|
"@webex/ts-sdp": "^1.8.1",
|
|
78
78
|
"@webex/web-capabilities": "^1.10.0",
|
|
79
|
-
"@webex/webex-core": "3.12.0-next.
|
|
79
|
+
"@webex/webex-core": "3.12.0-next.27",
|
|
80
80
|
"ampersand-collection": "^2.0.2",
|
|
81
81
|
"bowser": "^2.11.0",
|
|
82
82
|
"btoa": "^1.2.1",
|
|
@@ -94,5 +94,5 @@
|
|
|
94
94
|
"//": [
|
|
95
95
|
"TODO: upgrade jwt-decode when moving to node 18"
|
|
96
96
|
],
|
|
97
|
-
"version": "3.12.0-next.
|
|
97
|
+
"version": "3.12.0-next.88"
|
|
98
98
|
}
|
package/src/meeting/index.ts
CHANGED
|
@@ -4202,7 +4202,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4202
4202
|
}
|
|
4203
4203
|
|
|
4204
4204
|
/**
|
|
4205
|
-
* Transfer the moderator role to another eligible member
|
|
4205
|
+
* Transfer the moderator role to another eligible member.
|
|
4206
|
+
*
|
|
4207
|
+
* If the target member is currently joined in the current session, the request is
|
|
4208
|
+
* sent against the current locus. Otherwise, we search the breakout sessions and,
|
|
4209
|
+
* when the member is found in one, we send the request against that breakout
|
|
4210
|
+
* session's locus url instead.
|
|
4206
4211
|
* @param {String} memberId
|
|
4207
4212
|
* @param {Boolean} moderator
|
|
4208
4213
|
* @returns {Promise} see #members.transferHostToMember
|
|
@@ -4210,7 +4215,21 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4210
4215
|
* @memberof Meeting
|
|
4211
4216
|
*/
|
|
4212
4217
|
public transfer(memberId: string, moderator = true) {
|
|
4213
|
-
|
|
4218
|
+
const targetMember = this.members.membersCollection.get(memberId);
|
|
4219
|
+
|
|
4220
|
+
if (targetMember?.isInMeeting) {
|
|
4221
|
+
return this.members.transferHostToMember(memberId, moderator);
|
|
4222
|
+
}
|
|
4223
|
+
|
|
4224
|
+
const breakout = this.breakouts?.breakouts?.models?.find((bo: any) => {
|
|
4225
|
+
const breakoutMember = bo.members?.membersCollection?.get(memberId);
|
|
4226
|
+
|
|
4227
|
+
return breakoutMember?.isInMeeting;
|
|
4228
|
+
});
|
|
4229
|
+
|
|
4230
|
+
const breakoutLocusUrl = breakout?.breakoutRosterLocus?.url;
|
|
4231
|
+
|
|
4232
|
+
return this.members.transferHostToMember(memberId, moderator, breakoutLocusUrl);
|
|
4214
4233
|
}
|
|
4215
4234
|
|
|
4216
4235
|
/**
|
|
@@ -9168,7 +9187,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
9168
9187
|
options: {meetingId: this.id},
|
|
9169
9188
|
});
|
|
9170
9189
|
LoggerProxy.logger.log('Meeting:index#leave --> Leaving a meeting');
|
|
9171
|
-
|
|
9172
9190
|
this.stopListeningForMeetingEvents();
|
|
9173
9191
|
|
|
9174
9192
|
return MeetingUtil.leaveMeeting(this, options)
|
package/src/meeting/util.ts
CHANGED
|
@@ -920,9 +920,20 @@ const MeetingUtil = {
|
|
|
920
920
|
|
|
921
921
|
const options = buildLocusDeltaRequestOptions(originalOptions);
|
|
922
922
|
|
|
923
|
-
return meeting
|
|
924
|
-
|
|
925
|
-
|
|
923
|
+
return meeting.request(options).then((response) => {
|
|
924
|
+
const requestUri = options?.uri;
|
|
925
|
+
const meetingLocusUrl = meeting.locusUrl;
|
|
926
|
+
|
|
927
|
+
if (!requestUri || !meetingLocusUrl || !requestUri.startsWith(meetingLocusUrl)) {
|
|
928
|
+
LoggerProxy.logger.info(
|
|
929
|
+
`Meeting:util#generateLocusDeltaRequest --> skipping updateLocusFromApiResponse, request uri "${requestUri}" does not match meeting locusUrl "${meetingLocusUrl}"`
|
|
930
|
+
);
|
|
931
|
+
|
|
932
|
+
return response;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
return MeetingUtil.updateLocusFromApiResponse(meeting, response);
|
|
936
|
+
});
|
|
926
937
|
};
|
|
927
938
|
|
|
928
939
|
return locusDeltaRequest;
|
package/src/members/index.ts
CHANGED
|
@@ -1136,12 +1136,16 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
1136
1136
|
* Transfers the host to another member
|
|
1137
1137
|
* @param {String} memberId
|
|
1138
1138
|
* @param {boolean} [moderator] default true
|
|
1139
|
+
* @param {String} [breakoutLocusUrl] when provided, the request is sent against this locus url
|
|
1140
|
+
* (i.e. the breakout session's locus) instead of the main session's locus url
|
|
1139
1141
|
* @returns {Promise}
|
|
1140
1142
|
* @public
|
|
1141
1143
|
* @memberof Members
|
|
1142
1144
|
*/
|
|
1143
|
-
public transferHostToMember(memberId: string, moderator = true) {
|
|
1144
|
-
|
|
1145
|
+
public transferHostToMember(memberId: string, moderator = true, breakoutLocusUrl = '') {
|
|
1146
|
+
const locusUrl = breakoutLocusUrl || this.locusUrl;
|
|
1147
|
+
|
|
1148
|
+
if (!locusUrl) {
|
|
1145
1149
|
return Promise.reject(
|
|
1146
1150
|
new ParameterError(
|
|
1147
1151
|
'The associated locus url for this meetings members object must be defined.'
|
|
@@ -1153,11 +1157,14 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
1153
1157
|
new ParameterError('The member id must be defined to transfer host to the member.')
|
|
1154
1158
|
);
|
|
1155
1159
|
}
|
|
1156
|
-
const options = MembersUtil.generateTransferHostMemberOptions(
|
|
1160
|
+
const options: Record<string, any> = MembersUtil.generateTransferHostMemberOptions(
|
|
1157
1161
|
memberId,
|
|
1158
1162
|
moderator,
|
|
1159
|
-
|
|
1163
|
+
locusUrl
|
|
1160
1164
|
);
|
|
1165
|
+
if (breakoutLocusUrl && breakoutLocusUrl !== this.locusUrl) {
|
|
1166
|
+
options.authorizingLocusUrl = this.locusUrl;
|
|
1167
|
+
}
|
|
1161
1168
|
|
|
1162
1169
|
return this.membersRequest.transferHostToMember(options);
|
|
1163
1170
|
}
|
package/src/members/util.ts
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
ALIAS,
|
|
14
14
|
} from '../constants';
|
|
15
15
|
|
|
16
|
-
import {RoleAssignmentOptions, RoleAssignmentRequest, ServerRoleShape} from './types';
|
|
16
|
+
import {RoleAssignmentOptions, RoleAssignmentRequest, ServerRoleShape, ServerRoles} from './types';
|
|
17
17
|
import {Invitee} from '../meeting/type';
|
|
18
18
|
|
|
19
19
|
const MembersUtil = {
|
|
@@ -330,12 +330,20 @@ const MembersUtil = {
|
|
|
330
330
|
};
|
|
331
331
|
},
|
|
332
332
|
|
|
333
|
-
getTransferHostToMemberRequestParams: (options) => {
|
|
334
|
-
const body = {
|
|
333
|
+
getTransferHostToMemberRequestParams: (options: any) => {
|
|
334
|
+
const body: Record<string, any> = {
|
|
335
335
|
role: {
|
|
336
|
-
|
|
336
|
+
roles: [
|
|
337
|
+
{
|
|
338
|
+
hasRole: true,
|
|
339
|
+
type: ServerRoles.Moderator,
|
|
340
|
+
},
|
|
341
|
+
],
|
|
337
342
|
},
|
|
338
343
|
};
|
|
344
|
+
if (options.authorizingLocusUrl) {
|
|
345
|
+
body.authorizingLocusUrl = options.authorizingLocusUrl;
|
|
346
|
+
}
|
|
339
347
|
const uri = `${options.locusUrl}/${PARTICIPANT}/${options.memberId}/${CONTROLS}`;
|
|
340
348
|
|
|
341
349
|
return {
|
|
@@ -883,6 +883,67 @@ describe('plugin-meetings', () => {
|
|
|
883
883
|
assert.deepEqual(args, [[uuid1], locusUrls]);
|
|
884
884
|
});
|
|
885
885
|
});
|
|
886
|
+
describe('#transfer', () => {
|
|
887
|
+
it('should have #transfer', () => {
|
|
888
|
+
assert.exists(meeting.transfer);
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
it('should transfer host using the current locus when the target member is in the current session', async () => {
|
|
892
|
+
sinon.stub(meeting.members.membersCollection, 'get').withArgs(uuid2).returns({isInMeeting: true});
|
|
893
|
+
meeting.members.transferHostToMember = sinon.stub().resolves(test1);
|
|
894
|
+
|
|
895
|
+
await meeting.transfer(uuid2, false);
|
|
896
|
+
|
|
897
|
+
assert.calledOnceWithExactly(meeting.members.transferHostToMember, uuid2, false);
|
|
898
|
+
});
|
|
899
|
+
|
|
900
|
+
it('should transfer host using breakout locus when the target member is joined in a breakout session', async () => {
|
|
901
|
+
sinon.stub(meeting.members.membersCollection, 'get').withArgs(uuid2).returns({isInMeeting: false});
|
|
902
|
+
meeting.members.transferHostToMember = sinon.stub().resolves(test1);
|
|
903
|
+
meeting.breakouts.breakouts = {
|
|
904
|
+
models: [
|
|
905
|
+
{
|
|
906
|
+
members: {
|
|
907
|
+
membersCollection: {
|
|
908
|
+
get: sinon.stub().withArgs(uuid2).returns({isInMeeting: true}),
|
|
909
|
+
},
|
|
910
|
+
},
|
|
911
|
+
breakoutRosterLocus: {url: 'https://example.com/breakout-locus'},
|
|
912
|
+
},
|
|
913
|
+
],
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
await meeting.transfer(uuid2, false);
|
|
917
|
+
|
|
918
|
+
assert.calledOnceWithExactly(
|
|
919
|
+
meeting.members.transferHostToMember,
|
|
920
|
+
uuid2,
|
|
921
|
+
false,
|
|
922
|
+
'https://example.com/breakout-locus'
|
|
923
|
+
);
|
|
924
|
+
});
|
|
925
|
+
|
|
926
|
+
it('should not use breakout locus when the breakout member is not in meeting', async () => {
|
|
927
|
+
sinon.stub(meeting.members.membersCollection, 'get').withArgs(uuid2).returns({isInMeeting: false});
|
|
928
|
+
meeting.members.transferHostToMember = sinon.stub().resolves(test1);
|
|
929
|
+
meeting.breakouts.breakouts = {
|
|
930
|
+
models: [
|
|
931
|
+
{
|
|
932
|
+
members: {
|
|
933
|
+
membersCollection: {
|
|
934
|
+
get: sinon.stub().withArgs(uuid2).returns({isInMeeting: false}),
|
|
935
|
+
},
|
|
936
|
+
},
|
|
937
|
+
breakoutRosterLocus: {url: 'https://example.com/breakout-locus'},
|
|
938
|
+
},
|
|
939
|
+
],
|
|
940
|
+
};
|
|
941
|
+
|
|
942
|
+
await meeting.transfer(uuid2, false);
|
|
943
|
+
|
|
944
|
+
assert.calledOnceWithExactly(meeting.members.transferHostToMember, uuid2, false, undefined);
|
|
945
|
+
});
|
|
946
|
+
});
|
|
886
947
|
describe('#getMembers', () => {
|
|
887
948
|
it('should have #getMembers', () => {
|
|
888
949
|
assert.exists(meeting.getMembers);
|
|
@@ -319,6 +319,7 @@ describe('plugin-meetings', () => {
|
|
|
319
319
|
const addSequenceSpy = sinon.spy(MeetingUtil, 'addSequence');
|
|
320
320
|
|
|
321
321
|
const meeting = {
|
|
322
|
+
locusUrl: 'https://locus.example.com/loci/abc',
|
|
322
323
|
request: sinon.stub().returns(Promise.resolve('result')),
|
|
323
324
|
};
|
|
324
325
|
|
|
@@ -326,6 +327,7 @@ describe('plugin-meetings', () => {
|
|
|
326
327
|
|
|
327
328
|
const options = {
|
|
328
329
|
some: 'option',
|
|
330
|
+
uri: 'https://locus.example.com/loci/abc',
|
|
329
331
|
body: {},
|
|
330
332
|
};
|
|
331
333
|
|
|
@@ -339,7 +341,7 @@ describe('plugin-meetings', () => {
|
|
|
339
341
|
addSequenceSpy.resetHistory();
|
|
340
342
|
|
|
341
343
|
// body missing from options
|
|
342
|
-
result = await locusDeltaRequest({});
|
|
344
|
+
result = await locusDeltaRequest({uri: 'https://locus.example.com/loci/abc'});
|
|
343
345
|
assert.equal(result, 'result');
|
|
344
346
|
assert.calledOnceWithExactly(updateLocusFromApiResponseSpy, meeting, 'result');
|
|
345
347
|
assert.calledOnceWithExactly(addSequenceSpy, meeting, options.body);
|
|
@@ -353,6 +355,78 @@ describe('plugin-meetings', () => {
|
|
|
353
355
|
WeakRef.prototype.deref.restore();
|
|
354
356
|
});
|
|
355
357
|
|
|
358
|
+
it('calls updateLocusFromApiResponse when request uri starts with the meeting locusUrl', async () => {
|
|
359
|
+
const updateLocusFromApiResponseSpy = sinon.spy(MeetingUtil, 'updateLocusFromApiResponse');
|
|
360
|
+
|
|
361
|
+
const meeting = {
|
|
362
|
+
locusUrl: 'https://locus.example.com/loci/abc',
|
|
363
|
+
request: sinon.stub().returns(Promise.resolve('result')),
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
const locusDeltaRequest = MeetingUtil.generateLocusDeltaRequest(meeting);
|
|
367
|
+
|
|
368
|
+
const result = await locusDeltaRequest({
|
|
369
|
+
uri: 'https://locus.example.com/loci/abc/participant/123',
|
|
370
|
+
body: {},
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
assert.equal(result, 'result');
|
|
374
|
+
assert.calledOnceWithExactly(updateLocusFromApiResponseSpy, meeting, 'result');
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('does not call updateLocusFromApiResponse when request uri does not match the meeting locusUrl', async () => {
|
|
378
|
+
const updateLocusFromApiResponseSpy = sinon.spy(MeetingUtil, 'updateLocusFromApiResponse');
|
|
379
|
+
|
|
380
|
+
const meeting = {
|
|
381
|
+
locusUrl: 'https://locus.example.com/loci/abc',
|
|
382
|
+
request: sinon.stub().returns(Promise.resolve('result')),
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
const locusDeltaRequest = MeetingUtil.generateLocusDeltaRequest(meeting);
|
|
386
|
+
|
|
387
|
+
const result = await locusDeltaRequest({
|
|
388
|
+
uri: 'https://locus.example.com/loci/different',
|
|
389
|
+
body: {},
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
assert.equal(result, 'result');
|
|
393
|
+
assert.notCalled(updateLocusFromApiResponseSpy);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it('does not call updateLocusFromApiResponse when request uri is missing', async () => {
|
|
397
|
+
const updateLocusFromApiResponseSpy = sinon.spy(MeetingUtil, 'updateLocusFromApiResponse');
|
|
398
|
+
|
|
399
|
+
const meeting = {
|
|
400
|
+
locusUrl: 'https://locus.example.com/loci/abc',
|
|
401
|
+
request: sinon.stub().returns(Promise.resolve('result')),
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
const locusDeltaRequest = MeetingUtil.generateLocusDeltaRequest(meeting);
|
|
405
|
+
|
|
406
|
+
const result = await locusDeltaRequest({body: {}});
|
|
407
|
+
|
|
408
|
+
assert.equal(result, 'result');
|
|
409
|
+
assert.notCalled(updateLocusFromApiResponseSpy);
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it('does not call updateLocusFromApiResponse when meeting locusUrl is missing', async () => {
|
|
413
|
+
const updateLocusFromApiResponseSpy = sinon.spy(MeetingUtil, 'updateLocusFromApiResponse');
|
|
414
|
+
|
|
415
|
+
const meeting = {
|
|
416
|
+
request: sinon.stub().returns(Promise.resolve('result')),
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
const locusDeltaRequest = MeetingUtil.generateLocusDeltaRequest(meeting);
|
|
420
|
+
|
|
421
|
+
const result = await locusDeltaRequest({
|
|
422
|
+
uri: 'https://locus.example.com/loci/abc',
|
|
423
|
+
body: {},
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
assert.equal(result, 'result');
|
|
427
|
+
assert.notCalled(updateLocusFromApiResponseSpy);
|
|
428
|
+
});
|
|
429
|
+
|
|
356
430
|
it('calls generateBuildLocusDeltaRequestOptions as expected', () => {
|
|
357
431
|
const generateBuildLocusDeltaRequestOptionsSpy = sinon.spy(
|
|
358
432
|
MeetingUtil,
|
|
@@ -303,6 +303,67 @@ describe('plugin-meetings', () => {
|
|
|
303
303
|
});
|
|
304
304
|
});
|
|
305
305
|
|
|
306
|
+
describe('#transferHostToMember', () => {
|
|
307
|
+
it('should reject if no locus url is set and no breakoutLocusUrl is provided', async () => {
|
|
308
|
+
const members = createMembers({url: false});
|
|
309
|
+
|
|
310
|
+
await assert.isRejected(members.transferHostToMember('bob'));
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('should reject if no memberId is provided', async () => {
|
|
314
|
+
const members = createMembers({url: url1});
|
|
315
|
+
|
|
316
|
+
await assert.isRejected(members.transferHostToMember());
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('uses the main locus url when no breakoutLocusUrl is provided', async () => {
|
|
320
|
+
sandbox.spy(MembersUtil, 'generateTransferHostMemberOptions');
|
|
321
|
+
|
|
322
|
+
const members = createMembers({url: url1});
|
|
323
|
+
const {membersRequest} = members;
|
|
324
|
+
sandbox.spy(membersRequest, 'transferHostToMember');
|
|
325
|
+
|
|
326
|
+
await members.transferHostToMember('bob', true);
|
|
327
|
+
|
|
328
|
+
assert.calledOnceWithExactly(
|
|
329
|
+
MembersUtil.generateTransferHostMemberOptions,
|
|
330
|
+
'bob',
|
|
331
|
+
true,
|
|
332
|
+
url1
|
|
333
|
+
);
|
|
334
|
+
assert.calledOnceWithExactly(membersRequest.transferHostToMember, {
|
|
335
|
+
memberId: 'bob',
|
|
336
|
+
moderator: true,
|
|
337
|
+
locusUrl: url1,
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it('uses the breakoutLocusUrl when provided', async () => {
|
|
342
|
+
sandbox.spy(MembersUtil, 'generateTransferHostMemberOptions');
|
|
343
|
+
|
|
344
|
+
const members = createMembers({url: url1});
|
|
345
|
+
const {membersRequest} = members;
|
|
346
|
+
sandbox.spy(membersRequest, 'transferHostToMember');
|
|
347
|
+
|
|
348
|
+
const breakoutLocusUrl = 'https://example.com/breakout-locus';
|
|
349
|
+
|
|
350
|
+
await members.transferHostToMember('bob', true, breakoutLocusUrl);
|
|
351
|
+
|
|
352
|
+
assert.calledOnceWithExactly(
|
|
353
|
+
MembersUtil.generateTransferHostMemberOptions,
|
|
354
|
+
'bob',
|
|
355
|
+
true,
|
|
356
|
+
breakoutLocusUrl
|
|
357
|
+
);
|
|
358
|
+
assert.calledOnceWithExactly(membersRequest.transferHostToMember, {
|
|
359
|
+
memberId: 'bob',
|
|
360
|
+
moderator: true,
|
|
361
|
+
locusUrl: breakoutLocusUrl,
|
|
362
|
+
authorizingLocusUrl: url1,
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
|
|
306
367
|
describe('#clearMembers', () => {
|
|
307
368
|
it('should send clear event if clear members', () => {
|
|
308
369
|
const members = createMembers({url: url1});
|
|
@@ -194,7 +194,43 @@ describe('plugin-meetings', () => {
|
|
|
194
194
|
checkRequest({
|
|
195
195
|
method: 'PATCH',
|
|
196
196
|
uri: 'https://example.com/12345/participant/member1/controls',
|
|
197
|
-
body: {
|
|
197
|
+
body: {
|
|
198
|
+
role: {
|
|
199
|
+
roles: [
|
|
200
|
+
{
|
|
201
|
+
hasRole: true,
|
|
202
|
+
type: 'MODERATOR',
|
|
203
|
+
},
|
|
204
|
+
],
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('sends a request with authorizingLocusUrl when provided', async () => {
|
|
211
|
+
const options = {
|
|
212
|
+
locusUrl: url1,
|
|
213
|
+
memberId: 'member1',
|
|
214
|
+
moderator: true,
|
|
215
|
+
authorizingLocusUrl: 'https://example.com/breakout-locus',
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
await membersRequest.transferHostToMember(options);
|
|
219
|
+
|
|
220
|
+
checkRequest({
|
|
221
|
+
method: 'PATCH',
|
|
222
|
+
uri: 'https://example.com/12345/participant/member1/controls',
|
|
223
|
+
body: {
|
|
224
|
+
role: {
|
|
225
|
+
roles: [
|
|
226
|
+
{
|
|
227
|
+
hasRole: true,
|
|
228
|
+
type: 'MODERATOR',
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
},
|
|
232
|
+
authorizingLocusUrl: 'https://example.com/breakout-locus',
|
|
233
|
+
},
|
|
198
234
|
});
|
|
199
235
|
});
|
|
200
236
|
});
|
|
@@ -226,6 +226,69 @@ describe('plugin-meetings', () => {
|
|
|
226
226
|
});
|
|
227
227
|
});
|
|
228
228
|
|
|
229
|
+
describe('#generateTransferHostMemberOptions', () => {
|
|
230
|
+
it('returns the correct options', () => {
|
|
231
|
+
assert.deepEqual(
|
|
232
|
+
MembersUtil.generateTransferHostMemberOptions('member1', true, 'locusUrl'),
|
|
233
|
+
{
|
|
234
|
+
memberId: 'member1',
|
|
235
|
+
moderator: true,
|
|
236
|
+
locusUrl: 'locusUrl',
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
describe('#getTransferHostToMemberRequestParams', () => {
|
|
243
|
+
it('returns the correct request params without authorizingLocusUrl', () => {
|
|
244
|
+
const options = {
|
|
245
|
+
locusUrl: 'locusUrl',
|
|
246
|
+
memberId: 'member1',
|
|
247
|
+
moderator: true,
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
assert.deepEqual(MembersUtil.getTransferHostToMemberRequestParams(options), {
|
|
251
|
+
method: HTTP_VERBS.PATCH,
|
|
252
|
+
uri: 'locusUrl/participant/member1/controls',
|
|
253
|
+
body: {
|
|
254
|
+
role: {
|
|
255
|
+
roles: [
|
|
256
|
+
{
|
|
257
|
+
hasRole: true,
|
|
258
|
+
type: 'MODERATOR',
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('returns the correct request params with authorizingLocusUrl', () => {
|
|
267
|
+
const options = {
|
|
268
|
+
locusUrl: 'mainLocusUrl',
|
|
269
|
+
memberId: 'member1',
|
|
270
|
+
moderator: true,
|
|
271
|
+
authorizingLocusUrl: 'breakoutLocusUrl',
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
assert.deepEqual(MembersUtil.getTransferHostToMemberRequestParams(options), {
|
|
275
|
+
method: HTTP_VERBS.PATCH,
|
|
276
|
+
uri: 'mainLocusUrl/participant/member1/controls',
|
|
277
|
+
body: {
|
|
278
|
+
role: {
|
|
279
|
+
roles: [
|
|
280
|
+
{
|
|
281
|
+
hasRole: true,
|
|
282
|
+
type: 'MODERATOR',
|
|
283
|
+
},
|
|
284
|
+
],
|
|
285
|
+
},
|
|
286
|
+
authorizingLocusUrl: 'breakoutLocusUrl',
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
|
|
229
292
|
describe('#generateMuteMemberOptions', () => {
|
|
230
293
|
const testOptions = (isAudio) => {
|
|
231
294
|
const memberId = 'bob';
|