Implementing drag and drop simulation in Puppeteer for E2E testing

Hey everyone, I’m working on E2E tests for my React app that uses React-DnD. I’m trying to figure out how to simulate drag and drop actions using Puppeteer.

I’ve got this code so far:

// e2e-test.js
async function simulateDragAndDrop(page) {
  const mouse = page.mouse;
  await mouse.down();
  await mouse.move(200, 50);
  await page.waitForTimeout(500);
  await mouse.up();
}

This selects an element, but it’s not actually dragging it. Any ideas on how to make this work? I need to drag a specific element and drop it in a particular spot.

Has anyone successfully tested React-DnD components with Puppeteer? What’s the trick to getting the drag action to register properly? Thanks for any help!

I’ve found that simulating drag and drop in Puppeteer can be tricky, especially with React-DnD. One approach that’s worked well for me is using the dragAndDrop method from the @testing-library/user-event library. It’s designed to work with React components and handles the complex event simulation required for drag and drop.

Here’s a basic example of how you might use it:

import { dragAndDrop } from '@testing-library/user-event';

// In your test
const source = await page.$('#sourceElement');
const target = await page.$('#targetElement');

await dragAndDrop(source, target);

This method takes care of all the low-level event dispatching, making your tests more reliable and easier to write. Just make sure you have the library installed and properly set up in your testing environment. Also, remember to allow time for any post-drag animations or state updates before making assertions.

hey, i’ve had some luck with this. try using elementHandle.drag() method. it’s built into puppeteer and works pretty well. something like:

async function dragAndDrop(page, sourceSelector, targetSelector) {
const source = await page.$(sourceSelector);
const target = await page.$(targetSelector);
await source.drag(target);
}

this has worked for me with react-dnd stuff. hope it helps!

I’ve dealt with a similar challenge when testing our React app with React-DnD. The trick is to simulate the entire drag sequence, including the dragstart and dragend events.

Here’s what worked for me:

async function simulateDragAndDrop(page, sourceSelector, targetSelector) {
  const source = await page.$(sourceSelector);
  const target = await page.$(targetSelector);
  
  const sourceBox = await source.boundingBox();
  const targetBox = await target.boundingBox();

  await page.mouse.move(sourceBox.x + sourceBox.width / 2, sourceBox.y + sourceBox.height / 2);
  await page.mouse.down();
  await page.mouse.move(targetBox.x + targetBox.width / 2, targetBox.y + targetBox.height / 2, { steps: 10 });
  await page.mouse.up();
}

This function takes selectors for both the source and target elements. It calculates their positions, moves to the center of the source, presses down, moves towards the target in multiple steps (which is key for triggering the drag events), and then releases the mouse button.

Make sure to wait for any animations or state updates post-drag, as you might need to include a short delay or wait for a specific element to change to confirm the drop was registered.