@webex/plugin-meetings 1.144.2 → 1.146.1
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/constants.js +4 -2
- package/dist/constants.js.map +1 -1
- package/dist/meeting/index.js +15 -0
- package/dist/meeting/index.js.map +1 -1
- package/dist/members/index.js +63 -0
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +41 -0
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +59 -0
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/index.js +0 -2
- package/dist/metrics/index.js.map +1 -1
- package/dist/roap/handler.js +7 -8
- package/dist/roap/handler.js.map +1 -1
- package/dist/roap/index.js +8 -3
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/state.js +2 -0
- package/dist/roap/state.js.map +1 -1
- package/package.json +5 -5
- package/src/constants.js +1 -0
- package/src/meeting/index.js +13 -0
- package/src/members/index.js +56 -0
- package/src/members/request.js +35 -0
- package/src/members/util.js +58 -1
- package/src/metrics/index.js +0 -2
- package/src/roap/handler.js +7 -8
- package/src/roap/index.js +10 -3
- package/src/roap/state.js +2 -0
- package/test/unit/spec/meeting/index.js +16 -0
- package/test/unit/spec/members/index.js +192 -0
- package/test/unit/spec/members/request.js +101 -0
package/src/members/request.js
CHANGED
|
@@ -73,4 +73,39 @@ export default class MembersRequest extends StatelessWebexPlugin {
|
|
|
73
73
|
|
|
74
74
|
return this.request(requestParams);
|
|
75
75
|
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Sends a request to the DTMF endpoint to send tones
|
|
79
|
+
* @param {Object} options
|
|
80
|
+
* @param {String} options.locusUrl
|
|
81
|
+
* @param {String} options.url device url SIP user
|
|
82
|
+
* @param {String} options.tones a string of one or more DTMF tones to send
|
|
83
|
+
* @param {String} options.memberId ID of PSTN user
|
|
84
|
+
* @returns {Promise}
|
|
85
|
+
*/
|
|
86
|
+
sendDialPadKey(options) {
|
|
87
|
+
if (!options || !options.locusUrl || !options.memberId || !options.url || !options.tones && options.tones !== 0) {
|
|
88
|
+
throw new ParameterError('memberId must be defined, the associated locus url, the device url and DTMF tones for this meeting object must be defined.');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const requestParams = MembersUtil.generateSendDTMFRequestParams(options);
|
|
92
|
+
|
|
93
|
+
return this.request(requestParams);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {Object} options with format of {invitee: string, locusUrl: string}
|
|
98
|
+
* @returns {Promise}
|
|
99
|
+
* @throws {Error} if the options are not valid and complete, must have invitee with emailAddress OR email AND locusUrl
|
|
100
|
+
* @memberof MembersRequest
|
|
101
|
+
*/
|
|
102
|
+
cancelPhoneInvite(options) {
|
|
103
|
+
if (!(options?.invitee?.phoneNumber || options?.locusUrl)) {
|
|
104
|
+
throw new ParameterError('invitee must be passed and the associated locus url for this meeting object must be defined.');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const requestParams = MembersUtil.generateCancelInviteRequestParams(options);
|
|
108
|
+
|
|
109
|
+
return this.request(requestParams);
|
|
110
|
+
}
|
|
76
111
|
}
|
package/src/members/util.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import uuid from 'uuid';
|
|
2
|
+
|
|
1
3
|
import {
|
|
2
4
|
HTTP_VERBS,
|
|
3
5
|
CONTROLS,
|
|
@@ -5,7 +7,9 @@ import {
|
|
|
5
7
|
LEAVE,
|
|
6
8
|
PARTICIPANT,
|
|
7
9
|
VALID_EMAIL_ADDRESS,
|
|
8
|
-
DIALER_REGEX
|
|
10
|
+
DIALER_REGEX,
|
|
11
|
+
SEND_DTMF_ENDPOINT,
|
|
12
|
+
_REMOVE_
|
|
9
13
|
} from '../constants';
|
|
10
14
|
|
|
11
15
|
const MembersUtil = {};
|
|
@@ -156,4 +160,57 @@ MembersUtil.getTransferHostToMemberRequestParams = (options) => {
|
|
|
156
160
|
};
|
|
157
161
|
};
|
|
158
162
|
|
|
163
|
+
MembersUtil.genderateSendDTMFOptions = (url, tones, memberId, locusUrl) => ({
|
|
164
|
+
url,
|
|
165
|
+
tones,
|
|
166
|
+
memberId,
|
|
167
|
+
locusUrl
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
MembersUtil.generateSendDTMFRequestParams = ({
|
|
171
|
+
url, tones, memberId, locusUrl
|
|
172
|
+
}) => {
|
|
173
|
+
const body = {
|
|
174
|
+
device: {
|
|
175
|
+
url
|
|
176
|
+
},
|
|
177
|
+
memberId,
|
|
178
|
+
dtmf: {
|
|
179
|
+
correlationId: uuid.v4(),
|
|
180
|
+
tones,
|
|
181
|
+
direction: 'transmit'
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
const uri = `${locusUrl}/${PARTICIPANT}/${memberId}/${SEND_DTMF_ENDPOINT}`;
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
method: HTTP_VERBS.POST,
|
|
188
|
+
uri,
|
|
189
|
+
body
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
MembersUtil.cancelPhoneInviteOptions = (invitee, locusUrl) => ({
|
|
194
|
+
invitee,
|
|
195
|
+
locusUrl
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
MembersUtil.generateCancelInviteRequestParams = (options) => {
|
|
199
|
+
const body = {
|
|
200
|
+
actionType: _REMOVE_,
|
|
201
|
+
invitees: [
|
|
202
|
+
{
|
|
203
|
+
address: options.invitee.phoneNumber
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
};
|
|
207
|
+
const requestParams = {
|
|
208
|
+
method: HTTP_VERBS.PUT,
|
|
209
|
+
uri: options.locusUrl,
|
|
210
|
+
body
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return requestParams;
|
|
214
|
+
};
|
|
215
|
+
|
|
159
216
|
export default MembersUtil;
|
package/src/metrics/index.js
CHANGED
|
@@ -175,7 +175,6 @@ class Metrics {
|
|
|
175
175
|
eventId: uuid.v4(),
|
|
176
176
|
version: 1,
|
|
177
177
|
origin: {
|
|
178
|
-
buildType: 'prod',
|
|
179
178
|
name: 'endpoint',
|
|
180
179
|
networkType: 'unknown',
|
|
181
180
|
userAgent: this.userAgentToString(),
|
|
@@ -264,7 +263,6 @@ class Metrics {
|
|
|
264
263
|
origin: {
|
|
265
264
|
audioSetupDelay,
|
|
266
265
|
videoSetupDelay,
|
|
267
|
-
buildType: 'prod',
|
|
268
266
|
name: 'endpoint',
|
|
269
267
|
networkType: options.networkType || UNKNOWN,
|
|
270
268
|
userAgent: this.userAgentToString(),
|
package/src/roap/handler.js
CHANGED
|
@@ -192,8 +192,10 @@ export default class RoapHandler extends StatelessWebexPlugin {
|
|
|
192
192
|
handleAction(session, action, meeting, correlationId) {
|
|
193
193
|
let signal;
|
|
194
194
|
|
|
195
|
+
|
|
195
196
|
switch (action.type) {
|
|
196
197
|
case ROAP.RECEIVE_ROAP_MSG:
|
|
198
|
+
LoggerProxy.logger.log(`Roap:handler#handleAction --> RECEIVE_ROAP_MSG event captured, reciving a roap message : ${JSON.stringify(action)}`);
|
|
197
199
|
if (compareWithLastRoapMessage(this.lastRoapMessage, action)) {
|
|
198
200
|
LoggerProxy.logger.warn(`Roap:handler#handleAction --> duplicate roap offer from server: ${action.msg.seq}`);
|
|
199
201
|
}
|
|
@@ -204,18 +206,15 @@ export default class RoapHandler extends StatelessWebexPlugin {
|
|
|
204
206
|
}
|
|
205
207
|
break;
|
|
206
208
|
case ROAP.SEND_ROAP_MSG:
|
|
209
|
+
LoggerProxy.logger.log(`Roap:handler#handleAction --> SEND_ROAP_MSG event captured, sending roap message ${JSON.stringify(action)}`);
|
|
210
|
+
|
|
207
211
|
action.local = true;
|
|
208
212
|
this.execute(signal, session, action, meeting, ROAP.TX_);
|
|
209
213
|
break;
|
|
210
214
|
case ROAP.SEND_ROAP_MSG_SUCCESS:
|
|
211
|
-
//
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
// NOTE: When server send back an answer via mercury the
|
|
215
|
-
// remote SDP is already saved sent and ok message is sent back
|
|
216
|
-
// We dont have to indicate the roapHandler about the RX_ANSWER via SEND_ROAP_MSG_SUCCESS
|
|
217
|
-
// RoapHandler.transition(signal, session, meeting);
|
|
218
|
-
}
|
|
215
|
+
// NOTE: When server send back an answer via mercury the
|
|
216
|
+
// remote SDP is already saved sent and ok message is sent back
|
|
217
|
+
// We dont have to indicate the roapHandler about the RX_ANSWER via SEND_ROAP_MSG_SUCCESS
|
|
219
218
|
break;
|
|
220
219
|
case ROAP.RECEIVE_CALL_LEAVE:
|
|
221
220
|
RoapCollection.deleteSession(correlationId);
|
package/src/roap/index.js
CHANGED
|
@@ -174,6 +174,12 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
174
174
|
seq: options.seq
|
|
175
175
|
};
|
|
176
176
|
|
|
177
|
+
this.roapHandler.submit({
|
|
178
|
+
type: ROAP.SEND_ROAP_MSG,
|
|
179
|
+
msg: roapMessage,
|
|
180
|
+
correlationId: options.correlationId
|
|
181
|
+
});
|
|
182
|
+
|
|
177
183
|
return this.roapRequest
|
|
178
184
|
.sendRoap({
|
|
179
185
|
roapMessage,
|
|
@@ -186,10 +192,11 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
186
192
|
})
|
|
187
193
|
.then(() => {
|
|
188
194
|
meeting.setRoapSeq(options.seq);
|
|
195
|
+
|
|
189
196
|
this.roapHandler.submit({
|
|
190
|
-
type: ROAP.
|
|
191
|
-
|
|
192
|
-
correlationId:
|
|
197
|
+
type: ROAP.SEND_ROAP_MSG_SUCCESS,
|
|
198
|
+
seq: roapMessage.seq,
|
|
199
|
+
correlationId: meeting.correlationId
|
|
193
200
|
});
|
|
194
201
|
});
|
|
195
202
|
}
|
package/src/roap/state.js
CHANGED
|
@@ -25,6 +25,8 @@ const shouldStep = (roap, meeting) => {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
const handleTransition = (value, signal, meeting) => {
|
|
28
|
+
LoggerProxy.logger.log(`Roap:state#handleTransition --> current ${value} to ${signal}`);
|
|
29
|
+
|
|
28
30
|
switch (value) {
|
|
29
31
|
case ROAP.ROAP_STATE.INIT:
|
|
30
32
|
if (signal === ROAP.ROAP_SIGNAL.RX_OFFER) {
|
|
@@ -186,6 +186,22 @@ describe('plugin-meetings', () => {
|
|
|
186
186
|
assert.calledWith(meeting.members.addMember, uuid1, false);
|
|
187
187
|
});
|
|
188
188
|
});
|
|
189
|
+
describe('#cancelPhoneInvite', () => {
|
|
190
|
+
it('should have #invite', () => {
|
|
191
|
+
assert.exists(meeting.cancelPhoneInvite);
|
|
192
|
+
});
|
|
193
|
+
beforeEach(() => {
|
|
194
|
+
meeting.members.cancelPhoneInvite = sinon.stub().returns(Promise.resolve(test1));
|
|
195
|
+
});
|
|
196
|
+
it('should proxy members #cancelPhoneInvite and return a promise', async () => {
|
|
197
|
+
const cancel = meeting.cancelPhoneInvite(uuid1);
|
|
198
|
+
|
|
199
|
+
assert.exists(cancel.then);
|
|
200
|
+
await cancel;
|
|
201
|
+
assert.calledOnce(meeting.members.cancelPhoneInvite);
|
|
202
|
+
assert.calledWith(meeting.members.cancelPhoneInvite, uuid1);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
189
205
|
describe('#admit', () => {
|
|
190
206
|
it('should have #admit', () => {
|
|
191
207
|
assert.exists(meeting.admit);
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import sinon from 'sinon';
|
|
6
|
+
import uuid from 'uuid';
|
|
7
|
+
import chai from 'chai';
|
|
8
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
9
|
+
import {Credentials} from '@webex/webex-core';
|
|
10
|
+
import Support from '@webex/internal-plugin-support';
|
|
11
|
+
import MockWebex from '@webex/test-helper-mock-webex';
|
|
12
|
+
import Meetings from '@webex/plugin-meetings';
|
|
13
|
+
import Members from '@webex/plugin-meetings/src/members';
|
|
14
|
+
import MembersUtil from '@webex/plugin-meetings/src/members/util';
|
|
15
|
+
|
|
16
|
+
const {assert} = chai;
|
|
17
|
+
|
|
18
|
+
chai.use(chaiAsPromised);
|
|
19
|
+
sinon.assert.expose(chai.assert, {prefix: ''});
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
describe('plugin-meetings', () => {
|
|
23
|
+
let webex;
|
|
24
|
+
let url1;
|
|
25
|
+
const fakeMembersCollection = {
|
|
26
|
+
test1: {
|
|
27
|
+
namespace: 'Meetings',
|
|
28
|
+
participant: {
|
|
29
|
+
state: 'JOINED',
|
|
30
|
+
type: 'USER',
|
|
31
|
+
person: {
|
|
32
|
+
id: '6eb08f8b-bf69-3251-a126-b161bead2d21',
|
|
33
|
+
phoneNumber: '+18578675309',
|
|
34
|
+
isExternal: true,
|
|
35
|
+
primaryDisplayString: '+18578675309'
|
|
36
|
+
},
|
|
37
|
+
devices: [
|
|
38
|
+
{
|
|
39
|
+
url: 'https://fakeURL.com',
|
|
40
|
+
deviceType: 'SIP',
|
|
41
|
+
state: 'JOINED',
|
|
42
|
+
intents: [
|
|
43
|
+
null
|
|
44
|
+
],
|
|
45
|
+
correlationId: '1234',
|
|
46
|
+
provisionalUrl: 'dialout:///fake',
|
|
47
|
+
isSparkPstn: true
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
url: 'dialout:///fakeagain',
|
|
51
|
+
deviceType: 'PROVISIONAL',
|
|
52
|
+
state: 'JOINED',
|
|
53
|
+
intents: [
|
|
54
|
+
null
|
|
55
|
+
],
|
|
56
|
+
correlationId: '4321',
|
|
57
|
+
isVideoCallback: false,
|
|
58
|
+
clientUrl: 'https://fakeURL',
|
|
59
|
+
provisionalType: 'DIAL_OUT_ONLY',
|
|
60
|
+
dialingStatus: 'SUCCESS'
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
status: {
|
|
64
|
+
audioStatus: 'SENDRECV',
|
|
65
|
+
videoStatus: 'INACTIVE'
|
|
66
|
+
},
|
|
67
|
+
id: 'abc-123-abc-123',
|
|
68
|
+
guest: true,
|
|
69
|
+
resourceGuest: false,
|
|
70
|
+
moderator: false,
|
|
71
|
+
panelist: false,
|
|
72
|
+
moveToLobbyNotAllowed: true,
|
|
73
|
+
deviceUrl: 'https://fakeDeviceurl'
|
|
74
|
+
},
|
|
75
|
+
id: 'abc-123-abc-123',
|
|
76
|
+
status: 'IN_MEETING',
|
|
77
|
+
type: 'MEETING',
|
|
78
|
+
isModerator: false
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
describe('members', () => {
|
|
84
|
+
const sandbox = sinon.createSandbox();
|
|
85
|
+
let createMembers;
|
|
86
|
+
|
|
87
|
+
beforeEach(() => {
|
|
88
|
+
webex = new MockWebex({
|
|
89
|
+
children: {
|
|
90
|
+
meetings: Meetings,
|
|
91
|
+
credentials: Credentials,
|
|
92
|
+
support: Support
|
|
93
|
+
},
|
|
94
|
+
config: {
|
|
95
|
+
credentials: {
|
|
96
|
+
client_id: 'mock-client-id'
|
|
97
|
+
},
|
|
98
|
+
meetings: {
|
|
99
|
+
reconnection: {
|
|
100
|
+
enabled: false
|
|
101
|
+
},
|
|
102
|
+
mediaSettings: {},
|
|
103
|
+
metrics: {},
|
|
104
|
+
stats: {}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
url1 = `https://example.com/${uuid.v4()}`;
|
|
110
|
+
|
|
111
|
+
createMembers = (options) => new Members({locusUrl: options.url}, {parent: webex});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
afterEach(() => {
|
|
115
|
+
sandbox.restore();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('#addMembers', () => {
|
|
119
|
+
it('should invoke isInvalidInvitee and generateAddMemberOptions from MembersUtil when addMember is called with valid params', async () => {
|
|
120
|
+
sandbox.spy(MembersUtil, 'isInvalidInvitee');
|
|
121
|
+
sandbox.spy(MembersUtil, 'generateAddMemberOptions');
|
|
122
|
+
|
|
123
|
+
const members = createMembers({url: url1});
|
|
124
|
+
|
|
125
|
+
await members.addMember({phoneNumber: '+18578675309'});
|
|
126
|
+
assert.calledOnce(MembersUtil.isInvalidInvitee);
|
|
127
|
+
assert.calledOnce(MembersUtil.generateAddMemberOptions);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should throw a rejection if there is no locus url', async () => {
|
|
131
|
+
const members = createMembers({url: false});
|
|
132
|
+
|
|
133
|
+
assert.isRejected(members.addMember({email: 'test@cisco.com'}));
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe('#sendDialPadKey', () => {
|
|
138
|
+
it('should throw a rejection when calling sendDialPadKey with no tones', async () => {
|
|
139
|
+
const members = createMembers({url: url1});
|
|
140
|
+
|
|
141
|
+
assert.isRejected(members.sendDialPadKey());
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should throw a rejection when calling sendDialPadKey with no member is found', async () => {
|
|
145
|
+
const members = createMembers({url: url1});
|
|
146
|
+
|
|
147
|
+
assert.isRejected(members.sendDialPadKey('1', '1234'));
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('should call genderateSendDTMFOptions with proper options on Members util if we the member is valid', async () => {
|
|
151
|
+
sandbox.spy(MembersUtil, 'genderateSendDTMFOptions');
|
|
152
|
+
const members = createMembers({url: url1});
|
|
153
|
+
|
|
154
|
+
members.membersCollection.setAll(fakeMembersCollection);
|
|
155
|
+
await members.sendDialPadKey('1', 'test1');
|
|
156
|
+
assert.calledWith(MembersUtil.genderateSendDTMFOptions, 'https://fakeURL.com', '1', 'test1', url1);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should call the sendDialPadKey method on membersRequest if the member is valid', async () => {
|
|
160
|
+
const members = createMembers({url: url1});
|
|
161
|
+
|
|
162
|
+
const {membersRequest} = members;
|
|
163
|
+
|
|
164
|
+
assert.exists(membersRequest);
|
|
165
|
+
const sendDialPadKeyspy = sandbox.spy(membersRequest, 'sendDialPadKey');
|
|
166
|
+
|
|
167
|
+
members.membersCollection.setAll(fakeMembersCollection);
|
|
168
|
+
await members.sendDialPadKey('1', 'test1');
|
|
169
|
+
assert.calledOnce(sendDialPadKeyspy);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('#cancelPhoneInvite', () => {
|
|
174
|
+
it('should invoke isInvalidInvitee and generateAddMemberOptions from MembersUtil when addMember is called with valid params', async () => {
|
|
175
|
+
sandbox.spy(MembersUtil, 'isInvalidInvitee');
|
|
176
|
+
sandbox.spy(MembersUtil, 'cancelPhoneInviteOptions');
|
|
177
|
+
|
|
178
|
+
const members = createMembers({url: url1});
|
|
179
|
+
|
|
180
|
+
await members.cancelPhoneInvite({phoneNumber: '+18578675309'});
|
|
181
|
+
assert.calledOnce(MembersUtil.isInvalidInvitee);
|
|
182
|
+
assert.calledOnce(MembersUtil.cancelPhoneInviteOptions);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('should throw a rejection if there is no locus url', async () => {
|
|
186
|
+
const members = createMembers({url: false});
|
|
187
|
+
|
|
188
|
+
assert.isRejected(members.cancelPhoneInvite({phoneNumber: '+18578675309'}));
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
});
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import sinon from 'sinon';
|
|
2
|
+
import chai from 'chai';
|
|
3
|
+
import uuid from 'uuid';
|
|
4
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
5
|
+
import MockWebex from '@webex/test-helper-mock-webex';
|
|
6
|
+
import Meetings from '@webex/plugin-meetings';
|
|
7
|
+
import MembersRequest from '@webex/plugin-meetings/src/members/request';
|
|
8
|
+
|
|
9
|
+
const {assert} = chai;
|
|
10
|
+
|
|
11
|
+
chai.use(chaiAsPromised);
|
|
12
|
+
sinon.assert.expose(chai.assert, {prefix: ''});
|
|
13
|
+
|
|
14
|
+
describe('plugin-meetings', () => {
|
|
15
|
+
let membersRequest;
|
|
16
|
+
let url1;
|
|
17
|
+
let sandbox;
|
|
18
|
+
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
const webex = new MockWebex({
|
|
21
|
+
children: {
|
|
22
|
+
meetings: Meetings
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
sandbox = sinon.createSandbox();
|
|
27
|
+
|
|
28
|
+
url1 = `https://example.com/${uuid.v4()}`;
|
|
29
|
+
|
|
30
|
+
membersRequest = new MembersRequest({}, {
|
|
31
|
+
parent: webex
|
|
32
|
+
});
|
|
33
|
+
membersRequest.request = sinon.mock().returns(Promise.resolve({}));
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
sandbox.restore();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
describe('members request library', () => {
|
|
42
|
+
describe('#sendDialPadKey', () => {
|
|
43
|
+
it('sends a POST to the sendDtmf locus endpoint', async () => {
|
|
44
|
+
const locusUrl = url1;
|
|
45
|
+
const url = 'https://fakedeviceurl.com';
|
|
46
|
+
const tones = '1';
|
|
47
|
+
const memberId = 'test1';
|
|
48
|
+
|
|
49
|
+
await membersRequest.sendDialPadKey({
|
|
50
|
+
url,
|
|
51
|
+
tones,
|
|
52
|
+
memberId,
|
|
53
|
+
locusUrl
|
|
54
|
+
});
|
|
55
|
+
const requestParams = membersRequest.request.getCall(0).args[0];
|
|
56
|
+
|
|
57
|
+
assert.equal(requestParams.method, 'POST');
|
|
58
|
+
assert.equal(requestParams.uri, `${locusUrl}/participant/${memberId}/sendDtmf`);
|
|
59
|
+
assert.equal(requestParams.body.dtmf.tones, tones);
|
|
60
|
+
assert.equal(requestParams.body.device.url, url);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('#addMembers', () => {
|
|
65
|
+
it('sends a PUT to the locus endpoint', async () => {
|
|
66
|
+
const options = {
|
|
67
|
+
invitee: {
|
|
68
|
+
phoneNumber: '+18578675309'
|
|
69
|
+
},
|
|
70
|
+
locusUrl: url1
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
await membersRequest.addMembers(options);
|
|
74
|
+
const requestParams = membersRequest.request.getCall(0).args[0];
|
|
75
|
+
|
|
76
|
+
assert.equal(requestParams.method, 'PUT');
|
|
77
|
+
assert.equal(requestParams.uri, url1);
|
|
78
|
+
assert.equal(requestParams.body.invitees[0].address, '+18578675309');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe('#cancelPhoneInvite', () => {
|
|
83
|
+
it('sends a PUT to the locus endpoint', async () => {
|
|
84
|
+
const options = {
|
|
85
|
+
invitee: {
|
|
86
|
+
phoneNumber: '+18578675309'
|
|
87
|
+
},
|
|
88
|
+
locusUrl: url1
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
await membersRequest.cancelPhoneInvite(options);
|
|
92
|
+
const requestParams = membersRequest.request.getCall(0).args[0];
|
|
93
|
+
|
|
94
|
+
assert.equal(requestParams.method, 'PUT');
|
|
95
|
+
assert.equal(requestParams.uri, url1);
|
|
96
|
+
assert.equal(requestParams.body.invitees[0].address, '+18578675309');
|
|
97
|
+
assert.equal(requestParams.body.actionType, 'REMOVE');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
});
|