@servicetitan/titan-chatbot-ui-cypress 3.1.0 → 3.1.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.
Files changed (173) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +3 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/tests/index.d.ts +30 -0
  7. package/dist/tests/index.d.ts.map +1 -0
  8. package/dist/tests/index.js +30 -0
  9. package/dist/tests/index.js.map +1 -0
  10. package/dist/tests/titan-chat-ui/chat-error.shared-tests.d.ts +3 -0
  11. package/dist/tests/titan-chat-ui/chat-error.shared-tests.d.ts.map +1 -0
  12. package/dist/tests/titan-chat-ui/chat-error.shared-tests.js +138 -0
  13. package/dist/tests/titan-chat-ui/chat-error.shared-tests.js.map +1 -0
  14. package/dist/tests/titan-chat-ui/chat-input-file.shared-tests.d.ts +7 -0
  15. package/dist/tests/titan-chat-ui/chat-input-file.shared-tests.d.ts.map +1 -0
  16. package/dist/tests/titan-chat-ui/chat-input-file.shared-tests.js +123 -0
  17. package/dist/tests/titan-chat-ui/chat-input-file.shared-tests.js.map +1 -0
  18. package/dist/tests/titan-chat-ui/chat-input.shared-tests.d.ts +3 -0
  19. package/dist/tests/titan-chat-ui/chat-input.shared-tests.d.ts.map +1 -0
  20. package/dist/tests/titan-chat-ui/chat-input.shared-tests.js +71 -0
  21. package/dist/tests/titan-chat-ui/chat-input.shared-tests.js.map +1 -0
  22. package/dist/tests/titan-chat-ui/chat-log.shared-tests.d.ts +9 -0
  23. package/dist/tests/titan-chat-ui/chat-log.shared-tests.d.ts.map +1 -0
  24. package/dist/tests/titan-chat-ui/chat-log.shared-tests.js +73 -0
  25. package/dist/tests/titan-chat-ui/chat-log.shared-tests.js.map +1 -0
  26. package/dist/tests/titan-chat-ui/chat-messages.shared-tests.d.ts +8 -0
  27. package/dist/tests/titan-chat-ui/chat-messages.shared-tests.d.ts.map +1 -0
  28. package/dist/tests/titan-chat-ui/chat-messages.shared-tests.js +118 -0
  29. package/dist/tests/titan-chat-ui/chat-messages.shared-tests.js.map +1 -0
  30. package/dist/tests/titan-chat-ui/chat-notifications.shared-tests.d.ts +3 -0
  31. package/dist/tests/titan-chat-ui/chat-notifications.shared-tests.d.ts.map +1 -0
  32. package/dist/tests/titan-chat-ui/chat-notifications.shared-tests.js +110 -0
  33. package/dist/tests/titan-chat-ui/chat-notifications.shared-tests.js.map +1 -0
  34. package/dist/tests/titan-chat-ui/chat-timer.shared-tests.d.ts +3 -0
  35. package/dist/tests/titan-chat-ui/chat-timer.shared-tests.d.ts.map +1 -0
  36. package/dist/tests/titan-chat-ui/chat-timer.shared-tests.js +76 -0
  37. package/dist/tests/titan-chat-ui/chat-timer.shared-tests.js.map +1 -0
  38. package/dist/tests/titan-chat-ui/chat.shared-tests.d.ts +9 -0
  39. package/dist/tests/titan-chat-ui/chat.shared-tests.d.ts.map +1 -0
  40. package/dist/tests/titan-chat-ui/chat.shared-tests.js +111 -0
  41. package/dist/tests/titan-chat-ui/chat.shared-tests.js.map +1 -0
  42. package/dist/tests/titan-chat-ui/message-agent.shared-tests.d.ts +27 -0
  43. package/dist/tests/titan-chat-ui/message-agent.shared-tests.d.ts.map +1 -0
  44. package/dist/tests/titan-chat-ui/message-agent.shared-tests.js +67 -0
  45. package/dist/tests/titan-chat-ui/message-agent.shared-tests.js.map +1 -0
  46. package/dist/tests/titan-chat-ui/message-content-file.shared-tests.d.ts +10 -0
  47. package/dist/tests/titan-chat-ui/message-content-file.shared-tests.d.ts.map +1 -0
  48. package/dist/tests/titan-chat-ui/message-content-file.shared-tests.js +88 -0
  49. package/dist/tests/titan-chat-ui/message-content-file.shared-tests.js.map +1 -0
  50. package/dist/tests/titan-chat-ui/message-system.shared-tests.d.ts +16 -0
  51. package/dist/tests/titan-chat-ui/message-system.shared-tests.d.ts.map +1 -0
  52. package/dist/tests/titan-chat-ui/message-system.shared-tests.js +65 -0
  53. package/dist/tests/titan-chat-ui/message-system.shared-tests.js.map +1 -0
  54. package/dist/tests/titan-chat-ui/message-timeout.shared-tests.d.ts +8 -0
  55. package/dist/tests/titan-chat-ui/message-timeout.shared-tests.d.ts.map +1 -0
  56. package/dist/tests/titan-chat-ui/message-timeout.shared-tests.js +63 -0
  57. package/dist/tests/titan-chat-ui/message-timeout.shared-tests.js.map +1 -0
  58. package/dist/tests/titan-chat-ui/message-typing.shared-tests.d.ts +12 -0
  59. package/dist/tests/titan-chat-ui/message-typing.shared-tests.d.ts.map +1 -0
  60. package/dist/tests/titan-chat-ui/message-typing.shared-tests.js +46 -0
  61. package/dist/tests/titan-chat-ui/message-typing.shared-tests.js.map +1 -0
  62. package/dist/tests/titan-chat-ui/message-user.shared-tests.d.ts +10 -0
  63. package/dist/tests/titan-chat-ui/message-user.shared-tests.d.ts.map +1 -0
  64. package/dist/tests/titan-chat-ui/message-user.shared-tests.js +64 -0
  65. package/dist/tests/titan-chat-ui/message-user.shared-tests.js.map +1 -0
  66. package/dist/tests/titan-chatbot-ui/chatbot-filters.shared-tests.d.ts +7 -0
  67. package/dist/tests/titan-chatbot-ui/chatbot-filters.shared-tests.d.ts.map +1 -0
  68. package/dist/tests/titan-chatbot-ui/chatbot-filters.shared-tests.js +118 -0
  69. package/dist/tests/titan-chatbot-ui/chatbot-filters.shared-tests.js.map +1 -0
  70. package/dist/tests/titan-chatbot-ui/chatbot-help-center.shared-tests.d.ts +9 -0
  71. package/dist/tests/titan-chatbot-ui/chatbot-help-center.shared-tests.d.ts.map +1 -0
  72. package/dist/tests/titan-chatbot-ui/chatbot-help-center.shared-tests.js +162 -0
  73. package/dist/tests/titan-chatbot-ui/chatbot-help-center.shared-tests.js.map +1 -0
  74. package/dist/tests/titan-chatbot-ui/chatbot-links.shared-tests.d.ts +15 -0
  75. package/dist/tests/titan-chatbot-ui/chatbot-links.shared-tests.d.ts.map +1 -0
  76. package/dist/tests/titan-chatbot-ui/chatbot-links.shared-tests.js +123 -0
  77. package/dist/tests/titan-chatbot-ui/chatbot-links.shared-tests.js.map +1 -0
  78. package/dist/tests/titan-chatbot-ui/chatbot-live.shared-tests.d.ts +9 -0
  79. package/dist/tests/titan-chatbot-ui/chatbot-live.shared-tests.d.ts.map +1 -0
  80. package/dist/tests/titan-chatbot-ui/chatbot-live.shared-tests.js +84 -0
  81. package/dist/tests/titan-chatbot-ui/chatbot-live.shared-tests.js.map +1 -0
  82. package/dist/tests/titan-chatbot-ui/chatbot-message-answer-readonly.shared-tests.d.ts +8 -0
  83. package/dist/tests/titan-chatbot-ui/chatbot-message-answer-readonly.shared-tests.d.ts.map +1 -0
  84. package/dist/tests/titan-chatbot-ui/chatbot-message-answer-readonly.shared-tests.js +142 -0
  85. package/dist/tests/titan-chatbot-ui/chatbot-message-answer-readonly.shared-tests.js.map +1 -0
  86. package/dist/tests/titan-chatbot-ui/chatbot-message-answer.shared-tests.d.ts +8 -0
  87. package/dist/tests/titan-chatbot-ui/chatbot-message-answer.shared-tests.d.ts.map +1 -0
  88. package/dist/tests/titan-chatbot-ui/chatbot-message-answer.shared-tests.js +105 -0
  89. package/dist/tests/titan-chatbot-ui/chatbot-message-answer.shared-tests.js.map +1 -0
  90. package/dist/tests/titan-chatbot-ui/chatbot-message-feedback-form-guardrail.shared-tests.d.ts +3 -0
  91. package/dist/tests/titan-chatbot-ui/chatbot-message-feedback-form-guardrail.shared-tests.d.ts.map +1 -0
  92. package/dist/tests/titan-chatbot-ui/chatbot-message-feedback-form-guardrail.shared-tests.js +86 -0
  93. package/dist/tests/titan-chatbot-ui/chatbot-message-feedback-form-guardrail.shared-tests.js.map +1 -0
  94. package/dist/tests/titan-chatbot-ui/chatbot-message-feedback-form.shared-tests.d.ts +3 -0
  95. package/dist/tests/titan-chatbot-ui/chatbot-message-feedback-form.shared-tests.d.ts.map +1 -0
  96. package/dist/tests/titan-chatbot-ui/chatbot-message-feedback-form.shared-tests.js +143 -0
  97. package/dist/tests/titan-chatbot-ui/chatbot-message-feedback-form.shared-tests.js.map +1 -0
  98. package/dist/tests/titan-chatbot-ui/chatbot-message-feedback-popover.shared-tests.d.ts +8 -0
  99. package/dist/tests/titan-chatbot-ui/chatbot-message-feedback-popover.shared-tests.d.ts.map +1 -0
  100. package/dist/tests/titan-chatbot-ui/chatbot-message-feedback-popover.shared-tests.js +200 -0
  101. package/dist/tests/titan-chatbot-ui/chatbot-message-feedback-popover.shared-tests.js.map +1 -0
  102. package/dist/tests/titan-chatbot-ui/chatbot-message-typing.shared-tests.d.ts +11 -0
  103. package/dist/tests/titan-chatbot-ui/chatbot-message-typing.shared-tests.d.ts.map +1 -0
  104. package/dist/tests/titan-chatbot-ui/chatbot-message-typing.shared-tests.js +81 -0
  105. package/dist/tests/titan-chatbot-ui/chatbot-message-typing.shared-tests.js.map +1 -0
  106. package/dist/tests/titan-chatbot-ui/chatbot-restart-dialog.shared-tests.d.ts +8 -0
  107. package/dist/tests/titan-chatbot-ui/chatbot-restart-dialog.shared-tests.d.ts.map +1 -0
  108. package/dist/tests/titan-chatbot-ui/chatbot-restart-dialog.shared-tests.js +60 -0
  109. package/dist/tests/titan-chatbot-ui/chatbot-restart-dialog.shared-tests.js.map +1 -0
  110. package/dist/tests/titan-chatbot-ui/chatbot-restart-link.shared-tests.d.ts +8 -0
  111. package/dist/tests/titan-chatbot-ui/chatbot-restart-link.shared-tests.d.ts.map +1 -0
  112. package/dist/tests/titan-chatbot-ui/chatbot-restart-link.shared-tests.js +77 -0
  113. package/dist/tests/titan-chatbot-ui/chatbot-restart-link.shared-tests.js.map +1 -0
  114. package/dist/tests/titan-chatbot-ui/chatbot-session-feedback-modal.shared-tests.d.ts +7 -0
  115. package/dist/tests/titan-chatbot-ui/chatbot-session-feedback-modal.shared-tests.d.ts.map +1 -0
  116. package/dist/tests/titan-chatbot-ui/chatbot-session-feedback-modal.shared-tests.js +130 -0
  117. package/dist/tests/titan-chatbot-ui/chatbot-session-feedback-modal.shared-tests.js.map +1 -0
  118. package/dist/tests/titan-chatbot-ui/chatbot-titan-chatbot.shared-tests.d.ts +9 -0
  119. package/dist/tests/titan-chatbot-ui/chatbot-titan-chatbot.shared-tests.d.ts.map +1 -0
  120. package/dist/tests/titan-chatbot-ui/chatbot-titan-chatbot.shared-tests.js +157 -0
  121. package/dist/tests/titan-chatbot-ui/chatbot-titan-chatbot.shared-tests.js.map +1 -0
  122. package/dist/tests/titan-chatbot-ui/chatbot.shared-tests.d.ts +9 -0
  123. package/dist/tests/titan-chatbot-ui/chatbot.shared-tests.d.ts.map +1 -0
  124. package/dist/tests/titan-chatbot-ui/chatbot.shared-tests.js +114 -0
  125. package/dist/tests/titan-chatbot-ui/chatbot.shared-tests.js.map +1 -0
  126. package/dist/utils/chat-ui-selectors.d.ts +12 -0
  127. package/dist/utils/chat-ui-selectors.d.ts.map +1 -1
  128. package/dist/utils/chat-ui-selectors.js +24 -0
  129. package/dist/utils/chat-ui-selectors.js.map +1 -1
  130. package/dist/utils/test-utils-chatbot.d.ts +5 -0
  131. package/dist/utils/test-utils-chatbot.d.ts.map +1 -0
  132. package/dist/utils/test-utils-chatbot.js +55 -0
  133. package/dist/utils/test-utils-chatbot.js.map +1 -0
  134. package/dist/utils/test-utils.d.ts +6 -0
  135. package/dist/utils/test-utils.d.ts.map +1 -0
  136. package/dist/utils/test-utils.js +38 -0
  137. package/dist/utils/test-utils.js.map +1 -0
  138. package/package.json +10 -5
  139. package/src/index.ts +3 -0
  140. package/src/tests/index.ts +30 -0
  141. package/src/tests/titan-chat-ui/chat-error.shared-tests.tsx +185 -0
  142. package/src/tests/titan-chat-ui/chat-input-file.shared-tests.tsx +182 -0
  143. package/src/tests/titan-chat-ui/chat-input.shared-tests.tsx +99 -0
  144. package/src/tests/titan-chat-ui/chat-log.shared-tests.tsx +117 -0
  145. package/src/tests/titan-chat-ui/chat-messages.shared-tests.tsx +156 -0
  146. package/src/tests/titan-chat-ui/chat-notifications.shared-tests.tsx +153 -0
  147. package/src/tests/titan-chat-ui/chat-timer.shared-tests.tsx +106 -0
  148. package/src/tests/titan-chat-ui/chat.shared-tests.tsx +158 -0
  149. package/src/tests/titan-chat-ui/message-agent.shared-tests.tsx +170 -0
  150. package/src/tests/titan-chat-ui/message-content-file.shared-tests.tsx +139 -0
  151. package/src/tests/titan-chat-ui/message-system.shared-tests.tsx +147 -0
  152. package/src/tests/titan-chat-ui/message-timeout.shared-tests.tsx +117 -0
  153. package/src/tests/titan-chat-ui/message-typing.shared-tests.tsx +92 -0
  154. package/src/tests/titan-chat-ui/message-user.shared-tests.tsx +138 -0
  155. package/src/tests/titan-chatbot-ui/chatbot-filters.shared-tests.tsx +164 -0
  156. package/src/tests/titan-chatbot-ui/chatbot-help-center.shared-tests.tsx +225 -0
  157. package/src/tests/titan-chatbot-ui/chatbot-links.shared-tests.tsx +189 -0
  158. package/src/tests/titan-chatbot-ui/chatbot-live.shared-tests.tsx +127 -0
  159. package/src/tests/titan-chatbot-ui/chatbot-message-answer-readonly.shared-tests.tsx +187 -0
  160. package/src/tests/titan-chatbot-ui/chatbot-message-answer.shared-tests.tsx +144 -0
  161. package/src/tests/titan-chatbot-ui/chatbot-message-feedback-form-guardrail.shared-tests.tsx +127 -0
  162. package/src/tests/titan-chatbot-ui/chatbot-message-feedback-form.shared-tests.tsx +198 -0
  163. package/src/tests/titan-chatbot-ui/chatbot-message-feedback-popover.shared-tests.tsx +285 -0
  164. package/src/tests/titan-chatbot-ui/chatbot-message-typing.shared-tests.tsx +112 -0
  165. package/src/tests/titan-chatbot-ui/chatbot-restart-dialog.shared-tests.tsx +91 -0
  166. package/src/tests/titan-chatbot-ui/chatbot-restart-link.shared-tests.tsx +116 -0
  167. package/src/tests/titan-chatbot-ui/chatbot-session-feedback-modal.shared-tests.tsx +182 -0
  168. package/src/tests/titan-chatbot-ui/chatbot-titan-chatbot.shared-tests.tsx +221 -0
  169. package/src/tests/titan-chatbot-ui/chatbot.shared-tests.tsx +158 -0
  170. package/src/utils/chat-ui-selectors.ts +24 -0
  171. package/src/utils/test-utils-chatbot.tsx +73 -0
  172. package/src/utils/test-utils.tsx +52 -0
  173. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,221 @@
1
+ import { ILog, Log } from '@servicetitan/log-service';
2
+ import { Container, Provider } from '@servicetitan/react-ioc';
3
+ import {
4
+ ApiClientTitanChat,
5
+ CHATBOT_API_CLIENT,
6
+ CHATBOT_CLIENT_SETTINGS,
7
+ CHATBOT_UI_BACKEND_STORE_TOKEN,
8
+ CHATBOT_UI_STORE_TOKEN,
9
+ ChatbotCustomizations,
10
+ ChatbotUiBackendStore,
11
+ ChatbotUiStore,
12
+ IChatbotApiClient,
13
+ IChatbotUiBackendStore,
14
+ IChatbotUiStore,
15
+ Models,
16
+ } from '@servicetitan/titan-chatbot-api';
17
+ import { mount } from 'cypress/react';
18
+ import { FC, ReactElement, useMemo } from 'react';
19
+ import { CypressMocks } from '../..';
20
+ import { ChatUiSelectors } from '../../utils/chat-ui-selectors';
21
+
22
+ const ChatbotBaseUrl = 'https://chatbot-api.example.com/base/url';
23
+ const ChatbotVersion = 2;
24
+
25
+ const initializeTitanChatbotContainer = () => {
26
+ const rootContainer = new Container();
27
+ const container = new Container();
28
+ container.parent = rootContainer;
29
+ container.bind<ILog>(Log).to(CypressMocks.LogMock).inSingletonScope();
30
+ container.bind<IChatbotUiStore>(CHATBOT_UI_STORE_TOKEN).to(ChatbotUiStore).inSingletonScope();
31
+ container
32
+ .bind<IChatbotUiBackendStore>(CHATBOT_UI_BACKEND_STORE_TOKEN)
33
+ .to(ChatbotUiBackendStore)
34
+ .inSingletonScope();
35
+
36
+ // Set up Helpcenter API client
37
+ const clientSettings: ApiClientTitanChat.IChatbotClientSettingsTitanChat = {
38
+ clientId: 'TitanChatClientId',
39
+ version: String(ChatbotVersion),
40
+ constructorParametersFactory: () => ({
41
+ baseUrl: ChatbotBaseUrl,
42
+ }),
43
+ };
44
+ container
45
+ .bind<ApiClientTitanChat.IChatbotClientSettingsTitanChat>(CHATBOT_CLIENT_SETTINGS)
46
+ .toConstantValue(clientSettings);
47
+ container
48
+ .bind<IChatbotApiClient>(CHATBOT_API_CLIENT)
49
+ .to(ApiClientTitanChat.ChatbotApiClient)
50
+ .inSingletonScope();
51
+ return container;
52
+ };
53
+
54
+ interface IChatbotProps {
55
+ className?: string;
56
+ customizations?: ChatbotCustomizations;
57
+ }
58
+
59
+ export function runChatbotTitanChatbotSharedTests(
60
+ ChatbotComponent: FC<IChatbotProps>,
61
+ wrapperComponent?: (component: ReactElement) => ReactElement
62
+ ) {
63
+ let container: Container;
64
+ let log: CypressMocks.LogMock;
65
+ let apiClientSettings: ApiClientTitanChat.IChatbotClientSettingsTitanChat;
66
+ let apiClient: ApiClientTitanChat.ChatbotApiClient;
67
+ let uiStore: ChatbotUiStore;
68
+ let uiBackendStore: ChatbotUiBackendStore;
69
+
70
+ beforeEach(() => {
71
+ container = initializeTitanChatbotContainer();
72
+ log = container.get<CypressMocks.LogMock>(Log);
73
+ apiClientSettings =
74
+ container.get<ApiClientTitanChat.IChatbotClientSettingsTitanChat>(
75
+ CHATBOT_CLIENT_SETTINGS
76
+ );
77
+ apiClient = container.get<ApiClientTitanChat.ChatbotApiClient>(CHATBOT_API_CLIENT);
78
+ uiStore = container.get<ChatbotUiStore>(CHATBOT_UI_STORE_TOKEN);
79
+ uiBackendStore = container.get<ChatbotUiBackendStore>(CHATBOT_UI_BACKEND_STORE_TOKEN);
80
+ cy.viewport(550, 800);
81
+ cy.clock(Date.parse('2023-10-01T00:00:00Z'));
82
+ });
83
+
84
+ const render = () => {
85
+ const ChatbotWrapper: FC = () => {
86
+ const customizationContext = useMemo<ChatbotCustomizations>(
87
+ () => ({
88
+ filters: { enabled: true },
89
+ feedback: { title: 'TITLE' },
90
+ }),
91
+ []
92
+ );
93
+
94
+ const component = (
95
+ <ChatbotComponent
96
+ className="h-100vh max-h-100vh of-x-hidden"
97
+ customizations={customizationContext}
98
+ />
99
+ );
100
+
101
+ const wrappedComponent = wrapperComponent ? wrapperComponent(component) : component;
102
+
103
+ return (
104
+ <Provider
105
+ singletons={[
106
+ {
107
+ provide: Log,
108
+ useValue: log,
109
+ },
110
+ {
111
+ provide: CHATBOT_CLIENT_SETTINGS,
112
+ useValue: apiClientSettings,
113
+ },
114
+ { provide: CHATBOT_API_CLIENT, useValue: apiClient },
115
+ {
116
+ provide: CHATBOT_UI_STORE_TOKEN,
117
+ useValue: uiStore,
118
+ },
119
+ {
120
+ provide: CHATBOT_UI_BACKEND_STORE_TOKEN,
121
+ useValue: uiBackendStore,
122
+ },
123
+ ]}
124
+ >
125
+ {wrappedComponent}
126
+ </Provider>
127
+ );
128
+ };
129
+ cy.spy(uiStore, 'run').as('runSpy');
130
+ mount(<ChatbotWrapper />);
131
+ return cy.wrap(
132
+ new Promise(resolve => {
133
+ cy.get('@runSpy')
134
+ .should('have.been.calledOnce')
135
+ .then((invocation: any) => {
136
+ const initPromise = invocation.firstCall.returnValue as ReturnType<
137
+ IChatbotUiStore['run']
138
+ >;
139
+ initPromise.then(resolve);
140
+ });
141
+ })
142
+ );
143
+ };
144
+
145
+ it('should render the chatbot with titan chat API', () => {
146
+ const optionsMock = CypressMocks.TC.Options;
147
+ const sessionMock = CypressMocks.TC.SessionPost;
148
+ const messageMock = CypressMocks.TC.MessagePost;
149
+ const messageFeedbackMock = CypressMocks.TC.MessageFeedbackPost;
150
+ const sessionFeedbackMock = CypressMocks.TC.SessionFeedbackPost;
151
+
152
+ const aliasOptions = optionsMock.intercept(ChatbotBaseUrl, ChatbotVersion);
153
+ const aliasSession = sessionMock.intercept(ChatbotBaseUrl, ChatbotVersion);
154
+ const aliasMessage = messageMock.intercept(ChatbotBaseUrl, ChatbotVersion);
155
+ const { aliasPostMessage, aliasPostSession } = CypressMocks.TC.interceptFeedback(
156
+ ChatbotBaseUrl,
157
+ ChatbotVersion
158
+ );
159
+
160
+ render().then(() => {
161
+ cy.log('Getting options...');
162
+ cy.wait(aliasOptions).then(interception => {
163
+ expect(interception.request.url).to.equal(
164
+ `${ChatbotBaseUrl}/api/v${ChatbotVersion}/options`
165
+ );
166
+ expect(interception.response?.statusCode).to.equal(200);
167
+ expect(interception.response?.body).to.deep.equal(optionsMock.response);
168
+ });
169
+
170
+ // Ask the bot a question
171
+ cy.log('Sending message...');
172
+ ChatUiSelectors.chatInput.type(`${messageMock.request.question}{enter}`, { delay: 0 });
173
+
174
+ // Check that the session was created
175
+ cy.wait(aliasSession).then(interception => {
176
+ expect(interception.request.url).to.equal(
177
+ `${ChatbotBaseUrl}/api/v${ChatbotVersion}/session`
178
+ );
179
+ expect(interception.request.body).to.deep.equal(sessionMock.request);
180
+ expect(interception.response?.body).to.deep.equal(sessionMock.response);
181
+ expect(interception.response?.statusCode).to.equal(200);
182
+ });
183
+
184
+ // Check the user message is sent
185
+ cy.wait(aliasMessage).then(interception => {
186
+ expect(interception.request.url).to.equal(
187
+ `${ChatbotBaseUrl}/api/v${ChatbotVersion}/message`
188
+ );
189
+ expect(interception.request.body).to.deep.equal(messageMock.request);
190
+ expect(interception.response?.body).to.deep.equal(messageMock.response);
191
+ expect(interception.response?.statusCode).to.equal(200);
192
+ });
193
+
194
+ cy.tick(100);
195
+ // Send session feedback (manually)
196
+ cy.log('Sending session feedback...');
197
+ uiStore.sendSessionFeedback(new Models.Feedback(sessionFeedbackMock.request));
198
+ cy.wait(aliasPostSession).then(interception => {
199
+ expect(interception.request.url).to.equal(
200
+ `${ChatbotBaseUrl}/api/v${ChatbotVersion}/feedback`
201
+ );
202
+ expect(interception.request.body).to.deep.equal(sessionFeedbackMock.request);
203
+ expect(interception.response?.body).to.deep.equal(sessionFeedbackMock.response);
204
+ expect(interception.response?.statusCode).to.equal(200);
205
+ });
206
+
207
+ cy.tick(100);
208
+ // Check the feedback is sent with thumbs up
209
+ cy.log('Sending message feedback...');
210
+ ChatUiSelectors.chatbotMessageFeedbackThumbsUp.scrollIntoView().click({ force: true });
211
+ cy.wait(aliasPostMessage).then(interception => {
212
+ expect(interception.request.url).to.equal(
213
+ `${ChatbotBaseUrl}/api/v${ChatbotVersion}/feedback`
214
+ );
215
+ expect(interception.request.body).to.deep.equal(messageFeedbackMock.request);
216
+ expect(interception.response?.body).to.deep.equal(messageFeedbackMock.response);
217
+ expect(interception.response?.statusCode).to.equal(200);
218
+ });
219
+ });
220
+ });
221
+ }
@@ -0,0 +1,158 @@
1
+ import { Container } from '@servicetitan/react-ioc';
2
+ import {
3
+ CHATBOT_API_CLIENT,
4
+ CHATBOT_UI_STORE_TOKEN,
5
+ ChatbotCustomizations,
6
+ ChatbotUiStore,
7
+ IChatbotUiStore,
8
+ Models,
9
+ ModelsMocks,
10
+ } from '@servicetitan/titan-chatbot-api';
11
+ import { CSSProperties, FC, ReactElement } from 'react';
12
+ import { CypressMocks, testInitContainerChatbot, testRenderWrapperChatbot } from '../..';
13
+ import { ChatUiSelectors } from '../../utils/chat-ui-selectors';
14
+
15
+ interface IChatbotProps {
16
+ style?: CSSProperties;
17
+ customizations?: ChatbotCustomizations;
18
+ }
19
+
20
+ export function runChatbotSharedTests(
21
+ ChatbotComponent: FC<IChatbotProps>,
22
+ wrapperComponent?: (component: ReactElement) => ReactElement
23
+ ) {
24
+ let container: Container;
25
+ let api: CypressMocks.ChatbotApiClientMock;
26
+ let chatbotUiStore: IChatbotUiStore;
27
+
28
+ const mockApiClient = () => {
29
+ api.postSession = cy.stub().resolves(ModelsMocks.mockSession());
30
+ api.getOptions = cy.stub().resolves(ModelsMocks.mockFrontendModel());
31
+ };
32
+
33
+ const mockAskBotApi = (answer: string) => {
34
+ api.postMessage = cy.stub().as('askBot').resolves(
35
+ ModelsMocks.mockBotMessage({
36
+ answer,
37
+ })
38
+ );
39
+ api.postFeedback = cy
40
+ .stub()
41
+ .as('askBotFeedback')
42
+ .resolves(
43
+ ModelsMocks.mockFeedback({
44
+ rating: Models.FeedbackRatings.ThumbsUp,
45
+ })
46
+ );
47
+ };
48
+
49
+ beforeEach(() => {
50
+ container = testInitContainerChatbot();
51
+ api = container.get<CypressMocks.ChatbotApiClientMock>(CHATBOT_API_CLIENT);
52
+ chatbotUiStore = container.get<ChatbotUiStore>(CHATBOT_UI_STORE_TOKEN);
53
+ mockApiClient();
54
+ cy.viewport(550, 800);
55
+ });
56
+
57
+ const render = (onAfterInit?: () => void) => {
58
+ return cy.wrap(null).then(() => {
59
+ const customizationContext: ChatbotCustomizations = {
60
+ filters: { enabled: true },
61
+ feedback: { title: 'TITLE' },
62
+ };
63
+ const component = (
64
+ <ChatbotComponent
65
+ style={{
66
+ height: '100vh',
67
+ width: '100%',
68
+ maxWidth: '100vh',
69
+ overflowX: 'hidden',
70
+ }}
71
+ customizations={customizationContext}
72
+ />
73
+ );
74
+ const wrappedComponent = wrapperComponent ? wrapperComponent(component) : component;
75
+
76
+ return testRenderWrapperChatbot(container, wrappedComponent, onAfterInit);
77
+ });
78
+ };
79
+
80
+ const doAskBot = (message: string) => {
81
+ ChatUiSelectors.chatInput.type(`${message}{enter}`, { delay: 0 });
82
+ };
83
+ const doTriggerFile = () => {
84
+ chatbotUiStore.setFilePickerEnabled(true);
85
+ cy.then(() => {
86
+ ChatUiSelectors.chatUploadFile.should('be.visible');
87
+ });
88
+ };
89
+
90
+ it('should render the chatbot component', () => {
91
+ mockAskBotApi("Hello! I'm chatbot mocked response!!!");
92
+
93
+ render();
94
+
95
+ // Pick filter
96
+ ChatUiSelectors.chatbotFilterButton.first().click();
97
+ ChatUiSelectors.chatbotFilterOptions.find('label').first().click();
98
+ ChatUiSelectors.chatbotFilterButton.first().click();
99
+
100
+ // Ask chatbot
101
+ doAskBot('Hello, Chatbot!');
102
+ doAskBot('Hello, Chatbot! Hello, Chatbot! Hello, Chatbot! Hello, Chatbot! Hello, Chatbot!');
103
+ doTriggerFile();
104
+
105
+ // Check if the message is sent
106
+ cy.get('@askBot').should('have.been.calledTwice');
107
+ });
108
+
109
+ describe('with error handling', () => {
110
+ const mockAskBotApiError = (errorMessage: string) => {
111
+ api.postMessage = cy.stub().as('askBot').rejects(new Error(errorMessage));
112
+ };
113
+
114
+ it('should react on send message API error', () => {
115
+ mockAskBotApiError('Chatbot API error');
116
+ render();
117
+
118
+ doAskBot('Hello, Chatbot!');
119
+
120
+ cy.then(() => {
121
+ ChatUiSelectors.chatMessageFooter
122
+ .last()
123
+ .should('be.visible')
124
+ .should('contain.text', 'Message not delivered. Retry');
125
+ const errorBanner = ChatUiSelectors.chatError.should('be.visible').within(() => {
126
+ errorBanner
127
+ .find('.Banner__text > .Banner__title, [class^="_title-container"]')
128
+ .should('contain.text', 'Chat Error');
129
+ ChatUiSelectors.chatErrorText
130
+ .should('be.visible')
131
+ .should('contain.text', 'Failed to send message');
132
+ });
133
+ });
134
+
135
+ cy.then(() => {
136
+ mockAskBotApi("Hello! I'm chatbot mocked response!!!");
137
+ ChatUiSelectors.chatMessageErrorRetry.click();
138
+ ChatUiSelectors.chatMessageContentAgent
139
+ .should('be.visible')
140
+ .should('contain.text', "Hello! I'm chatbot mocked response!!!");
141
+ });
142
+ });
143
+ });
144
+
145
+ describe('with message feedback', () => {
146
+ it('should render the chatbot component', () => {
147
+ mockAskBotApi("Hello! I'm chatbot mocked response!!!");
148
+ render();
149
+
150
+ doAskBot('Hello!');
151
+ ChatUiSelectors.chatbotMessageFeedbackThumbsUp.should('be.visible').click();
152
+ cy.get('@askBotFeedback').should('have.been.calledOnce');
153
+ ChatUiSelectors.chatbotMessageFeedbackSuccess
154
+ .should('be.visible')
155
+ .should('contain.text', 'Thanks for your feedback.');
156
+ });
157
+ });
158
+ }
@@ -23,6 +23,18 @@ export class ChatUiSelectors {
23
23
  static get chatUploadFile() {
24
24
  return cy.getCy(ChatUiSelectors.cy.chatUploadFile);
25
25
  }
26
+ static get chatUploadFileBtn() {
27
+ return cy.getCy(ChatUiSelectors.cy.chatUploadFileBtn);
28
+ }
29
+ static get chatUploadFileName() {
30
+ return cy.getCy(ChatUiSelectors.cy.chatUploadFileName);
31
+ }
32
+ static get chatUploadFileEdit() {
33
+ return cy.getCy(ChatUiSelectors.cy.chatUploadFileEdit);
34
+ }
35
+ static get chatUploadFileDelete() {
36
+ return cy.getCy(ChatUiSelectors.cy.chatUploadFileDelete);
37
+ }
26
38
  static get chatMessageError() {
27
39
  return cy.getCy(ChatUiSelectors.cy.chatMessageError);
28
40
  }
@@ -161,6 +173,9 @@ export class ChatUiSelectors {
161
173
  static get chatbotSessionFeedbackComment() {
162
174
  return cy.getCy(ChatUiSelectors.cy.chatbotSessionFeedbackComment);
163
175
  }
176
+ static get chatbotRestartDialog() {
177
+ return cy.getCy(ChatUiSelectors.cy.chatbotRestartDialog);
178
+ }
164
179
  static get chatbotFilters() {
165
180
  return cy.getCy(ChatUiSelectors.cy.chatbotFilters);
166
181
  }
@@ -179,6 +194,9 @@ export class ChatUiSelectors {
179
194
  static get chatbotFilterOptions() {
180
195
  return cy.getCy(ChatUiSelectors.cy.chatbotFilterOptions);
181
196
  }
197
+ static get chatbotFilterContent() {
198
+ return cy.getCy(ChatUiSelectors.cy.chatbotFilterContent);
199
+ }
182
200
  static get chatbotLinksMore() {
183
201
  return cy.getCy(ChatUiSelectors.cy.chatbotLinksMore);
184
202
  }
@@ -201,6 +219,10 @@ export class ChatUiSelectors {
201
219
  chatInput: 'titan-chat-input',
202
220
  chatSend: 'titan-chat-send',
203
221
  chatUploadFile: 'titan-chat-upload-file',
222
+ chatUploadFileBtn: 'titan-chat-upload-file-btn',
223
+ chatUploadFileName: 'titan-chat-upload-file-name',
224
+ chatUploadFileEdit: 'titan-chat-upload-file-edit',
225
+ chatUploadFileDelete: 'titan-chat-upload-file-delete',
204
226
  chatMessageError: 'titan-chat-message-error',
205
227
  chatMessageErrorRetry: 'titan-chat-message-error-retry',
206
228
  chatNotifications: 'titan-chat-notifications',
@@ -241,12 +263,14 @@ export class ChatUiSelectors {
241
263
  chatbotSessionFeedbackThumbsUp: 'titan-chatbot-session-feedback-thumbs-up',
242
264
  chatbotSessionFeedbackThumbsDown: 'titan-chatbot-session-feedback-thumbs-down',
243
265
  chatbotSessionFeedbackComment: 'titan-chatbot-session-feedback-comment',
266
+ chatbotRestartDialog: 'titan-chatbot-restart-dialog',
244
267
  chatbotFilters: 'titan-chatbot-filters',
245
268
  chatbotFilterSearch: 'titan-chatbot-filter-search',
246
269
  chatbotFilterAll: 'titan-chatbot-filter-all',
247
270
  chatbotFilterNone: 'titan-chatbot-filter-none',
248
271
  chatbotFilterButton: 'titan-chatbot-filter-button',
249
272
  chatbotFilterOptions: 'titan-chatbot-filter-options',
273
+ chatbotFilterContent: 'titan-chatbot-filter-content',
250
274
  chatbotLinksMore: 'titan-chatbot-links-more',
251
275
  chatbotLinksCollapsible: 'titan-chatbot-links-collapsible',
252
276
  chatbotLinksLink: 'titan-chatbot-links-link',
@@ -0,0 +1,73 @@
1
+ import { ILog, Log } from '@servicetitan/log-service';
2
+ import { Container, provide } from '@servicetitan/react-ioc';
3
+ import { ChatParticipantIcon } from '@servicetitan/titan-chat-ui-common';
4
+ import {
5
+ CHATBOT_API_CLIENT,
6
+ CHATBOT_UI_BACKEND_STORE_TOKEN,
7
+ CHATBOT_UI_STORE_TOKEN,
8
+ ChatbotUiBackendStore,
9
+ ChatbotUiStore,
10
+ IChatbotApiClient,
11
+ IChatbotUiBackendStore,
12
+ IChatbotUiStore,
13
+ } from '@servicetitan/titan-chatbot-api';
14
+ import { mount } from 'cypress/react';
15
+ import { FC, ReactNode } from 'react';
16
+ import { CypressMocks } from '..';
17
+
18
+ export const testInitContainerChatbot = () => {
19
+ const rootContainer = new Container();
20
+ const container = new Container();
21
+ container.parent = rootContainer;
22
+ container.bind<ILog>(Log).to(CypressMocks.LogMock).inSingletonScope();
23
+ container
24
+ .bind<IChatbotApiClient>(CHATBOT_API_CLIENT)
25
+ .to(CypressMocks.ChatbotApiClientMock)
26
+ .inSingletonScope();
27
+ container.bind<IChatbotUiStore>(CHATBOT_UI_STORE_TOKEN).to(ChatbotUiStore).inSingletonScope();
28
+ container
29
+ .bind<IChatbotUiBackendStore>(CHATBOT_UI_BACKEND_STORE_TOKEN)
30
+ .to(ChatbotUiBackendStore)
31
+ .inSingletonScope();
32
+ return container;
33
+ };
34
+
35
+ export const testRenderWrapperChatbot = async (
36
+ container: Container,
37
+ component: ReactNode,
38
+ onAfterInit: () => void = () => {}
39
+ ) => {
40
+ const log = container.get<ILog>(Log);
41
+ const chatbotApiClient = container.get<IChatbotApiClient>(CHATBOT_API_CLIENT);
42
+ const chatbotUiStore = container.get<IChatbotUiStore>(CHATBOT_UI_STORE_TOKEN);
43
+ const chatbotUiBackendStore = container.get<IChatbotUiBackendStore>(
44
+ CHATBOT_UI_BACKEND_STORE_TOKEN
45
+ );
46
+
47
+ chatbotUiBackendStore.subscribe();
48
+ await chatbotUiStore.run({
49
+ agentName: 'EchoBot',
50
+ agentIcon: ChatParticipantIcon.Bot,
51
+ });
52
+ onAfterInit?.();
53
+
54
+ const RenderWrapper: FC = provide({
55
+ singletons: [
56
+ {
57
+ provide: Log,
58
+ useValue: log,
59
+ },
60
+ { provide: CHATBOT_API_CLIENT, useValue: chatbotApiClient },
61
+ {
62
+ provide: CHATBOT_UI_STORE_TOKEN,
63
+ useValue: chatbotUiStore,
64
+ },
65
+ {
66
+ provide: CHATBOT_UI_BACKEND_STORE_TOKEN,
67
+ useValue: chatbotUiBackendStore,
68
+ },
69
+ ],
70
+ })(() => component);
71
+ RenderWrapper.displayName = 'RenderWrapper';
72
+ mount(<RenderWrapper />);
73
+ };
@@ -0,0 +1,52 @@
1
+ import { Container, provide } from '@servicetitan/react-ioc';
2
+ import {
3
+ CHAT_UI_BACKEND_STORE_TOKEN,
4
+ CHAT_UI_STORE_TOKEN,
5
+ ChatParticipantIcon,
6
+ ChatUiBackendEchoStore,
7
+ ChatUiStore,
8
+ IChatUiBackendStore,
9
+ IChatUiStore,
10
+ } from '@servicetitan/titan-chat-ui-common';
11
+ import { mount } from 'cypress/react';
12
+ import { FC, ReactNode } from 'react';
13
+
14
+ export const testInitContainer = () => {
15
+ const rootContainer = new Container();
16
+ const container = new Container();
17
+ container.parent = rootContainer;
18
+ container.bind<IChatUiStore>(CHAT_UI_STORE_TOKEN).to(ChatUiStore).inSingletonScope();
19
+ container
20
+ .bind<IChatUiBackendStore>(CHAT_UI_BACKEND_STORE_TOKEN)
21
+ .to(ChatUiBackendEchoStore)
22
+ .inSingletonScope();
23
+ return container;
24
+ };
25
+
26
+ export const testRenderWrapper = async (
27
+ chatUiStore: IChatUiStore,
28
+ chatUiBackendStore: IChatUiBackendStore,
29
+ component: ReactNode,
30
+ onAfterInit: () => void = () => {}
31
+ ) => {
32
+ chatUiBackendStore.subscribe();
33
+ await chatUiStore.run({
34
+ agentName: 'EchoBot',
35
+ agentIcon: ChatParticipantIcon.Bot,
36
+ });
37
+ onAfterInit?.();
38
+ const RenderWrapper: FC = provide({
39
+ singletons: [
40
+ {
41
+ provide: CHAT_UI_STORE_TOKEN,
42
+ useValue: chatUiStore,
43
+ },
44
+ {
45
+ provide: CHAT_UI_BACKEND_STORE_TOKEN,
46
+ useValue: chatUiBackendStore,
47
+ },
48
+ ],
49
+ })(() => component);
50
+ RenderWrapper.displayName = 'RenderWrapper';
51
+ mount(<RenderWrapper />);
52
+ };