如何在Puppeteer中模拟拖拽?React-DnD应用E2E测试问题
Hey there! Let's work through your Puppeteer drag-and-drop questions, especially the tricky part with React-DnD.
To properly simulate dragging in Puppeteer, you need to complete the full mouse interaction cycle—you can't stop at just pressing and moving the mouse. Here's a reliable approach that uses element positions instead of hardcoded coordinates (which break if your layout changes):
// Wait for both the draggable element and drop zone to load await page.waitForSelector('#your-source-element'); await page.waitForSelector('#your-target-zone'); // Get references to the elements const sourceEl = await page.$('#your-source-element'); const targetEl = await page.$('#your-target-zone'); // Get the center coordinates of each element (so we drag to/from a consistent spot) const sourceBounds = await sourceEl.boundingBox(); const targetBounds = await targetEl.boundingBox(); const mouse = page.mouse; // Move to the source element's center and press the mouse button await mouse.move( sourceBounds.x + sourceBounds.width / 2, sourceBounds.y + sourceBounds.height / 2 ); await mouse.down(); // Add a small delay to let the browser register the "drag start" state await page.waitForTimeout(200); // Move the mouse to the target element's center await mouse.move( targetBounds.x + targetBounds.width / 2, targetBounds.y + targetBounds.height / 2 ); // Another short delay to ensure the target registers the hover await page.waitForTimeout(200); // Release the mouse button to complete the drop await mouse.up();
React-DnD wraps the native HTML5 drag-and-drop API, which means it listens to specific drag events (like dragstart, dragover, and drop) instead of just raw mouse movements. Your original code didn't trigger these events, which is why the drag didn't register with your React component.
Here's a solution that directly dispatches the native drag events in the browser context:
await page.evaluate(async (sourceSelector, targetSelector) => { const source = document.querySelector(sourceSelector); const target = document.querySelector(targetSelector); // Create a data transfer object (required for native drag events) const dataTransfer = new DataTransfer(); // Trigger dragstart on the source element const dragStart = new DragEvent('dragstart', { bubbles: true, cancelable: true, dataTransfer: dataTransfer }); source.dispatchEvent(dragStart); // Trigger dragenter and dragover on the target (required for drop to work) const dragEnter = new DragEvent('dragenter', { bubbles: true, cancelable: true, dataTransfer: dataTransfer }); target.dispatchEvent(dragEnter); const dragOver = new DragEvent('dragover', { bubbles: true, cancelable: true, dataTransfer: dataTransfer }); target.dispatchEvent(dragOver); // Trigger the drop event to complete the action const drop = new DragEvent('drop', { bubbles: true, cancelable: true, dataTransfer: dataTransfer }); target.dispatchEvent(drop); // Clean up with dragend const dragEnd = new DragEvent('dragend', { bubbles: true, cancelable: true, dataTransfer: dataTransfer }); source.dispatchEvent(dragEnd); }, '#your-source-selector', '#your-target-selector');
Why Your Original Code Failed
Your code only ran mouse.down() and mouse.move() but never called mouse.up() to finalize the drop. Plus, hardcoded coordinates are fragile, and React-DnD doesn't react to raw mouse events alone—it needs the native drag event chain to fire.
A quick tip: If you're still having issues, combine both approaches—simulate the mouse press/move first, then dispatch the native events. This covers edge cases where React-DnD might listen to both mouse and drag events.
内容的提问来源于stack exchange,提问作者Khushi

