Skip to content

Commit 957625f

Browse files
authored
regression: hide system messages toggle in edit room not clearing existing filters (#40295)
Signed-off-by: Abhinav Kumar <abhinav@avitechlab.com>
1 parent 92dbb53 commit 957625f

2 files changed

Lines changed: 177 additions & 4 deletions

File tree

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import type { IRoomWithRetentionPolicy } from '@rocket.chat/core-typings';
2+
import { mockAppRoot } from '@rocket.chat/mock-providers';
3+
import { render, screen, waitFor, within } from '@testing-library/react';
4+
import userEvent from '@testing-library/user-event';
5+
6+
import EditRoomInfo from './EditRoomInfo';
7+
import { createFakeRoom } from '../../../../../../tests/mocks/data';
8+
9+
jest.mock('../../../../../lib/rooms/roomCoordinator', () => ({
10+
roomCoordinator: {
11+
getRoomDirectives: () => ({
12+
allowRoomSettingChange: () => true,
13+
}),
14+
getRoomName: (_t: string, room: { name?: string }) => room.name ?? 'test-room',
15+
},
16+
}));
17+
18+
jest.mock('../../../../../components/avatar/RoomAvatarEditor', () => ({
19+
__esModule: true,
20+
default: () => null,
21+
}));
22+
23+
const noop = () => undefined;
24+
25+
const createRoom = (sysMes?: string[]) =>
26+
createFakeRoom<IRoomWithRetentionPolicy>({
27+
t: 'c',
28+
name: 'test-room',
29+
...(sysMes && { sysMes: sysMes as IRoomWithRetentionPolicy['sysMes'] }),
30+
});
31+
32+
const buildAppRoot = (saveFn: jest.Mock, room: IRoomWithRetentionPolicy) =>
33+
mockAppRoot()
34+
.withJohnDoe()
35+
.withPermission('edit-room')
36+
.withEndpoint('POST', '/v1/rooms.saveRoomSettings', saveFn as never)
37+
.withEndpoint('POST', '/v1/rooms.changeArchivationState', () => ({ success: true }) as never)
38+
.withEndpoint('GET', '/v1/rooms.nameExists', () => ({ exists: false }) as never)
39+
.withSetting('UTF8_Channel_Names_Validation', '[0-9a-zA-Z-_.]+')
40+
.withSetting('UI_Allow_room_names_with_special_chars', true)
41+
.withSetting('RetentionPolicy_Enabled', false)
42+
.withTranslations('en', 'core', {
43+
Save: 'Save',
44+
Hide_System_Messages: 'Hide system messages',
45+
Advanced_settings: 'Advanced settings',
46+
Select_messages_to_hide: 'Select messages to hide',
47+
})
48+
.withRoom(room)
49+
.build();
50+
51+
const openAdvancedSettings = async () => {
52+
await userEvent.click(await screen.findByRole('button', { name: /Advanced settings/i }));
53+
};
54+
55+
const findHideSysMesToggle = () => screen.findByLabelText(/Hide system messages/i);
56+
57+
const clickSave = async () => {
58+
await userEvent.click(screen.getByRole('button', { name: 'Save' }));
59+
};
60+
61+
const removeSystemMessageChip = async (translationKey: string) => {
62+
const chip = screen.getByRole('button', { name: new RegExp(translationKey, 'i') });
63+
await userEvent.click(chip);
64+
};
65+
66+
const selectSystemMessageOption = async (translationKey: string) => {
67+
const trigger = screen.getByRole('button', { name: /Select messages to hide/i });
68+
await userEvent.click(trigger);
69+
70+
const listboxes = await screen.findAllByRole('listbox', { hidden: true });
71+
const listbox = listboxes.find((el) => within(el).queryAllByRole('option', { hidden: true }).length > 0);
72+
73+
if (!listbox) {
74+
throw new Error('Could not find a listbox containing options');
75+
}
76+
77+
const optionEl = within(listbox).getByText(translationKey).closest('li[role="option"]');
78+
79+
if (!optionEl) {
80+
throw new Error(`Could not find option with text "${translationKey}"`);
81+
}
82+
83+
await userEvent.click(optionEl);
84+
};
85+
86+
it('should send systemMessages: [] when hideSysMes is toggled OFF', async () => {
87+
const saveFn = jest.fn((_data: Record<string, unknown>) => ({ rid: 'room-id', success: true }));
88+
const room = createRoom(['au', 'ru']);
89+
90+
render(<EditRoomInfo room={room} onClickClose={noop} onClickBack={noop} />, { wrapper: buildAppRoot(saveFn, room) });
91+
await openAdvancedSettings();
92+
93+
const toggle = await findHideSysMesToggle();
94+
expect(toggle).toBeChecked();
95+
96+
await userEvent.click(toggle);
97+
expect(toggle).not.toBeChecked();
98+
99+
await clickSave();
100+
await waitFor(() => expect(saveFn).toHaveBeenCalled());
101+
102+
expect(saveFn.mock.calls[0][0]).toEqual(expect.objectContaining({ systemMessages: [] }));
103+
});
104+
105+
it('should send selected systemMessages when user selects message types to hide', async () => {
106+
const saveFn = jest.fn((_data: Record<string, unknown>) => ({ rid: 'room-id', success: true }));
107+
const room = createRoom();
108+
109+
render(<EditRoomInfo room={room} onClickClose={noop} onClickBack={noop} />, { wrapper: buildAppRoot(saveFn, room) });
110+
await openAdvancedSettings();
111+
112+
const toggle = await findHideSysMesToggle();
113+
await userEvent.click(toggle);
114+
expect(toggle).toBeChecked();
115+
116+
await selectSystemMessageOption('Message_HideType_au');
117+
118+
await clickSave();
119+
await waitFor(() => expect(saveFn).toHaveBeenCalled());
120+
121+
expect(saveFn.mock.calls[0][0]).toEqual(expect.objectContaining({ systemMessages: expect.arrayContaining(['au']) }));
122+
});
123+
124+
it('should send existing systemMessages when toggle is turned ON without changing selection', async () => {
125+
const saveFn = jest.fn((_data: Record<string, unknown>) => ({ rid: 'room-id', success: true }));
126+
const room = createRoom();
127+
128+
render(<EditRoomInfo room={room} onClickClose={noop} onClickBack={noop} />, { wrapper: buildAppRoot(saveFn, room) });
129+
await openAdvancedSettings();
130+
131+
const toggle = await findHideSysMesToggle();
132+
expect(toggle).not.toBeChecked();
133+
134+
await userEvent.click(toggle);
135+
expect(toggle).toBeChecked();
136+
137+
await clickSave();
138+
await waitFor(() => expect(saveFn).toHaveBeenCalled());
139+
140+
expect(saveFn.mock.calls[0][0]).toEqual(expect.objectContaining({ systemMessages: [] }));
141+
});
142+
143+
it('should send updated systemMessages when only the multi-select is changed', async () => {
144+
const saveFn = jest.fn((_data: Record<string, unknown>) => ({ rid: 'room-id', success: true }));
145+
const room = createRoom(['ru']);
146+
147+
render(<EditRoomInfo room={room} onClickClose={noop} onClickBack={noop} />, { wrapper: buildAppRoot(saveFn, room) });
148+
await openAdvancedSettings();
149+
150+
const toggle = await findHideSysMesToggle();
151+
expect(toggle).toBeChecked();
152+
153+
await removeSystemMessageChip('Message_HideType_ru');
154+
await selectSystemMessageOption('Message_HideType_au');
155+
156+
await clickSave();
157+
await waitFor(() => expect(saveFn).toHaveBeenCalled());
158+
159+
expect(saveFn.mock.calls[0][0]).toEqual(expect.objectContaining({ systemMessages: expect.arrayContaining(['au']) }));
160+
});
161+
162+
it('should NOT send systemMessages when something else changed', async () => {
163+
const saveFn = jest.fn((_data: Record<string, unknown>) => ({ rid: 'room-id', success: true }));
164+
const room = createRoom(['au']);
165+
166+
render(<EditRoomInfo room={room} onClickClose={noop} onClickBack={noop} />, { wrapper: buildAppRoot(saveFn, room) });
167+
168+
await userEvent.type(await screen.findByRole('textbox', { name: 'Topic' }), 'new topic');
169+
170+
await clickSave();
171+
await waitFor(() => expect(saveFn).toHaveBeenCalled());
172+
173+
expect(saveFn.mock.calls[0][0]).not.toHaveProperty('systemMessages');
174+
});

apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,9 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) =>
170170
rid: room._id,
171171
...data,
172172
...((data.joinCode || 'joinCodeRequired' in data) && { joinCode: joinCodeRequired ? data.joinCode : '' }),
173-
...(data.systemMessages &&
174-
!hideSysMes && {
175-
systemMessages: data.systemMessages,
176-
}),
173+
...((dirtyFields.hideSysMes || dirtyFields.systemMessages) && {
174+
systemMessages: hideSysMes ? (data.systemMessages ?? defaultValues.systemMessages) : [],
175+
}),
177176
retentionEnabled,
178177
retentionOverrideGlobal,
179178
...(retentionEnabled &&

0 commit comments

Comments
 (0)