@webex/internal-plugin-metrics 3.12.0-webex-services-ready.4 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.repo-context.json +466 -0
- package/.sdd/manifest.json +626 -0
- package/AGENTS.md +208 -0
- package/README.md +274 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js +155 -94
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/config.js +3 -1
- package/dist/call-diagnostic/config.js.map +1 -1
- package/dist/config.js +7 -0
- package/dist/config.js.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics.js +118 -5
- package/dist/metrics.js.map +1 -1
- package/dist/metrics.types.js.map +1 -1
- package/dist/network-telemetry.js +610 -0
- package/dist/network-telemetry.js.map +1 -0
- package/dist/new-metrics.js +47 -11
- package/dist/new-metrics.js.map +1 -1
- package/dist/privacy-and-security-permission-enricher/constants.js +18 -0
- package/dist/privacy-and-security-permission-enricher/constants.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/index.js +143 -0
- package/dist/privacy-and-security-permission-enricher/index.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/types.js +7 -0
- package/dist/privacy-and-security-permission-enricher/types.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/utils.js +71 -0
- package/dist/privacy-and-security-permission-enricher/utils.js.map +1 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +12 -3
- package/dist/types/call-diagnostic/config.d.ts +2 -0
- package/dist/types/config.d.ts +8 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/metrics.types.d.ts +7 -3
- package/dist/types/network-telemetry.d.ts +108 -0
- package/dist/types/new-metrics.d.ts +13 -1
- package/dist/types/privacy-and-security-permission-enricher/constants.d.ts +6 -0
- package/dist/types/privacy-and-security-permission-enricher/index.d.ts +40 -0
- package/dist/types/privacy-and-security-permission-enricher/types.d.ts +14 -0
- package/dist/types/privacy-and-security-permission-enricher/utils.d.ts +5 -0
- package/dist/types/unhandled-exception-telemetry/index.d.ts +60 -0
- package/dist/types/unhandled-exception-telemetry/utils.d.ts +6 -0
- package/dist/unhandled-exception-telemetry/index.js +331 -0
- package/dist/unhandled-exception-telemetry/index.js.map +1 -0
- package/dist/unhandled-exception-telemetry/utils.js +105 -0
- package/dist/unhandled-exception-telemetry/utils.js.map +1 -0
- package/docs/adr/index.md +27 -0
- package/docs/architecture.md +437 -0
- package/docs/getting-started.md +131 -0
- package/docs/index.md +52 -0
- package/docs/specs/README.md +88 -0
- package/package.json +11 -11
- package/schemas/repo-context.schema.json +796 -0
- package/src/call-diagnostic/call-diagnostic-metrics.ts +100 -30
- package/src/call-diagnostic/config.ts +2 -0
- package/src/call-diagnostic/docs/README.md +535 -0
- package/src/config.js +7 -0
- package/src/docs/README.md +703 -0
- package/src/index.ts +11 -0
- package/src/metrics.js +123 -5
- package/src/metrics.types.ts +13 -3
- package/src/network-telemetry.ts +757 -0
- package/src/new-metrics.ts +44 -2
- package/src/privacy-and-security-permission-enricher/constants.ts +33 -0
- package/src/privacy-and-security-permission-enricher/docs/README.md +356 -0
- package/src/privacy-and-security-permission-enricher/index.ts +142 -0
- package/src/privacy-and-security-permission-enricher/types.ts +21 -0
- package/src/privacy-and-security-permission-enricher/utils.ts +82 -0
- package/src/rtcMetrics/docs/README.md +447 -0
- package/src/unhandled-exception-telemetry/docs/README.md +536 -0
- package/src/unhandled-exception-telemetry/index.ts +404 -0
- package/src/unhandled-exception-telemetry/utils.ts +101 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +485 -21
- package/test/unit/spec/metrics.js +14 -5
- package/test/unit/spec/network-telemetry.ts +610 -0
- package/test/unit/spec/new-metrics.ts +190 -48
- package/test/unit/spec/privacy-and-security-permission-enricher.ts +318 -0
- package/test/unit/spec/unhandled-exception-telemetry/utils.ts +109 -0
- package/test/unit/spec/unhandled-exception-telemetry.ts +689 -0
|
@@ -81,12 +81,20 @@ describe('internal-plugin-metrics', () => {
|
|
|
81
81
|
emailInput: 'test@test.com',
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
+
const fakeMeeting6 = {
|
|
85
|
+
...fakeMeeting,
|
|
86
|
+
id: '6',
|
|
87
|
+
correlationId: 'correlationId6',
|
|
88
|
+
callStateForMetrics: {meetingJoinPhase: 'in-meeting'},
|
|
89
|
+
};
|
|
90
|
+
|
|
84
91
|
const fakeMeetings = {
|
|
85
92
|
1: fakeMeeting,
|
|
86
93
|
2: fakeMeeting2,
|
|
87
94
|
3: fakeMeeting3,
|
|
88
95
|
4: fakeMeeting4,
|
|
89
96
|
5: fakeMeeting5,
|
|
97
|
+
6: fakeMeeting6,
|
|
90
98
|
};
|
|
91
99
|
|
|
92
100
|
let webex;
|
|
@@ -364,6 +372,23 @@ describe('internal-plugin-metrics', () => {
|
|
|
364
372
|
});
|
|
365
373
|
});
|
|
366
374
|
|
|
375
|
+
it('should build origin correctly when the meetings plugin is not available (before webex is ready)', () => {
|
|
376
|
+
// meetings plugin, geoHintInfo and meetingCollection are all absent before webex.ready
|
|
377
|
+
webex.meetings = undefined;
|
|
378
|
+
|
|
379
|
+
//@ts-ignore
|
|
380
|
+
const res = cd.getOrigin(
|
|
381
|
+
{subClientType: 'WEB_APP', clientType: 'TEAMS_CLIENT'},
|
|
382
|
+
fakeMeeting.id
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
assert.equal(res.clientInfo.clientType, 'TEAMS_CLIENT');
|
|
386
|
+
assert.equal(res.clientInfo.subClientType, 'WEB_APP');
|
|
387
|
+
assert.isUndefined(res.clientInfo.publicNetworkPrefix);
|
|
388
|
+
assert.isUndefined(res.clientInfo.localNetworkPrefix);
|
|
389
|
+
assert.equal(res.name, 'endpoint');
|
|
390
|
+
});
|
|
391
|
+
|
|
367
392
|
it('builds origin correctly, when overriding clientVersion', () => {
|
|
368
393
|
webex.meetings.config.metrics.clientVersion = '43.9.0.1234';
|
|
369
394
|
|
|
@@ -394,6 +419,64 @@ describe('internal-plugin-metrics', () => {
|
|
|
394
419
|
});
|
|
395
420
|
});
|
|
396
421
|
|
|
422
|
+
it('builds origin correctly with browser details provided by the host client', () => {
|
|
423
|
+
// host resolves wrapper browsers (WebOS, Electron) to the engine that determines capability
|
|
424
|
+
webex.meetings.config.metrics.browser = 'WebOS Browser';
|
|
425
|
+
webex.meetings.config.metrics.browserVersion = '108.0.0.0';
|
|
426
|
+
|
|
427
|
+
//@ts-ignore
|
|
428
|
+
const res = cd.getOrigin(
|
|
429
|
+
{subClientType: 'WEB_APP', clientType: 'TEAMS_CLIENT'},
|
|
430
|
+
fakeMeeting.id
|
|
431
|
+
);
|
|
432
|
+
|
|
433
|
+
assert.equal(res.clientInfo.browser, 'WebOS Browser');
|
|
434
|
+
assert.equal(res.clientInfo.browserVersion, '108.0.0.0');
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it('falls back to SDK browser detection when the host provides nothing', () => {
|
|
438
|
+
//@ts-ignore
|
|
439
|
+
const res = cd.getOrigin(
|
|
440
|
+
{subClientType: 'WEB_APP', clientType: 'TEAMS_CLIENT'},
|
|
441
|
+
fakeMeeting.id
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
assert.equal(res.clientInfo.browser, getBrowserName());
|
|
445
|
+
assert.equal(res.clientInfo.browserVersion, getBrowserVersion());
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
it('builds origin correctly with the browser support flags from config', () => {
|
|
449
|
+
// `false` is the meaningful "unsupported family" signal, so it must survive a truthy check
|
|
450
|
+
webex.meetings.config.metrics.isSupportedBrowserFamily = false;
|
|
451
|
+
webex.meetings.config.metrics.isOutdatedBrowserVersion = true;
|
|
452
|
+
|
|
453
|
+
//@ts-ignore
|
|
454
|
+
const res = cd.getOrigin(
|
|
455
|
+
{subClientType: 'WEB_APP', clientType: 'TEAMS_CLIENT'},
|
|
456
|
+
fakeMeeting.id
|
|
457
|
+
);
|
|
458
|
+
|
|
459
|
+
assert.deepEqual(res, {
|
|
460
|
+
clientInfo: {
|
|
461
|
+
browser: getBrowserName(),
|
|
462
|
+
browserVersion: getBrowserVersion(),
|
|
463
|
+
clientType: 'TEAMS_CLIENT',
|
|
464
|
+
clientVersion: 'webex-js-sdk/webex-version',
|
|
465
|
+
publicNetworkPrefix: '1.3.4.0',
|
|
466
|
+
localNetworkPrefix: '192.168.1.80',
|
|
467
|
+
os: getOSNameInternal(),
|
|
468
|
+
osVersion: getOSVersion() || 'unknown',
|
|
469
|
+
subClientType: 'WEB_APP',
|
|
470
|
+
isSupportedBrowserFamily: false,
|
|
471
|
+
isOutdatedBrowserVersion: true,
|
|
472
|
+
},
|
|
473
|
+
environment: 'meeting_evn',
|
|
474
|
+
name: 'endpoint',
|
|
475
|
+
networkType: 'unknown',
|
|
476
|
+
userAgent,
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
|
|
397
480
|
it('should build origin correctly with no meeting or stats analyzer', () => {
|
|
398
481
|
//@ts-ignore
|
|
399
482
|
const res = cd.getOrigin();
|
|
@@ -640,6 +723,63 @@ describe('internal-plugin-metrics', () => {
|
|
|
640
723
|
});
|
|
641
724
|
});
|
|
642
725
|
|
|
726
|
+
it('should build identifiers correctly with a meeting that has meetingInfo with locusClusterUrl', () => {
|
|
727
|
+
const res = cd.getIdentifiers({
|
|
728
|
+
mediaConnections: [
|
|
729
|
+
{mediaAgentAlias: 'mediaAgentAlias', mediaAgentGroupId: 'mediaAgentGroupId'},
|
|
730
|
+
],
|
|
731
|
+
meeting: {
|
|
732
|
+
...fakeMeeting,
|
|
733
|
+
meetingInfo: {
|
|
734
|
+
...fakeMeeting.meetingInfo,
|
|
735
|
+
locusClusterUrl: 'locus-k.wbx2.com',
|
|
736
|
+
},
|
|
737
|
+
},
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
assert.deepEqual(res, {
|
|
741
|
+
correlationId: 'correlationId',
|
|
742
|
+
deviceId: 'deviceUrl',
|
|
743
|
+
locusCluster: 'locus-k.wbx2.com',
|
|
744
|
+
locusId: 'url',
|
|
745
|
+
locusSessionId: 'locusSessionId',
|
|
746
|
+
locusStartTime: 'lastActive',
|
|
747
|
+
locusUrl: 'locus/url',
|
|
748
|
+
mediaAgentAlias: 'mediaAgentAlias',
|
|
749
|
+
mediaAgentGroupId: 'mediaAgentGroupId',
|
|
750
|
+
orgId: 'orgId',
|
|
751
|
+
userId: 'userId',
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
it('should build identifiers correctly given locusCluster', () => {
|
|
756
|
+
const res = cd.getIdentifiers({
|
|
757
|
+
correlationId: 'correlationId',
|
|
758
|
+
locusCluster: 'locus-k.wbx2.com',
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
assert.deepEqual(res, {
|
|
762
|
+
correlationId: 'correlationId',
|
|
763
|
+
deviceId: 'deviceUrl',
|
|
764
|
+
locusCluster: 'locus-k.wbx2.com',
|
|
765
|
+
locusUrl: 'locus-url',
|
|
766
|
+
orgId: 'orgId',
|
|
767
|
+
userId: 'userId',
|
|
768
|
+
});
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
it('should prefer meetingInfo locusClusterUrl over the locusCluster option', () => {
|
|
772
|
+
const res = cd.getIdentifiers({
|
|
773
|
+
meeting: {
|
|
774
|
+
...fakeMeeting,
|
|
775
|
+
meetingInfo: {...fakeMeeting.meetingInfo, locusClusterUrl: 'locus-k.wbx2.com'},
|
|
776
|
+
},
|
|
777
|
+
locusCluster: 'locus-a.wbx2.com',
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
assert.equal(res.locusCluster, 'locus-k.wbx2.com');
|
|
781
|
+
});
|
|
782
|
+
|
|
643
783
|
it('should build identifiers correctly with a meeting that has sessionCorrelationId', () => {
|
|
644
784
|
const res = cd.getIdentifiers({
|
|
645
785
|
mediaConnections: [
|
|
@@ -766,6 +906,60 @@ describe('internal-plugin-metrics', () => {
|
|
|
766
906
|
userId: 'preLoginId',
|
|
767
907
|
});
|
|
768
908
|
});
|
|
909
|
+
|
|
910
|
+
it('should use the userId from credentials when no device userId is available', () => {
|
|
911
|
+
cd.device.userId = undefined;
|
|
912
|
+
webex.credentials.getUserId = sinon.stub().returns('credentials-user-id');
|
|
913
|
+
|
|
914
|
+
const res = cd.getIdentifiers({
|
|
915
|
+
correlationId: 'correlationId',
|
|
916
|
+
});
|
|
917
|
+
|
|
918
|
+
assert.deepEqual(res, {
|
|
919
|
+
correlationId: 'correlationId',
|
|
920
|
+
locusUrl: 'locus-url',
|
|
921
|
+
deviceId: 'deviceUrl',
|
|
922
|
+
orgId: 'orgId',
|
|
923
|
+
userId: 'credentials-user-id',
|
|
924
|
+
});
|
|
925
|
+
});
|
|
926
|
+
|
|
927
|
+
it('should prefer the device userId over the credentials userId', () => {
|
|
928
|
+
webex.credentials.getUserId = sinon.stub().returns('credentials-user-id');
|
|
929
|
+
|
|
930
|
+
const res = cd.getIdentifiers({
|
|
931
|
+
correlationId: 'correlationId',
|
|
932
|
+
});
|
|
933
|
+
|
|
934
|
+
assert.equal(res.userId, 'userId');
|
|
935
|
+
assert.notCalled(webex.credentials.getUserId);
|
|
936
|
+
});
|
|
937
|
+
|
|
938
|
+
it('should fall back to preLoginId when neither the device nor credentials provide a userId', () => {
|
|
939
|
+
cd.device.userId = undefined;
|
|
940
|
+
webex.credentials.getUserId = sinon.stub().throws(new Error('no user token available'));
|
|
941
|
+
|
|
942
|
+
const res = cd.getIdentifiers({
|
|
943
|
+
correlationId: 'correlationId',
|
|
944
|
+
preLoginId: 'preLoginId',
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
assert.equal(res.userId, 'preLoginId');
|
|
948
|
+
});
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
describe('#getUserIdFromCredentials', () => {
|
|
952
|
+
it('should return the userId from credentials', () => {
|
|
953
|
+
webex.credentials.getUserId = sinon.stub().returns('credentials-user-id');
|
|
954
|
+
|
|
955
|
+
assert.equal(cd.getUserIdFromCredentials(), 'credentials-user-id');
|
|
956
|
+
});
|
|
957
|
+
|
|
958
|
+
it('should return undefined when credentials cannot provide a userId', () => {
|
|
959
|
+
webex.credentials.getUserId = sinon.stub().throws(new Error('no user token available'));
|
|
960
|
+
|
|
961
|
+
assert.isUndefined(cd.getUserIdFromCredentials());
|
|
962
|
+
});
|
|
769
963
|
});
|
|
770
964
|
|
|
771
965
|
it('should prepare diagnostic event successfully', () => {
|
|
@@ -984,6 +1178,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
984
1178
|
webexConferenceIdStr: undefined,
|
|
985
1179
|
sessionCorrelationId: undefined,
|
|
986
1180
|
globalMeetingId: undefined,
|
|
1181
|
+
locusCluster: undefined,
|
|
987
1182
|
});
|
|
988
1183
|
assert.notCalled(generateClientEventErrorPayloadSpy);
|
|
989
1184
|
assert.calledWith(
|
|
@@ -1138,6 +1333,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1138
1333
|
webexConferenceIdStr: undefined,
|
|
1139
1334
|
sessionCorrelationId: undefined,
|
|
1140
1335
|
globalMeetingId: undefined,
|
|
1336
|
+
locusCluster: undefined,
|
|
1141
1337
|
});
|
|
1142
1338
|
assert.notCalled(generateClientEventErrorPayloadSpy);
|
|
1143
1339
|
assert.calledWith(
|
|
@@ -1292,6 +1488,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1292
1488
|
webexConferenceIdStr: undefined,
|
|
1293
1489
|
globalMeetingId: undefined,
|
|
1294
1490
|
sessionCorrelationId: undefined,
|
|
1491
|
+
locusCluster: undefined,
|
|
1295
1492
|
});
|
|
1296
1493
|
assert.notCalled(generateClientEventErrorPayloadSpy);
|
|
1297
1494
|
assert.calledWith(
|
|
@@ -1448,6 +1645,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1448
1645
|
webexConferenceIdStr: undefined,
|
|
1449
1646
|
globalMeetingId: undefined,
|
|
1450
1647
|
sessionCorrelationId: undefined,
|
|
1648
|
+
locusCluster: undefined,
|
|
1451
1649
|
});
|
|
1452
1650
|
assert.notCalled(generateClientEventErrorPayloadSpy);
|
|
1453
1651
|
assert.calledWith(
|
|
@@ -1604,6 +1802,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1604
1802
|
webexConferenceIdStr: undefined,
|
|
1605
1803
|
globalMeetingId: undefined,
|
|
1606
1804
|
sessionCorrelationId: undefined,
|
|
1805
|
+
locusCluster: undefined,
|
|
1607
1806
|
});
|
|
1608
1807
|
assert.notCalled(generateClientEventErrorPayloadSpy);
|
|
1609
1808
|
assert.calledWith(
|
|
@@ -1822,6 +2021,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1822
2021
|
globalMeetingId: 'globalMeetingId1',
|
|
1823
2022
|
sessionCorrelationId: 'sessionCorrelationId1',
|
|
1824
2023
|
preLoginId: undefined,
|
|
2024
|
+
locusCluster: undefined,
|
|
1825
2025
|
});
|
|
1826
2026
|
|
|
1827
2027
|
assert.notCalled(generateClientEventErrorPayloadSpy);
|
|
@@ -1849,6 +2049,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1849
2049
|
webClientPreload: undefined,
|
|
1850
2050
|
isAutomatedUser: false,
|
|
1851
2051
|
userActivation: undefined,
|
|
2052
|
+
meetingJoinPhase: 'pre-join',
|
|
1852
2053
|
},
|
|
1853
2054
|
options
|
|
1854
2055
|
);
|
|
@@ -1875,6 +2076,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1875
2076
|
webClientPreload: undefined,
|
|
1876
2077
|
isAutomatedUser: false,
|
|
1877
2078
|
userActivation: undefined,
|
|
2079
|
+
meetingJoinPhase: 'pre-join',
|
|
1878
2080
|
},
|
|
1879
2081
|
eventId: 'my-fake-id',
|
|
1880
2082
|
origin: {
|
|
@@ -1926,6 +2128,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1926
2128
|
globalMeetingId: 'globalMeetingId1',
|
|
1927
2129
|
preLoginId: 'myPreLoginId',
|
|
1928
2130
|
sessionCorrelationId: 'sessionCorrelationId1',
|
|
2131
|
+
locusCluster: undefined,
|
|
1929
2132
|
});
|
|
1930
2133
|
|
|
1931
2134
|
assert.notCalled(generateClientEventErrorPayloadSpy);
|
|
@@ -1953,6 +2156,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1953
2156
|
webClientPreload: undefined,
|
|
1954
2157
|
isAutomatedUser: false,
|
|
1955
2158
|
userActivation: undefined,
|
|
2159
|
+
meetingJoinPhase: 'pre-join',
|
|
1956
2160
|
},
|
|
1957
2161
|
options
|
|
1958
2162
|
);
|
|
@@ -1984,12 +2188,43 @@ describe('internal-plugin-metrics', () => {
|
|
|
1984
2188
|
webClientPreload: undefined,
|
|
1985
2189
|
isAutomatedUser: false,
|
|
1986
2190
|
userActivation: undefined,
|
|
2191
|
+
meetingJoinPhase: 'pre-join',
|
|
1987
2192
|
},
|
|
1988
2193
|
},
|
|
1989
2194
|
options.preLoginId
|
|
1990
2195
|
);
|
|
1991
2196
|
});
|
|
1992
2197
|
|
|
2198
|
+
it('should add locusCluster from options to a pre-meeting client event', () => {
|
|
2199
|
+
const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
|
|
2200
|
+
sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
|
|
2201
|
+
|
|
2202
|
+
cd.submitClientEvent({
|
|
2203
|
+
name: 'client.meetinginfo.response',
|
|
2204
|
+
options: {correlationId: 'correlationId', locusCluster: 'locus-k.wbx2.com'},
|
|
2205
|
+
});
|
|
2206
|
+
|
|
2207
|
+
assert.equal(
|
|
2208
|
+
prepareDiagnosticEventSpy.firstCall.args[0].identifiers.locusCluster,
|
|
2209
|
+
'locus-k.wbx2.com'
|
|
2210
|
+
);
|
|
2211
|
+
});
|
|
2212
|
+
|
|
2213
|
+
it('should add locusCluster from options to an in-meeting client event when the meeting has none', () => {
|
|
2214
|
+
const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
|
|
2215
|
+
sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
|
|
2216
|
+
|
|
2217
|
+
cd.submitClientEvent({
|
|
2218
|
+
name: 'client.interstitial-window.launched',
|
|
2219
|
+
options: {meetingId: fakeMeeting.id, locusCluster: 'locus-k.wbx2.com'},
|
|
2220
|
+
});
|
|
2221
|
+
|
|
2222
|
+
assert.equal(
|
|
2223
|
+
prepareDiagnosticEventSpy.firstCall.args[0].identifiers.locusCluster,
|
|
2224
|
+
'locus-k.wbx2.com'
|
|
2225
|
+
);
|
|
2226
|
+
});
|
|
2227
|
+
|
|
1993
2228
|
it('should submit client event successfully with emailInput and userNameInput as options', () => {
|
|
1994
2229
|
cd.device.userId = undefined;
|
|
1995
2230
|
|
|
@@ -2021,6 +2256,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
2021
2256
|
globalMeetingId: 'globalMeetingId1',
|
|
2022
2257
|
preLoginId: 'myPreLoginId',
|
|
2023
2258
|
sessionCorrelationId: 'sessionCorrelationId1',
|
|
2259
|
+
locusCluster: undefined,
|
|
2024
2260
|
});
|
|
2025
2261
|
|
|
2026
2262
|
assert.notCalled(generateClientEventErrorPayloadSpy);
|
|
@@ -2050,6 +2286,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
2050
2286
|
webClientPreload: undefined,
|
|
2051
2287
|
isAutomatedUser: false,
|
|
2052
2288
|
userActivation: undefined,
|
|
2289
|
+
meetingJoinPhase: 'pre-join',
|
|
2053
2290
|
},
|
|
2054
2291
|
options
|
|
2055
2292
|
);
|
|
@@ -2083,6 +2320,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
2083
2320
|
webClientPreload: undefined,
|
|
2084
2321
|
isAutomatedUser: false,
|
|
2085
2322
|
userActivation: undefined,
|
|
2323
|
+
meetingJoinPhase: 'pre-join',
|
|
2086
2324
|
},
|
|
2087
2325
|
},
|
|
2088
2326
|
options.preLoginId
|
|
@@ -2250,6 +2488,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
2250
2488
|
webClientPreload: true,
|
|
2251
2489
|
isAutomatedUser: false,
|
|
2252
2490
|
userActivation: undefined,
|
|
2491
|
+
meetingJoinPhase: 'pre-join',
|
|
2253
2492
|
},
|
|
2254
2493
|
options
|
|
2255
2494
|
);
|
|
@@ -2276,6 +2515,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
2276
2515
|
webClientPreload: true,
|
|
2277
2516
|
isAutomatedUser: false,
|
|
2278
2517
|
userActivation: undefined,
|
|
2518
|
+
meetingJoinPhase: 'pre-join',
|
|
2279
2519
|
},
|
|
2280
2520
|
eventId: 'my-fake-id',
|
|
2281
2521
|
origin: {
|
|
@@ -2726,6 +2966,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
2726
2966
|
webClientPreload: undefined,
|
|
2727
2967
|
isAutomatedUser: false,
|
|
2728
2968
|
userActivation: undefined,
|
|
2969
|
+
meetingJoinPhase: 'pre-join',
|
|
2729
2970
|
},
|
|
2730
2971
|
eventId: 'my-fake-id',
|
|
2731
2972
|
origin: {
|
|
@@ -2804,6 +3045,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
2804
3045
|
webClientPreload: undefined,
|
|
2805
3046
|
isAutomatedUser: false,
|
|
2806
3047
|
userActivation: undefined,
|
|
3048
|
+
meetingJoinPhase: 'pre-join',
|
|
2807
3049
|
},
|
|
2808
3050
|
eventId: 'my-fake-id',
|
|
2809
3051
|
origin: {
|
|
@@ -3655,7 +3897,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
3655
3897
|
serviceErrorCode: undefined,
|
|
3656
3898
|
errorCode: 1026,
|
|
3657
3899
|
rawErrorMessage: '{}\nundefined https://example.com\nWEBEX_TRACKING_ID: undefined\n',
|
|
3658
|
-
|
|
3900
|
+
httpCode: 0,
|
|
3659
3901
|
});
|
|
3660
3902
|
});
|
|
3661
3903
|
|
|
@@ -3772,7 +4014,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
3772
4014
|
serviceErrorCode: undefined,
|
|
3773
4015
|
errorCode: 1026,
|
|
3774
4016
|
rawErrorMessage: '{}\nundefined https://example.com\nWEBEX_TRACKING_ID: undefined\n',
|
|
3775
|
-
|
|
4017
|
+
httpCode: 0,
|
|
3776
4018
|
});
|
|
3777
4019
|
});
|
|
3778
4020
|
|
|
@@ -3794,7 +4036,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
3794
4036
|
serviceErrorCode: undefined,
|
|
3795
4037
|
errorCode: 1010,
|
|
3796
4038
|
rawErrorMessage: '{}\nundefined https://example.com\nWEBEX_TRACKING_ID: undefined\n',
|
|
3797
|
-
|
|
4039
|
+
httpCode: 0,
|
|
3798
4040
|
});
|
|
3799
4041
|
});
|
|
3800
4042
|
|
|
@@ -3820,7 +4062,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
3820
4062
|
serviceErrorCode: undefined,
|
|
3821
4063
|
errorCode: 1010,
|
|
3822
4064
|
rawErrorMessage: '{}\nundefined https://example.com\nWEBEX_TRACKING_ID: undefined\n',
|
|
3823
|
-
|
|
4065
|
+
httpCode: 0,
|
|
3824
4066
|
});
|
|
3825
4067
|
});
|
|
3826
4068
|
|
|
@@ -3925,8 +4167,144 @@ describe('internal-plugin-metrics', () => {
|
|
|
3925
4167
|
});
|
|
3926
4168
|
});
|
|
3927
4169
|
|
|
3928
|
-
describe('
|
|
3929
|
-
it('should
|
|
4170
|
+
describe('httpCode', () => {
|
|
4171
|
+
it('should identify an outgoing Locus 429', () => {
|
|
4172
|
+
const rawErrorMessage =
|
|
4173
|
+
'partition 371 on PARALLEL_EXECUTOR_PARTITION_KEY_QUEUE_FULL state';
|
|
4174
|
+
const [res] = cd.generateClientEventErrorPayload({
|
|
4175
|
+
message: rawErrorMessage,
|
|
4176
|
+
statusCode: 429,
|
|
4177
|
+
options: {uri: 'https://locus.example.com/locus/api/v1/loci/call'},
|
|
4178
|
+
});
|
|
4179
|
+
|
|
4180
|
+
assert.deepEqual(res, {
|
|
4181
|
+
category: 'signaling',
|
|
4182
|
+
errorCode: 1002,
|
|
4183
|
+
errorDescription: 'LocusRateLimitedOutgoing',
|
|
4184
|
+
fatal: true,
|
|
4185
|
+
name: 'locus.response',
|
|
4186
|
+
rawErrorMessage,
|
|
4187
|
+
serviceErrorCode: undefined,
|
|
4188
|
+
shownToUser: false,
|
|
4189
|
+
httpCode: 429,
|
|
4190
|
+
});
|
|
4191
|
+
});
|
|
4192
|
+
|
|
4193
|
+
[
|
|
4194
|
+
['media', 'https://example.com/locus/api/v1/loci/123/media'],
|
|
4195
|
+
['hashtree', 'https://example.com/locus/api/v1/loci/123/hashtree'],
|
|
4196
|
+
['host-only Locus URL', 'https://locus.example.com/api/v1/resource'],
|
|
4197
|
+
['query-only Locus URL', 'https://example.com/api/v1/resource?service=locus'],
|
|
4198
|
+
].forEach(([operation, uri]) => {
|
|
4199
|
+
it(`should identify a Locus 429 for ${operation}`, () => {
|
|
4200
|
+
const [res] = cd.generateClientEventErrorPayload({
|
|
4201
|
+
message: 'Locus rate limited',
|
|
4202
|
+
statusCode: 429,
|
|
4203
|
+
options: {uri},
|
|
4204
|
+
});
|
|
4205
|
+
|
|
4206
|
+
assert.equal(res.errorCode, 1002);
|
|
4207
|
+
assert.equal(res.errorDescription, 'LocusRateLimitedOutgoing');
|
|
4208
|
+
assert.equal(res.httpCode, 429);
|
|
4209
|
+
});
|
|
4210
|
+
});
|
|
4211
|
+
|
|
4212
|
+
it('should identify an unavailable Locus 503', () => {
|
|
4213
|
+
const rawErrorMessage = 'Service unavailable';
|
|
4214
|
+
const [res] = cd.generateClientEventErrorPayload({
|
|
4215
|
+
message: rawErrorMessage,
|
|
4216
|
+
statusCode: 503,
|
|
4217
|
+
options: {uri: 'https://locus.example.com/locus/api/v1/loci/call'},
|
|
4218
|
+
});
|
|
4219
|
+
|
|
4220
|
+
assert.deepEqual(res, {
|
|
4221
|
+
category: 'signaling',
|
|
4222
|
+
errorCode: 1003,
|
|
4223
|
+
errorDescription: 'LocusUnavailable',
|
|
4224
|
+
fatal: true,
|
|
4225
|
+
name: 'locus.response',
|
|
4226
|
+
rawErrorMessage,
|
|
4227
|
+
serviceErrorCode: undefined,
|
|
4228
|
+
shownToUser: false,
|
|
4229
|
+
httpCode: 503,
|
|
4230
|
+
});
|
|
4231
|
+
});
|
|
4232
|
+
|
|
4233
|
+
it('should prefer a specific service error mapping over the Locus HTTP status', () => {
|
|
4234
|
+
const rawErrorMessage = 'Fraud detected';
|
|
4235
|
+
const [res] = cd.generateClientEventErrorPayload({
|
|
4236
|
+
body: {errorCode: 2423012},
|
|
4237
|
+
message: rawErrorMessage,
|
|
4238
|
+
statusCode: 429,
|
|
4239
|
+
options: {uri: 'https://locus.example.com/locus/api/v1/loci/call'},
|
|
4240
|
+
});
|
|
4241
|
+
|
|
4242
|
+
assert.deepEqual(res, {
|
|
4243
|
+
category: 'expected',
|
|
4244
|
+
errorCode: 12000,
|
|
4245
|
+
errorDescription: 'FraudDetection',
|
|
4246
|
+
fatal: true,
|
|
4247
|
+
name: 'locus.response',
|
|
4248
|
+
rawErrorMessage,
|
|
4249
|
+
serviceErrorCode: 2423012,
|
|
4250
|
+
shownToUser: true,
|
|
4251
|
+
httpCode: 429,
|
|
4252
|
+
});
|
|
4253
|
+
});
|
|
4254
|
+
|
|
4255
|
+
it('should retain an unmapped service error code on the Locus HTTP status payload', () => {
|
|
4256
|
+
const rawErrorMessage = 'Locus rate limited';
|
|
4257
|
+
const [res] = cd.generateClientEventErrorPayload({
|
|
4258
|
+
body: {errorCode: 2429999},
|
|
4259
|
+
message: rawErrorMessage,
|
|
4260
|
+
statusCode: 429,
|
|
4261
|
+
options: {uri: 'https://locus.example.com/locus/api/v1/loci/call'},
|
|
4262
|
+
});
|
|
4263
|
+
|
|
4264
|
+
assert.deepEqual(res, {
|
|
4265
|
+
category: 'signaling',
|
|
4266
|
+
errorCode: 1002,
|
|
4267
|
+
errorDescription: 'LocusRateLimitedOutgoing',
|
|
4268
|
+
fatal: true,
|
|
4269
|
+
name: 'locus.response',
|
|
4270
|
+
rawErrorMessage,
|
|
4271
|
+
serviceErrorCode: 2429999,
|
|
4272
|
+
shownToUser: false,
|
|
4273
|
+
httpCode: 429,
|
|
4274
|
+
});
|
|
4275
|
+
});
|
|
4276
|
+
|
|
4277
|
+
it('should not identify a non-Locus 429 as a Locus rate limit', () => {
|
|
4278
|
+
const [res] = cd.generateClientEventErrorPayload({
|
|
4279
|
+
message: 'Too many requests',
|
|
4280
|
+
statusCode: 429,
|
|
4281
|
+
options: {uri: 'https://example.com/api/v1/resource'},
|
|
4282
|
+
});
|
|
4283
|
+
|
|
4284
|
+
assert.deepEqual(res, {
|
|
4285
|
+
category: 'other',
|
|
4286
|
+
errorCode: 9999,
|
|
4287
|
+
errorDescription: 'UnknownError',
|
|
4288
|
+
fatal: true,
|
|
4289
|
+
name: 'other',
|
|
4290
|
+
rawErrorMessage: 'Too many requests',
|
|
4291
|
+
serviceErrorCode: 9999,
|
|
4292
|
+
shownToUser: false,
|
|
4293
|
+
httpCode: 429,
|
|
4294
|
+
});
|
|
4295
|
+
});
|
|
4296
|
+
|
|
4297
|
+
it('should keep the fallback classification when a 429 has no request URL', () => {
|
|
4298
|
+
const [res] = cd.generateClientEventErrorPayload({
|
|
4299
|
+
message: 'Too many requests',
|
|
4300
|
+
statusCode: 429,
|
|
4301
|
+
});
|
|
4302
|
+
|
|
4303
|
+
assert.equal(res.errorCode, 9999);
|
|
4304
|
+
assert.equal(res.httpCode, 429);
|
|
4305
|
+
});
|
|
4306
|
+
|
|
4307
|
+
it('should include httpCode for browser media errors', () => {
|
|
3930
4308
|
const [res, cached] = cd.generateClientEventErrorPayload({
|
|
3931
4309
|
name: 'PermissionDeniedError',
|
|
3932
4310
|
message: 'bad times',
|
|
@@ -3944,11 +4322,11 @@ describe('internal-plugin-metrics', () => {
|
|
|
3944
4322
|
rawErrorMessage: 'bad times',
|
|
3945
4323
|
serviceErrorCode: undefined,
|
|
3946
4324
|
shownToUser: false,
|
|
3947
|
-
|
|
4325
|
+
httpCode: 401,
|
|
3948
4326
|
});
|
|
3949
4327
|
});
|
|
3950
4328
|
|
|
3951
|
-
it('should include
|
|
4329
|
+
it('should include httpCode for SdpOfferCreationErrors', () => {
|
|
3952
4330
|
const [res, cached] = cd.generateClientEventErrorPayload({
|
|
3953
4331
|
name: 'SdpOfferCreationError',
|
|
3954
4332
|
message: 'bad times',
|
|
@@ -3966,11 +4344,11 @@ describe('internal-plugin-metrics', () => {
|
|
|
3966
4344
|
rawErrorMessage: 'bad times',
|
|
3967
4345
|
serviceErrorCode: undefined,
|
|
3968
4346
|
shownToUser: true,
|
|
3969
|
-
|
|
4347
|
+
httpCode: 404,
|
|
3970
4348
|
});
|
|
3971
4349
|
});
|
|
3972
4350
|
|
|
3973
|
-
it('should include
|
|
4351
|
+
it('should include httpCode for service error codes', () => {
|
|
3974
4352
|
const [res, cached] = cd.generateClientEventErrorPayload({
|
|
3975
4353
|
body: {errorCode: 58400},
|
|
3976
4354
|
message: 'bad times',
|
|
@@ -3985,11 +4363,11 @@ describe('internal-plugin-metrics', () => {
|
|
|
3985
4363
|
rawErrorMessage: 'bad times',
|
|
3986
4364
|
serviceErrorCode: 58400,
|
|
3987
4365
|
shownToUser: false,
|
|
3988
|
-
|
|
4366
|
+
httpCode: 400,
|
|
3989
4367
|
});
|
|
3990
4368
|
});
|
|
3991
4369
|
|
|
3992
|
-
it('should include
|
|
4370
|
+
it('should include httpCode for locus service error codes', () => {
|
|
3993
4371
|
const [res, cached] = cd.generateClientEventErrorPayload({
|
|
3994
4372
|
body: {errorCode: 2403001},
|
|
3995
4373
|
message: 'bad times',
|
|
@@ -4004,11 +4382,11 @@ describe('internal-plugin-metrics', () => {
|
|
|
4004
4382
|
rawErrorMessage: 'bad times',
|
|
4005
4383
|
serviceErrorCode: 2403001,
|
|
4006
4384
|
shownToUser: false,
|
|
4007
|
-
|
|
4385
|
+
httpCode: 400,
|
|
4008
4386
|
});
|
|
4009
4387
|
});
|
|
4010
4388
|
|
|
4011
|
-
it('should include
|
|
4389
|
+
it('should include httpCode for meetingInfo service error codes', () => {
|
|
4012
4390
|
const [res, cached] = cd.generateClientEventErrorPayload({
|
|
4013
4391
|
body: {data: {meetingInfo: {}}},
|
|
4014
4392
|
message: 'bad times',
|
|
@@ -4023,11 +4401,11 @@ describe('internal-plugin-metrics', () => {
|
|
|
4023
4401
|
rawErrorMessage: 'bad times',
|
|
4024
4402
|
serviceErrorCode: undefined,
|
|
4025
4403
|
shownToUser: false,
|
|
4026
|
-
|
|
4404
|
+
httpCode: 400,
|
|
4027
4405
|
});
|
|
4028
4406
|
});
|
|
4029
4407
|
|
|
4030
|
-
it('should include
|
|
4408
|
+
it('should include httpCode for network errors', () => {
|
|
4031
4409
|
const error = new WebexHttpError.NetworkOrCORSError({
|
|
4032
4410
|
statusCode: 400,
|
|
4033
4411
|
options: {service: '', headers: {}},
|
|
@@ -4042,11 +4420,11 @@ describe('internal-plugin-metrics', () => {
|
|
|
4042
4420
|
rawErrorMessage: 'undefined\nundefined /undefined\nWEBEX_TRACKING_ID: undefined\n',
|
|
4043
4421
|
serviceErrorCode: undefined,
|
|
4044
4422
|
shownToUser: false,
|
|
4045
|
-
|
|
4423
|
+
httpCode: 400,
|
|
4046
4424
|
});
|
|
4047
4425
|
});
|
|
4048
4426
|
|
|
4049
|
-
it('should include
|
|
4427
|
+
it('should include httpCode for unauthorized errors', () => {
|
|
4050
4428
|
const error = new WebexHttpError.Unauthorized({
|
|
4051
4429
|
statusCode: 401,
|
|
4052
4430
|
options: {service: '', headers: {}},
|
|
@@ -4061,11 +4439,11 @@ describe('internal-plugin-metrics', () => {
|
|
|
4061
4439
|
rawErrorMessage: 'undefined\nundefined /undefined\nWEBEX_TRACKING_ID: undefined\n',
|
|
4062
4440
|
serviceErrorCode: undefined,
|
|
4063
4441
|
shownToUser: false,
|
|
4064
|
-
|
|
4442
|
+
httpCode: 401,
|
|
4065
4443
|
});
|
|
4066
4444
|
});
|
|
4067
4445
|
|
|
4068
|
-
it('should include
|
|
4446
|
+
it('should include httpCode for unknown errors', () => {
|
|
4069
4447
|
const [res, cached] = cd.generateClientEventErrorPayload({
|
|
4070
4448
|
message: 'bad times',
|
|
4071
4449
|
statusCode: 404,
|
|
@@ -4079,7 +4457,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
4079
4457
|
serviceErrorCode: 9999,
|
|
4080
4458
|
errorDescription: 'UnknownError',
|
|
4081
4459
|
rawErrorMessage: 'bad times',
|
|
4082
|
-
|
|
4460
|
+
httpCode: 404,
|
|
4083
4461
|
});
|
|
4084
4462
|
});
|
|
4085
4463
|
});
|
|
@@ -4270,6 +4648,18 @@ describe('internal-plugin-metrics', () => {
|
|
|
4270
4648
|
});
|
|
4271
4649
|
|
|
4272
4650
|
describe('#buildClientEventFetchRequestOptions', () => {
|
|
4651
|
+
it('should add the locusCluster option to a pre-meeting event', async () => {
|
|
4652
|
+
const fetchOptions = await cd.buildClientEventFetchRequestOptions({
|
|
4653
|
+
name: 'client.interstitial-window.launched',
|
|
4654
|
+
options: {correlationId: 'correlationId', locusCluster: 'locus-k.wbx2.com'},
|
|
4655
|
+
});
|
|
4656
|
+
|
|
4657
|
+
assert.equal(
|
|
4658
|
+
fetchOptions.body.metrics[0].eventPayload.event.identifiers.locusCluster,
|
|
4659
|
+
'locus-k.wbx2.com'
|
|
4660
|
+
);
|
|
4661
|
+
});
|
|
4662
|
+
|
|
4273
4663
|
[undefined, 'myPreLoginId'].forEach((preLoginId) => {
|
|
4274
4664
|
it('returns expected options without preLoginId', async () => {
|
|
4275
4665
|
const options = {
|
|
@@ -4469,6 +4859,80 @@ describe('internal-plugin-metrics', () => {
|
|
|
4469
4859
|
options.meetingJoinPhase
|
|
4470
4860
|
);
|
|
4471
4861
|
});
|
|
4862
|
+
|
|
4863
|
+
it('includes expected meetingJoinPhase from meeting callStateForMetrics when in-meeting', async () => {
|
|
4864
|
+
// meetingId means in-meeting
|
|
4865
|
+
const options = {
|
|
4866
|
+
meetingId: fakeMeeting6.id,
|
|
4867
|
+
};
|
|
4868
|
+
|
|
4869
|
+
const fetchOptions = await cd.buildClientEventFetchRequestOptions({
|
|
4870
|
+
name: 'client.exit.app',
|
|
4871
|
+
payload: {trigger: 'user-interaction', canProceed: false},
|
|
4872
|
+
options,
|
|
4873
|
+
});
|
|
4874
|
+
|
|
4875
|
+
assert.equal(fetchOptions.body.metrics[0].eventPayload.event.meetingJoinPhase, 'in-meeting');
|
|
4876
|
+
});
|
|
4877
|
+
|
|
4878
|
+
it('prioritizes meetingJoinPhase from options over meeting callStateForMetrics', async () => {
|
|
4879
|
+
// meetingId means in-meeting
|
|
4880
|
+
const options = {
|
|
4881
|
+
meetingId: fakeMeeting6.id,
|
|
4882
|
+
meetingJoinPhase: 'join',
|
|
4883
|
+
};
|
|
4884
|
+
|
|
4885
|
+
const fetchOptions = await cd.buildClientEventFetchRequestOptions({
|
|
4886
|
+
name: 'client.exit.app',
|
|
4887
|
+
payload: {trigger: 'user-interaction', canProceed: false},
|
|
4888
|
+
options,
|
|
4889
|
+
});
|
|
4890
|
+
|
|
4891
|
+
assert.equal(
|
|
4892
|
+
fetchOptions.body.metrics[0].eventPayload.event.meetingJoinPhase,
|
|
4893
|
+
options.meetingJoinPhase
|
|
4894
|
+
);
|
|
4895
|
+
});
|
|
4896
|
+
|
|
4897
|
+
it('defaults meetingJoinPhase to pre-join during prejoin when not provided in options', async () => {
|
|
4898
|
+
// correlationId and no meeting id means prejoin
|
|
4899
|
+
const options = {
|
|
4900
|
+
correlationId: 'myCorrelationId',
|
|
4901
|
+
preLoginId: 'myPreLoginId',
|
|
4902
|
+
};
|
|
4903
|
+
|
|
4904
|
+
const fetchOptions = await cd.buildClientEventFetchRequestOptions({
|
|
4905
|
+
name: 'client.exit.app',
|
|
4906
|
+
payload: {trigger: 'user-interaction', canProceed: false},
|
|
4907
|
+
options,
|
|
4908
|
+
});
|
|
4909
|
+
|
|
4910
|
+
assert.equal(fetchOptions.body.metrics[0].eventPayload.event.meetingJoinPhase, 'pre-join');
|
|
4911
|
+
});
|
|
4912
|
+
|
|
4913
|
+
it('builds request options before webex is ready (no meetings plugin or internal metrics config)', async () => {
|
|
4914
|
+
// before webex.ready the meetings plugin and internal metrics config are not available
|
|
4915
|
+
webex.meetings = undefined;
|
|
4916
|
+
webex.internal.metrics = undefined;
|
|
4917
|
+
|
|
4918
|
+
const options = {
|
|
4919
|
+
correlationId: 'myCorrelationId',
|
|
4920
|
+
clientType: 'TEAMS_CLIENT',
|
|
4921
|
+
subClientType: 'WEB_APP',
|
|
4922
|
+
};
|
|
4923
|
+
|
|
4924
|
+
const fetchOptions = await cd.buildClientEventFetchRequestOptions({
|
|
4925
|
+
name: 'client.exit.app',
|
|
4926
|
+
payload: {trigger: 'user-interaction', canProceed: false},
|
|
4927
|
+
options,
|
|
4928
|
+
});
|
|
4929
|
+
|
|
4930
|
+
const eventPayload = fetchOptions.body.metrics[0].eventPayload;
|
|
4931
|
+
assert.equal(eventPayload.event.name, 'client.exit.app');
|
|
4932
|
+
assert.isUndefined(eventPayload.senderCountryCode);
|
|
4933
|
+
assert.isUndefined(fetchOptions.waitForServiceTimeout);
|
|
4934
|
+
assert.equal(fetchOptions.resource, 'clientmetrics');
|
|
4935
|
+
});
|
|
4472
4936
|
});
|
|
4473
4937
|
|
|
4474
4938
|
describe('#submitToCallDiagnosticsPreLogin', () => {
|