[Bug]: Canceling a drag operation does not fire `dragleave` event on drop target
Version
1.49.0
Steps to reproduce
- Clone my repo at https://github.com/danielwiehl/playwright-bug-reproducer-dnd-cancel
- npm install
- npm run test
- See failed test:
reproducer.spec.ts › should receive 'dragleave' event when canceling drag operation
Expected behavior
Canceling a drag operation should behave like canceling a drag operation in the browser, i.e., trigger a dragleave event on the drop target.
Actual behavior
Canceling a drag operation in Playwright does not trigger a dragleave event on the drop target. Only the dragend event is fired on the element where the drag operation was started.
Additional context
No response
Environment
System:
OS: Windows 11 10.0.26100
CPU: (20) x64 13th Gen Intel(R) Core(TM) i7-1370P
Memory: 34.69 GB / 63.66 GB
Binaries:
Node: 20.14.0 - C:\dev\nodejs\node.EXE
npm: 10.7.0 - C:\dev\nodejs\npm.CMD
IDEs:
VSCode: 1.95.1 - C:\dev\ide\Microsoft VS Code\bin\code.CMD
Languages:
Bash: 5.2.15 - C:\dev\programs\cmder\vendor\git-for-windows\usr\bin\bash.EXE
npmPackages:
@playwright/test: ^1.49.0 => 1.49.0
Hi Daniel! dragleave is not emitted on the target element, but on the dragged element. See https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragleave_event for docs on that.
To verify that, make the following change to your repro test:
diff --git a/tests/reproducer.spec.ts b/tests/reproducer.spec.ts
index b91d3f4..850f38a 100644
--- a/tests/reproducer.spec.ts
+++ b/tests/reproducer.spec.ts
@@ -29,7 +29,7 @@ test(`should receive 'dragleave' event when canceling drag operation`, async ({p
await page.keyboard.press('Escape');
// Assert log entries for cancelation.
- await expect.poll(() => logs).toContain('[dropTarget] dragleave'); // FAIL
+ await expect.poll(() => logs).toContain('[dragSource] dragleave'); // FAIL
await expect.poll(() => logs).toContain('[dragSource] dragend'); // success
});
@@ -73,6 +73,9 @@ async function setPageScript(page: Page): Promise<void> {
dragSource.addEventListener('dragend', () => {
console.log('[dragSource] dragend');
});
+ dragSource.addEventListener('dragleave', () => {
+ console.log('[dragSource] dragleave');
+ });
dropTarget.addEventListener('dragenter', () => {
console.log('[dropTarget] dragenter');
});
You'll see that it now passes. Let me know if that helps!
Thank you, @Skn0tt, for your quick response.
The dragleave event you mentioned occurs when the drag image is dragged out of the drag source's bounding box while being dragged toward the drop target, before the cancelation.
I am referring to the (missing) dragleave event on the drop target when canceling the drag operation while dragging over the drop target.
When you drag the drag image over the drop target, a dragenter event is fired on the drop target, followed by dragover events. If the drag operation is then canceled by pressing escape, a dragleave event should be fired on the drop target. Canceling the drag operation in browsers fires that event, but it is not fired when canceling the drag operation in Playwright.
I see, thanks for pointing that out. We'll take a look.
Why was this issue closed?
Thank you for your contribution to our project. This issue has been closed due to its limited upvotes and recent activity, and insufficient feedback for us to effectively act upon. Our priority is to focus on bugs that reflect higher user engagement and have actionable feedback, to ensure our bug database stays manageable.
Should you feel this closure was in error, please create a new issue and reference this one. We're open to revisiting it given increased support or additional clarity. Your understanding and cooperation are greatly appreciated.