Skip to content

Commit

Permalink
fix(behaviour): clear completion on "reset" (#1215)
Browse files Browse the repository at this point in the history
* chore(test): add real attributes to playground input

* test(debouncing): prevent unrealistic behaviour

* fix(behaviour): clear completion on "reset"

* chore: use right word in comment
  • Loading branch information
Haroenv authored Oct 27, 2023
1 parent ce8c78e commit caa3ef8
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 6 deletions.
31 changes: 31 additions & 0 deletions packages/autocomplete-core/src/__tests__/completion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,35 @@ describe('completion', () => {
})
);
});

test('clears completion on "reset"', () => {
const { inputElement, resetElement } = createPlayground(
createAutocomplete,
{
openOnFocus: true,
initialState: {
collections: [
createCollection({
source: {
getItemInputValue({ item }) {
return item.label;
},
},
items: [{ label: '1' }, { label: '2' }],
}),
],
},
}
);
inputElement.focus();

userEvent.type(inputElement, 'Some text to make sure reset shows');
expect(inputElement).toHaveValue('Some text to make sure reset shows');

userEvent.type(inputElement, '{arrowdown}');
expect(inputElement).toHaveValue('1');

resetElement.click();
expect(inputElement).toHaveValue('');
});
});
25 changes: 23 additions & 2 deletions packages/autocomplete-core/src/__tests__/debouncing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,31 @@ describe('debouncing', () => {
);
});

test('triggers subsequent queries after reopening the panel', async () => {
test('triggers subsequent queries after closing and reopening the panel', async () => {
const onStateChange = jest.fn();
const getItems = jest.fn(({ query }) => [{ label: query }]);
const { inputElement } = createPlayground(createAutocomplete, {
onStateChange,
openOnFocus: true,
getSources: () => debounced([createSource({ getItems })]),
});

userEvent.type(inputElement, 'abc{esc}');
inputElement.focus();
userEvent.type(inputElement, 'ab');
await defer(noop, delay);

expect(onStateChange).toHaveBeenLastCalledWith(
expect.objectContaining({
state: expect.objectContaining({
status: 'idle',
isOpen: true,
}),
})
);
expect(getItems).toHaveBeenCalledTimes(1);
expect(inputElement).toHaveValue('ab');

userEvent.type(inputElement, 'c{esc}');

expect(onStateChange).toHaveBeenLastCalledWith(
expect.objectContaining({
Expand All @@ -60,8 +76,11 @@ describe('debouncing', () => {
}),
})
);
expect(getItems).toHaveBeenCalledTimes(1);
expect(inputElement).toHaveValue('abc');

userEvent.type(inputElement, 'def');
expect(inputElement).toHaveValue('abcdef');

await defer(noop, delay);

Expand All @@ -78,6 +97,8 @@ describe('debouncing', () => {
}),
})
);
expect(getItems).toHaveBeenCalledTimes(2);
expect(inputElement).toHaveValue('abcdef');
});
});

Expand Down
9 changes: 7 additions & 2 deletions packages/autocomplete-core/src/__tests__/metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe('metadata', () => {
).content
)
).toEqual({
options: { 'autocomplete-core': ['environment'] },
options: { 'autocomplete-core': ['environment', 'onStateChange'] },
plugins: [],
ua: [{ segment: 'autocomplete-core', version }],
});
Expand Down Expand Up @@ -111,7 +111,12 @@ describe('metadata', () => {
).content
).options
).toEqual({
'autocomplete-core': ['openOnFocus', 'placeholder', 'environment'],
'autocomplete-core': [
'openOnFocus',
'placeholder',
'environment',
'onStateChange',
],
});
});

Expand Down
2 changes: 1 addition & 1 deletion packages/autocomplete-core/src/onKeyDown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export function onKeyDown<TItem extends BaseItem>({
} else if (event.key === 'Tab') {
store.dispatch('blur', null);

// Hitting the `Escape` key signals the end of a user interaction with the
// Hitting the `Tab` key signals the end of a user interaction with the
// autocomplete. At this point, we should ignore any requests that are still
// pending and could reopen the panel once they resolve, because that would
// result in an unsolicited UI behavior.
Expand Down
1 change: 1 addition & 0 deletions packages/autocomplete-core/src/stateReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export const stateReducer: Reducer = (state, action) => {
? action.props.defaultActiveItemId
: null,
status: 'idle',
completion: null,
query: '',
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ describe('createAlgoliaInsightsPlugin', () => {
<body>
<form>
<input />
<button
type="reset"
/>
</form>
</body>
`);
Expand All @@ -264,6 +267,9 @@ describe('createAlgoliaInsightsPlugin', () => {
<body>
<form>
<input />
<button
type="reset"
/>
</form>
</body>
`);
Expand All @@ -286,6 +292,9 @@ describe('createAlgoliaInsightsPlugin', () => {
/>
<form>
<input />
<button
type="reset"
/>
</form>
</body>
`);
Expand Down
31 changes: 30 additions & 1 deletion test/utils/createPlayground.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AutocompleteApi,
AutocompleteOptions,
createAutocomplete as createAutocompleteCore,
} from '@algolia/autocomplete-core';
Expand All @@ -7,9 +8,18 @@ export function createPlayground<TItem extends Record<string, unknown>>(
createAutocomplete: typeof createAutocompleteCore,
props: AutocompleteOptions<TItem>
) {
const autocomplete = createAutocomplete<TItem>(props);
const inputElement = document.createElement('input');
const resetElement = document.createElement('button');
resetElement.type = 'reset';
const formElement = document.createElement('form');
let autocomplete: AutocompleteApi<TItem> | null = null;
autocomplete = createAutocomplete<TItem>({
...props,
onStateChange(p) {
props.onStateChange?.(p);
simplifiedRender();
},
});
const inputProps = autocomplete.getInputProps({ inputElement });
const formProps = autocomplete.getFormProps({ inputElement });
inputElement.addEventListener('blur', inputProps.onBlur);
Expand All @@ -20,11 +30,30 @@ export function createPlayground<TItem extends Record<string, unknown>>(
formElement.addEventListener('reset', formProps.onReset);
formElement.addEventListener('submit', formProps.onSubmit);
formElement.appendChild(inputElement);
formElement.appendChild(resetElement);
document.body.appendChild(formElement);

function simplifiedRender() {
// early exit if the autocomplete instance is not ready yet (eg. through plugins)
if (!autocomplete) {
return;
}

Object.entries(autocomplete.getInputProps({ inputElement })).forEach(
([key, value]) => {
if (key.startsWith('on')) {
return;
}

inputElement[key as any] = value;
}
);
}

return {
...autocomplete,
inputElement,
resetElement,
formElement,
inputProps,
formProps,
Expand Down

0 comments on commit caa3ef8

Please sign in to comment.