message-list.test.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import sinon from 'sinon'
  2. import { expect } from 'chai'
  3. import { screen, render, fireEvent } from '@testing-library/react'
  4. import React from 'react'
  5. import MessageList from '../../../../../frontend/js/features/chat/components/message-list'
  6. import { stubMathJax, tearDownMathJaxStubs } from './stubs'
  7. import { UserProvider } from '@/shared/context/user-context'
  8. import { User, UserId } from '@ol-types/user'
  9. import { Message, ChatContext } from '@/features/chat/context/chat-context'
  10. import { ModalsContextProvider } from '@/features/ide-react/context/modals-context'
  11. import { SplitTestProvider } from '@/shared/context/split-test-context'
  12. describe('<MessageList />', function () {
  13. function ChatProviders({ children }: { children: React.ReactNode }) {
  14. const mockContextValue = {
  15. idOfMessageBeingEdited: null,
  16. }
  17. return (
  18. <UserProvider>
  19. <ModalsContextProvider>
  20. <SplitTestProvider>
  21. <ChatContext.Provider value={mockContextValue as any}>
  22. {children}
  23. </ChatContext.Provider>
  24. </SplitTestProvider>
  25. </ModalsContextProvider>
  26. </UserProvider>
  27. )
  28. }
  29. const currentUser: User = {
  30. id: 'fake_user' as UserId,
  31. first_name: 'fake_user_first_name',
  32. email: 'fake@example.com',
  33. }
  34. function createMessages(): Message[] {
  35. return [
  36. {
  37. id: '1',
  38. content: 'a message',
  39. user: currentUser,
  40. timestamp: new Date().getTime(),
  41. },
  42. {
  43. id: '2',
  44. content: 'another message',
  45. user: currentUser,
  46. timestamp: new Date().getTime(),
  47. },
  48. ]
  49. }
  50. before(function () {
  51. stubMathJax()
  52. })
  53. after(function () {
  54. tearDownMathJaxStubs()
  55. })
  56. let olUser: User
  57. beforeEach(function () {
  58. olUser = window.metaAttributesCache.get('ol-user')
  59. window.metaAttributesCache.set('ol-user', currentUser)
  60. })
  61. afterEach(function () {
  62. window.metaAttributesCache.set('ol-user', olUser)
  63. })
  64. it('renders multiple messages', function () {
  65. render(
  66. <ChatProviders>
  67. <MessageList
  68. messages={createMessages()}
  69. resetUnreadMessages={() => {}}
  70. />
  71. </ChatProviders>
  72. )
  73. screen.getByText('a message')
  74. screen.getByText('another message')
  75. })
  76. it('renders a single timestamp for all messages within 5 minutes', function () {
  77. const msgs = createMessages()
  78. msgs[0].timestamp = new Date(2019, 6, 3, 4, 23).getTime()
  79. msgs[1].timestamp = new Date(2019, 6, 3, 4, 27).getTime()
  80. render(
  81. <ChatProviders>
  82. <MessageList messages={msgs} resetUnreadMessages={() => {}} />
  83. </ChatProviders>
  84. )
  85. screen.getByText('4:23 am Wed, 3rd Jul 19')
  86. expect(screen.queryByText('4:27 am Wed, 3rd Jul 19')).to.not.exist
  87. })
  88. it('renders a timestamp for each messages separated for more than 5 minutes', function () {
  89. const msgs = createMessages()
  90. msgs[0].timestamp = new Date(2019, 6, 3, 4, 23).getTime()
  91. msgs[1].timestamp = new Date(2019, 6, 3, 4, 31).getTime()
  92. render(
  93. <ChatProviders>
  94. <MessageList messages={msgs} resetUnreadMessages={() => {}} />
  95. </ChatProviders>
  96. )
  97. screen.getByText('4:23 am Wed, 3rd Jul 19')
  98. screen.getByText('4:31 am Wed, 3rd Jul 19')
  99. })
  100. it('resets the number of unread messages after clicking on the input', function () {
  101. const resetUnreadMessages = sinon.stub()
  102. render(
  103. <ChatProviders>
  104. <MessageList
  105. messages={createMessages()}
  106. resetUnreadMessages={resetUnreadMessages}
  107. />
  108. </ChatProviders>
  109. )
  110. fireEvent.click(screen.getByRole('list'))
  111. expect(resetUnreadMessages).to.be.calledOnce
  112. })
  113. it('groups messages from different users separately', function () {
  114. const anotherUser: User = {
  115. id: 'another_user' as UserId,
  116. first_name: 'another_user_first_name',
  117. email: 'another@example.com',
  118. }
  119. const messages: Message[] = [
  120. {
  121. id: '1',
  122. content: 'first message from current user',
  123. user: currentUser,
  124. timestamp: new Date('2025-09-01 4:20:10').getTime(),
  125. },
  126. {
  127. id: '2',
  128. content: 'second message from current user',
  129. user: currentUser,
  130. timestamp: new Date('2025-09-01 4:20:11').getTime(),
  131. },
  132. {
  133. id: '3',
  134. content: 'first message from another user',
  135. user: anotherUser,
  136. timestamp: new Date('2025-09-01 4:20:12').getTime(),
  137. },
  138. {
  139. id: '4',
  140. content: 'second message from another user',
  141. user: anotherUser,
  142. timestamp: new Date('2025-09-01 4:20:13').getTime(),
  143. },
  144. ]
  145. render(
  146. <ChatProviders>
  147. <MessageList messages={messages} resetUnreadMessages={() => {}} />
  148. </ChatProviders>
  149. )
  150. const messageGroups = screen.getAllByRole('listitem')
  151. // Should have 2 message groups
  152. expect(messageGroups).to.have.length(2)
  153. screen.getByText('first message from current user')
  154. screen.getByText('second message from current user')
  155. screen.getByText('first message from another user')
  156. screen.getByText('second message from another user')
  157. })
  158. it('does not show deleted messages', function () {
  159. const messages: Message[] = [
  160. {
  161. id: '1',
  162. content: 'visible message',
  163. user: currentUser,
  164. timestamp: new Date().getTime(),
  165. },
  166. {
  167. id: '2',
  168. content: 'deleted message',
  169. user: currentUser,
  170. timestamp: new Date().getTime() + 1000,
  171. deleted: true,
  172. },
  173. {
  174. id: '3',
  175. content: 'another visible message',
  176. user: currentUser,
  177. timestamp: new Date().getTime() + 2000,
  178. },
  179. ]
  180. render(
  181. <ChatProviders>
  182. <MessageList messages={messages} resetUnreadMessages={() => {}} />
  183. </ChatProviders>
  184. )
  185. screen.getByText('visible message')
  186. screen.getByText('another visible message')
  187. expect(screen.queryByText('deleted message')).to.not.exist
  188. })
  189. })