Skip to content

Commit a027d22

Browse files
authored
Merge pull request #185 from nada-deriv/nada/FEQ-2399/use-sendbird-test
Nada/FEQ-2399/chore: unit test for usesendbird
2 parents 23fbf8e + 1516307 commit a027d22

File tree

2 files changed

+370
-1
lines changed

2 files changed

+370
-1
lines changed

src/components/DatePicker/DatePicker.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const DatePicker = ({
5959

6060
// To not display the date value when today's date is selected.
6161
const getValue = () => {
62-
if (selectedDate && (showLabel || selectedDate.getDate() !== new Date().getDate())) {
62+
if (selectedDate && (showLabel || selectedDate.toDateString() !== new Date().toDateString())) {
6363
return unixToDateString(selectedDate, displayFormat);
6464
}
6565
return '';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
import SendbirdChat from '@sendbird/chat';
2+
import { renderHook, waitFor } from '@testing-library/react';
3+
import useSendbird from '../useSendbird';
4+
5+
jest.mock('../../', () => ({
6+
...jest.requireActual('../../'),
7+
api: {
8+
account: {
9+
useSendbirdServiceToken: jest.fn().mockReturnValue({
10+
data: {
11+
app_id: 'A123-456-789',
12+
expiry_time: 1234567890,
13+
token: '0123445678901234567890',
14+
},
15+
isSuccess: true,
16+
}),
17+
useServerTime: jest.fn().mockReturnValue({
18+
data: {
19+
server_time: 1234567890,
20+
server_time_utc: 1719832008000,
21+
},
22+
}),
23+
},
24+
advertiser: {
25+
useGetInfo: jest.fn().mockReturnValue({
26+
data: {
27+
chat_user_id: 'chat_user_id1',
28+
id: 'id1',
29+
},
30+
}),
31+
},
32+
chat: {
33+
useCreate: jest.fn().mockReturnValue({
34+
isError: false,
35+
mutate: jest.fn(),
36+
}),
37+
},
38+
},
39+
}));
40+
41+
jest.mock('@sendbird/chat', () => ({
42+
init: jest.fn().mockReturnValue({
43+
connect: jest.fn().mockReturnValue(undefined),
44+
disconnect: jest.fn(),
45+
groupChannel: {
46+
addGroupChannelHandler: jest.fn(),
47+
getChannel: jest.fn().mockReturnValue(undefined),
48+
},
49+
}),
50+
SendBirdAction: {
51+
ChannelHandler: jest.fn().mockReturnValue({
52+
onMessageReceived: jest.fn(),
53+
}),
54+
},
55+
}));
56+
57+
const mockSendBirdChatApi = SendbirdChat as jest.Mocked<typeof SendbirdChat>;
58+
59+
const mockUserValues = {
60+
_iid: 'id1',
61+
connectionStatus: 'nonavailable',
62+
friendDiscoveryKey: null,
63+
friendName: null,
64+
isActive: true,
65+
lastSeenAt: null,
66+
metaData: {},
67+
nickname: 'client CR90000562',
68+
plainProfileUrl: '',
69+
preferredLanguages: [],
70+
requireAuth: false,
71+
userId: 'p2puser_CR_92_1719813335',
72+
};
73+
74+
const mockChannelValues = {
75+
_createdAt: 1719816440000,
76+
_iid: 'id1',
77+
_lastMemberCountUpdated: 0,
78+
_messageCollectionLastAccessedAt: 0,
79+
_myMutedRemainingTime: -1,
80+
_name: 'Chat about order 34',
81+
_pinnedMessagesUpdatedAt: 0,
82+
_typingEnded: 0,
83+
_typingStarted: 0,
84+
_typingStatus: {},
85+
_undeliveredMemberStateMap: {},
86+
_unreadMemberStateMap: {},
87+
_url: 'p2porder_CR_34_1719816439',
88+
channelType: 'group',
89+
coverUrl: 'https://static.sendbird.com/sample/cover/cover_11.jpg',
90+
createdAt: 1719816440000,
91+
creator: null,
92+
customType: '',
93+
data: '',
94+
hiddenState: 'unhidden',
95+
invitedAt: 1719816440289,
96+
inviter: null,
97+
isAccessCodeRequired: false,
98+
isBroadcast: false,
99+
isChatNotification: false,
100+
isDiscoverable: false,
101+
isDistinct: false,
102+
isEphemeral: false,
103+
isExclusive: false,
104+
isFrozen: false,
105+
isPublic: false,
106+
isPushEnabled: true,
107+
isSuper: false,
108+
joinedAt: 1719816440,
109+
joinedMemberCount: 2,
110+
lastMessage: null,
111+
lastPinnedMessage: null,
112+
memberCount: 2,
113+
members: [
114+
{
115+
_iid: 'id2',
116+
connectionStatus: 'offline',
117+
friendDiscoveryKey: null,
118+
friendName: null,
119+
isActive: true,
120+
isBlockedByMe: false,
121+
isBlockingMe: false,
122+
isMuted: false,
123+
lastSeenAt: -1,
124+
metaData: {},
125+
nickname: 'client CR90000101',
126+
plainProfileUrl: '',
127+
preferredLanguages: null,
128+
requireAuth: false,
129+
restrictionInfo: {
130+
description: null,
131+
endAt: -1,
132+
remainingDuration: -1,
133+
restrictionType: null,
134+
},
135+
role: null,
136+
state: 'joined',
137+
userId: 'p2puser_CR_19_1719783873',
138+
},
139+
],
140+
messageOffsetTimestamp: 0,
141+
messageSurvivalSeconds: -1,
142+
myCountPreference: 'all',
143+
myLastRead: 1719816440289,
144+
myMemberState: 'joined',
145+
myMutedState: 'unmuted',
146+
myPushTriggerOption: 'default',
147+
myRole: 'none',
148+
name: 'Chat about order 34',
149+
pinnedMessageIds: [],
150+
totalUnreadReplyCount: 0,
151+
unreadMentionCount: 0,
152+
unreadMessageCount: 0,
153+
url: 'p2porder_CR_34_1719816439',
154+
};
155+
156+
const mockRetrievedMessages = [
157+
{
158+
_iid: 'fthft4',
159+
channelType: 'group',
160+
channelUrl: 'chatchannelurl',
161+
createdAt: 1719829975618,
162+
customType: '',
163+
data: '1719829975217test message channel1',
164+
errorCode: 0,
165+
isFileMessage: jest.fn(() => false),
166+
isUserMessage: jest.fn(() => true),
167+
mentionType: 'users',
168+
message: 'test message channel',
169+
messageId: 1719829975217,
170+
messageType: 'user',
171+
sender: {
172+
_iid: 'rthhhrth',
173+
isActive: true,
174+
nickname: 'client CR90000562',
175+
userId: 'p2puser_CR_92_1719813335',
176+
},
177+
sendingStatus: 'succeeded',
178+
updatedAt: 0,
179+
},
180+
];
181+
182+
describe('useSendbird', () => {
183+
it('should return isError as true when there is error in orderInfo', async () => {
184+
const { result } = renderHook(() => useSendbird('id1', true, 'chatchannelurl'));
185+
186+
expect(result.current.isError).toBeTruthy();
187+
});
188+
189+
it('should return isError as true when no user is returned', async () => {
190+
const { result } = renderHook(() => useSendbird('id1', false, 'chatchannelurl'));
191+
await waitFor(() => {
192+
expect(result.current.isError).toBeTruthy();
193+
});
194+
});
195+
196+
it('should return isError as true, when no channel is returned', async () => {
197+
// @ts-expect-error only necessary properties are mocked
198+
mockSendBirdChatApi.init.mockReturnValue({
199+
connect: jest.fn().mockReturnValue(mockUserValues),
200+
disconnect: jest.fn(),
201+
groupChannel: {
202+
addGroupChannelHandler: jest.fn(),
203+
getChannel: jest.fn().mockReturnValue(undefined),
204+
},
205+
});
206+
const { result } = renderHook(() => useSendbird('id1', false, 'chatchannelurl'));
207+
await waitFor(() => {
208+
expect(result.current.isError).toBeTruthy();
209+
});
210+
});
211+
212+
it('should return the active chat channel', async () => {
213+
// @ts-expect-error only necessary properties are mocked
214+
mockSendBirdChatApi.init.mockReturnValue({
215+
connect: jest.fn().mockReturnValue(mockUserValues),
216+
disconnect: jest.fn(),
217+
groupChannel: {
218+
addGroupChannelHandler: jest.fn(),
219+
getChannel: jest.fn().mockReturnValue(mockChannelValues),
220+
},
221+
});
222+
const { result } = renderHook(() => useSendbird('id1', false, 'chatchannelurl'));
223+
await waitFor(() => {
224+
expect(result.current.activeChatChannel).toBe(mockChannelValues);
225+
});
226+
});
227+
228+
it('should return the messages', async () => {
229+
// @ts-expect-error only necessary properties are mocked
230+
mockSendBirdChatApi.init.mockReturnValue({
231+
connect: jest.fn().mockReturnValue(mockUserValues),
232+
disconnect: jest.fn(),
233+
groupChannel: {
234+
addGroupChannelHandler: jest.fn(),
235+
getChannel: jest.fn().mockReturnValue({
236+
...mockChannelValues,
237+
getMessagesByTimestamp: jest.fn().mockReturnValue(mockRetrievedMessages),
238+
}),
239+
},
240+
});
241+
const { result } = renderHook(() => useSendbird('id1', false, 'chatchannelurl'));
242+
243+
await waitFor(() => {
244+
expect(result.current.messages).toEqual([
245+
expect.objectContaining({
246+
message: 'test message channel',
247+
}),
248+
]);
249+
});
250+
});
251+
252+
it('should handle sendMessage', async () => {
253+
const mockFn = jest.fn();
254+
// @ts-expect-error only necessary properties are mocked
255+
mockSendBirdChatApi.init.mockReturnValue({
256+
connect: jest.fn().mockReturnValue(mockUserValues),
257+
disconnect: jest.fn(),
258+
groupChannel: {
259+
addGroupChannelHandler: jest.fn(),
260+
getChannel: jest.fn().mockReturnValue({
261+
...mockChannelValues,
262+
getMessagesByTimestamp: jest.fn().mockReturnValue(mockRetrievedMessages),
263+
sendUserMessage: mockFn.mockImplementation(params => {
264+
const message = {
265+
id: params.data, // Assuming data is used as id
266+
isFileMessage: () => false,
267+
isUserMessage: () => true,
268+
message: params.message,
269+
messageId: 1719829975217,
270+
};
271+
272+
// Simulate onSucceeded callback
273+
const onSucceeded = (
274+
handler: (message: {
275+
id: string;
276+
isFileMessage: () => void;
277+
isUserMessage: () => void;
278+
message: string;
279+
}) => void
280+
) => {
281+
handler(message); // Simulate invoking onSucceeded with mock message
282+
return {
283+
onFailed: () => {},
284+
onPending: () => {},
285+
onSucceeded: () => {},
286+
};
287+
};
288+
289+
return {
290+
onFailed: () => {},
291+
onPending: () => {},
292+
onSucceeded,
293+
};
294+
}),
295+
}),
296+
},
297+
});
298+
const { result } = renderHook(() => useSendbird('id1', false, 'chatchannelurl'));
299+
300+
await waitFor(() => {
301+
result.current.sendMessage('message to send');
302+
expect(mockFn).toHaveBeenCalledWith(expect.objectContaining({ message: 'message to send' }));
303+
});
304+
});
305+
306+
it('should handle sendFileMessage', async () => {
307+
const mockFn = jest.fn();
308+
// @ts-expect-error only necessary properties are mocked
309+
mockSendBirdChatApi.init.mockReturnValue({
310+
connect: jest.fn().mockReturnValue(mockUserValues),
311+
disconnect: jest.fn(),
312+
groupChannel: {
313+
addGroupChannelHandler: jest.fn(),
314+
getChannel: jest.fn().mockReturnValue({
315+
...mockChannelValues,
316+
getMessagesByTimestamp: jest.fn().mockReturnValue(mockRetrievedMessages),
317+
sendFileMessage: mockFn.mockImplementation(({ file, fileName, fileSize, mimeType }) => {
318+
const sentMessage = {
319+
channelUrl: 'mockChannelUrl',
320+
file,
321+
fileName,
322+
fileSize,
323+
isFileMessage: () => true, // Mocking isFileMessage for success case
324+
mimeType,
325+
};
326+
327+
// Simulate onPending callback
328+
const onPending = (handler: () => void) => {
329+
handler(); // Call the handler
330+
return { onFailed, onPending, onSucceeded };
331+
};
332+
333+
// Simulate onSucceeded callback
334+
const onSucceeded = (
335+
handler: (arg0: {
336+
channelUrl: string;
337+
file: File;
338+
fileName: string;
339+
fileSize: number;
340+
isFileMessage: () => boolean;
341+
mimeType: string;
342+
}) => void
343+
) => {
344+
handler(sentMessage);
345+
return { onFailed, onPending, onSucceeded };
346+
};
347+
348+
const onFailed = (handler: () => void) => {
349+
handler(); // Call the handler
350+
return { onFailed, onPending, onSucceeded };
351+
};
352+
return {
353+
onFailed,
354+
onPending,
355+
onSucceeded,
356+
};
357+
}),
358+
}),
359+
},
360+
});
361+
const { result } = renderHook(() => useSendbird('id1', false, 'chatchannelurl'));
362+
const file = new File([''], 'filename');
363+
364+
await waitFor(() => {
365+
result.current.sendFile(file);
366+
expect(mockFn).toHaveBeenCalledWith(expect.objectContaining({ file }));
367+
});
368+
});
369+
});

0 commit comments

Comments
 (0)