@microsoft/omnichannel-chat-widget 1.5.1-main.132e1c6 → 1.5.1-main.b37ad3d
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/lib/cjs/common/Constants.js +10 -8
- package/lib/cjs/common/telemetry/TelemetryConstants.js +0 -2
- package/lib/cjs/common/utils.js +2 -1
- package/lib/cjs/components/livechatwidget/common/chatDisconnectHelper.js +31 -16
- package/lib/cjs/components/livechatwidget/common/endChat.js +16 -4
- package/lib/cjs/components/livechatwidget/common/startChat.js +19 -80
- package/lib/cjs/components/livechatwidget/common/startChatErrorHandler.js +198 -0
- package/lib/cjs/components/livechatwidget/common/startChatErrorHandler.spec.js +282 -0
- package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +2 -10
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +0 -8
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.spec.js +1 -1
- package/lib/esm/common/Constants.js +7 -6
- package/lib/esm/common/telemetry/TelemetryConstants.js +0 -2
- package/lib/esm/common/utils.js +3 -2
- package/lib/esm/components/livechatwidget/common/chatDisconnectHelper.js +31 -16
- package/lib/esm/components/livechatwidget/common/endChat.js +14 -3
- package/lib/esm/components/livechatwidget/common/startChat.js +20 -81
- package/lib/esm/components/livechatwidget/common/startChatErrorHandler.js +191 -0
- package/lib/esm/components/livechatwidget/common/startChatErrorHandler.spec.js +280 -0
- package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +3 -11
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +0 -8
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.spec.js +1 -1
- package/lib/types/common/Constants.d.ts +8 -4
- package/lib/types/common/telemetry/TelemetryConstants.d.ts +0 -1
- package/lib/types/components/livechatwidget/common/endChat.d.ts +4 -3
- package/lib/types/components/livechatwidget/common/startChatErrorHandler.d.ts +5 -0
- package/lib/types/components/livechatwidget/common/startChatErrorHandler.spec.d.ts +1 -0
- package/package.json +3 -3
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
|
|
2
|
-
import {
|
|
2
|
+
import { Constants, LiveWorkItemState, WidgetLoadCustomErrorString, WidgetLoadTelemetryMessage } from "../../../common/Constants";
|
|
3
3
|
import { checkContactIdError, createTimer, getConversationDetailsCall, getStateFromCache, getWidgetCacheIdfromProps, isNullOrEmptyString, isUndefinedOrEmpty } from "../../../common/utils";
|
|
4
4
|
import { getAuthClientFunction, handleAuthentication } from "./authHelper";
|
|
5
5
|
import { ActivityStreamHandler } from "./ActivityStreamHandler";
|
|
6
6
|
import { BroadcastService } from "@microsoft/omnichannel-chat-components";
|
|
7
7
|
import { ConversationState } from "../../../contexts/common/ConversationState";
|
|
8
8
|
import { LiveChatWidgetActionType } from "../../../contexts/common/LiveChatWidgetActionType";
|
|
9
|
-
import { NotificationHandler } from "../../webchatcontainerstateful/webchatcontroller/notification/NotificationHandler";
|
|
10
|
-
import { NotificationScenarios } from "../../webchatcontainerstateful/webchatcontroller/enums/NotificationScenarios";
|
|
11
9
|
import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
|
|
12
10
|
import { TelemetryTimers } from "../../../common/telemetry/TelemetryManager";
|
|
13
11
|
import { createAdapter } from "./createAdapter";
|
|
@@ -15,6 +13,8 @@ import { createOnNewAdapterActivityHandler } from "../../../plugins/newMessageEv
|
|
|
15
13
|
import { handleChatReconnect, isPersistentEnabled, isReconnectEnabled } from "./reconnectChatHelper";
|
|
16
14
|
import { setPostChatContextAndLoadSurvey } from "./setPostChatContextAndLoadSurvey";
|
|
17
15
|
import { updateSessionDataForTelemetry } from "./updateSessionDataForTelemetry";
|
|
16
|
+
import { logWidgetLoadComplete, handleStartChatError } from "./startChatErrorHandler";
|
|
17
|
+
import { chatSDKStateCleanUp } from "./endChat";
|
|
18
18
|
|
|
19
19
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
20
|
let optionalParams = {};
|
|
@@ -107,13 +107,21 @@ const setPreChatAndInitiateChat = async (chatSDK, dispatch, setAdapter, isProact
|
|
|
107
107
|
|
|
108
108
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
109
109
|
const initStartChat = async (chatSDK, dispatch, setAdapter, state, props, params, persistedState) => {
|
|
110
|
-
var _props$controlProps2;
|
|
111
110
|
let isStartChatSuccessful = false;
|
|
112
111
|
const chatConfig = props === null || props === void 0 ? void 0 : props.chatConfig;
|
|
113
112
|
const getAuthToken = props === null || props === void 0 ? void 0 : props.getAuthToken;
|
|
114
|
-
|
|
113
|
+
if ((state === null || state === void 0 ? void 0 : state.appStates.conversationState) === ConversationState.Closed) {
|
|
114
|
+
// Preventive reset to avoid starting chat with previous requestId which could potentially cause problems
|
|
115
|
+
chatSDKStateCleanUp(chatSDK);
|
|
116
|
+
}
|
|
115
117
|
try {
|
|
116
|
-
var _newAdapter$activity
|
|
118
|
+
var _state$appStates, _newAdapter$activity$;
|
|
119
|
+
// Clear disconnect state on start chat
|
|
120
|
+
(state === null || state === void 0 ? void 0 : (_state$appStates = state.appStates) === null || _state$appStates === void 0 ? void 0 : _state$appStates.chatDisconnectEventReceived) && dispatch({
|
|
121
|
+
type: LiveChatWidgetActionType.SET_CHAT_DISCONNECT_EVENT_RECEIVED,
|
|
122
|
+
payload: false
|
|
123
|
+
});
|
|
124
|
+
|
|
117
125
|
//Start widget load timer
|
|
118
126
|
TelemetryTimers.WidgetLoadTimer = createTimer();
|
|
119
127
|
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
@@ -125,8 +133,7 @@ const initStartChat = async (chatSDK, dispatch, setAdapter, state, props, params
|
|
|
125
133
|
// set auth token to chat sdk before start chat
|
|
126
134
|
const authSuccess = await handleAuthentication(chatSDK, chatConfig, getAuthToken);
|
|
127
135
|
if (!authSuccess) {
|
|
128
|
-
|
|
129
|
-
throw new Error("Authentication was not successful");
|
|
136
|
+
throw new Error(WidgetLoadCustomErrorString.AuthenticationFailedErrorString);
|
|
130
137
|
}
|
|
131
138
|
}
|
|
132
139
|
|
|
@@ -189,16 +196,11 @@ const initStartChat = async (chatSDK, dispatch, setAdapter, state, props, params
|
|
|
189
196
|
});
|
|
190
197
|
}
|
|
191
198
|
if (persistedState) {
|
|
192
|
-
var _TelemetryTimers$Widg;
|
|
193
199
|
dispatch({
|
|
194
200
|
type: LiveChatWidgetActionType.SET_WIDGET_STATE,
|
|
195
201
|
payload: persistedState
|
|
196
202
|
});
|
|
197
|
-
|
|
198
|
-
Event: TelemetryEvent.WidgetLoadComplete,
|
|
199
|
-
Description: "Widget load complete. Persisted state retrieved",
|
|
200
|
-
ElapsedTimeInMilliseconds: TelemetryTimers === null || TelemetryTimers === void 0 ? void 0 : (_TelemetryTimers$Widg = TelemetryTimers.WidgetLoadTimer) === null || _TelemetryTimers$Widg === void 0 ? void 0 : _TelemetryTimers$Widg.milliSecondsElapsed
|
|
201
|
-
});
|
|
203
|
+
logWidgetLoadComplete(WidgetLoadTelemetryMessage.PersistedStateRetrievedMessage);
|
|
202
204
|
await setPostChatContextAndLoadSurvey(chatSDK, dispatch, true);
|
|
203
205
|
return;
|
|
204
206
|
}
|
|
@@ -209,11 +211,7 @@ const initStartChat = async (chatSDK, dispatch, setAdapter, state, props, params
|
|
|
209
211
|
type: LiveChatWidgetActionType.SET_LIVE_CHAT_CONTEXT,
|
|
210
212
|
payload: liveChatContext
|
|
211
213
|
});
|
|
212
|
-
|
|
213
|
-
Event: TelemetryEvent.WidgetLoadComplete,
|
|
214
|
-
Description: "Widget load complete",
|
|
215
|
-
ElapsedTimeInMilliseconds: TelemetryTimers === null || TelemetryTimers === void 0 ? void 0 : (_TelemetryTimers$Widg2 = TelemetryTimers.WidgetLoadTimer) === null || _TelemetryTimers$Widg2 === void 0 ? void 0 : _TelemetryTimers$Widg2.milliSecondsElapsed
|
|
216
|
-
});
|
|
214
|
+
logWidgetLoadComplete();
|
|
217
215
|
|
|
218
216
|
// Set post chat context in state
|
|
219
217
|
// Commenting this for now as post chat context is fetched during end chat
|
|
@@ -222,77 +220,18 @@ const initStartChat = async (chatSDK, dispatch, setAdapter, state, props, params
|
|
|
222
220
|
// Updating chat session detail for telemetry
|
|
223
221
|
await updateSessionDataForTelemetry(chatSDK, dispatch);
|
|
224
222
|
} catch (ex) {
|
|
225
|
-
|
|
226
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
227
|
-
if (ex.message === ChatSDKError.WidgetUseOutsideOperatingHour) {
|
|
228
|
-
var _TelemetryTimers$Widg3;
|
|
229
|
-
dispatch({
|
|
230
|
-
type: LiveChatWidgetActionType.SET_OUTSIDE_OPERATING_HOURS,
|
|
231
|
-
payload: true
|
|
232
|
-
});
|
|
233
|
-
dispatch({
|
|
234
|
-
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
235
|
-
payload: ConversationState.OutOfOffice
|
|
236
|
-
});
|
|
237
|
-
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
238
|
-
Event: TelemetryEvent.WidgetLoadComplete,
|
|
239
|
-
Description: "Widget load complete. Widget is OOOH.",
|
|
240
|
-
ElapsedTimeInMilliseconds: TelemetryTimers === null || TelemetryTimers === void 0 ? void 0 : (_TelemetryTimers$Widg3 = TelemetryTimers.WidgetLoadTimer) === null || _TelemetryTimers$Widg3 === void 0 ? void 0 : _TelemetryTimers$Widg3.milliSecondsElapsed
|
|
241
|
-
});
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
TelemetryHelper.logLoadingEvent(LogLevel.ERROR, {
|
|
245
|
-
Event: TelemetryEvent.WidgetLoadFailed,
|
|
246
|
-
ExceptionDetails: {
|
|
247
|
-
Exception: `Widget load Failed: ${ex}`
|
|
248
|
-
},
|
|
249
|
-
ElapsedTimeInMilliseconds: TelemetryTimers === null || TelemetryTimers === void 0 ? void 0 : (_TelemetryTimers$Widg4 = TelemetryTimers.WidgetLoadTimer) === null || _TelemetryTimers$Widg4 === void 0 ? void 0 : _TelemetryTimers$Widg4.milliSecondsElapsed
|
|
250
|
-
});
|
|
251
|
-
NotificationHandler.notifyError(NotificationScenarios.Connection, "Start Chat Failed: " + ex);
|
|
252
|
-
dispatch({
|
|
253
|
-
type: LiveChatWidgetActionType.SET_START_CHAT_FAILING,
|
|
254
|
-
payload: true
|
|
255
|
-
});
|
|
256
|
-
if (!hideErrorUIPane) {
|
|
257
|
-
// Set app state to failing start chat if hideErrorUI is not turned on
|
|
258
|
-
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
259
|
-
Event: TelemetryEvent.ErrorUIPaneLoaded,
|
|
260
|
-
Description: "Error UI Pane Loaded"
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
// Show the loading pane in other cases for failure, this will help for both hideStartChatButton case
|
|
264
|
-
dispatch({
|
|
265
|
-
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
266
|
-
payload: ConversationState.Loading
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
// If sessionInit was successful but LCW startchat failed due to some reason e.g adapter didn't load
|
|
270
|
-
// we need to directly endChat to avoid leaving ghost chats in OC, not disturbing any other UI state
|
|
271
|
-
if (isStartChatSuccessful === true) {
|
|
272
|
-
await forceEndChat(chatSDK);
|
|
273
|
-
}
|
|
223
|
+
handleStartChatError(dispatch, chatSDK, props, ex, isStartChatSuccessful);
|
|
274
224
|
} finally {
|
|
275
225
|
optionalParams = {};
|
|
276
226
|
widgetInstanceId = "";
|
|
277
227
|
}
|
|
278
228
|
};
|
|
279
229
|
|
|
280
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
281
|
-
const forceEndChat = async chatSDK => {
|
|
282
|
-
TelemetryHelper.logLoadingEvent(LogLevel.ERROR, {
|
|
283
|
-
Event: TelemetryEvent.WidgetLoadFailed,
|
|
284
|
-
ExceptionDetails: {
|
|
285
|
-
Exception: "SessionInit was successful, but widget load failed."
|
|
286
|
-
}
|
|
287
|
-
});
|
|
288
|
-
chatSDK === null || chatSDK === void 0 ? void 0 : chatSDK.endChat();
|
|
289
|
-
};
|
|
290
|
-
|
|
291
230
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
292
231
|
const canConnectToExistingChat = async (props, chatSDK, state, dispatch, setAdapter) => {
|
|
293
|
-
var _state$
|
|
232
|
+
var _state$appStates2, _persistedState$domai6, _persistedState$appSt;
|
|
294
233
|
// By pass this function in case of popout chat
|
|
295
|
-
if ((state === null || state === void 0 ? void 0 : (_state$
|
|
234
|
+
if ((state === null || state === void 0 ? void 0 : (_state$appStates2 = state.appStates) === null || _state$appStates2 === void 0 ? void 0 : _state$appStates2.hideStartChatButton) === true) {
|
|
296
235
|
return false;
|
|
297
236
|
}
|
|
298
237
|
const persistedState = getStateFromCache(getWidgetCacheIdfromProps(props));
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { ChatSDKErrorName, ChatSDKError } from "@microsoft/omnichannel-chat-sdk";
|
|
2
|
+
import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
|
|
3
|
+
import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
|
|
4
|
+
import { TelemetryTimers } from "../../../common/telemetry/TelemetryManager";
|
|
5
|
+
import { ConversationState } from "../../../contexts/common/ConversationState";
|
|
6
|
+
import { LiveChatWidgetActionType } from "../../../contexts/common/LiveChatWidgetActionType";
|
|
7
|
+
import { callingStateCleanUp, endChatStateCleanUp, closeChatStateCleanUp, chatSDKStateCleanUp } from "./endChat";
|
|
8
|
+
import { DataStoreManager } from "../../../common/contextDataStore/DataStoreManager";
|
|
9
|
+
import { getWidgetCacheIdfromProps } from "../../../common/utils";
|
|
10
|
+
import { WidgetLoadCustomErrorString, WidgetLoadTelemetryMessage } from "../../../common/Constants";
|
|
11
|
+
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
export const handleStartChatError = (dispatch, chatSDK, props, ex, isStartChatSuccessful) => {
|
|
14
|
+
var _props$controlProps;
|
|
15
|
+
if (!ex) {
|
|
16
|
+
logWidgetLoadFailed();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Handle internal or misc errors
|
|
21
|
+
if (ex.message === WidgetLoadCustomErrorString.AuthenticationFailedErrorString || ex.message === WidgetLoadCustomErrorString.NetworkErrorString) {
|
|
22
|
+
logWidgetLoadCompleteWithError(ex);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Handle ChatSDK errors
|
|
26
|
+
if (ex instanceof ChatSDKError) {
|
|
27
|
+
switch (ex.message) {
|
|
28
|
+
case ChatSDKErrorName.WidgetUseOutsideOperatingHour:
|
|
29
|
+
handleWidgetUseOutsideOperatingHour(dispatch);
|
|
30
|
+
return;
|
|
31
|
+
case ChatSDKErrorName.PersistentChatConversationRetrievalFailure:
|
|
32
|
+
handlePersistentChatConversationRetrievalFailure(ex);
|
|
33
|
+
break;
|
|
34
|
+
case ChatSDKErrorName.ConversationInitializationFailure:
|
|
35
|
+
handleConversationInitializationFailure(ex);
|
|
36
|
+
break;
|
|
37
|
+
case ChatSDKErrorName.ChatTokenRetrievalFailure:
|
|
38
|
+
handleChatTokenRetrievalFailure(ex);
|
|
39
|
+
break;
|
|
40
|
+
case ChatSDKErrorName.UninitializedChatSDK:
|
|
41
|
+
handleUninitializedChatSDK(ex);
|
|
42
|
+
break;
|
|
43
|
+
case ChatSDKErrorName.InvalidConversation:
|
|
44
|
+
case ChatSDKErrorName.ClosedConversation:
|
|
45
|
+
handleInvalidOrClosedConversation(dispatch, chatSDK, props, ex);
|
|
46
|
+
return;
|
|
47
|
+
default:
|
|
48
|
+
logWidgetLoadFailed(ex);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Show the error UI pane
|
|
53
|
+
dispatch({
|
|
54
|
+
type: LiveChatWidgetActionType.SET_START_CHAT_FAILING,
|
|
55
|
+
payload: true
|
|
56
|
+
});
|
|
57
|
+
if (!(props !== null && props !== void 0 && (_props$controlProps = props.controlProps) !== null && _props$controlProps !== void 0 && _props$controlProps.hideErrorUIPane)) {
|
|
58
|
+
// Set app state to failing start chat if hideErrorUI is not turned on
|
|
59
|
+
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
60
|
+
Event: TelemetryEvent.ErrorUIPaneLoaded,
|
|
61
|
+
Description: "Error UI Pane Loaded"
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
// Show the loading pane in other cases for failure, this will help for both hideStartChatButton case
|
|
65
|
+
dispatch({
|
|
66
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
67
|
+
payload: ConversationState.Loading
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// If sessionInit was successful but LCW startchat failed due to some reason e.g adapter didn't load
|
|
71
|
+
// we need to directly endChat to avoid leaving ghost chats in OC, not disturbing any other UI state
|
|
72
|
+
if (isStartChatSuccessful === true) {
|
|
73
|
+
forceEndChat(chatSDK);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const logWidgetLoadFailed = ex => {
|
|
77
|
+
var _TelemetryTimers$Widg;
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
79
|
+
const exDetails = {
|
|
80
|
+
Exception: `Widget load complete with error: ${ex}`
|
|
81
|
+
};
|
|
82
|
+
if (ex !== null && ex !== void 0 && ex.httpResponseStatusCode) {
|
|
83
|
+
exDetails.HttpResponseStatusCode = ex.httpResponseStatusCode;
|
|
84
|
+
}
|
|
85
|
+
TelemetryHelper.logLoadingEvent(LogLevel.ERROR, {
|
|
86
|
+
Event: TelemetryEvent.WidgetLoadFailed,
|
|
87
|
+
ExceptionDetails: exDetails,
|
|
88
|
+
ElapsedTimeInMilliseconds: TelemetryTimers === null || TelemetryTimers === void 0 ? void 0 : (_TelemetryTimers$Widg = TelemetryTimers.WidgetLoadTimer) === null || _TelemetryTimers$Widg === void 0 ? void 0 : _TelemetryTimers$Widg.milliSecondsElapsed
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
export const logWidgetLoadComplete = additionalMessage => {
|
|
92
|
+
var _TelemetryTimers$Widg2;
|
|
93
|
+
let descriptionString = "Widget load complete";
|
|
94
|
+
if (additionalMessage) {
|
|
95
|
+
descriptionString += `. ${additionalMessage}`;
|
|
96
|
+
}
|
|
97
|
+
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
98
|
+
Event: TelemetryEvent.WidgetLoadComplete,
|
|
99
|
+
Description: descriptionString,
|
|
100
|
+
ElapsedTimeInMilliseconds: TelemetryTimers === null || TelemetryTimers === void 0 ? void 0 : (_TelemetryTimers$Widg2 = TelemetryTimers.WidgetLoadTimer) === null || _TelemetryTimers$Widg2 === void 0 ? void 0 : _TelemetryTimers$Widg2.milliSecondsElapsed
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
const logWidgetLoadCompleteWithError = ex => {
|
|
104
|
+
var _TelemetryTimers$Widg3;
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
106
|
+
const exDetails = {
|
|
107
|
+
Exception: `Widget load complete with error: ${ex}`
|
|
108
|
+
};
|
|
109
|
+
if (ex !== null && ex !== void 0 && ex.httpResponseStatusCode) {
|
|
110
|
+
exDetails.HttpResponseStatusCode = ex.httpResponseStatusCode;
|
|
111
|
+
}
|
|
112
|
+
TelemetryHelper.logLoadingEvent(LogLevel.WARN, {
|
|
113
|
+
Event: TelemetryEvent.WidgetLoadComplete,
|
|
114
|
+
Description: "Widget load complete with error",
|
|
115
|
+
ExceptionDetails: exDetails,
|
|
116
|
+
ElapsedTimeInMilliseconds: TelemetryTimers === null || TelemetryTimers === void 0 ? void 0 : (_TelemetryTimers$Widg3 = TelemetryTimers.WidgetLoadTimer) === null || _TelemetryTimers$Widg3 === void 0 ? void 0 : _TelemetryTimers$Widg3.milliSecondsElapsed
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
121
|
+
const forceEndChat = chatSDK => {
|
|
122
|
+
TelemetryHelper.logLoadingEvent(LogLevel.ERROR, {
|
|
123
|
+
Event: TelemetryEvent.WidgetLoadFailed,
|
|
124
|
+
ExceptionDetails: {
|
|
125
|
+
Exception: "SessionInit was successful, but widget load failed."
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
chatSDK === null || chatSDK === void 0 ? void 0 : chatSDK.endChat();
|
|
129
|
+
};
|
|
130
|
+
const handleWidgetUseOutsideOperatingHour = dispatch => {
|
|
131
|
+
dispatch({
|
|
132
|
+
type: LiveChatWidgetActionType.SET_OUTSIDE_OPERATING_HOURS,
|
|
133
|
+
payload: true
|
|
134
|
+
});
|
|
135
|
+
dispatch({
|
|
136
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
137
|
+
payload: ConversationState.OutOfOffice
|
|
138
|
+
});
|
|
139
|
+
logWidgetLoadComplete(WidgetLoadTelemetryMessage.OOOHMessage);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
143
|
+
const handlePersistentChatConversationRetrievalFailure = ex => {
|
|
144
|
+
if (ex.httpResponseStatusCode === 400) {
|
|
145
|
+
logWidgetLoadFailed(ex);
|
|
146
|
+
} else {
|
|
147
|
+
logWidgetLoadCompleteWithError(ex);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
152
|
+
const handleConversationInitializationFailure = ex => {
|
|
153
|
+
if (ex.httpResponseStatusCode === 400) {
|
|
154
|
+
logWidgetLoadFailed(ex);
|
|
155
|
+
} else {
|
|
156
|
+
logWidgetLoadCompleteWithError(ex);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
161
|
+
const handleChatTokenRetrievalFailure = ex => {
|
|
162
|
+
if (ex.httpResponseStatusCode === 400) {
|
|
163
|
+
logWidgetLoadFailed(ex);
|
|
164
|
+
} else {
|
|
165
|
+
logWidgetLoadCompleteWithError(ex);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
170
|
+
const handleUninitializedChatSDK = ex => {
|
|
171
|
+
logWidgetLoadCompleteWithError(ex);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
175
|
+
const handleInvalidOrClosedConversation = (dispatch, chatSDK, props, ex) => {
|
|
176
|
+
var _DataStoreManager$cli;
|
|
177
|
+
logWidgetLoadCompleteWithError(ex);
|
|
178
|
+
|
|
179
|
+
// Reset all internal states
|
|
180
|
+
callingStateCleanUp(dispatch);
|
|
181
|
+
endChatStateCleanUp(dispatch);
|
|
182
|
+
closeChatStateCleanUp(dispatch);
|
|
183
|
+
chatSDKStateCleanUp(chatSDK);
|
|
184
|
+
(_DataStoreManager$cli = DataStoreManager.clientDataStore) === null || _DataStoreManager$cli === void 0 ? void 0 : _DataStoreManager$cli.removeData(getWidgetCacheIdfromProps(props));
|
|
185
|
+
|
|
186
|
+
// Starts new chat
|
|
187
|
+
dispatch({
|
|
188
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
189
|
+
payload: ConversationState.Closed
|
|
190
|
+
});
|
|
191
|
+
};
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { BroadcastService } from "@microsoft/omnichannel-chat-components";
|
|
2
|
+
import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
|
|
3
|
+
import { handleStartChatError } from "./startChatErrorHandler";
|
|
4
|
+
import { WidgetLoadCustomErrorString, WidgetLoadTelemetryMessage } from "../../../common/Constants";
|
|
5
|
+
import { ChatSDKError, ChatSDKErrorName } from "@microsoft/omnichannel-chat-sdk";
|
|
6
|
+
import { LiveChatWidgetActionType } from "../../../contexts/common/LiveChatWidgetActionType";
|
|
7
|
+
import { ConversationState } from "../../../contexts/common/ConversationState";
|
|
8
|
+
describe("startChatErrorHandler unit test", () => {
|
|
9
|
+
it("handleStartChatError should log failed event and return if exception is undefined", () => {
|
|
10
|
+
const dispatch = jest.fn();
|
|
11
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
12
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
13
|
+
handleStartChatError(dispatch, {}, {}, undefined, false);
|
|
14
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(1);
|
|
15
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("ERROR", expect.objectContaining({
|
|
16
|
+
ExceptionDetails: expect.objectContaining({
|
|
17
|
+
Exception: "Widget load complete with error: undefined"
|
|
18
|
+
})
|
|
19
|
+
}));
|
|
20
|
+
expect(dispatch).not.toHaveBeenCalled();
|
|
21
|
+
});
|
|
22
|
+
it("handleStartChatError should log failed with error event for AuthenticationFailedErrorString", () => {
|
|
23
|
+
const dispatch = jest.fn();
|
|
24
|
+
const mockEx = new Error(WidgetLoadCustomErrorString.AuthenticationFailedErrorString);
|
|
25
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
26
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
27
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
28
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(2);
|
|
29
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("WARN", expect.objectContaining({
|
|
30
|
+
ExceptionDetails: expect.objectContaining({
|
|
31
|
+
Exception: `Widget load complete with error: Error: ${WidgetLoadCustomErrorString.AuthenticationFailedErrorString}`
|
|
32
|
+
})
|
|
33
|
+
}));
|
|
34
|
+
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
35
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
36
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE
|
|
37
|
+
}));
|
|
38
|
+
});
|
|
39
|
+
it("handleStartChatError should log failed with error event for NetworkErrorString", () => {
|
|
40
|
+
const dispatch = jest.fn();
|
|
41
|
+
const mockEx = new Error(WidgetLoadCustomErrorString.NetworkErrorString);
|
|
42
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
43
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
44
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
45
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(2);
|
|
46
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("WARN", expect.objectContaining({
|
|
47
|
+
ExceptionDetails: expect.objectContaining({
|
|
48
|
+
Exception: `Widget load complete with error: Error: ${WidgetLoadCustomErrorString.NetworkErrorString}`
|
|
49
|
+
})
|
|
50
|
+
}));
|
|
51
|
+
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
52
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
53
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE
|
|
54
|
+
}));
|
|
55
|
+
});
|
|
56
|
+
it("handleStartChatError should log complete event for WidgetUseOutsideOperatingHour", () => {
|
|
57
|
+
const dispatch = jest.fn();
|
|
58
|
+
const mockEx = new ChatSDKError(ChatSDKErrorName.WidgetUseOutsideOperatingHour);
|
|
59
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
60
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
61
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
62
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(1);
|
|
63
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("INFO", expect.objectContaining({
|
|
64
|
+
Description: `Widget load complete. ${WidgetLoadTelemetryMessage.OOOHMessage}`
|
|
65
|
+
}));
|
|
66
|
+
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
67
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
68
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE
|
|
69
|
+
}));
|
|
70
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
71
|
+
type: LiveChatWidgetActionType.SET_OUTSIDE_OPERATING_HOURS
|
|
72
|
+
}));
|
|
73
|
+
});
|
|
74
|
+
it("handleStartChatError should log failed with error event for PersistentChatConversationRetrievalFailure for non-400 status", () => {
|
|
75
|
+
const dispatch = jest.fn();
|
|
76
|
+
const mockEx = new ChatSDKError(ChatSDKErrorName.PersistentChatConversationRetrievalFailure, 429);
|
|
77
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
78
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
79
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
80
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(2);
|
|
81
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("WARN", expect.objectContaining({
|
|
82
|
+
Description: "Widget load complete with error",
|
|
83
|
+
ExceptionDetails: expect.objectContaining({
|
|
84
|
+
Exception: `Widget load complete with error: ${ChatSDKErrorName.PersistentChatConversationRetrievalFailure}`,
|
|
85
|
+
HttpResponseStatusCode: 429
|
|
86
|
+
})
|
|
87
|
+
}));
|
|
88
|
+
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
89
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
90
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE
|
|
91
|
+
}));
|
|
92
|
+
});
|
|
93
|
+
it("handleStartChatError should log failed event for PersistentChatConversationRetrievalFailure for 400 status", () => {
|
|
94
|
+
const dispatch = jest.fn();
|
|
95
|
+
const mockEx = new ChatSDKError(ChatSDKErrorName.PersistentChatConversationRetrievalFailure, 400);
|
|
96
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
97
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
98
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
99
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(2);
|
|
100
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("ERROR", expect.objectContaining({
|
|
101
|
+
ExceptionDetails: expect.objectContaining({
|
|
102
|
+
Exception: `Widget load complete with error: ${ChatSDKErrorName.PersistentChatConversationRetrievalFailure}`,
|
|
103
|
+
HttpResponseStatusCode: 400
|
|
104
|
+
})
|
|
105
|
+
}));
|
|
106
|
+
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
107
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
108
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE
|
|
109
|
+
}));
|
|
110
|
+
});
|
|
111
|
+
it("handleStartChatError should log failed with error event for ConversationInitializationFailure for non-400 status", () => {
|
|
112
|
+
const dispatch = jest.fn();
|
|
113
|
+
const mockEx = new ChatSDKError(ChatSDKErrorName.ConversationInitializationFailure, 429);
|
|
114
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
115
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
116
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
117
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(2);
|
|
118
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("WARN", expect.objectContaining({
|
|
119
|
+
Description: "Widget load complete with error",
|
|
120
|
+
ExceptionDetails: expect.objectContaining({
|
|
121
|
+
Exception: `Widget load complete with error: ${ChatSDKErrorName.ConversationInitializationFailure}`,
|
|
122
|
+
HttpResponseStatusCode: 429
|
|
123
|
+
})
|
|
124
|
+
}));
|
|
125
|
+
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
126
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
127
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE
|
|
128
|
+
}));
|
|
129
|
+
});
|
|
130
|
+
it("handleStartChatError should log failed event for ConversationInitializationFailure for 400 status", () => {
|
|
131
|
+
const dispatch = jest.fn();
|
|
132
|
+
const mockEx = new ChatSDKError(ChatSDKErrorName.ConversationInitializationFailure, 400);
|
|
133
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
134
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
135
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
136
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(2);
|
|
137
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("ERROR", expect.objectContaining({
|
|
138
|
+
ExceptionDetails: expect.objectContaining({
|
|
139
|
+
Exception: `Widget load complete with error: ${ChatSDKErrorName.ConversationInitializationFailure}`,
|
|
140
|
+
HttpResponseStatusCode: 400
|
|
141
|
+
})
|
|
142
|
+
}));
|
|
143
|
+
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
144
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
145
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE
|
|
146
|
+
}));
|
|
147
|
+
});
|
|
148
|
+
it("handleStartChatError should log failed with error event for ChatTokenRetrievalFailure for non-400 status", () => {
|
|
149
|
+
const dispatch = jest.fn();
|
|
150
|
+
const mockEx = new ChatSDKError(ChatSDKErrorName.ChatTokenRetrievalFailure, 429);
|
|
151
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
152
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
153
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
154
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(2);
|
|
155
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("WARN", expect.objectContaining({
|
|
156
|
+
Description: "Widget load complete with error",
|
|
157
|
+
ExceptionDetails: expect.objectContaining({
|
|
158
|
+
Exception: `Widget load complete with error: ${ChatSDKErrorName.ChatTokenRetrievalFailure}`,
|
|
159
|
+
HttpResponseStatusCode: 429
|
|
160
|
+
})
|
|
161
|
+
}));
|
|
162
|
+
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
163
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
164
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE
|
|
165
|
+
}));
|
|
166
|
+
});
|
|
167
|
+
it("handleStartChatError should log failed event for ChatTokenRetrievalFailure for 400 status", () => {
|
|
168
|
+
const dispatch = jest.fn();
|
|
169
|
+
const mockEx = new ChatSDKError(ChatSDKErrorName.ChatTokenRetrievalFailure, 400);
|
|
170
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
171
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
172
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
173
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(2);
|
|
174
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("ERROR", expect.objectContaining({
|
|
175
|
+
ExceptionDetails: expect.objectContaining({
|
|
176
|
+
Exception: `Widget load complete with error: ${ChatSDKErrorName.ChatTokenRetrievalFailure}`,
|
|
177
|
+
HttpResponseStatusCode: 400
|
|
178
|
+
})
|
|
179
|
+
}));
|
|
180
|
+
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
181
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
182
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE
|
|
183
|
+
}));
|
|
184
|
+
});
|
|
185
|
+
it("handleStartChatError should log failed with error event for UninitializedChatSDK", () => {
|
|
186
|
+
const dispatch = jest.fn();
|
|
187
|
+
const mockEx = new ChatSDKError(ChatSDKErrorName.UninitializedChatSDK);
|
|
188
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
189
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
190
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
191
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(2);
|
|
192
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("WARN", expect.objectContaining({
|
|
193
|
+
Description: "Widget load complete with error",
|
|
194
|
+
ExceptionDetails: expect.objectContaining({
|
|
195
|
+
Exception: `Widget load complete with error: ${ChatSDKErrorName.UninitializedChatSDK}`
|
|
196
|
+
})
|
|
197
|
+
}));
|
|
198
|
+
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
199
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
200
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE
|
|
201
|
+
}));
|
|
202
|
+
});
|
|
203
|
+
it("handleStartChatError should log failed with error event for InvalidConversation", () => {
|
|
204
|
+
const dispatch = jest.fn();
|
|
205
|
+
const mockEx = new ChatSDKError(ChatSDKErrorName.InvalidConversation);
|
|
206
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
207
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
208
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
209
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(1);
|
|
210
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("WARN", expect.objectContaining({
|
|
211
|
+
Description: "Widget load complete with error",
|
|
212
|
+
ExceptionDetails: expect.objectContaining({
|
|
213
|
+
Exception: `Widget load complete with error: ${ChatSDKErrorName.InvalidConversation}`
|
|
214
|
+
})
|
|
215
|
+
}));
|
|
216
|
+
expect(dispatch).toHaveBeenCalledTimes(16);
|
|
217
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
218
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
219
|
+
payload: ConversationState.Closed
|
|
220
|
+
}));
|
|
221
|
+
});
|
|
222
|
+
it("handleStartChatError should log failed with error event for ClosedConversation", () => {
|
|
223
|
+
const dispatch = jest.fn();
|
|
224
|
+
const mockEx = new ChatSDKError(ChatSDKErrorName.ClosedConversation);
|
|
225
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
226
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
227
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
228
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(1);
|
|
229
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("WARN", expect.objectContaining({
|
|
230
|
+
Description: "Widget load complete with error",
|
|
231
|
+
ExceptionDetails: expect.objectContaining({
|
|
232
|
+
Exception: `Widget load complete with error: ${ChatSDKErrorName.ClosedConversation}`
|
|
233
|
+
})
|
|
234
|
+
}));
|
|
235
|
+
expect(dispatch).toHaveBeenCalledTimes(16);
|
|
236
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
237
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
238
|
+
payload: ConversationState.Closed
|
|
239
|
+
}));
|
|
240
|
+
});
|
|
241
|
+
it("handleStartChatError should log failed event for any other errors", () => {
|
|
242
|
+
const dispatch = jest.fn();
|
|
243
|
+
const mockEx = new ChatSDKError(ChatSDKErrorName.ScriptLoadFailure, 405);
|
|
244
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
245
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
246
|
+
handleStartChatError(dispatch, {}, {}, mockEx, false);
|
|
247
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(2);
|
|
248
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("ERROR", expect.objectContaining({
|
|
249
|
+
ExceptionDetails: expect.objectContaining({
|
|
250
|
+
Exception: `Widget load complete with error: ${ChatSDKErrorName.ScriptLoadFailure}`,
|
|
251
|
+
HttpResponseStatusCode: 405
|
|
252
|
+
})
|
|
253
|
+
}));
|
|
254
|
+
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
255
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
256
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE
|
|
257
|
+
}));
|
|
258
|
+
});
|
|
259
|
+
it("handleStartChatError should force end chat if isStartChatSuccessful is true", () => {
|
|
260
|
+
const dispatch = jest.fn();
|
|
261
|
+
const mockEx = new ChatSDKError(ChatSDKErrorName.ScriptLoadFailure, 405);
|
|
262
|
+
const mockSDK = {
|
|
263
|
+
endChat: jest.fn()
|
|
264
|
+
};
|
|
265
|
+
spyOn(BroadcastService, "postMessage").and.callFake(() => false);
|
|
266
|
+
spyOn(TelemetryHelper, "logLoadingEvent").and.callFake(() => false);
|
|
267
|
+
handleStartChatError(dispatch, mockSDK, {}, mockEx, true);
|
|
268
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledTimes(3);
|
|
269
|
+
expect(TelemetryHelper.logLoadingEvent).toHaveBeenCalledWith("ERROR", expect.objectContaining({
|
|
270
|
+
ExceptionDetails: expect.objectContaining({
|
|
271
|
+
Exception: "SessionInit was successful, but widget load failed."
|
|
272
|
+
})
|
|
273
|
+
}));
|
|
274
|
+
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
275
|
+
expect(dispatch).toHaveBeenCalledWith(expect.objectContaining({
|
|
276
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE
|
|
277
|
+
}));
|
|
278
|
+
expect(mockSDK.endChat).toHaveBeenCalled();
|
|
279
|
+
});
|
|
280
|
+
});
|