Answer
Drag and Drop in Playwright
Method 1 — locator.dragTo() (Simplest)
TypeScript
// Drag source element onto target element
await page.locator('#draggable-item').dragTo(page.locator('#drop-zone'));
// Drag a card to a different column (Kanban board)
await page.locator('.card[data-id="task-1"]').dragTo(
page.locator('.column[data-status="done"]')
);
Method 2 — dragTo with Options
TypeScript
await page.locator('#source').dragTo(page.locator('#target'), {
sourcePosition: { x: 10, y: 10 }, // Start from this offset within source
targetPosition: { x: 50, y: 20 }, // Drop at this offset within target
force: true, // Bypass actionability checks
});
Method 3 — Manual Mouse Events (For Complex UI)
TypeScript
// More control over the drag path
const source = page.locator('#item-to-drag');
const target = page.locator('#drop-target');
// Get bounding boxes
const sourceBox = await source.boundingBox();
const targetBox = await target.boundingBox();
if (sourceBox && targetBox) {
// Move to source center
await page.mouse.move(
sourceBox.x + sourceBox.width / 2,
sourceBox.y + sourceBox.height / 2
);
await page.mouse.down();
// Slowly drag to target (important for smooth DnD libraries)
await page.mouse.move(
targetBox.x + targetBox.width / 2,
targetBox.y + targetBox.height / 2,
{ steps: 10 } // Move in 10 steps for smooth animation
);
await page.mouse.up();
}
Method 4 — DataTransfer via evaluate() (HTML5 DnD)
TypeScript
// For HTML5 drag events
await page.locator('#source').dispatchEvent('dragstart');
await page.locator('#target').dispatchEvent('drop');
await page.locator('#source').dispatchEvent('dragend');
Full Example — Kanban Board
TypeScript
import { test, expect } from '@playwright/test';
test('drag task from Todo to Done', async ({ page }) => {
await page.goto('/kanban');
const task = page.locator('.task-card').filter({ hasText: 'Write tests' });
const doneColumn = page.locator('.kanban-column[data-status="done"]');
// Verify initial state
await expect(task).toBeVisible();
// Drag the task to Done column
await task.dragTo(doneColumn);
// Verify task moved to Done column
await expect(doneColumn.locator('.task-card').filter({ hasText: 'Write tests' }))
.toBeVisible();
});
Sortable List Example
TypeScript
test('reorder list items via drag', async ({ page }) => {
await page.goto('/sortable-list');
const firstItem = page.locator('.sortable-item').nth(0);
const thirdItem = page.locator('.sortable-item').nth(2);
// Move first item to third position
await firstItem.dragTo(thirdItem);
// Verify new order
await expect(page.locator('.sortable-item').nth(0)).toHaveText('Item 2');
});
