@webex/plugin-meetings 3.7.0-next.10 → 3.7.0-next.12

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.
@@ -2492,9 +2492,11 @@ describe('plugin-meetings', () => {
2492
2492
  mediaSettings: {},
2493
2493
  });
2494
2494
 
2495
- const checkLogCounter = (delay, expectedCounter) => {
2495
+ const checkLogCounter = (delayInMinutes, expectedCounter) => {
2496
+ const delayInMilliseconds = delayInMinutes * 60 * 1000;
2497
+
2496
2498
  // first check that the counter is not increased just before the delay
2497
- clock.tick(delay - 50);
2499
+ clock.tick(delayInMilliseconds - 50);
2498
2500
  assert.equal(logUploadCounter, expectedCounter - 1);
2499
2501
 
2500
2502
  // and now check that it has reached expected value after the delay
@@ -2502,22 +2504,18 @@ describe('plugin-meetings', () => {
2502
2504
  assert.equal(logUploadCounter, expectedCounter);
2503
2505
  };
2504
2506
 
2505
- checkLogCounter(100, 1);
2506
- checkLogCounter(1000, 2);
2507
- checkLogCounter(15000, 3);
2508
- checkLogCounter(15000, 4);
2509
- checkLogCounter(30000, 5);
2510
- checkLogCounter(30000, 6);
2511
- checkLogCounter(30000, 7);
2512
- checkLogCounter(60000, 8);
2513
- checkLogCounter(60000, 9);
2514
- checkLogCounter(60000, 10);
2515
-
2516
- // simulate media connection being removed -> no more log uploads should happen
2507
+ checkLogCounter(0.1, 1);
2508
+ checkLogCounter(15, 2);
2509
+ checkLogCounter(30, 3);
2510
+ checkLogCounter(60, 4);
2511
+ checkLogCounter(60, 5);
2512
+
2513
+ // simulate media connection being removed -> 1 more upload should happen, but nothing more afterwards
2517
2514
  meeting.mediaProperties.webrtcMediaConnection = undefined;
2515
+ checkLogCounter(60, 6);
2518
2516
 
2519
- clock.tick(60000);
2520
- assert.equal(logUploadCounter, 11);
2517
+ clock.tick(120*1000*60);
2518
+ assert.equal(logUploadCounter, 6);
2521
2519
 
2522
2520
  clock.restore();
2523
2521
  });
@@ -2,6 +2,7 @@ import {assert, expect} from '@webex/test-helper-chai';
2
2
  import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
3
3
  import Webinar from '@webex/plugin-meetings/src/webinar';
4
4
  import MockWebex from '@webex/test-helper-mock-webex';
5
+ import uuid from 'uuid';
5
6
  import sinon from 'sinon';
6
7
 
7
8
  describe('plugin-meetings', () => {
@@ -9,18 +10,28 @@ describe('plugin-meetings', () => {
9
10
 
10
11
  let webex;
11
12
  let webinar;
13
+ let uuidStub;
14
+ let getUserTokenStub;
12
15
 
13
16
  beforeEach(() => {
14
17
  // @ts-ignore
18
+ getUserTokenStub = sinon.stub().resolves('test-token');
19
+ uuidStub = sinon.stub(uuid,'v4').returns('test-uuid');
15
20
  webex = new MockWebex({});
16
21
  webex.internal.mercury.on = sinon.stub();
17
22
  webinar = new Webinar({}, {parent: webex});
18
23
  webinar.locusUrl = 'locusUrl';
24
+ webinar.webcastInstanceUrl = 'webcastInstanceUrl';
19
25
  webex.request = sinon.stub().returns(Promise.resolve('REQUEST_RETURN_VALUE'));
20
26
  webex.meetings = {};
27
+ webex.credentials.getUserToken = getUserTokenStub;
21
28
  webex.meetings.getMeetingByType = sinon.stub();
22
29
  });
23
30
 
31
+ afterEach(() => {
32
+ sinon.restore();
33
+ });
34
+
24
35
  describe('#locusUrlUpdate', () => {
25
36
  it('sets the locus url', () => {
26
37
  webinar.locusUrlUpdate('newUrl');
@@ -168,6 +179,311 @@ describe('plugin-meetings', () => {
168
179
  });
169
180
  });
170
181
 
182
+ describe("#startWebcast", () => {
183
+ const meeting = {
184
+ locusId: 'locusId',
185
+ correlationId: 'correlationId',
186
+ }
187
+ const layout = {
188
+ videoLayout: 'Prominent',
189
+ contentLayout: 'Prominent',
190
+ syncStageLayout: false,
191
+ syncStageInMeeting: false,
192
+ }
193
+ it(`sends a PUT request to start the webcast`, async () => {
194
+ const result = await webinar.startWebcast(meeting, layout);
195
+ assert.calledOnce(webex.request);
196
+ assert.calledWith(webex.request, {
197
+ method: "PUT",
198
+ uri: `${webinar.webcastInstanceUrl}/streaming`,
199
+ headers: {
200
+ authorization: 'test-token',
201
+ trackingId: 'webex-js-sdk_test-uuid',
202
+ 'Content-Type': 'application/json'
203
+ },
204
+ body: {
205
+ action: 'start',
206
+ meetingInfo: {
207
+ locusId: meeting.locusId,
208
+ correlationId: meeting.correlationId,
209
+ },
210
+ layout,
211
+ }
212
+ });
213
+ assert.equal(result, "REQUEST_RETURN_VALUE", "should return the resolved value from the request");
214
+ });
215
+
216
+ it('should handle undefined meeting parameter', async () => {
217
+ const errorLogger = sinon.stub(LoggerProxy.logger, 'error');
218
+
219
+ try {
220
+ await webinar.startWebcast(undefined, layout);
221
+ assert.fail('startWebcast should throw an error');
222
+ } catch (error) {
223
+ assert.equal(error.message, 'Meeting parameter does not meet expectations', 'should throw the correct error');
224
+ assert.calledOnce(errorLogger);
225
+ assert.calledWith(errorLogger, `Meeting:webinar#startWebcast failed --> meeting parameter : ${undefined}`);
226
+ } finally {
227
+ errorLogger.restore();
228
+ }
229
+ });
230
+
231
+ it('handles API call failures gracefully', async () => {
232
+ webex.request.rejects(new Error('API_ERROR'));
233
+ const errorLogger = sinon.stub(LoggerProxy.logger, 'error');
234
+
235
+ try {
236
+ await webinar.startWebcast(meeting, layout);
237
+ assert.fail('startWebcast should throw an error');
238
+ } catch (error) {
239
+ assert.equal(error.message, 'API_ERROR', 'should throw the correct error');
240
+ assert.calledOnce(errorLogger);
241
+ assert.calledWith(errorLogger, 'Meeting:webinar#startWebcast failed', sinon.match.instanceOf(Error));
242
+ } finally {
243
+ errorLogger.restore();
244
+ }
245
+ });
246
+ });
247
+
248
+ describe("#stopWebcast", () => {
249
+ it(`sends a PUT request to stop the webcast`, async () => {
250
+ const result = await webinar.stopWebcast();
251
+ assert.calledOnce(webex.request);
252
+ assert.calledWith(webex.request, {
253
+ method: "PUT",
254
+ uri: `${webinar.webcastInstanceUrl}/streaming`,
255
+ headers: {
256
+ authorization: 'test-token',
257
+ trackingId: 'webex-js-sdk_test-uuid',
258
+ 'Content-Type': 'application/json'
259
+ },
260
+ body: {
261
+ action: 'stop',
262
+ }
263
+ });
264
+ assert.equal(result, "REQUEST_RETURN_VALUE", "should return the resolved value from the request");
265
+ });
266
+
267
+ it('handles API call failures gracefully', async () => {
268
+ webex.request.rejects(new Error('API_ERROR'));
269
+ const errorLogger = sinon.stub(LoggerProxy.logger, 'error');
270
+
271
+ try {
272
+ await webinar.stopWebcast();
273
+ assert.fail('stopWebcast should throw an error');
274
+ } catch (error) {
275
+ assert.equal(error.message, 'API_ERROR', 'should throw the correct error');
276
+ assert.calledOnce(errorLogger);
277
+ assert.calledWith(errorLogger, 'Meeting:webinar#stopWebcast failed', sinon.match.instanceOf(Error));
278
+ } finally {
279
+ errorLogger.restore();
280
+ }
281
+ });
282
+ });
283
+
171
284
 
285
+ describe("#queryWebcastLayout", () => {
286
+ it(`sends a GET request to query the webcast layout`, async () => {
287
+ const result = await webinar.queryWebcastLayout();
288
+ assert.calledOnce(webex.request);
289
+ assert.calledWith(webex.request, {
290
+ method: "GET",
291
+ uri: `${webinar.webcastInstanceUrl}/layout`,
292
+ headers: {
293
+ authorization: 'test-token',
294
+ trackingId: 'webex-js-sdk_test-uuid',
295
+ },
296
+ });
297
+ assert.equal(result, "REQUEST_RETURN_VALUE", "should return the resolved value from the request");
298
+ });
299
+
300
+ it('handles API call failures gracefully', async () => {
301
+ webex.request.rejects(new Error('API_ERROR'));
302
+ const errorLogger = sinon.stub(LoggerProxy.logger, 'error');
303
+
304
+ try {
305
+ await webinar.queryWebcastLayout();
306
+ assert.fail('queryWebcastLayout should throw an error');
307
+ } catch (error) {
308
+ assert.equal(error.message, 'API_ERROR', 'should throw the correct error');
309
+ assert.calledOnce(errorLogger);
310
+ assert.calledWith(errorLogger, 'Meeting:webinar#queryWebcastLayout failed', sinon.match.instanceOf(Error));
311
+ } finally {
312
+ errorLogger.restore();
313
+ }
314
+ });
315
+ });
316
+
317
+ describe("#updateWebcastLayout", () => {
318
+ const layout = {
319
+ videoLayout: 'Prominent',
320
+ contentLayout: 'Prominent',
321
+ syncStageLayout: false,
322
+ syncStageInMeeting: false,
323
+ }
324
+ it(`sends a PUT request to update the webcast layout`, async () => {
325
+ const result = await webinar.updateWebcastLayout(layout);
326
+ assert.calledOnce(webex.request);
327
+ assert.calledWith(webex.request, {
328
+ method: "PUT",
329
+ uri: `${webinar.webcastInstanceUrl}/layout`,
330
+ headers: {
331
+ authorization: 'test-token',
332
+ trackingId: 'webex-js-sdk_test-uuid',
333
+ 'Content-Type': 'application/json'
334
+ },
335
+ body: {
336
+ layout
337
+ }
338
+ });
339
+ assert.equal(result, "REQUEST_RETURN_VALUE", "should return the resolved value from the request");
340
+ });
341
+
342
+ it('handles API call failures gracefully', async () => {
343
+ webex.request.rejects(new Error('API_ERROR'));
344
+ const errorLogger = sinon.stub(LoggerProxy.logger, 'error');
345
+
346
+ try {
347
+ await webinar.updateWebcastLayout(layout);
348
+ assert.fail('updateWebcastLayout should throw an error');
349
+ } catch (error) {
350
+ assert.equal(error.message, 'API_ERROR', 'should throw the correct error');
351
+ assert.calledOnce(errorLogger);
352
+ assert.calledWith(errorLogger, 'Meeting:webinar#updateWebcastLayout failed', sinon.match.instanceOf(Error));
353
+ } finally {
354
+ errorLogger.restore();
355
+ }
356
+ });
357
+ });
358
+
359
+ describe("#searchWebcastAttendees", () => {
360
+ const queryString = 'queryString';
361
+ const specialCharsQuery = 'query@string!';
362
+ const emptyQuery = '';
363
+
364
+ it("sends a GET request to search the webcast attendees", async () => {
365
+ const result = await webinar.searchWebcastAttendees(queryString);
366
+ assert.calledOnce(webex.request);
367
+ assert.calledWith(webex.request, {
368
+ method: "GET",
369
+ uri: `${webinar.webcastInstanceUrl}/attendees?keyword=${encodeURIComponent(queryString)}`,
370
+ headers: {
371
+ authorization: 'test-token',
372
+ trackingId: 'webex-js-sdk_test-uuid',
373
+ },
374
+ });
375
+ assert.equal(result, "REQUEST_RETURN_VALUE", "should return the resolved value from the request");
376
+ });
377
+
378
+ it('handles API call failures gracefully', async () => {
379
+ webex.request.rejects(new Error('API_ERROR'));
380
+ const errorLogger = sinon.stub(LoggerProxy.logger, 'error');
381
+
382
+ try {
383
+ await webinar.searchWebcastAttendees(queryString);
384
+ assert.fail('searchWebcastAttendees should throw an error');
385
+ } catch (error) {
386
+ assert.equal(error.message, 'API_ERROR', 'should throw the correct error');
387
+ assert.calledOnce(errorLogger);
388
+ assert.calledWith(errorLogger, 'Meeting:webinar#searchWebcastAttendees failed', sinon.match.instanceOf(Error));
389
+ } finally {
390
+ errorLogger.restore();
391
+ }
392
+ });
393
+
394
+ it("should handle empty query string", async () => {
395
+ const result = await webinar.searchWebcastAttendees(emptyQuery);
396
+ assert.calledOnce(webex.request);
397
+ assert.calledWith(webex.request, {
398
+ method: "GET",
399
+ uri: `${webinar.webcastInstanceUrl}/attendees?keyword=${encodeURIComponent(emptyQuery)}`,
400
+ headers: {
401
+ authorization: 'test-token',
402
+ trackingId: 'webex-js-sdk_test-uuid',
403
+ },
404
+ });
405
+ assert.equal(result, "REQUEST_RETURN_VALUE", "should return the resolved value from the request");
406
+ });
407
+
408
+ it("should handle query string with special characters", async () => {
409
+ const result = await webinar.searchWebcastAttendees(specialCharsQuery);
410
+ assert.calledOnce(webex.request);
411
+ assert.calledWith(webex.request, {
412
+ method: "GET",
413
+ uri: `${webinar.webcastInstanceUrl}/attendees?keyword=${encodeURIComponent(specialCharsQuery)}`,
414
+ headers: {
415
+ authorization: 'test-token',
416
+ trackingId: 'webex-js-sdk_test-uuid',
417
+ },
418
+ });
419
+ assert.equal(result, "REQUEST_RETURN_VALUE", "should return the resolved value from the request");
420
+ });
421
+ });
422
+
423
+
424
+ describe("#viewAllWebcastAttendees", () => {
425
+ it(`sends a GET request to view all the webcast attendees`, async () => {
426
+ const result = await webinar.viewAllWebcastAttendees();
427
+ assert.calledOnce(webex.request);
428
+ assert.calledWith(webex.request, {
429
+ method: "GET",
430
+ uri: `${webinar.webcastInstanceUrl}/attendees`,
431
+ headers: {
432
+ authorization: 'test-token',
433
+ trackingId: 'webex-js-sdk_test-uuid',
434
+ },
435
+ });
436
+ assert.equal(result, "REQUEST_RETURN_VALUE", "should return the resolved value from the request");
437
+ });
438
+
439
+ it('handles API call failures gracefully', async () => {
440
+ webex.request.rejects(new Error('API_ERROR'));
441
+ const errorLogger = sinon.stub(LoggerProxy.logger, 'error');
442
+
443
+ try {
444
+ await webinar.viewAllWebcastAttendees();
445
+ assert.fail('viewAllWebcastAttendees should throw an error');
446
+ } catch (error) {
447
+ assert.equal(error.message, 'API_ERROR', 'should throw the correct error');
448
+ assert.calledOnce(errorLogger);
449
+ assert.calledWith(errorLogger, 'Meeting:webinar#viewAllWebcastAttendees failed', sinon.match.instanceOf(Error));
450
+ } finally {
451
+ errorLogger.restore();
452
+ }
453
+ });
454
+ });
455
+
456
+ describe("#expelWebcastAttendee", () => {
457
+ const participantId = 'participantId'
458
+ it(`sends a DELETE request to expel the webcast attendee`, async () => {
459
+ const result = await webinar.expelWebcastAttendee(participantId);
460
+ assert.calledOnce(webex.request);
461
+ assert.calledWith(webex.request, {
462
+ method: "DELETE",
463
+ uri: `${webinar.webcastInstanceUrl}/attendees/${participantId}`,
464
+ headers: {
465
+ authorization: 'test-token',
466
+ trackingId: 'webex-js-sdk_test-uuid',
467
+ },
468
+ });
469
+ assert.equal(result, "REQUEST_RETURN_VALUE", "should return the resolved value from the request");
470
+ });
471
+
472
+ it('handles API call failures gracefully', async () => {
473
+ webex.request.rejects(new Error('API_ERROR'));
474
+ const errorLogger = sinon.stub(LoggerProxy.logger, 'error');
475
+
476
+ try {
477
+ await webinar.expelWebcastAttendee(participantId);
478
+ assert.fail('expelWebcastAttendee should throw an error');
479
+ } catch (error) {
480
+ assert.equal(error.message, 'API_ERROR', 'should throw the correct error');
481
+ assert.calledOnce(errorLogger);
482
+ assert.calledWith(errorLogger, 'Meeting:webinar#expelWebcastAttendee failed', sinon.match.instanceOf(Error));
483
+ } finally {
484
+ errorLogger.restore();
485
+ }
486
+ });
487
+ });
172
488
  })
173
489
  })