@webex/internal-plugin-metrics 3.12.0-next.3 → 3.12.0-next.31

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 (39) hide show
  1. package/dist/batcher.js +3 -0
  2. package/dist/batcher.js.map +1 -1
  3. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +23 -0
  4. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -1
  5. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +68 -51
  6. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
  7. package/dist/call-diagnostic/call-diagnostic-metrics.js +80 -8
  8. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
  9. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +5 -0
  10. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
  11. package/dist/call-diagnostic/config.js +16 -3
  12. package/dist/call-diagnostic/config.js.map +1 -1
  13. package/dist/config.js +1 -0
  14. package/dist/config.js.map +1 -1
  15. package/dist/metrics.js +1 -1
  16. package/dist/metrics.types.js.map +1 -1
  17. package/dist/prelogin-metrics-batcher.js +23 -0
  18. package/dist/prelogin-metrics-batcher.js.map +1 -1
  19. package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +9 -0
  20. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +69 -13
  21. package/dist/types/call-diagnostic/config.d.ts +4 -0
  22. package/dist/types/config.d.ts +1 -0
  23. package/dist/types/metrics.types.d.ts +2 -2
  24. package/package.json +11 -11
  25. package/src/batcher.js +4 -0
  26. package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +26 -0
  27. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +140 -69
  28. package/src/call-diagnostic/call-diagnostic-metrics.ts +74 -1
  29. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +5 -0
  30. package/src/call-diagnostic/config.ts +14 -0
  31. package/src/config.js +1 -0
  32. package/src/metrics.types.ts +1 -1
  33. package/src/prelogin-metrics-batcher.ts +26 -0
  34. package/test/unit/spec/batcher.js +43 -0
  35. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +150 -2
  36. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +243 -288
  37. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +764 -159
  38. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +27 -0
  39. package/test/unit/spec/prelogin-metrics-batcher.ts +190 -36
@@ -857,6 +857,115 @@ describe('internal-plugin-metrics', () => {
857
857
  });
858
858
  });
859
859
 
860
+ describe('#prepareDiagnosticEvent isAutomatedUser field', () => {
861
+ it('should set isAutomatedUser to false when window is not defined', () => {
862
+ const options = {meetingId: fakeMeeting.id};
863
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
864
+
865
+ const res = cd.prepareDiagnosticEvent(
866
+ {
867
+ canProceed: true,
868
+ identifiers: {correlationId: 'test-id'},
869
+ name: 'client.alert.displayed',
870
+ isAutomatedUser: false,
871
+ userActivation: undefined,
872
+ },
873
+ options
874
+ );
875
+
876
+ // In the test environment, isAutomatedUser should be false since we're not in a webdriver environment
877
+ assert.isFalse(
878
+ res.event.isAutomatedUser,
879
+ 'isAutomatedUser should be false in non-webdriver test environment'
880
+ );
881
+ });
882
+
883
+ it('should include isAutomatedUser field in the returned event', () => {
884
+ const options = {meetingId: fakeMeeting.id};
885
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
886
+
887
+ const res = cd.prepareDiagnosticEvent(
888
+ {
889
+ canProceed: true,
890
+ identifiers: {correlationId: 'test-id'},
891
+ name: 'client.alert.displayed',
892
+ isAutomatedUser: false,
893
+ userActivation: undefined,
894
+ },
895
+ options
896
+ );
897
+
898
+ // Verify the isAutomatedUser field is present in the event
899
+ assert.isDefined(res.event.isAutomatedUser, 'isAutomatedUser field should be defined');
900
+ assert.isBoolean(res.event.isAutomatedUser, 'isAutomatedUser should be a boolean');
901
+ });
902
+
903
+ it('should set isAutomatedUser to true when navigator.webdriver is true', () => {
904
+ const originalDescriptor = Object.getOwnPropertyDescriptor(global, 'navigator');
905
+ Object.defineProperty(global, 'navigator', {
906
+ value: {webdriver: true},
907
+ configurable: true,
908
+ writable: true,
909
+ });
910
+
911
+ const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
912
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
913
+ cd.setMercuryConnectedStatus(true);
914
+
915
+ cd.submitClientEvent({
916
+ name: 'client.alert.displayed',
917
+ options: {correlationId: 'correlationId'},
918
+ });
919
+
920
+ assert.isTrue(
921
+ prepareDiagnosticEventSpy.firstCall.args[0].isAutomatedUser,
922
+ 'isAutomatedUser should be true when navigator.webdriver is set'
923
+ );
924
+
925
+ if (originalDescriptor) {
926
+ Object.defineProperty(global, 'navigator', originalDescriptor);
927
+ } else {
928
+ delete (global as any).navigator;
929
+ }
930
+ });
931
+ });
932
+
933
+ describe('#getUserActivation', () => {
934
+ let originalDescriptor;
935
+
936
+ beforeEach(() => {
937
+ originalDescriptor = Object.getOwnPropertyDescriptor(global, 'navigator');
938
+ });
939
+
940
+ afterEach(() => {
941
+ if (originalDescriptor) {
942
+ Object.defineProperty(global, 'navigator', originalDescriptor);
943
+ } else {
944
+ delete (global as any).navigator;
945
+ }
946
+ });
947
+
948
+ it('should return the userActivation state when navigator.userActivation is available', () => {
949
+ Object.defineProperty(global, 'navigator', {
950
+ value: {userActivation: {hasBeenActive: true, isActive: false}},
951
+ configurable: true,
952
+ writable: true,
953
+ });
954
+
955
+ assert.deepEqual(cd.getUserActivation(), {hasBeenActive: true, isActive: false});
956
+ });
957
+
958
+ it('should return undefined when navigator.userActivation is not available', () => {
959
+ Object.defineProperty(global, 'navigator', {
960
+ value: {},
961
+ configurable: true,
962
+ writable: true,
963
+ });
964
+
965
+ assert.isUndefined(cd.getUserActivation());
966
+ });
967
+ });
968
+
860
969
  describe('#submitClientEvent', () => {
861
970
  it('should submit client event successfully with meetingId', () => {
862
971
  const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
@@ -907,11 +1016,15 @@ describe('internal-plugin-metrics', () => {
907
1016
  userId: 'userId',
908
1017
  },
909
1018
  loginType: 'login-ci',
1019
+ telemetryOptOut: undefined,
910
1020
  name: 'client.alert.displayed',
911
1021
  userType: 'host',
912
1022
  isConvergedArchitectureEnabled: undefined,
913
1023
  webexSubServiceType: undefined,
914
1024
  webClientPreload: undefined,
1025
+ isVipMeeting: false,
1026
+ isAutomatedUser: false,
1027
+ userActivation: undefined,
915
1028
  },
916
1029
  options
917
1030
  );
@@ -935,11 +1048,15 @@ describe('internal-plugin-metrics', () => {
935
1048
  userId: 'userId',
936
1049
  },
937
1050
  loginType: 'login-ci',
1051
+ telemetryOptOut: undefined,
938
1052
  name: 'client.alert.displayed',
939
1053
  userType: 'host',
940
1054
  isConvergedArchitectureEnabled: undefined,
941
1055
  webexSubServiceType: undefined,
942
1056
  webClientPreload: undefined,
1057
+ isVipMeeting: false,
1058
+ isAutomatedUser: false,
1059
+ userActivation: undefined,
943
1060
  },
944
1061
  eventId: 'my-fake-id',
945
1062
  origin: {
@@ -974,11 +1091,15 @@ describe('internal-plugin-metrics', () => {
974
1091
  userId: 'userId',
975
1092
  },
976
1093
  loginType: 'login-ci',
1094
+ telemetryOptOut: undefined,
977
1095
  name: 'client.alert.displayed',
978
1096
  userType: 'host',
979
1097
  isConvergedArchitectureEnabled: undefined,
980
1098
  webexSubServiceType: undefined,
981
1099
  webClientPreload: undefined,
1100
+ isVipMeeting: false,
1101
+ isAutomatedUser: false,
1102
+ userActivation: undefined,
982
1103
  },
983
1104
  eventId: 'my-fake-id',
984
1105
  origin: {
@@ -1049,11 +1170,15 @@ describe('internal-plugin-metrics', () => {
1049
1170
  userId: 'userId',
1050
1171
  },
1051
1172
  loginType: 'login-ci',
1173
+ telemetryOptOut: undefined,
1052
1174
  name: 'client.alert.displayed',
1053
1175
  userType: 'host',
1054
1176
  isConvergedArchitectureEnabled: undefined,
1055
1177
  webexSubServiceType: undefined,
1056
1178
  webClientPreload: undefined,
1179
+ isVipMeeting: false,
1180
+ isAutomatedUser: false,
1181
+ userActivation: undefined,
1057
1182
  },
1058
1183
  options
1059
1184
  );
@@ -1077,11 +1202,15 @@ describe('internal-plugin-metrics', () => {
1077
1202
  userId: 'userId',
1078
1203
  },
1079
1204
  loginType: 'login-ci',
1205
+ telemetryOptOut: undefined,
1080
1206
  name: 'client.alert.displayed',
1081
1207
  userType: 'host',
1082
1208
  isConvergedArchitectureEnabled: undefined,
1083
1209
  webexSubServiceType: undefined,
1084
1210
  webClientPreload: undefined,
1211
+ isVipMeeting: false,
1212
+ isAutomatedUser: false,
1213
+ userActivation: undefined,
1085
1214
  },
1086
1215
  eventId: 'my-fake-id',
1087
1216
  origin: {
@@ -1116,11 +1245,15 @@ describe('internal-plugin-metrics', () => {
1116
1245
  userId: 'userId',
1117
1246
  },
1118
1247
  loginType: 'login-ci',
1248
+ telemetryOptOut: undefined,
1119
1249
  name: 'client.alert.displayed',
1120
1250
  userType: 'host',
1121
1251
  isConvergedArchitectureEnabled: undefined,
1122
1252
  webexSubServiceType: undefined,
1123
1253
  webClientPreload: undefined,
1254
+ isVipMeeting: false,
1255
+ isAutomatedUser: false,
1256
+ userActivation: undefined,
1124
1257
  },
1125
1258
  eventId: 'my-fake-id',
1126
1259
  origin: {
@@ -1192,11 +1325,15 @@ describe('internal-plugin-metrics', () => {
1192
1325
  userId: 'userId',
1193
1326
  },
1194
1327
  loginType: 'login-ci',
1328
+ telemetryOptOut: undefined,
1195
1329
  name: 'client.alert.displayed',
1196
1330
  userType: 'host',
1197
1331
  isConvergedArchitectureEnabled: undefined,
1198
1332
  webexSubServiceType: undefined,
1199
1333
  webClientPreload: undefined,
1334
+ isVipMeeting: false,
1335
+ isAutomatedUser: false,
1336
+ userActivation: undefined,
1200
1337
  },
1201
1338
  options
1202
1339
  );
@@ -1221,11 +1358,15 @@ describe('internal-plugin-metrics', () => {
1221
1358
  userId: 'userId',
1222
1359
  },
1223
1360
  loginType: 'login-ci',
1361
+ telemetryOptOut: undefined,
1224
1362
  name: 'client.alert.displayed',
1225
1363
  userType: 'host',
1226
1364
  isConvergedArchitectureEnabled: undefined,
1227
1365
  webexSubServiceType: undefined,
1228
1366
  webClientPreload: undefined,
1367
+ isVipMeeting: false,
1368
+ isAutomatedUser: false,
1369
+ userActivation: undefined,
1229
1370
  },
1230
1371
  eventId: 'my-fake-id',
1231
1372
  origin: {
@@ -1261,11 +1402,15 @@ describe('internal-plugin-metrics', () => {
1261
1402
  userId: 'userId',
1262
1403
  },
1263
1404
  loginType: 'login-ci',
1405
+ telemetryOptOut: undefined,
1264
1406
  name: 'client.alert.displayed',
1265
1407
  userType: 'host',
1266
1408
  isConvergedArchitectureEnabled: undefined,
1267
1409
  webexSubServiceType: undefined,
1268
1410
  webClientPreload: undefined,
1411
+ isVipMeeting: false,
1412
+ isAutomatedUser: false,
1413
+ userActivation: undefined,
1269
1414
  },
1270
1415
  eventId: 'my-fake-id',
1271
1416
  origin: {
@@ -1336,11 +1481,15 @@ describe('internal-plugin-metrics', () => {
1336
1481
  userId: 'userId',
1337
1482
  },
1338
1483
  loginType: 'login-ci',
1484
+ telemetryOptOut: undefined,
1339
1485
  webClientPreload: undefined,
1340
1486
  name: 'client.alert.displayed',
1341
1487
  userType: 'host',
1342
1488
  isConvergedArchitectureEnabled: undefined,
1343
1489
  webexSubServiceType: undefined,
1490
+ isVipMeeting: false,
1491
+ isAutomatedUser: false,
1492
+ userActivation: undefined,
1344
1493
  },
1345
1494
  options
1346
1495
  );
@@ -1365,11 +1514,15 @@ describe('internal-plugin-metrics', () => {
1365
1514
  userId: 'userId',
1366
1515
  },
1367
1516
  loginType: 'login-ci',
1517
+ telemetryOptOut: undefined,
1368
1518
  webClientPreload: undefined,
1369
1519
  name: 'client.alert.displayed',
1370
1520
  userType: 'host',
1371
1521
  isConvergedArchitectureEnabled: undefined,
1372
1522
  webexSubServiceType: undefined,
1523
+ isVipMeeting: false,
1524
+ isAutomatedUser: false,
1525
+ userActivation: undefined,
1373
1526
  },
1374
1527
  eventId: 'my-fake-id',
1375
1528
  origin: {
@@ -1405,11 +1558,15 @@ describe('internal-plugin-metrics', () => {
1405
1558
  userId: 'userId',
1406
1559
  },
1407
1560
  loginType: 'login-ci',
1561
+ telemetryOptOut: undefined,
1408
1562
  webClientPreload: undefined,
1409
1563
  name: 'client.alert.displayed',
1410
1564
  userType: 'host',
1411
1565
  isConvergedArchitectureEnabled: undefined,
1412
1566
  webexSubServiceType: undefined,
1567
+ isVipMeeting: false,
1568
+ isAutomatedUser: false,
1569
+ userActivation: undefined,
1413
1570
  },
1414
1571
  eventId: 'my-fake-id',
1415
1572
  origin: {
@@ -1480,6 +1637,7 @@ describe('internal-plugin-metrics', () => {
1480
1637
  userId: 'userId',
1481
1638
  },
1482
1639
  loginType: 'login-ci',
1640
+ telemetryOptOut: undefined,
1483
1641
  name: 'client.alert.displayed',
1484
1642
  userType: 'host',
1485
1643
  userNameInput: 'test',
@@ -1487,6 +1645,9 @@ describe('internal-plugin-metrics', () => {
1487
1645
  isConvergedArchitectureEnabled: undefined,
1488
1646
  webexSubServiceType: undefined,
1489
1647
  webClientPreload: undefined,
1648
+ isVipMeeting: false,
1649
+ isAutomatedUser: false,
1650
+ userActivation: undefined,
1490
1651
  },
1491
1652
  options
1492
1653
  );
@@ -1511,6 +1672,7 @@ describe('internal-plugin-metrics', () => {
1511
1672
  userId: 'userId',
1512
1673
  },
1513
1674
  loginType: 'login-ci',
1675
+ telemetryOptOut: undefined,
1514
1676
  name: 'client.alert.displayed',
1515
1677
  userType: 'host',
1516
1678
  userNameInput: 'test',
@@ -1518,6 +1680,9 @@ describe('internal-plugin-metrics', () => {
1518
1680
  isConvergedArchitectureEnabled: undefined,
1519
1681
  webexSubServiceType: undefined,
1520
1682
  webClientPreload: undefined,
1683
+ isVipMeeting: false,
1684
+ isAutomatedUser: false,
1685
+ userActivation: undefined,
1521
1686
  },
1522
1687
  eventId: 'my-fake-id',
1523
1688
  origin: {
@@ -1553,6 +1718,7 @@ describe('internal-plugin-metrics', () => {
1553
1718
  userId: 'userId',
1554
1719
  },
1555
1720
  loginType: 'login-ci',
1721
+ telemetryOptOut: undefined,
1556
1722
  name: 'client.alert.displayed',
1557
1723
  userType: 'host',
1558
1724
  userNameInput: 'test',
@@ -1560,6 +1726,9 @@ describe('internal-plugin-metrics', () => {
1560
1726
  isConvergedArchitectureEnabled: undefined,
1561
1727
  webexSubServiceType: undefined,
1562
1728
  webClientPreload: undefined,
1729
+ isVipMeeting: false,
1730
+ isAutomatedUser: false,
1731
+ userActivation: undefined,
1563
1732
  },
1564
1733
  eventId: 'my-fake-id',
1565
1734
  origin: {
@@ -1684,8 +1853,11 @@ describe('internal-plugin-metrics', () => {
1684
1853
  userId: 'userId',
1685
1854
  },
1686
1855
  loginType: 'login-ci',
1856
+ telemetryOptOut: undefined,
1687
1857
  name: 'client.alert.displayed',
1688
1858
  webClientPreload: undefined,
1859
+ isAutomatedUser: false,
1860
+ userActivation: undefined,
1689
1861
  },
1690
1862
  options
1691
1863
  );
@@ -1707,8 +1879,11 @@ describe('internal-plugin-metrics', () => {
1707
1879
  userId: 'userId',
1708
1880
  },
1709
1881
  loginType: 'login-ci',
1882
+ telemetryOptOut: undefined,
1710
1883
  name: 'client.alert.displayed',
1711
1884
  webClientPreload: undefined,
1885
+ isAutomatedUser: false,
1886
+ userActivation: undefined,
1712
1887
  },
1713
1888
  eventId: 'my-fake-id',
1714
1889
  origin: {
@@ -1782,8 +1957,11 @@ describe('internal-plugin-metrics', () => {
1782
1957
  userId: 'myPreLoginId',
1783
1958
  },
1784
1959
  loginType: 'login-ci',
1960
+ telemetryOptOut: undefined,
1785
1961
  name: 'client.alert.displayed',
1786
1962
  webClientPreload: undefined,
1963
+ isAutomatedUser: false,
1964
+ userActivation: undefined,
1787
1965
  },
1788
1966
  options
1789
1967
  );
@@ -1811,7 +1989,10 @@ describe('internal-plugin-metrics', () => {
1811
1989
  },
1812
1990
  eventData: {webClientDomain: 'whatever', isMercuryConnected: true},
1813
1991
  loginType: 'login-ci',
1992
+ telemetryOptOut: undefined,
1814
1993
  webClientPreload: undefined,
1994
+ isAutomatedUser: false,
1995
+ userActivation: undefined,
1815
1996
  },
1816
1997
  },
1817
1998
  options.preLoginId
@@ -1873,8 +2054,11 @@ describe('internal-plugin-metrics', () => {
1873
2054
  userNameInput: 'current',
1874
2055
  emailInput: 'current',
1875
2056
  loginType: 'login-ci',
2057
+ telemetryOptOut: undefined,
1876
2058
  name: 'client.alert.displayed',
1877
2059
  webClientPreload: undefined,
2060
+ isAutomatedUser: false,
2061
+ userActivation: undefined,
1878
2062
  },
1879
2063
  options
1880
2064
  );
@@ -1902,9 +2086,12 @@ describe('internal-plugin-metrics', () => {
1902
2086
  },
1903
2087
  eventData: {webClientDomain: 'whatever', isMercuryConnected: true},
1904
2088
  loginType: 'login-ci',
2089
+ telemetryOptOut: undefined,
1905
2090
  userNameInput: 'current',
1906
2091
  emailInput: 'current',
1907
2092
  webClientPreload: undefined,
2093
+ isAutomatedUser: false,
2094
+ userActivation: undefined,
1908
2095
  },
1909
2096
  },
1910
2097
  options.preLoginId
@@ -1944,12 +2131,16 @@ describe('internal-plugin-metrics', () => {
1944
2131
  userId: 'userId',
1945
2132
  },
1946
2133
  loginType: 'fakeLoginType',
2134
+ telemetryOptOut: undefined,
1947
2135
  name: 'client.alert.displayed',
1948
2136
  userType: 'host',
1949
2137
  joinFlowVersion: 'Other',
1950
2138
  isConvergedArchitectureEnabled: undefined,
1951
2139
  webexSubServiceType: undefined,
1952
2140
  webClientPreload: undefined,
2141
+ isVipMeeting: false,
2142
+ isAutomatedUser: false,
2143
+ userActivation: undefined,
1953
2144
  },
1954
2145
  eventId: 'my-fake-id',
1955
2146
  origin: {
@@ -1999,12 +2190,16 @@ describe('internal-plugin-metrics', () => {
1999
2190
  userId: 'userId',
2000
2191
  },
2001
2192
  loginType: 'fakeLoginType',
2193
+ telemetryOptOut: undefined,
2002
2194
  name: 'client.alert.displayed',
2003
2195
  userType: 'host',
2004
2196
  joinFlowVersion: 'Other',
2005
2197
  isConvergedArchitectureEnabled: undefined,
2006
2198
  webexSubServiceType: undefined,
2007
2199
  webClientPreload: undefined,
2200
+ isVipMeeting: false,
2201
+ isAutomatedUser: false,
2202
+ userActivation: undefined,
2008
2203
  },
2009
2204
  eventId: 'my-fake-id',
2010
2205
  origin: {
@@ -2059,8 +2254,11 @@ describe('internal-plugin-metrics', () => {
2059
2254
  userId: 'userId',
2060
2255
  },
2061
2256
  loginType: 'login-ci',
2257
+ telemetryOptOut: undefined,
2062
2258
  name: 'client.alert.displayed',
2063
2259
  webClientPreload: true,
2260
+ isAutomatedUser: false,
2261
+ userActivation: undefined,
2064
2262
  },
2065
2263
  options
2066
2264
  );
@@ -2082,8 +2280,221 @@ describe('internal-plugin-metrics', () => {
2082
2280
  userId: 'userId',
2083
2281
  },
2084
2282
  loginType: 'login-ci',
2283
+ telemetryOptOut: undefined,
2085
2284
  name: 'client.alert.displayed',
2086
2285
  webClientPreload: true,
2286
+ isAutomatedUser: false,
2287
+ userActivation: undefined,
2288
+ },
2289
+ eventId: 'my-fake-id',
2290
+ origin: {
2291
+ origin: 'fake-origin',
2292
+ },
2293
+ originTime: {
2294
+ sent: 'not_defined_yet',
2295
+ triggered: now.toISOString(),
2296
+ },
2297
+ senderCountryCode: 'UK',
2298
+ version: 1,
2299
+ });
2300
+ });
2301
+
2302
+ it('should submit client event with isVipMeeting: false when vipMeeting is false', () => {
2303
+ const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
2304
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
2305
+ const generateClientEventErrorPayloadSpy = sinon.spy(cd, 'generateClientEventErrorPayload');
2306
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
2307
+
2308
+ webex.meetings.getBasicMeetingInformation = sinon.stub().returns({
2309
+ ...fakeMeeting,
2310
+ meetingInfo: {
2311
+ vipmeeting: false,
2312
+ },
2313
+ });
2314
+
2315
+ const options = {
2316
+ correlationId: 'correlationId',
2317
+ webexConferenceIdStr: 'webexConferenceIdStr1',
2318
+ globalMeetingId: 'globalMeetingId1',
2319
+ sessionCorrelationId: 'sessionCorrelationId1',
2320
+ meetingId: fakeMeeting.id,
2321
+ };
2322
+ cd.setMercuryConnectedStatus(true);
2323
+ cd.submitClientEvent({
2324
+ name: 'client.alert.displayed',
2325
+ options,
2326
+ });
2327
+
2328
+ assert.notCalled(generateClientEventErrorPayloadSpy);
2329
+ assert.calledWith(
2330
+ prepareDiagnosticEventSpy,
2331
+ {
2332
+ canProceed: true,
2333
+ eventData: {
2334
+ webClientDomain: 'whatever',
2335
+ isMercuryConnected: true,
2336
+ },
2337
+ identifiers: {
2338
+ correlationId: 'correlationId',
2339
+ webexConferenceIdStr: 'webexConferenceIdStr1',
2340
+ globalMeetingId: 'globalMeetingId1',
2341
+ sessionCorrelationId: 'sessionCorrelationId1',
2342
+ deviceId: 'deviceUrl',
2343
+ locusId: 'url',
2344
+ locusSessionId: 'locusSessionId',
2345
+ locusStartTime: 'lastActive',
2346
+ locusUrl: 'locus/url',
2347
+ orgId: 'orgId',
2348
+ userId: 'userId',
2349
+ },
2350
+ loginType: 'login-ci',
2351
+ telemetryOptOut: undefined,
2352
+ name: 'client.alert.displayed',
2353
+ userType: 'host',
2354
+ isConvergedArchitectureEnabled: undefined,
2355
+ webexSubServiceType: undefined,
2356
+ webClientPreload: undefined,
2357
+ isVipMeeting: false,
2358
+ isAutomatedUser: false,
2359
+ userActivation: undefined,
2360
+ },
2361
+ options
2362
+ );
2363
+ assert.calledWith(submitToCallDiagnosticsSpy, {
2364
+ event: {
2365
+ canProceed: true,
2366
+ eventData: {
2367
+ webClientDomain: 'whatever',
2368
+ isMercuryConnected: true,
2369
+ },
2370
+ identifiers: {
2371
+ correlationId: 'correlationId',
2372
+ webexConferenceIdStr: 'webexConferenceIdStr1',
2373
+ globalMeetingId: 'globalMeetingId1',
2374
+ sessionCorrelationId: 'sessionCorrelationId1',
2375
+ deviceId: 'deviceUrl',
2376
+ locusId: 'url',
2377
+ locusSessionId: 'locusSessionId',
2378
+ locusStartTime: 'lastActive',
2379
+ locusUrl: 'locus/url',
2380
+ orgId: 'orgId',
2381
+ userId: 'userId',
2382
+ },
2383
+ loginType: 'login-ci',
2384
+ telemetryOptOut: undefined,
2385
+ name: 'client.alert.displayed',
2386
+ userType: 'host',
2387
+ isConvergedArchitectureEnabled: undefined,
2388
+ webexSubServiceType: undefined,
2389
+ webClientPreload: undefined,
2390
+ isVipMeeting: false,
2391
+ isAutomatedUser: false,
2392
+ userActivation: undefined,
2393
+ },
2394
+ eventId: 'my-fake-id',
2395
+ origin: {
2396
+ origin: 'fake-origin',
2397
+ },
2398
+ originTime: {
2399
+ sent: 'not_defined_yet',
2400
+ triggered: now.toISOString(),
2401
+ },
2402
+ senderCountryCode: 'UK',
2403
+ version: 1,
2404
+ });
2405
+ });
2406
+
2407
+ it('should submit client event with isVipMeeting: true when vipMeeting is true', () => {
2408
+ const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
2409
+ const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
2410
+ const generateClientEventErrorPayloadSpy = sinon.spy(cd, 'generateClientEventErrorPayload');
2411
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
2412
+
2413
+ webex.meetings.getBasicMeetingInformation = sinon.stub().returns({
2414
+ ...fakeMeeting,
2415
+ meetingInfo: {
2416
+ vipmeeting: true,
2417
+ },
2418
+ });
2419
+
2420
+ const options = {
2421
+ correlationId: 'correlationId',
2422
+ webexConferenceIdStr: 'webexConferenceIdStr1',
2423
+ globalMeetingId: 'globalMeetingId1',
2424
+ sessionCorrelationId: 'sessionCorrelationId1',
2425
+ meetingId: fakeMeeting.id,
2426
+ };
2427
+ cd.setMercuryConnectedStatus(true);
2428
+ cd.submitClientEvent({
2429
+ name: 'client.alert.displayed',
2430
+ options,
2431
+ });
2432
+
2433
+ assert.notCalled(generateClientEventErrorPayloadSpy);
2434
+ assert.calledWith(
2435
+ prepareDiagnosticEventSpy,
2436
+ {
2437
+ canProceed: true,
2438
+ eventData: {
2439
+ webClientDomain: 'whatever',
2440
+ isMercuryConnected: true,
2441
+ },
2442
+ identifiers: {
2443
+ correlationId: 'correlationId',
2444
+ webexConferenceIdStr: 'webexConferenceIdStr1',
2445
+ globalMeetingId: 'globalMeetingId1',
2446
+ sessionCorrelationId: 'sessionCorrelationId1',
2447
+ deviceId: 'deviceUrl',
2448
+ locusId: 'url',
2449
+ locusSessionId: 'locusSessionId',
2450
+ locusStartTime: 'lastActive',
2451
+ locusUrl: 'locus/url',
2452
+ orgId: 'orgId',
2453
+ userId: 'userId',
2454
+ },
2455
+ loginType: 'login-ci',
2456
+ telemetryOptOut: undefined,
2457
+ name: 'client.alert.displayed',
2458
+ userType: 'host',
2459
+ isConvergedArchitectureEnabled: undefined,
2460
+ webexSubServiceType: undefined,
2461
+ webClientPreload: undefined,
2462
+ isVipMeeting: true,
2463
+ isAutomatedUser: false,
2464
+ userActivation: undefined,
2465
+ },
2466
+ options
2467
+ );
2468
+ assert.calledWith(submitToCallDiagnosticsSpy, {
2469
+ event: {
2470
+ canProceed: true,
2471
+ eventData: {
2472
+ webClientDomain: 'whatever',
2473
+ isMercuryConnected: true,
2474
+ },
2475
+ identifiers: {
2476
+ correlationId: 'correlationId',
2477
+ webexConferenceIdStr: 'webexConferenceIdStr1',
2478
+ globalMeetingId: 'globalMeetingId1',
2479
+ sessionCorrelationId: 'sessionCorrelationId1',
2480
+ deviceId: 'deviceUrl',
2481
+ locusId: 'url',
2482
+ locusSessionId: 'locusSessionId',
2483
+ locusStartTime: 'lastActive',
2484
+ locusUrl: 'locus/url',
2485
+ orgId: 'orgId',
2486
+ userId: 'userId',
2487
+ },
2488
+ loginType: 'login-ci',
2489
+ telemetryOptOut: undefined,
2490
+ name: 'client.alert.displayed',
2491
+ userType: 'host',
2492
+ isConvergedArchitectureEnabled: undefined,
2493
+ webexSubServiceType: undefined,
2494
+ webClientPreload: undefined,
2495
+ isVipMeeting: true,
2496
+ isAutomatedUser: false,
2497
+ userActivation: undefined,
2087
2498
  },
2088
2499
  eventId: 'my-fake-id',
2089
2500
  origin: {
@@ -2153,11 +2564,15 @@ describe('internal-plugin-metrics', () => {
2153
2564
  },
2154
2565
  ],
2155
2566
  loginType: 'login-ci',
2567
+ telemetryOptOut: undefined,
2156
2568
  name: 'client.alert.displayed',
2157
2569
  userType: 'host',
2158
2570
  isConvergedArchitectureEnabled: undefined,
2159
2571
  webexSubServiceType: undefined,
2160
2572
  webClientPreload: undefined,
2573
+ isVipMeeting: false,
2574
+ isAutomatedUser: false,
2575
+ userActivation: undefined,
2161
2576
  },
2162
2577
  eventId: 'my-fake-id',
2163
2578
  origin: {
@@ -2235,11 +2650,15 @@ describe('internal-plugin-metrics', () => {
2235
2650
  },
2236
2651
  ],
2237
2652
  loginType: 'login-ci',
2653
+ telemetryOptOut: undefined,
2238
2654
  name: 'client.alert.displayed',
2239
2655
  userType: 'host',
2240
2656
  isConvergedArchitectureEnabled: undefined,
2241
2657
  webexSubServiceType: undefined,
2242
2658
  webClientPreload: undefined,
2659
+ isVipMeeting: false,
2660
+ isAutomatedUser: false,
2661
+ userActivation: undefined,
2243
2662
  },
2244
2663
  eventId: 'my-fake-id',
2245
2664
  origin: {
@@ -2311,8 +2730,11 @@ describe('internal-plugin-metrics', () => {
2311
2730
  },
2312
2731
  ],
2313
2732
  loginType: 'login-ci',
2733
+ telemetryOptOut: undefined,
2314
2734
  name: 'client.alert.displayed',
2315
2735
  webClientPreload: undefined,
2736
+ isAutomatedUser: false,
2737
+ userActivation: undefined,
2316
2738
  },
2317
2739
  eventId: 'my-fake-id',
2318
2740
  origin: {
@@ -2386,8 +2808,11 @@ describe('internal-plugin-metrics', () => {
2386
2808
  },
2387
2809
  ],
2388
2810
  loginType: 'login-ci',
2811
+ telemetryOptOut: undefined,
2389
2812
  name: 'client.alert.displayed',
2390
2813
  webClientPreload: undefined,
2814
+ isAutomatedUser: false,
2815
+ userActivation: undefined,
2391
2816
  },
2392
2817
  eventId: 'my-fake-id',
2393
2818
  origin: {
@@ -2468,11 +2893,15 @@ describe('internal-plugin-metrics', () => {
2468
2893
  },
2469
2894
  ],
2470
2895
  loginType: 'login-ci',
2896
+ telemetryOptOut: undefined,
2471
2897
  name: 'client.alert.displayed',
2472
2898
  userType: 'host',
2473
2899
  isConvergedArchitectureEnabled: undefined,
2474
2900
  webexSubServiceType: undefined,
2475
2901
  webClientPreload: undefined,
2902
+ isVipMeeting: false,
2903
+ isAutomatedUser: false,
2904
+ userActivation: undefined,
2476
2905
  },
2477
2906
  eventId: 'my-fake-id',
2478
2907
  origin: {
@@ -2563,16 +2992,18 @@ describe('internal-plugin-metrics', () => {
2563
2992
  });
2564
2993
 
2565
2994
  assert.calledThrice(submitToCallDiagnosticsStub);
2566
- });
2995
+ });
2567
2996
 
2568
- ([
2569
- ['client.media.render.start'],
2570
- ['client.media.render.stop'],
2571
- ['client.media.rx.start'],
2572
- ['client.media.rx.stop'],
2573
- ['client.media.tx.start'],
2574
- ['client.media.tx.stop']
2575
- ] as const).forEach(([name]) => {
2997
+ (
2998
+ [
2999
+ ['client.media.render.start'],
3000
+ ['client.media.render.stop'],
3001
+ ['client.media.rx.start'],
3002
+ ['client.media.rx.stop'],
3003
+ ['client.media.tx.start'],
3004
+ ['client.media.tx.stop'],
3005
+ ] as const
3006
+ ).forEach(([name]) => {
2576
3007
  it(`should only send ${name} once per mediaType`, () => {
2577
3008
  const options = {
2578
3009
  meetingId: fakeMeeting.id,
@@ -2616,7 +3047,8 @@ describe('internal-plugin-metrics', () => {
2616
3047
  });
2617
3048
 
2618
3049
  assert.notCalled(submitToCallDiagnosticsStub);
2619
- assert.neverCalledWithMatch(webex.logger.log,
3050
+ assert.neverCalledWithMatch(
3051
+ webex.logger.log,
2620
3052
  'call-diagnostic-events -> ',
2621
3053
  sinon.match(createEventLimitRegex(name, 'mediaType video'))
2622
3054
  );
@@ -2659,7 +3091,7 @@ describe('internal-plugin-metrics', () => {
2659
3091
  // Send event with different shareInstanceId
2660
3092
  cd.submitClientEvent({
2661
3093
  name,
2662
- payload: { ...payload, shareInstanceId: 'instance-2' },
3094
+ payload: {...payload, shareInstanceId: 'instance-2'},
2663
3095
  options,
2664
3096
  });
2665
3097
 
@@ -2667,89 +3099,88 @@ describe('internal-plugin-metrics', () => {
2667
3099
  });
2668
3100
  });
2669
3101
 
2670
- ([
2671
- ['client.roap-message.received'],
2672
- ['client.roap-message.sent']
2673
- ] as const).forEach(([name]) => {
2674
- it(`should not send third event of same type and not log warning again for ${name}`, () => {
2675
- const options = {
2676
- meetingId: fakeMeeting.id,
2677
- };
2678
- const payload = {
2679
- roap: {
2680
- messageType: 'OFFER' as const,
2681
- },
2682
- };
2683
- const submitToCallDiagnosticsStub = sinon.stub(cd, 'submitToCallDiagnostics');
2684
-
2685
- // Clear any existing call history to get accurate counts
2686
- webex.logger.log.resetHistory();
2687
-
2688
- // Send first event
2689
- cd.submitClientEvent({
2690
- name,
2691
- payload,
2692
- options,
2693
- });
2694
-
2695
- assert.calledOnce(submitToCallDiagnosticsStub);
2696
- submitToCallDiagnosticsStub.resetHistory();
2697
-
2698
- // Send second event (should trigger warning)
2699
- cd.submitClientEvent({
2700
- name,
2701
- payload,
2702
- options,
2703
- });
2704
-
2705
- assert.notCalled(submitToCallDiagnosticsStub);
2706
- assert.calledWith(
2707
- webex.logger.log,
2708
- 'call-diagnostic-events -> ',
2709
- sinon.match(createEventLimitRegex(name, 'ROAP type OFFER'))
2710
- );
2711
- webex.logger.log.resetHistory();
2712
-
2713
- cd.submitClientEvent({
2714
- name,
2715
- payload,
2716
- options,
3102
+ ([['client.roap-message.received'], ['client.roap-message.sent']] as const).forEach(
3103
+ ([name]) => {
3104
+ it(`should not send third event of same type and not log warning again for ${name}`, () => {
3105
+ const options = {
3106
+ meetingId: fakeMeeting.id,
3107
+ };
3108
+ const payload = {
3109
+ roap: {
3110
+ messageType: 'OFFER' as const,
3111
+ },
3112
+ };
3113
+ const submitToCallDiagnosticsStub = sinon.stub(cd, 'submitToCallDiagnostics');
3114
+
3115
+ // Clear any existing call history to get accurate counts
3116
+ webex.logger.log.resetHistory();
3117
+
3118
+ // Send first event
3119
+ cd.submitClientEvent({
3120
+ name,
3121
+ payload,
3122
+ options,
3123
+ });
3124
+
3125
+ assert.calledOnce(submitToCallDiagnosticsStub);
3126
+ submitToCallDiagnosticsStub.resetHistory();
3127
+
3128
+ // Send second event (should trigger warning)
3129
+ cd.submitClientEvent({
3130
+ name,
3131
+ payload,
3132
+ options,
3133
+ });
3134
+
3135
+ assert.notCalled(submitToCallDiagnosticsStub);
3136
+ assert.calledWith(
3137
+ webex.logger.log,
3138
+ 'call-diagnostic-events -> ',
3139
+ sinon.match(createEventLimitRegex(name, 'ROAP type OFFER'))
3140
+ );
3141
+ webex.logger.log.resetHistory();
3142
+
3143
+ cd.submitClientEvent({
3144
+ name,
3145
+ payload,
3146
+ options,
3147
+ });
3148
+
3149
+ assert.notCalled(submitToCallDiagnosticsStub);
3150
+ assert.neverCalledWithMatch(
3151
+ webex.logger.log,
3152
+ 'call-diagnostic-events -> ',
3153
+ sinon.match(createEventLimitRegex(name, 'ROAP type OFFER'))
3154
+ );
2717
3155
  });
2718
3156
 
2719
- assert.notCalled(submitToCallDiagnosticsStub);
2720
- assert.neverCalledWithMatch(
2721
- webex.logger.log,
2722
- 'call-diagnostic-events -> ',
2723
- sinon.match(createEventLimitRegex(name, 'ROAP type OFFER'))
2724
- );
2725
- });
3157
+ it(`should handle roap.type instead of roap.messageType for ${name}`, () => {
3158
+ const options = {
3159
+ meetingId: fakeMeeting.id,
3160
+ };
3161
+ const payload = {
3162
+ roap: {
3163
+ type: 'ANSWER' as const,
3164
+ },
3165
+ };
3166
+ const submitToCallDiagnosticsStub = sinon.stub(cd, 'submitToCallDiagnostics');
2726
3167
 
2727
- it(`should handle roap.type instead of roap.messageType for ${name}`, () => {
2728
- const options = {
2729
- meetingId: fakeMeeting.id,
2730
- };
2731
- const payload = {
2732
- roap: {
2733
- type: 'ANSWER' as const,
2734
- },
2735
- };
2736
- const submitToCallDiagnosticsStub = sinon.stub(cd, 'submitToCallDiagnostics');
3168
+ cd.submitClientEvent({
3169
+ name,
3170
+ payload,
3171
+ options,
3172
+ });
2737
3173
 
2738
- cd.submitClientEvent({
2739
- name,
2740
- payload,
2741
- options,
2742
- });
3174
+ cd.submitClientEvent({
3175
+ name,
3176
+ payload,
3177
+ options,
3178
+ });
2743
3179
 
2744
- cd.submitClientEvent({
2745
- name,
2746
- payload,
2747
- options,
3180
+ assert.calledOnce(submitToCallDiagnosticsStub);
2748
3181
  });
2749
-
2750
- assert.calledOnce(submitToCallDiagnosticsStub);
2751
- });
2752
- });
3182
+ }
3183
+ );
2753
3184
  });
2754
3185
  });
2755
3186
 
@@ -2760,7 +3191,11 @@ describe('internal-plugin-metrics', () => {
2760
3191
  cd.callDiagnosticEventsBatcher = {request: requestStub};
2761
3192
  //@ts-ignore
2762
3193
  cd.submitToCallDiagnostics({event: 'test'});
2763
- assert.calledWith(requestStub, {eventPayload: {event: 'test'}, type: ['diagnostic-event']});
3194
+ assert.calledWith(requestStub, {
3195
+ eventPayload: {event: 'test'},
3196
+ type: ['diagnostic-event'],
3197
+ markTelemetryOptOutOnResponse: true,
3198
+ });
2764
3199
  });
2765
3200
  });
2766
3201
 
@@ -2829,6 +3264,7 @@ describe('internal-plugin-metrics', () => {
2829
3264
  mediaEngineSoftwareVersion: getOSVersion() || 'unknown',
2830
3265
  startTime: now.toISOString(),
2831
3266
  },
3267
+ webexSubServiceType: undefined,
2832
3268
  },
2833
3269
  options
2834
3270
  );
@@ -2869,6 +3305,7 @@ describe('internal-plugin-metrics', () => {
2869
3305
  mediaEngineSoftwareVersion: getOSVersion() || 'unknown',
2870
3306
  startTime: now.toISOString(),
2871
3307
  },
3308
+ webexSubServiceType: undefined,
2872
3309
  },
2873
3310
  },
2874
3311
  });
@@ -2907,10 +3344,48 @@ describe('internal-plugin-metrics', () => {
2907
3344
  mediaEngineSoftwareVersion: getOSVersion() || 'unknown',
2908
3345
  startTime: now.toISOString(),
2909
3346
  },
3347
+ webexSubServiceType: undefined,
2910
3348
  },
2911
3349
  });
2912
3350
  });
2913
3351
 
3352
+ it('includes webexSubServiceType in the media quality event payload', () => {
3353
+ const meeting = {
3354
+ ...fakeMeeting,
3355
+ meetingInfo: {
3356
+ enableConvergedArchitecture: true,
3357
+ enableEvent: true,
3358
+ enableConvergedWebinarLargeScale: true,
3359
+ },
3360
+ };
3361
+ const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
3362
+ sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
3363
+ webex.meetings.getBasicMeetingInformation = sinon.stub().returns(meeting);
3364
+
3365
+ const options = {
3366
+ networkType: 'wifi' as const,
3367
+ meetingId: fakeMeeting.id,
3368
+ };
3369
+
3370
+ cd.submitMQE({
3371
+ name: 'client.mediaquality.event',
3372
+ payload: {
3373
+ //@ts-ignore
3374
+ intervals: [{}],
3375
+ },
3376
+ options,
3377
+ });
3378
+
3379
+ assert.calledOnceWithExactly(
3380
+ prepareDiagnosticEventSpy,
3381
+ sinon.match({
3382
+ name: 'client.mediaquality.event',
3383
+ webexSubServiceType: 'LargeScaleWebinar',
3384
+ }),
3385
+ options
3386
+ );
3387
+ });
3388
+
2914
3389
  it('throws if meeting id not provided', () => {
2915
3390
  assert.throws(() =>
2916
3391
  cd.submitMQE({
@@ -3631,6 +4106,97 @@ describe('internal-plugin-metrics', () => {
3631
4106
  });
3632
4107
  });
3633
4108
 
4109
+ describe('#getTelemetryOptOut', () => {
4110
+ it('returns "manual" when manual telemetry opt-out is enabled', () => {
4111
+ cd.setIsTelemetryOptOutManual(true);
4112
+ assert.equal(cd.getTelemetryOptOut(), 'manual');
4113
+ });
4114
+
4115
+ it('returns "automatic" when automatic telemetry opt-out is enabled', () => {
4116
+ cd.setIsTelemetryOptOutAutomatic(true);
4117
+ assert.equal(cd.getTelemetryOptOut(), 'automatic');
4118
+ });
4119
+
4120
+ it('returns "manual" when manual opt-out takes precedence over automatic', () => {
4121
+ cd.setIsTelemetryOptOutManual(true);
4122
+ cd.setIsTelemetryOptOutAutomatic(true);
4123
+ assert.equal(cd.getTelemetryOptOut(), 'manual');
4124
+ });
4125
+
4126
+ it('returns undefined when neither manual nor automatic opt-out is set', () => {
4127
+ assert.isUndefined(cd.getTelemetryOptOut());
4128
+ });
4129
+
4130
+ it('returns undefined after disabling manual opt-out', () => {
4131
+ cd.setIsTelemetryOptOutManual(true);
4132
+ cd.setIsTelemetryOptOutManual(false);
4133
+ assert.isUndefined(cd.getTelemetryOptOut());
4134
+ });
4135
+ });
4136
+
4137
+ describe('#setIsTelemetryOptOutManual', () => {
4138
+ it('sets manual telemetry opt-out to true', () => {
4139
+ cd.setIsTelemetryOptOutManual(true);
4140
+ assert.equal(cd.getTelemetryOptOut(), 'manual');
4141
+ });
4142
+
4143
+ it('sets manual telemetry opt-out to false', () => {
4144
+ cd.setIsTelemetryOptOutManual(true);
4145
+ cd.setIsTelemetryOptOutManual(false);
4146
+ assert.isUndefined(cd.getTelemetryOptOut());
4147
+ });
4148
+
4149
+ it('can toggle manual telemetry opt-out multiple times', () => {
4150
+ cd.setIsTelemetryOptOutManual(true);
4151
+ assert.equal(cd.getTelemetryOptOut(), 'manual');
4152
+
4153
+ cd.setIsTelemetryOptOutManual(false);
4154
+ assert.isUndefined(cd.getTelemetryOptOut());
4155
+
4156
+ cd.setIsTelemetryOptOutManual(true);
4157
+ assert.equal(cd.getTelemetryOptOut(), 'manual');
4158
+ });
4159
+
4160
+ it('manual opt-out takes precedence when automatic is also set', () => {
4161
+ cd.setIsTelemetryOptOutAutomatic(true);
4162
+ cd.setIsTelemetryOptOutManual(true);
4163
+ assert.equal(cd.getTelemetryOptOut(), 'manual');
4164
+ });
4165
+ });
4166
+
4167
+ describe('#setIsTelemetryOptOutAutomatic', () => {
4168
+ it('sets automatic telemetry opt-out to true', () => {
4169
+ cd.setIsTelemetryOptOutAutomatic(true);
4170
+ assert.equal(cd.getTelemetryOptOut(), 'automatic');
4171
+ });
4172
+
4173
+ it('sets automatic telemetry opt-out to false', () => {
4174
+ cd.setIsTelemetryOptOutAutomatic(true);
4175
+ cd.setIsTelemetryOptOutAutomatic(false);
4176
+ assert.isUndefined(cd.getTelemetryOptOut());
4177
+ });
4178
+
4179
+ it('can toggle automatic telemetry opt-out multiple times', () => {
4180
+ cd.setIsTelemetryOptOutAutomatic(true);
4181
+ assert.equal(cd.getTelemetryOptOut(), 'automatic');
4182
+
4183
+ cd.setIsTelemetryOptOutAutomatic(false);
4184
+ assert.isUndefined(cd.getTelemetryOptOut());
4185
+
4186
+ cd.setIsTelemetryOptOutAutomatic(true);
4187
+ assert.equal(cd.getTelemetryOptOut(), 'automatic');
4188
+ });
4189
+
4190
+ it('does not override manual opt-out', () => {
4191
+ cd.setIsTelemetryOptOutManual(true);
4192
+ cd.setIsTelemetryOptOutAutomatic(true);
4193
+ assert.equal(cd.getTelemetryOptOut(), 'manual');
4194
+
4195
+ cd.setIsTelemetryOptOutAutomatic(false);
4196
+ assert.equal(cd.getTelemetryOptOut(), 'manual');
4197
+ });
4198
+ });
4199
+
3634
4200
  describe('#getSubServiceType', () => {
3635
4201
  it('returns subServicetype as PMR when PMR meeting', () => {
3636
4202
  fakeMeeting.meetingInfo = {
@@ -3680,6 +4246,15 @@ describe('internal-plugin-metrics', () => {
3680
4246
  assert.deepEqual(cd.getSubServiceType(fakeMeeting), 'Webcast');
3681
4247
  });
3682
4248
 
4249
+ it('returns subServicetype as LargeScaleWebinar when meeting is converged Webinar and enable large scale', () => {
4250
+ fakeMeeting.meetingInfo = {
4251
+ enableEvent: true,
4252
+ enableConvergedArchitecture: true,
4253
+ enableConvergedWebinarLargeScale: true,
4254
+ };
4255
+ assert.deepEqual(cd.getSubServiceType(fakeMeeting), 'LargeScaleWebinar');
4256
+ });
4257
+
3683
4258
  it('returns subServicetype as undefined when correct parameters are not found', () => {
3684
4259
  fakeMeeting.meetingInfo = {};
3685
4260
  assert.deepEqual(cd.getSubServiceType(fakeMeeting), undefined);
@@ -3740,12 +4315,16 @@ describe('internal-plugin-metrics', () => {
3740
4315
  userId: 'userId',
3741
4316
  },
3742
4317
  loginType: 'login-ci',
4318
+ telemetryOptOut: undefined,
3743
4319
  name: 'client.exit.app',
3744
4320
  trigger: 'user-interaction',
3745
4321
  userType: 'host',
3746
4322
  isConvergedArchitectureEnabled: undefined,
3747
4323
  webexSubServiceType: undefined,
3748
4324
  webClientPreload: undefined,
4325
+ isVipMeeting: false,
4326
+ isAutomatedUser: false,
4327
+ userActivation: undefined,
3749
4328
  },
3750
4329
  eventId: 'my-fake-id',
3751
4330
  origin: {
@@ -3913,7 +4492,11 @@ describe('internal-plugin-metrics', () => {
3913
4492
  cd.submitToCallDiagnosticsPreLogin({event: 'test'}, preLoginId);
3914
4493
  //@ts-ignore
3915
4494
  assert.calledWith(cd.preLoginMetricsBatcher.savePreLoginId, preLoginId);
3916
- assert.calledWith(requestStub, {eventPayload: {event: 'test'}, type: ['diagnostic-event']});
4495
+ assert.calledWith(requestStub, {
4496
+ eventPayload: {event: 'test'},
4497
+ type: ['diagnostic-event'],
4498
+ markTelemetryOptOutOnResponse: true,
4499
+ });
3917
4500
  });
3918
4501
  });
3919
4502
 
@@ -4114,12 +4697,14 @@ describe('internal-plugin-metrics', () => {
4114
4697
  payload: {
4115
4698
  meetingSummaryInfo: {
4116
4699
  featureName: 'syncSystemMuteStatus',
4117
- featureActions: [{
4118
- actionName: 'syncMeetingMicUnmuteStatusToSystem',
4119
- actionId: '14200',
4120
- isInitialValue: false,
4121
- clickCount: '1'
4122
- }]
4700
+ featureActions: [
4701
+ {
4702
+ actionName: 'syncMeetingMicUnmuteStatusToSystem',
4703
+ actionId: '14200',
4704
+ isInitialValue: false,
4705
+ clickCount: '1',
4706
+ },
4707
+ ],
4123
4708
  },
4124
4709
  },
4125
4710
  options,
@@ -4140,22 +4725,28 @@ describe('internal-plugin-metrics', () => {
4140
4725
  locusSessionId: 'locusSessionId',
4141
4726
  locusStartTime: 'lastActive',
4142
4727
  },
4143
- eventData: { webClientDomain: 'whatever'},
4728
+ eventData: {webClientDomain: 'whatever'},
4144
4729
  userType: 'host',
4145
4730
  loginType: 'login-ci',
4731
+ telemetryOptOut: undefined,
4146
4732
  isConvergedArchitectureEnabled: undefined,
4147
4733
  webexSubServiceType: undefined,
4148
4734
  webClientPreload: undefined,
4735
+ isVipMeeting: false,
4736
+ isAutomatedUser: false,
4737
+ userActivation: undefined,
4149
4738
  meetingSummaryInfo: {
4150
4739
  featureName: 'syncSystemMuteStatus',
4151
- featureActions: [{
4152
- actionName: 'syncMeetingMicUnmuteStatusToSystem',
4153
- actionId: '14200',
4154
- isInitialValue: false,
4155
- clickCount: '1'
4156
- }]
4740
+ featureActions: [
4741
+ {
4742
+ actionName: 'syncMeetingMicUnmuteStatusToSystem',
4743
+ actionId: '14200',
4744
+ isInitialValue: false,
4745
+ clickCount: '1',
4746
+ },
4747
+ ],
4157
4748
  },
4158
- key: "UcfFeatureUsage",
4749
+ key: 'UcfFeatureUsage',
4159
4750
  },
4160
4751
  options
4161
4752
  );
@@ -4168,7 +4759,7 @@ describe('internal-plugin-metrics', () => {
4168
4759
  },
4169
4760
  event: {
4170
4761
  canProceed: true,
4171
- eventData: { webClientDomain: 'whatever'},
4762
+ eventData: {webClientDomain: 'whatever'},
4172
4763
  identifiers: {
4173
4764
  correlationId: 'correlationId',
4174
4765
  deviceId: 'deviceUrl',
@@ -4180,21 +4771,27 @@ describe('internal-plugin-metrics', () => {
4180
4771
  userId: 'userId',
4181
4772
  },
4182
4773
  loginType: 'login-ci',
4774
+ telemetryOptOut: undefined,
4183
4775
  name: 'client.feature.meeting.summary',
4184
4776
  userType: 'host',
4185
4777
  isConvergedArchitectureEnabled: undefined,
4186
4778
  webexSubServiceType: undefined,
4187
4779
  webClientPreload: undefined,
4780
+ isVipMeeting: false,
4781
+ isAutomatedUser: false,
4782
+ userActivation: undefined,
4188
4783
  meetingSummaryInfo: {
4189
4784
  featureName: 'syncSystemMuteStatus',
4190
- featureActions: [{
4191
- actionName: 'syncMeetingMicUnmuteStatusToSystem',
4192
- actionId: '14200',
4193
- isInitialValue: false,
4194
- clickCount: '1'
4195
- }]
4785
+ featureActions: [
4786
+ {
4787
+ actionName: 'syncMeetingMicUnmuteStatusToSystem',
4788
+ actionId: '14200',
4789
+ isInitialValue: false,
4790
+ clickCount: '1',
4791
+ },
4792
+ ],
4196
4793
  },
4197
- key: "UcfFeatureUsage",
4794
+ key: 'UcfFeatureUsage',
4198
4795
  },
4199
4796
  originTime: {
4200
4797
  sent: 'not_defined_yet',
@@ -4235,12 +4832,14 @@ describe('internal-plugin-metrics', () => {
4235
4832
  payload: {
4236
4833
  meetingSummaryInfo: {
4237
4834
  featureName: 'syncSystemMuteStatus',
4238
- featureActions: [{
4239
- actionName: 'syncMeetingMicUnmuteStatusToSystem',
4240
- actionId: '14200',
4241
- isInitialValue: false,
4242
- clickCount: '1'
4243
- }]
4835
+ featureActions: [
4836
+ {
4837
+ actionName: 'syncMeetingMicUnmuteStatusToSystem',
4838
+ actionId: '14200',
4839
+ isInitialValue: false,
4840
+ clickCount: '1',
4841
+ },
4842
+ ],
4244
4843
  },
4245
4844
  },
4246
4845
  delaySubmitEvent: true,
@@ -4252,12 +4851,14 @@ describe('internal-plugin-metrics', () => {
4252
4851
  payload: {
4253
4852
  meetingSummaryInfo: {
4254
4853
  featureName: 'syncSystemVideoStatus',
4255
- featureActions: [{
4256
- actionName: 'syncMeetingVideoUnmuteStatusToSystem',
4257
- actionId: '13400',
4258
- isInitialValue: false,
4259
- clickCount: '1'
4260
- }]
4854
+ featureActions: [
4855
+ {
4856
+ actionName: 'syncMeetingVideoUnmuteStatusToSystem',
4857
+ actionId: '13400',
4858
+ isInitialValue: false,
4859
+ clickCount: '1',
4860
+ },
4861
+ ],
4261
4862
  },
4262
4863
  },
4263
4864
  delaySubmitEvent: true,
@@ -4275,12 +4876,14 @@ describe('internal-plugin-metrics', () => {
4275
4876
  payload: {
4276
4877
  meetingSummaryInfo: {
4277
4878
  featureName: 'syncSystemMuteStatus',
4278
- featureActions: [{
4279
- actionName: 'syncMeetingMicUnmuteStatusToSystem',
4280
- actionId: '14200',
4281
- isInitialValue: false,
4282
- clickCount: '1'
4283
- }]
4879
+ featureActions: [
4880
+ {
4881
+ actionName: 'syncMeetingMicUnmuteStatusToSystem',
4882
+ actionId: '14200',
4883
+ isInitialValue: false,
4884
+ clickCount: '1',
4885
+ },
4886
+ ],
4284
4887
  },
4285
4888
  },
4286
4889
  options: {
@@ -4293,12 +4896,14 @@ describe('internal-plugin-metrics', () => {
4293
4896
  payload: {
4294
4897
  meetingSummaryInfo: {
4295
4898
  featureName: 'syncSystemVideoStatus',
4296
- featureActions: [{
4297
- actionName: 'syncMeetingVideoUnmuteStatusToSystem',
4298
- actionId: '13400',
4299
- isInitialValue: false,
4300
- clickCount: '1'
4301
- }]
4899
+ featureActions: [
4900
+ {
4901
+ actionName: 'syncMeetingVideoUnmuteStatusToSystem',
4902
+ actionId: '13400',
4903
+ isInitialValue: false,
4904
+ clickCount: '1',
4905
+ },
4906
+ ],
4302
4907
  },
4303
4908
  },
4304
4909
  options: {
@@ -4322,17 +4927,17 @@ describe('internal-plugin-metrics', () => {
4322
4927
 
4323
4928
  it('should clear event limits for specific correlationId only', () => {
4324
4929
  // Use the actual correlationIds from our fakeMeeting fixtures
4325
- const correlationId1 = fakeMeeting.correlationId; // e.g. 'correlationId1'
4326
- const correlationId2 = fakeMeeting2.correlationId; // e.g. 'correlationId2'
4327
- const options1 = { meetingId: fakeMeeting.id };
4328
- const options2 = { meetingId: fakeMeeting2.id };
4329
- const payload = { mediaType: 'video' as const };
4930
+ const correlationId1 = fakeMeeting.correlationId; // e.g. 'correlationId1'
4931
+ const correlationId2 = fakeMeeting2.correlationId; // e.g. 'correlationId2'
4932
+ const options1 = {meetingId: fakeMeeting.id};
4933
+ const options2 = {meetingId: fakeMeeting2.id};
4934
+ const payload = {mediaType: 'video' as const};
4330
4935
 
4331
4936
  // Set up events for both correlations to trigger limits
4332
- cd.submitClientEvent({ name: 'client.media.render.start', payload, options: options1 });
4333
- cd.submitClientEvent({ name: 'client.media.render.start', payload, options: options2 });
4334
- cd.submitClientEvent({ name: 'client.media.render.start', payload, options: options1 });
4335
- cd.submitClientEvent({ name: 'client.media.render.start', payload, options: options2 });
4937
+ cd.submitClientEvent({name: 'client.media.render.start', payload, options: options1});
4938
+ cd.submitClientEvent({name: 'client.media.render.start', payload, options: options2});
4939
+ cd.submitClientEvent({name: 'client.media.render.start', payload, options: options1});
4940
+ cd.submitClientEvent({name: 'client.media.render.start', payload, options: options2});
4336
4941
  assert.isTrue(cd.eventLimitTracker.size > 0);
4337
4942
  assert.isTrue(cd.eventLimitWarningsLogged.size > 0);
4338
4943
 
@@ -4343,17 +4948,17 @@ describe('internal-plugin-metrics', () => {
4343
4948
  const remainingWarningKeys = Array.from(cd.eventLimitWarningsLogged.keys());
4344
4949
 
4345
4950
  // Should have no keys with correlationId1
4346
- assert.isFalse(remainingTrackerKeys.some(key => key.split(':')[1] === correlationId1));
4347
- assert.isFalse(remainingWarningKeys.some(key => key.split(':')[1] === correlationId1));
4951
+ assert.isFalse(remainingTrackerKeys.some((key) => key.split(':')[1] === correlationId1));
4952
+ assert.isFalse(remainingWarningKeys.some((key) => key.split(':')[1] === correlationId1));
4348
4953
 
4349
4954
  // Should still have keys with correlationId2
4350
- assert.isTrue(remainingTrackerKeys.some(key => key.split(':')[1] === correlationId2));
4351
- assert.isTrue(remainingWarningKeys.some(key => key.split(':')[1] === correlationId2));
4955
+ assert.isTrue(remainingTrackerKeys.some((key) => key.split(':')[1] === correlationId2));
4956
+ assert.isTrue(remainingWarningKeys.some((key) => key.split(':')[1] === correlationId2));
4352
4957
  });
4353
4958
 
4354
4959
  it('should handle empty correlationId gracefully', () => {
4355
- const options = { meetingId: fakeMeeting.id };
4356
- const payload = { mediaType: 'video' as const };
4960
+ const options = {meetingId: fakeMeeting.id};
4961
+ const payload = {mediaType: 'video' as const};
4357
4962
 
4358
4963
  // Set up some tracking data
4359
4964
  cd.submitClientEvent({
@@ -4381,8 +4986,8 @@ describe('internal-plugin-metrics', () => {
4381
4986
  });
4382
4987
 
4383
4988
  it('should handle non-existent correlationId gracefully', () => {
4384
- const options = { meetingId: fakeMeeting.id };
4385
- const payload = { mediaType: 'video' as const };
4989
+ const options = {meetingId: fakeMeeting.id};
4990
+ const payload = {mediaType: 'video' as const};
4386
4991
 
4387
4992
  // Set up some tracking data
4388
4993
  cd.submitClientEvent({
@@ -4403,10 +5008,10 @@ describe('internal-plugin-metrics', () => {
4403
5008
 
4404
5009
  it('should clear multiple event types for the same correlationId', () => {
4405
5010
  const correlationId = fakeMeeting.correlationId;
4406
- const options = { meetingId: fakeMeeting.id };
4407
- const videoPayload = { mediaType: 'video' as const };
4408
- const audioPayload = { mediaType: 'audio' as const };
4409
- const roapPayload = { roap: { messageType: 'OFFER' as const } };
5011
+ const options = {meetingId: fakeMeeting.id};
5012
+ const videoPayload = {mediaType: 'video' as const};
5013
+ const audioPayload = {mediaType: 'audio' as const};
5014
+ const roapPayload = {roap: {messageType: 'OFFER' as const}};
4410
5015
 
4411
5016
  // Set up multiple event types for the same correlation
4412
5017
  cd.submitClientEvent({
@@ -4459,8 +5064,8 @@ describe('internal-plugin-metrics', () => {
4459
5064
 
4460
5065
  it('should allow events to be sent again after clearing limits for correlationId', () => {
4461
5066
  const correlationId = fakeMeeting.correlationId;
4462
- const options = { meetingId: fakeMeeting.id };
4463
- const payload = { mediaType: 'video' as const };
5067
+ const options = {meetingId: fakeMeeting.id};
5068
+ const payload = {mediaType: 'video' as const};
4464
5069
  const submitToCallDiagnosticsStub = sinon.stub(cd, 'submitToCallDiagnostics');
4465
5070
 
4466
5071
  // Send first event (should succeed)