diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts
index 69ef1ecba5..87685050ec 100644
--- a/packages/playwright-core/src/server/frames.ts
+++ b/packages/playwright-core/src/server/frames.ts
@@ -1210,6 +1210,9 @@ export class Frame extends SdkObject {
// Note: do not perform locator handlers checkpoint to avoid moving the mouse in the middle of a drag operation.
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options.strict, false /* performActionPreChecks */, async handle => {
return handle._retryPointerAction(progress, 'move and up', false, async point => {
+ // NOTE: Normal browsers emit usually a lot of dragover/mousemove events during drag'n
+ // drop operations. We want to emit minimal (2) to make Angular CDK work.
+ await this._page.mouse.move(point.x, point.y);
await this._page.mouse.move(point.x, point.y);
await this._page.mouse.up();
}, {
diff --git a/tests/assets/drag-n-drop-manual.html b/tests/assets/drag-n-drop-manual.html
new file mode 100644
index 0000000000..143b87ef9a
--- /dev/null
+++ b/tests/assets/drag-n-drop-manual.html
@@ -0,0 +1,112 @@
+
+
+
+
+
+ Select this element, drag it to the Drop Zone and then release the selection to move the element.
+
+ Drop Zone
+
+
+
diff --git a/tests/page/page-drag.spec.ts b/tests/page/page-drag.spec.ts
index c227978f23..906e037d91 100644
--- a/tests/page/page-drag.spec.ts
+++ b/tests/page/page-drag.spec.ts
@@ -53,6 +53,25 @@ it.describe('Drag and drop', () => {
]);
});
+ it('should send the right events when using dragTo', async ({ server, page, browserName }) => {
+ await page.goto(server.PREFIX + '/drag-n-drop.html');
+ const events = await trackEvents(await page.$('body'));
+ await page.locator('#source').dragTo(page.locator('#target'));
+ expect(await events.jsonValue()).toEqual([
+ 'mousemove at 120;86',
+ 'mousedown at 120;86',
+ browserName === 'firefox' ? 'dragstart at 120;86' : 'mousemove at 240;350',
+ browserName === 'firefox' ? 'mousemove at 240;350' : 'dragstart at 120;86',
+ 'dragenter at 240;350',
+ // NOTE: Normal browsers emit usually a lot of dragover events during drag'n
+ // drop operations. We want to emit minimal (2) to make Angular CDK work.
+ 'dragover at 240;350',
+ 'dragover at 240;350',
+ 'drop at 240;350',
+ 'dragend',
+ ]);
+ });
+
it('should not send dragover on the first mousemove', async ({ server, page, browserName }) => {
it.fixme(browserName !== 'chromium');
@@ -293,6 +312,34 @@ it.describe('Drag and drop', () => {
expect(await page.$eval('#target', target => target.contains(document.querySelector('#source')))).toBe(true); // could not find source in target
});
+ it('should work with manual drag\'n drop and emit correct mousemove events', {
+ annotation: {
+ type: 'issue',
+ description: 'https://github.com/microsoft/playwright/issues/34688',
+ }
+ }, async ({ page, server }) => {
+ await page.goto(server.PREFIX + '/drag-n-drop-manual.html');
+ const events = await page.evaluateHandle(() => {
+ const events = [];
+ document.addEventListener('mousemove', (event: MouseEvent) => {
+ events.push({
+ type: event.type,
+ x: event.clientX,
+ y: event.clientY,
+ });
+ });
+ return events;
+ });
+ await page.dragAndDrop('#source', '#target');
+ expect(await events.jsonValue()).toEqual([
+ { type: 'mousemove', x: 120, y: 86 },
+ // NOTE: Normal browsers emit usually a lot of mousemove events during drag'n
+ // drop operations. We want to emit minimal (2) to make Angular CDK work.
+ { type: 'mousemove', x: 240, y: 350 },
+ { type: 'mousemove', x: 240, y: 350 },
+ ]);
+ });
+
it('should allow specifying the position', async ({ page, server }) => {
await page.setContent(`