VALIDATION LAB•DRAG & DROP
Mouse
Drag & Drop
Reorder a Kanban card across columns using mouse events and verify the destination column owns it.
Scenario
Kanban, file managers, image gallery reorder — drag is everywhere and notoriously hard to test. Native `dragTo()` works for HTML5 drag, but custom React DnD libs need pointer events + `force: true`.
Todo
Doing
Done
Live widget · interact freely
Manual test checklist
- 1Drag QA card from Doing → Done — card moves and counts update
- 2Drag back to Doing — card returns; no duplicates
- 3Try dragging past the right edge — column should auto-scroll, not crash
- 4On touch device, long-press to start drag — same UX?
- 5Tab into a card — does it expose keyboard reorder (Space + arrows)?
Expected result
Dragging the 'QA review' card from Doing → Done updates the source/dest counts.
Automation challenge
Try `card.dragTo(target)` first. If your real app uses React DnD, fall back to `dispatchEvent('mousedown')` + intermediate `mousemove` + `mouseup` with `{ force: true }`. Assert via the column count, not the visual position.
Stable selectors
- Card to drag
[data-testid="dnd-card-qa"] - Source column
[data-testid="dnd-col-doing"] - Target column
[data-testid="dnd-col-done"]
Locator strategy
Three levels from simple IDs to scoped Playwright locators. IDs and names are easy to learn but are not always the best long-term choice when labels change or components repeat.
Use simple IDs and names to understand how locating elements works.
123
await page.goto('https://lab.hakdogan.com/practice/drag-drop');
await page.locator('#dnd-card-qa').dragTo(page.locator('#dnd-col-done'));Avoid as primary strategies
XPath (unless there is no alternative), long CSS chains, Tailwind-style utility class selectors, generated or unstable IDs, and volatile framework internals break when layout, styling, or DOM structure shifts.
12
await page.locator('.w-full.rounded-xl.border.bg-blue-500').fill('demo@example.com');
await page.locator('//div[2]/form/div[1]/input').fill('demo@example.com');Reference Playwright spec
1234567891011
import { test, expect } from '@playwright/test';
test('kanban drag and drop', async ({ page }) => {
await page.goto('https://lab.hakdogan.com/practice/drag-drop');
const card = page.getByTestId('dnd-card-qa');
const target = page.getByTestId('dnd-col-done');
await card.dragTo(target);
await expect(page.getByTestId('dnd-col-done')).toContainText('QA review');
});Headed Test Playback
Simulated headed-browser flow — no real browser is launched.
Automation-style playback (Playwright-shaped logs). No real browser; no commands run on your machine.
drag-drop.spec.ts- Locating QA card
- Dragging to Done column
- Asserting card moved