@webex/internal-plugin-metrics 3.0.0-beta.28 → 3.0.0-beta.281

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 (60) hide show
  1. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +65 -0
  2. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -0
  3. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +456 -0
  4. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -0
  5. package/dist/call-diagnostic/call-diagnostic-metrics.js +775 -0
  6. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -0
  7. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +337 -0
  8. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -0
  9. package/dist/call-diagnostic/config.js +604 -0
  10. package/dist/call-diagnostic/config.js.map +1 -0
  11. package/dist/config.js +20 -1
  12. package/dist/config.js.map +1 -1
  13. package/dist/index.js +30 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/metrics.js +30 -30
  16. package/dist/metrics.js.map +1 -1
  17. package/dist/metrics.types.js +7 -0
  18. package/dist/metrics.types.js.map +1 -0
  19. package/dist/new-metrics.js +333 -0
  20. package/dist/new-metrics.js.map +1 -0
  21. package/dist/types/batcher.d.ts +2 -0
  22. package/dist/types/call-diagnostic/call-diagnostic-metrics-batcher.d.ts +2 -0
  23. package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +194 -0
  24. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +395 -0
  25. package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +96 -0
  26. package/dist/types/call-diagnostic/config.d.ts +171 -0
  27. package/dist/types/client-metrics-batcher.d.ts +2 -0
  28. package/dist/types/config.d.ts +35 -0
  29. package/dist/types/index.d.ts +13 -0
  30. package/dist/types/metrics.d.ts +3 -0
  31. package/dist/types/metrics.types.d.ts +103 -0
  32. package/dist/types/new-metrics.d.ts +139 -0
  33. package/dist/types/utils.d.ts +6 -0
  34. package/dist/utils.js +27 -0
  35. package/dist/utils.js.map +1 -0
  36. package/package.json +13 -8
  37. package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +82 -0
  38. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +414 -0
  39. package/src/call-diagnostic/call-diagnostic-metrics.ts +843 -0
  40. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +362 -0
  41. package/src/call-diagnostic/config.ts +660 -0
  42. package/src/config.js +19 -0
  43. package/src/index.ts +43 -0
  44. package/src/metrics.js +25 -27
  45. package/src/metrics.types.ts +159 -0
  46. package/src/new-metrics.ts +317 -0
  47. package/src/utils.ts +17 -0
  48. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +394 -0
  49. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +477 -0
  50. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +1787 -0
  51. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +565 -0
  52. package/test/unit/spec/metrics.js +65 -97
  53. package/test/unit/spec/new-metrics.ts +269 -0
  54. package/test/unit/spec/utils.ts +22 -0
  55. package/tsconfig.json +6 -0
  56. package/dist/call-diagnostic-events-batcher.js +0 -60
  57. package/dist/call-diagnostic-events-batcher.js.map +0 -1
  58. package/src/call-diagnostic-events-batcher.js +0 -62
  59. package/src/index.js +0 -17
  60. package/test/unit/spec/call-diagnostic-events-batcher.js +0 -195
@@ -0,0 +1,1787 @@
1
+ import sinon from 'sinon';
2
+ import {assert} from '@webex/test-helper-chai';
3
+ import {WebexHttpError} from '@webex/webex-core';
4
+
5
+ import CallDiagnosticMetrics from '../../../../src/call-diagnostic/call-diagnostic-metrics';
6
+ import CallDiagnosticLatencies from '../../../../src/call-diagnostic/call-diagnostic-metrics-latencies';
7
+ import * as Utils from '../../../../src/call-diagnostic/call-diagnostic-metrics.util';
8
+ import {BrowserDetection} from '@webex/common';
9
+ import {getOSNameInternal} from '@webex/internal-plugin-metrics';
10
+ import uuid from 'uuid';
11
+ import {omit} from 'lodash';
12
+
13
+ //@ts-ignore
14
+ global.window = {location: {hostname: 'whatever'}};
15
+
16
+ const {getOSName, getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
17
+ const userAgent = `webex-js-sdk/test-webex-version client=Cantina; (os=${getOSName()}/${
18
+ getOSVersion().split('.')[0]
19
+ })`;
20
+
21
+ describe('internal-plugin-metrics', () => {
22
+ describe('CallDiagnosticMetrics', () => {
23
+ var now = new Date();
24
+
25
+ let cd: CallDiagnosticMetrics;
26
+
27
+ const fakeMeeting = {
28
+ id: '1',
29
+ correlationId: 'correlationId',
30
+ environment: 'meeting_evn',
31
+ locusUrl: 'locus/url',
32
+ locusInfo: {
33
+ fullState: {
34
+ lastActive: 'lastActive',
35
+ },
36
+ },
37
+ meetingInfo: {},
38
+ getCurUserType: () => 'host',
39
+ };
40
+
41
+ let webex;
42
+
43
+ beforeEach(() => {
44
+ webex = {
45
+ canAuthorize: true,
46
+ version: 'webex-version',
47
+ internal: {
48
+ services: {
49
+ get: () => 'locus-url',
50
+ },
51
+ metrics: {
52
+ submitClientMetrics: sinon.stub(),
53
+ },
54
+ newMetrics: {
55
+ postPreLoginMetric: sinon.stub(),
56
+ },
57
+ device: {
58
+ userId: 'userId',
59
+ url: 'deviceUrl',
60
+ orgId: 'orgId',
61
+ },
62
+ },
63
+ meetings: {
64
+ config: {
65
+ metrics: {
66
+ clientType: 'TEAMS_CLIENT',
67
+ subClientType: 'WEB_APP',
68
+ clientName: 'Cantina'
69
+ },
70
+ },
71
+ meetingCollection: {
72
+ get: () => fakeMeeting,
73
+ },
74
+ geoHintInfo: {
75
+ clientAddress: '1.3.4.5',
76
+ countryCode: 'UK',
77
+ },
78
+ },
79
+ credentials: {
80
+ isUnverifiedGuest: false,
81
+ },
82
+ prepareFetchOptions: sinon.stub().callsFake((opts: any) => ({...opts, foo: 'bar'})),
83
+ request: sinon.stub().resolves({body: {}}),
84
+ logger: {
85
+ log: sinon.stub(),
86
+ error: sinon.stub(),
87
+ },
88
+ };
89
+
90
+ webex.internal.newMetrics.callDiagnosticLatencies = new CallDiagnosticLatencies(
91
+ {},
92
+ {parent: webex}
93
+ );
94
+
95
+ sinon.createSandbox();
96
+ sinon.useFakeTimers(now.getTime());
97
+ cd = new CallDiagnosticMetrics({}, {parent: webex});
98
+ sinon.stub(uuid, 'v4').returns('my-fake-id');
99
+ });
100
+
101
+ afterEach(() => {
102
+ sinon.restore();
103
+ });
104
+
105
+ describe('#getOrigin', () => {
106
+ it('should build origin correctly', () => {
107
+ sinon.stub(Utils, 'anonymizeIPAddress').returns('1.1.1.1');
108
+
109
+ //@ts-ignore
110
+ const res = cd.getOrigin(
111
+ {subClientType: 'WEB_APP', clientType: 'TEAMS_CLIENT'},
112
+ fakeMeeting.id
113
+ );
114
+
115
+ assert.deepEqual(res, {
116
+ clientInfo: {
117
+ browser: getBrowserName(),
118
+ browserVersion: getBrowserVersion(),
119
+ clientType: 'TEAMS_CLIENT',
120
+ clientVersion: 'webex-js-sdk/webex-version',
121
+ localNetworkPrefix: '1.1.1.1',
122
+ os: getOSNameInternal(),
123
+ osVersion: getOSVersion(),
124
+ subClientType: 'WEB_APP',
125
+ },
126
+ environment: 'meeting_evn',
127
+ name: 'endpoint',
128
+ networkType: 'unknown',
129
+ userAgent,
130
+ });
131
+ });
132
+
133
+ it('should build origin correctly with newEnvironment and createLaunchMethod', () => {
134
+ sinon.stub(Utils, 'anonymizeIPAddress').returns('1.1.1.1');
135
+
136
+ //@ts-ignore
137
+ const res = cd.getOrigin(
138
+ {subClientType: 'WEB_APP', clientType: 'TEAMS_CLIENT', newEnvironment: 'test-new-env', clientLaunchMethod: 'url-handler'},
139
+ fakeMeeting.id
140
+ );
141
+
142
+ assert.deepEqual(res, {
143
+ clientInfo: {
144
+ browser: getBrowserName(),
145
+ browserVersion: getBrowserVersion(),
146
+ clientType: 'TEAMS_CLIENT',
147
+ clientVersion: 'webex-js-sdk/webex-version',
148
+ localNetworkPrefix: '1.1.1.1',
149
+ os: getOSNameInternal(),
150
+ osVersion: getOSVersion(),
151
+ subClientType: 'WEB_APP',
152
+ clientLaunchMethod: 'url-handler',
153
+ },
154
+ environment: 'meeting_evn',
155
+ newEnvironment: 'test-new-env',
156
+ name: 'endpoint',
157
+ networkType: 'unknown',
158
+ userAgent,
159
+ });
160
+ });
161
+
162
+ it('should build origin correctly and environment can be passed in options', () => {
163
+ sinon.stub(Utils, 'anonymizeIPAddress').returns('1.1.1.1');
164
+
165
+ //@ts-ignore
166
+ const res = cd.getOrigin(
167
+ {subClientType: 'WEB_APP', clientType: 'TEAMS_CLIENT', clientLaunchMethod: 'url-handler', environment: 'test-env'},
168
+ fakeMeeting.id
169
+ );
170
+
171
+ assert.deepEqual(res, {
172
+ clientInfo: {
173
+ browser: getBrowserName(),
174
+ browserVersion: getBrowserVersion(),
175
+ clientType: 'TEAMS_CLIENT',
176
+ clientVersion: 'webex-js-sdk/webex-version',
177
+ localNetworkPrefix: '1.1.1.1',
178
+ os: getOSNameInternal(),
179
+ osVersion: getOSVersion(),
180
+ subClientType: 'WEB_APP',
181
+ clientLaunchMethod: 'url-handler'
182
+ },
183
+ environment: 'test-env',
184
+ name: 'endpoint',
185
+ networkType: 'unknown',
186
+ userAgent,
187
+ });
188
+ });
189
+
190
+ it('should build origin correctly with no meeting', () => {
191
+ sinon.stub(Utils, 'anonymizeIPAddress').returns('1.1.1.1');
192
+
193
+ //@ts-ignore
194
+ const res = cd.getOrigin();
195
+
196
+ assert.deepEqual(res, {
197
+ clientInfo: {
198
+ browser: getBrowserName(),
199
+ browserVersion: getBrowserVersion(),
200
+ clientType: 'TEAMS_CLIENT',
201
+ clientVersion: 'webex-js-sdk/webex-version',
202
+ localNetworkPrefix: '1.1.1.1',
203
+ os: getOSNameInternal(),
204
+ osVersion: getOSVersion(),
205
+ subClientType: 'WEB_APP',
206
+ },
207
+ name: 'endpoint',
208
+ networkType: 'unknown',
209
+ userAgent,
210
+ });
211
+ });
212
+
213
+ it('builds origin correctly, when overriding clientVersion', () => {
214
+ webex.meetings.config.metrics.clientVersion = '43.9.0.1234';
215
+
216
+ //@ts-ignore
217
+ const res = cd.getOrigin(
218
+ {subClientType: 'WEB_APP', clientType: 'TEAMS_CLIENT'},
219
+ fakeMeeting.id
220
+ );
221
+
222
+ assert.deepEqual(res, {
223
+ clientInfo: {
224
+ browser: getBrowserName(),
225
+ browserVersion: getBrowserVersion(),
226
+ clientType: 'TEAMS_CLIENT',
227
+ clientVersion: '43.9.0.1234',
228
+ localNetworkPrefix: '1.3.4.0',
229
+ majorVersion: 43,
230
+ minorVersion: 9,
231
+ os: getOSNameInternal(),
232
+ osVersion: getOSVersion(),
233
+ subClientType: 'WEB_APP',
234
+ },
235
+ environment: 'meeting_evn',
236
+ name: 'endpoint',
237
+ networkType: 'unknown',
238
+ userAgent,
239
+ });
240
+ });
241
+ });
242
+
243
+ describe('#getIdentifiers', () => {
244
+ it('should build identifiers correctly', () => {
245
+ const res = cd.getIdentifiers({
246
+ mediaConnections: [
247
+ {mediaAgentAlias: 'mediaAgentAlias', mediaAgentGroupId: 'mediaAgentGroupId'},
248
+ ],
249
+ meeting: fakeMeeting,
250
+ });
251
+
252
+ assert.deepEqual(res, {
253
+ correlationId: 'correlationId',
254
+ deviceId: 'deviceUrl',
255
+ locusId: 'url',
256
+ locusStartTime: 'lastActive',
257
+ locusUrl: 'locus/url',
258
+ mediaAgentAlias: 'mediaAgentAlias',
259
+ mediaAgentGroupId: 'mediaAgentGroupId',
260
+ orgId: 'orgId',
261
+ userId: 'userId',
262
+ });
263
+ });
264
+
265
+ it('should build identifiers correctly with a meeting that has meetingInfo with a webexConferenceIdStr and globalMeetingId, and that should take precedence over the options passed to it', () => {
266
+ const res = cd.getIdentifiers({
267
+ mediaConnections: [
268
+ {mediaAgentAlias: 'mediaAgentAlias', mediaAgentGroupId: 'mediaAgentGroupId'},
269
+ ],
270
+ webexConferenceIdStr: 'webexConferenceIdStr',
271
+ globalMeetingId: 'globalMeetingId',
272
+ meeting: {...fakeMeeting, meetingInfo: {...fakeMeeting.meetingInfo, confID: 'webexConferenceIdStr1', meetingId: 'globalMeetingId1'}},
273
+ });
274
+
275
+ assert.deepEqual(res, {
276
+ correlationId: 'correlationId',
277
+ webexConferenceIdStr: 'webexConferenceIdStr1',
278
+ globalMeetingId: 'globalMeetingId1',
279
+ deviceId: 'deviceUrl',
280
+ locusId: 'url',
281
+ locusStartTime: 'lastActive',
282
+ locusUrl: 'locus/url',
283
+ mediaAgentAlias: 'mediaAgentAlias',
284
+ mediaAgentGroupId: 'mediaAgentGroupId',
285
+ orgId: 'orgId',
286
+ userId: 'userId',
287
+ });
288
+ });
289
+
290
+ it('should build identifiers correctly given webexConferenceIdStr', () => {
291
+ const res = cd.getIdentifiers({
292
+ correlationId: 'correlationId',
293
+ webexConferenceIdStr: 'webexConferenceIdStr1',
294
+ });
295
+
296
+ assert.deepEqual(res, {
297
+ correlationId: 'correlationId',
298
+ webexConferenceIdStr: 'webexConferenceIdStr1',
299
+ deviceId: 'deviceUrl',
300
+ locusUrl: 'locus-url',
301
+ orgId: 'orgId',
302
+ userId: 'userId',
303
+ });
304
+ })
305
+
306
+ it('should build identifiers correctly given globalMeetingId', () => {
307
+ const res = cd.getIdentifiers({
308
+ correlationId: 'correlationId',
309
+ globalMeetingId: 'globalMeetingId1',
310
+ });
311
+
312
+ assert.deepEqual(res, {
313
+ correlationId: 'correlationId',
314
+ globalMeetingId: 'globalMeetingId1',
315
+ deviceId: 'deviceUrl',
316
+ locusUrl: 'locus-url',
317
+ orgId: 'orgId',
318
+ userId: 'userId',
319
+ });
320
+ });
321
+
322
+ it('should build identifiers correctly given correlationId', () => {
323
+ const res = cd.getIdentifiers({
324
+ correlationId: 'correlationId',
325
+ });
326
+
327
+ assert.deepEqual(res, {
328
+ correlationId: 'correlationId',
329
+ deviceId: 'deviceUrl',
330
+ locusUrl: 'locus-url',
331
+ orgId: 'orgId',
332
+ userId: 'userId',
333
+ });
334
+ });
335
+
336
+ it('should throw Error if correlationId is missing', () => {
337
+ assert.throws(() =>
338
+ cd.getIdentifiers({
339
+ mediaConnections: [
340
+ {mediaAgentAlias: 'mediaAgentAlias', mediaAgentGroupId: 'mediaAgentGroupId'},
341
+ ],
342
+ meeting: {...fakeMeeting, correlationId: undefined},
343
+ })
344
+ );
345
+ });
346
+
347
+ it('should build identifiers correctly given preLoginId and no device userId available', () => {
348
+ webex.internal.device.userId = undefined;
349
+
350
+ const res = cd.getIdentifiers({
351
+ correlationId: 'correlationId',
352
+ preLoginId: 'preLoginId',
353
+ });
354
+
355
+ assert.deepEqual(res, {
356
+ correlationId: "correlationId",
357
+ locusUrl: "locus-url",
358
+ deviceId: 'deviceUrl',
359
+ orgId: 'orgId',
360
+ userId: 'preLoginId',
361
+ });
362
+ })
363
+ });
364
+
365
+ it('should prepare diagnostic event successfully', () => {
366
+ const options = {meetingId: fakeMeeting.id};
367
+ const getOriginStub = sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
368
+ const clearEmptyKeysRecursivelyStub = sinon.stub(Utils, 'clearEmptyKeysRecursively');
369
+
370
+ const res = cd.prepareDiagnosticEvent(
371
+ {
372
+ canProceed: false,
373
+ identifiers: {correlationId: 'id', webexConferenceIdStr: 'webexConferenceIdStr1', globalMeetingId: 'globalMeetingId1'},
374
+ name: 'client.alert.displayed',
375
+ },
376
+ options
377
+ );
378
+
379
+ assert.calledWith(getOriginStub, options, options.meetingId);
380
+ assert.calledOnce(clearEmptyKeysRecursivelyStub);
381
+ assert.deepEqual(res, {
382
+ event: {
383
+ canProceed: false,
384
+ identifiers: {
385
+ correlationId: 'id',
386
+ webexConferenceIdStr: 'webexConferenceIdStr1',
387
+ globalMeetingId: 'globalMeetingId1',
388
+ },
389
+ name: 'client.alert.displayed',
390
+ },
391
+ eventId: 'my-fake-id',
392
+ origin: {
393
+ origin: 'fake-origin',
394
+ },
395
+ originTime: {
396
+ sent: 'not_defined_yet',
397
+ triggered: now.toISOString(),
398
+ },
399
+ senderCountryCode: 'UK',
400
+ version: 1,
401
+ });
402
+ });
403
+
404
+ describe('#submitClientEvent', () => {
405
+ it('should submit client event successfully with meetingId', () => {
406
+ const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
407
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
408
+ const generateClientEventErrorPayloadSpy = sinon.spy(cd, 'generateClientEventErrorPayload');
409
+ const getIdentifiersSpy = sinon.spy(cd, 'getIdentifiers');
410
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
411
+ const options = {
412
+ meetingId: fakeMeeting.id,
413
+ mediaConnections: [{mediaAgentAlias: 'alias', mediaAgentGroupId: '1'}],
414
+ };
415
+
416
+ cd.submitClientEvent({
417
+ name: 'client.alert.displayed',
418
+ options,
419
+ });
420
+
421
+ assert.calledWith(getIdentifiersSpy, {
422
+ meeting: fakeMeeting,
423
+ mediaConnections: [{mediaAgentAlias: 'alias', mediaAgentGroupId: '1'}],
424
+ webexConferenceIdStr: undefined,
425
+ globalMeetingId: undefined,
426
+ });
427
+ assert.notCalled(generateClientEventErrorPayloadSpy);
428
+ assert.calledWith(
429
+ prepareDiagnosticEventSpy,
430
+ {
431
+ canProceed: true,
432
+ eventData: {
433
+ webClientDomain: 'whatever',
434
+ },
435
+ identifiers: {
436
+ correlationId: 'correlationId',
437
+ deviceId: 'deviceUrl',
438
+ locusId: 'url',
439
+ locusStartTime: 'lastActive',
440
+ locusUrl: 'locus/url',
441
+ mediaAgentAlias: 'alias',
442
+ mediaAgentGroupId: '1',
443
+ orgId: 'orgId',
444
+ userId: 'userId',
445
+ },
446
+ loginType: 'login-ci',
447
+ name: 'client.alert.displayed',
448
+ userType: 'host',
449
+ isConvergedArchitectureEnabled: undefined,
450
+ },
451
+ options
452
+ );
453
+ assert.calledWith(submitToCallDiagnosticsSpy, {
454
+ event: {
455
+ canProceed: true,
456
+ eventData: {
457
+ webClientDomain: 'whatever',
458
+ },
459
+ identifiers: {
460
+ correlationId: 'correlationId',
461
+ deviceId: 'deviceUrl',
462
+ locusId: 'url',
463
+ locusStartTime: 'lastActive',
464
+ locusUrl: 'locus/url',
465
+ mediaAgentAlias: 'alias',
466
+ mediaAgentGroupId: '1',
467
+ orgId: 'orgId',
468
+ userId: 'userId',
469
+ },
470
+ loginType: 'login-ci',
471
+ name: 'client.alert.displayed',
472
+ userType: 'host',
473
+ isConvergedArchitectureEnabled: undefined,
474
+ },
475
+ eventId: 'my-fake-id',
476
+ origin: {
477
+ origin: 'fake-origin',
478
+ },
479
+ originTime: {
480
+ sent: 'not_defined_yet',
481
+ triggered: now.toISOString(),
482
+ },
483
+ senderCountryCode: 'UK',
484
+ version: 1,
485
+ });
486
+
487
+ const webexLoggerLogCalls = webex.logger.log.getCalls();
488
+ assert.deepEqual(webexLoggerLogCalls[0].args, [
489
+ 'call-diagnostic-events -> ',
490
+ 'CallDiagnosticMetrics: @submitClientEvent. Submit Client Event CA event.',
491
+ `name: client.alert.displayed`,
492
+ `payload: undefined`,
493
+ `options: ${JSON.stringify(options)}`,
494
+ ]);
495
+
496
+ assert.deepEqual(webexLoggerLogCalls[1].args, [
497
+ 'call-diagnostic-events -> ',
498
+ 'CallDiagnosticMetrics: @createClientEventObjectInMeeting. Creating in meeting event object.',
499
+ `name: client.alert.displayed`
500
+ ]);
501
+
502
+ assert.deepEqual(webexLoggerLogCalls[2].args, [
503
+ 'call-diagnostic-events -> ',
504
+ 'CallDiagnosticMetrics: @submitToCallDiagnostics. Preparing to send the request',
505
+ `finalEvent: {"eventPayload":{"eventId":"my-fake-id","version":1,"origin":{"origin":"fake-origin"},"originTime":{"triggered":"${now.toISOString()}","sent":"not_defined_yet"},"senderCountryCode":"UK","event":{"name":"client.alert.displayed","canProceed":true,"identifiers":{"correlationId":"correlationId","userId":"userId","deviceId":"deviceUrl","orgId":"orgId","locusUrl":"locus/url","locusId":"url","locusStartTime":"lastActive","mediaAgentAlias":"alias","mediaAgentGroupId":"1"},"eventData":{"webClientDomain":"whatever"},"userType":"host","loginType":"login-ci"}},"type":["diagnostic-event"]}`,
506
+ ]);
507
+
508
+ });
509
+
510
+ it('should submit client event successfully with correlationId, webexConferenceIdStr and globalMeetingId', () => {
511
+ const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
512
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
513
+ const generateClientEventErrorPayloadSpy = sinon.spy(cd, 'generateClientEventErrorPayload');
514
+ const getIdentifiersSpy = sinon.spy(cd, 'getIdentifiers');
515
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
516
+
517
+ const options = {
518
+ correlationId: 'correlationId',
519
+ webexConferenceIdStr: 'webexConferenceIdStr1',
520
+ globalMeetingId: 'globalMeetingId1',
521
+ };
522
+
523
+ cd.submitClientEvent({
524
+ name: 'client.alert.displayed',
525
+ options,
526
+ });
527
+
528
+ assert.calledWith(getIdentifiersSpy, {
529
+ correlationId: 'correlationId',
530
+ webexConferenceIdStr: 'webexConferenceIdStr1',
531
+ globalMeetingId: 'globalMeetingId1',
532
+ preLoginId: undefined,
533
+ });
534
+
535
+ assert.notCalled(generateClientEventErrorPayloadSpy);
536
+ assert.calledWith(
537
+ prepareDiagnosticEventSpy,
538
+ {
539
+ canProceed: true,
540
+ eventData: {
541
+ webClientDomain: 'whatever',
542
+ },
543
+ identifiers: {
544
+ correlationId: 'correlationId',
545
+ webexConferenceIdStr: 'webexConferenceIdStr1',
546
+ globalMeetingId: 'globalMeetingId1',
547
+ deviceId: 'deviceUrl',
548
+ locusUrl: 'locus-url',
549
+ orgId: 'orgId',
550
+ userId: 'userId',
551
+ },
552
+ loginType: 'login-ci',
553
+ name: 'client.alert.displayed',
554
+ },
555
+ options
556
+ );
557
+ assert.calledWith(submitToCallDiagnosticsSpy, {
558
+ event: {
559
+ canProceed: true,
560
+ eventData: {
561
+ webClientDomain: 'whatever',
562
+ },
563
+ identifiers: {
564
+ correlationId: 'correlationId',
565
+ webexConferenceIdStr: 'webexConferenceIdStr1',
566
+ globalMeetingId: 'globalMeetingId1',
567
+ deviceId: 'deviceUrl',
568
+ locusUrl: 'locus-url',
569
+ orgId: 'orgId',
570
+ userId: 'userId',
571
+ },
572
+ loginType: 'login-ci',
573
+ name: 'client.alert.displayed',
574
+ },
575
+ eventId: 'my-fake-id',
576
+ origin: {
577
+ origin: 'fake-origin',
578
+ },
579
+ originTime: {
580
+ sent: 'not_defined_yet',
581
+ triggered: now.toISOString(),
582
+ },
583
+ senderCountryCode: 'UK',
584
+ version: 1,
585
+ });
586
+
587
+ const webexLoggerLogCalls = webex.logger.log.getCalls();
588
+
589
+ assert.deepEqual(webexLoggerLogCalls[0].args, [
590
+ 'call-diagnostic-events -> ',
591
+ 'CallDiagnosticMetrics: @submitClientEvent. Submit Client Event CA event.',
592
+ `name: client.alert.displayed`,
593
+ `payload: undefined`,
594
+ `options: ${JSON.stringify(options)}`,
595
+ ]);
596
+
597
+ assert.deepEqual(webexLoggerLogCalls[1].args, [
598
+ 'call-diagnostic-events -> ',
599
+ 'CallDiagnosticMetrics: @createClientEventObjectPreMeeting. Creating pre meeting event object.',
600
+ `name: client.alert.displayed`
601
+ ]);
602
+
603
+ assert.deepEqual(webexLoggerLogCalls[2].args, [
604
+ 'call-diagnostic-events -> ',
605
+ 'CallDiagnosticMetrics: @submitToCallDiagnostics. Preparing to send the request',
606
+ `finalEvent: {"eventPayload":{"eventId":"my-fake-id","version":1,"origin":{"origin":"fake-origin"},"originTime":{"triggered":"${now.toISOString()}","sent":"not_defined_yet"},"senderCountryCode":"UK","event":{"name":"client.alert.displayed","canProceed":true,"identifiers":{"correlationId":"correlationId","userId":"userId","deviceId":"deviceUrl","orgId":"orgId","locusUrl":"locus-url","webexConferenceIdStr":"webexConferenceIdStr1","globalMeetingId":"globalMeetingId1"},"eventData":{"webClientDomain":"whatever"},"loginType":"login-ci"}},"type":["diagnostic-event"]}`,
607
+ ]);
608
+
609
+
610
+ });
611
+
612
+ it('should submit client event successfully with preLoginId', () => {
613
+ webex.internal.device.userId = undefined;
614
+
615
+ const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
616
+ const submitToCallDiagnosticsPreLoginSpy = sinon.spy(cd, 'submitToCallDiagnosticsPreLogin');
617
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
618
+ const generateClientEventErrorPayloadSpy = sinon.spy(cd, 'generateClientEventErrorPayload');
619
+ const getIdentifiersSpy = sinon.spy(cd, 'getIdentifiers');
620
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
621
+
622
+ const options = {
623
+ correlationId: 'correlationId',
624
+ webexConferenceIdStr: 'webexConferenceIdStr1',
625
+ globalMeetingId: 'globalMeetingId1',
626
+ preLoginId: 'myPreLoginId'
627
+ };
628
+
629
+ cd.submitClientEvent({
630
+ name: 'client.alert.displayed',
631
+ options,
632
+ });
633
+
634
+ assert.calledWith(getIdentifiersSpy, {
635
+ correlationId: 'correlationId',
636
+ webexConferenceIdStr: 'webexConferenceIdStr1',
637
+ globalMeetingId: 'globalMeetingId1',
638
+ preLoginId: 'myPreLoginId',
639
+ });
640
+
641
+ assert.notCalled(generateClientEventErrorPayloadSpy);
642
+ assert.calledWith(
643
+ prepareDiagnosticEventSpy,
644
+ {
645
+ canProceed: true,
646
+ eventData: {
647
+ webClientDomain: 'whatever',
648
+ },
649
+ identifiers: {
650
+ correlationId: 'correlationId',
651
+ webexConferenceIdStr: 'webexConferenceIdStr1',
652
+ globalMeetingId: 'globalMeetingId1',
653
+ deviceId: 'deviceUrl',
654
+ locusUrl: 'locus-url',
655
+ orgId: 'orgId',
656
+ userId: 'myPreLoginId',
657
+ },
658
+ loginType: 'login-ci',
659
+ name: 'client.alert.displayed',
660
+ },
661
+ options
662
+ );
663
+ assert.notCalled(submitToCallDiagnosticsSpy);
664
+ assert.calledWith(submitToCallDiagnosticsPreLoginSpy, {
665
+ event: {
666
+ canProceed: true,
667
+ eventData: {
668
+ webClientDomain: 'whatever',
669
+ },
670
+ identifiers: {
671
+ correlationId: 'correlationId',
672
+ webexConferenceIdStr: 'webexConferenceIdStr1',
673
+ globalMeetingId: 'globalMeetingId1',
674
+ deviceId: 'deviceUrl',
675
+ locusUrl: 'locus-url',
676
+ orgId: 'orgId',
677
+ userId: 'myPreLoginId',
678
+ },
679
+ loginType: 'login-ci',
680
+ name: 'client.alert.displayed',
681
+ },
682
+ eventId: 'my-fake-id',
683
+ origin: { buildType: 'test', networkType: 'unknown', origin: 'fake-origin' },
684
+ originTime: {
685
+ triggered: now.toISOString(),
686
+ sent: now.toISOString()
687
+ },
688
+ senderCountryCode: 'UK',
689
+ version: 1,
690
+ });
691
+ })
692
+
693
+ it('it should include errors if provided with meetingId', () => {
694
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
695
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
696
+
697
+ const options = {
698
+ meetingId: fakeMeeting.id,
699
+ webexConferenceIdStr: 'webexConferenceIdStr1',
700
+ globalMeetingId: 'globalMeetingId1',
701
+ mediaConnections: [{mediaAgentAlias: 'alias', mediaAgentGroupId: '1'}],
702
+ rawError: {
703
+ body: {
704
+ errorCode: 2409005,
705
+ },
706
+ },
707
+ };
708
+
709
+ cd.submitClientEvent({
710
+ name: 'client.alert.displayed',
711
+ options,
712
+ });
713
+
714
+ assert.calledWith(submitToCallDiagnosticsSpy, {
715
+ event: {
716
+ canProceed: true,
717
+ eventData: {
718
+ webClientDomain: 'whatever',
719
+ },
720
+ identifiers: {
721
+ correlationId: 'correlationId',
722
+ webexConferenceIdStr: 'webexConferenceIdStr1',
723
+ globalMeetingId: 'globalMeetingId1',
724
+ deviceId: 'deviceUrl',
725
+ locusId: 'url',
726
+ locusStartTime: 'lastActive',
727
+ locusUrl: 'locus/url',
728
+ mediaAgentAlias: 'alias',
729
+ mediaAgentGroupId: '1',
730
+ orgId: 'orgId',
731
+ userId: 'userId',
732
+ },
733
+ errors: [
734
+ {
735
+ category: 'expected',
736
+ errorDescription: 'StartRecordingFailed',
737
+ fatal: true,
738
+ name: 'other',
739
+ shownToUser: false,
740
+ serviceErrorCode: 2409005,
741
+ errorCode: 4029,
742
+ },
743
+ ],
744
+ loginType: 'login-ci',
745
+ name: 'client.alert.displayed',
746
+ userType: 'host',
747
+ isConvergedArchitectureEnabled: undefined,
748
+ },
749
+ eventId: 'my-fake-id',
750
+ origin: {
751
+ origin: 'fake-origin',
752
+ },
753
+ originTime: {
754
+ sent: 'not_defined_yet',
755
+ triggered: now.toISOString(),
756
+ },
757
+ senderCountryCode: 'UK',
758
+ version: 1,
759
+ });
760
+
761
+ const webexLoggerLogCalls = webex.logger.log.getCalls();
762
+ assert.deepEqual(webexLoggerLogCalls[0].args, [
763
+ 'call-diagnostic-events -> ',
764
+ 'CallDiagnosticMetrics: @submitClientEvent. Submit Client Event CA event.',
765
+ `name: client.alert.displayed`,
766
+ `payload: undefined`,
767
+ `options: ${JSON.stringify(options)}`,
768
+ ]);
769
+
770
+
771
+ assert.deepEqual(webexLoggerLogCalls[1].args, [
772
+ 'call-diagnostic-events -> ',
773
+ 'CallDiagnosticMetrics: @prepareClientEvent. Error detected, attempting to map and attach it to the event...',
774
+ `name: client.alert.displayed`,
775
+ `rawError: ${options.rawError}`
776
+ ]);
777
+
778
+ assert.deepEqual(webexLoggerLogCalls[2].args, [
779
+ 'call-diagnostic-events -> ',
780
+ 'CallDiagnosticMetrics: @prepareClientEvent. Generated errors:',
781
+ `generatedError: {"fatal":true,"shownToUser":false,"name":"other","category":"expected","errorCode":4029,"serviceErrorCode":2409005,"errorDescription":"StartRecordingFailed"}`
782
+ ])
783
+
784
+ assert.deepEqual(webexLoggerLogCalls[3].args, [
785
+ 'call-diagnostic-events -> ',
786
+ 'CallDiagnosticMetrics: @createClientEventObjectInMeeting. Creating in meeting event object.',
787
+ `name: client.alert.displayed`
788
+ ]);
789
+
790
+ assert.deepEqual(webexLoggerLogCalls[4].args, [
791
+ 'call-diagnostic-events -> ',
792
+ 'CallDiagnosticMetrics: @submitToCallDiagnostics. Preparing to send the request',
793
+ `finalEvent: {"eventPayload":{"eventId":"my-fake-id","version":1,"origin":{"origin":"fake-origin"},"originTime":{"triggered":"${now.toISOString()}","sent":"not_defined_yet"},"senderCountryCode":"UK","event":{"name":"client.alert.displayed","canProceed":true,"identifiers":{"correlationId":"correlationId","userId":"userId","deviceId":"deviceUrl","orgId":"orgId","locusUrl":"locus/url","locusId":"url","locusStartTime":"lastActive","mediaAgentAlias":"alias","mediaAgentGroupId":"1","webexConferenceIdStr":"webexConferenceIdStr1","globalMeetingId":"globalMeetingId1"},"errors":[{"fatal":true,"shownToUser":false,"name":"other","category":"expected","errorCode":4029,"serviceErrorCode":2409005,"errorDescription":"StartRecordingFailed"}],"eventData":{"webClientDomain":"whatever"},"userType":"host","loginType":"login-ci"}},"type":["diagnostic-event"]}`,
794
+ ]);
795
+ });
796
+
797
+ it('it send the raw error message if meetingId provided', () => {
798
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
799
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
800
+
801
+ const options = {
802
+ meetingId: fakeMeeting.id,
803
+ mediaConnections: [{mediaAgentAlias: 'alias', mediaAgentGroupId: '1'}],
804
+ rawError: new Error('bad times')
805
+ };
806
+
807
+ cd.submitClientEvent({
808
+ name: 'client.alert.displayed',
809
+ options,
810
+ });
811
+
812
+ console.log(submitToCallDiagnosticsSpy.getCalls()[0].args[0].event.errors)
813
+
814
+ assert.calledWith(submitToCallDiagnosticsSpy, {
815
+ event: {
816
+ canProceed: true,
817
+ eventData: {
818
+ webClientDomain: 'whatever',
819
+ rawErrorMessage: 'bad times',
820
+ },
821
+ identifiers: {
822
+ correlationId: 'correlationId',
823
+ deviceId: 'deviceUrl',
824
+ locusId: 'url',
825
+ locusStartTime: 'lastActive',
826
+ locusUrl: 'locus/url',
827
+ mediaAgentAlias: 'alias',
828
+ mediaAgentGroupId: '1',
829
+ orgId: 'orgId',
830
+ userId: 'userId',
831
+ },
832
+ errors: [
833
+ {
834
+ fatal: true,
835
+ shownToUser: false,
836
+ name: 'other',
837
+ category: 'other',
838
+ errorCode: 9999,
839
+ serviceErrorCode: 9999,
840
+ errorDescription: 'UnknownError',
841
+ },
842
+ ],
843
+ loginType: 'login-ci',
844
+ name: 'client.alert.displayed',
845
+ userType: 'host',
846
+ isConvergedArchitectureEnabled: undefined,
847
+ },
848
+ eventId: 'my-fake-id',
849
+ origin: {
850
+ origin: 'fake-origin',
851
+ },
852
+ originTime: {
853
+ sent: 'not_defined_yet',
854
+ triggered: now.toISOString(),
855
+ },
856
+ senderCountryCode: 'UK',
857
+ version: 1,
858
+ });
859
+
860
+ const webexLoggerLogCalls = webex.logger.log.getCalls();
861
+ assert.deepEqual(webexLoggerLogCalls[0].args, [
862
+ 'call-diagnostic-events -> ',
863
+ 'CallDiagnosticMetrics: @submitClientEvent. Submit Client Event CA event.',
864
+ `name: client.alert.displayed`,
865
+ `payload: undefined`,
866
+ `options: ${JSON.stringify(options)}`,
867
+ ]);
868
+
869
+ assert.deepEqual(webexLoggerLogCalls[1].args, [
870
+ 'call-diagnostic-events -> ',
871
+ 'CallDiagnosticMetrics: @prepareClientEvent. Error detected, attempting to map and attach it to the event...',
872
+ `name: client.alert.displayed`,
873
+ `rawError: ${JSON.stringify({
874
+ message: options.rawError.message,
875
+ name: options.rawError.name,
876
+ stack: options.rawError.stack,
877
+ })}`,
878
+ ]);
879
+
880
+ assert.deepEqual(webexLoggerLogCalls[2].args, [
881
+ 'call-diagnostic-events -> ',
882
+ 'CallDiagnosticMetrics: @prepareClientEvent. Generated errors:',
883
+ `generatedError: {"fatal":true,"shownToUser":false,"name":"other","category":"other","errorCode":9999,"serviceErrorCode":9999,"errorDescription":"UnknownError"}`,
884
+ ]);
885
+
886
+ assert.deepEqual(webexLoggerLogCalls[3].args, [
887
+ 'call-diagnostic-events -> ',
888
+ 'CallDiagnosticMetrics: @createClientEventObjectInMeeting. Creating in meeting event object.',
889
+ `name: client.alert.displayed`,
890
+ ]);
891
+
892
+ assert.deepEqual(webexLoggerLogCalls[4].args, [
893
+ 'call-diagnostic-events -> ',
894
+ 'CallDiagnosticMetrics: @submitToCallDiagnostics. Preparing to send the request',
895
+ `finalEvent: {"eventPayload":{"eventId":"my-fake-id","version":1,"origin":{"origin":"fake-origin"},"originTime":{"triggered":"${now.toISOString()}","sent":"not_defined_yet"},"senderCountryCode":"UK","event":{"name":"client.alert.displayed","canProceed":true,"identifiers":{"correlationId":"correlationId","userId":"userId","deviceId":"deviceUrl","orgId":"orgId","locusUrl":"locus/url","locusId":"url","locusStartTime":"lastActive","mediaAgentAlias":"alias","mediaAgentGroupId":"1"},"errors":[{"fatal":true,"shownToUser":false,"name":"other","category":"other","errorCode":9999,"serviceErrorCode":9999,"errorDescription":"UnknownError"}],"eventData":{"webClientDomain":"whatever","rawErrorMessage":"bad times"},"userType":"host","loginType":"login-ci"}},"type":["diagnostic-event"]}`,
896
+ ]);
897
+ });
898
+
899
+ it('it should include errors if provided with correlationId', () => {
900
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
901
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
902
+
903
+ const options = {
904
+ correlationId: 'correlationId',
905
+ rawError: new Error('bad times'),
906
+ };
907
+
908
+ cd.submitClientEvent({
909
+ name: 'client.alert.displayed',
910
+ options,
911
+ });
912
+
913
+ assert.calledWith(submitToCallDiagnosticsSpy, {
914
+ event: {
915
+ canProceed: true,
916
+ eventData: {
917
+ webClientDomain: 'whatever',
918
+ rawErrorMessage: 'bad times',
919
+ },
920
+ identifiers: {
921
+ correlationId: 'correlationId',
922
+ deviceId: 'deviceUrl',
923
+ locusUrl: 'locus-url',
924
+ orgId: 'orgId',
925
+ userId: 'userId',
926
+ },
927
+ errors: [
928
+ {
929
+ fatal: true,
930
+ shownToUser: false,
931
+ name: 'other',
932
+ category: 'other',
933
+ errorCode: 9999,
934
+ serviceErrorCode: 9999,
935
+ errorDescription: 'UnknownError',
936
+ },
937
+ ],
938
+ loginType: 'login-ci',
939
+ name: 'client.alert.displayed',
940
+ },
941
+ eventId: 'my-fake-id',
942
+ origin: {
943
+ origin: 'fake-origin',
944
+ },
945
+ originTime: {
946
+ sent: 'not_defined_yet',
947
+ triggered: now.toISOString(),
948
+ },
949
+ senderCountryCode: 'UK',
950
+ version: 1,
951
+ });
952
+
953
+ const webexLoggerLogCalls = webex.logger.log.getCalls();
954
+
955
+ assert.deepEqual(webexLoggerLogCalls[0].args, [
956
+ 'call-diagnostic-events -> ',
957
+ 'CallDiagnosticMetrics: @submitClientEvent. Submit Client Event CA event.',
958
+ `name: client.alert.displayed`,
959
+ `payload: undefined`,
960
+ `options: ${JSON.stringify(options)}`,
961
+ ]);
962
+
963
+
964
+ assert.deepEqual(webexLoggerLogCalls[1].args, [
965
+ 'call-diagnostic-events -> ',
966
+ 'CallDiagnosticMetrics: @prepareClientEvent. Error detected, attempting to map and attach it to the event...',
967
+ `name: client.alert.displayed`,
968
+ `rawError: ${JSON.stringify({
969
+ message: options.rawError.message,
970
+ name: options.rawError.name,
971
+ stack: options.rawError.stack,
972
+ })}`,
973
+ ]);
974
+
975
+ assert.deepEqual(webexLoggerLogCalls[2].args, [
976
+ 'call-diagnostic-events -> ',
977
+ 'CallDiagnosticMetrics: @prepareClientEvent. Generated errors:',
978
+ `generatedError: {"fatal":true,"shownToUser":false,"name":"other","category":"other","errorCode":9999,"serviceErrorCode":9999,"errorDescription":"UnknownError"}`,
979
+ ]);
980
+
981
+ assert.deepEqual(webexLoggerLogCalls[3].args, [
982
+ 'call-diagnostic-events -> ',
983
+ 'CallDiagnosticMetrics: @createClientEventObjectPreMeeting. Creating pre meeting event object.',
984
+ `name: client.alert.displayed`
985
+ ]);
986
+
987
+ assert.deepEqual(webexLoggerLogCalls[4].args, [
988
+ 'call-diagnostic-events -> ',
989
+ 'CallDiagnosticMetrics: @submitToCallDiagnostics. Preparing to send the request',
990
+ `finalEvent: {"eventPayload":{"eventId":"my-fake-id","version":1,"origin":{"origin":"fake-origin"},"originTime":{"triggered":"${now.toISOString()}","sent":"not_defined_yet"},"senderCountryCode":"UK","event":{"name":"client.alert.displayed","errors":[{"fatal":true,"shownToUser":false,"name":"other","category":"other","errorCode":9999,"serviceErrorCode":9999,"errorDescription":"UnknownError"}],"canProceed":true,"identifiers":{"correlationId":"correlationId","userId":"userId","deviceId":"deviceUrl","orgId":"orgId","locusUrl":"locus-url"},"eventData":{"webClientDomain":"whatever","rawErrorMessage":"bad times"},"loginType":"login-ci"}},"type":["diagnostic-event"]}`,
991
+ ]);
992
+ });
993
+
994
+ it('it should send the raw error message if provided with correlationId', () => {
995
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
996
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
997
+
998
+ const options = {
999
+ correlationId: 'correlationId',
1000
+ rawError: {
1001
+ body: {
1002
+ errorCode: 2409005,
1003
+ },
1004
+ },
1005
+ };
1006
+
1007
+ cd.submitClientEvent({
1008
+ name: 'client.alert.displayed',
1009
+ options,
1010
+ });
1011
+
1012
+ assert.calledWith(submitToCallDiagnosticsSpy, {
1013
+ event: {
1014
+ canProceed: true,
1015
+ eventData: {
1016
+ webClientDomain: 'whatever',
1017
+ },
1018
+ identifiers: {
1019
+ correlationId: 'correlationId',
1020
+ deviceId: 'deviceUrl',
1021
+ locusUrl: 'locus-url',
1022
+ orgId: 'orgId',
1023
+ userId: 'userId',
1024
+ },
1025
+ errors: [
1026
+ {
1027
+ category: 'expected',
1028
+ errorDescription: 'StartRecordingFailed',
1029
+ fatal: true,
1030
+ name: 'other',
1031
+ shownToUser: false,
1032
+ serviceErrorCode: 2409005,
1033
+ errorCode: 4029,
1034
+ },
1035
+ ],
1036
+ loginType: 'login-ci',
1037
+ name: 'client.alert.displayed',
1038
+ },
1039
+ eventId: 'my-fake-id',
1040
+ origin: {
1041
+ origin: 'fake-origin',
1042
+ },
1043
+ originTime: {
1044
+ sent: 'not_defined_yet',
1045
+ triggered: now.toISOString(),
1046
+ },
1047
+ senderCountryCode: 'UK',
1048
+ version: 1,
1049
+ });
1050
+
1051
+ const webexLoggerLogCalls = webex.logger.log.getCalls();
1052
+
1053
+ assert.deepEqual(webexLoggerLogCalls[0].args, [
1054
+ 'call-diagnostic-events -> ',
1055
+ 'CallDiagnosticMetrics: @submitClientEvent. Submit Client Event CA event.',
1056
+ `name: client.alert.displayed`,
1057
+ `payload: undefined`,
1058
+ `options: ${JSON.stringify(options)}`,
1059
+ ]);
1060
+
1061
+ assert.deepEqual(webexLoggerLogCalls[1].args, [
1062
+ 'call-diagnostic-events -> ',
1063
+ 'CallDiagnosticMetrics: @prepareClientEvent. Error detected, attempting to map and attach it to the event...',
1064
+ `name: client.alert.displayed`,
1065
+ `rawError: ${options.rawError}`,
1066
+ ]);
1067
+
1068
+ assert.deepEqual(webexLoggerLogCalls[2].args, [
1069
+ 'call-diagnostic-events -> ',
1070
+ 'CallDiagnosticMetrics: @prepareClientEvent. Generated errors:',
1071
+ `generatedError: {"fatal":true,"shownToUser":false,"name":"other","category":"expected","errorCode":4029,"serviceErrorCode":2409005,"errorDescription":"StartRecordingFailed"}`,
1072
+ ]);
1073
+
1074
+ assert.deepEqual(webexLoggerLogCalls[3].args, [
1075
+ 'call-diagnostic-events -> ',
1076
+ 'CallDiagnosticMetrics: @createClientEventObjectPreMeeting. Creating pre meeting event object.',
1077
+ `name: client.alert.displayed`,
1078
+ ]);
1079
+
1080
+ assert.deepEqual(webexLoggerLogCalls[4].args, [
1081
+ 'call-diagnostic-events -> ',
1082
+ 'CallDiagnosticMetrics: @submitToCallDiagnostics. Preparing to send the request',
1083
+ `finalEvent: {"eventPayload":{"eventId":"my-fake-id","version":1,"origin":{"origin":"fake-origin"},"originTime":{"triggered":"${now.toISOString()}","sent":"not_defined_yet"},"senderCountryCode":"UK","event":{"name":"client.alert.displayed","errors":[{"fatal":true,"shownToUser":false,"name":"other","category":"expected","errorCode":4029,"serviceErrorCode":2409005,"errorDescription":"StartRecordingFailed"}],"canProceed":true,"identifiers":{"correlationId":"correlationId","userId":"userId","deviceId":"deviceUrl","orgId":"orgId","locusUrl":"locus-url"},"eventData":{"webClientDomain":"whatever"},"loginType":"login-ci"}},"type":["diagnostic-event"]}`,
1084
+ ]);
1085
+ });
1086
+
1087
+ it('should include errors in payload if provided via payload', () => {
1088
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
1089
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
1090
+
1091
+ const options = {
1092
+ meetingId: fakeMeeting.id,
1093
+ mediaConnections: [{mediaAgentAlias: 'alias', mediaAgentGroupId: '1'}],
1094
+ };
1095
+
1096
+ cd.submitClientEvent({
1097
+ name: 'client.alert.displayed',
1098
+ payload: {
1099
+ errors: [
1100
+ {
1101
+ name: 'locus.response',
1102
+ fatal: true,
1103
+ category: 'signaling',
1104
+ shownToUser: false,
1105
+ },
1106
+ ],
1107
+ },
1108
+ options,
1109
+ });
1110
+
1111
+ assert.calledWith(submitToCallDiagnosticsSpy, {
1112
+ event: {
1113
+ canProceed: true,
1114
+ eventData: {
1115
+ webClientDomain: 'whatever',
1116
+ },
1117
+ identifiers: {
1118
+ correlationId: 'correlationId',
1119
+ deviceId: 'deviceUrl',
1120
+ locusId: 'url',
1121
+ locusStartTime: 'lastActive',
1122
+ locusUrl: 'locus/url',
1123
+ mediaAgentAlias: 'alias',
1124
+ mediaAgentGroupId: '1',
1125
+ orgId: 'orgId',
1126
+ userId: 'userId',
1127
+ },
1128
+ errors: [
1129
+ {
1130
+ name: 'locus.response',
1131
+ fatal: true,
1132
+ category: 'signaling',
1133
+ shownToUser: false,
1134
+ },
1135
+ ],
1136
+ loginType: 'login-ci',
1137
+ name: 'client.alert.displayed',
1138
+ userType: 'host',
1139
+ isConvergedArchitectureEnabled: undefined,
1140
+ },
1141
+ eventId: 'my-fake-id',
1142
+ origin: {
1143
+ origin: 'fake-origin',
1144
+ },
1145
+ originTime: {
1146
+ sent: 'not_defined_yet',
1147
+ triggered: now.toISOString(),
1148
+ },
1149
+ senderCountryCode: 'UK',
1150
+ version: 1,
1151
+ });
1152
+ });
1153
+
1154
+ it('should throw if meetingId nor correlationId not provided', () => {
1155
+ assert.throws(() =>
1156
+ cd.submitClientEvent({
1157
+ name: 'client.alert.displayed',
1158
+ })
1159
+ );
1160
+ });
1161
+
1162
+ it('should send behavioral event if meetingId provided but meeting is undefined', () => {
1163
+ webex.meetings.meetingCollection.get = sinon.stub().returns(undefined);
1164
+ cd.submitClientEvent({name: 'client.alert.displayed', options: {meetingId: 'meetingId'}});
1165
+ assert.calledWith(
1166
+ webex.internal.metrics.submitClientMetrics,
1167
+ 'js_sdk_call_diagnostic_event_failed_to_send',
1168
+ {
1169
+ fields: {meetingId: 'meetingId', name: 'client.alert.displayed'},
1170
+ }
1171
+ );
1172
+ });
1173
+
1174
+ it('should submit client to diagnostic when no preLoginId provided', () => {
1175
+ const testEvent = {name: 'client.alert.displayed', options: {meetingId: 'meetingId'}};
1176
+ sinon.stub(cd, 'prepareClientEvent').returns(testEvent);
1177
+ sinon.stub(cd, 'submitToCallDiagnostics');
1178
+ sinon.stub(cd, 'submitToCallDiagnosticsPreLogin');
1179
+ //@ts-ignore
1180
+ cd.submitClientEvent(testEvent);
1181
+ assert.calledWith(cd.submitToCallDiagnostics, testEvent);
1182
+ assert.notCalled(cd.submitToCallDiagnosticsPreLogin);
1183
+ });
1184
+
1185
+ it('should submit event to prelogin when preLoginId provided', () => {
1186
+ const testEvent = {name: 'client.alert.displayed', options: {preLoginId: 'preLoginId'}};
1187
+ sinon.stub(cd, 'prepareClientEvent').returns(testEvent);
1188
+ sinon.stub(cd, 'submitToCallDiagnosticsPreLogin');
1189
+ sinon.stub(cd, 'submitToCallDiagnostics');
1190
+ //@ts-ignore
1191
+ cd.submitClientEvent(testEvent);
1192
+ assert.calledWith(cd.submitToCallDiagnosticsPreLogin, testEvent);
1193
+ assert.notCalled(cd.submitToCallDiagnostics);
1194
+ });
1195
+ });
1196
+
1197
+ it('should send request to call diagnostic batcher', () => {
1198
+ const requestStub = sinon.stub();
1199
+ //@ts-ignore
1200
+ cd.callDiagnosticEventsBatcher = {request: requestStub};
1201
+ //@ts-ignore
1202
+ cd.submitToCallDiagnostics({event: 'test'});
1203
+ assert.calledWith(requestStub, {eventPayload: {event: 'test'}, type: ['diagnostic-event']});
1204
+ });
1205
+
1206
+ describe('#submitMQE', () => {
1207
+ it('submits the event correctly', () => {
1208
+ const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
1209
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
1210
+ const getErrorPayloadForClientErrorCodeSpy = sinon.spy(
1211
+ cd,
1212
+ 'getErrorPayloadForClientErrorCode'
1213
+ );
1214
+ const getIdentifiersSpy = sinon.spy(cd, 'getIdentifiers');
1215
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
1216
+ const options = {
1217
+ networkType: 'wifi' as const,
1218
+ meetingId: fakeMeeting.id,
1219
+ webexConferenceIdStr: 'webexConferenceIdStr1',
1220
+ globalMeetingId: 'globalMeetingId1',
1221
+ };
1222
+
1223
+ cd.submitMQE({
1224
+ name: 'client.mediaquality.event',
1225
+ payload: {
1226
+ //@ts-ignore
1227
+ intervals: [{}],
1228
+ },
1229
+ options,
1230
+ });
1231
+
1232
+ assert.calledWith(getIdentifiersSpy, {
1233
+ meeting: fakeMeeting,
1234
+ mediaConnections: undefined,
1235
+ webexConferenceIdStr: 'webexConferenceIdStr1',
1236
+ globalMeetingId: 'globalMeetingId1',
1237
+ });
1238
+ assert.notCalled(getErrorPayloadForClientErrorCodeSpy);
1239
+ assert.calledWith(
1240
+ prepareDiagnosticEventSpy,
1241
+ {
1242
+ name: 'client.mediaquality.event',
1243
+ canProceed: true,
1244
+ identifiers: {
1245
+ correlationId: 'correlationId',
1246
+ webexConferenceIdStr: 'webexConferenceIdStr1',
1247
+ globalMeetingId: 'globalMeetingId1',
1248
+ userId: 'userId',
1249
+ deviceId: 'deviceUrl',
1250
+ orgId: 'orgId',
1251
+ locusUrl: 'locus/url',
1252
+ locusId: 'url',
1253
+ locusStartTime: 'lastActive',
1254
+ },
1255
+ eventData: {webClientDomain: 'whatever'},
1256
+ intervals: [{}],
1257
+ sourceMetadata: {
1258
+ applicationSoftwareType: 'webex-js-sdk',
1259
+ applicationSoftwareVersion: 'webex-version',
1260
+ mediaEngineSoftwareType: 'browser',
1261
+ mediaEngineSoftwareVersion: getOSVersion(),
1262
+ startTime: now.toISOString(),
1263
+ },
1264
+ },
1265
+ options
1266
+ );
1267
+
1268
+ assert.calledWith(submitToCallDiagnosticsSpy, {
1269
+ eventId: 'my-fake-id',
1270
+ version: 1,
1271
+ origin: {origin: 'fake-origin'},
1272
+ originTime: {triggered: now.toISOString(), sent: 'not_defined_yet'},
1273
+ senderCountryCode: 'UK',
1274
+ event: {
1275
+ name: 'client.mediaquality.event',
1276
+ canProceed: true,
1277
+ identifiers: {
1278
+ correlationId: 'correlationId',
1279
+ webexConferenceIdStr: 'webexConferenceIdStr1',
1280
+ globalMeetingId: 'globalMeetingId1',
1281
+ userId: 'userId',
1282
+ deviceId: 'deviceUrl',
1283
+ orgId: 'orgId',
1284
+ locusUrl: 'locus/url',
1285
+ locusId: 'url',
1286
+ locusStartTime: 'lastActive',
1287
+ },
1288
+ eventData: {webClientDomain: 'whatever'},
1289
+ intervals: [{}],
1290
+ sourceMetadata: {
1291
+ applicationSoftwareType: 'webex-js-sdk',
1292
+ applicationSoftwareVersion: 'webex-version',
1293
+ mediaEngineSoftwareType: 'browser',
1294
+ mediaEngineSoftwareVersion: getOSVersion(),
1295
+ startTime: now.toISOString(),
1296
+ },
1297
+ },
1298
+ });
1299
+ });
1300
+
1301
+ it('throws if meeting id not provided', () => {
1302
+ assert.throws(() =>
1303
+ cd.submitMQE({
1304
+ name: 'client.mediaquality.event',
1305
+ payload: {
1306
+ //@ts-ignore
1307
+ intervals: [{}],
1308
+ },
1309
+ //@ts-ignore
1310
+ options: {meetingId: undefined, networkType: 'wifi'},
1311
+ })
1312
+ );
1313
+ });
1314
+
1315
+ it('should send behavioral event if meeting is undefined', () => {
1316
+ webex.meetings.meetingCollection.get = sinon.stub().returns(undefined);
1317
+ cd.submitMQE({
1318
+ name: 'client.mediaquality.event',
1319
+ payload: {
1320
+ //@ts-ignore
1321
+ intervals: [{}],
1322
+ },
1323
+ options: {meetingId: 'meetingId'},
1324
+ });
1325
+ assert.calledWith(
1326
+ webex.internal.metrics.submitClientMetrics,
1327
+ 'js_sdk_call_diagnostic_event_failed_to_send',
1328
+ {
1329
+ fields: {meetingId: 'meetingId', name: 'client.mediaquality.event'},
1330
+ }
1331
+ );
1332
+ });
1333
+ });
1334
+
1335
+ describe('#getErrorPayloadForClientErrorCode', () => {
1336
+ it('it should grab the payload for client error code correctly', () => {
1337
+ const res = cd.getErrorPayloadForClientErrorCode({
1338
+ clientErrorCode: 4008,
1339
+ serviceErrorCode: 10000,
1340
+ });
1341
+ assert.deepEqual(res, {
1342
+ category: 'signaling',
1343
+ errorDescription: 'NewLocusError',
1344
+ fatal: true,
1345
+ name: 'other',
1346
+ shownToUser: false,
1347
+ errorCode: 4008,
1348
+ serviceErrorCode: 10000,
1349
+ });
1350
+ });
1351
+
1352
+ it('should generate the correct payload for client error 4009', () => {
1353
+ const res = cd.getErrorPayloadForClientErrorCode({
1354
+ clientErrorCode: 4009,
1355
+ serviceErrorCode: undefined,
1356
+ });
1357
+ assert.deepEqual(res, {
1358
+ category: 'network',
1359
+ errorDescription: 'NetworkUnavailable',
1360
+ fatal: true,
1361
+ name: 'other',
1362
+ shownToUser: false,
1363
+ errorCode: 4009,
1364
+ serviceErrorCode: undefined,
1365
+ });
1366
+ })
1367
+
1368
+ it('it should return undefined if trying to get payload for client error code that doesnt exist', () => {
1369
+ const res = cd.getErrorPayloadForClientErrorCode({
1370
+ clientErrorCode: 123456,
1371
+ serviceErrorCode: 100000,
1372
+ });
1373
+ assert.deepEqual(res, undefined);
1374
+ });
1375
+ });
1376
+
1377
+ describe('#generateClientEventErrorPayload', () => {
1378
+ const defaultExpectedRes = {
1379
+ category: 'expected',
1380
+ errorDescription: 'StartRecordingFailed',
1381
+ fatal: true,
1382
+ name: 'other',
1383
+ shownToUser: false,
1384
+ errorCode: 4029,
1385
+ serviceErrorCode: 2409005,
1386
+ };
1387
+
1388
+ const checkNameError = (payload: any, isExpectedToBeCalled: boolean) => {
1389
+ const res = cd.generateClientEventErrorPayload(payload);
1390
+ const expectedResult = {
1391
+ category: 'expected',
1392
+ errorDescription: 'CameraPermissionDenied',
1393
+ fatal: true,
1394
+ name: 'other',
1395
+ shownToUser: false,
1396
+ serviceErrorCode: undefined,
1397
+ errorCode: 4032,
1398
+ errorData: {errorName: payload.name},
1399
+ };
1400
+
1401
+ if (isExpectedToBeCalled) {
1402
+ assert.deepEqual(res, expectedResult);
1403
+ } else {
1404
+ assert.notDeepEqual(res, expectedResult);
1405
+ }
1406
+ };
1407
+
1408
+ it('should generate media event error payload if rawError has a media error name', () => {
1409
+ checkNameError({name: 'PermissionDeniedError'}, true);
1410
+ });
1411
+
1412
+ it('should not generate media event error payload if rawError has a name that is not recognized', () => {
1413
+ checkNameError({name: 'SomeRandomError'}, false);
1414
+ });
1415
+
1416
+ const checkCodeError = (payload: any, expetedRes: any) => {
1417
+ const res = cd.generateClientEventErrorPayload(payload);
1418
+ assert.deepEqual(res, expetedRes);
1419
+ };
1420
+ it('should generate event error payload correctly', () => {
1421
+ checkCodeError({body: {errorCode: 2409005}}, defaultExpectedRes);
1422
+ });
1423
+
1424
+ it('should generate event error payload correctly if rawError has body.code', () => {
1425
+ checkCodeError({body: {code: 2409005}}, defaultExpectedRes);
1426
+ });
1427
+
1428
+ it('should generate event error payload correctly if rawError has body.reason.reasonCode', () => {
1429
+ checkCodeError({body: {reason: {reasonCode: 2409005}}}, defaultExpectedRes);
1430
+ });
1431
+
1432
+ it('should generate event error payload correctly if rawError has error.body.errorCode', () => {
1433
+ checkCodeError({error: {body: {errorCode: 2409005}}}, defaultExpectedRes);
1434
+ });
1435
+
1436
+ const checkLocusError = (payload: any, isExpectedToBeCalled: boolean) => {
1437
+ const res = cd.generateClientEventErrorPayload(payload);
1438
+ const expectedResult = {
1439
+ category: 'signaling',
1440
+ errorDescription: 'NewLocusError',
1441
+ fatal: true,
1442
+ name: 'other',
1443
+ shownToUser: false,
1444
+ serviceErrorCode: 2400000,
1445
+ errorCode: 4008,
1446
+ };
1447
+
1448
+ if (isExpectedToBeCalled) {
1449
+ assert.deepEqual(res, expectedResult);
1450
+ } else {
1451
+ assert.notDeepEqual(res, expectedResult);
1452
+ }
1453
+ };
1454
+
1455
+ it('should return default new locus event error payload correctly if locus error is recognized', () => {
1456
+ checkLocusError({body: {errorCode: 2400000}}, true);
1457
+ });
1458
+
1459
+ it('should not return default new locus event error payload correctly if locus is not recognized', () => {
1460
+ checkLocusError({body: {errorCode: 1400000}}, false);
1461
+ });
1462
+
1463
+ const checkMeetingInfoError = (payload: any, isExpectedToBeCalled: boolean) => {
1464
+ const res = cd.generateClientEventErrorPayload(payload);
1465
+ const expectedResult = {
1466
+ category: 'signaling',
1467
+ errorDescription: 'MeetingInfoLookupError',
1468
+ fatal: true,
1469
+ name: 'other',
1470
+ shownToUser: false,
1471
+ serviceErrorCode: undefined,
1472
+ errorCode: 4100,
1473
+ };
1474
+
1475
+ if (isExpectedToBeCalled) {
1476
+ assert.deepEqual(res, expectedResult);
1477
+ } else {
1478
+ assert.notDeepEqual(res, expectedResult);
1479
+ }
1480
+ };
1481
+
1482
+ it('should return default meeting info lookup error payload if data.meetingInfo was found on error body', () => {
1483
+ checkMeetingInfoError({body: {data: {meetingInfo: 'something'}}}, true);
1484
+ });
1485
+
1486
+ it('should return default meeting info lookup error payload if body.url contains wbxappapi', () => {
1487
+ checkMeetingInfoError({body: {url: '1234567-wbxappapiabcdefg'}}, true);
1488
+ });
1489
+
1490
+ it('should not return default meeting info lookup error payload if body.url does not contain wbxappapi and data.meetingInfo was not found on error body', () => {
1491
+ checkMeetingInfoError({body: {data: '1234567-wbxappapiabcdefg'}}, false);
1492
+ });
1493
+
1494
+ it('should return NetworkError code for a NetworkOrCORSERror', () => {
1495
+ const res = cd.generateClientEventErrorPayload(
1496
+ new WebexHttpError.NetworkOrCORSError({
1497
+ url: 'https://example.com',
1498
+ statusCode: 0,
1499
+ body: {},
1500
+ options: {headers: {}, url: 'https://example.com'},
1501
+ })
1502
+ );
1503
+ assert.deepEqual(res, {
1504
+ category: 'network',
1505
+ errorDescription: '{}\nundefined https://example.com\nWEBEX_TRACKING_ID: undefined\n',
1506
+ fatal: true,
1507
+ name: 'other',
1508
+ shownToUser: false,
1509
+ serviceErrorCode: undefined,
1510
+ errorCode: 1026,
1511
+ });
1512
+ });
1513
+
1514
+ it('should return AuthenticationFailed code for an Unauthorized error', () => {
1515
+ const res = cd.generateClientEventErrorPayload(
1516
+ new WebexHttpError.Unauthorized({
1517
+ url: 'https://example.com',
1518
+ statusCode: 0,
1519
+ body: {},
1520
+ options: {headers: {}, url: 'https://example.com'},
1521
+ })
1522
+ );
1523
+ assert.deepEqual(res, {
1524
+ category: 'network',
1525
+ errorDescription: '{}\nundefined https://example.com\nWEBEX_TRACKING_ID: undefined\n',
1526
+ fatal: true,
1527
+ name: 'other',
1528
+ shownToUser: false,
1529
+ serviceErrorCode: undefined,
1530
+ errorCode: 1010,
1531
+ });
1532
+ });
1533
+
1534
+ it('should return unknown error otherwise', () => {
1535
+ const res = cd.generateClientEventErrorPayload({somethgin: 'new'});
1536
+ assert.deepEqual(res, {
1537
+ category: 'other',
1538
+ errorDescription: 'UnknownError',
1539
+ fatal: true,
1540
+ name: 'other',
1541
+ shownToUser: false,
1542
+ serviceErrorCode: 9999,
1543
+ errorCode: 9999,
1544
+ });
1545
+ });
1546
+
1547
+ it('should generate event error payload correctly for locus error 2423012', () => {
1548
+ const res = cd.generateClientEventErrorPayload({body: {errorCode: 2423012}});
1549
+ assert.deepEqual(res, {
1550
+ category: 'expected',
1551
+ errorDescription: 'FraudDetection',
1552
+ fatal: true,
1553
+ name: 'locus.response',
1554
+ shownToUser: true,
1555
+ serviceErrorCode: 2423012,
1556
+ errorCode: 12000,
1557
+ });
1558
+ });
1559
+ it('should generate event error payload correctly for locus error 2409062', () => {
1560
+ const res = cd.generateClientEventErrorPayload({body: {errorCode: 2409062}});
1561
+ assert.deepEqual(res, {
1562
+ category: 'expected',
1563
+ errorDescription: 'E2EENotSupported',
1564
+ fatal: true,
1565
+ name: 'locus.response',
1566
+ shownToUser: true,
1567
+ serviceErrorCode: 2409062,
1568
+ errorCode: 12002,
1569
+ });
1570
+ });
1571
+
1572
+
1573
+ it('should generate event error payload correctly for locus error 2423021', () => {
1574
+ const res = cd.generateClientEventErrorPayload({body: {errorCode: 2423021}});
1575
+ assert.deepEqual(res, {
1576
+ category: 'expected',
1577
+ errorDescription: 'LocusLobbyFullCMR',
1578
+ fatal: true,
1579
+ name: 'locus.response',
1580
+ shownToUser: true,
1581
+ serviceErrorCode: 2423021,
1582
+ errorCode: 12001,
1583
+ });
1584
+ });
1585
+ });
1586
+
1587
+ describe('#getCurLoginType', () => {
1588
+ it('returns login-ci if not unverified guest', () => {
1589
+ webex.credentials.isUnverifiedGuest = false;
1590
+ assert.deepEqual(cd.getCurLoginType(), 'login-ci');
1591
+ });
1592
+ it('returns unverified guest', () => {
1593
+ webex.credentials.isUnverifiedGuest = true;
1594
+ assert.deepEqual(cd.getCurLoginType(), 'unverified-guest');
1595
+ });
1596
+ });
1597
+
1598
+ describe('#getIsConvergedArchitectureEnabled', () => {
1599
+ it('returns true if converged architecture is enabled', () => {
1600
+ fakeMeeting.meetingInfo = {enableConvergedArchitecture: true};
1601
+ assert.deepEqual(cd.getIsConvergedArchitectureEnabled({meetingId: fakeMeeting.id}), true);
1602
+ });
1603
+ it('returns false if converged architecture is not enabled', () => {
1604
+ fakeMeeting.meetingInfo = {enableConvergedArchitecture: false};
1605
+ assert.deepEqual(cd.getIsConvergedArchitectureEnabled({meetingId: fakeMeeting.id}), false);
1606
+ });
1607
+ it('returns undefined if converged architecture is not defined', () => {
1608
+ fakeMeeting.meetingInfo = {};
1609
+ assert.deepEqual(
1610
+ cd.getIsConvergedArchitectureEnabled({meetingId: fakeMeeting.id}),
1611
+ undefined
1612
+ );
1613
+ });
1614
+ });
1615
+
1616
+ describe('#buildClientEventFetchRequestOptions', () => {
1617
+ [undefined, 'myPreLoginId'].forEach((preLoginId) => {
1618
+ it('returns expected options without preLoginId', async () => {
1619
+ const options = {
1620
+ meetingId: fakeMeeting.id,
1621
+ preLoginId
1622
+ };
1623
+
1624
+ const triggered = new Date();
1625
+ const fetchOptions = await cd.buildClientEventFetchRequestOptions({
1626
+ name: 'client.exit.app',
1627
+ payload: { trigger: 'user-interaction', canProceed: false },
1628
+ options,
1629
+ });
1630
+
1631
+ assert.deepEqual(fetchOptions.body, {
1632
+ metrics: [
1633
+ {
1634
+ eventPayload: {
1635
+ event: {
1636
+ canProceed: false,
1637
+ eventData: {
1638
+ webClientDomain: 'whatever',
1639
+ },
1640
+ identifiers: {
1641
+ correlationId: 'correlationId',
1642
+ deviceId: 'deviceUrl',
1643
+ locusId: 'url',
1644
+ locusStartTime: 'lastActive',
1645
+ locusUrl: 'locus/url',
1646
+ orgId: 'orgId',
1647
+ userId: 'userId',
1648
+ },
1649
+ loginType: 'login-ci',
1650
+ name: 'client.exit.app',
1651
+ trigger: 'user-interaction',
1652
+ userType: 'host',
1653
+ isConvergedArchitectureEnabled: undefined,
1654
+ },
1655
+ eventId: 'my-fake-id',
1656
+ origin: {
1657
+ buildType: 'test',
1658
+ clientInfo: {
1659
+ clientType: 'TEAMS_CLIENT',
1660
+ clientVersion: 'webex-js-sdk/webex-version',
1661
+ localNetworkPrefix:
1662
+ Utils.anonymizeIPAddress(webex.meetings.geoHintInfo?.clientAddress) ||
1663
+ undefined,
1664
+ os: getOSNameInternal() || 'unknown',
1665
+ osVersion: getOSVersion(),
1666
+ subClientType: 'WEB_APP',
1667
+ },
1668
+ environment: 'meeting_evn',
1669
+ name: 'endpoint',
1670
+ networkType: 'unknown',
1671
+ userAgent,
1672
+ },
1673
+ originTime: {
1674
+ sent: 'not_defined_yet',
1675
+ triggered: triggered.toISOString(),
1676
+ },
1677
+ senderCountryCode: webex.meetings.geoHintInfo?.countryCode,
1678
+ version: 1,
1679
+ },
1680
+ type: ['diagnostic-event'],
1681
+ },
1682
+ ],
1683
+ });
1684
+
1685
+ const rest = omit(fetchOptions, 'body');
1686
+
1687
+ if (preLoginId) {
1688
+ assert.deepEqual(rest, {
1689
+ foo: 'bar',
1690
+ method: 'POST',
1691
+ resource: 'clientmetrics-prelogin',
1692
+ service: 'metrics',
1693
+ headers: {
1694
+ authorization: false,
1695
+ 'x-prelogin-userid': preLoginId,
1696
+ }
1697
+ })
1698
+ } else {
1699
+ assert.deepEqual(rest, {
1700
+ foo: 'bar',
1701
+ method: 'POST',
1702
+ resource: 'clientmetrics',
1703
+ service: 'metrics',
1704
+ headers: {}
1705
+ })
1706
+ }
1707
+
1708
+ const webexLoggerLogCalls = webex.logger.log.getCalls();
1709
+
1710
+ assert.deepEqual(webexLoggerLogCalls[0].args, [
1711
+ 'call-diagnostic-events -> ',
1712
+ 'CallDiagnosticMetrics: @buildClientEventFetchRequestOptions. Building request options object for fetch()...',
1713
+ `name: client.exit.app`,
1714
+ `payload: {"trigger":"user-interaction","canProceed":false}`,
1715
+ `options: ${JSON.stringify(options)}`,
1716
+ ]);
1717
+
1718
+ assert.deepEqual(webexLoggerLogCalls[1].args, [
1719
+ 'call-diagnostic-events -> ',
1720
+ 'CallDiagnosticMetrics: @createClientEventObjectInMeeting. Creating in meeting event object.',
1721
+ `name: client.exit.app`
1722
+ ]);
1723
+ });
1724
+ });
1725
+ });
1726
+
1727
+ describe('#submitToCallDiagnosticsPreLogin', async () => {
1728
+ it('should call webex.request with expected options', async () => {
1729
+ sinon.spy(Utils, 'prepareDiagnosticMetricItem');
1730
+ await cd.submitToCallDiagnosticsPreLogin(
1731
+ {
1732
+ //@ts-ignore
1733
+ event: {name: 'client.alert.displayed', canProceed: true},
1734
+ //@ts-ignore
1735
+ originTime: {triggered: 'now'},
1736
+ },
1737
+ 'my-id'
1738
+ );
1739
+
1740
+ assert.calledWith(Utils.prepareDiagnosticMetricItem, webex, {
1741
+ eventPayload: {
1742
+ event: {name: 'client.alert.displayed', canProceed: true},
1743
+ originTime: {triggered: 'now', sent: now.toISOString()},
1744
+ origin: {buildType: 'test', networkType: 'unknown'},
1745
+ },
1746
+ type: ['diagnostic-event'],
1747
+ });
1748
+
1749
+ assert.calledWith(
1750
+ webex.internal.newMetrics.postPreLoginMetric,
1751
+ {
1752
+ eventPayload: {
1753
+ event: {
1754
+ name: 'client.alert.displayed',
1755
+ canProceed: true,
1756
+ },
1757
+ originTime: {
1758
+ sent: now.toISOString(),
1759
+ triggered: 'now',
1760
+ },
1761
+ origin: {
1762
+ buildType: 'test',
1763
+ networkType: 'unknown',
1764
+ },
1765
+ },
1766
+ type: ['diagnostic-event'],
1767
+ },
1768
+ 'my-id'
1769
+ );
1770
+ });
1771
+ });
1772
+
1773
+ describe('#isServiceErrorExpected', () => {
1774
+ it('returns true for code mapped to "expected"', () => {
1775
+ assert.isTrue(cd.isServiceErrorExpected(2423012));
1776
+ });
1777
+
1778
+ it('returns false for code mapped to "signaling"', () => {
1779
+ assert.isFalse(cd.isServiceErrorExpected(400001));
1780
+ });
1781
+
1782
+ it('returns false for unmapped code', () => {
1783
+ assert.isFalse(cd.isServiceErrorExpected(999999));
1784
+ });
1785
+ });
1786
+ });
1787
+ });