playwright drag and drop

Viewed 7651

Trying to test some drag and drop functionality, looks like playwright doesn't have drag and drop functionality so I'm using mouse.move(), mouse.down() & mouse.up().

However my attempts seem to be failing, the target is not being moved. Code below:

test("drag and drop test", async () => {
  await page.goto("https://www.w3schools.com/html/html5_draganddrop.asp");
  await page.waitForSelector("#accept-choices");
  await page.click("#accept-choices");
  await page.waitForSelector("#div1");
  let xStart, yStart, xFinish, yFinish, elementHandle, rect;
  elementHandle = await page.$("#div1");
  rect = await elementHandle.boundingBox();
  xStart = rect.x + rect.width / 2;
  yStart = rect.y + rect.height / 2;
  elementHandle = await page.$("#div2");
  rect = await elementHandle.boundingBox();
  xFinish = rect.x + rect.width / 2;
  yFinish = rect.y + rect.height / 2;
  console.log(`move from (${xStart}, ${yStart}) to (${xFinish},${yFinish})`);
  await page.screenshot({ path: "before drag.png" });
  await page.mouse.move(xStart, yStart);
  await page.mouse.down();
  await page.mouse.move(xFinish, yFinish);
  await page.mouse.up();
  await page.screenshot({ path: "after drag.png" });
});
2 Answers

I've also struggled with how to make drag and drop possible with playwright.

I needed to move vertically, for example,

before reorder 1 2 3

after reorder applied 2 1 3

    const exampleOneDrag = await page.$(
      `[data-testid="${exampleOne}-drag-icon-button"]`
    )
    const exampleTwoDrag = await page.$(
      `[data-testid="${exampleTwo}-drag-icon-button"]`
    )
    const oneBoundingBox = await exampleOneDrag?.boundingBox()
    const twoBoundingBox = await exampleTwoDrag?.boundingBox()

    if (oneBoundingBox && twoBoundingBox) {
      await page.mouse.move(
        oneBoundingBox.x + oneBoundingBox.width / 2,
        oneBoundingBox.y + oneBoundingBox.height / 2,
        { steps: 5 }
      )
      await page.mouse.down()
      await page.mouse.move(
        twoBoundingBox.x + twoBoundingBox.width / 2,
        twoBoundingBox.y + twoBoundingBox.height / 2,
        { steps: 5 }
      )
      await page.mouse.up()
    }

The keypoint to be able to work this was steps:5 options. I am not entirely sure what it does, but I've found from here : https://github.com/codeceptjs/CodeceptJS/blob/e815d82af028e904051b5b6c70873164e1df1bfd/lib/helper/Playwright.js#L2289-L2307e

hope this works for you. I think your case, you should change like this

  await page.mouse.move(xStart, xFinish);
  await page.mouse.down();
  await page.mouse.move(yStart, yFinish);

Version 1.13.0 added API methods for that. Check out the documentation.
Copied from the docs:

page.dragAndDrop(source, target[, options])

  • source: string
  • target: string
  • options: Object
    • force boolean Whether to bypass the actionability checks. Defaults to false.
    • noWaitAfter boolean Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to false.
    • timeout number Maximum time in milliseconds, defaults to 30 seconds, pass 0 to disable timeout. The default value can be changed by using the browserContext.setDefaultTimeout(timeout) or page.setDefaultTimeout(timeout) methods.
    • trial: boolean When set, this method only performs the actionability checks and skips the action. Defaults to false. Useful to wait until the element is ready for the action without performing it.
  • returns: Promise<void>
Related