Skip to content

Commit 4c423c1

Browse files
authored
test: add missing tests (#3101)
1 parent 9156f6f commit 4c423c1

7 files changed

Lines changed: 791 additions & 0 deletions

File tree

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import React from 'react';
2+
import { act, fireEvent, render, screen, waitFor, within } from '@testing-library/react';
3+
4+
import { Chat } from '../../Chat';
5+
import { ChannelListItem } from '../ChannelListItem';
6+
import {
7+
generateMember,
8+
generateUser,
9+
initClientWithChannels,
10+
} from '../../../mock-builders';
11+
import { ResizeObserverMock } from '../../../mock-builders/browser';
12+
13+
const ResizeObserverConstructor =
14+
ResizeObserverMock as unknown as typeof window.ResizeObserver;
15+
16+
describe('ChannelListItemActionButtons defaults', () => {
17+
const alice = generateUser({ id: 'alice-id' });
18+
const bob = generateUser({ id: 'bob-id' });
19+
20+
const ownCapabilities = [
21+
'ban-channel-members',
22+
'leave-channel',
23+
'mute-channel',
24+
'read-events',
25+
'send-message',
26+
];
27+
28+
beforeEach(() => {
29+
window.ResizeObserver = ResizeObserverConstructor;
30+
});
31+
32+
afterEach(() => {
33+
vi.clearAllMocks();
34+
delete window.ResizeObserver;
35+
});
36+
37+
const setupTwoMemberGroupChannel = async () => {
38+
const { channels, client } = await initClientWithChannels({
39+
channelsData: [
40+
{
41+
channel: {
42+
id: 'two-member-group',
43+
member_count: 2,
44+
own_capabilities: ownCapabilities,
45+
},
46+
members: [generateMember({ user: alice }), generateMember({ user: bob })],
47+
messages: [],
48+
},
49+
],
50+
customUser: alice,
51+
});
52+
return { channel: channels[0], client };
53+
};
54+
55+
it('mutes channel from quick action with success notification', async () => {
56+
const { channel, client } = await setupTwoMemberGroupChannel();
57+
vi.spyOn(channel, 'mute').mockResolvedValue(undefined);
58+
const addSpy = vi.spyOn(client.notifications, 'add');
59+
60+
act(() => {
61+
render(
62+
<Chat client={client}>
63+
<ChannelListItem channel={channel} />
64+
</Chat>,
65+
);
66+
});
67+
68+
act(() => {
69+
fireEvent.click(screen.getByRole('button', { name: 'Mute' }));
70+
});
71+
await waitFor(() => {
72+
expect(channel.mute).toHaveBeenCalledTimes(1);
73+
expect(addSpy).toHaveBeenCalledWith(
74+
expect.objectContaining({
75+
message: 'Channel muted',
76+
options: expect.objectContaining({ severity: 'success' }),
77+
}),
78+
);
79+
});
80+
});
81+
82+
it('shows mute error notification when mute fails', async () => {
83+
const { channel, client } = await setupTwoMemberGroupChannel();
84+
vi.spyOn(channel, 'mute').mockRejectedValueOnce(new Error('mute failed'));
85+
const addSpy = vi.spyOn(client.notifications, 'add');
86+
87+
act(() => {
88+
render(
89+
<Chat client={client}>
90+
<ChannelListItem channel={channel} />
91+
</Chat>,
92+
);
93+
});
94+
95+
act(() => {
96+
fireEvent.click(screen.getByRole('button', { name: 'Mute' }));
97+
});
98+
99+
await waitFor(() => {
100+
expect(addSpy).toHaveBeenCalledWith(
101+
expect.objectContaining({
102+
message: 'Failed to update channel mute status',
103+
options: expect.objectContaining({ severity: 'error' }),
104+
}),
105+
);
106+
});
107+
});
108+
109+
it('blocks the other member from dropdown', async () => {
110+
const { channel, client } = await setupTwoMemberGroupChannel();
111+
vi.spyOn(channel, 'banUser').mockResolvedValue(undefined);
112+
const addSpy = vi.spyOn(client.notifications, 'add');
113+
114+
act(() => {
115+
render(
116+
<Chat client={client}>
117+
<ChannelListItem channel={channel} />
118+
</Chat>,
119+
);
120+
});
121+
122+
const toggle = document.querySelector(
123+
'.str-chat__channel-list-item__action-buttons .str-chat__button--circular',
124+
) as HTMLButtonElement;
125+
act(() => {
126+
fireEvent.click(toggle);
127+
});
128+
129+
const menu = document.querySelector('.str-chat__context-menu') as HTMLElement;
130+
act(() => {
131+
fireEvent.click(within(menu).getByRole('button', { name: 'Block User' }));
132+
});
133+
134+
await waitFor(() => {
135+
expect(channel.banUser).toHaveBeenCalledWith(bob.id, {});
136+
expect(addSpy).toHaveBeenCalledWith(
137+
expect.objectContaining({
138+
message: 'User blocked',
139+
options: expect.objectContaining({ severity: 'success' }),
140+
}),
141+
);
142+
});
143+
});
144+
145+
it('leaves channel from dropdown', async () => {
146+
const { channel, client } = await setupTwoMemberGroupChannel();
147+
vi.spyOn(channel, 'removeMembers').mockResolvedValue(undefined);
148+
const addSpy = vi.spyOn(client.notifications, 'add');
149+
150+
act(() => {
151+
render(
152+
<Chat client={client}>
153+
<ChannelListItem channel={channel} />
154+
</Chat>,
155+
);
156+
});
157+
158+
const toggle = document.querySelector(
159+
'.str-chat__channel-list-item__action-buttons .str-chat__button--circular',
160+
) as HTMLButtonElement;
161+
act(() => {
162+
fireEvent.click(toggle);
163+
});
164+
165+
const menu = document.querySelector('.str-chat__context-menu') as HTMLElement;
166+
act(() => {
167+
fireEvent.click(within(menu).getByRole('button', { name: 'Leave Channel' }));
168+
});
169+
170+
await waitFor(() => {
171+
expect(channel.removeMembers).toHaveBeenCalledWith([alice.id]);
172+
expect(addSpy).toHaveBeenCalledWith(
173+
expect.objectContaining({
174+
message: 'Left channel',
175+
options: expect.objectContaining({ severity: 'success' }),
176+
}),
177+
);
178+
});
179+
});
180+
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React from 'react';
2+
import { act, renderHook } from '@testing-library/react';
3+
4+
import { useReactionsFetcher } from '../useReactionsFetcher';
5+
import { ChatProvider } from '../../../../context/ChatContext';
6+
import {
7+
generateMessage,
8+
getTestClientWithUser,
9+
mockChatContext,
10+
} from '../../../../mock-builders';
11+
import type { LocalMessage, MessageResponse } from 'stream-chat';
12+
13+
describe('useReactionsFetcher', () => {
14+
it('paginates until next is empty', async () => {
15+
const client = await getTestClientWithUser({ id: 'u1' });
16+
const queryReactions = vi
17+
.spyOn(client, 'queryReactions')
18+
.mockResolvedValueOnce({
19+
duration: '0',
20+
next: 'page-2',
21+
reactions: [{ created_at: new Date(), type: 'like', updated_at: new Date() }],
22+
} as never)
23+
.mockResolvedValueOnce({
24+
duration: '0',
25+
reactions: [{ created_at: new Date(), type: 'love', updated_at: new Date() }],
26+
} as never);
27+
28+
const message = generateMessage() as MessageResponse & LocalMessage;
29+
30+
const wrapper = ({ children }: { children?: React.ReactNode }) => (
31+
<ChatProvider value={mockChatContext({ client })}>{children}</ChatProvider>
32+
);
33+
34+
const { result } = renderHook(() => useReactionsFetcher(message), { wrapper });
35+
36+
let reactions: unknown[];
37+
await act(async () => {
38+
reactions = await result.current();
39+
});
40+
41+
expect(queryReactions).toHaveBeenCalledTimes(2);
42+
expect(queryReactions.mock.calls[0]?.[3]).toEqual(
43+
expect.objectContaining({ limit: 25, next: undefined }),
44+
);
45+
expect(queryReactions.mock.calls[1]?.[3]).toEqual(
46+
expect.objectContaining({ limit: 25, next: 'page-2' }),
47+
);
48+
expect(reactions!).toHaveLength(2);
49+
});
50+
});

0 commit comments

Comments
 (0)