Skip to content

Commit d563369

Browse files
authored
feat: allow to configure the search query debounce interval (#2107)
The search will now debounce instead of throttle the search queries.
1 parent 9aa4aea commit d563369

File tree

6 files changed

+523
-73
lines changed

6 files changed

+523
-73
lines changed

docusaurus/docs/React/components/utility-components/channel-search.mdx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,14 @@ Custom search function to override default. The first argument should expect an
338338
| --------------------------------------------------------------------------------------------------- |
339339
| (`params: ChannelSearchFunctionParams, event: React.BaseSyntheticEvent` ) => Promise<void\> \| void |
340340

341+
### searchDebounceIntervalMs
342+
343+
The number of milliseconds to debounce the search query.
344+
345+
| Type | Default |
346+
|----------|---------|
347+
| `number` | 300 |
348+
341349
### SearchInput
342350

343351
Custom UI component to display the search text input.

docusaurus/docs/React/guides/customization/channel-search.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ const additionalProps = {
311311
312312
### The searchFunction Prop:
313313
314-
By default the `ChannelSearch` component searches just for users. Use the `searchForChannels` prop to also search for channels.
314+
By default, the `ChannelSearch` component searches just for users. Use the `searchForChannels` prop to also search for channels.
315315
316316
To override the search method, completely use the `searchFunction` prop. This prop is useful, say, when you want to search just for channels
317317
and for only channels that the current logged in user is a member of. See the example below for this.

src/components/ChannelList/__tests__/ChannelList.test.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ const channelsQueryStateMock = {
4848
};
4949

5050
/**
51-
* We are gonna use following custom UI components for preview and list.
51+
* We use the following custom UI components for preview and list.
5252
* If we use ChannelPreviewMessenger or ChannelPreviewLastMessage here, then changes
5353
* to those components might end up breaking tests for ChannelList, which will be quite painful
5454
* to debug then.
@@ -438,6 +438,7 @@ describe('ChannelList', () => {
438438
});
439439

440440
describe('channel search', () => {
441+
const defaultSearchDebounceInterval = 300;
441442
const inputText = 'xxxxxxxxxx';
442443
const user1 = generateUser();
443444
const user2 = generateUser();
@@ -551,20 +552,24 @@ describe('ChannelList', () => {
551552
])(
552553
'theme v%s %s unmount search results on result click, if configured',
553554
async (themeVersion, _, clearSearchOnClickOutside) => {
555+
jest.useFakeTimers('modern');
556+
jest.spyOn(client, 'queryUsers').mockResolvedValue({ users: [generateUser()] });
554557
const { container } = await renderComponents(
555558
{ channel, client, themeVersion },
556559
{ additionalChannelSearchProps: { clearSearchOnClickOutside } },
557560
);
558-
const input = screen.queryByTestId('search-input');
561+
const input = screen.getByTestId('search-input');
559562
await act(() => {
560563
fireEvent.change(input, {
561564
target: {
562565
value: inputText,
563566
},
564567
});
565568
});
566-
567-
const searchResults = screen.queryAllByRole('option');
569+
await act(() => {
570+
jest.advanceTimersByTime(defaultSearchDebounceInterval + 1);
571+
});
572+
const searchResults = screen.queryAllByTestId('channel-search-result-user');
568573
useMockedApis(client, [getOrCreateChannelApi(generateChannel())]);
569574
await act(() => {
570575
fireEvent.click(searchResults[0]);
@@ -577,6 +582,7 @@ describe('ChannelList', () => {
577582
expect(container.querySelector(SEARCH_RESULT_LIST_SELECTOR)).toBeInTheDocument();
578583
}
579584
});
585+
jest.useRealTimers();
580586
},
581587
);
582588

@@ -645,6 +651,8 @@ describe('ChannelList', () => {
645651
it.each([['1'], ['2']])(
646652
'theme v%s should add the selected result to the top of the channel list',
647653
async (themeVersion) => {
654+
jest.useFakeTimers('modern');
655+
jest.spyOn(client, 'queryUsers').mockResolvedValue({ users: [generateUser()] });
648656
const getComputedStyleMock = jest.spyOn(window, 'getComputedStyle');
649657
getComputedStyleMock.mockReturnValue({
650658
getPropertyValue: jest.fn().mockReturnValue(themeVersion),
@@ -679,8 +687,11 @@ describe('ChannelList', () => {
679687
},
680688
});
681689
});
690+
await act(() => {
691+
jest.advanceTimersByTime(defaultSearchDebounceInterval + 1);
692+
});
682693

683-
const targetChannelPreview = screen.queryByText(channelNotInTheList.channel.name);
694+
const targetChannelPreview = screen.getByText(channelNotInTheList.channel.name);
684695
expect(targetChannelPreview).toBeInTheDocument();
685696
await act(() => {
686697
fireEvent.click(targetChannelPreview);
@@ -693,6 +704,7 @@ describe('ChannelList', () => {
693704
}
694705
});
695706
getComputedStyleMock.mockClear();
707+
jest.useRealTimers();
696708
},
697709
);
698710
});

0 commit comments

Comments
 (0)