[Bug]: DragTo Fails in 1.50
Version
1.50.1
Steps to reproduce
Sadly, cannot reproduce. We have a complex dragTo with force:true. Test passes on 1.49.1 but fails on 1.50 As this is a complex private dom, not sure how to repro. Some guidelines might help.
Expected behavior
Drag would work
Actual behavior
does not drag. no error is produced.
Additional context
No response
Environment
System:
OS: macOS 15.3
CPU: (16) arm64 Apple M4 Max
Memory: 9.79 GB / 128.00 GB
Binaries:
Node: 22.13.1 - ~/.nvm/versions/node/v22.13.1/bin/node
npm: 11.1.0 - ~/.nvm/versions/node/v22.13.1/bin/npm
IDEs:
VSCode: 1.97.0 - /usr/local/bin/code
Languages:
Bash: 3.2.57 - /bin/bash
npmPackages:
@playwright/test: 1.49.1 => 1.50.0
Hi Tally, we unfortunately need a reproduction in order to triage this issue further. Maybe you can create a self-contained reproduction with the dev team of your site?
hola @mxschmitt ! not sure this is actually the problem, but if you can try this one:
import {expect, test} from '@playwright/test';
test('draggable', async ({ page }) => {
await page.goto('https://material.angular.io/cdk/drag-drop/examples');
await page.locator('button', { hasText: /got it/ }).click();
await expect (page.locator('.popup')).toBeHidden();
const example = page.locator('example-viewer', { hasText: 'Drag&Drop connected sorting group'})
await example.scrollIntoViewIfNeeded();
const leftColumn = example.locator('.example-container').nth(0);
const rightColumn = example.locator('.example-container').nth(1);
await leftColumn.getByText('Get to work').dragTo(rightColumn.getByText('Take a shower'));
await expect(rightColumn.getByText('Get to work')).toBeVisible();
});
Dragto is not yelling, but at the same time it does not do what is expected. do I miss anything here? is that a problem with the Angular CDK?
Investigation notes:
- TL;DR: Angular requires at least two
'mousemove'events on the target element. - Without that, it does not correctly identity the drop target. It then falls back internally to
target = sourceso the drag'n drop is not working. - It expects to end up twice in this handler.
- This handler is added globally on the document here.
- For the first time we end up in the handler, it should go into this condition: https://github.com/angular/components/blob/7abd0ebbe48755ff5403a78820c7f6211ab4f56a/src/cdk/drag-drop/drag-ref.ts#L680 and identify the target element based on x/y coordinates.
- The second time it should (does not) go into this condition: https://github.com/angular/components/blob/7abd0ebbe48755ff5403a78820c7f6211ab4f56a/src/cdk/drag-drop/drag-ref.ts#L728
- The reason why it works for a normal user is that it emits much more
mousemoveevents compared to Playwright - Solution: We should also try to emit more, I think an intermediate
mousemovex -/+ 1 shouldn't hurt and make Angular work.
e.g. this makes it pass:
diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts
index 2183d3f40..5abf9a8d0 100644
--- a/packages/playwright-core/src/server/frames.ts
+++ b/packages/playwright-core/src/server/frames.ts
@@ -1210,6 +1210,7 @@ export class Frame extends SdkObject {
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options.strict, false /* performActionPreChecks */, async handle => {
return handle._retryPointerAction(progress, 'move and up', false, async point => {
await this._page.mouse.move(point.x, point.y);
+ await this._page.mouse.move(point.x + 1, point.y);
await this._page.mouse.up();
}, {
...options,
@Tallyb from quickly running this script in v1.49.0 it wasn't passing for me in v1.49.0 either, is this the same what you are experiencing?
No, this was not passing on 1.49, but as we use angular cdk, I was hoping it will shed some light.
I'll try to get it fixed and then you can try the @beta version and see if it works there!
Filed it upstream: https://github.com/angular/components/issues/30580
Workaround for now:
import assert from 'node:assert';
async function angularDragnDrop(page: Page, from: Locator, to: Locator) {
const fromBoundingBox = await from.boundingBox();
assert(fromBoundingBox, 'Could not find "from" element');
const toBoundingBox = await to.boundingBox();
assert(toBoundingBox, 'Could not find "to" element');
await page.mouse.move(fromBoundingBox.x + fromBoundingBox.width / 2, fromBoundingBox.y + fromBoundingBox.height / 2);
await page.mouse.down();
// Needed because of https://github.com/angular/components/issues/30580
await page.mouse.move(toBoundingBox.x + toBoundingBox.width / 2, toBoundingBox.y + toBoundingBox.height / 2);
await page.mouse.move(toBoundingBox.x + toBoundingBox.width / 2, toBoundingBox.y + toBoundingBox.height / 2);
await page.mouse.up();
}
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.