@webex/plugin-memberships 2.59.2 → 2.59.3-next.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/.eslintrc.js +6 -6
- package/README.md +50 -50
- package/babel.config.js +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/memberships.js +297 -297
- package/dist/memberships.js.map +1 -1
- package/jest.config.js +3 -3
- package/package.json +20 -19
- package/process +1 -1
- package/src/index.js +14 -14
- package/src/memberships.js +654 -654
- package/test/integration/spec/memberships.js +854 -854
|
@@ -1,854 +1,854 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import '@webex/plugin-logger';
|
|
6
|
-
import '@webex/plugin-messages';
|
|
7
|
-
import '@webex/plugin-memberships';
|
|
8
|
-
import '@webex/plugin-people';
|
|
9
|
-
import '@webex/plugin-rooms';
|
|
10
|
-
import WebexCore from '@webex/webex-core';
|
|
11
|
-
import {SDK_EVENT, hydraTypes, constructHydraId} from '@webex/common';
|
|
12
|
-
import {assert} from '@webex/test-helper-chai';
|
|
13
|
-
import sinon from 'sinon';
|
|
14
|
-
import testUsers from '@webex/test-helper-test-users';
|
|
15
|
-
|
|
16
|
-
const debug = require('debug')('memberships');
|
|
17
|
-
|
|
18
|
-
describe('plugin-memberships', function () {
|
|
19
|
-
this.timeout(60000);
|
|
20
|
-
|
|
21
|
-
let webex, user, actor;
|
|
22
|
-
|
|
23
|
-
before(() =>
|
|
24
|
-
testUsers.create({count: 1}).then(([u]) => {
|
|
25
|
-
user = u;
|
|
26
|
-
webex = new WebexCore({credentials: user.token});
|
|
27
|
-
webex.people.get('me').then((person) => {
|
|
28
|
-
actor = person;
|
|
29
|
-
debug('SDK User (Actor) for tests:');
|
|
30
|
-
debug(`- name: ${actor.displayName}`);
|
|
31
|
-
debug(`- id: ${actor.id}`);
|
|
32
|
-
});
|
|
33
|
-
})
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
describe('#memberships', () => {
|
|
37
|
-
let user1;
|
|
38
|
-
|
|
39
|
-
before(() =>
|
|
40
|
-
testUsers.create({count: 1}).then((users) => {
|
|
41
|
-
user1 = users[0];
|
|
42
|
-
debug('User that memberships are created for:');
|
|
43
|
-
debug(`- name: ${user1.displayName}`);
|
|
44
|
-
debug(`- id: ${constructHydraId(hydraTypes.PEOPLE, user1.id)}`);
|
|
45
|
-
})
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
let room;
|
|
49
|
-
|
|
50
|
-
beforeEach(() =>
|
|
51
|
-
webex.rooms.create({title: 'Webex Test Room'}).then((r) => {
|
|
52
|
-
debug('Created Cisco Test Room');
|
|
53
|
-
room = r;
|
|
54
|
-
})
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
afterEach(() => {
|
|
58
|
-
webex.memberships.stopListening();
|
|
59
|
-
webex.memberships.off('created');
|
|
60
|
-
webex.memberships.off('updated');
|
|
61
|
-
webex.memberships.off('deleted');
|
|
62
|
-
webex.memberships.off('seen');
|
|
63
|
-
webex.rooms
|
|
64
|
-
.remove(room)
|
|
65
|
-
.catch((e) => webex.logger.error(`Failed to clean up after unit test: ${e}`));
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
describe('#create()', () => {
|
|
69
|
-
it('creates a membership by user id', () =>
|
|
70
|
-
webex.memberships
|
|
71
|
-
.create({
|
|
72
|
-
roomId: room.id,
|
|
73
|
-
personId: user1.id,
|
|
74
|
-
})
|
|
75
|
-
.then((membership) => {
|
|
76
|
-
assert.isMembership(membership);
|
|
77
|
-
}));
|
|
78
|
-
|
|
79
|
-
it('creates a membership by user email', () => {
|
|
80
|
-
const created = new Promise((resolve) => {
|
|
81
|
-
webex.memberships.on('created', (event) => {
|
|
82
|
-
debug('membership:created event handler for membership by email test called');
|
|
83
|
-
resolve(event);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
return webex.memberships.listen().then(() =>
|
|
88
|
-
webex.memberships
|
|
89
|
-
.create({
|
|
90
|
-
roomId: room.id,
|
|
91
|
-
personEmail: user1.email,
|
|
92
|
-
})
|
|
93
|
-
.then(async (membership) => {
|
|
94
|
-
validateMembership(membership);
|
|
95
|
-
const event = await created;
|
|
96
|
-
|
|
97
|
-
validateMembershipEvent(event, membership, actor);
|
|
98
|
-
})
|
|
99
|
-
);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('creates a membership and sets moderator status', () => {
|
|
103
|
-
// "Creating" a member as a moderator actually generates
|
|
104
|
-
// two events, first a created event (with non-moderator status)
|
|
105
|
-
// followed by an updated event with isModerator set to true
|
|
106
|
-
const created = new Promise((resolve) => {
|
|
107
|
-
webex.memberships.on('created', (event) => {
|
|
108
|
-
debug('membership:created event handler for moderator test called');
|
|
109
|
-
resolve(event);
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
const updated = new Promise((resolve) => {
|
|
113
|
-
webex.memberships.on('updated', (event) => {
|
|
114
|
-
debug('membership:updated event handler for moderator test called');
|
|
115
|
-
|
|
116
|
-
if (event.data.personId === actor.id) {
|
|
117
|
-
debug(
|
|
118
|
-
'Setting a member to moderator implicitly sets the ' +
|
|
119
|
-
'caller of the API to moderator as well. In this test we ' +
|
|
120
|
-
'will ignore this event'
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
resolve(event);
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
return webex.memberships.listen().then(() =>
|
|
130
|
-
webex.memberships
|
|
131
|
-
.create({
|
|
132
|
-
roomId: room.id,
|
|
133
|
-
personId: user1.id,
|
|
134
|
-
isModerator: true,
|
|
135
|
-
})
|
|
136
|
-
.then(async (m) => {
|
|
137
|
-
const membership = m;
|
|
138
|
-
|
|
139
|
-
validateMembership(membership, true);
|
|
140
|
-
const event = await created;
|
|
141
|
-
|
|
142
|
-
// We expect the isModerator status to be false on create
|
|
143
|
-
membership.isModerator = false;
|
|
144
|
-
validateMembershipEvent(event, membership, actor);
|
|
145
|
-
|
|
146
|
-
const event2 = await updated;
|
|
147
|
-
|
|
148
|
-
// We expect the isModerator status to be false on create
|
|
149
|
-
membership.isModerator = true;
|
|
150
|
-
validateMembershipEvent(event2, membership, actor);
|
|
151
|
-
})
|
|
152
|
-
);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('creates a space and memberships simultaniously', () => {
|
|
156
|
-
// "Creating" a space with users generates a unique event
|
|
157
|
-
// activity object shape via the client that contains
|
|
158
|
-
// multiple "participants". There isn't a documented
|
|
159
|
-
// way to perform this action via the API with more than
|
|
160
|
-
// one user at the time of edit.
|
|
161
|
-
const created = new Promise((resolve) => {
|
|
162
|
-
webex.memberships.on('created', (event) => {
|
|
163
|
-
debug('membership:created event handler for new space test called');
|
|
164
|
-
resolve(event);
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
return (
|
|
169
|
-
webex.memberships
|
|
170
|
-
.listen()
|
|
171
|
-
// Cleanup current room, we need to catch the event when it's created.
|
|
172
|
-
.then(() => webex.rooms.remove(room))
|
|
173
|
-
// Create a room to trigger created event.
|
|
174
|
-
.then(() => webex.rooms.create({title: 'Webex Test Room'}))
|
|
175
|
-
// Store new room object and get the memberships of the room.
|
|
176
|
-
.then((r) => {
|
|
177
|
-
room = r;
|
|
178
|
-
|
|
179
|
-
return webex.memberships.list({roomId: room.id});
|
|
180
|
-
})
|
|
181
|
-
// validate data
|
|
182
|
-
.then(async ({items: [membership]}) => {
|
|
183
|
-
const event = await created;
|
|
184
|
-
|
|
185
|
-
validateMembership(membership, false);
|
|
186
|
-
validateMembershipEvent(event, membership, actor);
|
|
187
|
-
})
|
|
188
|
-
);
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
describe('#get()', () => {
|
|
193
|
-
let membership;
|
|
194
|
-
|
|
195
|
-
before(() =>
|
|
196
|
-
// this could be in parallel once KMS always sends new keys
|
|
197
|
-
webex.rooms
|
|
198
|
-
.create({title: 'Membership A'})
|
|
199
|
-
.then((room) => Promise.all([room, webex.rooms.create({title: 'Membership B'})]))
|
|
200
|
-
.then((rooms) => {
|
|
201
|
-
const room = rooms[0];
|
|
202
|
-
|
|
203
|
-
return webex.memberships.create({
|
|
204
|
-
roomId: room.id,
|
|
205
|
-
personId: user1.id,
|
|
206
|
-
});
|
|
207
|
-
})
|
|
208
|
-
.then((m) => {
|
|
209
|
-
membership = m;
|
|
210
|
-
})
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
it('retrieves a single membership', () =>
|
|
214
|
-
webex.memberships.get(membership).then((m) => {
|
|
215
|
-
assert.deepEqual(m, membership);
|
|
216
|
-
}));
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
describe('#list()', () => {
|
|
220
|
-
let room;
|
|
221
|
-
|
|
222
|
-
before(() =>
|
|
223
|
-
// this could be in parallel once KMS always sends new keys
|
|
224
|
-
webex.rooms
|
|
225
|
-
.create({title: 'Membership A'})
|
|
226
|
-
.then((room) => Promise.all([room, webex.rooms.create({title: 'Membership B'})]))
|
|
227
|
-
.then((rooms) => {
|
|
228
|
-
room = rooms[0];
|
|
229
|
-
|
|
230
|
-
return webex.memberships.create({
|
|
231
|
-
roomId: room.id,
|
|
232
|
-
personId: user1.id,
|
|
233
|
-
});
|
|
234
|
-
})
|
|
235
|
-
);
|
|
236
|
-
|
|
237
|
-
it('retrieves all memberships for a room', () =>
|
|
238
|
-
webex.memberships.list({roomId: room.id}).then((memberships) => {
|
|
239
|
-
assert.isDefined(memberships);
|
|
240
|
-
assert.isAbove(memberships.length, 0);
|
|
241
|
-
for (const membership of memberships) {
|
|
242
|
-
assert.isMembership(membership);
|
|
243
|
-
assert.equal(membership.roomId, room.id);
|
|
244
|
-
}
|
|
245
|
-
}));
|
|
246
|
-
|
|
247
|
-
it('retrieves a bounded set of memberships for a room', () => {
|
|
248
|
-
const spy = sinon.spy();
|
|
249
|
-
|
|
250
|
-
return webex.memberships
|
|
251
|
-
.list({roomId: room.id, max: 1})
|
|
252
|
-
.then((memberships) => {
|
|
253
|
-
assert.lengthOf(memberships, 1);
|
|
254
|
-
|
|
255
|
-
return (function f(page) {
|
|
256
|
-
for (const membership of page) {
|
|
257
|
-
spy(membership.id);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (page.hasNext()) {
|
|
261
|
-
return page.next().then(f);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return Promise.resolve();
|
|
265
|
-
})(memberships);
|
|
266
|
-
})
|
|
267
|
-
.then(() => {
|
|
268
|
-
assert.calledTwice(spy);
|
|
269
|
-
});
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
it('retrieves all room memberships for a user', () =>
|
|
273
|
-
webex.memberships
|
|
274
|
-
.list({
|
|
275
|
-
personId: user.id,
|
|
276
|
-
roomId: room.id,
|
|
277
|
-
})
|
|
278
|
-
.then((memberships) => {
|
|
279
|
-
const membership = memberships.items[0];
|
|
280
|
-
|
|
281
|
-
return webex.memberships
|
|
282
|
-
.list({
|
|
283
|
-
personEmail: user.email,
|
|
284
|
-
})
|
|
285
|
-
.then((memberships) => {
|
|
286
|
-
assert.isDefined(memberships);
|
|
287
|
-
assert.isAbove(memberships.length, 0);
|
|
288
|
-
for (const membership of memberships) {
|
|
289
|
-
assert.isMembership(membership);
|
|
290
|
-
assert.equal(membership.personEmail, user.email);
|
|
291
|
-
}
|
|
292
|
-
assert.deepInclude(memberships.items, membership);
|
|
293
|
-
});
|
|
294
|
-
}));
|
|
295
|
-
|
|
296
|
-
it('retrieves a bounded set of memberships for a user', () => {
|
|
297
|
-
const spy = sinon.spy();
|
|
298
|
-
|
|
299
|
-
return webex.memberships
|
|
300
|
-
.list({personId: user.id, max: 1})
|
|
301
|
-
.then((memberships) => {
|
|
302
|
-
assert.lengthOf(memberships, 1);
|
|
303
|
-
|
|
304
|
-
return (function f(page) {
|
|
305
|
-
for (const membership of page) {
|
|
306
|
-
assert.equal(membership.personEmail, user.email);
|
|
307
|
-
spy(membership.id);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
if (page.hasNext()) {
|
|
311
|
-
return page.next().then(f);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
return Promise.resolve();
|
|
315
|
-
})(memberships);
|
|
316
|
-
})
|
|
317
|
-
.then(() => {
|
|
318
|
-
assert.isAbove(spy.callCount, 0);
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
describe('#listWithReadStatus()', () => {
|
|
324
|
-
let room;
|
|
325
|
-
|
|
326
|
-
before(() => {
|
|
327
|
-
// Create a new SDK instance so the 2nd user can post a message
|
|
328
|
-
user1.webex = new WebexCore({credentials: user1.token});
|
|
329
|
-
|
|
330
|
-
// Setup a space with both users
|
|
331
|
-
return webex.rooms
|
|
332
|
-
.create({title: 'Membership A'})
|
|
333
|
-
.then((room) => Promise.all([room, webex.rooms.create({title: 'Membership B'})]))
|
|
334
|
-
.then((rooms) => {
|
|
335
|
-
room = rooms[0];
|
|
336
|
-
|
|
337
|
-
return webex.memberships.create({
|
|
338
|
-
roomId: room.id,
|
|
339
|
-
personId: user1.id,
|
|
340
|
-
});
|
|
341
|
-
});
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
it('retrieves memberships with read status for a room that has not been visited', () =>
|
|
345
|
-
webex.memberships.listWithReadStatus({roomId: room.id}).then((memberships) => {
|
|
346
|
-
assert.isDefined(memberships);
|
|
347
|
-
assert.equal(memberships.items.length, 2);
|
|
348
|
-
for (const membership of memberships.items) {
|
|
349
|
-
if (membership.personId !== actor.id) {
|
|
350
|
-
assert.notExists(
|
|
351
|
-
membership.lastSeenId,
|
|
352
|
-
'no lastSeenId for a room that has never been visited'
|
|
353
|
-
);
|
|
354
|
-
assert.notExists(
|
|
355
|
-
membership.lastSeenDate,
|
|
356
|
-
'no lastSeenDate for a room that has never been visited'
|
|
357
|
-
);
|
|
358
|
-
}
|
|
359
|
-
assert.equal(membership.roomId, room.id);
|
|
360
|
-
}
|
|
361
|
-
}));
|
|
362
|
-
|
|
363
|
-
it('validates read status activity after other user posts a message', () =>
|
|
364
|
-
user1.webex.messages
|
|
365
|
-
.create({
|
|
366
|
-
roomId: room.id,
|
|
367
|
-
text: 'Message to create activity for other member',
|
|
368
|
-
})
|
|
369
|
-
.then(() =>
|
|
370
|
-
webex.memberships.listWithReadStatus({roomId: room.id}).then((memberships) => {
|
|
371
|
-
assert.isDefined(memberships);
|
|
372
|
-
assert.equal(memberships.items.length, 2);
|
|
373
|
-
for (const membership of memberships.items) {
|
|
374
|
-
assert.exists(
|
|
375
|
-
membership.lastSeenId,
|
|
376
|
-
'lastSeenId exists in a room that has been visited'
|
|
377
|
-
);
|
|
378
|
-
assert.exists(
|
|
379
|
-
membership.lastSeenDate,
|
|
380
|
-
'lastSeenDate exists in a room that has been visited'
|
|
381
|
-
);
|
|
382
|
-
assert.equal(membership.roomId, room.id);
|
|
383
|
-
// listWithReadStatus does not include created
|
|
384
|
-
// fudge it here so we can validate all the other fields
|
|
385
|
-
membership.created = 'foo';
|
|
386
|
-
assert.isMembership(membership);
|
|
387
|
-
}
|
|
388
|
-
})
|
|
389
|
-
));
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
describe('#update()', () => {
|
|
393
|
-
let membership, sdkMember, room;
|
|
394
|
-
|
|
395
|
-
before(() => {
|
|
396
|
-
// Before setting another user to moderator
|
|
397
|
-
// We will set the test user to moderator
|
|
398
|
-
// and wait for the expected events to arive
|
|
399
|
-
const updated = new Promise((resolve) => {
|
|
400
|
-
webex.memberships.on('updated', (event) => {
|
|
401
|
-
debug('membership:updated event handler for update test called');
|
|
402
|
-
webex.memberships.stopListening(); // disable this callback after test
|
|
403
|
-
webex.memberships.off('updated');
|
|
404
|
-
resolve(event);
|
|
405
|
-
});
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
const roomUpdated = new Promise((resolve) => {
|
|
409
|
-
webex.rooms.on('updated', (event) => {
|
|
410
|
-
debug('rooms:updated event handler for update test called');
|
|
411
|
-
webex.rooms.stopListening(); // disable this callback after test
|
|
412
|
-
webex.rooms.off('updated');
|
|
413
|
-
resolve(event);
|
|
414
|
-
});
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
return webex.memberships
|
|
418
|
-
.listen()
|
|
419
|
-
.then(() => webex.rooms.listen())
|
|
420
|
-
.then(() =>
|
|
421
|
-
webex.rooms
|
|
422
|
-
.create({title: 'Membership E'})
|
|
423
|
-
.then((r) => {
|
|
424
|
-
room = r;
|
|
425
|
-
debug(`Room under test ID: ${room.id}`);
|
|
426
|
-
|
|
427
|
-
// First get the SDK users membership
|
|
428
|
-
return webex.memberships.list({
|
|
429
|
-
roomId: room.id,
|
|
430
|
-
personId: actor.id,
|
|
431
|
-
});
|
|
432
|
-
})
|
|
433
|
-
.then((membershipList) => {
|
|
434
|
-
assert.isArray(
|
|
435
|
-
membershipList.items,
|
|
436
|
-
'membership list not returned after room creation'
|
|
437
|
-
);
|
|
438
|
-
assert.equal(
|
|
439
|
-
membershipList.items.length,
|
|
440
|
-
1,
|
|
441
|
-
'SDK Test user not a member of room just created'
|
|
442
|
-
);
|
|
443
|
-
sdkMember = membershipList.items[0];
|
|
444
|
-
|
|
445
|
-
validateMembership(sdkMember);
|
|
446
|
-
sdkMember.isModerator = true;
|
|
447
|
-
|
|
448
|
-
// Then update the SDK user to a moderator
|
|
449
|
-
return webex.memberships.update(sdkMember);
|
|
450
|
-
})
|
|
451
|
-
.then(async (m) => {
|
|
452
|
-
debug('SDK User is now moderator. Wait for events');
|
|
453
|
-
validateMembership(m, true);
|
|
454
|
-
const event = await updated;
|
|
455
|
-
|
|
456
|
-
validateMembershipEvent(event, m, actor);
|
|
457
|
-
const roomUpdatedEvent = await roomUpdated;
|
|
458
|
-
|
|
459
|
-
return Promise.resolve(roomUpdatedEvent);
|
|
460
|
-
})
|
|
461
|
-
.then((roomUpdatedEvent) => {
|
|
462
|
-
// Check that the expected rooms:updated event matches
|
|
463
|
-
// what we expect when a room is first moderated
|
|
464
|
-
validateRoomsUpdatedEvent(
|
|
465
|
-
roomUpdatedEvent,
|
|
466
|
-
room,
|
|
467
|
-
/* expected value of isLocked */ true
|
|
468
|
-
);
|
|
469
|
-
|
|
470
|
-
// Finally, create the user for our test
|
|
471
|
-
return webex.memberships.create({
|
|
472
|
-
roomId: room.id,
|
|
473
|
-
personId: user1.id,
|
|
474
|
-
});
|
|
475
|
-
})
|
|
476
|
-
.then((m) => {
|
|
477
|
-
debug('User 1 Membership created in Membership E');
|
|
478
|
-
membership = m;
|
|
479
|
-
validateMembership(membership);
|
|
480
|
-
})
|
|
481
|
-
.catch((e) => debug(`membership failed: ${e}`))
|
|
482
|
-
);
|
|
483
|
-
});
|
|
484
|
-
|
|
485
|
-
after(() => {
|
|
486
|
-
// Before deleting the test space
|
|
487
|
-
// We will unset the test user to moderator
|
|
488
|
-
// and wait for the expected events to arive
|
|
489
|
-
const updated = new Promise((resolve) => {
|
|
490
|
-
webex.memberships.on('updated', (event) => {
|
|
491
|
-
debug('membership:updated event handler for update test called');
|
|
492
|
-
webex.memberships.stopListening(); // disable this callback after test
|
|
493
|
-
webex.memberships.off('updated');
|
|
494
|
-
resolve(event);
|
|
495
|
-
});
|
|
496
|
-
});
|
|
497
|
-
|
|
498
|
-
const roomUpdated = new Promise((resolve) => {
|
|
499
|
-
webex.rooms.on('updated', (event) => {
|
|
500
|
-
debug('rooms:updated event handler for update test called');
|
|
501
|
-
webex.rooms.stopListening(); // disable this callback after test
|
|
502
|
-
webex.rooms.off('updated');
|
|
503
|
-
resolve(event);
|
|
504
|
-
});
|
|
505
|
-
});
|
|
506
|
-
|
|
507
|
-
sdkMember.isModerator = false;
|
|
508
|
-
|
|
509
|
-
return webex.rooms
|
|
510
|
-
.listen()
|
|
511
|
-
.then(() => webex.memberships.listen())
|
|
512
|
-
.then(() => webex.memberships.update(sdkMember))
|
|
513
|
-
.then(async (m) => {
|
|
514
|
-
debug('SDK User is no longer a moderator. Wait for events');
|
|
515
|
-
validateMembership(m, /* expected isModerator status */ false);
|
|
516
|
-
const event = await updated;
|
|
517
|
-
|
|
518
|
-
debug('Validating memberships:updated event...');
|
|
519
|
-
validateMembershipEvent(event, m, actor);
|
|
520
|
-
|
|
521
|
-
const roomUpdatedEvent = await roomUpdated;
|
|
522
|
-
|
|
523
|
-
return Promise.resolve(roomUpdatedEvent);
|
|
524
|
-
})
|
|
525
|
-
.then((roomUpdatedEvent) => {
|
|
526
|
-
// Check that the expected rooms:updated event matches
|
|
527
|
-
// what we expect when a room moves into the unmoderated state
|
|
528
|
-
debug('Validating rooms:updated event...');
|
|
529
|
-
debug(`roomId: ${room.id}, event.data.id: ${roomUpdatedEvent.data.id}`);
|
|
530
|
-
|
|
531
|
-
return Promise.resolve(
|
|
532
|
-
validateRoomsUpdatedEvent(roomUpdatedEvent, room, /* expected isLocked value */ false)
|
|
533
|
-
);
|
|
534
|
-
})
|
|
535
|
-
.catch((e) => debug(`after logic for #update()' failed: ${e}`));
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
it('assigns a membership to moderator status', () => {
|
|
539
|
-
assert.isFalse(membership.isModerator);
|
|
540
|
-
membership.isModerator = true;
|
|
541
|
-
|
|
542
|
-
const updated = new Promise((resolve) => {
|
|
543
|
-
webex.memberships.on('updated', (event) => {
|
|
544
|
-
debug('membership:updated event handler for assign moderator test called');
|
|
545
|
-
resolve(event);
|
|
546
|
-
});
|
|
547
|
-
});
|
|
548
|
-
|
|
549
|
-
return webex.memberships.listen().then(() =>
|
|
550
|
-
webex.memberships.update(membership).then(async (m) => {
|
|
551
|
-
debug('membership updated');
|
|
552
|
-
assert.deepEqual(m, membership);
|
|
553
|
-
validateMembership(membership, true);
|
|
554
|
-
const event = await updated;
|
|
555
|
-
|
|
556
|
-
validateMembershipEvent(event, membership, actor);
|
|
557
|
-
})
|
|
558
|
-
);
|
|
559
|
-
});
|
|
560
|
-
|
|
561
|
-
it("revokes a member's moderator status", () => {
|
|
562
|
-
assert.isTrue(membership.isModerator);
|
|
563
|
-
membership.isModerator = false;
|
|
564
|
-
|
|
565
|
-
const updated = new Promise((resolve) => {
|
|
566
|
-
webex.memberships.on('updated', (event) => {
|
|
567
|
-
debug('membership:updated event handler for revoke moderator test called');
|
|
568
|
-
resolve(event);
|
|
569
|
-
});
|
|
570
|
-
});
|
|
571
|
-
|
|
572
|
-
return webex.memberships.listen().then(() =>
|
|
573
|
-
webex.memberships.update(membership).then(async (m) => {
|
|
574
|
-
assert.deepEqual(m, membership);
|
|
575
|
-
validateMembership(membership, false);
|
|
576
|
-
const event = await updated;
|
|
577
|
-
|
|
578
|
-
validateMembershipEvent(event, membership, actor);
|
|
579
|
-
})
|
|
580
|
-
);
|
|
581
|
-
});
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
describe('#updateLastSeen()', () => {
|
|
585
|
-
let actor1, message;
|
|
586
|
-
|
|
587
|
-
before(() => {
|
|
588
|
-
// Get another SDK instance for the second user
|
|
589
|
-
// so that one user can send the message
|
|
590
|
-
// and another can mark it as read
|
|
591
|
-
user1.webex = new WebexCore({credentials: user1.token});
|
|
592
|
-
|
|
593
|
-
return user1.webex.people
|
|
594
|
-
.get('me')
|
|
595
|
-
.then((person) => {
|
|
596
|
-
actor1 = person;
|
|
597
|
-
|
|
598
|
-
return webex.rooms.create({title: 'Read Receipt Test'});
|
|
599
|
-
})
|
|
600
|
-
.then((r) => {
|
|
601
|
-
room = r;
|
|
602
|
-
|
|
603
|
-
return webex.memberships.create({
|
|
604
|
-
roomId: room.id,
|
|
605
|
-
personId: actor1.id,
|
|
606
|
-
});
|
|
607
|
-
})
|
|
608
|
-
.then(() =>
|
|
609
|
-
webex.messages
|
|
610
|
-
.create({
|
|
611
|
-
roomId: room.id,
|
|
612
|
-
text: 'This is a test message',
|
|
613
|
-
})
|
|
614
|
-
.then((m) => {
|
|
615
|
-
message = m;
|
|
616
|
-
assert.isMessage(message);
|
|
617
|
-
})
|
|
618
|
-
);
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
it('marks a message as read and verifies membership:updated event', () => {
|
|
622
|
-
const seenPromise = new Promise((resolve) => {
|
|
623
|
-
webex.memberships.on('seen', (event) => {
|
|
624
|
-
debug('membership:seen event handler for updateLastSeen test called');
|
|
625
|
-
resolve(event);
|
|
626
|
-
});
|
|
627
|
-
});
|
|
628
|
-
|
|
629
|
-
debug(`${user1.displayName} marked message as read...`);
|
|
630
|
-
|
|
631
|
-
return webex.memberships.listen().then(() =>
|
|
632
|
-
user1.webex.memberships.updateLastSeen(message).then(async (m) => {
|
|
633
|
-
debug('membership seen');
|
|
634
|
-
validateMembership(m);
|
|
635
|
-
const event = await seenPromise;
|
|
636
|
-
|
|
637
|
-
debug(`...${user.displayName} got the membership:seen event.`);
|
|
638
|
-
assert.equal(
|
|
639
|
-
event.data.lastSeenId,
|
|
640
|
-
message.id,
|
|
641
|
-
'message:seen lastSeenID matches id of message that was acknlowledged'
|
|
642
|
-
);
|
|
643
|
-
validateMembershipEvent(event, m, actor1, actor);
|
|
644
|
-
})
|
|
645
|
-
);
|
|
646
|
-
});
|
|
647
|
-
});
|
|
648
|
-
|
|
649
|
-
describe('#hide()', () => {
|
|
650
|
-
let membership, roomId;
|
|
651
|
-
|
|
652
|
-
// We need a one-on-on space for this test
|
|
653
|
-
// We create it by sending a message to the test user
|
|
654
|
-
before(() =>
|
|
655
|
-
// Ensure that room is a one-on-one object
|
|
656
|
-
webex.messages
|
|
657
|
-
.create({
|
|
658
|
-
toPersonId: user1.id,
|
|
659
|
-
text: 'This message will create a 1-1 space',
|
|
660
|
-
})
|
|
661
|
-
.then((message) => {
|
|
662
|
-
roomId = message.roomId;
|
|
663
|
-
|
|
664
|
-
// Get the test users membership
|
|
665
|
-
return webex.memberships.list({
|
|
666
|
-
roomId,
|
|
667
|
-
personId: user.id,
|
|
668
|
-
});
|
|
669
|
-
})
|
|
670
|
-
.then((memberships) => {
|
|
671
|
-
membership = memberships.items[0];
|
|
672
|
-
})
|
|
673
|
-
);
|
|
674
|
-
|
|
675
|
-
it('hides a space and validates the membership is updated', () => {
|
|
676
|
-
const updatedEventPromise = new Promise((resolve) => {
|
|
677
|
-
webex.memberships.on('updated', (event) => {
|
|
678
|
-
debug('membership:updated event handler called');
|
|
679
|
-
resolve(event);
|
|
680
|
-
});
|
|
681
|
-
});
|
|
682
|
-
|
|
683
|
-
return webex.memberships.listen().then(() => {
|
|
684
|
-
debug(`Hiding my membership in 1-1 space with ID: ${roomId}...`);
|
|
685
|
-
membership.isRoomHidden = true;
|
|
686
|
-
|
|
687
|
-
return webex.memberships
|
|
688
|
-
.update(membership)
|
|
689
|
-
.then(async (m) => {
|
|
690
|
-
debug(
|
|
691
|
-
'memberships.update() request returned OK. Waiting for memberships:updated event'
|
|
692
|
-
);
|
|
693
|
-
assert(
|
|
694
|
-
m.isRoomHidden,
|
|
695
|
-
'membership returned from meberships.update() did not have isRoomHidden set to true'
|
|
696
|
-
);
|
|
697
|
-
const event = await updatedEventPromise;
|
|
698
|
-
|
|
699
|
-
assert(
|
|
700
|
-
event.data.isRoomHidden,
|
|
701
|
-
'memberships:updated event did not have isRoomHidden set to true'
|
|
702
|
-
);
|
|
703
|
-
validateMembershipEvent(event, m, actor);
|
|
704
|
-
})
|
|
705
|
-
.catch((e) => assert.fail(`Updating room to hidden failed: ${e.message}`));
|
|
706
|
-
});
|
|
707
|
-
});
|
|
708
|
-
});
|
|
709
|
-
|
|
710
|
-
describe('#remove()', () => {
|
|
711
|
-
let membership;
|
|
712
|
-
|
|
713
|
-
before(() =>
|
|
714
|
-
webex.rooms
|
|
715
|
-
.create({title: 'Membership F'})
|
|
716
|
-
.then((r) => {
|
|
717
|
-
room = r;
|
|
718
|
-
|
|
719
|
-
return webex.memberships.create({
|
|
720
|
-
roomId: room.id,
|
|
721
|
-
personId: user1.id,
|
|
722
|
-
});
|
|
723
|
-
})
|
|
724
|
-
.then((m) => {
|
|
725
|
-
membership = m;
|
|
726
|
-
})
|
|
727
|
-
);
|
|
728
|
-
|
|
729
|
-
it('deletes a single membership', () => {
|
|
730
|
-
const deletedEventPromise = new Promise((resolve) => {
|
|
731
|
-
webex.memberships.on('deleted', (event) => {
|
|
732
|
-
debug('membership:deleted event handler for delete single membership test called');
|
|
733
|
-
resolve(event);
|
|
734
|
-
});
|
|
735
|
-
});
|
|
736
|
-
|
|
737
|
-
return webex.memberships
|
|
738
|
-
.listen()
|
|
739
|
-
.then(() =>
|
|
740
|
-
webex.memberships.remove(membership).catch((reason) => {
|
|
741
|
-
webex.logger.error('Failed to delete membership', reason);
|
|
742
|
-
})
|
|
743
|
-
)
|
|
744
|
-
.then(async (body) => {
|
|
745
|
-
debug('member deleted');
|
|
746
|
-
assert.notOk(body);
|
|
747
|
-
|
|
748
|
-
return webex.memberships.list(room);
|
|
749
|
-
})
|
|
750
|
-
.then(async (memberships) => {
|
|
751
|
-
assert.notInclude(memberships, membership);
|
|
752
|
-
const event = await deletedEventPromise;
|
|
753
|
-
|
|
754
|
-
validateMembershipEvent(event, membership, actor);
|
|
755
|
-
});
|
|
756
|
-
});
|
|
757
|
-
});
|
|
758
|
-
});
|
|
759
|
-
});
|
|
760
|
-
|
|
761
|
-
/**
|
|
762
|
-
* Validate a Membership object.
|
|
763
|
-
* @param {Object} membership
|
|
764
|
-
* @param {Boolean} isModerator -- expected moderator status of member
|
|
765
|
-
* @returns {void}
|
|
766
|
-
*/
|
|
767
|
-
function validateMembership(membership, isModerator = false) {
|
|
768
|
-
assert.isDefined(membership);
|
|
769
|
-
if ('isModerator' in membership) {
|
|
770
|
-
assert.equal(membership.isModerator, isModerator, 'unexpected isModerator status');
|
|
771
|
-
} else {
|
|
772
|
-
// moderator status not returned for membership:seen events
|
|
773
|
-
assert.exists(membership.lastSeenId);
|
|
774
|
-
// fudge the moderator field so we can do the general check
|
|
775
|
-
// eslint-disable-next-line no-param-reassign
|
|
776
|
-
membership.isModerator = 'manually added';
|
|
777
|
-
}
|
|
778
|
-
assert.isMembership(membership);
|
|
779
|
-
debug('membership validated');
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
/**
|
|
783
|
-
* Validate a membership event.
|
|
784
|
-
* @param {Object} event - membership event
|
|
785
|
-
* @param {Object} membership -- return from the API that generate this event
|
|
786
|
-
* @param {Object} actor - person object for user who performed action
|
|
787
|
-
* @param {Object} creator - person object for user who called listen()
|
|
788
|
-
* @returns {void}
|
|
789
|
-
*/
|
|
790
|
-
function validateMembershipEvent(event, membership, actor, creator = actor) {
|
|
791
|
-
assert.isTrue(
|
|
792
|
-
event.resource === SDK_EVENT.EXTERNAL.RESOURCE.MEMBERSHIPS,
|
|
793
|
-
'not a membership event'
|
|
794
|
-
);
|
|
795
|
-
assert.isDefined(event.event, 'membership event type not set');
|
|
796
|
-
assert.isDefined(event.created, 'event listener created date not set');
|
|
797
|
-
assert.equal(event.createdBy, creator.id, 'event listener createdBy not set to our actor');
|
|
798
|
-
assert.equal(event.orgId, actor.orgId, "event listener orgId not === to our actor's");
|
|
799
|
-
assert.equal(event.ownedBy, 'creator', 'event listener not owned by creator');
|
|
800
|
-
assert.equal(event.status, 'active', 'event listener status not active');
|
|
801
|
-
assert.equal(event.actorId, actor.id, "event actorId not equal to our actor's id");
|
|
802
|
-
|
|
803
|
-
// Ensure event data matches data returned from function call
|
|
804
|
-
// Skip this until we figure out how conversations converts the internal test user UUID
|
|
805
|
-
assert.equal(event.data.id, membership.id, 'event/membership.id not equal');
|
|
806
|
-
assert.equal(event.data.roomId, membership.roomId, 'event/membership.roomId not equal');
|
|
807
|
-
assert.equal(event.data.personId, membership.personId, 'event/membership.personId not equal');
|
|
808
|
-
assert.equal(
|
|
809
|
-
event.data.personOrgId,
|
|
810
|
-
membership.personOrgId,
|
|
811
|
-
'event/membership.personId not equal'
|
|
812
|
-
);
|
|
813
|
-
assert.equal(
|
|
814
|
-
event.data.personEmail,
|
|
815
|
-
membership.personEmail,
|
|
816
|
-
'event/membership.personEmail not equal'
|
|
817
|
-
);
|
|
818
|
-
assert.equal(
|
|
819
|
-
event.data.personDisplayName,
|
|
820
|
-
membership.personDisplayName,
|
|
821
|
-
'event/membership.personDisplayName not equal'
|
|
822
|
-
);
|
|
823
|
-
assert.equal(event.data.roomType, membership.roomType, 'event/membership.roomType not equal');
|
|
824
|
-
assert.equal(event.data.isHidden, membership.isHidden, 'event/membership.isHidden not equal');
|
|
825
|
-
if (event.event !== 'seen') {
|
|
826
|
-
// moderator status not returned on membership:seen events
|
|
827
|
-
assert.equal(
|
|
828
|
-
event.data.isModerator,
|
|
829
|
-
membership.isModerator,
|
|
830
|
-
'event/membership.isModerator not equal'
|
|
831
|
-
);
|
|
832
|
-
}
|
|
833
|
-
debug(`membership:${event.event} event validated`);
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
/**
|
|
837
|
-
* Validate a rooms:updated event for moderated space change
|
|
838
|
-
*
|
|
839
|
-
* We check this in membership tests (instead of the rooms tests)
|
|
840
|
-
* because a change in membership is the activity that triggers this event.
|
|
841
|
-
* @param {Object} event - rooms event
|
|
842
|
-
* @param {Object} room -- return from the API that created the room
|
|
843
|
-
* @param {Boolean} isLocked - expected value for isLocked
|
|
844
|
-
* @returns {void}
|
|
845
|
-
*/
|
|
846
|
-
function validateRoomsUpdatedEvent(event, room, isLocked) {
|
|
847
|
-
const {data} = event;
|
|
848
|
-
|
|
849
|
-
assert(room.id === data.id, 'rooms:updated event did not have the expected roomId');
|
|
850
|
-
assert(room.type === data.type, 'rooms:updated event did not have the expected room type');
|
|
851
|
-
assert(data.isLocked === isLocked, 'rooms:updated did not have expected isLocked value');
|
|
852
|
-
|
|
853
|
-
debug(`rooms:${event.event} event validated`);
|
|
854
|
-
}
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import '@webex/plugin-logger';
|
|
6
|
+
import '@webex/plugin-messages';
|
|
7
|
+
import '@webex/plugin-memberships';
|
|
8
|
+
import '@webex/plugin-people';
|
|
9
|
+
import '@webex/plugin-rooms';
|
|
10
|
+
import WebexCore from '@webex/webex-core';
|
|
11
|
+
import {SDK_EVENT, hydraTypes, constructHydraId} from '@webex/common';
|
|
12
|
+
import {assert} from '@webex/test-helper-chai';
|
|
13
|
+
import sinon from 'sinon';
|
|
14
|
+
import testUsers from '@webex/test-helper-test-users';
|
|
15
|
+
|
|
16
|
+
const debug = require('debug')('memberships');
|
|
17
|
+
|
|
18
|
+
describe('plugin-memberships', function () {
|
|
19
|
+
this.timeout(60000);
|
|
20
|
+
|
|
21
|
+
let webex, user, actor;
|
|
22
|
+
|
|
23
|
+
before(() =>
|
|
24
|
+
testUsers.create({count: 1}).then(([u]) => {
|
|
25
|
+
user = u;
|
|
26
|
+
webex = new WebexCore({credentials: user.token});
|
|
27
|
+
webex.people.get('me').then((person) => {
|
|
28
|
+
actor = person;
|
|
29
|
+
debug('SDK User (Actor) for tests:');
|
|
30
|
+
debug(`- name: ${actor.displayName}`);
|
|
31
|
+
debug(`- id: ${actor.id}`);
|
|
32
|
+
});
|
|
33
|
+
})
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
describe('#memberships', () => {
|
|
37
|
+
let user1;
|
|
38
|
+
|
|
39
|
+
before(() =>
|
|
40
|
+
testUsers.create({count: 1}).then((users) => {
|
|
41
|
+
user1 = users[0];
|
|
42
|
+
debug('User that memberships are created for:');
|
|
43
|
+
debug(`- name: ${user1.displayName}`);
|
|
44
|
+
debug(`- id: ${constructHydraId(hydraTypes.PEOPLE, user1.id)}`);
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
let room;
|
|
49
|
+
|
|
50
|
+
beforeEach(() =>
|
|
51
|
+
webex.rooms.create({title: 'Webex Test Room'}).then((r) => {
|
|
52
|
+
debug('Created Cisco Test Room');
|
|
53
|
+
room = r;
|
|
54
|
+
})
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
afterEach(() => {
|
|
58
|
+
webex.memberships.stopListening();
|
|
59
|
+
webex.memberships.off('created');
|
|
60
|
+
webex.memberships.off('updated');
|
|
61
|
+
webex.memberships.off('deleted');
|
|
62
|
+
webex.memberships.off('seen');
|
|
63
|
+
webex.rooms
|
|
64
|
+
.remove(room)
|
|
65
|
+
.catch((e) => webex.logger.error(`Failed to clean up after unit test: ${e}`));
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('#create()', () => {
|
|
69
|
+
it('creates a membership by user id', () =>
|
|
70
|
+
webex.memberships
|
|
71
|
+
.create({
|
|
72
|
+
roomId: room.id,
|
|
73
|
+
personId: user1.id,
|
|
74
|
+
})
|
|
75
|
+
.then((membership) => {
|
|
76
|
+
assert.isMembership(membership);
|
|
77
|
+
}));
|
|
78
|
+
|
|
79
|
+
it('creates a membership by user email', () => {
|
|
80
|
+
const created = new Promise((resolve) => {
|
|
81
|
+
webex.memberships.on('created', (event) => {
|
|
82
|
+
debug('membership:created event handler for membership by email test called');
|
|
83
|
+
resolve(event);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return webex.memberships.listen().then(() =>
|
|
88
|
+
webex.memberships
|
|
89
|
+
.create({
|
|
90
|
+
roomId: room.id,
|
|
91
|
+
personEmail: user1.email,
|
|
92
|
+
})
|
|
93
|
+
.then(async (membership) => {
|
|
94
|
+
validateMembership(membership);
|
|
95
|
+
const event = await created;
|
|
96
|
+
|
|
97
|
+
validateMembershipEvent(event, membership, actor);
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('creates a membership and sets moderator status', () => {
|
|
103
|
+
// "Creating" a member as a moderator actually generates
|
|
104
|
+
// two events, first a created event (with non-moderator status)
|
|
105
|
+
// followed by an updated event with isModerator set to true
|
|
106
|
+
const created = new Promise((resolve) => {
|
|
107
|
+
webex.memberships.on('created', (event) => {
|
|
108
|
+
debug('membership:created event handler for moderator test called');
|
|
109
|
+
resolve(event);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
const updated = new Promise((resolve) => {
|
|
113
|
+
webex.memberships.on('updated', (event) => {
|
|
114
|
+
debug('membership:updated event handler for moderator test called');
|
|
115
|
+
|
|
116
|
+
if (event.data.personId === actor.id) {
|
|
117
|
+
debug(
|
|
118
|
+
'Setting a member to moderator implicitly sets the ' +
|
|
119
|
+
'caller of the API to moderator as well. In this test we ' +
|
|
120
|
+
'will ignore this event'
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
resolve(event);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return webex.memberships.listen().then(() =>
|
|
130
|
+
webex.memberships
|
|
131
|
+
.create({
|
|
132
|
+
roomId: room.id,
|
|
133
|
+
personId: user1.id,
|
|
134
|
+
isModerator: true,
|
|
135
|
+
})
|
|
136
|
+
.then(async (m) => {
|
|
137
|
+
const membership = m;
|
|
138
|
+
|
|
139
|
+
validateMembership(membership, true);
|
|
140
|
+
const event = await created;
|
|
141
|
+
|
|
142
|
+
// We expect the isModerator status to be false on create
|
|
143
|
+
membership.isModerator = false;
|
|
144
|
+
validateMembershipEvent(event, membership, actor);
|
|
145
|
+
|
|
146
|
+
const event2 = await updated;
|
|
147
|
+
|
|
148
|
+
// We expect the isModerator status to be false on create
|
|
149
|
+
membership.isModerator = true;
|
|
150
|
+
validateMembershipEvent(event2, membership, actor);
|
|
151
|
+
})
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('creates a space and memberships simultaniously', () => {
|
|
156
|
+
// "Creating" a space with users generates a unique event
|
|
157
|
+
// activity object shape via the client that contains
|
|
158
|
+
// multiple "participants". There isn't a documented
|
|
159
|
+
// way to perform this action via the API with more than
|
|
160
|
+
// one user at the time of edit.
|
|
161
|
+
const created = new Promise((resolve) => {
|
|
162
|
+
webex.memberships.on('created', (event) => {
|
|
163
|
+
debug('membership:created event handler for new space test called');
|
|
164
|
+
resolve(event);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
return (
|
|
169
|
+
webex.memberships
|
|
170
|
+
.listen()
|
|
171
|
+
// Cleanup current room, we need to catch the event when it's created.
|
|
172
|
+
.then(() => webex.rooms.remove(room))
|
|
173
|
+
// Create a room to trigger created event.
|
|
174
|
+
.then(() => webex.rooms.create({title: 'Webex Test Room'}))
|
|
175
|
+
// Store new room object and get the memberships of the room.
|
|
176
|
+
.then((r) => {
|
|
177
|
+
room = r;
|
|
178
|
+
|
|
179
|
+
return webex.memberships.list({roomId: room.id});
|
|
180
|
+
})
|
|
181
|
+
// validate data
|
|
182
|
+
.then(async ({items: [membership]}) => {
|
|
183
|
+
const event = await created;
|
|
184
|
+
|
|
185
|
+
validateMembership(membership, false);
|
|
186
|
+
validateMembershipEvent(event, membership, actor);
|
|
187
|
+
})
|
|
188
|
+
);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
describe('#get()', () => {
|
|
193
|
+
let membership;
|
|
194
|
+
|
|
195
|
+
before(() =>
|
|
196
|
+
// this could be in parallel once KMS always sends new keys
|
|
197
|
+
webex.rooms
|
|
198
|
+
.create({title: 'Membership A'})
|
|
199
|
+
.then((room) => Promise.all([room, webex.rooms.create({title: 'Membership B'})]))
|
|
200
|
+
.then((rooms) => {
|
|
201
|
+
const room = rooms[0];
|
|
202
|
+
|
|
203
|
+
return webex.memberships.create({
|
|
204
|
+
roomId: room.id,
|
|
205
|
+
personId: user1.id,
|
|
206
|
+
});
|
|
207
|
+
})
|
|
208
|
+
.then((m) => {
|
|
209
|
+
membership = m;
|
|
210
|
+
})
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
it('retrieves a single membership', () =>
|
|
214
|
+
webex.memberships.get(membership).then((m) => {
|
|
215
|
+
assert.deepEqual(m, membership);
|
|
216
|
+
}));
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe('#list()', () => {
|
|
220
|
+
let room;
|
|
221
|
+
|
|
222
|
+
before(() =>
|
|
223
|
+
// this could be in parallel once KMS always sends new keys
|
|
224
|
+
webex.rooms
|
|
225
|
+
.create({title: 'Membership A'})
|
|
226
|
+
.then((room) => Promise.all([room, webex.rooms.create({title: 'Membership B'})]))
|
|
227
|
+
.then((rooms) => {
|
|
228
|
+
room = rooms[0];
|
|
229
|
+
|
|
230
|
+
return webex.memberships.create({
|
|
231
|
+
roomId: room.id,
|
|
232
|
+
personId: user1.id,
|
|
233
|
+
});
|
|
234
|
+
})
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
it('retrieves all memberships for a room', () =>
|
|
238
|
+
webex.memberships.list({roomId: room.id}).then((memberships) => {
|
|
239
|
+
assert.isDefined(memberships);
|
|
240
|
+
assert.isAbove(memberships.length, 0);
|
|
241
|
+
for (const membership of memberships) {
|
|
242
|
+
assert.isMembership(membership);
|
|
243
|
+
assert.equal(membership.roomId, room.id);
|
|
244
|
+
}
|
|
245
|
+
}));
|
|
246
|
+
|
|
247
|
+
it('retrieves a bounded set of memberships for a room', () => {
|
|
248
|
+
const spy = sinon.spy();
|
|
249
|
+
|
|
250
|
+
return webex.memberships
|
|
251
|
+
.list({roomId: room.id, max: 1})
|
|
252
|
+
.then((memberships) => {
|
|
253
|
+
assert.lengthOf(memberships, 1);
|
|
254
|
+
|
|
255
|
+
return (function f(page) {
|
|
256
|
+
for (const membership of page) {
|
|
257
|
+
spy(membership.id);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (page.hasNext()) {
|
|
261
|
+
return page.next().then(f);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return Promise.resolve();
|
|
265
|
+
})(memberships);
|
|
266
|
+
})
|
|
267
|
+
.then(() => {
|
|
268
|
+
assert.calledTwice(spy);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('retrieves all room memberships for a user', () =>
|
|
273
|
+
webex.memberships
|
|
274
|
+
.list({
|
|
275
|
+
personId: user.id,
|
|
276
|
+
roomId: room.id,
|
|
277
|
+
})
|
|
278
|
+
.then((memberships) => {
|
|
279
|
+
const membership = memberships.items[0];
|
|
280
|
+
|
|
281
|
+
return webex.memberships
|
|
282
|
+
.list({
|
|
283
|
+
personEmail: user.email,
|
|
284
|
+
})
|
|
285
|
+
.then((memberships) => {
|
|
286
|
+
assert.isDefined(memberships);
|
|
287
|
+
assert.isAbove(memberships.length, 0);
|
|
288
|
+
for (const membership of memberships) {
|
|
289
|
+
assert.isMembership(membership);
|
|
290
|
+
assert.equal(membership.personEmail, user.email);
|
|
291
|
+
}
|
|
292
|
+
assert.deepInclude(memberships.items, membership);
|
|
293
|
+
});
|
|
294
|
+
}));
|
|
295
|
+
|
|
296
|
+
it('retrieves a bounded set of memberships for a user', () => {
|
|
297
|
+
const spy = sinon.spy();
|
|
298
|
+
|
|
299
|
+
return webex.memberships
|
|
300
|
+
.list({personId: user.id, max: 1})
|
|
301
|
+
.then((memberships) => {
|
|
302
|
+
assert.lengthOf(memberships, 1);
|
|
303
|
+
|
|
304
|
+
return (function f(page) {
|
|
305
|
+
for (const membership of page) {
|
|
306
|
+
assert.equal(membership.personEmail, user.email);
|
|
307
|
+
spy(membership.id);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (page.hasNext()) {
|
|
311
|
+
return page.next().then(f);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return Promise.resolve();
|
|
315
|
+
})(memberships);
|
|
316
|
+
})
|
|
317
|
+
.then(() => {
|
|
318
|
+
assert.isAbove(spy.callCount, 0);
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
describe('#listWithReadStatus()', () => {
|
|
324
|
+
let room;
|
|
325
|
+
|
|
326
|
+
before(() => {
|
|
327
|
+
// Create a new SDK instance so the 2nd user can post a message
|
|
328
|
+
user1.webex = new WebexCore({credentials: user1.token});
|
|
329
|
+
|
|
330
|
+
// Setup a space with both users
|
|
331
|
+
return webex.rooms
|
|
332
|
+
.create({title: 'Membership A'})
|
|
333
|
+
.then((room) => Promise.all([room, webex.rooms.create({title: 'Membership B'})]))
|
|
334
|
+
.then((rooms) => {
|
|
335
|
+
room = rooms[0];
|
|
336
|
+
|
|
337
|
+
return webex.memberships.create({
|
|
338
|
+
roomId: room.id,
|
|
339
|
+
personId: user1.id,
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
it('retrieves memberships with read status for a room that has not been visited', () =>
|
|
345
|
+
webex.memberships.listWithReadStatus({roomId: room.id}).then((memberships) => {
|
|
346
|
+
assert.isDefined(memberships);
|
|
347
|
+
assert.equal(memberships.items.length, 2);
|
|
348
|
+
for (const membership of memberships.items) {
|
|
349
|
+
if (membership.personId !== actor.id) {
|
|
350
|
+
assert.notExists(
|
|
351
|
+
membership.lastSeenId,
|
|
352
|
+
'no lastSeenId for a room that has never been visited'
|
|
353
|
+
);
|
|
354
|
+
assert.notExists(
|
|
355
|
+
membership.lastSeenDate,
|
|
356
|
+
'no lastSeenDate for a room that has never been visited'
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
assert.equal(membership.roomId, room.id);
|
|
360
|
+
}
|
|
361
|
+
}));
|
|
362
|
+
|
|
363
|
+
it('validates read status activity after other user posts a message', () =>
|
|
364
|
+
user1.webex.messages
|
|
365
|
+
.create({
|
|
366
|
+
roomId: room.id,
|
|
367
|
+
text: 'Message to create activity for other member',
|
|
368
|
+
})
|
|
369
|
+
.then(() =>
|
|
370
|
+
webex.memberships.listWithReadStatus({roomId: room.id}).then((memberships) => {
|
|
371
|
+
assert.isDefined(memberships);
|
|
372
|
+
assert.equal(memberships.items.length, 2);
|
|
373
|
+
for (const membership of memberships.items) {
|
|
374
|
+
assert.exists(
|
|
375
|
+
membership.lastSeenId,
|
|
376
|
+
'lastSeenId exists in a room that has been visited'
|
|
377
|
+
);
|
|
378
|
+
assert.exists(
|
|
379
|
+
membership.lastSeenDate,
|
|
380
|
+
'lastSeenDate exists in a room that has been visited'
|
|
381
|
+
);
|
|
382
|
+
assert.equal(membership.roomId, room.id);
|
|
383
|
+
// listWithReadStatus does not include created
|
|
384
|
+
// fudge it here so we can validate all the other fields
|
|
385
|
+
membership.created = 'foo';
|
|
386
|
+
assert.isMembership(membership);
|
|
387
|
+
}
|
|
388
|
+
})
|
|
389
|
+
));
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
describe('#update()', () => {
|
|
393
|
+
let membership, sdkMember, room;
|
|
394
|
+
|
|
395
|
+
before(() => {
|
|
396
|
+
// Before setting another user to moderator
|
|
397
|
+
// We will set the test user to moderator
|
|
398
|
+
// and wait for the expected events to arive
|
|
399
|
+
const updated = new Promise((resolve) => {
|
|
400
|
+
webex.memberships.on('updated', (event) => {
|
|
401
|
+
debug('membership:updated event handler for update test called');
|
|
402
|
+
webex.memberships.stopListening(); // disable this callback after test
|
|
403
|
+
webex.memberships.off('updated');
|
|
404
|
+
resolve(event);
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
const roomUpdated = new Promise((resolve) => {
|
|
409
|
+
webex.rooms.on('updated', (event) => {
|
|
410
|
+
debug('rooms:updated event handler for update test called');
|
|
411
|
+
webex.rooms.stopListening(); // disable this callback after test
|
|
412
|
+
webex.rooms.off('updated');
|
|
413
|
+
resolve(event);
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
return webex.memberships
|
|
418
|
+
.listen()
|
|
419
|
+
.then(() => webex.rooms.listen())
|
|
420
|
+
.then(() =>
|
|
421
|
+
webex.rooms
|
|
422
|
+
.create({title: 'Membership E'})
|
|
423
|
+
.then((r) => {
|
|
424
|
+
room = r;
|
|
425
|
+
debug(`Room under test ID: ${room.id}`);
|
|
426
|
+
|
|
427
|
+
// First get the SDK users membership
|
|
428
|
+
return webex.memberships.list({
|
|
429
|
+
roomId: room.id,
|
|
430
|
+
personId: actor.id,
|
|
431
|
+
});
|
|
432
|
+
})
|
|
433
|
+
.then((membershipList) => {
|
|
434
|
+
assert.isArray(
|
|
435
|
+
membershipList.items,
|
|
436
|
+
'membership list not returned after room creation'
|
|
437
|
+
);
|
|
438
|
+
assert.equal(
|
|
439
|
+
membershipList.items.length,
|
|
440
|
+
1,
|
|
441
|
+
'SDK Test user not a member of room just created'
|
|
442
|
+
);
|
|
443
|
+
sdkMember = membershipList.items[0];
|
|
444
|
+
|
|
445
|
+
validateMembership(sdkMember);
|
|
446
|
+
sdkMember.isModerator = true;
|
|
447
|
+
|
|
448
|
+
// Then update the SDK user to a moderator
|
|
449
|
+
return webex.memberships.update(sdkMember);
|
|
450
|
+
})
|
|
451
|
+
.then(async (m) => {
|
|
452
|
+
debug('SDK User is now moderator. Wait for events');
|
|
453
|
+
validateMembership(m, true);
|
|
454
|
+
const event = await updated;
|
|
455
|
+
|
|
456
|
+
validateMembershipEvent(event, m, actor);
|
|
457
|
+
const roomUpdatedEvent = await roomUpdated;
|
|
458
|
+
|
|
459
|
+
return Promise.resolve(roomUpdatedEvent);
|
|
460
|
+
})
|
|
461
|
+
.then((roomUpdatedEvent) => {
|
|
462
|
+
// Check that the expected rooms:updated event matches
|
|
463
|
+
// what we expect when a room is first moderated
|
|
464
|
+
validateRoomsUpdatedEvent(
|
|
465
|
+
roomUpdatedEvent,
|
|
466
|
+
room,
|
|
467
|
+
/* expected value of isLocked */ true
|
|
468
|
+
);
|
|
469
|
+
|
|
470
|
+
// Finally, create the user for our test
|
|
471
|
+
return webex.memberships.create({
|
|
472
|
+
roomId: room.id,
|
|
473
|
+
personId: user1.id,
|
|
474
|
+
});
|
|
475
|
+
})
|
|
476
|
+
.then((m) => {
|
|
477
|
+
debug('User 1 Membership created in Membership E');
|
|
478
|
+
membership = m;
|
|
479
|
+
validateMembership(membership);
|
|
480
|
+
})
|
|
481
|
+
.catch((e) => debug(`membership failed: ${e}`))
|
|
482
|
+
);
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
after(() => {
|
|
486
|
+
// Before deleting the test space
|
|
487
|
+
// We will unset the test user to moderator
|
|
488
|
+
// and wait for the expected events to arive
|
|
489
|
+
const updated = new Promise((resolve) => {
|
|
490
|
+
webex.memberships.on('updated', (event) => {
|
|
491
|
+
debug('membership:updated event handler for update test called');
|
|
492
|
+
webex.memberships.stopListening(); // disable this callback after test
|
|
493
|
+
webex.memberships.off('updated');
|
|
494
|
+
resolve(event);
|
|
495
|
+
});
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
const roomUpdated = new Promise((resolve) => {
|
|
499
|
+
webex.rooms.on('updated', (event) => {
|
|
500
|
+
debug('rooms:updated event handler for update test called');
|
|
501
|
+
webex.rooms.stopListening(); // disable this callback after test
|
|
502
|
+
webex.rooms.off('updated');
|
|
503
|
+
resolve(event);
|
|
504
|
+
});
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
sdkMember.isModerator = false;
|
|
508
|
+
|
|
509
|
+
return webex.rooms
|
|
510
|
+
.listen()
|
|
511
|
+
.then(() => webex.memberships.listen())
|
|
512
|
+
.then(() => webex.memberships.update(sdkMember))
|
|
513
|
+
.then(async (m) => {
|
|
514
|
+
debug('SDK User is no longer a moderator. Wait for events');
|
|
515
|
+
validateMembership(m, /* expected isModerator status */ false);
|
|
516
|
+
const event = await updated;
|
|
517
|
+
|
|
518
|
+
debug('Validating memberships:updated event...');
|
|
519
|
+
validateMembershipEvent(event, m, actor);
|
|
520
|
+
|
|
521
|
+
const roomUpdatedEvent = await roomUpdated;
|
|
522
|
+
|
|
523
|
+
return Promise.resolve(roomUpdatedEvent);
|
|
524
|
+
})
|
|
525
|
+
.then((roomUpdatedEvent) => {
|
|
526
|
+
// Check that the expected rooms:updated event matches
|
|
527
|
+
// what we expect when a room moves into the unmoderated state
|
|
528
|
+
debug('Validating rooms:updated event...');
|
|
529
|
+
debug(`roomId: ${room.id}, event.data.id: ${roomUpdatedEvent.data.id}`);
|
|
530
|
+
|
|
531
|
+
return Promise.resolve(
|
|
532
|
+
validateRoomsUpdatedEvent(roomUpdatedEvent, room, /* expected isLocked value */ false)
|
|
533
|
+
);
|
|
534
|
+
})
|
|
535
|
+
.catch((e) => debug(`after logic for #update()' failed: ${e}`));
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
it('assigns a membership to moderator status', () => {
|
|
539
|
+
assert.isFalse(membership.isModerator);
|
|
540
|
+
membership.isModerator = true;
|
|
541
|
+
|
|
542
|
+
const updated = new Promise((resolve) => {
|
|
543
|
+
webex.memberships.on('updated', (event) => {
|
|
544
|
+
debug('membership:updated event handler for assign moderator test called');
|
|
545
|
+
resolve(event);
|
|
546
|
+
});
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
return webex.memberships.listen().then(() =>
|
|
550
|
+
webex.memberships.update(membership).then(async (m) => {
|
|
551
|
+
debug('membership updated');
|
|
552
|
+
assert.deepEqual(m, membership);
|
|
553
|
+
validateMembership(membership, true);
|
|
554
|
+
const event = await updated;
|
|
555
|
+
|
|
556
|
+
validateMembershipEvent(event, membership, actor);
|
|
557
|
+
})
|
|
558
|
+
);
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
it("revokes a member's moderator status", () => {
|
|
562
|
+
assert.isTrue(membership.isModerator);
|
|
563
|
+
membership.isModerator = false;
|
|
564
|
+
|
|
565
|
+
const updated = new Promise((resolve) => {
|
|
566
|
+
webex.memberships.on('updated', (event) => {
|
|
567
|
+
debug('membership:updated event handler for revoke moderator test called');
|
|
568
|
+
resolve(event);
|
|
569
|
+
});
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
return webex.memberships.listen().then(() =>
|
|
573
|
+
webex.memberships.update(membership).then(async (m) => {
|
|
574
|
+
assert.deepEqual(m, membership);
|
|
575
|
+
validateMembership(membership, false);
|
|
576
|
+
const event = await updated;
|
|
577
|
+
|
|
578
|
+
validateMembershipEvent(event, membership, actor);
|
|
579
|
+
})
|
|
580
|
+
);
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
describe('#updateLastSeen()', () => {
|
|
585
|
+
let actor1, message;
|
|
586
|
+
|
|
587
|
+
before(() => {
|
|
588
|
+
// Get another SDK instance for the second user
|
|
589
|
+
// so that one user can send the message
|
|
590
|
+
// and another can mark it as read
|
|
591
|
+
user1.webex = new WebexCore({credentials: user1.token});
|
|
592
|
+
|
|
593
|
+
return user1.webex.people
|
|
594
|
+
.get('me')
|
|
595
|
+
.then((person) => {
|
|
596
|
+
actor1 = person;
|
|
597
|
+
|
|
598
|
+
return webex.rooms.create({title: 'Read Receipt Test'});
|
|
599
|
+
})
|
|
600
|
+
.then((r) => {
|
|
601
|
+
room = r;
|
|
602
|
+
|
|
603
|
+
return webex.memberships.create({
|
|
604
|
+
roomId: room.id,
|
|
605
|
+
personId: actor1.id,
|
|
606
|
+
});
|
|
607
|
+
})
|
|
608
|
+
.then(() =>
|
|
609
|
+
webex.messages
|
|
610
|
+
.create({
|
|
611
|
+
roomId: room.id,
|
|
612
|
+
text: 'This is a test message',
|
|
613
|
+
})
|
|
614
|
+
.then((m) => {
|
|
615
|
+
message = m;
|
|
616
|
+
assert.isMessage(message);
|
|
617
|
+
})
|
|
618
|
+
);
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
it('marks a message as read and verifies membership:updated event', () => {
|
|
622
|
+
const seenPromise = new Promise((resolve) => {
|
|
623
|
+
webex.memberships.on('seen', (event) => {
|
|
624
|
+
debug('membership:seen event handler for updateLastSeen test called');
|
|
625
|
+
resolve(event);
|
|
626
|
+
});
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
debug(`${user1.displayName} marked message as read...`);
|
|
630
|
+
|
|
631
|
+
return webex.memberships.listen().then(() =>
|
|
632
|
+
user1.webex.memberships.updateLastSeen(message).then(async (m) => {
|
|
633
|
+
debug('membership seen');
|
|
634
|
+
validateMembership(m);
|
|
635
|
+
const event = await seenPromise;
|
|
636
|
+
|
|
637
|
+
debug(`...${user.displayName} got the membership:seen event.`);
|
|
638
|
+
assert.equal(
|
|
639
|
+
event.data.lastSeenId,
|
|
640
|
+
message.id,
|
|
641
|
+
'message:seen lastSeenID matches id of message that was acknlowledged'
|
|
642
|
+
);
|
|
643
|
+
validateMembershipEvent(event, m, actor1, actor);
|
|
644
|
+
})
|
|
645
|
+
);
|
|
646
|
+
});
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
describe('#hide()', () => {
|
|
650
|
+
let membership, roomId;
|
|
651
|
+
|
|
652
|
+
// We need a one-on-on space for this test
|
|
653
|
+
// We create it by sending a message to the test user
|
|
654
|
+
before(() =>
|
|
655
|
+
// Ensure that room is a one-on-one object
|
|
656
|
+
webex.messages
|
|
657
|
+
.create({
|
|
658
|
+
toPersonId: user1.id,
|
|
659
|
+
text: 'This message will create a 1-1 space',
|
|
660
|
+
})
|
|
661
|
+
.then((message) => {
|
|
662
|
+
roomId = message.roomId;
|
|
663
|
+
|
|
664
|
+
// Get the test users membership
|
|
665
|
+
return webex.memberships.list({
|
|
666
|
+
roomId,
|
|
667
|
+
personId: user.id,
|
|
668
|
+
});
|
|
669
|
+
})
|
|
670
|
+
.then((memberships) => {
|
|
671
|
+
membership = memberships.items[0];
|
|
672
|
+
})
|
|
673
|
+
);
|
|
674
|
+
|
|
675
|
+
it('hides a space and validates the membership is updated', () => {
|
|
676
|
+
const updatedEventPromise = new Promise((resolve) => {
|
|
677
|
+
webex.memberships.on('updated', (event) => {
|
|
678
|
+
debug('membership:updated event handler called');
|
|
679
|
+
resolve(event);
|
|
680
|
+
});
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
return webex.memberships.listen().then(() => {
|
|
684
|
+
debug(`Hiding my membership in 1-1 space with ID: ${roomId}...`);
|
|
685
|
+
membership.isRoomHidden = true;
|
|
686
|
+
|
|
687
|
+
return webex.memberships
|
|
688
|
+
.update(membership)
|
|
689
|
+
.then(async (m) => {
|
|
690
|
+
debug(
|
|
691
|
+
'memberships.update() request returned OK. Waiting for memberships:updated event'
|
|
692
|
+
);
|
|
693
|
+
assert(
|
|
694
|
+
m.isRoomHidden,
|
|
695
|
+
'membership returned from meberships.update() did not have isRoomHidden set to true'
|
|
696
|
+
);
|
|
697
|
+
const event = await updatedEventPromise;
|
|
698
|
+
|
|
699
|
+
assert(
|
|
700
|
+
event.data.isRoomHidden,
|
|
701
|
+
'memberships:updated event did not have isRoomHidden set to true'
|
|
702
|
+
);
|
|
703
|
+
validateMembershipEvent(event, m, actor);
|
|
704
|
+
})
|
|
705
|
+
.catch((e) => assert.fail(`Updating room to hidden failed: ${e.message}`));
|
|
706
|
+
});
|
|
707
|
+
});
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
describe('#remove()', () => {
|
|
711
|
+
let membership;
|
|
712
|
+
|
|
713
|
+
before(() =>
|
|
714
|
+
webex.rooms
|
|
715
|
+
.create({title: 'Membership F'})
|
|
716
|
+
.then((r) => {
|
|
717
|
+
room = r;
|
|
718
|
+
|
|
719
|
+
return webex.memberships.create({
|
|
720
|
+
roomId: room.id,
|
|
721
|
+
personId: user1.id,
|
|
722
|
+
});
|
|
723
|
+
})
|
|
724
|
+
.then((m) => {
|
|
725
|
+
membership = m;
|
|
726
|
+
})
|
|
727
|
+
);
|
|
728
|
+
|
|
729
|
+
it('deletes a single membership', () => {
|
|
730
|
+
const deletedEventPromise = new Promise((resolve) => {
|
|
731
|
+
webex.memberships.on('deleted', (event) => {
|
|
732
|
+
debug('membership:deleted event handler for delete single membership test called');
|
|
733
|
+
resolve(event);
|
|
734
|
+
});
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
return webex.memberships
|
|
738
|
+
.listen()
|
|
739
|
+
.then(() =>
|
|
740
|
+
webex.memberships.remove(membership).catch((reason) => {
|
|
741
|
+
webex.logger.error('Failed to delete membership', reason);
|
|
742
|
+
})
|
|
743
|
+
)
|
|
744
|
+
.then(async (body) => {
|
|
745
|
+
debug('member deleted');
|
|
746
|
+
assert.notOk(body);
|
|
747
|
+
|
|
748
|
+
return webex.memberships.list(room);
|
|
749
|
+
})
|
|
750
|
+
.then(async (memberships) => {
|
|
751
|
+
assert.notInclude(memberships, membership);
|
|
752
|
+
const event = await deletedEventPromise;
|
|
753
|
+
|
|
754
|
+
validateMembershipEvent(event, membership, actor);
|
|
755
|
+
});
|
|
756
|
+
});
|
|
757
|
+
});
|
|
758
|
+
});
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* Validate a Membership object.
|
|
763
|
+
* @param {Object} membership
|
|
764
|
+
* @param {Boolean} isModerator -- expected moderator status of member
|
|
765
|
+
* @returns {void}
|
|
766
|
+
*/
|
|
767
|
+
function validateMembership(membership, isModerator = false) {
|
|
768
|
+
assert.isDefined(membership);
|
|
769
|
+
if ('isModerator' in membership) {
|
|
770
|
+
assert.equal(membership.isModerator, isModerator, 'unexpected isModerator status');
|
|
771
|
+
} else {
|
|
772
|
+
// moderator status not returned for membership:seen events
|
|
773
|
+
assert.exists(membership.lastSeenId);
|
|
774
|
+
// fudge the moderator field so we can do the general check
|
|
775
|
+
// eslint-disable-next-line no-param-reassign
|
|
776
|
+
membership.isModerator = 'manually added';
|
|
777
|
+
}
|
|
778
|
+
assert.isMembership(membership);
|
|
779
|
+
debug('membership validated');
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Validate a membership event.
|
|
784
|
+
* @param {Object} event - membership event
|
|
785
|
+
* @param {Object} membership -- return from the API that generate this event
|
|
786
|
+
* @param {Object} actor - person object for user who performed action
|
|
787
|
+
* @param {Object} creator - person object for user who called listen()
|
|
788
|
+
* @returns {void}
|
|
789
|
+
*/
|
|
790
|
+
function validateMembershipEvent(event, membership, actor, creator = actor) {
|
|
791
|
+
assert.isTrue(
|
|
792
|
+
event.resource === SDK_EVENT.EXTERNAL.RESOURCE.MEMBERSHIPS,
|
|
793
|
+
'not a membership event'
|
|
794
|
+
);
|
|
795
|
+
assert.isDefined(event.event, 'membership event type not set');
|
|
796
|
+
assert.isDefined(event.created, 'event listener created date not set');
|
|
797
|
+
assert.equal(event.createdBy, creator.id, 'event listener createdBy not set to our actor');
|
|
798
|
+
assert.equal(event.orgId, actor.orgId, "event listener orgId not === to our actor's");
|
|
799
|
+
assert.equal(event.ownedBy, 'creator', 'event listener not owned by creator');
|
|
800
|
+
assert.equal(event.status, 'active', 'event listener status not active');
|
|
801
|
+
assert.equal(event.actorId, actor.id, "event actorId not equal to our actor's id");
|
|
802
|
+
|
|
803
|
+
// Ensure event data matches data returned from function call
|
|
804
|
+
// Skip this until we figure out how conversations converts the internal test user UUID
|
|
805
|
+
assert.equal(event.data.id, membership.id, 'event/membership.id not equal');
|
|
806
|
+
assert.equal(event.data.roomId, membership.roomId, 'event/membership.roomId not equal');
|
|
807
|
+
assert.equal(event.data.personId, membership.personId, 'event/membership.personId not equal');
|
|
808
|
+
assert.equal(
|
|
809
|
+
event.data.personOrgId,
|
|
810
|
+
membership.personOrgId,
|
|
811
|
+
'event/membership.personId not equal'
|
|
812
|
+
);
|
|
813
|
+
assert.equal(
|
|
814
|
+
event.data.personEmail,
|
|
815
|
+
membership.personEmail,
|
|
816
|
+
'event/membership.personEmail not equal'
|
|
817
|
+
);
|
|
818
|
+
assert.equal(
|
|
819
|
+
event.data.personDisplayName,
|
|
820
|
+
membership.personDisplayName,
|
|
821
|
+
'event/membership.personDisplayName not equal'
|
|
822
|
+
);
|
|
823
|
+
assert.equal(event.data.roomType, membership.roomType, 'event/membership.roomType not equal');
|
|
824
|
+
assert.equal(event.data.isHidden, membership.isHidden, 'event/membership.isHidden not equal');
|
|
825
|
+
if (event.event !== 'seen') {
|
|
826
|
+
// moderator status not returned on membership:seen events
|
|
827
|
+
assert.equal(
|
|
828
|
+
event.data.isModerator,
|
|
829
|
+
membership.isModerator,
|
|
830
|
+
'event/membership.isModerator not equal'
|
|
831
|
+
);
|
|
832
|
+
}
|
|
833
|
+
debug(`membership:${event.event} event validated`);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* Validate a rooms:updated event for moderated space change
|
|
838
|
+
*
|
|
839
|
+
* We check this in membership tests (instead of the rooms tests)
|
|
840
|
+
* because a change in membership is the activity that triggers this event.
|
|
841
|
+
* @param {Object} event - rooms event
|
|
842
|
+
* @param {Object} room -- return from the API that created the room
|
|
843
|
+
* @param {Boolean} isLocked - expected value for isLocked
|
|
844
|
+
* @returns {void}
|
|
845
|
+
*/
|
|
846
|
+
function validateRoomsUpdatedEvent(event, room, isLocked) {
|
|
847
|
+
const {data} = event;
|
|
848
|
+
|
|
849
|
+
assert(room.id === data.id, 'rooms:updated event did not have the expected roomId');
|
|
850
|
+
assert(room.type === data.type, 'rooms:updated event did not have the expected room type');
|
|
851
|
+
assert(data.isLocked === isLocked, 'rooms:updated did not have expected isLocked value');
|
|
852
|
+
|
|
853
|
+
debug(`rooms:${event.event} event validated`);
|
|
854
|
+
}
|