@servicetitan/titan-chatbot-api 7.1.1 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/api-client/__mocks__/chatbot-api-client.mock.js +21 -47
- package/dist/api-client/__mocks__/chatbot-api-client.mock.js.map +1 -1
- package/dist/api-client/base/chatbot-api-client.js +3 -4
- package/dist/api-client/base/chatbot-api-client.js.map +1 -1
- package/dist/api-client/help-center/__tests__/converter-from-models.test.js +48 -15
- package/dist/api-client/help-center/__tests__/converter-from-models.test.js.map +1 -1
- package/dist/api-client/help-center/__tests__/converter-to-models.test.js +23 -22
- package/dist/api-client/help-center/__tests__/converter-to-models.test.js.map +1 -1
- package/dist/api-client/help-center/chatbot-api-client.js +51 -52
- package/dist/api-client/help-center/chatbot-api-client.js.map +1 -1
- package/dist/api-client/help-center/converter-from-models.js +15 -12
- package/dist/api-client/help-center/converter-from-models.js.map +1 -1
- package/dist/api-client/help-center/converter-to-models.js +29 -26
- package/dist/api-client/help-center/converter-to-models.js.map +1 -1
- package/dist/api-client/help-center/index.d.ts +2 -1
- package/dist/api-client/help-center/index.d.ts.map +1 -1
- package/dist/api-client/help-center/index.js +1 -0
- package/dist/api-client/help-center/index.js.map +1 -1
- package/dist/api-client/help-center/native-client.js +1192 -2884
- package/dist/api-client/help-center/native-client.js.map +1 -1
- package/dist/api-client/index.d.ts +2 -1
- package/dist/api-client/index.d.ts.map +1 -1
- package/dist/api-client/index.js +14 -7
- package/dist/api-client/index.js.map +1 -1
- package/dist/api-client/models/__mocks__/models.mock.js +154 -124
- package/dist/api-client/models/__mocks__/models.mock.js.map +1 -1
- package/dist/api-client/models/index.d.ts +2 -1
- package/dist/api-client/models/index.d.ts.map +1 -1
- package/dist/api-client/models/index.js +8 -7
- package/dist/api-client/models/index.js.map +1 -1
- package/dist/api-client/titan-chat/__tests__/native-client.test.js +6 -6
- package/dist/api-client/titan-chat/__tests__/native-client.test.js.map +1 -1
- package/dist/api-client/titan-chat/chatbot-api-client.js +40 -35
- package/dist/api-client/titan-chat/chatbot-api-client.js.map +1 -1
- package/dist/api-client/titan-chat/index.d.ts +2 -1
- package/dist/api-client/titan-chat/index.d.ts.map +1 -1
- package/dist/api-client/titan-chat/index.js +1 -0
- package/dist/api-client/titan-chat/index.js.map +1 -1
- package/dist/api-client/titan-chat/native-client.d.ts +14 -14
- package/dist/api-client/titan-chat/native-client.d.ts.map +1 -1
- package/dist/api-client/titan-chat/native-client.js +359 -809
- package/dist/api-client/titan-chat/native-client.js.map +1 -1
- package/dist/api-client/utils/__tests__/model-utils.test.js +454 -191
- package/dist/api-client/utils/__tests__/model-utils.test.js.map +1 -1
- package/dist/api-client/utils/model-utils.d.ts.map +1 -1
- package/dist/api-client/utils/model-utils.js +28 -25
- package/dist/api-client/utils/model-utils.js.map +1 -1
- package/dist/hooks/use-customization-chatbot.js +2 -1
- package/dist/hooks/use-customization-chatbot.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/models/chatbot-customizations.js +2 -1
- package/dist/models/chatbot-customizations.js.map +1 -1
- package/dist/models/index.d.ts +1 -1
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +2 -1
- package/dist/models/index.js.map +1 -1
- package/dist/stores/__tests__/chatbot-ui-backend.store.test.js +267 -172
- package/dist/stores/__tests__/chatbot-ui-backend.store.test.js.map +1 -1
- package/dist/stores/__tests__/chatbot-ui.store.test.js +61 -64
- package/dist/stores/__tests__/chatbot-ui.store.test.js.map +1 -1
- package/dist/stores/__tests__/filter.store.test.js +243 -116
- package/dist/stores/__tests__/filter.store.test.js.map +1 -1
- package/dist/stores/__tests__/initialize.store.test.js +9 -8
- package/dist/stores/__tests__/initialize.store.test.js.map +1 -1
- package/dist/stores/__tests__/message-feedback-guardrail.store.test.js +8 -7
- package/dist/stores/__tests__/message-feedback-guardrail.store.test.js.map +1 -1
- package/dist/stores/__tests__/message-feedback.store.test.js +34 -27
- package/dist/stores/__tests__/message-feedback.store.test.js.map +1 -1
- package/dist/stores/__tests__/session-feedback.store.test.js +9 -8
- package/dist/stores/__tests__/session-feedback.store.test.js.map +1 -1
- package/dist/stores/chatbot-ui-backend.store.js +171 -240
- package/dist/stores/chatbot-ui-backend.store.js.map +1 -1
- package/dist/stores/chatbot-ui.store.js +73 -46
- package/dist/stores/chatbot-ui.store.js.map +1 -1
- package/dist/stores/filter.store.js +298 -378
- package/dist/stores/filter.store.js.map +1 -1
- package/dist/stores/index.d.ts +5 -3
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/index.js +3 -2
- package/dist/stores/index.js.map +1 -1
- package/dist/stores/initialize.store.js +55 -51
- package/dist/stores/initialize.store.js.map +1 -1
- package/dist/stores/message-feedback-base.store.js +2 -1
- package/dist/stores/message-feedback-base.store.js.map +1 -1
- package/dist/stores/message-feedback-guardrail.store.js +50 -47
- package/dist/stores/message-feedback-guardrail.store.js.map +1 -1
- package/dist/stores/message-feedback.store.js +84 -89
- package/dist/stores/message-feedback.store.js.map +1 -1
- package/dist/stores/session-feedback.store.js +46 -39
- package/dist/stores/session-feedback.store.js.map +1 -1
- package/dist/utils/__tests__/axios-utils.test.js +8 -7
- package/dist/utils/__tests__/axios-utils.test.js.map +1 -1
- package/dist/utils/axios-utils.js +9 -7
- package/dist/utils/axios-utils.js.map +1 -1
- package/dist/utils/test-utils.js +5 -5
- package/dist/utils/test-utils.js.map +1 -1
- package/package.json +3 -3
- package/src/api-client/help-center/index.ts +2 -1
- package/src/api-client/help-center/native-client.ts +4 -4
- package/src/api-client/index.ts +2 -6
- package/src/api-client/models/index.ts +15 -13
- package/src/api-client/titan-chat/index.ts +2 -1
- package/src/api-client/titan-chat/native-client.ts +17 -14
- package/src/api-client/utils/model-utils.ts +4 -8
- package/src/index.ts +1 -1
- package/src/models/index.ts +1 -1
- package/src/stores/index.ts +5 -12
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,50 +1,43 @@
|
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) {
|
|
3
|
+
Object.defineProperty(obj, key, {
|
|
4
|
+
value: value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true
|
|
8
|
+
});
|
|
9
|
+
} else {
|
|
10
|
+
obj[key] = value;
|
|
11
|
+
}
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
1
14
|
import { expect } from '@jest/globals';
|
|
2
15
|
import { Log } from '@servicetitan/log-service';
|
|
3
|
-
import { ChatError, ChatRunState
|
|
16
|
+
import { ChatError, ChatRunState } from '@servicetitan/titan-chat-ui-common';
|
|
4
17
|
import { CHATBOT_API_CLIENT, Models, ModelsMocks } from '../../api-client';
|
|
5
18
|
import { ChatbotApiClientMock } from '../../api-client/__mocks__/chatbot-api-client.mock';
|
|
6
19
|
import { initTestContainer } from '../../utils/test-utils';
|
|
7
20
|
import { ChatbotUiBackendStore } from '../chatbot-ui-backend.store';
|
|
8
21
|
import { CHATBOT_UI_STORE_TOKEN, ChatbotUiStore } from '../chatbot-ui.store';
|
|
9
22
|
const WELCOME_MESSAGE = 'Hi there! I’m Agent, an AI chatbot powered by Titan Intelligence. I’m here to answer your questions about using ServiceTitan. You can ask me things like "How to merge duplicate customers?". Do you have a question for me?';
|
|
10
|
-
const initContainer = initTestContainer(ChatbotUiBackendStore, container
|
|
11
|
-
container
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
enumerable: true,
|
|
17
|
-
configurable: true,
|
|
18
|
-
writable: true,
|
|
19
|
-
value: jest.fn()
|
|
20
|
-
});
|
|
21
|
-
Object.defineProperty(this, "info", {
|
|
22
|
-
enumerable: true,
|
|
23
|
-
configurable: true,
|
|
24
|
-
writable: true,
|
|
25
|
-
value: jest.fn()
|
|
26
|
-
});
|
|
27
|
-
Object.defineProperty(this, "warning", {
|
|
28
|
-
enumerable: true,
|
|
29
|
-
configurable: true,
|
|
30
|
-
writable: true,
|
|
31
|
-
value: jest.fn()
|
|
32
|
-
});
|
|
23
|
+
const initContainer = initTestContainer(ChatbotUiBackendStore, (container)=>{
|
|
24
|
+
container.bind(Log).to(class {
|
|
25
|
+
constructor(){
|
|
26
|
+
_define_property(this, "error", jest.fn());
|
|
27
|
+
_define_property(this, "info", jest.fn());
|
|
28
|
+
_define_property(this, "warning", jest.fn());
|
|
33
29
|
}
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
container
|
|
37
|
-
.bind(CHATBOT_API_CLIENT)
|
|
38
|
-
.toConstantValue(new ChatbotApiClientMock());
|
|
30
|
+
}).inSingletonScope();
|
|
31
|
+
container.bind(CHATBOT_API_CLIENT).toConstantValue(new ChatbotApiClientMock());
|
|
39
32
|
container.bind(CHATBOT_UI_STORE_TOKEN).to(ChatbotUiStore).inSingletonScope();
|
|
40
33
|
});
|
|
41
|
-
describe('[ChatbotUiBackendStore]', ()
|
|
34
|
+
describe('[ChatbotUiBackendStore]', ()=>{
|
|
42
35
|
let container;
|
|
43
36
|
let store;
|
|
44
37
|
let chatbotApi;
|
|
45
38
|
let chatUiStore;
|
|
46
39
|
let log;
|
|
47
|
-
beforeEach(()
|
|
40
|
+
beforeEach(()=>{
|
|
48
41
|
container = initContainer();
|
|
49
42
|
store = container.get(ChatbotUiBackendStore);
|
|
50
43
|
chatbotApi = container.get(CHATBOT_API_CLIENT);
|
|
@@ -53,63 +46,69 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
53
46
|
jest.useFakeTimers();
|
|
54
47
|
jest.setSystemTime(new Date('2000-01-01T00:00:00.000Z'));
|
|
55
48
|
});
|
|
56
|
-
afterEach(()
|
|
49
|
+
afterEach(()=>{
|
|
57
50
|
jest.useRealTimers();
|
|
58
51
|
jest.clearAllMocks();
|
|
59
52
|
});
|
|
60
|
-
describe('with subscription', ()
|
|
53
|
+
describe('with subscription', ()=>{
|
|
61
54
|
let spyOn;
|
|
62
55
|
let spyOff;
|
|
63
|
-
beforeEach(()
|
|
56
|
+
beforeEach(()=>{
|
|
64
57
|
spyOn = jest.spyOn(chatUiStore, 'on');
|
|
65
58
|
spyOff = jest.spyOn(chatUiStore, 'off');
|
|
66
59
|
});
|
|
67
|
-
test('should subscribe on external events', ()
|
|
60
|
+
test('should subscribe on external events', ()=>{
|
|
68
61
|
store.subscribe();
|
|
69
62
|
expect(spyOn).toHaveBeenCalledTimes(8);
|
|
70
63
|
expect(spyOff).toHaveBeenCalledTimes(8);
|
|
71
64
|
});
|
|
72
|
-
test('should unsubscribe from external events', ()
|
|
65
|
+
test('should unsubscribe from external events', ()=>{
|
|
73
66
|
store.unsubscribe();
|
|
74
67
|
expect(chatUiStore.on).toHaveBeenCalledTimes(0);
|
|
75
68
|
expect(chatUiStore.off).toHaveBeenCalledTimes(8);
|
|
76
69
|
});
|
|
77
70
|
});
|
|
78
|
-
describe('with run', ()
|
|
79
|
-
const runChatUiEventListener = async (listener, args)
|
|
80
|
-
return new Promise((resolve, reject)
|
|
81
|
-
listener.apply(store, [
|
|
71
|
+
describe('with run', ()=>{
|
|
72
|
+
const runChatUiEventListener = async (listener, args)=>{
|
|
73
|
+
return new Promise((resolve, reject)=>{
|
|
74
|
+
listener.apply(store, [
|
|
75
|
+
resolve,
|
|
76
|
+
reject,
|
|
77
|
+
...args
|
|
78
|
+
]);
|
|
82
79
|
});
|
|
83
80
|
};
|
|
84
|
-
const runStore = async ()
|
|
81
|
+
const runStore = async ()=>{
|
|
85
82
|
await runChatUiEventListener(store.handleRun, []);
|
|
86
83
|
await jest.advanceTimersToNextTimerAsync(); // Wait for the timer to be set
|
|
87
84
|
};
|
|
88
|
-
const mockChatbotSession = ()
|
|
85
|
+
const mockChatbotSession = ()=>{
|
|
89
86
|
chatbotApi.getOptions.mockResolvedValue(ModelsMocks.mockFrontendModel());
|
|
90
87
|
chatbotApi.postSession.mockResolvedValue(ModelsMocks.mockSession());
|
|
91
88
|
chatbotApi.deleteSession.mockResolvedValue(ModelsMocks.mockSession());
|
|
92
89
|
};
|
|
93
|
-
const mockChatbotAnswer = (answer)
|
|
90
|
+
const mockChatbotAnswer = (answer)=>{
|
|
94
91
|
const answerMock = ModelsMocks.mockBotMessage({
|
|
95
92
|
id: 123,
|
|
96
|
-
answer
|
|
93
|
+
answer
|
|
97
94
|
});
|
|
98
95
|
chatbotApi.postMessage.mockResolvedValue(answerMock);
|
|
99
96
|
return answerMock;
|
|
100
97
|
};
|
|
101
|
-
const mockChatbotAnswers = (answers)
|
|
102
|
-
const answerMocks = answers.map(({ answer, answerId }, index)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
98
|
+
const mockChatbotAnswers = (answers)=>{
|
|
99
|
+
const answerMocks = answers.map(({ answer, answerId }, index)=>ModelsMocks.mockBotMessage({
|
|
100
|
+
id: answerId !== null && answerId !== void 0 ? answerId : 123 + index,
|
|
101
|
+
answer
|
|
102
|
+
}));
|
|
106
103
|
// Mock in reverse order to simulate responses coming back in different order
|
|
107
|
-
[
|
|
104
|
+
[
|
|
105
|
+
...answerMocks
|
|
106
|
+
].reverse().forEach((mock)=>{
|
|
108
107
|
chatbotApi.postMessage.mockResolvedValueOnce(mock);
|
|
109
108
|
});
|
|
110
109
|
return answerMocks;
|
|
111
110
|
};
|
|
112
|
-
const ensureChatStarted = ()
|
|
111
|
+
const ensureChatStarted = ()=>{
|
|
113
112
|
expect(chatUiStore.isAgentTyping).toBe(false);
|
|
114
113
|
expect(chatUiStore.isFilePickerEnabled).toBe(false);
|
|
115
114
|
expect(chatUiStore.file).toBe(undefined);
|
|
@@ -120,7 +119,7 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
120
119
|
expect(chatUiStore.scrollCounter > 1).toBe(true);
|
|
121
120
|
expect(chatUiStore.status).toBe(ChatRunState.Started);
|
|
122
121
|
};
|
|
123
|
-
test('should run chatbot without stored session', async ()
|
|
122
|
+
test('should run chatbot without stored session', async ()=>{
|
|
124
123
|
store.subscribe();
|
|
125
124
|
mockChatbotSession();
|
|
126
125
|
await runStore();
|
|
@@ -131,8 +130,7 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
131
130
|
/*
|
|
132
131
|
* We don't have session yet because we've just initialized the chat with welcome message
|
|
133
132
|
* and we don't do any chatbotApi.postSession call
|
|
134
|
-
*/
|
|
135
|
-
expect(store.session).toBeUndefined();
|
|
133
|
+
*/ expect(store.session).toBeUndefined();
|
|
136
134
|
expect(chatbotApi.postSession).toHaveBeenCalledTimes(0);
|
|
137
135
|
const botAnswer = mockChatbotAnswer('bot answer');
|
|
138
136
|
await chatUiStore.sendMessageText('user question');
|
|
@@ -147,7 +145,7 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
147
145
|
// Ensure that question data contains answerId from bot answer
|
|
148
146
|
expect(question.data).toEqual({
|
|
149
147
|
answerId: botAnswer.id,
|
|
150
|
-
selections: undefined
|
|
148
|
+
selections: undefined
|
|
151
149
|
});
|
|
152
150
|
expect(answer.type).toBe('message');
|
|
153
151
|
expect(answer.participant.isAgent).toBe(true);
|
|
@@ -155,32 +153,38 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
155
153
|
expect(answer.data).toEqual(botAnswer);
|
|
156
154
|
expect(log.error).toHaveBeenCalledTimes(0);
|
|
157
155
|
});
|
|
158
|
-
test('should have correct answer ids in user messages for simultaneous messages', async ()
|
|
156
|
+
test('should have correct answer ids in user messages for simultaneous messages', async ()=>{
|
|
159
157
|
store.subscribe();
|
|
160
158
|
mockChatbotSession();
|
|
161
159
|
await runStore();
|
|
162
160
|
ensureChatStarted();
|
|
163
161
|
expect(chatUiStore.messages.length).toBe(1);
|
|
164
162
|
const [botAnswer1, botAnswer2] = mockChatbotAnswers([
|
|
165
|
-
{
|
|
166
|
-
|
|
163
|
+
{
|
|
164
|
+
answer: 'bot answer 1',
|
|
165
|
+
answerId: 111
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
answer: 'bot answer 2',
|
|
169
|
+
answerId: 222
|
|
170
|
+
}
|
|
167
171
|
]);
|
|
168
172
|
await Promise.all([
|
|
169
173
|
chatUiStore.sendMessageText('user question 1'),
|
|
170
|
-
chatUiStore.sendMessageText('user question 2')
|
|
174
|
+
chatUiStore.sendMessageText('user question 2')
|
|
171
175
|
]);
|
|
172
176
|
expect(chatUiStore.messages.length).toBe(5);
|
|
173
177
|
const textMessages = chatUiStore.messages;
|
|
174
|
-
const question1 = textMessages.find(x
|
|
175
|
-
const answer1 = textMessages.find(x
|
|
176
|
-
const question2 = textMessages.find(x
|
|
177
|
-
const answer2 = textMessages.find(x
|
|
178
|
+
const question1 = textMessages.find((x)=>x.message === 'user question 1');
|
|
179
|
+
const answer1 = textMessages.find((x)=>x.message === 'bot answer 1');
|
|
180
|
+
const question2 = textMessages.find((x)=>x.message === 'user question 2');
|
|
181
|
+
const answer2 = textMessages.find((x)=>x.message === 'bot answer 2');
|
|
178
182
|
expect(question1.type).toBe('message');
|
|
179
183
|
expect(question1.participant.isAgent).toBe(false);
|
|
180
184
|
expect(question1.message).toBe('user question 1');
|
|
181
185
|
expect(question1.data).toEqual({
|
|
182
186
|
answerId: botAnswer1.id,
|
|
183
|
-
selections: undefined
|
|
187
|
+
selections: undefined
|
|
184
188
|
});
|
|
185
189
|
expect(answer1.type).toBe('message');
|
|
186
190
|
expect(answer1.participant.isAgent).toBe(true);
|
|
@@ -191,7 +195,7 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
191
195
|
expect(question2.message).toBe('user question 2');
|
|
192
196
|
expect(question2.data).toEqual({
|
|
193
197
|
answerId: botAnswer2.id,
|
|
194
|
-
selections: undefined
|
|
198
|
+
selections: undefined
|
|
195
199
|
});
|
|
196
200
|
expect(answer2.type).toBe('message');
|
|
197
201
|
expect(answer2.participant.isAgent).toBe(true);
|
|
@@ -199,7 +203,7 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
199
203
|
expect(answer2.data).toEqual(botAnswer2);
|
|
200
204
|
expect(log.error).toHaveBeenCalledTimes(0);
|
|
201
205
|
});
|
|
202
|
-
test('should run chatbot with stored session with expiration', async ()
|
|
206
|
+
test('should run chatbot with stored session with expiration', async ()=>{
|
|
203
207
|
mockChatbotSession();
|
|
204
208
|
await jest.advanceTimersByTimeAsync(1000 * 60 * 60 * 16);
|
|
205
209
|
await runStore();
|
|
@@ -209,7 +213,7 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
209
213
|
expect(chatbotApi.postSession).toHaveBeenCalledTimes(0);
|
|
210
214
|
expect(log.error).toHaveBeenCalledTimes(0);
|
|
211
215
|
});
|
|
212
|
-
test('should destroy', async ()
|
|
216
|
+
test('should destroy', async ()=>{
|
|
213
217
|
mockChatbotSession();
|
|
214
218
|
await runStore();
|
|
215
219
|
store.session = ModelsMocks.mockSession();
|
|
@@ -220,7 +224,7 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
220
224
|
expect(store.session).toBeUndefined();
|
|
221
225
|
expect(log.error).toHaveBeenCalledTimes(0);
|
|
222
226
|
});
|
|
223
|
-
test('should restart', async ()
|
|
227
|
+
test('should restart', async ()=>{
|
|
224
228
|
mockChatbotSession();
|
|
225
229
|
await runStore();
|
|
226
230
|
store.session = ModelsMocks.mockSession();
|
|
@@ -230,26 +234,30 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
230
234
|
expect(chatUiStore.status).toBe(ChatRunState.Started);
|
|
231
235
|
expect(log.error).toHaveBeenCalledTimes(0);
|
|
232
236
|
});
|
|
233
|
-
describe('with messages', ()
|
|
234
|
-
test('should send message', async ()
|
|
237
|
+
describe('with messages', ()=>{
|
|
238
|
+
test('should send message', async ()=>{
|
|
235
239
|
mockChatbotSession();
|
|
236
240
|
mockChatbotAnswer('bot answer');
|
|
237
241
|
await runStore();
|
|
238
242
|
await chatUiStore.sendMessageText('user question');
|
|
239
243
|
const message = chatUiStore.messages.at(-1);
|
|
240
|
-
await runChatUiEventListener(store.handleMessageSend, [
|
|
244
|
+
await runChatUiEventListener(store.handleMessageSend, [
|
|
245
|
+
message
|
|
246
|
+
]);
|
|
241
247
|
expect(chatUiStore.messages.length).toBe(3);
|
|
242
248
|
expect(chatUiStore.messages[0].message).toBe(WELCOME_MESSAGE);
|
|
243
249
|
expect(chatUiStore.messages[1].message).toBe('user question');
|
|
244
250
|
expect(chatUiStore.messages[2].message).toBe('bot answer');
|
|
245
251
|
expect(log.error).toHaveBeenCalledTimes(0);
|
|
246
252
|
});
|
|
247
|
-
test('should send message with error', async ()
|
|
253
|
+
test('should send message with error', async ()=>{
|
|
248
254
|
mockChatbotSession();
|
|
249
255
|
chatbotApi.postMessage.mockRejectedValue(new Error('error'));
|
|
250
256
|
await chatUiStore.sendMessageText('user question');
|
|
251
257
|
const message = chatUiStore.messages.at(-1);
|
|
252
|
-
await runChatUiEventListener(store.handleMessageSend, [
|
|
258
|
+
await runChatUiEventListener(store.handleMessageSend, [
|
|
259
|
+
message
|
|
260
|
+
]);
|
|
253
261
|
expect(chatbotApi.postSession).toHaveBeenCalled();
|
|
254
262
|
expect(chatbotApi.postMessage).toHaveBeenCalled();
|
|
255
263
|
expect(chatUiStore.isError).toBe(true);
|
|
@@ -257,61 +265,85 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
257
265
|
category: 'TitanChatbot',
|
|
258
266
|
code: 'TitanChatbot_FailedToSendMessage',
|
|
259
267
|
error: new Error('error'),
|
|
260
|
-
message: 'Failed to send message'
|
|
268
|
+
message: 'Failed to send message'
|
|
261
269
|
});
|
|
262
270
|
});
|
|
263
|
-
test('should use per-request timeoutMs when provided', async ()
|
|
271
|
+
test('should use per-request timeoutMs when provided', async ()=>{
|
|
264
272
|
mockChatbotSession();
|
|
265
|
-
chatbotApi.postMessage.mockImplementation(()
|
|
273
|
+
chatbotApi.postMessage.mockImplementation(()=>new Promise((resolve)=>setTimeout(()=>resolve(ModelsMocks.mockBotMessage({
|
|
274
|
+
answer: 'late answer'
|
|
275
|
+
})), 200)));
|
|
266
276
|
await runStore();
|
|
267
277
|
await chatUiStore.sendMessageText('user question');
|
|
268
278
|
const message = chatUiStore.messages.at(-1);
|
|
269
|
-
const p = runChatUiEventListener(store.handleMessageSend, [
|
|
279
|
+
const p = runChatUiEventListener(store.handleMessageSend, [
|
|
280
|
+
message,
|
|
281
|
+
undefined,
|
|
282
|
+
50
|
|
283
|
+
]);
|
|
270
284
|
await jest.advanceTimersByTimeAsync(50);
|
|
271
285
|
await p;
|
|
272
286
|
expect(chatUiStore.isError).toBe(true);
|
|
273
287
|
expect(log.error).toHaveBeenCalledWith(expect.objectContaining({
|
|
274
288
|
code: 'TitanChatbot_FailedToSendMessage',
|
|
275
|
-
message: 'Failed to send message'
|
|
289
|
+
message: 'Failed to send message'
|
|
276
290
|
}));
|
|
277
291
|
});
|
|
278
|
-
test('should fall back to global timeout when no per-request timeoutMs', async ()
|
|
292
|
+
test('should fall back to global timeout when no per-request timeoutMs', async ()=>{
|
|
279
293
|
mockChatbotSession();
|
|
280
|
-
chatbotApi.postMessage.mockImplementation(()
|
|
281
|
-
|
|
294
|
+
chatbotApi.postMessage.mockImplementation(()=>new Promise((resolve)=>setTimeout(()=>resolve(ModelsMocks.mockBotMessage({
|
|
295
|
+
answer: 'late answer'
|
|
296
|
+
})), 200)));
|
|
297
|
+
chatUiStore.setCustomizationContext({
|
|
298
|
+
timeouts: {
|
|
299
|
+
chatbotRequestTimeoutMs: 100
|
|
300
|
+
}
|
|
301
|
+
});
|
|
282
302
|
await runStore();
|
|
283
303
|
await chatUiStore.sendMessageText('user question');
|
|
284
304
|
const message = chatUiStore.messages.at(-1);
|
|
285
305
|
// No per-request timeoutMs — should use global (100ms)
|
|
286
|
-
const p = runChatUiEventListener(store.handleMessageSend, [
|
|
306
|
+
const p = runChatUiEventListener(store.handleMessageSend, [
|
|
307
|
+
message,
|
|
308
|
+
undefined
|
|
309
|
+
]);
|
|
287
310
|
await jest.advanceTimersByTimeAsync(100);
|
|
288
311
|
await p;
|
|
289
312
|
expect(chatUiStore.isError).toBe(true);
|
|
290
|
-
expect(log.error).toHaveBeenCalledWith(expect.objectContaining({
|
|
313
|
+
expect(log.error).toHaveBeenCalledWith(expect.objectContaining({
|
|
314
|
+
code: 'TitanChatbot_FailedToSendMessage'
|
|
315
|
+
}));
|
|
291
316
|
});
|
|
292
|
-
test('should fall back to DEFAULT timeout when neither per-request nor global timeout is set', async ()
|
|
317
|
+
test('should fall back to DEFAULT timeout when neither per-request nor global timeout is set', async ()=>{
|
|
293
318
|
mockChatbotSession();
|
|
294
|
-
chatbotApi.postMessage.mockImplementation(()
|
|
319
|
+
chatbotApi.postMessage.mockImplementation(()=>new Promise((resolve)=>setTimeout(()=>resolve(ModelsMocks.mockBotMessage({
|
|
320
|
+
answer: 'late answer'
|
|
321
|
+
})), 40000)));
|
|
295
322
|
await runStore();
|
|
296
323
|
await chatUiStore.sendMessageText('user question');
|
|
297
324
|
const message = chatUiStore.messages.at(-1);
|
|
298
325
|
// No per-request timeoutMs, no global timeout — should use DEFAULT (31000ms)
|
|
299
|
-
const p = runChatUiEventListener(store.handleMessageSend, [
|
|
326
|
+
const p = runChatUiEventListener(store.handleMessageSend, [
|
|
327
|
+
message,
|
|
328
|
+
undefined
|
|
329
|
+
]);
|
|
300
330
|
await jest.runOnlyPendingTimersAsync();
|
|
301
331
|
await p;
|
|
302
332
|
expect(chatUiStore.isError).toBe(true);
|
|
303
|
-
expect(log.error).toHaveBeenCalledWith(expect.objectContaining({
|
|
333
|
+
expect(log.error).toHaveBeenCalledWith(expect.objectContaining({
|
|
334
|
+
code: 'TitanChatbot_FailedToSendMessage'
|
|
335
|
+
}));
|
|
304
336
|
});
|
|
305
|
-
test('should not abort store-level controller when per-request timeout fires', async ()
|
|
337
|
+
test('should not abort store-level controller when per-request timeout fires', async ()=>{
|
|
306
338
|
mockChatbotSession();
|
|
307
339
|
/*
|
|
308
340
|
* First message: slow — will time out at 50ms
|
|
309
341
|
* Second message: fast — should succeed despite the first timing out
|
|
310
|
-
*/
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
342
|
+
*/ const fastAnswer = ModelsMocks.mockBotMessage({
|
|
343
|
+
answer: 'fast answer'
|
|
344
|
+
});
|
|
345
|
+
chatbotApi.postMessage.mockImplementationOnce(()=>new Promise(()=>{})) // never resolves — times out
|
|
346
|
+
.mockResolvedValueOnce(fastAnswer);
|
|
315
347
|
await runStore();
|
|
316
348
|
await chatUiStore.sendMessageText('slow question');
|
|
317
349
|
const slowMessage = chatUiStore.messages.at(-1);
|
|
@@ -319,7 +351,7 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
319
351
|
const p1 = runChatUiEventListener(store.handleMessageSend, [
|
|
320
352
|
slowMessage,
|
|
321
353
|
undefined,
|
|
322
|
-
50
|
|
354
|
+
50
|
|
323
355
|
]);
|
|
324
356
|
await jest.advanceTimersByTimeAsync(50);
|
|
325
357
|
await p1;
|
|
@@ -329,15 +361,19 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
329
361
|
chatUiStore.resetError(ChatRunState.Started);
|
|
330
362
|
await chatUiStore.sendMessageText('fast question');
|
|
331
363
|
const fastMessage = chatUiStore.messages.at(-1);
|
|
332
|
-
await runChatUiEventListener(store.handleMessageSend, [
|
|
364
|
+
await runChatUiEventListener(store.handleMessageSend, [
|
|
365
|
+
fastMessage
|
|
366
|
+
]);
|
|
333
367
|
expect(chatUiStore.isError).toBe(false);
|
|
334
368
|
expect(chatUiStore.messages.at(-1)).toMatchObject({
|
|
335
|
-
message: 'fast answer'
|
|
369
|
+
message: 'fast answer'
|
|
336
370
|
});
|
|
337
371
|
});
|
|
338
|
-
test('should preserve per-request timeoutMs on retry', async ()
|
|
372
|
+
test('should preserve per-request timeoutMs on retry', async ()=>{
|
|
339
373
|
mockChatbotSession();
|
|
340
|
-
chatbotApi.postMessage.mockImplementation(()
|
|
374
|
+
chatbotApi.postMessage.mockImplementation(()=>new Promise((resolve)=>setTimeout(()=>resolve(ModelsMocks.mockBotMessage({
|
|
375
|
+
answer: 'late answer'
|
|
376
|
+
})), 200)));
|
|
341
377
|
await runStore();
|
|
342
378
|
await chatUiStore.sendMessageText('user question');
|
|
343
379
|
const message = chatUiStore.messages.at(-1);
|
|
@@ -345,110 +381,155 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
345
381
|
const p1 = runChatUiEventListener(store.handleMessageSend, [
|
|
346
382
|
message,
|
|
347
383
|
undefined,
|
|
348
|
-
50
|
|
384
|
+
50
|
|
349
385
|
]);
|
|
350
386
|
await jest.advanceTimersByTimeAsync(50);
|
|
351
387
|
await p1;
|
|
352
388
|
expect(chatUiStore.isError).toBe(true);
|
|
353
389
|
// Retry should reuse the persisted timeoutMs (50ms), not fall back to default (31000ms)
|
|
354
|
-
chatbotApi.postMessage.mockImplementation(()
|
|
355
|
-
|
|
390
|
+
chatbotApi.postMessage.mockImplementation(()=>new Promise((resolve)=>setTimeout(()=>resolve(ModelsMocks.mockBotMessage({
|
|
391
|
+
answer: 'late answer'
|
|
392
|
+
})), 200)));
|
|
393
|
+
const p2 = runChatUiEventListener(store.handleMessageSendRetry, [
|
|
394
|
+
message
|
|
395
|
+
]);
|
|
356
396
|
await jest.advanceTimersByTimeAsync(50);
|
|
357
397
|
await p2;
|
|
358
398
|
// If retry had fallen back to default 31000ms, it would not have timed out in 50ms
|
|
359
|
-
expect(log.error).toHaveBeenCalledWith(expect.objectContaining({
|
|
399
|
+
expect(log.error).toHaveBeenCalledWith(expect.objectContaining({
|
|
400
|
+
code: 'TitanChatbot_FailedToSendMessage'
|
|
401
|
+
}));
|
|
360
402
|
});
|
|
361
|
-
test('should send message retry', async ()
|
|
403
|
+
test('should send message retry', async ()=>{
|
|
362
404
|
mockChatbotSession();
|
|
363
405
|
const spyMessage = jest.spyOn(chatbotApi, 'postMessage');
|
|
364
406
|
// Retry with non-text message should not call "message"
|
|
365
407
|
const messageNonText = ModelsMocks.mockChatMessageModel({
|
|
366
|
-
type: 'welcome'
|
|
408
|
+
type: 'welcome'
|
|
367
409
|
});
|
|
368
|
-
await runChatUiEventListener(store.handleMessageSendRetry, [
|
|
410
|
+
await runChatUiEventListener(store.handleMessageSendRetry, [
|
|
411
|
+
messageNonText
|
|
412
|
+
]);
|
|
369
413
|
expect(spyMessage).not.toHaveBeenCalled();
|
|
370
414
|
// Retry with text message should call "message"
|
|
371
415
|
const message = ModelsMocks.mockChatMessageModel({
|
|
372
|
-
message: 'message'
|
|
416
|
+
message: 'message'
|
|
373
417
|
});
|
|
374
|
-
await runChatUiEventListener(store.handleMessageSendRetry, [
|
|
418
|
+
await runChatUiEventListener(store.handleMessageSendRetry, [
|
|
419
|
+
message
|
|
420
|
+
]);
|
|
375
421
|
expect(spyMessage).toHaveBeenCalledWith(ModelsMocks.mockUserMessage({
|
|
376
422
|
context: undefined,
|
|
377
423
|
selections: undefined,
|
|
378
|
-
question: 'message'
|
|
424
|
+
question: 'message'
|
|
379
425
|
}), expect.any(AbortSignal));
|
|
380
426
|
});
|
|
381
427
|
});
|
|
382
|
-
describe('with session start', ()
|
|
383
|
-
const createSession = (id)
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
428
|
+
describe('with session start', ()=>{
|
|
429
|
+
const createSession = (id)=>ModelsMocks.mockSession({
|
|
430
|
+
id,
|
|
431
|
+
data: {
|
|
432
|
+
custom: 'data'
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
test('should start session', async ()=>{
|
|
388
436
|
const spyGetData = jest.spyOn(store, 'getSessionData').mockResolvedValue({
|
|
389
|
-
defaultData: 'defaultData'
|
|
437
|
+
defaultData: 'defaultData'
|
|
390
438
|
});
|
|
391
439
|
chatbotApi.postSession.mockResolvedValue(createSession(1));
|
|
392
440
|
const { session } = await runChatUiEventListener(store.handleSessionStart, [
|
|
393
|
-
{
|
|
441
|
+
{
|
|
442
|
+
custom: 'data'
|
|
443
|
+
}
|
|
394
444
|
]);
|
|
395
445
|
expect(spyGetData).toHaveBeenCalled();
|
|
396
446
|
expect(session).toEqual(createSession(1));
|
|
397
447
|
expect(chatbotApi.postSession).toHaveBeenCalledWith({
|
|
398
|
-
data: {
|
|
448
|
+
data: {
|
|
449
|
+
custom: 'data',
|
|
450
|
+
defaultData: 'defaultData'
|
|
451
|
+
}
|
|
399
452
|
}, expect.any(AbortSignal));
|
|
400
453
|
});
|
|
401
|
-
test('should handle multiple calls', async ()
|
|
454
|
+
test('should handle multiple calls', async ()=>{
|
|
402
455
|
chatbotApi.postSession.mockResolvedValue(createSession(1));
|
|
403
|
-
const p1 = runChatUiEventListener(store.handleSessionStart, [
|
|
404
|
-
|
|
405
|
-
|
|
456
|
+
const p1 = runChatUiEventListener(store.handleSessionStart, [
|
|
457
|
+
{
|
|
458
|
+
custom: 'data'
|
|
459
|
+
}
|
|
460
|
+
]);
|
|
461
|
+
const p2 = runChatUiEventListener(store.handleSessionStart, [
|
|
462
|
+
{
|
|
463
|
+
custom: 'data'
|
|
464
|
+
}
|
|
465
|
+
]);
|
|
466
|
+
const [r1, r2] = await Promise.all([
|
|
467
|
+
p1,
|
|
468
|
+
p2
|
|
469
|
+
]);
|
|
406
470
|
expect(r1.session).toEqual(createSession(1));
|
|
407
471
|
expect(r2.session).toEqual(createSession(1));
|
|
408
472
|
expect(chatbotApi.postSession).toHaveBeenCalledTimes(1);
|
|
409
473
|
expect(chatbotApi.postSession).toHaveBeenCalledWith({
|
|
410
|
-
data: {
|
|
474
|
+
data: {
|
|
475
|
+
custom: 'data'
|
|
476
|
+
}
|
|
411
477
|
}, expect.any(AbortSignal));
|
|
412
478
|
});
|
|
413
|
-
test('should handle forced calls', async ()
|
|
479
|
+
test('should handle forced calls', async ()=>{
|
|
414
480
|
chatbotApi.postSession.mockResolvedValue(createSession(1));
|
|
415
481
|
const { session } = await runChatUiEventListener(store.handleSessionStart, [
|
|
416
|
-
{
|
|
482
|
+
{
|
|
483
|
+
custom: 'data'
|
|
484
|
+
}
|
|
417
485
|
]);
|
|
418
486
|
chatbotApi.postSession.mockResolvedValue(createSession(2));
|
|
419
|
-
const { session: session2 } = await runChatUiEventListener(store.handleSessionStart, [
|
|
487
|
+
const { session: session2 } = await runChatUiEventListener(store.handleSessionStart, [
|
|
488
|
+
{
|
|
489
|
+
custom: 'data'
|
|
490
|
+
}
|
|
491
|
+
]);
|
|
420
492
|
expect(chatbotApi.postSession).toHaveBeenCalledTimes(1);
|
|
421
493
|
expect(session === null || session === void 0 ? void 0 : session.id).toEqual(1);
|
|
422
494
|
expect(session2 === null || session2 === void 0 ? void 0 : session2.id).toEqual(1);
|
|
423
495
|
expect(session === session2).toBe(true);
|
|
424
496
|
// Make api call return another session object and ensure that after
|
|
425
497
|
chatbotApi.postSession.mockResolvedValue(createSession(3));
|
|
426
|
-
const { session: session3 } = await runChatUiEventListener(store.handleSessionStart, [
|
|
498
|
+
const { session: session3 } = await runChatUiEventListener(store.handleSessionStart, [
|
|
499
|
+
{
|
|
500
|
+
custom: 'data'
|
|
501
|
+
},
|
|
502
|
+
true
|
|
503
|
+
]);
|
|
427
504
|
expect(chatbotApi.postSession).toHaveBeenCalledTimes(2);
|
|
428
505
|
expect(session3 === null || session3 === void 0 ? void 0 : session3.id).toEqual(3);
|
|
429
506
|
expect(session === session3).toBe(false);
|
|
430
507
|
});
|
|
431
508
|
});
|
|
432
|
-
describe('with session feedback', ()
|
|
433
|
-
const createSessionFeedback = ()
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
test('should send feedback', async ()
|
|
509
|
+
describe('with session feedback', ()=>{
|
|
510
|
+
const createSessionFeedback = ()=>ModelsMocks.mockFeedback({
|
|
511
|
+
sessionId: 1,
|
|
512
|
+
messageId: undefined,
|
|
513
|
+
rating: Models.FeedbackRatings.ThumbsUp,
|
|
514
|
+
description: 'description'
|
|
515
|
+
});
|
|
516
|
+
test('should send feedback', async ()=>{
|
|
440
517
|
mockChatbotSession();
|
|
441
518
|
chatbotApi.postFeedback.mockResolvedValueOnce(createSessionFeedback());
|
|
442
|
-
const { feedback, state } = await runChatUiEventListener(store.handleSessionFeedback, [
|
|
519
|
+
const { feedback, state } = await runChatUiEventListener(store.handleSessionFeedback, [
|
|
520
|
+
createSessionFeedback()
|
|
521
|
+
]);
|
|
443
522
|
expect(state).toBe(Models.ChatbotFeedbackState.Success);
|
|
444
523
|
expect(feedback).toEqual(createSessionFeedback());
|
|
445
524
|
expect(chatbotApi.postSession).toHaveBeenCalled();
|
|
446
525
|
expect(chatbotApi.postFeedback).toHaveBeenCalledWith(createSessionFeedback(), expect.any(AbortSignal));
|
|
447
526
|
});
|
|
448
|
-
test('should send feedback with session error', async ()
|
|
527
|
+
test('should send feedback with session error', async ()=>{
|
|
449
528
|
chatbotApi.postSession.mockRejectedValueOnce('session error');
|
|
450
529
|
chatbotApi.postFeedback.mockResolvedValueOnce(createSessionFeedback());
|
|
451
|
-
const { feedback, state } = await runChatUiEventListener(store.handleSessionFeedback, [
|
|
530
|
+
const { feedback, state } = await runChatUiEventListener(store.handleSessionFeedback, [
|
|
531
|
+
createSessionFeedback()
|
|
532
|
+
]);
|
|
452
533
|
expect(state).toBe(Models.ChatbotFeedbackState.Failure);
|
|
453
534
|
expect(feedback).toEqual(createSessionFeedback());
|
|
454
535
|
expect(chatbotApi.postSession).toHaveBeenCalled();
|
|
@@ -458,14 +539,16 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
458
539
|
category: 'TitanChatbot',
|
|
459
540
|
code: 'TitanChatbot_FailedToSendFeedback',
|
|
460
541
|
error: 'session error',
|
|
461
|
-
message: 'Failed to send feedback'
|
|
542
|
+
message: 'Failed to send feedback'
|
|
462
543
|
});
|
|
463
544
|
});
|
|
464
|
-
test('should send feedback with error', async ()
|
|
545
|
+
test('should send feedback with error', async ()=>{
|
|
465
546
|
mockChatbotSession();
|
|
466
547
|
chatbotApi.postSession.mockReset().mockRejectedValue(new Error('session error'));
|
|
467
548
|
chatbotApi.postFeedback.mockResolvedValueOnce(createSessionFeedback());
|
|
468
|
-
const { feedback, state } = await runChatUiEventListener(store.handleSessionFeedback, [
|
|
549
|
+
const { feedback, state } = await runChatUiEventListener(store.handleSessionFeedback, [
|
|
550
|
+
createSessionFeedback()
|
|
551
|
+
]);
|
|
469
552
|
expect(state).toBe(Models.ChatbotFeedbackState.Failure);
|
|
470
553
|
expect(feedback).toEqual(createSessionFeedback());
|
|
471
554
|
expect(chatbotApi.postSession).toHaveBeenCalled();
|
|
@@ -475,82 +558,94 @@ describe('[ChatbotUiBackendStore]', () => {
|
|
|
475
558
|
category: 'TitanChatbot',
|
|
476
559
|
code: 'TitanChatbot_FailedToSendFeedback',
|
|
477
560
|
error: new Error('session error'),
|
|
478
|
-
message: 'Failed to send feedback'
|
|
561
|
+
message: 'Failed to send feedback'
|
|
479
562
|
});
|
|
480
563
|
});
|
|
481
564
|
});
|
|
482
|
-
describe('with message feedback', ()
|
|
483
|
-
const createMessageFeedback = ()
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
565
|
+
describe('with message feedback', ()=>{
|
|
566
|
+
const createMessageFeedback = ()=>ModelsMocks.mockFeedback({
|
|
567
|
+
sessionId: 1,
|
|
568
|
+
messageId: 1,
|
|
569
|
+
description: 'description',
|
|
570
|
+
linkUrl: 'linkUrl',
|
|
571
|
+
options: [
|
|
572
|
+
Models.FeedbackOptions.Unclear,
|
|
573
|
+
Models.FeedbackOptions.Incorrect
|
|
574
|
+
],
|
|
575
|
+
rating: Models.FeedbackRatings.ThumbsUp
|
|
576
|
+
});
|
|
577
|
+
const createLogError = (errorMessage)=>({
|
|
578
|
+
category: 'TitanChatbot',
|
|
579
|
+
code: 'TitanChatbot_FailedToSendMessageFeedback',
|
|
580
|
+
error: errorMessage,
|
|
581
|
+
message: 'Failed to send message feedback'
|
|
582
|
+
});
|
|
583
|
+
test('should assert message feedback 1', async ()=>{
|
|
584
|
+
var _chatUiStore_error;
|
|
499
585
|
const { feedback, state } = await runChatUiEventListener(store.handleMessageFeedback, []);
|
|
500
586
|
expect(feedback).toBeUndefined();
|
|
501
587
|
expect(state).toBe(Models.ChatbotFeedbackState.Failure);
|
|
502
588
|
expect(chatUiStore.isError).toBe(true);
|
|
503
|
-
expect((
|
|
589
|
+
expect((_chatUiStore_error = chatUiStore.error) === null || _chatUiStore_error === void 0 ? void 0 : _chatUiStore_error.message).toBe('Failed to send message feedback');
|
|
504
590
|
expect(log.error).toHaveBeenCalledWith({
|
|
505
591
|
category: 'TitanChatbot',
|
|
506
592
|
code: 'TitanChatbot_FailedToSendMessageFeedback',
|
|
507
593
|
error: new ChatError('Message feedback is missing.'),
|
|
508
|
-
message: 'Failed to send message feedback'
|
|
594
|
+
message: 'Failed to send message feedback'
|
|
509
595
|
});
|
|
510
596
|
expect(chatbotApi.postFeedback).not.toHaveBeenCalled();
|
|
511
597
|
});
|
|
512
|
-
test('should assert message feedback 3', async ()
|
|
513
|
-
var
|
|
598
|
+
test('should assert message feedback 3', async ()=>{
|
|
599
|
+
var _chatUiStore_error;
|
|
514
600
|
chatbotApi.postSession.mockRejectedValueOnce('session error');
|
|
515
|
-
const { feedback, state } = await runChatUiEventListener(store.handleMessageFeedback, [
|
|
601
|
+
const { feedback, state } = await runChatUiEventListener(store.handleMessageFeedback, [
|
|
602
|
+
createMessageFeedback()
|
|
603
|
+
]);
|
|
516
604
|
expect(state).toBe(Models.ChatbotFeedbackState.Failure);
|
|
517
605
|
expect(feedback).toEqual(createMessageFeedback());
|
|
518
606
|
expect(chatUiStore.isError).toBe(true);
|
|
519
|
-
expect((
|
|
607
|
+
expect((_chatUiStore_error = chatUiStore.error) === null || _chatUiStore_error === void 0 ? void 0 : _chatUiStore_error.message).toBe('Failed to send message feedback');
|
|
520
608
|
expect(log.error).toHaveBeenCalledWith({
|
|
521
609
|
category: 'TitanChatbot',
|
|
522
610
|
code: 'TitanChatbot_FailedToSendMessageFeedback',
|
|
523
611
|
error: 'session error',
|
|
524
|
-
message: 'Failed to send message feedback'
|
|
612
|
+
message: 'Failed to send message feedback'
|
|
525
613
|
});
|
|
526
614
|
expect(chatbotApi.postFeedback).not.toHaveBeenCalled();
|
|
527
615
|
});
|
|
528
|
-
test('should send message feedback', async ()
|
|
616
|
+
test('should send message feedback', async ()=>{
|
|
529
617
|
mockChatbotSession();
|
|
530
618
|
chatbotApi.postFeedback.mockResolvedValueOnce(createMessageFeedback());
|
|
531
619
|
const feedback = createMessageFeedback();
|
|
532
|
-
await runChatUiEventListener(store.handleMessageFeedback, [
|
|
620
|
+
await runChatUiEventListener(store.handleMessageFeedback, [
|
|
621
|
+
feedback
|
|
622
|
+
]);
|
|
533
623
|
expect(chatbotApi.postFeedback).toHaveBeenCalledWith({
|
|
534
|
-
...feedback
|
|
624
|
+
...feedback
|
|
535
625
|
}, expect.any(AbortSignal));
|
|
536
626
|
});
|
|
537
|
-
test('should send message feedback with session error', async ()
|
|
627
|
+
test('should send message feedback with session error', async ()=>{
|
|
538
628
|
chatbotApi.postSession.mockRejectedValueOnce('session error');
|
|
539
629
|
chatbotApi.postFeedback.mockResolvedValueOnce(createMessageFeedback());
|
|
540
630
|
const feedback = createMessageFeedback();
|
|
541
|
-
await runChatUiEventListener(store.handleMessageFeedback, [
|
|
631
|
+
await runChatUiEventListener(store.handleMessageFeedback, [
|
|
632
|
+
feedback
|
|
633
|
+
]);
|
|
542
634
|
expect(chatbotApi.postFeedback).not.toHaveBeenCalled();
|
|
543
635
|
expect(log.error).toHaveBeenCalledWith(createLogError('session error'));
|
|
544
636
|
});
|
|
545
|
-
test('should send message feedback with feedback error', async ()
|
|
637
|
+
test('should send message feedback with feedback error', async ()=>{
|
|
546
638
|
mockChatbotSession();
|
|
547
639
|
chatbotApi.postFeedback.mockRejectedValueOnce('feedback error');
|
|
548
640
|
const feedback = createMessageFeedback();
|
|
549
|
-
await runChatUiEventListener(store.handleMessageFeedback, [
|
|
641
|
+
await runChatUiEventListener(store.handleMessageFeedback, [
|
|
642
|
+
feedback
|
|
643
|
+
]);
|
|
550
644
|
expect(chatbotApi.postFeedback).toHaveBeenCalledTimes(1);
|
|
551
645
|
expect(log.error).toHaveBeenCalledWith(createLogError('feedback error'));
|
|
552
646
|
});
|
|
553
647
|
});
|
|
554
648
|
});
|
|
555
649
|
});
|
|
650
|
+
|
|
556
651
|
//# sourceMappingURL=chatbot-ui-backend.store.test.js.map
|