Interaction Testing

How to Test Drag and Drop with Playwright

Drag and drop is one of the hardest interactions to automate reliably. Playwright provides several APIs for it, but choosing the right one depends on how your application implements dragging. This guide covers every approach: HTML5 drag events, pointer-based dragging, sortable lists, file drops, and the common pitfalls that cause test flakiness.

0

Generates standard Playwright files you can inspect, modify, and run in any CI pipeline.

Open-source test automation

1. Two Types of Drag and Drop on the Web

Web applications implement drag and drop in two fundamentally different ways, and the testing approach differs for each. The first is the HTML5 Drag and Drop API, which uses native browser events likedragstart,dragover,drop, anddragend. Elements with thedraggableattribute participate in this API. It supports drag between windows and native file drops but has limited styling control during the drag.

The second type is pointer-based (or mouse-based) dragging. Libraries like react-beautiful-dnd, dnd-kit, and SortableJS implement dragging using mouse or pointer events (mousedown, mousemove, mouseup) without the HTML5 Drag API. These libraries provide better visual feedback, smoother animations, and more control over the drag behavior. They are more common in modern React applications but require a different testing approach.

To determine which type your application uses, inspect the draggable element in devtools. If it has adraggable="true"attribute, it likely uses the HTML5 API. If it does not, or if the drag library adds event listeners for pointer events, it uses pointer-based dragging. Some libraries (like react-dnd) support both backends, so check which backend is configured in your application code.

2. Using Playwright's dragTo Method

Playwright provides a built-indragTo()method on locators that handles the most common drag and drop scenarios. The basic usage is:source.dragTo(target). This performs a complete drag sequence: hover over the source, press the mouse button, move to the target, and release.

The dragTomethod works well with HTML5 drag and drop because it triggers the native drag events that the API expects. For pointer-based drag implementations, results can vary. Some pointer-based libraries require specific mouse movement patterns (like moving slowly in small increments) thatdragTodoes not replicate. IfdragTodoes not work for your library, use the low-level mouse API described in the next section.

You can pass options todragToto control the drag position. ThesourcePositionand targetPositionoptions let you specify where on the source element to pick up and where on the target element to drop. This is useful when the drop behavior depends on the exact position (for example, dropping above or below an item in a sortable list).

Try Assrt for free

Open-source AI testing framework. No signup required.

Get Started

3. Low-Level Mouse Events for Custom Drag

When dragTodoes not work, use Playwright's low-level mouse API to simulate the drag manually. The sequence is: hover over the source element, press the mouse button, move to intermediate points, move to the target, and release. The intermediate moves are critical because many drag libraries require movement events to activate the drag state.

Here is the general pattern: first, get the bounding boxes of the source and target elements usingboundingBox(). Calculate the center coordinates of each. Then execute the drag sequence:page.mouse.move(sourceX, sourceY),page.mouse.down(), add small intermediate moves (5 to 10 pixels at a time),page.mouse.move(targetX, targetY), then page.mouse.up().

The number of intermediate steps depends on the library. Some libraries (like react-beautiful-dnd) require significant mouse movement before they activate the drag. A common pattern is to move 10 pixels down from the source first, pause briefly, then move to the target. Thestepsoption on mouse.move()controls how many intermediate mousemove events are fired. A value of 10 to 20 usually works for most libraries.

4. Testing Sortable Lists and Kanban Boards

Sortable lists and kanban boards are the most common drag and drop patterns in web applications. Testing them requires verifying both the visual reorder and the data update. After dragging an item from position 1 to position 3, verify that the DOM order reflects the new position and that any API call to save the order was made with the correct payload.

For sortable lists, the drop target is often the gap between items rather than the items themselves. Position your drop coordinates carefully. Dropping on the top half of an item typically places the dragged item above it, while dropping on the bottom half places it below. Use the target element's bounding box to calculate the correct Y offset. If you consistently get the wrong order, try adjusting the Y offset by a few pixels.

For kanban boards with multiple columns, the drag crosses container boundaries. Drag from an item in one column to a position in another column. Verify that the item appears in the new column and that the source column no longer contains it. Also check that the column item counts update correctly. These cross-container drags are the most valuable to test because they exercise the most complex logic.

5. Testing File Drop Zones

File drop zones accept files dragged from the operating system into the browser. Testing this with Playwright does not require actual OS-level drag because Playwright provides a file upload API. For drop zones that also have a file input element, usesetInputFiles()on the hidden file input. This is the most reliable approach and works across all browsers.

For drop zones that rely exclusively on drag events (without a file input fallback), you need to dispatch synthetic drop events usingpage.evaluate(). Create a DataTransfer object, add File objects to it, and dispatch dragenter, dragover, and drop events on the drop zone element. This approach is more complex but accurately simulates the native file drop flow.

After the drop, verify the expected behavior: a preview image should appear, an upload progress indicator should show, and the file should eventually be uploaded. Use Playwright's network interception to verify the upload request was made with the correct file data. For large files, consider using small test fixtures (a 1x1 pixel PNG, a minimal PDF) to keep test execution fast.

6. Cross-Browser Issues and CI Reliability

Drag and drop is one of the most browser-dependent interactions to automate. The HTML5 Drag API has known differences between Chromium, Firefox, and WebKit. Pointer events behave slightly differently across engines. If your tests pass in Chromium but fail in Firefox, the issue is almost certainly in event dispatch differences, not in your test logic. Start by getting tests working in Chromium, then add cross-browser testing as a separate step.

In CI environments, drag tests can be flaky due to slower rendering. The drag library might not register a move event if the mouse jumps too quickly from source to target. Adding intermediate steps and small delays between mouse events helps. Use Playwright'sslowMooption during debugging to visualize the drag sequence and identify where it breaks.

For teams that want to generate drag and drop tests automatically, Assrt can detect draggable elements during its crawl and generate appropriate Playwright test code. It analyzes whether the element uses HTML5 drag attributes or pointer-based libraries and selects the correct testing approach. The generated tests are standard Playwright files that you can customize, extend with additional assertions, and run in any CI pipeline.

Ready to automate your testing?

Assrt discovers test scenarios, writes Playwright tests from plain English, and self-heals when your UI changes.

$npm install @assrt/sdk