dom-testing-library icon indicating copy to clipboard operation
dom-testing-library copied to clipboard

`fireEvent.drop` API behaves not as expected about preventDefault in Browser and js env

Open electroluxcode opened this issue 1 year ago • 2 comments

  • @testing-library/dom 9.3.4 version:
  • Testing Framework and version: null
  • DOM Environment: 20.0.3

Reproduction:


import { fireEvent, render,act } from '@testing-library/react'
import type { FC } from 'react'

function tick(): Promise<void> {
	return new Promise((resolve) => {
		setTimeout(resolve, 0)
	})
}

async function fireDragDrop(source: Element) {
	await act(async () => {
		fireEvent.dragStart(source)
		fireEvent.dragEnter(source)
		fireEvent.dragOver(source)
		fireEvent.drop(source)
		await tick()
	})
}

const Container: FC = (function Container() {
	return (
	<>
		<div draggable="true"
		data-testid={'Other1'}
		onDragStart={(e)=>{
			e.preventDefault()
			console.log("ondragstart")
		}}
		onDragOver={()=>{
			console.log("onDragOver")
		}}>
		other1
		</div>
	</>
	)
})

describe('drag', () => {
	it('prevent', async () => {
		const rendered = render(<Container />)
		const box1 = (await rendered.findAllByTestId('Other1'))[0]
		await fireDragDrop(box1)
	})
})

What you did:

run it in brower and testing env

Problem description:

when I run this component in the browser, onDragOver isn't executed due to e.preventDefault() in the onDragStart test case,

but onDragOver is executed in testing env after onDragStart

Expect

ii should prevent onDragOver fn in test env

electroluxcode avatar Jul 14 '24 06:07 electroluxcode

Hi @electroluxcode, thanks for taking the time to open this. fireEvent is a very low level API, all it does is dispatch the event based on the configuration. I think you should be trying your use case with user-event instead. To top that, I'm not sure I understand the reasoning behind calling e.preventDefault() in onDragStart (afaik, usually calling e.preventDefault in drag scenarios only has meaning in onDragOver or onDragEnter to mark that an item can be dropped somewhere). I'm also not sure the browser's behavior is following the spec and I couldn't find any mention about that. Are you familiar with any spec that defines this behavior?

MatanBobi avatar Jul 15 '24 16:07 MatanBobi

Hi @electroluxcode, thanks for taking the time to open this. fireEvent is a very low level API, all it does is dispatch the event based on the configuration. I think you should be trying your use case with user-event instead. To top that, I'm not sure I understand the reasoning behind calling e.preventDefault() in onDragStart (afaik, usually calling e.preventDefault in drag scenarios only has meaning in onDragOver or onDragEnter to mark that an item can be dropped somewhere). I'm also not sure the browser's behavior is following the spec and I couldn't find any mention about that. Are you familiar with any spec that defines this behavior?

@MatanBobi Thank you very much for your reply. The reason I call e.preventDefault() in onDragStart is to avoid dragging some page elements that shouldn't be draggable. You can refer to

https://github.com/react-dnd/react-dnd/blob/7c88c37489a53b5ac98699c46a506a8e085f1c03/packages/backend-html5/src/HTML5BackendImpl.ts#L551-L553

This is a snippet of react-dnd code where this logic is encapsulated within the onDragStart method. I wanted to write test cases for this code snippet, but found that the onDragStart event behaves unexpectedly during testing.

and after reading your reply, I looked into user-event, but it seems there are no methods related to dragStart or dragOver.

and regarding the browser's behavior you mentioned, you can refer to https://html.spec.whatwg.org/multipage/dnd.html#dndevents.

electroluxcode avatar Jul 16 '24 01:07 electroluxcode