@webex/contact-center 0.0.0-next.1
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/README.md +81 -0
- package/__mocks__/workerMock.js +15 -0
- package/babel.config.js +15 -0
- package/dist/cc.js +1416 -0
- package/dist/cc.js.map +1 -0
- package/dist/config.js +72 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.js +58 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.js +142 -0
- package/dist/index.js.map +1 -0
- package/dist/logger-proxy.js +115 -0
- package/dist/logger-proxy.js.map +1 -0
- package/dist/metrics/MetricsManager.js +474 -0
- package/dist/metrics/MetricsManager.js.map +1 -0
- package/dist/metrics/behavioral-events.js +322 -0
- package/dist/metrics/behavioral-events.js.map +1 -0
- package/dist/metrics/constants.js +134 -0
- package/dist/metrics/constants.js.map +1 -0
- package/dist/services/WebCallingService.js +323 -0
- package/dist/services/WebCallingService.js.map +1 -0
- package/dist/services/agent/index.js +177 -0
- package/dist/services/agent/index.js.map +1 -0
- package/dist/services/agent/types.js +137 -0
- package/dist/services/agent/types.js.map +1 -0
- package/dist/services/config/Util.js +203 -0
- package/dist/services/config/Util.js.map +1 -0
- package/dist/services/config/constants.js +221 -0
- package/dist/services/config/constants.js.map +1 -0
- package/dist/services/config/index.js +607 -0
- package/dist/services/config/index.js.map +1 -0
- package/dist/services/config/types.js +334 -0
- package/dist/services/config/types.js.map +1 -0
- package/dist/services/constants.js +117 -0
- package/dist/services/constants.js.map +1 -0
- package/dist/services/core/Err.js +43 -0
- package/dist/services/core/Err.js.map +1 -0
- package/dist/services/core/GlobalTypes.js +6 -0
- package/dist/services/core/GlobalTypes.js.map +1 -0
- package/dist/services/core/Utils.js +126 -0
- package/dist/services/core/Utils.js.map +1 -0
- package/dist/services/core/WebexRequest.js +96 -0
- package/dist/services/core/WebexRequest.js.map +1 -0
- package/dist/services/core/aqm-reqs.js +246 -0
- package/dist/services/core/aqm-reqs.js.map +1 -0
- package/dist/services/core/constants.js +109 -0
- package/dist/services/core/constants.js.map +1 -0
- package/dist/services/core/types.js +6 -0
- package/dist/services/core/types.js.map +1 -0
- package/dist/services/core/websocket/WebSocketManager.js +187 -0
- package/dist/services/core/websocket/WebSocketManager.js.map +1 -0
- package/dist/services/core/websocket/connection-service.js +111 -0
- package/dist/services/core/websocket/connection-service.js.map +1 -0
- package/dist/services/core/websocket/keepalive.worker.js +94 -0
- package/dist/services/core/websocket/keepalive.worker.js.map +1 -0
- package/dist/services/core/websocket/types.js +6 -0
- package/dist/services/core/websocket/types.js.map +1 -0
- package/dist/services/index.js +78 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/task/AutoWrapup.js +88 -0
- package/dist/services/task/AutoWrapup.js.map +1 -0
- package/dist/services/task/TaskManager.js +369 -0
- package/dist/services/task/TaskManager.js.map +1 -0
- package/dist/services/task/constants.js +58 -0
- package/dist/services/task/constants.js.map +1 -0
- package/dist/services/task/contact.js +464 -0
- package/dist/services/task/contact.js.map +1 -0
- package/dist/services/task/dialer.js +60 -0
- package/dist/services/task/dialer.js.map +1 -0
- package/dist/services/task/index.js +1188 -0
- package/dist/services/task/index.js.map +1 -0
- package/dist/services/task/types.js +214 -0
- package/dist/services/task/types.js.map +1 -0
- package/dist/types/cc.d.ts +676 -0
- package/dist/types/config.d.ts +66 -0
- package/dist/types/constants.d.ts +45 -0
- package/dist/types/index.d.ts +178 -0
- package/dist/types/logger-proxy.d.ts +71 -0
- package/dist/types/metrics/MetricsManager.d.ts +223 -0
- package/dist/types/metrics/behavioral-events.d.ts +29 -0
- package/dist/types/metrics/constants.d.ts +127 -0
- package/dist/types/services/WebCallingService.d.ts +1 -0
- package/dist/types/services/agent/index.d.ts +46 -0
- package/dist/types/services/agent/types.d.ts +413 -0
- package/dist/types/services/config/Util.d.ts +19 -0
- package/dist/types/services/config/constants.d.ts +203 -0
- package/dist/types/services/config/index.d.ts +171 -0
- package/dist/types/services/config/types.d.ts +1113 -0
- package/dist/types/services/constants.d.ts +97 -0
- package/dist/types/services/core/Err.d.ts +119 -0
- package/dist/types/services/core/GlobalTypes.d.ts +33 -0
- package/dist/types/services/core/Utils.d.ts +36 -0
- package/dist/types/services/core/WebexRequest.d.ts +22 -0
- package/dist/types/services/core/aqm-reqs.d.ts +16 -0
- package/dist/types/services/core/constants.d.ts +85 -0
- package/dist/types/services/core/types.d.ts +47 -0
- package/dist/types/services/core/websocket/WebSocketManager.d.ts +34 -0
- package/dist/types/services/core/websocket/connection-service.d.ts +27 -0
- package/dist/types/services/core/websocket/keepalive.worker.d.ts +2 -0
- package/dist/types/services/core/websocket/types.d.ts +37 -0
- package/dist/types/services/index.d.ts +52 -0
- package/dist/types/services/task/AutoWrapup.d.ts +40 -0
- package/dist/types/services/task/TaskManager.d.ts +1 -0
- package/dist/types/services/task/constants.d.ts +46 -0
- package/dist/types/services/task/contact.d.ts +59 -0
- package/dist/types/services/task/dialer.d.ts +28 -0
- package/dist/types/services/task/index.d.ts +569 -0
- package/dist/types/services/task/types.d.ts +1041 -0
- package/dist/types/types.d.ts +452 -0
- package/dist/types/webex-config.d.ts +53 -0
- package/dist/types/webex.d.ts +7 -0
- package/dist/types.js +292 -0
- package/dist/types.js.map +1 -0
- package/dist/webex-config.js +60 -0
- package/dist/webex-config.js.map +1 -0
- package/dist/webex.js +99 -0
- package/dist/webex.js.map +1 -0
- package/jest.config.js +45 -0
- package/package.json +83 -0
- package/src/cc.ts +1618 -0
- package/src/config.ts +65 -0
- package/src/constants.ts +51 -0
- package/src/index.ts +220 -0
- package/src/logger-proxy.ts +110 -0
- package/src/metrics/MetricsManager.ts +512 -0
- package/src/metrics/behavioral-events.ts +332 -0
- package/src/metrics/constants.ts +135 -0
- package/src/services/WebCallingService.ts +351 -0
- package/src/services/agent/index.ts +149 -0
- package/src/services/agent/types.ts +440 -0
- package/src/services/config/Util.ts +261 -0
- package/src/services/config/constants.ts +249 -0
- package/src/services/config/index.ts +743 -0
- package/src/services/config/types.ts +1117 -0
- package/src/services/constants.ts +111 -0
- package/src/services/core/Err.ts +126 -0
- package/src/services/core/GlobalTypes.ts +34 -0
- package/src/services/core/Utils.ts +132 -0
- package/src/services/core/WebexRequest.ts +103 -0
- package/src/services/core/aqm-reqs.ts +272 -0
- package/src/services/core/constants.ts +106 -0
- package/src/services/core/types.ts +48 -0
- package/src/services/core/websocket/WebSocketManager.ts +196 -0
- package/src/services/core/websocket/connection-service.ts +142 -0
- package/src/services/core/websocket/keepalive.worker.js +88 -0
- package/src/services/core/websocket/types.ts +40 -0
- package/src/services/index.ts +71 -0
- package/src/services/task/AutoWrapup.ts +86 -0
- package/src/services/task/TaskManager.ts +420 -0
- package/src/services/task/constants.ts +52 -0
- package/src/services/task/contact.ts +429 -0
- package/src/services/task/dialer.ts +52 -0
- package/src/services/task/index.ts +1375 -0
- package/src/services/task/types.ts +1113 -0
- package/src/types.ts +639 -0
- package/src/webex-config.ts +54 -0
- package/src/webex.js +96 -0
- package/test/unit/spec/cc.ts +1985 -0
- package/test/unit/spec/metrics/MetricsManager.ts +491 -0
- package/test/unit/spec/metrics/behavioral-events.ts +102 -0
- package/test/unit/spec/services/WebCallingService.ts +416 -0
- package/test/unit/spec/services/agent/index.ts +65 -0
- package/test/unit/spec/services/config/index.ts +1035 -0
- package/test/unit/spec/services/core/Utils.ts +279 -0
- package/test/unit/spec/services/core/WebexRequest.ts +144 -0
- package/test/unit/spec/services/core/aqm-reqs.ts +570 -0
- package/test/unit/spec/services/core/websocket/WebSocketManager.ts +378 -0
- package/test/unit/spec/services/core/websocket/connection-service.ts +178 -0
- package/test/unit/spec/services/task/TaskManager.ts +1351 -0
- package/test/unit/spec/services/task/contact.ts +204 -0
- package/test/unit/spec/services/task/dialer.ts +157 -0
- package/test/unit/spec/services/task/index.ts +1474 -0
- package/tsconfig.json +6 -0
- package/typedoc.json +37 -0
- package/typedoc.md +240 -0
- package/umd/contact-center.min.js +3 -0
- package/umd/contact-center.min.js.map +1 -0
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
import {PRODUCT_NAME} from '../../../../src/constants';
|
|
2
|
+
import MetricsManager from '../../../../src/metrics/MetricsManager';
|
|
3
|
+
import {METRIC_EVENT_NAMES} from '../../../../src/metrics/constants';
|
|
4
|
+
import {WebexSDK} from '../../../../src/types';
|
|
5
|
+
import {EventPayload} from '@webex/internal-plugin-metrics/src/metrics.types';
|
|
6
|
+
import LoggerProxy from '../../../../src/logger-proxy';
|
|
7
|
+
|
|
8
|
+
describe('MetricsManagerImplementation', () => {
|
|
9
|
+
let webex: WebexSDK;
|
|
10
|
+
let metricsManager: MetricsManager;
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
webex = {
|
|
14
|
+
internal: {
|
|
15
|
+
newMetrics: {
|
|
16
|
+
submitBehavioralEvent: jest.fn(),
|
|
17
|
+
submitOperationalEvent: jest.fn(),
|
|
18
|
+
submitBusinessEvent: jest.fn(),
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
once: jest.fn(),
|
|
22
|
+
ready: true,
|
|
23
|
+
} as unknown as WebexSDK;
|
|
24
|
+
|
|
25
|
+
MetricsManager.resetInstance();
|
|
26
|
+
metricsManager = MetricsManager.getInstance({webex});
|
|
27
|
+
metricsManager.setMetricsDisabled(false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
jest.clearAllMocks();
|
|
32
|
+
jest.resetAllMocks();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('trackEvent', () => {
|
|
36
|
+
it('should submit a behavioral, operational and business event when newMetrics is available', () => {
|
|
37
|
+
const eventName = METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS;
|
|
38
|
+
const data: EventPayload = {key: 'value'};
|
|
39
|
+
|
|
40
|
+
metricsManager.trackEvent(eventName, data, ['behavioral', 'operational', 'business']);
|
|
41
|
+
|
|
42
|
+
expect(webex.internal.newMetrics.submitBehavioralEvent).toHaveBeenCalledTimes(1);
|
|
43
|
+
expect(webex.internal.newMetrics.submitOperationalEvent).toHaveBeenCalledTimes(1);
|
|
44
|
+
expect(webex.internal.newMetrics.submitBusinessEvent).toHaveBeenCalledTimes(1);
|
|
45
|
+
|
|
46
|
+
expect(webex.internal.newMetrics.submitBehavioralEvent).toHaveBeenCalledWith({
|
|
47
|
+
product: PRODUCT_NAME,
|
|
48
|
+
agent: 'user',
|
|
49
|
+
target: 'station_login',
|
|
50
|
+
verb: 'complete',
|
|
51
|
+
payload: data,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
expect(webex.internal.newMetrics.submitOperationalEvent).toHaveBeenCalledWith({
|
|
55
|
+
name: PRODUCT_NAME.toUpperCase() + "_" + METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS.replace(/ /g, '_').toUpperCase(),
|
|
56
|
+
payload: data,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
expect(webex.internal.newMetrics.submitBusinessEvent).toHaveBeenCalledWith({
|
|
60
|
+
name: PRODUCT_NAME.toUpperCase() + "_" + METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS.replace(/ /g, '_').toUpperCase(),
|
|
61
|
+
payload: data,
|
|
62
|
+
metadata: {
|
|
63
|
+
appType: PRODUCT_NAME,
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should not submit a behavioral, operational and business event if array is invalid', () => {
|
|
69
|
+
const eventName = METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS;
|
|
70
|
+
const data: EventPayload = {key: 'value'};
|
|
71
|
+
|
|
72
|
+
metricsManager.trackEvent(eventName, data, ['nonexistent']);
|
|
73
|
+
|
|
74
|
+
expect(webex.internal.newMetrics.submitBehavioralEvent).toHaveBeenCalledTimes(0);
|
|
75
|
+
expect(webex.internal.newMetrics.submitOperationalEvent).toHaveBeenCalledTimes(0);
|
|
76
|
+
expect(webex.internal.newMetrics.submitBusinessEvent).toHaveBeenCalledTimes(0);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should not submit a behavioral, operational and business event if metricsDisabled is true', () => {
|
|
80
|
+
const eventName = METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS;
|
|
81
|
+
const data: EventPayload = {key: 'value'};
|
|
82
|
+
|
|
83
|
+
metricsManager.setMetricsDisabled(true);
|
|
84
|
+
metricsManager.trackEvent(eventName, data, ['behavioral', 'operational', 'business']);
|
|
85
|
+
|
|
86
|
+
expect(webex.internal.newMetrics.submitBehavioralEvent).toHaveBeenCalledTimes(0);
|
|
87
|
+
expect(webex.internal.newMetrics.submitOperationalEvent).toHaveBeenCalledTimes(0);
|
|
88
|
+
expect(webex.internal.newMetrics.submitBusinessEvent).toHaveBeenCalledTimes(0);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should not submit a behavioral event if metricsDisabled is true', () => {
|
|
92
|
+
const eventName = METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS;
|
|
93
|
+
const data: EventPayload = {key: 'value'};
|
|
94
|
+
|
|
95
|
+
metricsManager.setMetricsDisabled(true);
|
|
96
|
+
metricsManager.trackBehavioralEvent(eventName, data);
|
|
97
|
+
|
|
98
|
+
expect(webex.internal.newMetrics.submitBehavioralEvent).toHaveBeenCalledTimes(0);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should not submit a operational event if metricsDisabled is true', () => {
|
|
102
|
+
const eventName = METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS;
|
|
103
|
+
const data: EventPayload = {key: 'value'};
|
|
104
|
+
|
|
105
|
+
metricsManager.setMetricsDisabled(true);
|
|
106
|
+
metricsManager.trackOperationalEvent(eventName, data);
|
|
107
|
+
|
|
108
|
+
expect(webex.internal.newMetrics.submitOperationalEvent).toHaveBeenCalledTimes(0);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should not submit a business event if metricsDisabled is true', () => {
|
|
112
|
+
const eventName = METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS;
|
|
113
|
+
const data: EventPayload = {key: 'value'};
|
|
114
|
+
|
|
115
|
+
metricsManager.setMetricsDisabled(true);
|
|
116
|
+
metricsManager.trackBusinessEvent(eventName, data);
|
|
117
|
+
|
|
118
|
+
expect(webex.internal.newMetrics.submitBusinessEvent).toHaveBeenCalledTimes(0);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe('clearPendingEvents', () => {
|
|
123
|
+
it('should clear pending events', () => {
|
|
124
|
+
metricsManager['pendingBehavioralEvents'] = [
|
|
125
|
+
{taxonomy: {product: 'wxcc_sdk', agent: 'user', target: 'test', verb: 'get'}, payload: {}},
|
|
126
|
+
];
|
|
127
|
+
metricsManager['pendingOperationalEvents'] = [{name: 'TEST', payload: {}}];
|
|
128
|
+
metricsManager['pendingBusinessEvents'] = [{name: 'TEST', payload: {}}];
|
|
129
|
+
metricsManager['readyToSubmitEvents'] = true;
|
|
130
|
+
metricsManager['submittingEvents'] = true;
|
|
131
|
+
metricsManager['clearPendingEvents']();
|
|
132
|
+
expect(metricsManager['pendingBehavioralEvents']).toEqual([]);
|
|
133
|
+
expect(metricsManager['pendingOperationalEvents']).toEqual([]);
|
|
134
|
+
expect(metricsManager['pendingBusinessEvents']).toEqual([]);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
describe('setMetricsDisabled', () => {
|
|
139
|
+
it('should set metricsDisabled to true', () => {
|
|
140
|
+
const clearPendingEventsSpy = jest.spyOn(
|
|
141
|
+
MetricsManager.prototype as any,
|
|
142
|
+
'clearPendingEvents'
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
metricsManager.setMetricsDisabled(true);
|
|
146
|
+
|
|
147
|
+
expect(clearPendingEventsSpy).toHaveBeenCalled();
|
|
148
|
+
expect(metricsManager['metricsDisabled']).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
describe('submitPendingEvents', () => {
|
|
153
|
+
it('should return if submittingEvents is true', async () => {
|
|
154
|
+
metricsManager['submittingEvents'] = true;
|
|
155
|
+
await metricsManager['submitPendingEvents']();
|
|
156
|
+
expect(webex.internal.newMetrics.submitBehavioralEvent).toHaveBeenCalledTimes(0);
|
|
157
|
+
expect(webex.internal.newMetrics.submitOperationalEvent).toHaveBeenCalledTimes(0);
|
|
158
|
+
expect(webex.internal.newMetrics.submitBusinessEvent).toHaveBeenCalledTimes(0);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should submit pending events if there are any', async () => {
|
|
162
|
+
metricsManager['pendingBehavioralEvents'] = [
|
|
163
|
+
{taxonomy: {product: 'wxcc_sdk', agent: 'user', target: 'test', verb: 'get'}, payload: {}},
|
|
164
|
+
];
|
|
165
|
+
metricsManager['pendingOperationalEvents'] = [{name: 'TEST', payload: {}}];
|
|
166
|
+
metricsManager['pendingBusinessEvents'] = [{name: 'TEST', payload: {}}];
|
|
167
|
+
metricsManager['readyToSubmitEvents'] = true;
|
|
168
|
+
|
|
169
|
+
await metricsManager['submitPendingEvents']();
|
|
170
|
+
|
|
171
|
+
expect(webex.internal.newMetrics.submitBehavioralEvent).toHaveBeenCalledTimes(1);
|
|
172
|
+
expect(webex.internal.newMetrics.submitOperationalEvent).toHaveBeenCalledTimes(1);
|
|
173
|
+
expect(webex.internal.newMetrics.submitBusinessEvent).toHaveBeenCalledTimes(1);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('should not submit events if there are none', async () => {
|
|
177
|
+
metricsManager['pendingBehavioralEvents'] = [];
|
|
178
|
+
metricsManager['pendingOperationalEvents'] = [];
|
|
179
|
+
metricsManager['pendingBusinessEvents'] = [];
|
|
180
|
+
metricsManager['readyToSubmitEvents'] = true;
|
|
181
|
+
|
|
182
|
+
await metricsManager['submitPendingEvents']();
|
|
183
|
+
|
|
184
|
+
expect(webex.internal.newMetrics.submitBehavioralEvent).toHaveBeenCalledTimes(0);
|
|
185
|
+
expect(webex.internal.newMetrics.submitOperationalEvent).toHaveBeenCalledTimes(0);
|
|
186
|
+
expect(webex.internal.newMetrics.submitBusinessEvent).toHaveBeenCalledTimes(0);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
describe('getInstance', () => {
|
|
191
|
+
it('should return the same instance', () => {
|
|
192
|
+
const instance1 = MetricsManager.getInstance({webex});
|
|
193
|
+
const instance2 = MetricsManager.getInstance({webex});
|
|
194
|
+
|
|
195
|
+
expect(instance1).toBe(instance2);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('should create a new instance if none exists', () => {
|
|
199
|
+
MetricsManager['instance'] = undefined;
|
|
200
|
+
|
|
201
|
+
const instance = MetricsManager.getInstance({webex});
|
|
202
|
+
|
|
203
|
+
expect(instance).toBeInstanceOf(MetricsManager);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
describe('timeEvent', () => {
|
|
208
|
+
it('should not set the event if metrics are disabled', () => {
|
|
209
|
+
jest.spyOn(MetricsManager.prototype as any, 'isMetricsDisabled').mockReturnValue(true);
|
|
210
|
+
const eventName = 'testEvent';
|
|
211
|
+
|
|
212
|
+
metricsManager.timeEvent(eventName);
|
|
213
|
+
|
|
214
|
+
expect(metricsManager['runningEvents'][eventName]).toBeUndefined();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('should set the event with the current timestamp if metrics are enabled', () => {
|
|
218
|
+
jest.spyOn(MetricsManager.prototype as any, 'isMetricsDisabled').mockReturnValue(false);
|
|
219
|
+
const eventName = 'testEvent';
|
|
220
|
+
const mockTimestamp = 1234567890;
|
|
221
|
+
jest.spyOn(Date, 'now').mockReturnValue(mockTimestamp);
|
|
222
|
+
|
|
223
|
+
metricsManager.timeEvent(eventName);
|
|
224
|
+
|
|
225
|
+
expect(metricsManager['runningEvents'][eventName]['startTime']).toBe(mockTimestamp);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('should set the event with the current timestamp if a single event name is provided and metrics are enabled', () => {
|
|
229
|
+
jest.spyOn(MetricsManager.prototype as any, 'isMetricsDisabled').mockReturnValue(false);
|
|
230
|
+
const eventName = 'testEvent';
|
|
231
|
+
const mockTimestamp = 1234567890;
|
|
232
|
+
jest.spyOn(Date, 'now').mockReturnValue(mockTimestamp);
|
|
233
|
+
metricsManager.timeEvent(eventName);
|
|
234
|
+
|
|
235
|
+
expect(metricsManager['runningEvents'][eventName]).toEqual({
|
|
236
|
+
startTime: mockTimestamp,
|
|
237
|
+
keys: new Set([eventName]),
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('should set the event with an array of keys when metrics are enabled', () => {
|
|
242
|
+
jest.spyOn(MetricsManager.prototype as any, 'isMetricsDisabled').mockReturnValue(false);
|
|
243
|
+
const eventArray = ['eventSuccess', 'eventFailed'];
|
|
244
|
+
const mockTimestamp = 987654321;
|
|
245
|
+
jest.spyOn(Date, 'now').mockReturnValue(mockTimestamp);
|
|
246
|
+
metricsManager.timeEvent(eventArray);
|
|
247
|
+
|
|
248
|
+
// The generic key is the first element of the array.
|
|
249
|
+
expect(metricsManager['runningEvents'][eventArray[0]]).toEqual({
|
|
250
|
+
startTime: mockTimestamp,
|
|
251
|
+
keys: new Set(eventArray),
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
describe('addDurationIfTimed', () => {
|
|
257
|
+
it('should return options when event name is not in runningEvents', () => {
|
|
258
|
+
const options: EventPayload = {key: 'value'};
|
|
259
|
+
const result = metricsManager['addDurationIfTimed']('event1', options);
|
|
260
|
+
expect(result).toEqual(options);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('should add duration to options when event name is in runningEvents and options is provided', () => {
|
|
264
|
+
metricsManager['runningEvents']['event1'] = {
|
|
265
|
+
startTime: 500,
|
|
266
|
+
keys: new Set(['event1']),
|
|
267
|
+
};
|
|
268
|
+
jest.spyOn(Date, 'now').mockImplementation(() => 1000);
|
|
269
|
+
const options: EventPayload = {key: 'value'};
|
|
270
|
+
const result = metricsManager['addDurationIfTimed']('event1', options);
|
|
271
|
+
expect(result).toEqual({key: 'value', duration_ms: 500});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('should create a new payload with duration when event name is in runningEvents and options is not provided', () => {
|
|
275
|
+
metricsManager['runningEvents']['event1'] = {
|
|
276
|
+
startTime: 500,
|
|
277
|
+
keys: new Set(['event1']),
|
|
278
|
+
};
|
|
279
|
+
jest.spyOn(Date, 'now').mockImplementation(() => 1000);
|
|
280
|
+
const result = metricsManager['addDurationIfTimed']('event1');
|
|
281
|
+
expect(result).toEqual({duration_ms: 500});
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it('should return options when options is provided but event name is not in runningEvents', () => {
|
|
285
|
+
const options: EventPayload = {key: 'value'};
|
|
286
|
+
jest.spyOn(Date, 'now').mockImplementation(() => 1000);
|
|
287
|
+
const result = metricsManager['addDurationIfTimed']('event2', options);
|
|
288
|
+
expect(result).toEqual(options);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('should return an empty object when neither options is provided nor event name is in runningEvents', () => {
|
|
292
|
+
const result = metricsManager['addDurationIfTimed']('event3');
|
|
293
|
+
expect(result).toEqual({});
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
describe('MetricsManagerInstantiation', () => {
|
|
299
|
+
let webexMock: WebexSDK;
|
|
300
|
+
|
|
301
|
+
beforeEach(() => {
|
|
302
|
+
MetricsManager.resetInstance();
|
|
303
|
+
webexMock = {
|
|
304
|
+
once: jest.fn(),
|
|
305
|
+
internal: {
|
|
306
|
+
newMetrics: {
|
|
307
|
+
submitBehavioralEvent: jest.fn(),
|
|
308
|
+
submitOperationalEvent: jest.fn(),
|
|
309
|
+
submitBusinessEvent: jest.fn(),
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
ready: false,
|
|
313
|
+
} as unknown as WebexSDK;
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
afterEach(() => {
|
|
317
|
+
jest.clearAllMocks();
|
|
318
|
+
jest.resetAllMocks();
|
|
319
|
+
MetricsManager.resetInstance();
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
afterAll(() => {
|
|
323
|
+
jest.clearAllMocks();
|
|
324
|
+
jest.resetAllMocks();
|
|
325
|
+
MetricsManager.resetInstance();
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
it('should call setReadyToSubmitEvents if webex is ready', () => {
|
|
329
|
+
webexMock.ready = true;
|
|
330
|
+
const setReadyToSubmitEventsSpy = jest.spyOn(
|
|
331
|
+
MetricsManager.prototype as any,
|
|
332
|
+
'setReadyToSubmitEvents'
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
MetricsManager.getInstance({webex: webexMock});
|
|
336
|
+
|
|
337
|
+
expect(setReadyToSubmitEventsSpy).toHaveBeenCalled();
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('should call setReadyToSubmitEvents when webex emits ready event', () => {
|
|
341
|
+
webexMock.ready = false;
|
|
342
|
+
const setReadyToSubmitEventsSpy = jest.spyOn(
|
|
343
|
+
MetricsManager.prototype as any,
|
|
344
|
+
'setReadyToSubmitEvents'
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
MetricsManager.getInstance({webex: webexMock});
|
|
348
|
+
expect(webexMock.once).toHaveBeenCalledWith('ready', expect.any(Function));
|
|
349
|
+
const readyCallback = (webexMock.once as jest.Mock).mock.calls[0][1];
|
|
350
|
+
readyCallback();
|
|
351
|
+
|
|
352
|
+
expect(setReadyToSubmitEventsSpy).toHaveBeenCalled();
|
|
353
|
+
webexMock.ready = true;
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('should store metrics in queue when instantiated without webex and later emit metrics when webex is provided', () => {
|
|
357
|
+
|
|
358
|
+
const instance = MetricsManager.getInstance();
|
|
359
|
+
expect(instance).toBeDefined();
|
|
360
|
+
expect(instance['pendingBehavioralEvents'].length).toBe(0);
|
|
361
|
+
instance.trackEvent(METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS, {key: 'value'}, ['behavioral']);
|
|
362
|
+
expect(instance['pendingBehavioralEvents'].length).toBe(1);
|
|
363
|
+
|
|
364
|
+
const setReadyToSubmitEventsSpy = jest.spyOn(
|
|
365
|
+
MetricsManager.prototype as any,
|
|
366
|
+
'setReadyToSubmitEvents'
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
MetricsManager.getInstance({webex: webexMock});
|
|
370
|
+
expect(webexMock.once).toHaveBeenCalledWith('ready', expect.any(Function));
|
|
371
|
+
const readyCallback = (webexMock.once as jest.Mock).mock.calls[0][1];
|
|
372
|
+
readyCallback();
|
|
373
|
+
|
|
374
|
+
expect(setReadyToSubmitEventsSpy).toHaveBeenCalled();
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
describe('getCommonTrackingFieldForAQMResponse', () => {
|
|
379
|
+
it('should extract common tracking fields from a response with nested data', () => {
|
|
380
|
+
const response = {
|
|
381
|
+
data: {
|
|
382
|
+
agentId: 'agent1',
|
|
383
|
+
agentSessionId: 'session1',
|
|
384
|
+
teamId: 'team1',
|
|
385
|
+
siteId: 'site1',
|
|
386
|
+
orgId: 'org1',
|
|
387
|
+
trackingId: 'track1'
|
|
388
|
+
},
|
|
389
|
+
trackingId: 'notifTrack1',
|
|
390
|
+
type: 'some_event'
|
|
391
|
+
};
|
|
392
|
+
const expected = {
|
|
393
|
+
agentId: 'agent1',
|
|
394
|
+
agentSessionId: 'session1',
|
|
395
|
+
teamId: 'team1',
|
|
396
|
+
siteId: 'site1',
|
|
397
|
+
orgId: 'org1',
|
|
398
|
+
eventType: 'some_event',
|
|
399
|
+
trackingId: 'track1',
|
|
400
|
+
notifTrackingId: 'notifTrack1'
|
|
401
|
+
};
|
|
402
|
+
const result = MetricsManager.getCommonTrackingFieldForAQMResponse(response);
|
|
403
|
+
expect(result).toEqual(expected);
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
it('should extract common tracking fields from a flat response', () => {
|
|
407
|
+
const response = {
|
|
408
|
+
agentId: 'agent2',
|
|
409
|
+
agentSessionId: 'session2',
|
|
410
|
+
teamId: 'team2',
|
|
411
|
+
siteId: 'site2',
|
|
412
|
+
orgId: 'org2',
|
|
413
|
+
type: 'event_type',
|
|
414
|
+
trackingId: 'notifTrack2'
|
|
415
|
+
};
|
|
416
|
+
const expected = {
|
|
417
|
+
agentId: 'agent2',
|
|
418
|
+
agentSessionId: 'session2',
|
|
419
|
+
teamId: 'team2',
|
|
420
|
+
siteId: 'site2',
|
|
421
|
+
orgId: 'org2',
|
|
422
|
+
eventType: 'event_type',
|
|
423
|
+
trackingId: undefined,
|
|
424
|
+
notifTrackingId: 'notifTrack2'
|
|
425
|
+
};
|
|
426
|
+
const result = MetricsManager.getCommonTrackingFieldForAQMResponse(response);
|
|
427
|
+
expect(result).toEqual(expected);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it('should handle responses with missing fields gracefully', () => {
|
|
431
|
+
const response = {};
|
|
432
|
+
const expected = {
|
|
433
|
+
agentId: undefined,
|
|
434
|
+
agentSessionId: undefined,
|
|
435
|
+
teamId: undefined,
|
|
436
|
+
siteId: undefined,
|
|
437
|
+
orgId: undefined,
|
|
438
|
+
eventType: undefined,
|
|
439
|
+
trackingId: undefined,
|
|
440
|
+
notifTrackingId: undefined
|
|
441
|
+
};
|
|
442
|
+
const result = MetricsManager.getCommonTrackingFieldForAQMResponse(response);
|
|
443
|
+
expect(result).toEqual(expected);
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
describe('getCommonTrackingFieldForAQMResponseFailed', () => {
|
|
448
|
+
it('should extract common tracking fields from a failure response with complete fields', () => {
|
|
449
|
+
const failureResponse = {
|
|
450
|
+
data: {
|
|
451
|
+
agentId: 'agent1',
|
|
452
|
+
reason: 'Some reason',
|
|
453
|
+
reasonCode: 'R001'
|
|
454
|
+
},
|
|
455
|
+
trackingId: 'notifTrack1',
|
|
456
|
+
orgId: 'org1',
|
|
457
|
+
type: 'failure_event'
|
|
458
|
+
};
|
|
459
|
+
const expected = {
|
|
460
|
+
agentId: 'agent1',
|
|
461
|
+
trackingId: 'notifTrack1',
|
|
462
|
+
notifTrackingId: 'notifTrack1',
|
|
463
|
+
orgId: 'org1',
|
|
464
|
+
failureType: 'failure_event',
|
|
465
|
+
failureReason: 'Some reason',
|
|
466
|
+
reasonCode: 'R001'
|
|
467
|
+
};
|
|
468
|
+
const result = MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failureResponse);
|
|
469
|
+
expect(result).toEqual(expected);
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it('should handle failure responses with missing fields gracefully', () => {
|
|
473
|
+
const failureResponse = {
|
|
474
|
+
data: {},
|
|
475
|
+
trackingId: undefined,
|
|
476
|
+
orgId: 'org2',
|
|
477
|
+
type: undefined
|
|
478
|
+
};
|
|
479
|
+
const expected = {
|
|
480
|
+
agentId: undefined,
|
|
481
|
+
trackingId: undefined,
|
|
482
|
+
notifTrackingId: undefined,
|
|
483
|
+
orgId: 'org2',
|
|
484
|
+
failureType: undefined,
|
|
485
|
+
failureReason: undefined,
|
|
486
|
+
reasonCode: undefined
|
|
487
|
+
};
|
|
488
|
+
const result = MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failureResponse);
|
|
489
|
+
expect(result).toEqual(expected);
|
|
490
|
+
});
|
|
491
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import {PRODUCT_NAME as product} from '../../../../src/constants';
|
|
2
|
+
import {getEventTaxonomy} from '../../../../src/metrics/behavioral-events';
|
|
3
|
+
import {METRIC_EVENT_NAMES} from '../../../../src/metrics/constants';
|
|
4
|
+
|
|
5
|
+
describe('metrics/behavioral-events', () => {
|
|
6
|
+
describe('getEventTaxonomy', () => {
|
|
7
|
+
it('returns the correct taxonomy for the given event', () => {
|
|
8
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.AGENT_RONA)).toEqual({
|
|
9
|
+
product,
|
|
10
|
+
agent: 'service',
|
|
11
|
+
target: 'agent_rona',
|
|
12
|
+
verb: 'set',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS)).toEqual({
|
|
16
|
+
product,
|
|
17
|
+
agent: 'user',
|
|
18
|
+
target: 'station_login',
|
|
19
|
+
verb: 'complete',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.STATION_LOGIN_FAILED)).toEqual({
|
|
23
|
+
product,
|
|
24
|
+
agent: 'user',
|
|
25
|
+
target: 'station_login',
|
|
26
|
+
verb: 'fail',
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.STATION_LOGOUT_SUCCESS)).toEqual({
|
|
30
|
+
product,
|
|
31
|
+
agent: 'user',
|
|
32
|
+
target: 'station_logout',
|
|
33
|
+
verb: 'complete',
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.STATION_LOGOUT_FAILED)).toEqual({
|
|
37
|
+
product,
|
|
38
|
+
agent: 'user',
|
|
39
|
+
target: 'station_logout',
|
|
40
|
+
verb: 'fail',
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.STATION_RELOGIN_SUCCESS)).toEqual({
|
|
44
|
+
product,
|
|
45
|
+
agent: 'user',
|
|
46
|
+
target: 'station_relogin',
|
|
47
|
+
verb: 'complete',
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.STATION_RELOGIN_FAILED)).toEqual({
|
|
51
|
+
product,
|
|
52
|
+
agent: 'user',
|
|
53
|
+
target: 'station_relogin',
|
|
54
|
+
verb: 'fail',
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.AGENT_STATE_CHANGE_SUCCESS)).toEqual({
|
|
58
|
+
product,
|
|
59
|
+
agent: 'user',
|
|
60
|
+
target: 'state_change',
|
|
61
|
+
verb: 'complete',
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.AGENT_STATE_CHANGE_FAILED)).toEqual({
|
|
65
|
+
product,
|
|
66
|
+
agent: 'user',
|
|
67
|
+
target: 'state_change',
|
|
68
|
+
verb: 'fail',
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.FETCH_BUDDY_AGENTS_SUCCESS)).toEqual({
|
|
72
|
+
product,
|
|
73
|
+
agent: 'user',
|
|
74
|
+
target: 'buddy_agents_fetch',
|
|
75
|
+
verb: 'complete',
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.FETCH_BUDDY_AGENTS_FAILED)).toEqual({
|
|
79
|
+
product,
|
|
80
|
+
agent: 'user',
|
|
81
|
+
target: 'buddy_agents_fetch',
|
|
82
|
+
verb: 'fail',
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.WEBSOCKET_REGISTER_SUCCESS)).toEqual({
|
|
86
|
+
product,
|
|
87
|
+
agent: 'user',
|
|
88
|
+
target: 'websocket_register',
|
|
89
|
+
verb: 'complete',
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
expect(getEventTaxonomy(METRIC_EVENT_NAMES.WEBSOCKET_REGISTER_FAILED)).toEqual({
|
|
93
|
+
product,
|
|
94
|
+
agent: 'user',
|
|
95
|
+
target: 'websocket_register',
|
|
96
|
+
verb: 'fail',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
expect(getEventTaxonomy('' as METRIC_EVENT_NAMES)).toEqual(undefined);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|