@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,156 @@
1
+ import { Container } from '@servicetitan/react-ioc';
2
+ import {
3
+ CHAT_UI_BACKEND_STORE_TOKEN,
4
+ CHAT_UI_STORE_TOKEN,
5
+ ChatMessageModelBase,
6
+ ChatUiBackendEchoStore,
7
+ IChatUiBackendStore,
8
+ IChatUiStore,
9
+ mockChatMessageModelText,
10
+ } from '@servicetitan/titan-chat-ui-common';
11
+ import { FC } from 'react';
12
+ import { ChatUiSelectors } from '../../utils/chat-ui-selectors';
13
+ import { testInitContainer, testRenderWrapper } from '../../utils/test-utils';
14
+
15
+ export function runChatMessagesSharedTests(
16
+ ChatMessagesComponent: FC<{
17
+ className?: string;
18
+ messages: ChatMessageModelBase[];
19
+ showTypingIndicator?: boolean;
20
+ }>
21
+ ) {
22
+ let container: Container;
23
+ let chatUiStore: IChatUiStore;
24
+ let chatUiBackendStore: IChatUiBackendStore;
25
+
26
+ beforeEach(() => {
27
+ container = testInitContainer();
28
+ chatUiStore = container.get<IChatUiStore>(CHAT_UI_STORE_TOKEN);
29
+ chatUiBackendStore = container.get<ChatUiBackendEchoStore>(CHAT_UI_BACKEND_STORE_TOKEN);
30
+ cy.viewport(800, 800);
31
+ // cy.clock(new Date('2023-10-01T10:10:00Z').getTime());
32
+ });
33
+
34
+ const render = (messages: ChatMessageModelBase[], onAfterInit?: () => void) =>
35
+ cy
36
+ .wrap(null)
37
+ .then(() =>
38
+ testRenderWrapper(
39
+ chatUiStore,
40
+ chatUiBackendStore,
41
+ <ChatMessagesComponent messages={messages} />,
42
+ onAfterInit
43
+ )
44
+ );
45
+
46
+ it('should render default chat', () => {
47
+ render([]);
48
+
49
+ ChatUiSelectors.chatMessages.should('exist');
50
+ ChatUiSelectors.chatMessage.should('have.length', 0);
51
+ });
52
+
53
+ it('should render several consecutive agent messages without extra avatars', () => {
54
+ render([
55
+ mockChatMessageModelText(true, {
56
+ id: 'id1',
57
+ timestamp: new Date('2023-01-01T10:10:00Z'),
58
+ message: 'Hello, this is the first message',
59
+ }),
60
+ mockChatMessageModelText(true, {
61
+ id: 'id2',
62
+ message: 'Hello, this is the second message. '.repeat(5).trim(),
63
+ timestamp: new Date('2023-01-01T10:10:59.999Z'),
64
+ }),
65
+ mockChatMessageModelText(true, {
66
+ id: 'id3',
67
+ message: 'Hello, this is the third message',
68
+ timestamp: new Date('2023-01-01T10:11:00Z'),
69
+ }),
70
+ mockChatMessageModelText(true, {
71
+ id: 'id4',
72
+ message: 'Hello, this is the forth message',
73
+ timestamp: new Date('2023-01-01T10:11:01Z'),
74
+ }),
75
+ mockChatMessageModelText(false, {
76
+ id: 'id11',
77
+ timestamp: new Date('2023-01-01T11:10:00Z'),
78
+ message: 'Hello, this is the first message',
79
+ }),
80
+ mockChatMessageModelText(false, {
81
+ id: 'id22',
82
+ message: 'Hello, this is the second message',
83
+ timestamp: new Date('2023-01-01T11:11:00Z'),
84
+ }),
85
+ mockChatMessageModelText(false, {
86
+ id: 'id33',
87
+ message: 'Hello, this is the third message',
88
+ timestamp: new Date('2023-01-01T11:12:00Z'),
89
+ }),
90
+ mockChatMessageModelText(false, {
91
+ id: 'id44',
92
+ message: 'Hello, this is the forth message',
93
+ timestamp: new Date('2023-01-01T11:12:01Z'),
94
+ }),
95
+ ]);
96
+
97
+ const getTimestamp = (i: number) =>
98
+ ChatUiSelectors.chatMessage
99
+ .eq(i)
100
+ .find(`[data-cy="${ChatUiSelectors.cy.chatMessageFooter}"]`);
101
+
102
+ ChatUiSelectors.chatMessageAgent.should('have.length', 4);
103
+ ChatUiSelectors.chatMessageUser.should('have.length', 4);
104
+
105
+ // Agent avatar should be visible only for the first message in group
106
+ const getAvatar = (i: number) =>
107
+ ChatUiSelectors.chatMessageAgent
108
+ .find(`[data-cy="${ChatUiSelectors.cy.chatAvatar}"]`)
109
+ .eq(i);
110
+ getAvatar(0).should('be.visible');
111
+ getAvatar(1).should('not.exist');
112
+ getAvatar(2).should('not.exist');
113
+ getAvatar(3).should('not.exist');
114
+
115
+ // Footer with date should be visible only for the different formatted timestamps
116
+ getTimestamp(0).should('not.exist');
117
+ getTimestamp(1).should('be.visible').should('contain.text', 'agent • 10:10 AM');
118
+ getTimestamp(2).should('not.exist');
119
+ getTimestamp(3).should('be.visible').should('contain.text', 'agent • 10:11 AM');
120
+ getTimestamp(4).should('be.visible').should('contain.text', '11:10 AM');
121
+ getTimestamp(5).should('be.visible').should('contain.text', '11:11 AM');
122
+ getTimestamp(6).should('not.exist');
123
+ getTimestamp(7).should('be.visible').should('contain.text', '11:12 AM');
124
+ });
125
+
126
+ it('should render empty state when no messages', () => {
127
+ render([]);
128
+
129
+ ChatUiSelectors.chatMessages.should('exist');
130
+ ChatUiSelectors.chatMessage.should('have.length', 0);
131
+ });
132
+
133
+ it('should handle mixed message types correctly', () => {
134
+ render([
135
+ mockChatMessageModelText(false, {
136
+ id: 'user1',
137
+ timestamp: new Date('2023-01-01T10:00:00Z'),
138
+ message: 'User message first',
139
+ }),
140
+ mockChatMessageModelText(true, {
141
+ id: 'agent1',
142
+ timestamp: new Date('2023-01-01T10:01:00Z'),
143
+ message: 'Agent response',
144
+ }),
145
+ mockChatMessageModelText(false, {
146
+ id: 'user2',
147
+ timestamp: new Date('2023-01-01T10:02:00Z'),
148
+ message: 'User follow-up',
149
+ }),
150
+ ]);
151
+
152
+ ChatUiSelectors.chatMessage.should('have.length', 3);
153
+ ChatUiSelectors.chatMessageUser.should('have.length', 2);
154
+ ChatUiSelectors.chatMessageAgent.should('have.length', 1);
155
+ });
156
+ }
@@ -0,0 +1,153 @@
1
+ import { Container } from '@servicetitan/react-ioc';
2
+ import {
3
+ CHAT_UI_BACKEND_STORE_TOKEN,
4
+ CHAT_UI_STORE_TOKEN,
5
+ ChatRunState,
6
+ ChatUiBackendEchoStore,
7
+ IChatUiBackendStore,
8
+ IChatUiStore,
9
+ } from '@servicetitan/titan-chat-ui-common';
10
+ import { FC } from 'react';
11
+ import { ChatUiSelectors } from '../../utils/chat-ui-selectors';
12
+ import { testInitContainer, testRenderWrapper } from '../../utils/test-utils';
13
+
14
+ export const runChatNotificationsTests = (ChatNotifications: FC) => {
15
+ let container: Container;
16
+ let chatUiStore: IChatUiStore;
17
+ let chatUiBackendStore: IChatUiBackendStore;
18
+
19
+ beforeEach(() => {
20
+ container = testInitContainer();
21
+ chatUiStore = container.get<IChatUiStore>(CHAT_UI_STORE_TOKEN);
22
+ chatUiBackendStore = container.get<ChatUiBackendEchoStore>(CHAT_UI_BACKEND_STORE_TOKEN);
23
+ cy.viewport(800, 800);
24
+ });
25
+
26
+ const render = (onAfterInit?: () => void) =>
27
+ cy
28
+ .wrap(null)
29
+ .then(() =>
30
+ testRenderWrapper(
31
+ chatUiStore,
32
+ chatUiBackendStore,
33
+ <ChatNotifications />,
34
+ onAfterInit
35
+ )
36
+ );
37
+
38
+ it('should render notifications container', () => {
39
+ render();
40
+ ChatUiSelectors.chatNotifications.should('exist');
41
+ });
42
+
43
+ it('should show timer when timer is set and no error', () => {
44
+ render(() => {
45
+ chatUiStore.setTimer({
46
+ secondsLeft: 30,
47
+ secondsTotal: 60,
48
+ });
49
+ chatUiStore.setStatus(ChatRunState.Started);
50
+ });
51
+
52
+ ChatUiSelectors.chatNotifications.should('be.visible');
53
+ ChatUiSelectors.chatTimer.should('be.visible');
54
+ ChatUiSelectors.chatError.should('not.exist');
55
+ });
56
+
57
+ it('should show error when error is present', () => {
58
+ render(() => {
59
+ chatUiStore.setError('Test error message');
60
+ });
61
+
62
+ ChatUiSelectors.chatNotifications.should('be.visible');
63
+ ChatUiSelectors.chatError.should('be.visible');
64
+ ChatUiSelectors.chatTimer.should('not.exist');
65
+ });
66
+
67
+ it('should hide timer when error is present', () => {
68
+ render(() => {
69
+ chatUiStore.setTimer({
70
+ secondsLeft: 30,
71
+ secondsTotal: 60,
72
+ });
73
+ chatUiStore.setError('Test error message');
74
+ });
75
+
76
+ ChatUiSelectors.chatNotifications.should('be.visible');
77
+ ChatUiSelectors.chatError.should('be.visible');
78
+ ChatUiSelectors.chatTimer.should('not.exist');
79
+ });
80
+
81
+ it('should be empty when no timer and no error', () => {
82
+ render(() => {
83
+ chatUiStore.resetError(ChatRunState.Started);
84
+ chatUiStore.setTimer(undefined);
85
+ });
86
+
87
+ ChatUiSelectors.chatNotifications.should('exist');
88
+ ChatUiSelectors.chatTimer.should('not.exist');
89
+ ChatUiSelectors.chatError.should('not.exist');
90
+ });
91
+
92
+ it('should update when timer is added', () => {
93
+ render();
94
+
95
+ ChatUiSelectors.chatTimer.should('not.exist');
96
+
97
+ cy.then(() => {
98
+ chatUiStore.setTimer({
99
+ secondsLeft: 30,
100
+ secondsTotal: 60,
101
+ });
102
+ chatUiStore.setStatus(ChatRunState.Started);
103
+ });
104
+
105
+ ChatUiSelectors.chatTimer.should('be.visible');
106
+ });
107
+
108
+ it('should update when error is added', () => {
109
+ render();
110
+
111
+ ChatUiSelectors.chatError.should('not.exist');
112
+
113
+ cy.then(() => {
114
+ chatUiStore.setError('New error message');
115
+ });
116
+
117
+ ChatUiSelectors.chatError.should('be.visible');
118
+ });
119
+
120
+ it('should switch from timer to error when error occurs', () => {
121
+ render(() => {
122
+ chatUiStore.setTimer({
123
+ secondsLeft: 30,
124
+ secondsTotal: 60,
125
+ });
126
+ chatUiStore.setStatus(ChatRunState.Started);
127
+ });
128
+
129
+ ChatUiSelectors.chatTimer.should('be.visible');
130
+ ChatUiSelectors.chatError.should('not.exist');
131
+
132
+ cy.then(() => {
133
+ chatUiStore.setError('Error occurred');
134
+ });
135
+
136
+ ChatUiSelectors.chatError.should('be.visible');
137
+ ChatUiSelectors.chatTimer.should('not.exist');
138
+ });
139
+
140
+ it('should handle error recovery', () => {
141
+ render(() => {
142
+ chatUiStore.setError('Test error');
143
+ });
144
+
145
+ ChatUiSelectors.chatError.should('be.visible');
146
+
147
+ cy.then(() => {
148
+ chatUiStore.resetError(ChatRunState.Started);
149
+ });
150
+
151
+ ChatUiSelectors.chatError.should('not.exist');
152
+ });
153
+ };
@@ -0,0 +1,106 @@
1
+ import { Container } from '@servicetitan/react-ioc';
2
+ import {
3
+ CHAT_UI_BACKEND_STORE_TOKEN,
4
+ CHAT_UI_STORE_TOKEN,
5
+ ChatUiBackendEchoStore,
6
+ IChatUiBackendStore,
7
+ IChatUiStore,
8
+ } from '@servicetitan/titan-chat-ui-common';
9
+ import { FC } from 'react';
10
+ import { ChatUiSelectors } from '../../utils/chat-ui-selectors';
11
+ import { testInitContainer, testRenderWrapper } from '../../utils/test-utils';
12
+
13
+ export const runChatTimerTests = (ChatTimer: FC) => {
14
+ let container: Container;
15
+ let chatUiStore: IChatUiStore;
16
+ let chatUiBackendStore: IChatUiBackendStore;
17
+
18
+ beforeEach(() => {
19
+ container = testInitContainer();
20
+ chatUiStore = container.get<IChatUiStore>(CHAT_UI_STORE_TOKEN);
21
+ chatUiBackendStore = container.get<ChatUiBackendEchoStore>(CHAT_UI_BACKEND_STORE_TOKEN);
22
+ cy.viewport(800, 800);
23
+ });
24
+
25
+ const render = (onAfterInit?: () => void) =>
26
+ cy
27
+ .wrap(null)
28
+ .then(() =>
29
+ testRenderWrapper(chatUiStore, chatUiBackendStore, <ChatTimer />, onAfterInit)
30
+ );
31
+
32
+ it('should not render when timer is not set', () => {
33
+ render();
34
+ ChatUiSelectors.chatTimer.should('not.exist');
35
+ });
36
+
37
+ it('should render timer when timer is set', () => {
38
+ render(() => {
39
+ chatUiStore.setTimer({ secondsLeft: 30, secondsTotal: 60 });
40
+ });
41
+
42
+ ChatUiSelectors.chatTimer.should('be.visible');
43
+ ChatUiSelectors.chatTimer.should('contain.text', 'Chat inactive');
44
+ ChatUiSelectors.chatTimer.should(
45
+ 'contain.text',
46
+ 'Are you still there? Please respond within'
47
+ );
48
+ ChatUiSelectors.chatTimer.should('contain.text', '30s');
49
+ ChatUiSelectors.chatTimer.should('contain.text', 'or this chat will time out.');
50
+ });
51
+
52
+ it('should display correct seconds left', () => {
53
+ render(() => {
54
+ chatUiStore.setTimer({ secondsLeft: 45, secondsTotal: 60 });
55
+ });
56
+
57
+ ChatUiSelectors.chatTimer.should('contain.text', '45s');
58
+ });
59
+
60
+ it('should render restart button with correct text', () => {
61
+ render(() => {
62
+ chatUiStore.setTimer({ secondsLeft: 30, secondsTotal: 60 });
63
+ });
64
+
65
+ ChatUiSelectors.chatTimerRestart.should('be.visible');
66
+ ChatUiSelectors.chatTimerRestart.should('contain.text', "I'm here");
67
+ });
68
+
69
+ it('should call restartTimers when restart button is clicked', () => {
70
+ render(() => {
71
+ chatUiStore.setTimer({ secondsLeft: 30, secondsTotal: 60 });
72
+ cy.spy(chatUiStore, 'restartTimers').as('restartTimersSpy');
73
+ });
74
+
75
+ ChatUiSelectors.chatTimerRestart.click();
76
+ cy.get('@restartTimersSpy').should('have.been.called');
77
+ });
78
+
79
+ it('should update display when timer seconds change', () => {
80
+ render(() => {
81
+ chatUiStore.setTimer({ secondsLeft: 30, secondsTotal: 60 });
82
+ });
83
+
84
+ ChatUiSelectors.chatTimer.should('contain.text', '30s');
85
+
86
+ // Update timer value and wait for re-render
87
+ cy.then(() => {
88
+ chatUiStore.setTimer({ secondsLeft: 15, secondsTotal: 60 });
89
+ });
90
+ ChatUiSelectors.chatTimer.should('contain.text', '15s');
91
+ });
92
+
93
+ it('should hide timer when timer is cleared', () => {
94
+ render(() => {
95
+ chatUiStore.setTimer({ secondsLeft: 30, secondsTotal: 60 });
96
+ });
97
+
98
+ ChatUiSelectors.chatTimer.should('be.visible');
99
+
100
+ // Clear timer
101
+ cy.then(() => {
102
+ chatUiStore.setTimer();
103
+ });
104
+ ChatUiSelectors.chatTimer.should('not.exist');
105
+ });
106
+ };
@@ -0,0 +1,158 @@
1
+ import { Container } from '@servicetitan/react-ioc';
2
+ import {
3
+ CHAT_UI_BACKEND_STORE_TOKEN,
4
+ CHAT_UI_STORE_TOKEN,
5
+ ChatCustomizations,
6
+ ChatRunState,
7
+ ChatUiBackendEchoStore,
8
+ IChatUiBackendStore,
9
+ IChatUiStore,
10
+ } from '@servicetitan/titan-chat-ui-common';
11
+ import { ComponentType } from 'react';
12
+ import { ChatUiSelectors } from '../../utils/chat-ui-selectors';
13
+ import { testInitContainer, testRenderWrapper } from '../../utils/test-utils';
14
+
15
+ interface IChatProps {
16
+ className?: string;
17
+ customizations?: ChatCustomizations;
18
+ }
19
+
20
+ export function runChatSharedTests(ChatComponent: ComponentType<IChatProps>) {
21
+ let container: Container;
22
+ let chatUiStore: IChatUiStore;
23
+ let chatUiBackendStore: IChatUiBackendStore;
24
+
25
+ beforeEach(() => {
26
+ container = testInitContainer();
27
+ chatUiStore = container.get<IChatUiStore>(CHAT_UI_STORE_TOKEN);
28
+ chatUiBackendStore = container.get<ChatUiBackendEchoStore>(CHAT_UI_BACKEND_STORE_TOKEN);
29
+ cy.viewport(800, 800);
30
+ });
31
+
32
+ const render = (props?: IChatProps, onAfterInit?: () => void) =>
33
+ cy
34
+ .wrap(null)
35
+ .then(() =>
36
+ testRenderWrapper(
37
+ chatUiStore,
38
+ chatUiBackendStore,
39
+ <ChatComponent {...props} />,
40
+ onAfterInit
41
+ )
42
+ );
43
+
44
+ it('should render chat component with default state', () => {
45
+ render();
46
+
47
+ ChatUiSelectors.chat.should('exist');
48
+ ChatUiSelectors.chat.should('be.visible');
49
+ });
50
+
51
+ it('should render loading component when chat is starting', () => {
52
+ render(undefined, () => {
53
+ chatUiStore.setStatus(ChatRunState.Initializing);
54
+ });
55
+
56
+ ChatUiSelectors.chat.should('exist');
57
+ ChatUiSelectors.chatConnecting.should('exist');
58
+ ChatUiSelectors.chatMessages.should('not.exist');
59
+ ChatUiSelectors.chatInput.should('not.exist');
60
+ });
61
+
62
+ it('should render chat messages and input when not starting', () => {
63
+ render(undefined, () => {
64
+ chatUiStore.setStatus(ChatRunState.Started);
65
+ });
66
+
67
+ ChatUiSelectors.chat.should('exist');
68
+ ChatUiSelectors.chatConnecting.should('not.exist');
69
+ ChatUiSelectors.chatMessages.should('exist');
70
+ ChatUiSelectors.chatInput.should('exist');
71
+ ChatUiSelectors.chatNotifications.should('exist');
72
+ });
73
+
74
+ it('should apply custom className when provided', () => {
75
+ const customClass = 'custom-chat-class';
76
+ render({ className: customClass });
77
+
78
+ ChatUiSelectors.chat.should('have.class', customClass);
79
+ });
80
+
81
+ it('should render custom loading component when provided', () => {
82
+ const customLoadingComponent = <div data-cy="custom-loading">Custom Loading</div>;
83
+ const customizations: ChatCustomizations = {
84
+ loadingComponent: customLoadingComponent,
85
+ };
86
+
87
+ render({ customizations }, () => {
88
+ chatUiStore.setStatus(ChatRunState.Initializing);
89
+ });
90
+
91
+ cy.get('[data-cy="custom-loading"]').should('exist');
92
+ cy.get('[data-cy="custom-loading"]').should('contain.text', 'Custom Loading');
93
+ ChatUiSelectors.chatConnecting.should('not.exist');
94
+ });
95
+
96
+ it('should render custom footer component when provided', () => {
97
+ const customFooterComponent = <div data-cy="custom-footer">Custom Footer</div>;
98
+ const customizations: ChatCustomizations = {
99
+ footerComponent: customFooterComponent,
100
+ };
101
+
102
+ render({ customizations }, () => {
103
+ chatUiStore.setStatus(ChatRunState.Started);
104
+ });
105
+
106
+ cy.get('[data-cy="custom-footer"]').should('exist');
107
+ cy.get('[data-cy="custom-footer"]').should('contain.text', 'Custom Footer');
108
+ });
109
+
110
+ it('should hide chat input when input is disabled in customizations', () => {
111
+ const customizations: ChatCustomizations = {
112
+ input: {
113
+ isDisabled: true,
114
+ },
115
+ };
116
+
117
+ render({ customizations }, () => {
118
+ chatUiStore.setStatus(ChatRunState.Started);
119
+ });
120
+
121
+ ChatUiSelectors.chat.should('exist');
122
+ ChatUiSelectors.chatMessages.should('exist');
123
+ ChatUiSelectors.chatInput.should('not.exist');
124
+ ChatUiSelectors.chatUploadFile.should('not.exist');
125
+ });
126
+
127
+ it('should show chat input and upload file when input is enabled', () => {
128
+ const customizations: ChatCustomizations = {
129
+ input: {
130
+ isDisabled: false,
131
+ },
132
+ };
133
+
134
+ render({ customizations }, () => {
135
+ chatUiStore.setStatus(ChatRunState.Started);
136
+ chatUiStore.setFilePickerEnabled(true);
137
+ });
138
+
139
+ ChatUiSelectors.chat.should('exist');
140
+ ChatUiSelectors.chatMessages.should('exist');
141
+ ChatUiSelectors.chatInput.should('exist');
142
+ ChatUiSelectors.chatUploadFile.should('exist');
143
+ });
144
+
145
+ it('should set customization context in store when customizations are provided', () => {
146
+ const customizations: ChatCustomizations = {
147
+ input: {
148
+ isDisabled: true,
149
+ },
150
+ };
151
+
152
+ render({ customizations });
153
+
154
+ cy.wait(1).then(() => {
155
+ expect(chatUiStore.customizations).to.deep.equal(customizations);
156
+ });
157
+ });
158
+ }