Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does not work with UserEvent v14 #18

Open
asnoeyink opened this issue Aug 29, 2022 · 5 comments
Open

Does not work with UserEvent v14 #18

asnoeyink opened this issue Aug 29, 2022 · 5 comments

Comments

@asnoeyink
Copy link

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.

@saltenasl
Copy link

saltenasl commented Jan 6, 2023

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.

@dalevfenton
Copy link

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!

@blissdev
Copy link

blissdev commented Apr 1, 2024

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

@saltenasl
Copy link

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.

@rhdhvolschenk
Copy link

@saltenasl Thank you so much for sharing your utility methods (#18 (comment))

Amazing <3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants