11import React from 'react' ;
22import { act , renderHook } from '@testing-library/react-hooks' ;
33import { ChatProvider } from './index' ;
4- import { Client } from '@twilio/conversations' ;
5- import { mockConversation , mockClient } from '../../__mocks__/@twilio/conversations' ;
64import useChatContext from '../../hooks/useChatContext/useChatContext' ;
75import useVideoContext from '../../hooks/useVideoContext/useVideoContext' ;
6+ import { setImmediate } from 'timers' ;
7+ import EventEmitter from 'events' ;
88
9- jest . mock ( '@twilio/conversations' ) ;
9+ const mockConversation : any = new EventEmitter ( ) ;
10+ mockConversation . getMessages = jest . fn ( ( ) => Promise . resolve ( { items : [ 'mockMessage' ] } ) ) ;
11+
12+ const mockConversationsClient : any = new EventEmitter ( ) ;
13+ mockConversationsClient . getConversationByUniqueName = jest . fn ( ( ) => Promise . resolve ( mockConversation ) ) ;
14+
15+ jest . mock ( '@twilio/conversations' , ( ) => {
16+ return { Client : jest . fn ( ( ) => mockConversationsClient ) } ;
17+ } ) ;
1018jest . mock ( '../../hooks/useVideoContext/useVideoContext' ) ;
19+
1120const mockUseVideoContext = useVideoContext as jest . Mock < any > ;
1221const mockOnError = jest . fn ( ) ;
1322
14- const mockClientCreate = Client . create as jest . Mock < any > ;
15-
1623const mockRoom = { sid : 'mockRoomSid' } ;
17-
1824const wrapper : React . FC = ( { children } ) => < ChatProvider > { children } </ ChatProvider > ;
1925
2026describe ( 'the ChatProvider component' , ( ) => {
@@ -25,12 +31,13 @@ describe('the ChatProvider component', () => {
2531
2632 it ( 'should return a Conversation after connect has been called and after a room exists' , async ( ) => {
2733 // Setup mock as if user is not connected to a room
28- mockUseVideoContext . mockImplementation ( ( ) => ( { } ) ) ;
34+ mockUseVideoContext . mockImplementation ( ( ) => ( { onError : mockOnError } ) ) ;
2935 const { result, rerender, waitForNextUpdate } = renderHook ( useChatContext , { wrapper } ) ;
3036
31- result . current . connect ( 'mockToken' ) ;
32- await waitForNextUpdate ( ) ;
33- expect ( mockClientCreate ) . toHaveBeenCalledWith ( 'mockToken' ) ;
37+ await act ( ( ) => {
38+ result . current . connect ( 'mockToken' ) ;
39+ mockConversationsClient . emit ( 'stateChanged' , 'initialized' ) ;
40+ } ) ;
3441
3542 // conversation should be null as there is no room
3643 expect ( result . current . conversation ) . toBe ( null ) ;
@@ -41,21 +48,27 @@ describe('the ChatProvider component', () => {
4148 rerender ( ) ;
4249 await waitForNextUpdate ( ) ;
4350
44- expect ( mockClient . getConversationByUniqueName ) . toHaveBeenCalledWith ( 'mockRoomSid' ) ;
51+ expect ( mockConversationsClient . getConversationByUniqueName ) . toHaveBeenCalledWith ( 'mockRoomSid' ) ;
4552 expect ( result . current . conversation ) . toBe ( mockConversation ) ;
4653 } ) ;
4754
4855 it ( 'should load all messages after obtaining a conversation' , async ( ) => {
4956 const { result, waitForNextUpdate } = renderHook ( useChatContext , { wrapper } ) ;
50- result . current . connect ( 'mockToken' ) ;
57+ act ( ( ) => {
58+ result . current . connect ( 'mockToken' ) ;
59+ mockConversationsClient . emit ( 'stateChanged' , 'initialized' ) ;
60+ } ) ;
5161 await waitForNextUpdate ( ) ;
5262
5363 expect ( result . current . messages ) . toEqual ( [ 'mockMessage' ] ) ;
5464 } ) ;
5565
5666 it ( 'should add new messages to the "messages" array' , async ( ) => {
5767 const { result, waitForNextUpdate } = renderHook ( useChatContext , { wrapper } ) ;
58- result . current . connect ( 'mockToken' ) ;
68+ act ( ( ) => {
69+ result . current . connect ( 'mockToken' ) ;
70+ mockConversationsClient . emit ( 'stateChanged' , 'initialized' ) ;
71+ } ) ;
5972 await waitForNextUpdate ( ) ;
6073
6174 act ( ( ) => {
@@ -70,7 +83,10 @@ describe('the ChatProvider component', () => {
7083
7184 expect ( result . current . hasUnreadMessages ) . toBe ( false ) ;
7285
73- result . current . connect ( 'mockToken' ) ;
86+ act ( ( ) => {
87+ result . current . connect ( 'mockToken' ) ;
88+ mockConversationsClient . emit ( 'stateChanged' , 'initialized' ) ;
89+ } ) ;
7490 await waitForNextUpdate ( ) ;
7591
7692 expect ( result . current . hasUnreadMessages ) . toBe ( true ) ;
@@ -84,7 +100,10 @@ describe('the ChatProvider component', () => {
84100 result . current . setIsChatWindowOpen ( true ) ;
85101 } ) ;
86102
87- result . current . connect ( 'mockToken' ) ;
103+ act ( ( ) => {
104+ result . current . connect ( 'mockToken' ) ;
105+ mockConversationsClient . emit ( 'stateChanged' , 'initialized' ) ;
106+ } ) ;
88107 await waitForNextUpdate ( ) ;
89108
90109 expect ( result . current . hasUnreadMessages ) . toBe ( false ) ;
@@ -94,7 +113,10 @@ describe('the ChatProvider component', () => {
94113 // Setup mock so that no messages are loaded after a conversation is obtained.
95114 mockConversation . getMessages . mockImplementationOnce ( ( ) => Promise . resolve ( { items : [ ] } ) ) ;
96115 const { result, waitForNextUpdate } = renderHook ( useChatContext , { wrapper } ) ;
97- result . current . connect ( 'mockToken' ) ;
116+ act ( ( ) => {
117+ result . current . connect ( 'mockToken' ) ;
118+ mockConversationsClient . emit ( 'stateChanged' , 'initialized' ) ;
119+ } ) ;
98120 await waitForNextUpdate ( ) ;
99121
100122 expect ( result . current . hasUnreadMessages ) . toBe ( false ) ;
@@ -110,7 +132,10 @@ describe('the ChatProvider component', () => {
110132 // Setup mock so that no messages are loaded after a conversation is obtained.
111133 mockConversation . getMessages . mockImplementationOnce ( ( ) => Promise . resolve ( { items : [ ] } ) ) ;
112134 const { result, waitForNextUpdate } = renderHook ( useChatContext , { wrapper } ) ;
113- result . current . connect ( 'mockToken' ) ;
135+ act ( ( ) => {
136+ result . current . connect ( 'mockToken' ) ;
137+ mockConversationsClient . emit ( 'stateChanged' , 'initialized' ) ;
138+ } ) ;
114139 await waitForNextUpdate ( ) ;
115140
116141 expect ( result . current . hasUnreadMessages ) . toBe ( false ) ;
@@ -126,39 +151,45 @@ describe('the ChatProvider component', () => {
126151
127152 it ( 'should set hasUnreadMessages to false when the chat window is opened' , async ( ) => {
128153 const { result, waitForNextUpdate } = renderHook ( useChatContext , { wrapper } ) ;
129- result . current . connect ( 'mockToken' ) ;
154+ act ( ( ) => {
155+ result . current . connect ( 'mockToken' ) ;
156+ mockConversationsClient . emit ( 'stateChanged' , 'initialized' ) ;
157+ } ) ;
130158 await waitForNextUpdate ( ) ;
131159
132160 expect ( result . current . hasUnreadMessages ) . toBe ( true ) ;
133161
134162 act ( ( ) => {
135163 result . current . setIsChatWindowOpen ( true ) ;
136164 } ) ;
137-
138165 expect ( result . current . hasUnreadMessages ) . toBe ( false ) ;
139166 } ) ;
140167
141- it ( 'should call onError when there is an error connecting with the conversations client' , done => {
142- mockClientCreate . mockImplementationOnce ( ( ) => Promise . reject ( 'mockError' ) ) ;
168+ it ( 'should call onError when there is an error connecting with the conversations client' , ( ) => {
143169 const { result } = renderHook ( useChatContext , { wrapper } ) ;
170+
144171 result . current . connect ( 'mockToken' ) ;
172+ mockConversationsClient . emit ( 'stateChanged' , 'failed' ) ;
173+
174+ expect ( mockOnError ) . toHaveBeenCalledWith (
175+ new Error ( "There was a problem connecting to Twilio's conversation service." )
176+ ) ;
177+ } ) ;
178+
179+ it ( 'should call onError when there is an error getting the conversation' , done => {
180+ mockConversationsClient . getConversationByUniqueName . mockImplementationOnce ( ( ) => Promise . reject ( 'mockError' ) ) ;
181+ const { result } = renderHook ( useChatContext , { wrapper } ) ;
182+
183+ act ( ( ) => {
184+ result . current . connect ( 'mockToken' ) ;
185+ mockConversationsClient . emit ( 'stateChanged' , 'initialized' ) ;
186+ } ) ;
145187
146188 setImmediate ( ( ) => {
147189 expect ( mockOnError ) . toHaveBeenCalledWith (
148- new Error ( " There was a problem connecting to Twilio's conversation service." )
190+ new Error ( ' There was a problem getting the Conversation associated with this room.' )
149191 ) ;
150192 done ( ) ;
151193 } ) ;
152194 } ) ;
153-
154- it ( 'should call onError when there is an error obtaining the conversation' , async ( ) => {
155- mockClient . getConversationByUniqueName . mockImplementationOnce ( ( ) => Promise . reject ( 'mockError' ) ) ;
156- const { result, waitForNextUpdate } = renderHook ( useChatContext , { wrapper } ) ;
157- result . current . connect ( 'mockToken' ) ;
158- await waitForNextUpdate ( ) ;
159-
160- expect ( mockOnError ) . toHaveBeenCalledWith (
161- new Error ( 'There was a problem getting the Conversation associated with this room.' )
162- ) ;
163- } ) ;
164195} ) ;
0 commit comments