react-beautiful-dnd-test-utils
react-beautiful-dnd-test-utils copied to clipboard
Does not work with UserEvent v14
UserEvent v14 introduced a couple of breaking changes that have broken compatibility with this library.
- All userEvents now return promises that must be awaited/resolved
- The "{space}" key code has been removed in favor of "[Space]" or " "
The lint rules for testing-library are also out of date, but I think that's on another one of your projects.
If anyone's looking for a solution on how to drag and drop with the latest react, jest and react testing library, here are my utils that do work:
import { act, fireEvent, screen } from '@testing-library/react'
enum Keys {
SPACE = 32,
ARROW_LEFT = 37,
ARROW_UP = 38,
ARROW_RIGHT = 39,
ARROW_DOWN = 40,
}
export enum DragDirection {
LEFT = Keys.ARROW_LEFT,
UP = Keys.ARROW_UP,
RIGHT = Keys.ARROW_RIGHT,
DOWN = Keys.ARROW_DOWN,
}
// taken from https://github.com/hello-pangea/dnd/blob/main/test/unit/integration/util/controls.ts#L20
const createTransitionEndEvent = (): Event => {
const event = new Event('transitionend', {
bubbles: true,
cancelable: true,
}) as TransitionEvent
// cheating and adding property to event as
// TransitionEvent constructor does not exist.
// This is needed because of the following check
// https://github.com/atlassian/react-beautiful-dnd/blob/master/src/view/draggable/draggable.jsx#L130
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(event as any).propertyName = 'transform'
return event
}
export const pickUp = async (element: HTMLElement) => {
fireEvent.keyDown(element, {
keyCode: Keys.SPACE,
})
await screen.findByText(/You have lifted an item/i)
await act(() => {
jest.runOnlyPendingTimers()
})
}
export const move = async (element: HTMLElement, direction: DragDirection) => {
fireEvent.keyDown(element, {
keyCode: direction,
})
await screen.findByText(/(You have moved the item | has been combined with)/i)
}
export const drop = async (element: HTMLElement) => {
fireEvent.keyDown(element, {
keyCode: Keys.SPACE,
})
fireEvent(element, createTransitionEndEvent())
await screen.findByText(/You have dropped the item/i)
}
Notes:
- I have both
provided.draggableProps
andprovided.dragHandleProps
spread on the sameelement
(the same one which I am passing to the util functions).TransitionEnd
event must be fired on the element which hasprovided.draggableProps
spreaded on. - This requires
jest.useFakeTimers({ advanceTimers: true })
(in my caseadvanceTimers
is required otherwise it hangs, i haven't checked whether it's because of the drag and drop library or something in my code). This is not strictly necessary, theact
block can be removed but then anot wrapped in act
error comes up with the source beingTransitionGroup
. - It only works when moving items up/down because there's no bounding client rect in jsdom.
If anyone's looking for a solution on how to drag and drop with the latest react, jest and react testing library, here are my utils that do work:
import { act, fireEvent, screen } from '@testing-library/react' enum Keys { SPACE = 32, ARROW_LEFT = 37, ARROW_UP = 38, ARROW_RIGHT = 39, ARROW_DOWN = 40, } export enum DragDirection { LEFT = Keys.ARROW_LEFT, UP = Keys.ARROW_UP, RIGHT = Keys.ARROW_RIGHT, DOWN = Keys.ARROW_DOWN, } // taken from https://github.com/hello-pangea/dnd/blob/main/test/unit/integration/util/controls.ts#L20 const createTransitionEndEvent = (): Event => { const event = new Event('transitionend', { bubbles: true, cancelable: true, }) as TransitionEvent // cheating and adding property to event as // TransitionEvent constructor does not exist. // This is needed because of the following check // https://github.com/atlassian/react-beautiful-dnd/blob/master/src/view/draggable/draggable.jsx#L130 // eslint-disable-next-line @typescript-eslint/no-explicit-any ;(event as any).propertyName = 'transform' return event } export const pickUp = async (element: HTMLElement) => { fireEvent.keyDown(element, { keyCode: Keys.SPACE, }) await screen.findByText(/You have lifted an item/i) await act(() => { jest.runOnlyPendingTimers() }) } export const move = async (element: HTMLElement, direction: DragDirection) => { fireEvent.keyDown(element, { keyCode: direction, }) await screen.findByText(/(You have moved the item | has been combined with)/i) } export const drop = async (element: HTMLElement) => { fireEvent.keyDown(element, { keyCode: Keys.SPACE, }) fireEvent(element, createTransitionEndEvent()) await screen.findByText(/You have dropped the item/i) }
Notes:
- I have both
provided.draggableProps
andprovided.dragHandleProps
spread on the sameelement
(the same one which I am passing to the util functions).TransitionEnd
event must be fired on the element which hasprovided.draggableProps
spreaded on.- This requires
jest.useFakeTimers({ advanceTimers: true })
(in my caseadvanceTimers
is required otherwise it hangs, i haven't checked whether it's because of the drag and drop library or something in my code). This is not strictly necessary, theact
block can be removed but then anot wrapped in act
error comes up with the source beingTransitionGroup
.- It only works when moving items up/down because there's no bounding client rect in jsdom.
Used this with user events 14 today to test a drag & drop menu, we removed the await
from the act
because it was generating a warning or error. But thanks for posting this!
How does one use the provided code? Does it replace this library?
How does one use the provided code? Does it replace this library?
Yes it does replace this library, though it's been a while and I can't tell you whether it still works with the latest versions of the libraries mentioned in my original comment.
@saltenasl Thank you so much for sharing your utility methods (https://github.com/colinrobertbrooks/react-beautiful-dnd-test-utils/issues/18#issuecomment-1373388693)
Amazing <3