@webex/internal-plugin-calendar 3.0.0-beta.4 → 3.0.0-beta.400

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.
@@ -2,13 +2,19 @@
2
2
  * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
3
  */
4
4
 
5
- import {assert} from '@webex/test-helper-chai';
5
+ import { assert, expect } from "@webex/test-helper-chai";
6
6
  import Calendar from '@webex/internal-plugin-calendar';
7
7
  import MockWebex from '@webex/test-helper-mock-webex';
8
- import btoa from 'btoa';
8
+ import { base64 } from "@webex/common";
9
9
  import sinon from 'sinon';
10
10
 
11
- import {CALENDAR_REGISTERED, CALENDAR_UPDATED, CALENDAR_DELETE, CALENDAR_CREATE, CALENDAR_UNREGISTERED} from '../../../src/constants';
11
+ import {
12
+ CALENDAR_REGISTERED,
13
+ CALENDAR_UPDATED,
14
+ CALENDAR_DELETE,
15
+ CALENDAR_CREATE,
16
+ CALENDAR_UNREGISTERED,
17
+ } from '../../../src/constants';
12
18
 
13
19
  describe('internal-plugin-calendar', () => {
14
20
  describe('Calendar Apis', () => {
@@ -17,14 +23,14 @@ describe('internal-plugin-calendar', () => {
17
23
  beforeEach(async () => {
18
24
  webex = new MockWebex({
19
25
  children: {
20
- calendar: Calendar
21
- }
26
+ calendar: Calendar,
27
+ },
22
28
  });
23
29
 
24
30
  webex.canAuthorize = true;
25
31
  webex.internal.device = {
26
32
  register: sinon.stub().returns(Promise.resolve()),
27
- unregister: sinon.stub().returns(Promise.resolve())
33
+ unregister: sinon.stub().returns(Promise.resolve()),
28
34
  };
29
35
  webex.internal.mercury = {
30
36
  connect: sinon.stub().returns(Promise.resolve()),
@@ -40,16 +46,73 @@ describe('internal-plugin-calendar', () => {
40
46
  callback({data: {calendarMeetingExternal: {id: 'calendarId1'}}});
41
47
  }
42
48
  }),
43
- off: sinon.spy()
49
+ off: sinon.spy(),
50
+ };
51
+ webex.internal.encryption = {
52
+ kms: {
53
+ createUnboundKeys: sinon.stub().resolves([{
54
+ uri: "kms://kms-us-int.wbx2.com/keys/xxxx-xxxx-xxxx-xxxx"
55
+ }])
56
+ },
57
+ encryptText: sinon.stub().resolves("encryptedText")
44
58
  };
45
59
  });
46
60
 
61
+ describe('Private API', () => {
62
+ describe('#prefetchEncryptionKey', () => {
63
+ it('waits for the ability to authorize before doing anything', () => {
64
+ webex.canAuthorize = false;
65
+
66
+ webex.internal.calendar.prefetchEncryptionKey();
67
+
68
+ assert.notCalled(webex.internal.encryption.kms.createUnboundKeys);
69
+
70
+ // Behaviour when the user can authorize is tested elsewhere, so just ensure it gets called again
71
+ const prefetchEncryptionKeyStub = sinon.stub(webex.internal.calendar, 'prefetchEncryptionKey');
72
+
73
+ webex.trigger('change:canAuthorize');
74
+
75
+ assert.calledOnce(prefetchEncryptionKeyStub);
76
+ assert.calledWith(prefetchEncryptionKeyStub);
77
+ });
78
+
79
+ it('does nothing when the current user is an unverified guest', () => {
80
+ webex.credentials.isUnverifiedGuest = true;
81
+
82
+ webex.internal.calendar.prefetchEncryptionKey();
83
+
84
+ assert.notCalled(webex.internal.encryption.kms.createUnboundKeys);
85
+ });
86
+
87
+ it('creates an encryption key when the current user can authorize', () => {
88
+ webex.internal.calendar.prefetchEncryptionKey();
89
+
90
+ assert.calledOnce(webex.internal.encryption.kms.createUnboundKeys);
91
+ assert.calledWith(webex.internal.encryption.kms.createUnboundKeys, {count: 1});
92
+ });
93
+ });
94
+
95
+ describe('#initialize', () => {
96
+ it('adds relevant handlers when webex is ready', () => {
97
+ const prefetchEncryptionKeyStub = sinon.stub(webex.internal.calendar, 'prefetchEncryptionKey');
98
+
99
+ assert.notCalled(prefetchEncryptionKeyStub);
100
+
101
+ // Initialize should have already run, so there should be an event handler already
102
+ webex.trigger('ready');
103
+
104
+ assert.calledOnce(prefetchEncryptionKeyStub);
105
+ assert.calledWith(prefetchEncryptionKeyStub);
106
+ });
107
+ });
108
+ });
109
+
47
110
  describe('Public Api Contract', () => {
48
111
  describe('#register()', () => {
49
112
  it('on calendar register call mercury registration', async () => {
50
113
  await webex.internal.calendar.register();
51
114
  assert.calledOnce(webex.internal.device.register);
52
- assert.callCount(webex.internal.mercury.on, 5);
115
+ assert.callCount(webex.internal.mercury.on, 6);
53
116
  assert.equal(webex.internal.calendar.registered, true);
54
117
  });
55
118
  it('should trigger `calendar:register` event', async () => {
@@ -91,7 +154,7 @@ describe('internal-plugin-calendar', () => {
91
154
  it('should call `mercury.unregister` and `device.unregister`', async () => {
92
155
  await webex.internal.calendar.register();
93
156
  await webex.internal.calendar.unregister();
94
- assert.callCount(webex.internal.mercury.off, 5);
157
+ assert.callCount(webex.internal.mercury.off, 6);
95
158
  assert.calledOnce(webex.internal.mercury.disconnect);
96
159
  assert.calledOnce(webex.internal.device.unregister);
97
160
  });
@@ -108,14 +171,25 @@ describe('internal-plugin-calendar', () => {
108
171
 
109
172
  describe('#syncCalendar()', () => {
110
173
  it('should sync from calendar service', async () => {
111
- webex.request = sinon.stub().returns(Promise.resolve({body: {items: [{id: 'calendar1'}, {id: 'calendar2'}]}})); webex.request = sinon.stub().returns(
174
+ webex.request = sinon
175
+ .stub()
176
+ .returns(Promise.resolve({body: {items: [{id: 'calendar1'}, {id: 'calendar2'}]}}));
177
+ webex.request = sinon.stub().returns(
112
178
  Promise.resolve({
113
179
  body: {
114
180
  items: [
115
- {id: 'calendar1', encryptedNotes: 'notes1', encryptedParticipants: ['participant1']},
116
- {id: 'calendar2', encryptedNotes: 'notes2', encryptedParticipants: ['participant2']}
117
- ]
118
- }
181
+ {
182
+ id: 'calendar1',
183
+ encryptedNotes: 'notes1',
184
+ encryptedParticipants: ['participant1'],
185
+ },
186
+ {
187
+ id: 'calendar2',
188
+ encryptedNotes: 'notes2',
189
+ encryptedParticipants: ['participant2'],
190
+ },
191
+ ],
192
+ },
119
193
  })
120
194
  );
121
195
  await webex.internal.calendar.syncCalendar({fromDate: 'xx-xx', toDate: 'xx-nn'});
@@ -123,7 +197,7 @@ describe('internal-plugin-calendar', () => {
123
197
  method: 'GET',
124
198
  service: 'calendar',
125
199
  resource: 'calendarEvents',
126
- qs: {fromDate: 'xx-xx', toDate: 'xx-nn'}
200
+ qs: {fromDate: 'xx-xx', toDate: 'xx-nn'},
127
201
  });
128
202
  assert.equal(webex.internal.calendar.getAll().length, 2);
129
203
  assert.equal(webex.internal.calendar.getAll()[0].id, 'calendar1');
@@ -136,10 +210,18 @@ describe('internal-plugin-calendar', () => {
136
210
  Promise.resolve({
137
211
  body: {
138
212
  items: [
139
- {id: 'calendar1', encryptedNotes: 'notes1', encryptedParticipants: ['participant1']},
140
- {id: 'calendar2', encryptedNotes: 'notes2', encryptedParticipants: ['participant2']}
141
- ]
142
- }
213
+ {
214
+ id: 'calendar1',
215
+ encryptedNotes: 'notes1',
216
+ encryptedParticipants: ['participant1'],
217
+ },
218
+ {
219
+ id: 'calendar2',
220
+ encryptedNotes: 'notes2',
221
+ encryptedParticipants: ['participant2'],
222
+ },
223
+ ],
224
+ },
143
225
  })
144
226
  );
145
227
  const res = await webex.internal.calendar.list({fromDate: 'xx-xx', toDate: 'xx-nn'});
@@ -149,7 +231,7 @@ describe('internal-plugin-calendar', () => {
149
231
  method: 'GET',
150
232
  service: 'calendar',
151
233
  resource: 'calendarEvents',
152
- qs: {fromDate: 'xx-xx', toDate: 'xx-nn'}
234
+ qs: {fromDate: 'xx-xx', toDate: 'xx-nn'},
153
235
  });
154
236
  });
155
237
 
@@ -157,31 +239,27 @@ describe('internal-plugin-calendar', () => {
157
239
  const webexRequestStub = sinon.stub();
158
240
 
159
241
  // calendar list stub
160
- webexRequestStub.withArgs({
161
- method: 'GET',
162
- service: 'calendar',
163
- resource: 'calendarEvents',
164
- qs: {fromDate: 'xx-xx', toDate: 'xx-nn'}
165
- }).returns(
166
- Promise.resolve({
167
- body: {
168
- items: [
169
- {id: 'calendar1', encryptedParticipants: ['participant1']},
170
- {id: 'calendar2', encryptedNotes: 'notes2', encryptedParticipants: ['participant2']}
171
- ]
172
- }
242
+ webexRequestStub
243
+ .withArgs({
244
+ method: 'GET',
245
+ service: 'calendar',
246
+ resource: 'calendarEvents',
247
+ qs: {fromDate: 'xx-xx', toDate: 'xx-nn'},
173
248
  })
174
- );
175
- // getNotes stub
176
- webexRequestStub.withArgs({
177
- method: 'GET',
178
- service: 'calendar',
179
- resource: `calendarEvents/${btoa('calendar1')}/notes`
180
- }).returns(
181
- Promise.resolve({
182
- body: null
183
- })
184
- );
249
+ .returns(
250
+ Promise.resolve({
251
+ body: {
252
+ items: [
253
+ {id: 'calendar1', encryptedParticipants: ['participant1']},
254
+ {
255
+ id: 'calendar2',
256
+ encryptedNotes: 'notes2',
257
+ encryptedParticipants: ['participant2'],
258
+ },
259
+ ],
260
+ },
261
+ })
262
+ );
185
263
 
186
264
  // Assign webexRequestStub to webex.request
187
265
  webex.request = webexRequestStub;
@@ -190,19 +268,14 @@ describe('internal-plugin-calendar', () => {
190
268
 
191
269
  assert.equal(res.length, 2);
192
270
  assert.deepEqual(res, [
193
- {id: 'calendar1', encryptedNotes: null, encryptedParticipants: ['participant1']},
194
- {id: 'calendar2', encryptedNotes: 'notes2', encryptedParticipants: ['participant2']}
271
+ {id: 'calendar1', encryptedParticipants: ['participant1']},
272
+ {id: 'calendar2', encryptedNotes: 'notes2', encryptedParticipants: ['participant2']},
195
273
  ]);
196
274
  assert.calledWith(webex.request, {
197
275
  method: 'GET',
198
276
  service: 'calendar',
199
277
  resource: 'calendarEvents',
200
- qs: {fromDate: 'xx-xx', toDate: 'xx-nn'}
201
- });
202
- assert.calledWith(webex.request, {
203
- method: 'GET',
204
- service: 'calendar',
205
- resource: `calendarEvents/${btoa('calendar1')}/notes`
278
+ qs: {fromDate: 'xx-xx', toDate: 'xx-nn'},
206
279
  });
207
280
  });
208
281
 
@@ -210,33 +283,27 @@ describe('internal-plugin-calendar', () => {
210
283
  const webexRequestStub = sinon.stub();
211
284
 
212
285
  // calendar list stub
213
- webexRequestStub.withArgs({
214
- method: 'GET',
215
- service: 'calendar',
216
- resource: 'calendarEvents',
217
- qs: {fromDate: 'xx-xx', toDate: 'xx-nn'}
218
- }).returns(
219
- Promise.resolve({
220
- body: {
221
- items: [
222
- {id: 'calendar1', encryptedParticipants: ['participant1']},
223
- {id: 'calendar2', encryptedNotes: 'notes2', encryptedParticipants: ['participant2']}
224
- ]
225
- }
226
- })
227
- );
228
- // getNotes stub
229
- webexRequestStub.withArgs({
230
- method: 'GET',
231
- service: 'calendar',
232
- resource: `calendarEvents/${btoa('calendar1')}/notes`
233
- }).returns(
234
- Promise.resolve({
235
- body: {
236
- encryptedNotes: 'notes1'
237
- }
286
+ webexRequestStub
287
+ .withArgs({
288
+ method: 'GET',
289
+ service: 'calendar',
290
+ resource: 'calendarEvents',
291
+ qs: {fromDate: 'xx-xx', toDate: 'xx-nn'},
238
292
  })
239
- );
293
+ .returns(
294
+ Promise.resolve({
295
+ body: {
296
+ items: [
297
+ {id: 'calendar1', encryptedNotes: 'notes1', encryptedParticipants: ['participant1']},
298
+ {
299
+ id: 'calendar2',
300
+ encryptedNotes: 'notes2',
301
+ encryptedParticipants: ['participant2'],
302
+ },
303
+ ],
304
+ },
305
+ })
306
+ );
240
307
 
241
308
  // Assign webexRequestStub to webex.request
242
309
  webex.request = webexRequestStub;
@@ -246,18 +313,13 @@ describe('internal-plugin-calendar', () => {
246
313
  assert.equal(res.length, 2);
247
314
  assert.deepEqual(res, [
248
315
  {id: 'calendar1', encryptedNotes: 'notes1', encryptedParticipants: ['participant1']},
249
- {id: 'calendar2', encryptedNotes: 'notes2', encryptedParticipants: ['participant2']}
316
+ {id: 'calendar2', encryptedNotes: 'notes2', encryptedParticipants: ['participant2']},
250
317
  ]);
251
318
  assert.calledWith(webex.request, {
252
319
  method: 'GET',
253
320
  service: 'calendar',
254
321
  resource: 'calendarEvents',
255
- qs: {fromDate: 'xx-xx', toDate: 'xx-nn'}
256
- });
257
- assert.calledWith(webex.request, {
258
- method: 'GET',
259
- service: 'calendar',
260
- resource: `calendarEvents/${btoa('calendar1')}/notes`
322
+ qs: {fromDate: 'xx-xx', toDate: 'xx-nn'},
261
323
  });
262
324
  });
263
325
  });
@@ -269,8 +331,8 @@ describe('internal-plugin-calendar', () => {
269
331
  webex.request = sinon.stub().returns(
270
332
  Promise.resolve({
271
333
  body: {
272
- encryptedNotes: 'notes1'
273
- }
334
+ encryptedNotes: 'notes1',
335
+ },
274
336
  })
275
337
  );
276
338
 
@@ -280,30 +342,172 @@ describe('internal-plugin-calendar', () => {
280
342
  assert.calledWith(webex.request, {
281
343
  method: 'GET',
282
344
  service: 'calendar',
283
- resource: `calendarEvents/${btoa(id)}/notes`
345
+ resource: `calendarEvents/${base64.encode(id)}/notes`,
284
346
  });
285
347
  });
286
348
  });
287
349
 
288
350
  describe('#getParticipants()', () => {
289
- const id = 'meetingId123';
351
+ const uri = 'participantsUrl';
290
352
 
291
353
  it('should fetch the meeting participants', async () => {
292
354
  webex.request = sinon.stub().returns(
293
355
  Promise.resolve({
294
356
  body: {
295
- encryptedParticipants: ['participant1']
296
- }
357
+ encryptedParticipants: ['participant1'],
358
+ },
297
359
  })
298
360
  );
299
361
 
300
- const res = await webex.internal.calendar.getParticipants(id);
362
+ const res = await webex.internal.calendar.getParticipants(uri);
301
363
 
302
364
  assert.equal(res.body.encryptedParticipants.length, 1);
303
365
  assert.calledWith(webex.request, {
304
366
  method: 'GET',
305
- service: 'calendar',
306
- resource: `calendarEvents/${btoa(id)}/participants`
367
+ uri,
368
+ });
369
+ });
370
+ });
371
+
372
+ describe('#getNotesByUrl()', () => {
373
+ const uri = 'notesUrl';
374
+
375
+ it('should fetch the meeting notes', async () => {
376
+ webex.request = sinon.stub().returns(
377
+ Promise.resolve({
378
+ body: {
379
+ encryptedParticipants: ['participant1'],
380
+ },
381
+ })
382
+ );
383
+
384
+ const res = await webex.internal.calendar.getNotesByUrl(uri);
385
+
386
+ assert.equal(res.body.encryptedParticipants.length, 1);
387
+ assert.calledWith(webex.request, {
388
+ method: 'GET',
389
+ uri,
390
+ });
391
+ });
392
+ });
393
+
394
+ describe("#getSchedulerData()", () => {
395
+ it("should fetch meeting calendar data", async () => {
396
+ const query = {
397
+ siteName: "scheduler01.dmz.webex.com",
398
+ clientMeetingId: "YWJjZGFiY2QtYWJjZC1hYmNkLWFiY2QtMDAwMDAwMDA"
399
+ };
400
+
401
+ webex.request = sinon.stub().resolves({
402
+ body: {
403
+ encryptedSubject: "My Meeting 1",
404
+ schedulerPreferences: {
405
+ uiControlAttributes: {
406
+ displayHostSaveMeetingTemplate: true
407
+ },
408
+ webexOptions: {
409
+ sessionTypeId: 3
410
+ }
411
+ }
412
+ }
413
+ });
414
+
415
+ const res = await webex.internal.calendar.getSchedulerData(query);
416
+
417
+ expect(res.body.encryptedSubject).to.equal("My Meeting 1");
418
+ expect(res.body.schedulerPreferences.uiControlAttributes.displayHostSaveMeetingTemplate).to.be.true;
419
+ expect(res.body.schedulerPreferences.webexOptions.sessionTypeId).to.equal(3);
420
+ assert.calledWith(webex.request, {
421
+ method: "GET",
422
+ service: "calendar",
423
+ resource: "schedulerData",
424
+ qs: {
425
+ siteName: query.siteName,
426
+ clientMeetingId: query.clientMeetingId
427
+ }
428
+ });
429
+ });
430
+ });
431
+
432
+ describe("#createCalendarEvent()", () => {
433
+ it("should create an calendar event", async () => {
434
+ const data = {
435
+ encryptionKeyUrl: "kms://kms-us-int.wbx2.com/keys/d1c14fc5-be10-4389-ae83-9521f92fbfd3",
436
+ notes: "This is Agenda",
437
+ subject: "My Meeting 1",
438
+ webexOptions: "{}"
439
+ };
440
+ const query = {};
441
+
442
+ webex.request = sinon.stub().resolves({
443
+ body: {
444
+ meetingId: "abcdabcd-abcd-abcd-abcd-00000000",
445
+ globalMeetingId: "xxxx-xxxx-xxxx-xxxx"
446
+ }
447
+ });
448
+
449
+ const res = await webex.internal.calendar.createCalendarEvent(data);
450
+
451
+ expect(res.body.meetingId).to.equal("abcdabcd-abcd-abcd-abcd-00000000");
452
+ expect(res.body.globalMeetingId).to.equal("xxxx-xxxx-xxxx-xxxx");
453
+ assert.calledWith(webex.request, {
454
+ method: "POST",
455
+ service: "calendar",
456
+ body: data,
457
+ resource: "calendarEvents/sync",
458
+ qs: query
459
+ });
460
+ });
461
+ });
462
+
463
+ describe("#updateCalendarEvent()", () => {
464
+ it("should update a calendar event", async () => {
465
+ const id = "abcdabcd-abcd-abcd-abcd-00000000";
466
+ const data = {
467
+ encryptionKeyUrl: "kms://kms-us-int.wbx2.com/keys/d1c14fc5-be10-4389-ae83-9521f92fbfd3",
468
+ notes: "This is Agenda",
469
+ subject: "My Meeting 1",
470
+ webexOptions: "{}"
471
+ };
472
+ const query = {};
473
+
474
+ webex.request = sinon.stub().resolves({
475
+ body: {
476
+ meetingId: "abcdabcd-abcd-abcd-abcd-00000000",
477
+ globalMeetingId: "xxxx-xxxx-xxxx-xxxx"
478
+ }
479
+ });
480
+
481
+ const res = await webex.internal.calendar.updateCalendarEvent(id, data);
482
+
483
+ expect(res.body.meetingId).to.equal("abcdabcd-abcd-abcd-abcd-00000000");
484
+ expect(res.body.globalMeetingId).to.equal("xxxx-xxxx-xxxx-xxxx");
485
+ assert.calledWith(webex.request, {
486
+ method: "PATCH",
487
+ service: "calendar",
488
+ body: data,
489
+ resource: `calendarEvents/${base64.encode(id)}/sync`,
490
+ qs: query
491
+ });
492
+ });
493
+ });
494
+
495
+ describe("#deleteCalendarEvent()", () => {
496
+ it("should delete a calendar event", async () => {
497
+ const id = "abcdabcd-abcd-abcd-abcd-00000000";
498
+ const query = {};
499
+
500
+ webex.request = sinon.stub().resolves({
501
+ body: {}
502
+ });
503
+
504
+ await webex.internal.calendar.deleteCalendarEvent(id, query);
505
+
506
+ assert.calledWith(webex.request, {
507
+ method: "DELETE",
508
+ service: "calendar",
509
+ resource: `calendarEvents/${base64.encode(id)}/sync`,
510
+ qs: query
307
511
  });
308
512
  });
309
513
  });
@@ -5,7 +5,10 @@ import CalendarUtils from '../../../src/util';
5
5
  describe('Calendar utils', () => {
6
6
  describe('#calculateEndTime()', () => {
7
7
  it('return the end time for meeting', () => {
8
- const result = CalendarUtils.calculateEndTime({start: '2020-02-21T18:57:00.000Z', durationMinutes: 30});
8
+ const result = CalendarUtils.calculateEndTime({
9
+ start: '2020-02-21T18:57:00.000Z',
10
+ durationMinutes: 30,
11
+ });
9
12
 
10
13
  assert.equal(new Date(result.endTime).toISOString(), '2020-02-21T19:27:00.000Z');
11
14
  });