Skip to content

Commit

Permalink
fix: throw error when click/hover on pointer-events: none (#647)
Browse files Browse the repository at this point in the history
When trying to use one of
* `userEvent.click`
* `userEvent.dblClick`
* `userEvent.hover`
* `userEvent.unhover`
on an element with disabled pointer events, an error is thrown.

Co-authored-by: Philipp Fritsche <ph.fritsche@gmail.com>
  • Loading branch information
vicrep and ph-fritsche committed Apr 14, 2021
1 parent 0537940 commit 6b2ce66
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 41 deletions.
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ See the
constructor documentation for more options.

Note that `click` will trigger hover events before clicking. To disable this,
set the `skipHover` option to `true`.
set the `skipHover` option to `true`. Also note that trying to click an element
with `pointer-events` being set to `"none"` (i.e. unclickable) will throw an error.

### `dblClick(element, eventInit, options)`

Expand Down Expand Up @@ -256,11 +257,8 @@ test('types into the input', () => {
render(
<>
<label for="time">Enter a time</label>
<input
type="time"
id="time"
/>
</>
<input type="time" id="time" />
</>,
)
const input = screen.getByLabelText(/enter a time/i)
userEvent.type(input, '13:58')
Expand Down
11 changes: 3 additions & 8 deletions src/__tests__/click.js
Original file line number Diff line number Diff line change
Expand Up @@ -474,12 +474,7 @@ test('right click fires `contextmenu` instead of `click', () => {
expect(getEvents('click')).toHaveLength(0)
})

test('fires no events when clicking element with pointer-events set to none', () => {
const {element, getEventSnapshot} = setup(
`<div style="pointer-events: none"></div>`,
)
userEvent.click(element)
expect(getEventSnapshot()).toMatchInlineSnapshot(
`No events were fired on: div`,
)
test('throws when clicking element with pointer-events set to none', () => {
const {element} = setup(`<div style="pointer-events: none"></div>`)
expect(() => userEvent.click(element)).toThrowError(/unable to click/i)
})
11 changes: 4 additions & 7 deletions src/__tests__/dblclick.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,12 +281,9 @@ test('fires mouse events with custom buttons property', () => {
`)
})

test('fires no events when dblClick element with pointer-events set to none', () => {
const {element, getEventSnapshot} = setup(
`<div style="pointer-events: none"></div>`,
)
userEvent.dblClick(element)
expect(getEventSnapshot()).toMatchInlineSnapshot(
`No events were fired on: div`,
test('throws an error when dblClick element with pointer-events set to none', () => {
const {element} = setup(`<div style="pointer-events: none"></div>`)
expect(() => userEvent.dblClick(element)).toThrowError(
/unable to double-click/i,
)
})
11 changes: 3 additions & 8 deletions src/__tests__/hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,7 @@ test('fires non-bubbling events on parents for unhover', () => {
`)
})

test('fires no events when hovering element with pointer-events set to none', () => {
const {element, getEventSnapshot} = setup(
`<div style="pointer-events: none"></div>`,
)
userEvent.hover(element)
expect(getEventSnapshot()).toMatchInlineSnapshot(
`No events were fired on: div`,
)
test('throws when hovering element with pointer-events set to none', () => {
const {element} = setup(`<div style="pointer-events: none"></div>`)
expect(() => userEvent.hover(element)).toThrowError(/unable to hover/i)
})
11 changes: 3 additions & 8 deletions src/__tests__/unhover.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,7 @@ test('no events fired on labels that contain disabled controls', () => {
)
})

test('fires no events when unhover element with pointer-events set to none', () => {
const {element, getEventSnapshot} = setup(
`<div style="pointer-events: none"></div>`,
)
userEvent.unhover(element)
expect(getEventSnapshot()).toMatchInlineSnapshot(
`No events were fired on: div`,
)
test('throws when unhover element with pointer-events set to none', () => {
const {element} = setup(`<div style="pointer-events: none"></div>`)
expect(() => userEvent.unhover(element)).toThrowError(/unable to unhover/i)
})
12 changes: 10 additions & 2 deletions src/click.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,11 @@ function click(
init?: MouseEventInit,
{skipHover = false, clickCount = 0}: clickOptions = {},
) {
if (!hasPointerEvents(element)) return
if (!hasPointerEvents(element)) {
throw new Error(
'unable to click element as it has or inherits pointer-events set to "none".',
)
}
if (!skipHover) hover(element, init)

if (isElementType(element, 'label')) {
Expand All @@ -143,7 +147,11 @@ function fireClick(element: Element, mouseEventOptions: MouseEventInit) {
}

function dblClick(element: Element, init?: MouseEventInit) {
if (!hasPointerEvents(element)) return
if (!hasPointerEvents(element)) {
throw new Error(
'unable to double-click element as it has or inherits pointer-events set to "none".',
)
}
hover(element, init)
click(element, init, {skipHover: true, clickCount: 0})
click(element, init, {skipHover: true, clickCount: 1})
Expand Down
12 changes: 10 additions & 2 deletions src/hover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ function getParentElements(element: Element) {
}

function hover(element: Element, init?: MouseEventInit) {
if (!hasPointerEvents(element)) return
if (!hasPointerEvents(element)) {
throw new Error(
'unable to hover element as it has or inherits pointer-events set to "none".',
)
}
if (isLabelWithInternallyDisabledControl(element)) return

const parentElements = getParentElements(element).reverse()
Expand All @@ -39,7 +43,11 @@ function hover(element: Element, init?: MouseEventInit) {
}

function unhover(element: Element, init?: MouseEventInit) {
if (!hasPointerEvents(element)) return
if (!hasPointerEvents(element)) {
throw new Error(
'unable to unhover element as it has or inherits pointer-events set to "none".',
)
}
if (isLabelWithInternallyDisabledControl(element)) return

const parentElements = getParentElements(element)
Expand Down

0 comments on commit 6b2ce66

Please sign in to comment.