Skip to content

Commit ff43179

Browse files
authored
fix: prevent querying thread draft when drafts are disabled (#2767)
1 parent c014b1f commit ff43179

File tree

7 files changed

+85
-26
lines changed

7 files changed

+85
-26
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@
142142
"emoji-mart": "^5.4.0",
143143
"react": "^19.0.0 || ^18.0.0 || ^17.0.0 || ^16.14.0",
144144
"react-dom": "^19.0.0 || ^18.0.0 || ^17.0.0 || ^16.14.0",
145-
"stream-chat": "^9.8.0"
145+
"stream-chat": "^9.10.1"
146146
},
147147
"peerDependenciesMeta": {
148148
"@breezystack/lamejs": {
@@ -236,7 +236,7 @@
236236
"react": "^19.0.0",
237237
"react-dom": "^19.0.0",
238238
"semantic-release": "^24.2.3",
239-
"stream-chat": "^9.8.0",
239+
"stream-chat": "^9.10.1",
240240
"ts-jest": "^29.2.5",
241241
"typescript": "^5.4.5",
242242
"typescript-eslint": "^8.17.0"

src/components/MessageInput/MessageInput.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,12 @@ const MessageInputProvider = (props: PropsWithChildren<MessageInputProps>) => {
111111

112112
useEffect(() => {
113113
const threadId = messageComposer.threadId;
114-
if (!threadId || !messageComposer.channel || !messageComposer.compositionIsEmpty)
114+
if (
115+
!threadId ||
116+
!messageComposer.channel ||
117+
!messageComposer.compositionIsEmpty ||
118+
!messageComposer.config.drafts.enabled
119+
)
115120
return;
116121
// get draft data for legacy thead composer
117122
messageComposer.channel.getDraft({ parent_id: threadId }).then(({ draft }) => {

src/components/MessageInput/__tests__/EditMessageForm.test.js

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -822,18 +822,6 @@ describe(`EditMessageForm`, () => {
822822
});
823823

824824
describe('Submitting', () => {
825-
it('should not submit the message if content not change', async () => {
826-
const { customChannel, customClient } = await setup();
827-
const { container, submit } = await renderComponent({
828-
customChannel,
829-
customClient,
830-
});
831-
832-
await act(() => submit());
833-
834-
expect(editMock).not.toHaveBeenCalled();
835-
await axeNoViolations(container);
836-
});
837825
it('should submit the input value with text changed', async () => {
838826
const { customChannel, customClient } = await setup();
839827
const { container, submit } = await renderComponent({

src/components/MessageInput/__tests__/ThreadMessageInput.test.js

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
generateUser,
77
initClientWithChannels,
88
} from '../../../mock-builders';
9-
import { act, fireEvent, render, screen } from '@testing-library/react';
9+
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
1010
import { ChatProvider, MessageProvider, useChannelActionContext } from '../../../context';
1111
import { Channel } from '../../Channel';
1212
import { MessageActionsBox } from '../../MessageActions';
@@ -78,7 +78,9 @@ const setup = async ({ channelData } = {}) => {
7878
const sendFileSpy = jest.spyOn(customChannel, 'sendFile').mockResolvedValueOnce({
7979
file: fileUploadUrl,
8080
});
81-
const getDraftSpy = jest.spyOn(customChannel, 'getDraft').mockResolvedValue({});
81+
const getDraftSpy = jest
82+
.spyOn(customChannel, 'getDraft')
83+
.mockResolvedValue({ draft: { message: { id: 'x' } } });
8284
customChannel.initialized = true;
8385
customClient.activeChannels[customChannel.cid] = customChannel;
8486
return { customChannel, customClient, getDraftSpy, sendFileSpy, sendImageSpy };
@@ -157,13 +159,68 @@ const renderComponent = async ({
157159
};
158160

159161
describe('MessageInput in Thread', () => {
162+
describe('draft', () => {
163+
it('is queried when drafts are enabled', async () => {
164+
const { customChannel, customClient, getDraftSpy } = await setup();
165+
await act(() => {
166+
customClient.setMessageComposerSetupFunction(({ composer }) => {
167+
composer.updateConfig({ drafts: { enabled: true } });
168+
});
169+
});
170+
await renderComponent({
171+
customChannel,
172+
customClient,
173+
});
174+
expect(getDraftSpy).toHaveBeenCalledTimes(1);
175+
});
176+
it('prevents querying if composition is not empty', async () => {
177+
const { customChannel, customClient, getDraftSpy } = await setup();
178+
await act(() => {
179+
customClient.setMessageComposerSetupFunction(({ composer }) => {
180+
composer.updateConfig({ drafts: { enabled: true } });
181+
composer.textComposer.setText('abc');
182+
});
183+
});
184+
await renderComponent({
185+
customChannel,
186+
customClient,
187+
});
188+
expect(getDraftSpy).not.toHaveBeenCalled();
189+
});
190+
it('prevents querying if not rendered inside a thread', async () => {
191+
const { customChannel, customClient, getDraftSpy } = await setup();
192+
await act(() => {
193+
customClient.setMessageComposerSetupFunction(({ composer }) => {
194+
composer.updateConfig({ drafts: { enabled: true } });
195+
composer.compositionContext = customChannel;
196+
});
197+
});
198+
await renderComponent({
199+
customChannel,
200+
customClient,
201+
});
202+
expect(getDraftSpy).not.toHaveBeenCalled();
203+
});
204+
it('prevents querying if drafts are disabled (default)', async () => {
205+
const { customChannel, customClient, getDraftSpy } = await setup();
206+
await renderComponent({
207+
customChannel,
208+
customClient,
209+
});
210+
expect(getDraftSpy).not.toHaveBeenCalled();
211+
});
212+
});
213+
160214
it('renders in the thread context for direct messaging channel', async () => {
161215
const { customChannel, customClient } = await setup();
162216
await renderComponent({
163217
customChannel,
164218
customClient,
165219
});
166-
expect(screen.getByLabelText('Also send as a direct message')).toBeInTheDocument();
220+
221+
await waitFor(() => {
222+
expect(screen.getByLabelText('Also send as a direct message')).toBeInTheDocument();
223+
});
167224
});
168225
it('renders in the thread context for non-direct messaging channel', async () => {
169226
const mainListMessage = generateMessage({ cid, user });

src/mock-builders/generator/channel.js renamed to src/mock-builders/generator/channel.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import { nanoid } from 'nanoid';
2+
import type { ChannelConfigWithInfo, ChannelResponse } from 'stream-chat';
23

3-
export const generateChannel = (options = { channel: {} }) => {
4+
export const generateChannel = (
5+
options: {
6+
channel?: Partial<ChannelResponse>;
7+
config?: Partial<ChannelConfigWithInfo>;
8+
} = { channel: {}, config: {} },
9+
) => {
410
const { channel: optionsChannel, config, ...optionsBesidesChannel } = options;
511
const id = optionsChannel?.id ?? nanoid();
612
const type = optionsChannel?.type ?? 'messaging';
@@ -43,7 +49,7 @@ export const generateChannel = (options = { channel: {} }) => {
4349
uploads: true,
4450
url_enrichment: true,
4551
...config,
46-
},
52+
} as ChannelConfigWithInfo,
4753

4854
created_at: '2020-04-28T11:20:48.578147Z',
4955

@@ -56,11 +62,12 @@ export const generateChannel = (options = { channel: {} }) => {
5662
role: 'user',
5763
updated_at: '2020-04-28T11:21:08.357468Z',
5864
},
65+
disabled: false,
5966
frozen: false,
6067
id,
6168
type,
6269
updated_at: '2020-04-28T11:20:48.578147Z',
6370
...restOptionsChannel,
64-
},
71+
} as ChannelResponse,
6572
};
6673
};

src/mock-builders/generator/reminder.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import type { ReminderResponse } from 'stream-chat';
2+
import { generateChannel } from './channel';
23

34
const baseData = {
4-
channel_cid: 'channel_cid',
5+
channel_cid: 'messaging:id',
56
message_id: 'message_id',
67
user_id: 'user_id',
78
} as const;
@@ -16,6 +17,7 @@ export const generateReminderResponse = ({
1617
const created_at = new Date().toISOString();
1718
const basePayload: ReminderResponse = {
1819
...baseData,
20+
channel: generateChannel({ channel: { cid: baseData.channel_cid } }).channel,
1921
created_at,
2022
message: { id: baseData.message_id, type: 'regular' },
2123
updated_at: created_at,

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12036,10 +12036,10 @@ [email protected]:
1203612036
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
1203712037
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
1203812038

12039-
stream-chat@^9.8.0:
12040-
version "9.8.0"
12041-
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.8.0.tgz#52782073a3923367fe97638fde39ce18e4eed28a"
12042-
integrity sha512-iKFVFOKWuW2/GTWBOps9YWZoQBlXdJ05FiOKXI/AnCMCGzOpmvEyaoCtsktvdeMaetmZojVPbw/5jomP36Qg0Q==
12039+
stream-chat@^9.10.1:
12040+
version "9.10.1"
12041+
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.10.1.tgz#d460faeacfc55159bce0caf16067d4dec344b474"
12042+
integrity sha512-JwiM/iqaU16SlyG90eAezayKGnVmhNjrPfRKATlriwvGEaO8kgZfCUg5It4hIqXgdIAHFbrwHF6OHexWVXpY8w==
1204312043
dependencies:
1204412044
"@types/jsonwebtoken" "^9.0.8"
1204512045
"@types/ws" "^8.5.14"

0 commit comments

Comments
 (0)