Skip to content

Commit 16b1fb6

Browse files
committed
chore: add tests for send message pending tasks
1 parent 6e6a3e3 commit 16b1fb6

File tree

1 file changed

+154
-45
lines changed

1 file changed

+154
-45
lines changed

package/src/__tests__/offline-support/optimistic-update.js

Lines changed: 154 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import { v4 as uuidv4 } from 'uuid';
77

88
import { Channel } from '../../components/Channel/Channel';
99
import { Chat } from '../../components/Chat/Chat';
10-
import { MessagesContext } from '../../contexts';
10+
import { ChannelContext, ChatContext, MessageInputContext, MessagesContext } from '../../contexts';
1111
import { deleteMessageApi } from '../../mock-builders/api/deleteMessage';
1212
import { deleteReactionApi } from '../../mock-builders/api/deleteReaction';
1313
import { erroredDeleteApi, erroredPostApi } from '../../mock-builders/api/error';
1414
import { getOrCreateChannelApi } from '../../mock-builders/api/getOrCreateChannel';
15+
import { sendMessageApi } from '../../mock-builders/api/sendMessage';
1516
import { sendReactionApi } from '../../mock-builders/api/sendReaction';
1617
import { useMockedApis } from '../../mock-builders/api/useMockedApis';
1718
import dispatchConnectionChangedEvent from '../../mock-builders/event/connectionChanged';
@@ -100,7 +101,6 @@ export const OptimisticUpdates = () => {
100101
const channelResponse = createChannel();
101102
useMockedApis(chatClient, [getOrCreateChannelApi(channelResponse)]);
102103
channel = chatClient.channel('messaging', channelResponse.id);
103-
console.log('BEFORE HERE');
104104
await channel.watch();
105105

106106
channel.cid = channelResponse.channel.cid;
@@ -178,7 +178,7 @@ export const OptimisticUpdates = () => {
178178
});
179179
});
180180

181-
it('pending task should be cleared if deleteMessage request is succesful', async () => {
181+
it('pending task should be cleared if deleteMessage request is successful', async () => {
182182
const message = generateMessage();
183183
render(
184184
<Chat client={chatClient} enableOfflineSupport>
@@ -238,7 +238,7 @@ export const OptimisticUpdates = () => {
238238
});
239239
});
240240

241-
it('pending task should be cleared if sendReaction request is succesful', async () => {
241+
it('pending task should be cleared if sendReaction request is successful', async () => {
242242
const reaction = generateReaction();
243243
const targetMessage = channel.state.messages[0];
244244

@@ -265,6 +265,69 @@ export const OptimisticUpdates = () => {
265265
});
266266
});
267267

268+
describe('send message', () => {
269+
it('pending task should exist if sendMessage request fails', async () => {
270+
const newMessage = generateMessage();
271+
272+
render(
273+
<Chat client={chatClient} enableOfflineSupport>
274+
<Channel channel={channel} initialValue={newMessage.text}>
275+
<CallbackEffectWithContext
276+
callback={async ({ sendMessage }) => {
277+
useMockedApis(chatClient, [erroredPostApi()]);
278+
try {
279+
await sendMessage({ customMessageData: newMessage });
280+
} catch (e) {
281+
// do nothing
282+
}
283+
}}
284+
context={MessageInputContext}
285+
>
286+
<View testID='children' />
287+
</CallbackEffectWithContext>
288+
</Channel>
289+
</Chat>,
290+
);
291+
await waitFor(() => expect(screen.getByTestId('children')).toBeTruthy());
292+
await waitFor(async () => {
293+
const pendingTasksRows = await BetterSqlite.selectFromTable('pendingTasks');
294+
const pendingTaskType = pendingTasksRows?.[0]?.type;
295+
const pendingTaskPayload = JSON.parse(pendingTasksRows?.[0]?.payload || '{}');
296+
expect(pendingTaskType).toBe('send-message');
297+
expect(pendingTaskPayload[0].id).toEqual(newMessage.id);
298+
expect(pendingTaskPayload[0].text).toEqual(newMessage.text);
299+
});
300+
});
301+
302+
it('pending task should be cleared if sendMessage request is successful', async () => {
303+
const newMessage = generateMessage();
304+
305+
// initialValue is needed as a prop to trick the message input ctx into thinking
306+
// we are sending a message.
307+
render(
308+
<Chat client={chatClient} enableOfflineSupport>
309+
<Channel channel={channel} initialValue={newMessage.text}>
310+
<CallbackEffectWithContext
311+
callback={async ({ sendMessage }) => {
312+
useMockedApis(chatClient, [sendMessageApi(newMessage)]);
313+
await sendMessage({ customMessageData: newMessage });
314+
}}
315+
context={MessageInputContext}
316+
>
317+
<View testID='children' />
318+
</CallbackEffectWithContext>
319+
</Channel>
320+
</Chat>,
321+
);
322+
await waitFor(() => expect(screen.getByTestId('children')).toBeTruthy());
323+
324+
await waitFor(async () => {
325+
const pendingTasksRows = await BetterSqlite.selectFromTable('pendingTasks');
326+
expect(pendingTasksRows.length).toBe(0);
327+
});
328+
});
329+
});
330+
268331
describe('delete reaction', () => {
269332
it('pending task should exist if deleteReaction request fails', async () => {
270333
const reaction = generateReaction();
@@ -299,7 +362,7 @@ export const OptimisticUpdates = () => {
299362
});
300363
});
301364

302-
it('pending task should be cleared if deleteReaction request is succesful', async () => {
365+
it('pending task should be cleared if deleteReaction request is successful', async () => {
303366
const reaction = generateReaction();
304367
const targetMessage = channel.state.messages[0];
305368

@@ -327,52 +390,98 @@ export const OptimisticUpdates = () => {
327390
});
328391
});
329392

330-
it('pending task should be executed after connection is recovered', async () => {
331-
const message = channel.state.messages[0];
332-
const reaction = generateReaction();
333-
334-
render(
335-
<Chat client={chatClient} enableOfflineSupport>
336-
<Channel channel={channel} initialValue={message.text}>
337-
<CallbackEffectWithContext
338-
callback={async ({ deleteMessage, sendReaction }) => {
339-
useMockedApis(chatClient, [erroredDeleteApi()]);
340-
try {
341-
await deleteMessage(reaction);
342-
} catch (e) {
343-
// do nothing
344-
}
345-
346-
useMockedApis(chatClient, [erroredPostApi()]);
347-
try {
348-
await sendReaction(reaction.type, message.id);
349-
} catch (e) {
350-
// do nothing
351-
}
352-
}}
353-
context={MessagesContext}
354-
>
355-
<View testID='children' />
356-
</CallbackEffectWithContext>
357-
</Channel>
358-
</Chat>,
359-
);
360-
await waitFor(() => expect(screen.getByTestId('children')).toBeTruthy());
393+
describe('pending task execution', () => {
394+
it('pending task should be executed after connection is recovered', async () => {
395+
const message = channel.state.messages[0];
396+
const reaction = generateReaction();
397+
398+
render(
399+
<Chat client={chatClient} enableOfflineSupport>
400+
<Channel channel={channel} initialValue={message.text}>
401+
<CallbackEffectWithContext
402+
callback={async ({ deleteMessage, sendReaction }) => {
403+
useMockedApis(chatClient, [erroredDeleteApi()]);
404+
try {
405+
await deleteMessage(message);
406+
} catch (e) {
407+
// do nothing
408+
}
409+
410+
useMockedApis(chatClient, [erroredPostApi()]);
411+
try {
412+
await sendReaction(reaction.type, message.id);
413+
} catch (e) {
414+
// do nothing
415+
}
416+
}}
417+
context={MessagesContext}
418+
>
419+
<View testID='children' />
420+
</CallbackEffectWithContext>
421+
</Channel>
422+
</Chat>,
423+
);
424+
await waitFor(() => expect(screen.getByTestId('children')).toBeTruthy());
425+
426+
await waitFor(async () => {
427+
const pendingTasksRows = await BetterSqlite.selectFromTable('pendingTasks');
428+
429+
expect(pendingTasksRows.length).toBe(2);
430+
});
431+
432+
const deleteMessageSpy = jest.spyOn(chatClient, '_deleteMessage').mockImplementation();
433+
const sendReactionSpy = jest.spyOn(channel, '_sendReaction').mockImplementation();
361434

362-
await waitFor(async () => {
363-
const pendingTasksRows = await BetterSqlite.selectFromTable('pendingTasks');
435+
act(() => dispatchConnectionChangedEvent(chatClient, true));
364436

365-
expect(pendingTasksRows.length).toBe(2);
437+
await waitFor(() => {
438+
expect(deleteMessageSpy).toHaveBeenCalled();
439+
expect(sendReactionSpy).toHaveBeenCalled();
440+
});
366441
});
367442

368-
const deleteMessageSpy = jest.spyOn(chatClient, '_deleteMessage').mockImplementation();
369-
const sendReactionSpy = jest.spyOn(channel, '_sendReaction').mockImplementation();
443+
// This is a separate test so CallbackEffectWithContext does not need to be modified in order
444+
// to accept multiple contexts. It can be improved in the future.
445+
it('send message pending task should be executed after connection is recovered', async () => {
446+
const newMessage = generateMessage();
370447

371-
act(() => dispatchConnectionChangedEvent(chatClient, true));
448+
// initialValue is needed as a prop to trick the message input ctx into thinking
449+
// we are sending a message.
450+
render(
451+
<Chat client={chatClient} enableOfflineSupport>
452+
<Channel channel={channel} initialValue={newMessage.text}>
453+
<CallbackEffectWithContext
454+
callback={async ({ sendMessage }) => {
455+
useMockedApis(chatClient, [erroredPostApi()]);
456+
try {
457+
await sendMessage({ customMessageData: newMessage });
458+
} catch (e) {
459+
// do nothing
460+
}
461+
}}
462+
context={MessageInputContext}
463+
>
464+
<View testID='children' />
465+
</CallbackEffectWithContext>
466+
</Channel>
467+
</Chat>,
468+
);
469+
await waitFor(() => expect(screen.getByTestId('children')).toBeTruthy());
470+
471+
await waitFor(async () => {
472+
const pendingTasksRows = await BetterSqlite.selectFromTable('pendingTasks');
473+
console.log('TESTINGROWS: ', pendingTasksRows);
474+
475+
expect(pendingTasksRows.length).toBe(1);
476+
});
372477

373-
await waitFor(() => {
374-
expect(deleteMessageSpy).toHaveBeenCalled();
375-
expect(sendReactionSpy).toHaveBeenCalled();
478+
const sendMessageSpy = jest.spyOn(channel, '_sendMessage').mockImplementation();
479+
480+
act(() => dispatchConnectionChangedEvent(chatClient, true));
481+
482+
await waitFor(() => {
483+
expect(sendMessageSpy).toHaveBeenCalled();
484+
});
376485
});
377486
});
378487
});

0 commit comments

Comments
 (0)