Skip to content

Commit 675a7ed

Browse files
fix(autocomplete): clear panel query in instantsearch.js
1 parent 4f1cabe commit 675a7ed

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed

packages/instantsearch.js/src/widgets/autocomplete/autocomplete.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ function AutocompleteWrapper<TItem extends BaseHit>({
190190
indices,
191191
getSearchPageURL,
192192
onSelect: userOnSelect,
193-
refine,
193+
refine: refineAutocomplete,
194194
cssClasses,
195195
renderState,
196196
instantSearchInstance,
@@ -223,6 +223,7 @@ function AutocompleteWrapper<TItem extends BaseHit>({
223223
) ?? false;
224224

225225
const onRefine = (query: string) => {
226+
refineAutocomplete(query);
226227
instantSearchInstance.setUiState((uiState) => ({
227228
...uiState,
228229
[targetIndex!.getIndexId()]: {
@@ -388,9 +389,11 @@ function AutocompleteWrapper<TItem extends BaseHit>({
388389
...getInputProps(),
389390
// @ts-ignore - This clashes with some ambient React JSX declarations.
390391
onInput: (evt: JSXPreact.TargetedEvent<HTMLInputElement>) =>
391-
refine(evt.currentTarget.value),
392+
refineAutocomplete(evt.currentTarget.value),
393+
}}
394+
onClear={() => {
395+
onRefine('');
392396
}}
393-
onClear={() => onRefine('')}
394397
isSearchStalled={instantSearchInstance.status === 'stalled'}
395398
/>
396399
<AutocompletePanel {...getPanelProps()}>

tests/common/widgets/autocomplete/options.tsx

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,81 @@ export function createOptionsTests(
788788
expect(input).toHaveFocus();
789789
});
790790

791+
test('clearing the query also clears internal autocomplete query', async () => {
792+
const searchClient = createMockedSearchClient(
793+
createMultiSearchResponse(
794+
createSingleSearchResponse({
795+
index: 'indexName',
796+
hits: [
797+
{ objectID: '1', name: 'Item 1' },
798+
{ objectID: '2', name: 'Item 2' },
799+
],
800+
})
801+
)
802+
);
803+
804+
await setup({
805+
instantSearchOptions: {
806+
indexName: 'indexName',
807+
searchClient,
808+
},
809+
widgetParams: {
810+
javascript: {
811+
indices: [
812+
{
813+
indexName: 'indexName',
814+
templates: {
815+
item: (props) => props.item.name,
816+
},
817+
},
818+
],
819+
},
820+
react: {
821+
indices: [
822+
{
823+
indexName: 'indexName',
824+
itemComponent: (props) => props.item.name,
825+
},
826+
],
827+
},
828+
vue: {},
829+
},
830+
});
831+
832+
await act(async () => {
833+
await wait(0);
834+
});
835+
836+
const input = screen.getByRole('combobox', { name: /submit/i });
837+
838+
await act(async () => {
839+
userEvent.click(input);
840+
userEvent.type(input, 'Item 3');
841+
userEvent.keyboard('{Enter}');
842+
await wait(0);
843+
userEvent.keyboard('{Enter}');
844+
await wait(0);
845+
});
846+
847+
expect(input).not.toHaveFocus();
848+
expect(input).toHaveAttribute('aria-expanded', 'false');
849+
expect(screen.getByRole('button', { name: /clear/i })).toBeVisible();
850+
851+
await act(async () => {
852+
userEvent.click(screen.getByRole('button', { name: /clear/i }));
853+
await wait(0);
854+
});
855+
856+
expect(searchClient.search).toHaveBeenLastCalledWith([
857+
{
858+
indexName: 'indexName',
859+
params: expect.objectContaining({
860+
query: '',
861+
}),
862+
},
863+
]);
864+
});
865+
791866
test('refocuses the input after clearing the query', async () => {
792867
const searchClient = createMockedSearchClient(
793868
createMultiSearchResponse(

0 commit comments

Comments
 (0)