react-beautiful-dnd-test-utils icon indicating copy to clipboard operation
react-beautiful-dnd-test-utils copied to clipboard

Does not work with UserEvent v14

Open asnoeyink opened this issue 2 years ago • 5 comments

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.

asnoeyink avatar Aug 29 '22 17:08 asnoeyink

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:

  1. I have both provided.draggableProps and provided.dragHandleProps spread on the same element (the same one which I am passing to the util functions). TransitionEnd event must be fired on the element which has provided.draggableProps spreaded on.
  2. This requires jest.useFakeTimers({ advanceTimers: true }) (in my case advanceTimers 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, the act block can be removed but then a not wrapped in act error comes up with the source being TransitionGroup.
  3. It only works when moving items up/down because there's no bounding client rect in jsdom.

saltenasl avatar Jan 06 '23 09:01 saltenasl

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:

  1. I have both provided.draggableProps and provided.dragHandleProps spread on the same element (the same one which I am passing to the util functions). TransitionEnd event must be fired on the element which has provided.draggableProps spreaded on.
  2. This requires jest.useFakeTimers({ advanceTimers: true }) (in my case advanceTimers 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, the act block can be removed but then a not wrapped in act error comes up with the source being TransitionGroup.
  3. 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!

dalevfenton avatar Feb 10 '23 01:02 dalevfenton

How does one use the provided code? Does it replace this library?

blissdev avatar Apr 01 '24 17:04 blissdev

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 avatar Apr 01 '24 18:04 saltenasl

@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

rhdhvolschenk avatar Apr 03 '24 13:04 rhdhvolschenk