Skip to content

Commit b039a29

Browse files
committed
Resolve conflict after rebase from main
1 parent 8e9e748 commit b039a29

File tree

5 files changed

+190
-156
lines changed

5 files changed

+190
-156
lines changed

src/modules/GroupChannel/context/__test__/GroupChannelProvider.spec.tsx renamed to src/modules/GroupChannel/context/__tests__/GroupChannelProvider.spec.tsx

File renamed without changes.

src/modules/GroupChannel/context/__test__/useGroupChannel.spec.tsx renamed to src/modules/GroupChannel/context/__tests__/useGroupChannel.spec.tsx

File renamed without changes.

src/modules/GroupChannel/context/__tests__/useMessageActions.spec.ts

Lines changed: 0 additions & 154 deletions
This file was deleted.

src/modules/GroupChannel/context/__test__/useMessageActions.spec.tsx renamed to src/modules/GroupChannel/context/__tests__/useMessageActions.spec.tsx

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,65 @@
11
import { renderHook } from '@testing-library/react-hooks';
2+
import { UserMessageCreateParams, FileMessageCreateParams } from '@sendbird/chat/message';
3+
24
import { useMessageActions } from '../hooks/useMessageActions';
35

6+
const mockEventHandlers = {
7+
message: {
8+
onSendMessageFailed: jest.fn(),
9+
onUpdateMessageFailed: jest.fn(),
10+
onFileUploadFailed: jest.fn(),
11+
},
12+
};
13+
const mockChannel = {
14+
url: 'test-channel',
15+
members: [{ userId: '1', nickname: 'user1' }],
16+
};
17+
const mockGetChannel = jest.fn().mockResolvedValue(mockChannel);
18+
const mockMessageCollection = {
19+
dispose: jest.fn(),
20+
setMessageCollectionHandler: jest.fn(),
21+
initialize: jest.fn().mockResolvedValue(null),
22+
loadPrevious: jest.fn(),
23+
loadNext: jest.fn(),
24+
};
25+
jest.mock('../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
26+
__esModule: true,
27+
default: jest.fn(() => ({
28+
state: {
29+
eventHandlers: mockEventHandlers,
30+
stores: {
31+
sdkStore: {
32+
sdk: {
33+
groupChannel: {
34+
getChannel: mockGetChannel,
35+
addGroupChannelHandler: jest.fn(),
36+
removeGroupChannelHandler: jest.fn(),
37+
},
38+
createMessageCollection: jest.fn().mockReturnValue(mockMessageCollection),
39+
},
40+
initialized: true,
41+
},
42+
},
43+
config: {
44+
markAsReadScheduler: {
45+
push: jest.fn(),
46+
},
47+
groupChannel: {
48+
replyType: 'NONE',
49+
threadReplySelectType: 'PARENT',
50+
},
51+
groupChannelSettings: {
52+
enableMessageSearch: true,
53+
},
54+
isOnline: true,
55+
pubSub: {
56+
subscribe: () => ({ remove: jest.fn() }),
57+
},
58+
},
59+
},
60+
})),
61+
}));
62+
463
describe('useMessageActions', () => {
564
// Setup common mocks
665
const mockSendUserMessage = jest.fn();
@@ -183,4 +242,133 @@ describe('useMessageActions', () => {
183242
);
184243
});
185244
});
245+
246+
describe('processParams', () => {
247+
const mockParams = {
248+
sendUserMessage: jest.fn(),
249+
sendFileMessage: jest.fn(),
250+
sendMultipleFilesMessage: jest.fn(),
251+
updateUserMessage: jest.fn(),
252+
scrollToBottom: jest.fn(),
253+
replyType: 'NONE',
254+
};
255+
it('should handle successful user message', async () => {
256+
const { result } = renderHook(() => useMessageActions(mockParams));
257+
const params: UserMessageCreateParams = { message: 'test' };
258+
259+
await result.current.sendUserMessage(params);
260+
261+
expect(mockParams.sendUserMessage).toHaveBeenCalledWith(
262+
expect.objectContaining({ message: 'test' }),
263+
expect.any(Function),
264+
);
265+
});
266+
267+
it('should handle void return from onBeforeSendFileMessage', async () => {
268+
const onBeforeSendFileMessage = jest.fn();
269+
const { result } = renderHook(() => useMessageActions({
270+
...mockParams,
271+
onBeforeSendFileMessage,
272+
}),
273+
);
274+
275+
const fileParams: FileMessageCreateParams = {
276+
file: new File([], 'test.txt'),
277+
};
278+
279+
await result.current.sendFileMessage(fileParams);
280+
281+
expect(onBeforeSendFileMessage).toHaveBeenCalled();
282+
expect(mockParams.sendFileMessage).toHaveBeenCalledWith(
283+
expect.objectContaining(fileParams),
284+
expect.any(Function),
285+
);
286+
});
287+
288+
it('should handle file upload error', async () => {
289+
// Arrange
290+
const error = new Error('Upload failed');
291+
const onBeforeSendFileMessage = jest.fn().mockRejectedValue(error);
292+
const fileParams: FileMessageCreateParams = {
293+
file: new File([], 'test.txt'),
294+
fileName: 'test.txt',
295+
};
296+
297+
const { result } = renderHook(() => useMessageActions({
298+
...mockParams,
299+
onBeforeSendFileMessage,
300+
}),
301+
);
302+
303+
await expect(async () => {
304+
await result.current.sendFileMessage(fileParams);
305+
}).rejects.toThrow('Upload failed');
306+
307+
// Wait for next tick to ensure all promises are resolved
308+
await new Promise(process.nextTick);
309+
310+
expect(onBeforeSendFileMessage).toHaveBeenCalled();
311+
expect(mockEventHandlers.message.onFileUploadFailed).toHaveBeenCalledWith(error);
312+
expect(mockEventHandlers.message.onSendMessageFailed).toHaveBeenCalledWith(
313+
expect.objectContaining({
314+
file: fileParams.file,
315+
fileName: fileParams.fileName,
316+
}),
317+
error,
318+
);
319+
});
320+
321+
it('should handle message update error', async () => {
322+
// Arrange
323+
const error = new Error('Update failed');
324+
const onBeforeUpdateUserMessage = jest.fn().mockRejectedValue(error);
325+
const messageParams = {
326+
messageId: 1,
327+
message: 'update message',
328+
};
329+
330+
const { result } = renderHook(() => useMessageActions({
331+
...mockParams,
332+
onBeforeUpdateUserMessage,
333+
}),
334+
);
335+
336+
await expect(async () => {
337+
await result.current.updateUserMessage(messageParams.messageId, {
338+
message: messageParams.message,
339+
});
340+
}).rejects.toThrow('Update failed');
341+
342+
// Wait for next tick to ensure all promises are resolved
343+
await new Promise(process.nextTick);
344+
345+
expect(onBeforeUpdateUserMessage).toHaveBeenCalled();
346+
expect(mockEventHandlers.message.onUpdateMessageFailed).toHaveBeenCalledWith(
347+
expect.objectContaining({
348+
message: messageParams.message,
349+
}),
350+
error,
351+
);
352+
});
353+
354+
it('should preserve modified params from onBefore handlers', async () => {
355+
const onBeforeSendUserMessage = jest.fn().mockImplementation((params) => ({
356+
...params,
357+
message: 'modified',
358+
}));
359+
360+
const { result } = renderHook(() => useMessageActions({
361+
...mockParams,
362+
onBeforeSendUserMessage,
363+
}),
364+
);
365+
366+
await result.current.sendUserMessage({ message: 'original' });
367+
368+
expect(mockParams.sendUserMessage).toHaveBeenCalledWith(
369+
expect.objectContaining({ message: 'modified' }),
370+
expect.any(Function),
371+
);
372+
});
373+
});
186374
});

src/modules/GroupChannel/context/hooks/useMessageActions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
VOICE_MESSAGE_MIME_TYPE,
2222
} from '../../../../utils/consts';
2323
import type { CoreMessageType } from '../../../../utils';
24-
import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
24+
import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
2525
import type { GroupChannelState, OnBeforeHandler } from '../types';
2626

2727
type MessageListDataSource = ReturnType<typeof useGroupChannelMessages>;
@@ -70,7 +70,7 @@ export function useMessageActions(params: Params): MessageActions {
7070
quoteMessage,
7171
replyType,
7272
} = params;
73-
const { eventHandlers } = useSendbirdStateContext();
73+
const { state: { eventHandlers } } = useSendbird();
7474
const buildInternalMessageParams = useCallback(
7575
<T extends BaseMessageCreateParams>(basicParams: T): T => {
7676
const messageParams = { ...basicParams } as T;

0 commit comments

Comments
 (0)