diff --git a/src/__tests__/select-focus.js b/src/__tests__/select-focus.js
new file mode 100644
index 00000000..48cd05c6
--- /dev/null
+++ b/src/__tests__/select-focus.js
@@ -0,0 +1,65 @@
+import * as React from 'react'
+import {render, fireEvent, screen} from '../'
+
+test.each(['input', 'textarea'])(
+ 'fireEvent.select flushes automatic %s focus and previous blur updates',
+ elementType => {
+ function Example() {
+ const [focused, setFocused] = React.useState(false)
+ const [blurred, setBlurred] = React.useState(false)
+ return (
+ <>
+ setBlurred(true)} />
+ {React.createElement(elementType, {
+ 'aria-label': 'selection',
+ onFocus: () => setFocused(true),
+ 'data-focused': focused,
+ 'data-blurred': blurred,
+ })}
+ >
+ )
+ }
+ render()
+ const previous = screen.getByRole('textbox', {name: 'previous'})
+ previous.focus()
+ const input = screen.getByRole('textbox', {name: 'selection'})
+ fireEvent.select(input)
+ expect(input).toHaveFocus()
+ expect(input).toHaveAttribute('data-focused', 'true')
+ expect(input).toHaveAttribute('data-blurred', 'true')
+ },
+)
+
+test('fireEvent.select preserves native focus, selection and key event ordering', () => {
+ const events = []
+ const handleSelect = jest.fn()
+ render()
+ const input = screen.getByRole('textbox', {name: 'selection'})
+ const focusSpy = jest.fn(() => events.push('focus'))
+ input.addEventListener('select', () => events.push('select'))
+ input.addEventListener('focus', focusSpy)
+ input.addEventListener('keyup', () => events.push('keyup'))
+ fireEvent.select(input)
+ expect(events).toEqual(['select', 'focus', 'keyup'])
+ expect(handleSelect).toHaveBeenCalledTimes(1)
+ fireEvent.select(input)
+ expect(focusSpy).toHaveBeenCalledTimes(1)
+})
+
+test('fireEvent.select flushes updates when the input is already focused', () => {
+ function Example() {
+ const [selected, setSelected] = React.useState(false)
+ return (
+ setSelected(true)}
+ data-selected={selected}
+ />
+ )
+ }
+ render()
+ const input = screen.getByRole('textbox', {name: 'selection'})
+ input.focus()
+ fireEvent.select(input)
+ expect(input).toHaveAttribute('data-selected', 'true')
+})
diff --git a/src/fire-event.js b/src/fire-event.js
index cb790c7f..cc95a2e4 100644
--- a/src/fire-event.js
+++ b/src/fire-event.js
@@ -1,4 +1,4 @@
-import {fireEvent as dtlFireEvent} from '@testing-library/dom'
+import {fireEvent as dtlFireEvent, getConfig} from '@testing-library/dom'
// react-testing-library's version of fireEvent will call
// dom-testing-library's version of fireEvent. The reason
@@ -39,7 +39,9 @@ const select = fireEvent.select
fireEvent.select = (node, init) => {
select(node, init)
// React tracks this event only on focused inputs
- node.focus()
+ getConfig().eventWrapper(() => {
+ node.focus()
+ })
// React creates this event when one of the following native events happens
// - contextMenu