diff --git a/src/__tests__/downshift.lifecycle.js b/src/__tests__/downshift.lifecycle.js index dfd3782e..1b9ccef1 100644 --- a/src/__tests__/downshift.lifecycle.js +++ b/src/__tests__/downshift.lifecycle.js @@ -16,6 +16,8 @@ jest.mock('../utils', () => { afterEach(() => { utils.scrollIntoView.mockReset() + // Ensure any pending timers are cleared if not already handled by tests + jest.clearAllTimers() }) test('do not set state after unmount', () => { @@ -256,6 +258,67 @@ test('controlled highlighted index change scrolls the item into view', () => { ) }) +test('input blur when menu is open does not reset state', () => { + const handleStateChange = jest.fn() + const items = ['apple', 'banana'] + + render( + String(i)}> + {({ + getInputProps, + getToggleButtonProps, + getMenuProps, + getItemProps, + getRootProps, + }) => ( +
+ +
+ )} +
, + ) + + const input = screen.getByTestId('downshift-input') + const toggleButton = screen.getByTestId('toggle-button') + + fireEvent.click(toggleButton) + jest.runAllTimers() + + expect(screen.getByTestId('downshift-menu')).toBeInTheDocument() + expect(handleStateChange).toHaveBeenCalledWith( + expect.objectContaining({ + type: Downshift.stateChangeTypes.clickButton, + isOpen: true, + }), + expect.anything(), + ) + + act(() => { + input.focus() + }) + fireEvent.blur(input) + + jest.runAllTimers() + + expect(handleStateChange).toHaveBeenCalledTimes(1) +}) + function mouseDownAndUp(node) { fireEvent.mouseDown(node) fireEvent.mouseUp(node) diff --git a/src/downshift.js b/src/downshift.js index 49bdda0f..b13f9fca 100644 --- a/src/downshift.js +++ b/src/downshift.js @@ -883,7 +883,13 @@ class Downshift extends Component { this._rootNode && this._rootNode.contains(activeElement) - if (!downshiftButtonIsActive) { + // We check for the containment of the newly activeElement in the _menuNode here due to iOS emitting a blur event right away when the menu is opened (maybe due to not showing the keyboard?) + const activeElementWithinMenu = + this._menuNode && + activeElement && + this._menuNode.contains(activeElement) + + if (!downshiftButtonIsActive && !activeElementWithinMenu) { this.reset({type: stateChangeTypes.blurInput}) } })