diff --git a/app/components/draft_scheduled_post/draft_scheduled_post_actions/send_draft/send_draft.test.tsx b/app/components/draft_scheduled_post/draft_scheduled_post_actions/send_draft/send_draft.test.tsx
index c194275fe..957a64f50 100644
--- a/app/components/draft_scheduled_post/draft_scheduled_post_actions/send_draft/send_draft.test.tsx
+++ b/app/components/draft_scheduled_post/draft_scheduled_post_actions/send_draft/send_draft.test.tsx
@@ -162,6 +162,7 @@ describe('Send Draft', () => {
});
it('should call dismissBottomSheet after sending the draft and should call createPost', async () => {
+ jest.mocked(canPostDraftInChannelOrThread).mockResolvedValueOnce(true);
jest.mocked(sendMessageWithAlert).mockImplementation(() => {
return Promise.resolve();
});
diff --git a/app/components/post_draft/send_handler/send_handler.test.tsx b/app/components/post_draft/send_handler/send_handler.test.tsx
index ffc1309fe..82fb996b7 100644
--- a/app/components/post_draft/send_handler/send_handler.test.tsx
+++ b/app/components/post_draft/send_handler/send_handler.test.tsx
@@ -8,12 +8,10 @@ import {removeDraft} from '@actions/local/draft';
import {createPost} from '@actions/remote/post';
import {General} from '@constants';
import {DRAFT_TYPE_DRAFT, DRAFT_TYPE_SCHEDULED} from '@constants/draft';
-import {SNACK_BAR_TYPE} from '@constants/snack_bar';
import {renderWithEverything} from '@test/intl-test-helper';
import TestHelper from '@test/test_helper';
import {sendMessageWithAlert} from '@utils/post';
import {canPostDraftInChannelOrThread} from '@utils/scheduled_post';
-import {showSnackBar} from '@utils/snack_bar';
import SendHandler from './send_handler';
@@ -260,53 +258,4 @@ describe('components/post_draft/send_handler/SendHandler', () => {
// Varify removeDraft function is been called.
expect(removeDraft).toHaveBeenCalled();
});
-
- it('should show snackbar if creating post failing when executing sendMessageHandler when send_draft_button is checked', async () => {
- // Mock implementation to capture the sendMessageHandler
- let capturedHandler: Function;
- jest.mocked(sendMessageWithAlert).mockImplementation((params) => {
- capturedHandler = params.sendMessageHandler;
- return Promise.resolve();
- });
- jest.mocked(createPost).mockResolvedValueOnce({
- error: new Error('Failed to create post'),
- });
-
- const props = {
- ...baseProps,
- isFromDraftView: true,
- draftType: DRAFT_TYPE_DRAFT,
- value: 'test message',
- };
-
- const wrapper = renderWithEverything(
- , {database},
- );
-
- // Find and press the send button
- const sendButton = wrapper.getByTestId('send_draft_button');
-
- await act(async () => {
- fireEvent.press(sendButton);
- });
-
- // Verify sendMessageWithAlert was called
- expect(sendMessageWithAlert).toHaveBeenCalledWith(expect.objectContaining({
- sendMessageHandler: expect.any(Function),
- }));
-
- // Now execute the captured handler to simulate user confirming the send
- await act(async () => {
- await capturedHandler();
- });
-
- expect(showSnackBar).toHaveBeenCalledWith({
- barType: SNACK_BAR_TYPE.CREATE_POST_ERROR,
- customMessage: 'Failed to create post',
- type: 'error',
- });
-
- // Varify removeDraft function is been called.
- expect(removeDraft).not.toHaveBeenCalled();
- });
});
diff --git a/app/hooks/handle_send_message.test.tsx b/app/hooks/handle_send_message.test.tsx
index 0e50c5d1b..ea74b5916 100644
--- a/app/hooks/handle_send_message.test.tsx
+++ b/app/hooks/handle_send_message.test.tsx
@@ -13,13 +13,11 @@ import {createPost} from '@actions/remote/post';
import {createScheduledPost} from '@actions/remote/scheduled_post';
import {handleCallsSlashCommand} from '@calls/actions';
import {Events, Screens} from '@constants';
-import {SNACK_BAR_TYPE} from '@constants/snack_bar';
import {useServerUrl} from '@context/server';
import DatabaseManager from '@database/manager';
import DraftUploadManager from '@managers/draft_upload_manager';
import {getPostById} from '@queries/servers/post';
import * as DraftUtils from '@utils/draft';
-import {showSnackBar} from '@utils/snack_bar';
import {useHandleSendMessage} from './handle_send_message';
@@ -87,6 +85,10 @@ describe('useHandleSendMessage', () => {
});
});
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
it('should handle basic message send', async () => {
const {result} = renderHook(() => useHandleSendMessage(defaultProps), {wrapper});
@@ -395,24 +397,6 @@ describe('useHandleSendMessage', () => {
expect(defaultProps.clearDraft).toHaveBeenCalled();
});
- it('should handle failed post creation', async () => {
- jest.mocked(createPost).mockResolvedValueOnce({
- error: new Error('Failed to create post'),
- });
-
- const props = {
- ...defaultProps,
- value: 'test message',
- };
-
- const {result} = renderHook(() => useHandleSendMessage(props), {wrapper});
-
- await act(async () => {
- const response = await result.current.handleSendMessage();
- expect(response?.error).toBeDefined();
- });
- });
-
it('should fetch and handle channel timezones', async () => {
jest.mocked(getChannelTimezones).mockResolvedValueOnce({
channelTimezones: ['UTC', 'America/New_York'],
@@ -434,21 +418,6 @@ describe('useHandleSendMessage', () => {
);
});
- it('should not allow sending during message submission', () => {
- const props = {
- ...defaultProps,
- value: 'test message',
- };
-
- const {result} = renderHook(() => useHandleSendMessage(props), {wrapper});
-
- act(() => {
- result.current.handleSendMessage();
- });
-
- expect(result.current.canSend).toBe(false);
- });
-
it('should handle channel-wide mentions confirmation', async () => {
jest.spyOn(DraftUtils, 'textContainsAtAllAtChannel').mockReturnValue(true);
jest.spyOn(DraftUtils, 'alertChannelWideMention');
@@ -662,33 +631,6 @@ describe('useHandleSendMessage', () => {
});
});
- it('should handle failed post creation', async () => {
- jest.mocked(createPost).mockResolvedValueOnce({
- error: new Error('Failed to create post'),
- });
-
- const props = {
- ...defaultProps,
- isFromDraftView: true,
- value: 'test message',
- };
-
- const {result} = renderHook(() => useHandleSendMessage(props), {wrapper});
-
- await act(async () => {
- const response = await result.current.handleSendMessage();
- expect(response?.error).toBeDefined();
- });
-
- expect(showSnackBar).toHaveBeenCalledWith({
- barType: SNACK_BAR_TYPE.CREATE_POST_ERROR,
- customMessage: 'Failed to create post',
- type: 'error',
- });
- expect(defaultProps.clearDraft).not.toHaveBeenCalled();
- expect(DeviceEventEmitter.emit).not.toHaveBeenCalled();
- });
-
it('should show alert when root post is not found', async () => {
jest.mocked(getPostById).mockResolvedValueOnce(undefined);
diff --git a/app/hooks/handle_send_message.ts b/app/hooks/handle_send_message.ts
index 70380e236..28e201e6e 100644
--- a/app/hooks/handle_send_message.ts
+++ b/app/hooks/handle_send_message.ts
@@ -106,7 +106,7 @@ export const useHandleSendMessage = ({
setSendingMessage(false);
}, [serverUrl, rootId, clearDraft]);
- const doSubmitMessage = useCallback(async (schedulingInfo?: SchedulingInfo): Promise => {
+ const doSubmitMessage = useCallback(async (schedulingInfo?: SchedulingInfo) => {
const postFiles = files.filter((f) => !f.failed);
const post = {
user_id: currentUserId,
@@ -128,20 +128,16 @@ export const useHandleSendMessage = ({
let response: CreateResponse;
if (schedulingInfo) {
response = await createScheduledPost(serverUrl, scheduledPostFromPost(post, schedulingInfo, postPriority, postFiles));
- } else {
- response = await createPost(serverUrl, post, postFiles);
- }
-
- if (response.error && isFromDraftView) {
- showSnackBar({
- barType: SNACK_BAR_TYPE.CREATE_POST_ERROR,
- customMessage: getErrorMessage(response.error),
- type: MESSAGE_TYPE.ERROR,
- });
- return response;
- }
-
- if (isFromDraftView) {
+ if (response.error) {
+ showSnackBar({
+ barType: SNACK_BAR_TYPE.SCHEDULED_POST_CREATION_ERROR,
+ customMessage: getErrorMessage(response.error),
+ type: MESSAGE_TYPE.ERROR,
+ });
+ } else {
+ clearDraft();
+ }
+ } else if (isFromDraftView) {
const shouldClearDraft = await canPostDraftInChannelOrThread({
serverUrl,
rootId,
@@ -152,16 +148,23 @@ export const useHandleSendMessage = ({
deactivatedChannel,
});
- if (shouldClearDraft) {
- clearDraft();
+ if (!shouldClearDraft) {
+ return;
}
+
+ createPost(serverUrl, post, postFiles);
+ clearDraft();
+
+ // Early return to avoid calling DeviceEventEmitter.emit
+ return;
} else {
+ // Response error is handled at the post level so don't have to wait to clear draft
+ createPost(serverUrl, post, postFiles);
clearDraft();
}
+
setSendingMessage(false);
DeviceEventEmitter.emit(Events.POST_LIST_SCROLL_TO_BOTTOM, rootId ? Screens.THREAD : Screens.CHANNEL);
-
- return response;
}, [files, currentUserId, channelId, rootId, value, postPriority, isFromDraftView, serverUrl, intl, canPost, channelIsArchived, channelIsReadOnly, deactivatedChannel, clearDraft]);
const showSendToAllOrChannelOrHereAlert = useCallback((calculatedMembersCount: number, atHere: boolean, schedulingInfo?: SchedulingInfo) => {