@webex/internal-plugin-metrics 3.0.0-beta.19 → 3.0.0-beta.191

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.
Files changed (67) hide show
  1. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +134 -0
  2. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -0
  3. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +451 -0
  4. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -0
  5. package/dist/call-diagnostic/call-diagnostic-metrics.js +511 -0
  6. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -0
  7. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +106 -0
  8. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -0
  9. package/dist/call-diagnostic/config.js +461 -0
  10. package/dist/call-diagnostic/config.js.map +1 -0
  11. package/dist/call-diagnostic/generated-types-temp/ClientEvent.js +7 -0
  12. package/dist/call-diagnostic/generated-types-temp/ClientEvent.js.map +1 -0
  13. package/dist/call-diagnostic/generated-types-temp/Event.js +7 -0
  14. package/dist/call-diagnostic/generated-types-temp/Event.js.map +1 -0
  15. package/dist/call-diagnostic/generated-types-temp/MediaQualityEvent.js +7 -0
  16. package/dist/call-diagnostic/generated-types-temp/MediaQualityEvent.js.map +1 -0
  17. package/dist/config.js +20 -1
  18. package/dist/config.js.map +1 -1
  19. package/dist/index.js +25 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/metrics.js +30 -30
  22. package/dist/metrics.js.map +1 -1
  23. package/dist/metrics.types.js +7 -0
  24. package/dist/metrics.types.js.map +1 -0
  25. package/dist/new-metrics.js +185 -0
  26. package/dist/new-metrics.js.map +1 -0
  27. package/dist/types/batcher.d.ts +2 -0
  28. package/dist/types/call-diagnostic/call-diagnostic-metrics-batcher.d.ts +2 -0
  29. package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +189 -0
  30. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +324 -0
  31. package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +31 -0
  32. package/dist/types/call-diagnostic/config.d.ts +57 -0
  33. package/dist/types/call-diagnostic/generated-types-temp/ClientEvent.d.ts +1112 -0
  34. package/dist/types/call-diagnostic/generated-types-temp/Event.d.ts +4851 -0
  35. package/dist/types/call-diagnostic/generated-types-temp/MediaQualityEvent.d.ts +2121 -0
  36. package/dist/types/client-metrics-batcher.d.ts +2 -0
  37. package/dist/types/config.d.ts +35 -0
  38. package/dist/types/index.d.ts +11 -0
  39. package/dist/types/metrics.d.ts +3 -0
  40. package/dist/types/metrics.types.d.ts +87 -0
  41. package/dist/types/new-metrics.d.ts +83 -0
  42. package/package.json +12 -8
  43. package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +148 -0
  44. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +408 -0
  45. package/src/call-diagnostic/call-diagnostic-metrics.ts +528 -0
  46. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +102 -0
  47. package/src/call-diagnostic/config.ts +455 -0
  48. package/src/call-diagnostic/generated-types-temp/ClientEvent.ts +2357 -0
  49. package/src/call-diagnostic/generated-types-temp/Event.ts +7669 -0
  50. package/src/call-diagnostic/generated-types-temp/MediaQualityEvent.ts +2321 -0
  51. package/src/config.js +19 -0
  52. package/src/index.ts +39 -0
  53. package/src/metrics.js +25 -27
  54. package/src/metrics.types.ts +131 -0
  55. package/src/new-metrics.ts +170 -0
  56. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +243 -0
  57. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +474 -0
  58. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +722 -0
  59. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +76 -0
  60. package/test/unit/spec/metrics.js +65 -97
  61. package/test/unit/spec/new-metrics.ts +91 -0
  62. package/tsconfig.json +6 -0
  63. package/dist/call-diagnostic-events-batcher.js +0 -60
  64. package/dist/call-diagnostic-events-batcher.js.map +0 -1
  65. package/src/call-diagnostic-events-batcher.js +0 -62
  66. package/src/index.js +0 -17
  67. package/test/unit/spec/call-diagnostic-events-batcher.js +0 -195
@@ -0,0 +1,722 @@
1
+ import sinon from 'sinon';
2
+ import {assert} from '@webex/test-helper-chai';
3
+
4
+ import CallDiagnosticMetrics from '../../../../src/call-diagnostic/call-diagnostic-metrics';
5
+ import * as Utils from '../../../../src/call-diagnostic/call-diagnostic-metrics.util';
6
+ import {BrowserDetection} from '@webex/common';
7
+ import {getOSNameInternal} from '@webex/internal-plugin-metrics';
8
+ import uuid from 'uuid';
9
+
10
+ //@ts-ignore
11
+ global.window = {location: {hostname: 'whatever'}};
12
+
13
+ const {getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
14
+
15
+ describe('internal-plugin-metrics', () => {
16
+ describe('CallDiagnosticMetrics', () => {
17
+ var now = new Date();
18
+
19
+ let cd: CallDiagnosticMetrics;
20
+
21
+ const fakeMeeting = {
22
+ id: '1',
23
+ correlationId: 'correlationId',
24
+ environment: 'meeting_evn',
25
+ locusUrl: 'locus/url',
26
+ locusInfo: {
27
+ fullState: {
28
+ lastActive: 'lastActive',
29
+ },
30
+ },
31
+ getCurUserType: () => 'host',
32
+ };
33
+
34
+ let webex;
35
+
36
+ beforeEach(() => {
37
+ webex = {
38
+ canAuthorize: true,
39
+ version: 'webex-version',
40
+ internal: {
41
+ services: {
42
+ get: () => 'locus-url',
43
+ },
44
+ metrics: {
45
+ submitClientMetrics: sinon.stub()
46
+ },
47
+ device: {
48
+ userId: 'userId',
49
+ url: 'deviceUrl',
50
+ orgId: 'orgId',
51
+ }
52
+ },
53
+ meetings: {
54
+ config: {
55
+ metrics: {
56
+ clientType: 'TEAMS_CLIENT',
57
+ subClientType: 'WEB_APP',
58
+ },
59
+ },
60
+ metrics: {
61
+ clientName: 'Cantina',
62
+ },
63
+ meetingCollection: {
64
+ get: () => fakeMeeting
65
+ },
66
+ geoHintInfo: {
67
+ clientAddress: '1.3.4.5',
68
+ countryCode: 'UK',
69
+ },
70
+ },
71
+ credentials: {
72
+ isUnverifiedGuest: false
73
+ }
74
+ };
75
+
76
+ sinon.createSandbox();
77
+ sinon.useFakeTimers(now.getTime());
78
+ cd = new CallDiagnosticMetrics({}, {parent: webex});
79
+ sinon.stub(uuid, 'v4').returns('my-fake-id');
80
+ });
81
+
82
+ afterEach(() => {
83
+ sinon.restore();
84
+ });
85
+
86
+ describe("#getOrigin", () => {
87
+ it('should build origin correctly', () => {
88
+ sinon.stub(Utils, 'anonymizeIPAddress').returns('1.1.1.1');
89
+
90
+ //@ts-ignore
91
+ const res = cd.getOrigin(
92
+ {subClientType: 'WEB_APP', clientType: 'TEAMS_CLIENT'},
93
+ fakeMeeting.id
94
+ );
95
+
96
+ assert.deepEqual(res, {
97
+ clientInfo: {
98
+ browser: getBrowserName(),
99
+ browserVersion: getBrowserVersion(),
100
+ clientType: 'TEAMS_CLIENT',
101
+ clientVersion: 'webex-js-sdk/webex-version',
102
+ localNetworkPrefix: '1.1.1.1',
103
+ os: getOSNameInternal(),
104
+ osVersion: getOSVersion(),
105
+ subClientType: 'WEB_APP',
106
+ },
107
+ environment: 'meeting_evn',
108
+ name: 'endpoint',
109
+ networkType: 'unknown',
110
+ userAgent: 'webex-js-sdk/test-webex-version client=Cantina; (os=linux/5)',
111
+ });
112
+ });
113
+
114
+ it('should build origin correctly with no meeting', () => {
115
+ sinon.stub(Utils, 'anonymizeIPAddress').returns('1.1.1.1');
116
+
117
+ //@ts-ignore
118
+ const res = cd.getOrigin();
119
+
120
+ assert.deepEqual(res, {
121
+ clientInfo: {
122
+ browser: getBrowserName(),
123
+ browserVersion: getBrowserVersion(),
124
+ clientType: 'TEAMS_CLIENT',
125
+ clientVersion: 'webex-js-sdk/webex-version',
126
+ localNetworkPrefix: '1.1.1.1',
127
+ os: getOSNameInternal(),
128
+ osVersion: getOSVersion(),
129
+ subClientType: 'WEB_APP',
130
+ },
131
+ name: 'endpoint',
132
+ networkType: 'unknown',
133
+ userAgent: 'webex-js-sdk/test-webex-version client=Cantina; (os=linux/5)',
134
+ });
135
+ });
136
+ })
137
+
138
+ describe("#getIdentifiers", () => {
139
+ it('should build identifiers correctly', () => {
140
+ const res = cd.getIdentifiers({
141
+ mediaConnections: [
142
+ {mediaAgentAlias: 'mediaAgentAlias', mediaAgentGroupId: 'mediaAgentGroupId'},
143
+ ],
144
+ meeting: fakeMeeting,
145
+ });
146
+
147
+ assert.deepEqual(res, {
148
+ correlationId: 'correlationId',
149
+ deviceId: 'deviceUrl',
150
+ locusId: 'url',
151
+ locusStartTime: 'lastActive',
152
+ locusUrl: 'locus/url',
153
+ mediaAgentAlias: 'mediaAgentAlias',
154
+ mediaAgentGroupId: 'mediaAgentGroupId',
155
+ orgId: 'orgId',
156
+ userId: 'userId',
157
+ });
158
+ });
159
+
160
+ it('should build identifiers correctly given correlationId', () => {
161
+ const res = cd.getIdentifiers({
162
+ correlationId: 'correlationId'
163
+ });
164
+
165
+ assert.deepEqual(res, {
166
+ correlationId: 'correlationId',
167
+ deviceId: 'deviceUrl',
168
+ locusUrl: 'locus-url',
169
+ orgId: 'orgId',
170
+ userId: 'userId',
171
+ });
172
+ });
173
+
174
+ it('should throw Error if correlationId is missing', () => {
175
+ assert.throws(() =>
176
+ cd.getIdentifiers({
177
+ mediaConnections: [
178
+ {mediaAgentAlias: 'mediaAgentAlias', mediaAgentGroupId: 'mediaAgentGroupId'},
179
+ ],
180
+ meeting: {...fakeMeeting, correlationId: undefined},
181
+ })
182
+ );
183
+ });
184
+ })
185
+
186
+ it('should prepare diagnostic event successfully', () => {
187
+ const options = {meetingId: fakeMeeting.id};
188
+ const getOriginStub = sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
189
+ const clearEmptyKeysRecursivelyStub = sinon.stub(Utils, 'clearEmptyKeysRecursively');
190
+
191
+ const res = cd.prepareDiagnosticEvent(
192
+ {
193
+ canProceed: false,
194
+ identifiers: {correlationId: 'id'},
195
+ name: 'client.alert.displayed',
196
+ },
197
+ options
198
+ );
199
+
200
+ assert.calledWith(getOriginStub, options, options.meetingId);
201
+ assert.calledOnce(clearEmptyKeysRecursivelyStub);
202
+ assert.deepEqual(res, {
203
+ event: {
204
+ canProceed: false,
205
+ identifiers: {
206
+ correlationId: 'id',
207
+ },
208
+ name: 'client.alert.displayed',
209
+ },
210
+ eventId: 'my-fake-id',
211
+ origin: {
212
+ origin: 'fake-origin',
213
+ },
214
+ originTime: {
215
+ sent: 'not_defined_yet',
216
+ triggered: now.toISOString(),
217
+ },
218
+ senderCountryCode: 'UK',
219
+ version: 1,
220
+ });
221
+ });
222
+
223
+ describe('#submitClientEvent', () => {
224
+ it('should submit client event successfully with meetingId', () => {
225
+ const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
226
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
227
+ const generateClientEventErrorPayloadSpy = sinon.spy(cd, 'generateClientEventErrorPayload');
228
+ const getIdentifiersSpy = sinon.spy(cd, 'getIdentifiers');
229
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
230
+ const options = {
231
+ meetingId: fakeMeeting.id,
232
+ mediaConnections: [{mediaAgentAlias: 'alias', mediaAgentGroupId: '1'}],
233
+ };
234
+
235
+ cd.submitClientEvent({
236
+ name: 'client.alert.displayed',
237
+ options,
238
+ });
239
+
240
+ assert.calledWith(getIdentifiersSpy, {
241
+ meeting: fakeMeeting,
242
+ mediaConnections: [{mediaAgentAlias: 'alias', mediaAgentGroupId: '1'}],
243
+ });
244
+ assert.notCalled(generateClientEventErrorPayloadSpy);
245
+ assert.calledWith(
246
+ prepareDiagnosticEventSpy,
247
+ {
248
+ canProceed: true,
249
+ eventData: {
250
+ webClientDomain: 'whatever',
251
+ },
252
+ identifiers: {
253
+ correlationId: 'correlationId',
254
+ deviceId: 'deviceUrl',
255
+ locusId: 'url',
256
+ locusStartTime: 'lastActive',
257
+ locusUrl: 'locus/url',
258
+ mediaAgentAlias: 'alias',
259
+ mediaAgentGroupId: '1',
260
+ orgId: 'orgId',
261
+ userId: 'userId',
262
+ },
263
+ loginType: 'login-ci',
264
+ name: 'client.alert.displayed',
265
+ userType: 'host',
266
+ },
267
+ options
268
+ );
269
+ assert.calledWith(submitToCallDiagnosticsSpy, {
270
+ event: {
271
+ canProceed: true,
272
+ eventData: {
273
+ webClientDomain: 'whatever',
274
+ },
275
+ identifiers: {
276
+ correlationId: 'correlationId',
277
+ deviceId: 'deviceUrl',
278
+ locusId: 'url',
279
+ locusStartTime: 'lastActive',
280
+ locusUrl: 'locus/url',
281
+ mediaAgentAlias: 'alias',
282
+ mediaAgentGroupId: '1',
283
+ orgId: 'orgId',
284
+ userId: 'userId',
285
+ },
286
+ loginType: 'login-ci',
287
+ name: 'client.alert.displayed',
288
+ userType: 'host',
289
+ },
290
+ eventId: 'my-fake-id',
291
+ origin: {
292
+ origin: 'fake-origin',
293
+ },
294
+ originTime: {
295
+ sent: 'not_defined_yet',
296
+ triggered: now.toISOString(),
297
+ },
298
+ senderCountryCode: 'UK',
299
+ version: 1,
300
+ });
301
+ });
302
+
303
+ it('should submit client event successfully with correlationId', () => {
304
+ const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
305
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
306
+ const generateClientEventErrorPayloadSpy = sinon.spy(cd, 'generateClientEventErrorPayload');
307
+ const getIdentifiersSpy = sinon.spy(cd, 'getIdentifiers');
308
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
309
+
310
+ const options = {
311
+ correlationId: 'correlationId'
312
+ };
313
+
314
+ cd.submitClientEvent({
315
+ name: 'client.alert.displayed',
316
+ options,
317
+ });
318
+
319
+ assert.calledWith(getIdentifiersSpy, {
320
+ correlationId: 'correlationId',
321
+ });
322
+
323
+ assert.notCalled(generateClientEventErrorPayloadSpy);
324
+ assert.calledWith(
325
+ prepareDiagnosticEventSpy,
326
+ {
327
+ canProceed: true,
328
+ eventData: {
329
+ webClientDomain: 'whatever',
330
+ },
331
+ identifiers: {
332
+ correlationId: 'correlationId',
333
+ deviceId: 'deviceUrl',
334
+ locusUrl: 'locus-url',
335
+ orgId: 'orgId',
336
+ userId: 'userId',
337
+ },
338
+ loginType: 'login-ci',
339
+ name: 'client.alert.displayed',
340
+ },
341
+ options
342
+ );
343
+ assert.calledWith(submitToCallDiagnosticsSpy, {
344
+ event: {
345
+ canProceed: true,
346
+ eventData: {
347
+ webClientDomain: 'whatever',
348
+ },
349
+ identifiers: {
350
+ correlationId: 'correlationId',
351
+ deviceId: 'deviceUrl',
352
+ locusUrl: 'locus-url',
353
+ orgId: 'orgId',
354
+ userId: 'userId',
355
+ },
356
+ loginType: 'login-ci',
357
+ name: 'client.alert.displayed',
358
+ },
359
+ eventId: 'my-fake-id',
360
+ origin: {
361
+ origin: 'fake-origin',
362
+ },
363
+ originTime: {
364
+ sent: 'not_defined_yet',
365
+ triggered: now.toISOString(),
366
+ },
367
+ senderCountryCode: 'UK',
368
+ version: 1,
369
+ });
370
+ });
371
+
372
+ it('it should include errors if provided', () => {
373
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
374
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
375
+
376
+ const options = {
377
+ meetingId: fakeMeeting.id,
378
+ mediaConnections: [{mediaAgentAlias: 'alias', mediaAgentGroupId: '1'}],
379
+ rawError: {
380
+ body: {
381
+ errorCode: 2409005,
382
+ },
383
+ },
384
+ };
385
+
386
+ cd.submitClientEvent({
387
+ name: 'client.alert.displayed',
388
+ options,
389
+ });
390
+
391
+ assert.calledWith(submitToCallDiagnosticsSpy, {
392
+ event: {
393
+ canProceed: true,
394
+ eventData: {
395
+ webClientDomain: 'whatever',
396
+ },
397
+ identifiers: {
398
+ correlationId: 'correlationId',
399
+ deviceId: 'deviceUrl',
400
+ locusId: 'url',
401
+ locusStartTime: 'lastActive',
402
+ locusUrl: 'locus/url',
403
+ mediaAgentAlias: 'alias',
404
+ mediaAgentGroupId: '1',
405
+ orgId: 'orgId',
406
+ userId: 'userId',
407
+ },
408
+ errors: [{
409
+ category: 'expected',
410
+ errorDescription: 'StartRecordingFailed',
411
+ fatal: true,
412
+ name: 'other',
413
+ shownToUser: false,
414
+ serviceErrorCode: 2409005,
415
+ errorCode: 4029
416
+ }],
417
+ loginType: 'login-ci',
418
+ name: 'client.alert.displayed',
419
+ userType: 'host',
420
+ },
421
+ eventId: 'my-fake-id',
422
+ origin: {
423
+ origin: 'fake-origin',
424
+ },
425
+ originTime: {
426
+ sent: 'not_defined_yet',
427
+ triggered: now.toISOString(),
428
+ },
429
+ senderCountryCode: 'UK',
430
+ version: 1,
431
+ });
432
+ });
433
+
434
+ it('should include erros in payload if provided via payload', () => {
435
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
436
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
437
+
438
+ const options = {
439
+ meetingId: fakeMeeting.id,
440
+ mediaConnections: [{mediaAgentAlias: 'alias', mediaAgentGroupId: '1'}],
441
+ };
442
+
443
+ cd.submitClientEvent({
444
+ name: 'client.alert.displayed',
445
+ payload: {
446
+ errors: [{
447
+ name: 'locus.response',
448
+ fatal: true,
449
+ category: 'signaling',
450
+ shownToUser: false,
451
+ }]
452
+ },
453
+ options,
454
+ });
455
+
456
+ assert.calledWith(submitToCallDiagnosticsSpy, {
457
+ event: {
458
+ canProceed: true,
459
+ eventData: {
460
+ webClientDomain: 'whatever',
461
+ },
462
+ identifiers: {
463
+ correlationId: 'correlationId',
464
+ deviceId: 'deviceUrl',
465
+ locusId: 'url',
466
+ locusStartTime: 'lastActive',
467
+ locusUrl: 'locus/url',
468
+ mediaAgentAlias: 'alias',
469
+ mediaAgentGroupId: '1',
470
+ orgId: 'orgId',
471
+ userId: 'userId',
472
+ },
473
+ errors: [{
474
+ name: 'locus.response',
475
+ fatal: true,
476
+ category: 'signaling',
477
+ shownToUser: false,
478
+ }],
479
+ loginType: 'login-ci',
480
+ name: 'client.alert.displayed',
481
+ userType: 'host',
482
+ },
483
+ eventId: 'my-fake-id',
484
+ origin: {
485
+ origin: 'fake-origin',
486
+ },
487
+ originTime: {
488
+ sent: 'not_defined_yet',
489
+ triggered: now.toISOString(),
490
+ },
491
+ senderCountryCode: 'UK',
492
+ version: 1,
493
+ });
494
+ })
495
+
496
+ it('should throw if meetingId nor correlationId not provided', () => {
497
+ assert.throws(() =>
498
+ cd.submitClientEvent({
499
+ name: 'client.alert.displayed',
500
+ options: {},
501
+ })
502
+ );
503
+ });
504
+
505
+ it('should send behavioral event if meetingId provided but meeting is undefined', () => {
506
+ webex.meetings.meetingCollection.get = sinon.stub().returns(undefined);
507
+ cd.submitClientEvent({name: 'client.alert.displayed', options: {meetingId: 'meetingId'}});
508
+ assert.calledWith(
509
+ webex.internal.metrics.submitClientMetrics,
510
+ 'js_sdk_call_diagnostic_event_failed_to_send',
511
+ {
512
+ fields: {meetingId: 'meetingId', name: 'client.alert.displayed'},
513
+ }
514
+ );
515
+ })
516
+ });
517
+
518
+ it('should send request to call diagnostic batcher', () => {
519
+ const requestStub = sinon.stub();
520
+ //@ts-ignore
521
+ cd.callDiagnosticEventsBatcher = {request: requestStub};
522
+ //@ts-ignore
523
+ cd.submitToCallDiagnostics({event: 'test'});
524
+ assert.calledWith(requestStub, {eventPayload: {event: 'test'}, type: ['diagnostic-event']});
525
+ });
526
+
527
+ describe('#submitMQE', () => {
528
+ it('submits the event correctly', () => {
529
+ const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
530
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
531
+ const getErrorPayloadForClientErrorCodeSpy = sinon.spy(cd, 'getErrorPayloadForClientErrorCode');
532
+ const getIdentifiersSpy = sinon.spy(cd, 'getIdentifiers');
533
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
534
+ const options = {
535
+ networkType: 'wifi' as const,
536
+ meetingId: fakeMeeting.id,
537
+ };
538
+
539
+ cd.submitMQE({
540
+ name: 'client.mediaquality.event',
541
+ payload: {
542
+ //@ts-ignore
543
+ intervals: [{}],
544
+ },
545
+ options,
546
+ });
547
+
548
+ assert.calledWith(getIdentifiersSpy, {
549
+ meeting: fakeMeeting,
550
+ mediaConnections: undefined,
551
+ });
552
+ assert.notCalled(getErrorPayloadForClientErrorCodeSpy);
553
+ assert.calledWith(
554
+ prepareDiagnosticEventSpy,
555
+ {
556
+ name: 'client.mediaquality.event',
557
+ canProceed: true,
558
+ identifiers: {
559
+ correlationId: 'correlationId',
560
+ userId: 'userId',
561
+ deviceId: 'deviceUrl',
562
+ orgId: 'orgId',
563
+ locusUrl: 'locus/url',
564
+ locusId: 'url',
565
+ locusStartTime: 'lastActive',
566
+ },
567
+ eventData: {webClientDomain: 'whatever'},
568
+ intervals: [{}],
569
+ sourceMetadata: {
570
+ applicationSoftwareType: 'webex-js-sdk',
571
+ applicationSoftwareVersion: 'webex-version',
572
+ mediaEngineSoftwareType: 'browser',
573
+ mediaEngineSoftwareVersion: getOSVersion(),
574
+ startTime: now.toISOString(),
575
+ },
576
+ },
577
+ options
578
+ );
579
+
580
+ assert.calledWith(submitToCallDiagnosticsSpy, {
581
+ eventId: 'my-fake-id',
582
+ version: 1,
583
+ origin: {origin: 'fake-origin'},
584
+ originTime: {triggered: now.toISOString(), sent: 'not_defined_yet'},
585
+ senderCountryCode: 'UK',
586
+ event: {
587
+ name: 'client.mediaquality.event',
588
+ canProceed: true,
589
+ identifiers: {
590
+ correlationId: 'correlationId',
591
+ userId: 'userId',
592
+ deviceId: 'deviceUrl',
593
+ orgId: 'orgId',
594
+ locusUrl: 'locus/url',
595
+ locusId: 'url',
596
+ locusStartTime: 'lastActive',
597
+ },
598
+ eventData: {webClientDomain: 'whatever'},
599
+ intervals: [{}],
600
+ sourceMetadata: {
601
+ applicationSoftwareType: 'webex-js-sdk',
602
+ applicationSoftwareVersion: 'webex-version',
603
+ mediaEngineSoftwareType: 'browser',
604
+ mediaEngineSoftwareVersion: getOSVersion(),
605
+ startTime: now.toISOString(),
606
+ },
607
+ },
608
+ });
609
+ });
610
+
611
+ it('throws if meeting id not provided', () => {
612
+ assert.throws(() =>
613
+ cd.submitMQE({
614
+ name: 'client.mediaquality.event',
615
+ payload: {
616
+ //@ts-ignore
617
+ intervals: [{}],
618
+ },
619
+ //@ts-ignore
620
+ options: {meetingId: undefined, networkType: 'wifi'},
621
+ })
622
+ );
623
+ });
624
+
625
+ it('should send behavioral event if meeting is undefined', () => {
626
+ webex.meetings.meetingCollection.get = sinon.stub().returns(undefined);
627
+ cd.submitMQE({
628
+ name: 'client.mediaquality.event',
629
+ payload: {
630
+ //@ts-ignore
631
+ intervals: [{}],
632
+ },
633
+ options: {meetingId: 'meetingId'},
634
+ });
635
+ assert.calledWith(
636
+ webex.internal.metrics.submitClientMetrics,
637
+ 'js_sdk_call_diagnostic_event_failed_to_send',
638
+ {
639
+ fields: {meetingId: 'meetingId', name: 'client.mediaquality.event'},
640
+ }
641
+ );
642
+ })
643
+ });
644
+ describe('#getErrorPayloadForClientErrorCode', () => {
645
+ it('it should grab the payload for client error code correctly', () => {
646
+ const res = cd.getErrorPayloadForClientErrorCode({clientErrorCode: 4008, serviceErrorCode: 10000});
647
+ assert.deepEqual(res, {
648
+ category: 'signaling',
649
+ errorDescription: 'NewLocusError',
650
+ fatal: true,
651
+ name: 'other',
652
+ shownToUser: false,
653
+ errorCode: 4008,
654
+ serviceErrorCode: 10000,
655
+ });
656
+ });
657
+
658
+ it('it should return undefined if trying to get payload for client error code that doesnt exist', () => {
659
+ const res = cd.getErrorPayloadForClientErrorCode({clientErrorCode: 123456, serviceErrorCode: 100000});
660
+ assert.deepEqual(res, undefined);
661
+ });
662
+ });
663
+
664
+ describe('#generateClientEventErrorPayload', () => {
665
+ it('should generate event error payload correctly', () => {
666
+ const res = cd.generateClientEventErrorPayload({body: {errorCode: 2409005}});
667
+ assert.deepEqual(res, {
668
+ category: 'expected',
669
+ errorDescription: 'StartRecordingFailed',
670
+ fatal: true,
671
+ name: 'other',
672
+ shownToUser: false,
673
+ errorCode: 4029,
674
+ serviceErrorCode: 2409005
675
+ });
676
+ });
677
+
678
+ it('should return default new locus event error payload correctly if locus error', () => {
679
+ const res = cd.generateClientEventErrorPayload({body: {errorCode: 2400000}});
680
+ assert.deepEqual(res, {
681
+ category: 'signaling',
682
+ errorDescription: 'NewLocusError',
683
+ fatal: true,
684
+ name: 'other',
685
+ shownToUser: false,
686
+ serviceErrorCode: 2400000,
687
+ errorCode: 4008,
688
+ });
689
+ });
690
+
691
+
692
+ it('should return default meeting info lookup error payload correctly if not locus error', () => {
693
+ const res = cd.generateClientEventErrorPayload({body: {errorCode: 9400000}});
694
+ assert.deepEqual(res, {
695
+ category: 'signaling',
696
+ errorDescription: 'MeetingInfoLookupError',
697
+ fatal: true,
698
+ name: 'other',
699
+ shownToUser: false,
700
+ serviceErrorCode: 9400000,
701
+ errorCode: 4100,
702
+ });
703
+ });
704
+
705
+ it('should return undefined if no error code provided', () => {
706
+ const res = cd.generateClientEventErrorPayload({body: {errorCode: undefined}});
707
+ assert.deepEqual(res, undefined);
708
+ });
709
+ });
710
+
711
+ describe('#getCurLoginType', () => {
712
+ it('returns login-ci if not unverified guest', () => {
713
+ webex.credentials.isUnverifiedGuest = false;
714
+ assert.deepEqual(cd.getCurLoginType(), 'login-ci');
715
+ });
716
+ it('returns unverified guest', () => {
717
+ webex.credentials.isUnverifiedGuest = true;
718
+ assert.deepEqual(cd.getCurLoginType(), 'unverified-guest');
719
+ })
720
+ })
721
+ });
722
+ });