diff --git a/packages/autocomplete/src/lib/AsyncAutocomplete.test.tsx b/packages/autocomplete/src/lib/AsyncAutocomplete.test.tsx
index 5d95559f1..31464a094 100644
--- a/packages/autocomplete/src/lib/AsyncAutocomplete.test.tsx
+++ b/packages/autocomplete/src/lib/AsyncAutocomplete.test.tsx
@@ -5,6 +5,7 @@ import { server } from '@availity/mock/src/lib/server';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { AsyncAutocomplete } from './AsyncAutocomplete';
+import { mock } from 'node:test';
const api = new AvApi({ name: 'example' } as ApiConfig);
@@ -182,63 +183,85 @@ describe('AsyncAutocomplete', () => {
});
});
- // test('should call loadOptions when scroll to the bottom', async () => {
- // const client = new QueryClient();
-
- // render(
- //
- //
- //
- // );
-
- // const input = screen.getByRole('combobox');
- // fireEvent.click(input);
- // fireEvent.keyDown(input, { key: 'ArrowDown' });
-
- // await waitFor(() => {
- // expect(screen.getByText('Option 0')).toBeDefined();
- // expect(() => screen.getByText('Option 10')).toThrow();
- // });
-
- // await act(async () => {
- // const options = await screen.findByRole('listbox');
- // fireEvent.scroll(options, { target: { scrollTop: options.scrollHeight } });
- // });
-
- // await waitFor(() => {
- // expect(screen.getByText('Option 10')).toBeDefined();
- // expect(() => screen.getByText('Option 20')).toThrow();
- // });
- // });
-
- // test('should call loadOptions when mouse enters the listbox if not enough options for scroll', async () => {
- // const client = new QueryClient();
-
- // render(
- //
- //
- //
- // );
-
- // const input = screen.getByRole('combobox');
- // fireEvent.click(input);
- // fireEvent.keyDown(input, { key: 'ArrowDown' });
-
- // await waitFor(() => {
- // expect(screen.getByText('Option 0')).toBeDefined();
- // expect(() => screen.getByText('Option 5')).toThrow();
- // });
-
- // await act(async () => {
- // const options = await screen.findByRole('listbox');
- // fireEvent.mouseEnter(options);
- // });
-
- // await waitFor(() => {
- // expect(screen.getByText('Option 5')).toBeDefined();
- // expect(() => screen.getByText('Option 10')).toThrow();
- // });
- // });
+ test('should call loadOptions when scroll to the bottom', async () => {
+ const mockLoadOptions = jest.fn(loadOptions);
+ const client = new QueryClient();
+
+ render(
+
+
+
+ );
+
+ const input = screen.getByRole('combobox');
+ fireEvent.click(input);
+ fireEvent.keyDown(input, { key: 'ArrowUp' });
+
+ const listbox = await screen.findByRole('listbox');
+ Object.defineProperty(listbox, 'scrollHeight', { value: 500, writable: true });
+ Object.defineProperty(listbox, 'clientHeight', { value: 100, writable: true });
+ Object.defineProperty(listbox, 'scrollTop', { value: 0, writable: true });
+
+ // wait for no-scroll loading fallback to finish before testing scroll behavior
+ await waitFor(() => expect(() => screen.getByAltText('Loading')).toThrow());
+ const initialCallCount = mockLoadOptions.mock.calls.length;
+
+ fireEvent.scroll(listbox, { target: { scrollTop: 200 } });
+
+ // should not loadOptions since not scrolled to bottom
+ await waitFor(() => {
+ expect(mockLoadOptions).toHaveBeenCalledTimes(initialCallCount);
+ });
+
+ fireEvent.scroll(listbox, { target: { scrollTop: 400 } });
+
+ await waitFor(() => {
+ expect(mockLoadOptions).toHaveBeenCalledTimes(initialCallCount + 1);
+ });
+ });
+
+ test('should call loadOptions if more options available and not enough options for scroll', async () => {
+ const mockLoadOptions = jest.fn(loadOptions);
+ const client = new QueryClient();
+
+ render(
+
+
+
+ );
+
+ const input = screen.getByRole('combobox');
+ fireEvent.click(input);
+ fireEvent.keyDown(input, { key: 'ArrowDown' });
+
+ await waitFor(() => {
+ expect(mockLoadOptions).toHaveBeenCalled();
+ });
+
+ // should load more options until enough options for scroll or no more options to load
+ const listbox = await screen.findByRole('listbox');
+ Object.defineProperty(listbox, 'scrollHeight', { value: 500, writable: true });
+ Object.defineProperty(listbox, 'clientHeight', { value: 100, writable: true });
+ Object.defineProperty(listbox, 'scrollTop', { value: 0, writable: true });
+
+ await waitFor(() => expect(() => screen.getByAltText('Loading')).toThrow());
+
+ // count number of calls before satisfying scrollable condition
+ const maxCallCount = mockLoadOptions.mock.calls.length;
+
+ fireEvent.pointerEnter(listbox);
+
+ // should not fallback to load more options as scrollable condition is satisfied
+ await waitFor(() => {
+ expect(mockLoadOptions).toHaveBeenCalledTimes(maxCallCount);
+ });
+ });
+
test('should search with input value', async () => {
const mockLoadOptions = jest.fn(async () => ({ options: [{ label: 'Option 1' }], hasMore: false, offset: 50 }));
diff --git a/packages/autocomplete/src/lib/AsyncAutocomplete.tsx b/packages/autocomplete/src/lib/AsyncAutocomplete.tsx
index 328f69a33..a861ef9bc 100644
--- a/packages/autocomplete/src/lib/AsyncAutocomplete.tsx
+++ b/packages/autocomplete/src/lib/AsyncAutocomplete.tsx
@@ -112,7 +112,7 @@ export const AsyncAutocomplete = <
const difference = listboxNode.scrollHeight - (listboxNode.scrollTop + listboxNode.clientHeight);
// Only fetch if we are near the bottom, not already fetching, and there are more results
- if (difference <= 5 && !isLoading && !isFetching && hasNextPage) {
+ if (difference <= 10 && !isLoading && !isFetching && hasNextPage) {
fetchNextPage();
}
}
@@ -142,7 +142,7 @@ export const AsyncAutocomplete = <
...ListboxProps,
ref: setListboxRef,
onScroll: handleAddingOptions,
- onPointerEnter: handleAddingOptions,
+ onPointerEnter: handleAddingOptions
}}
/>
);