be consistent with pointer/mouse events

This commit is contained in:
Robin Malfait
2020-09-29 13:14:31 +02:00
parent 4b2aacfdf2
commit 57ad598202
6 changed files with 96 additions and 112 deletions
@@ -17,12 +17,11 @@ import {
import {
click,
focus,
hover,
mouseMove,
mouseLeave,
press,
shift,
type,
unHover,
word,
Keys,
} from '../../test-utils/interactions'
@@ -633,7 +632,7 @@ describe('Keyboard interactions', () => {
// Activate the first menu item
const items = getMenuItems()
await hover(items[0])
await mouseMove(items[0])
// Close menu, and invoke the item
await press(Keys.Enter)
@@ -682,7 +681,7 @@ describe('Keyboard interactions', () => {
// Activate the second menu item
const items = getMenuItems()
await hover(items[1])
await mouseMove(items[1])
// Close menu, and invoke the item
await press(Keys.Enter)
@@ -698,7 +697,7 @@ describe('Keyboard interactions', () => {
await click(getMenuButton())
// Active the last menu item
await hover(getMenuItems()[2])
await mouseMove(getMenuItems()[2])
// Close menu, and invoke the item
await press(Keys.Enter)
@@ -2323,15 +2322,15 @@ describe('Mouse interactions', () => {
const items = getMenuItems()
// We should be able to go to the second item
await hover(items[1])
await mouseMove(items[1])
assertMenuLinkedWithMenuItem(getMenu(), items[1])
// We should be able to go to the first item
await hover(items[0])
await mouseMove(items[0])
assertMenuLinkedWithMenuItem(getMenu(), items[0])
// We should be able to go to the last item
await hover(items[2])
await mouseMove(items[2])
assertMenuLinkedWithMenuItem(getMenu(), items[2])
})
)
@@ -2438,7 +2437,7 @@ describe('Mouse interactions', () => {
const items = getMenuItems()
// Try to hover over item 1, which is disabled
await hover(items[1])
await mouseMove(items[1])
// We should not have an active item now
assertNoActiveMenuItem(getMenu())
@@ -2465,24 +2464,24 @@ describe('Mouse interactions', () => {
const items = getMenuItems()
// We should be able to go to the second item
await hover(items[1])
await mouseMove(items[1])
assertMenuLinkedWithMenuItem(getMenu(), items[1])
await unHover(items[1])
await mouseLeave(items[1])
assertNoActiveMenuItem(getMenu())
// We should be able to go to the first item
await hover(items[0])
await mouseMove(items[0])
assertMenuLinkedWithMenuItem(getMenu(), items[0])
await unHover(items[0])
await mouseLeave(items[0])
assertNoActiveMenuItem(getMenu())
// We should be able to go to the last item
await hover(items[2])
await mouseMove(items[2])
assertMenuLinkedWithMenuItem(getMenu(), items[2])
await unHover(items[2])
await mouseLeave(items[2])
assertNoActiveMenuItem(getMenu())
})
)
@@ -2509,10 +2508,10 @@ describe('Mouse interactions', () => {
const items = getMenuItems()
// Try to hover over item 1, which is disabled
await hover(items[1])
await mouseMove(items[1])
assertNoActiveMenuItem(getMenu())
await unHover(items[1])
await mouseLeave(items[1])
assertNoActiveMenuItem(getMenu())
})
)
@@ -535,27 +535,6 @@ function Item<TTag extends React.ElementType = typeof DEFAULT_ITEM_TAG>(
return () => dispatch({ type: ActionTypes.UnregisterItem, id })
}, [bag, id])
const handlePointerEnter = React.useCallback(() => {
if (disabled) return
dispatch({ type: ActionTypes.GoToItem, focus: Focus.SpecificItem, id })
}, [disabled, id, dispatch])
const handleFocus = React.useCallback(() => {
if (disabled) return dispatch({ type: ActionTypes.GoToItem, focus: Focus.Nothing })
dispatch({ type: ActionTypes.GoToItem, focus: Focus.SpecificItem, id })
}, [disabled, id, dispatch])
const handlePointerLeave = React.useCallback(() => {
if (disabled) return
dispatch({ type: ActionTypes.GoToItem, focus: Focus.Nothing })
}, [disabled, dispatch])
const handleMouseMove = React.useCallback(() => {
if (disabled) return
if (active) return
dispatch({ type: ActionTypes.GoToItem, focus: Focus.SpecificItem, id })
}, [disabled, active, id, dispatch])
const handleClick = React.useCallback(
(event: { preventDefault: Function }) => {
if (disabled) return event.preventDefault()
@@ -566,6 +545,22 @@ function Item<TTag extends React.ElementType = typeof DEFAULT_ITEM_TAG>(
[d, dispatch, state.buttonRef, disabled, onClick]
)
const handleFocus = React.useCallback(() => {
if (disabled) return dispatch({ type: ActionTypes.GoToItem, focus: Focus.Nothing })
dispatch({ type: ActionTypes.GoToItem, focus: Focus.SpecificItem, id })
}, [disabled, id, dispatch])
const handlePointerMove = React.useCallback(() => {
if (disabled) return
if (active) return
dispatch({ type: ActionTypes.GoToItem, focus: Focus.SpecificItem, id })
}, [disabled, active, id, dispatch])
const handlePointerLeave = React.useCallback(() => {
if (disabled) return
dispatch({ type: ActionTypes.GoToItem, focus: Focus.Nothing })
}, [disabled, dispatch])
const propsBag = React.useMemo(() => ({ active, disabled }), [active, disabled])
const propsWeControl = {
id,
@@ -575,8 +570,7 @@ function Item<TTag extends React.ElementType = typeof DEFAULT_ITEM_TAG>(
'aria-disabled': disabled === true ? true : undefined,
onClick: handleClick,
onFocus: handleFocus,
onMouseMove: handleMouseMove,
onPointerEnter: handlePointerEnter,
onPointerMove: handlePointerMove,
onPointerLeave: handlePointerLeave,
}
@@ -89,13 +89,28 @@ export async function focus(element: Document | Element | Window | Node | null)
throw err
}
}
export async function mouseMove(element: Document | Element | Window | Node | null) {
export async function mouseEnter(element: Document | Element | Window | null) {
try {
if (element === null) return expect(element).not.toBe(null)
const d = disposables()
fireEvent.pointerOver(element)
fireEvent.pointerEnter(element)
fireEvent.mouseOver(element)
await new Promise(d.nextFrame)
} catch (err) {
if (Error.captureStackTrace) Error.captureStackTrace(err, mouseEnter)
throw err
}
}
export async function mouseMove(element: Document | Element | Window | null) {
try {
if (element === null) return expect(element).not.toBe(null)
const d = disposables()
fireEvent.pointerMove(element)
fireEvent.mouseMove(element)
await new Promise(d.nextFrame)
@@ -105,27 +120,9 @@ export async function mouseMove(element: Document | Element | Window | Node | nu
}
}
export async function hover(element: Document | Element | Window | Node | null) {
export async function mouseLeave(element: Document | Element | Window | null) {
try {
if (element === null) return expect(element).not.toBe(null)
const d = disposables()
fireEvent.pointerOver(element)
fireEvent.pointerEnter(element)
fireEvent.mouseOver(element)
await new Promise(d.nextFrame)
} catch (err) {
if (Error.captureStackTrace) Error.captureStackTrace(err, hover)
throw err
}
}
export async function unHover(element: Document | Element | Window | Node | null) {
try {
if (element === null) return expect(element).not.toBe(null)
const d = disposables()
fireEvent.pointerOut(element)
@@ -135,7 +132,7 @@ export async function unHover(element: Document | Element | Window | Node | null
await new Promise(d.nextFrame)
} catch (err) {
if (Error.captureStackTrace) Error.captureStackTrace(err, unHover)
if (Error.captureStackTrace) Error.captureStackTrace(err, mouseLeave)
throw err
}
}
@@ -16,12 +16,11 @@ import {
import {
click,
focus,
hover,
mouseMove,
mouseLeave,
press,
shift,
type,
unHover,
Keys,
word,
} from '../../test-utils/interactions'
@@ -812,7 +811,7 @@ describe('Keyboard interactions', () => {
// Activate the first menu item
const items = getMenuItems()
await hover(items[0])
await mouseMove(items[0])
// Close menu, and invoke the item
await press(Keys.Enter)
@@ -861,7 +860,7 @@ describe('Keyboard interactions', () => {
// Activate the second menu item
const items = getMenuItems()
await hover(items[1])
await mouseMove(items[1])
// Close menu, and invoke the item
await press(Keys.Enter)
@@ -877,7 +876,7 @@ describe('Keyboard interactions', () => {
await click(getMenuButton())
// Active the last menu item
await hover(getMenuItems()[2])
await mouseMove(getMenuItems()[2])
// Close menu, and invoke the item
await press(Keys.Enter)
@@ -2273,15 +2272,15 @@ describe('Mouse interactions', () => {
const items = getMenuItems()
// We should be able to go to the second item
await hover(items[1])
await mouseMove(items[1])
assertMenuLinkedWithMenuItem(getMenu(), items[1])
// We should be able to go to the first item
await hover(items[0])
await mouseMove(items[0])
assertMenuLinkedWithMenuItem(getMenu(), items[0])
// We should be able to go to the last item
await hover(items[2])
await mouseMove(items[2])
assertMenuLinkedWithMenuItem(getMenu(), items[2])
})
@@ -2372,7 +2371,7 @@ describe('Mouse interactions', () => {
const items = getMenuItems()
// Try to hover over item 1, which is disabled
await hover(items[1])
await mouseMove(items[1])
// We should not have an active item now
assertNoActiveMenuItem(getMenu())
@@ -2396,24 +2395,24 @@ describe('Mouse interactions', () => {
const items = getMenuItems()
// We should be able to go to the second item
await hover(items[1])
await mouseMove(items[1])
assertMenuLinkedWithMenuItem(getMenu(), items[1])
await unHover(items[1])
await mouseLeave(items[1])
assertNoActiveMenuItem(getMenu())
// We should be able to go to the first item
await hover(items[0])
await mouseMove(items[0])
assertMenuLinkedWithMenuItem(getMenu(), items[0])
await unHover(items[0])
await mouseLeave(items[0])
assertNoActiveMenuItem(getMenu())
// We should be able to go to the last item
await hover(items[2])
await mouseMove(items[2])
assertMenuLinkedWithMenuItem(getMenu(), items[2])
await unHover(items[2])
await mouseLeave(items[2])
assertNoActiveMenuItem(getMenu())
})
@@ -2435,10 +2434,10 @@ describe('Mouse interactions', () => {
const items = getMenuItems()
// Try to hover over item 1, which is disabled
await hover(items[1])
await mouseMove(items[1])
assertNoActiveMenuItem(getMenu())
await unHover(items[1])
await mouseLeave(items[1])
assertNoActiveMenuItem(getMenu())
})
@@ -419,9 +419,10 @@ export const MenuItem = defineComponent({
onMounted(() => api.registerItem(id, dataRef))
onUnmounted(() => api.unregisterItem(id))
function handlePointerEnter() {
if (disabled) return
api.goToItem(Focus.SpecificItem, id)
function handleClick(event: MouseEvent) {
if (disabled) return event.preventDefault()
api.closeMenu()
nextTick(() => api.buttonRef.value?.focus())
}
function handleFocus() {
@@ -429,21 +430,15 @@ export const MenuItem = defineComponent({
api.goToItem(Focus.SpecificItem, id)
}
function handlePointerLeave() {
if (disabled) return
api.goToItem(Focus.Nothing)
}
function handleMouseMove() {
function handlePointerMove() {
if (disabled) return
if (active.value) return
api.goToItem(Focus.SpecificItem, id)
}
function handleClick(event: MouseEvent) {
if (disabled) return event.preventDefault()
api.closeMenu()
nextTick(() => api.buttonRef.value?.focus())
function handlePointerLeave() {
if (disabled) return
api.goToItem(Focus.Nothing)
}
return () => {
@@ -456,8 +451,7 @@ export const MenuItem = defineComponent({
'aria-disabled': disabled === true ? true : undefined,
onClick: handleClick,
onFocus: handleFocus,
onMouseMove: handleMouseMove,
onPointerEnter: handlePointerEnter,
onPointerMove: handlePointerMove,
onPointerLeave: handlePointerLeave,
}
@@ -85,20 +85,7 @@ export async function focus(element: Document | Element | Window | null) {
}
}
export async function mouseMove(element: Document | Element | Window | null) {
try {
if (element === null) return expect(element).not.toBe(null)
fireEvent.mouseMove(element)
await new Promise<void>(nextTick)
} catch (err) {
if (Error.captureStackTrace) Error.captureStackTrace(err, mouseMove)
throw err
}
}
export async function hover(element: Document | Element | Window | null) {
export async function mouseEnter(element: Document | Element | Window | null) {
try {
if (element === null) return expect(element).not.toBe(null)
@@ -108,12 +95,26 @@ export async function hover(element: Document | Element | Window | null) {
await new Promise<void>(nextTick)
} catch (err) {
if (Error.captureStackTrace) Error.captureStackTrace(err, hover)
if (Error.captureStackTrace) Error.captureStackTrace(err, mouseEnter)
throw err
}
}
export async function unHover(element: Document | Element | Window | null) {
export async function mouseMove(element: Document | Element | Window | null) {
try {
if (element === null) return expect(element).not.toBe(null)
fireEvent.pointerMove(element)
fireEvent.mouseMove(element)
await new Promise<void>(nextTick)
} catch (err) {
if (Error.captureStackTrace) Error.captureStackTrace(err, mouseMove)
throw err
}
}
export async function mouseLeave(element: Document | Element | Window | null) {
try {
if (element === null) return expect(element).not.toBe(null)
@@ -124,7 +125,7 @@ export async function unHover(element: Document | Element | Window | null) {
await new Promise<void>(nextTick)
} catch (err) {
if (Error.captureStackTrace) Error.captureStackTrace(err, unHover)
if (Error.captureStackTrace) Error.captureStackTrace(err, mouseLeave)
throw err
}
}