Repo of the Day
4teamwork/cypress-drag-drop
Published: Jan 10, 2023
Open repository ↗A cypress child command for drag'n'drop support.
Summary
@4tw/cypress-drag-drop is a Cypress child command plugin that adds drag-and-drop support to end-to-end tests. It registers two commands, drag and move, that wrap Cypress's lower-level event triggering so tests can simulate dragging elements to drop targets or moving elements by a relative offset. The plugin is published under the GPL-3.0 license.
What it is useful for
Cypress's built-in trigger command can fire individual mouse events, but reliably scripting a full drag-and-drop interaction (mousedown, multiple mousemove steps, mouseup) against arbitrary drop targets is awkward to maintain by hand. This plugin packages that sequence into a single readable call, which is useful when you need to test UI built on HTML5 drag-and-drop, libraries like SortableJS or react-beautiful-dnd, kanban boards, file upload zones, or any widget where reordering happens by dragging.
The drag command also returns a boolean describing whether the drop was accepted, which is useful when an application silently rejects drops in some zones and you want your assertion to reflect that.
How engineers can use it
Install the package as a dev dependency:
npm install --save-dev @4tw/cypress-drag-drop
Then register it before Cypress loads, typically in cypress/support/commands.js:
require('@4tw/cypress-drag-drop')
ES module syntax is also shown in the README:
import '@4tw/cypress-drag-drop'
TypeScript users need to add the package to compilerOptions.types in tsconfig.json, alongside cypress.
In a spec file, call it against any element yielded by cy.get:
cy.get('.sourceitem').drag('.targetitem')
Options can be split into source and target keys, or applied to both:
cy.get('.sourceitem').drag('.target', {
source: { x: 100, y: 100 },
target: { position: 'left' },
force: true,
})
The README states these options are passed directly to Cypress's trigger command, so any argument listed in the Cypress trigger docs is accepted.
For relative movement rather than dropping on a target, use move with deltaX and deltaY:
cy.get('.sourceitem').move({ deltaX: 100, deltaY: 100 })
The README notes that position, x, and y are not accepted by move because it uses clientX and clientY internally.
To verify the outcome, chain .then and assert on the boolean:
cy.get('.sourceitem').drag('.target').then((success) => {
assert.isTrue(success)
})
The plugin code lives in index.js and tests run via yarn test, with fixtures loaded through a cy.setExample('NameOfTheComponent') helper. Because the GPL-3.0 license is copylefted rather than permissive, teams should confirm it is compatible with their project's license before adopting.