diff --git a/README.md b/README.md
index c951f48b..65c99e13 100644
--- a/README.md
+++ b/README.md
@@ -50,7 +50,6 @@ change the state of the checkbox.
-
- [Installation](#installation)
- [API](#api)
- [`click(element)`](#clickelement)
@@ -61,6 +60,8 @@ change the state of the checkbox.
- [`selectOptions(element, values)`](#selectoptionselement-values)
- [`toggleSelectOptions(element, values)`](#toggleselectoptionselement-values)
- [`tab({shift, focusTrap})`](#tabshift-focustrap)
+ - [`async hover(element)`](#async-hoverelement)
+ - [`async unhover(element)`](#async-unhoverelement)
- [Issues](#issues)
- [🐛 Bugs](#-bugs)
- [💡 Feature Requests](#-feature-requests)
@@ -398,6 +399,37 @@ it('should cycle elements in document tab order', () => {
})
```
+### `async hover(element)`
+
+Hovers over `element`.
+
+```jsx
+import React from 'react'
+import {render, screen} from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import Tooltip from '../tooltip'
+
+test('hover', async () => {
+ const messageText = 'Hello'
+ render(
+
+
+ ,
+ )
+
+ await userEvent.hover(screen.getByLabelText(/delete/i))
+ expect(screen.getByText(messageText)).toBeInTheDocument()
+ await userEvent.unhover(screen.getByLabelText(/delete/i))
+ expect(screen.queryByText(messageText)).not.toBeInTheDocument()
+})
+```
+
+### `async unhover(element)`
+
+Unhovers out of `element`.
+
+> See [above](#async-hoverelement) for an example
+
## Issues
_Looking to contribute? Look for the [Good First Issue][good-first-issue]
@@ -482,6 +514,7 @@ Thanks goes to these people ([emoji key][emojis]):
+
This project follows the [all-contributors][all-contributors] specification.
diff --git a/src/__tests__/hover.js b/src/__tests__/hover.js
new file mode 100644
index 00000000..f7a99031
--- /dev/null
+++ b/src/__tests__/hover.js
@@ -0,0 +1,14 @@
+import React from 'react'
+import userEvent from '..'
+import {setup} from './helpers/utils'
+
+test('hover', async () => {
+ const {element, getEventCalls} = setup()
+
+ await userEvent.hover(element)
+ expect(getEventCalls()).toMatchInlineSnapshot(`
+ mouseover: Left (0)
+ mouseenter: Left (0)
+ mousemove: Left (0)
+ `)
+})
diff --git a/src/__tests__/unhover.js b/src/__tests__/unhover.js
new file mode 100644
index 00000000..f8e811f5
--- /dev/null
+++ b/src/__tests__/unhover.js
@@ -0,0 +1,13 @@
+import React from 'react'
+import userEvent from '..'
+import {setup} from './helpers/utils'
+
+test('unhover', async () => {
+ const {element, getEventCalls} = setup()
+
+ await userEvent.unhover(element)
+ expect(getEventCalls()).toMatchInlineSnapshot(`
+ mousemove: Left (0)
+ mouseleave: Left (0)
+ `)
+})
diff --git a/src/index.js b/src/index.js
index d09cb723..4a7af1ff 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,5 +1,6 @@
import {fireEvent} from '@testing-library/dom'
import {type} from './type'
+import {tick} from './tick'
function isMousePressEvent(event) {
return (
@@ -451,6 +452,24 @@ function tab({shift = false, focusTrap = document} = {}) {
}
}
+async function hover(element, init) {
+ await tick()
+ fireEvent.mouseOver(element, getMouseEventOptions('mouseover', init))
+ await tick()
+ fireEvent.mouseEnter(element, getMouseEventOptions('mouseenter', init))
+ await tick()
+ fireEvent.mouseMove(element, getMouseEventOptions('mousemove', init))
+}
+
+async function unhover(element, init) {
+ await tick()
+ fireEvent.mouseMove(element, getMouseEventOptions('mousemove', init))
+ await tick()
+ fireEvent.mouseOut(element, getMouseEventOptions('mouseout', init))
+ await tick()
+ fireEvent.mouseLeave(element, getMouseEventOptions('mouseleave', init))
+}
+
const userEvent = {
click,
dblClick,
@@ -460,6 +479,8 @@ const userEvent = {
type,
upload,
tab,
+ hover,
+ unhover,
}
export default userEvent
diff --git a/typings/index.d.ts b/typings/index.d.ts
index 4d7151cb..b82a39c6 100644
--- a/typings/index.d.ts
+++ b/typings/index.d.ts
@@ -45,6 +45,8 @@ declare const userEvent: {
userOpts?: ITypeOpts,
) => Promise
tab: (userOpts?: ITabUserOptions) => void
+ hover: (element: TargetElement, init?: MouseEventInit) => Promise
+ unhover: (element: TargetElement, init?: MouseEventInit) => Promise
}
export default userEvent