I am trying to make DnD work in Cypress and React app.
At first I was trying all examples around those with simulating by mouse events but it is not working in general in my environment. :(
I was able to write a test where I know the drag element and drop element using this code.
const dataTransfer = new DataTransfer();
cy.get(dragSelector).trigger("dragstart", {
dataTransfer,
force: true,
});
cy.get(dropSelector).trigger("drop", {
dataTransfer,
force: true,
});
And it's working well. Similar sample code I have found in Cypress cookbook.
But now I need to do DnD where I don't know the drop zone / elem. Its resizer and I need dnd by offset for example 20px on Y axis. (Resize element height by 20px)
So is it possible to do it somehow like this?
const dataTransfer = new DataTransfer();
// drag selector is element with draggable attribute and I need move it by 20px from top to down
cy.get(dragSelector).trigger("dragstart", {
dataTransfer,
force: true,
}).trigger("drop",{...how to set drop offset if is possible...})
trigger drop event as some parameters like offsetX and offsetY or x or y and pageX or pageY... but I was not successful.
Like I sad I am not able use it by simulating mouse events in my app from unknow reason its not working.
This is how I'm testing a divider (resizer) using mouse events.
I did add cypress-real-events
for mousedown and mouseup, but it may be ok to use .trigger('mousedown')
instead.
My app is React hooks, and I found it needed a small wait before checking. I think that can be optimized with a .should()
, but for my tests now this is working.
Cypress.Commands.add('checkPosition',
{prevSubject: true},
(subject, start, delta = {dx:0}) => {
cy.wait(75, {log:false}).then(function () {
const deltaValue = delta.dx || delta.dy
const measurePoint = measurePoint || (delta.dx ? 'pageX' : 'pageY')
const current = getClientRect(subject[0])[measurePoint]
const expected = start[measurePoint] + deltaValue
expect(current).to.be.closeTo(expected, variance)
})
}
)
let start;
cy.get(divider)
.then(subject => start = getClientRect(subject[0]))
.realMouseDown({position:'center'})
.then($el => {
cy.wrap($el, {log:false})
.trigger('mousemove', { pageX: start.pageX +20 })
.checkPosition(start, {dx:20})
.trigger('mousemove', { pageX: start.pageX +40 })
.checkPosition(start, {dx:40})
// more steps as required
.realMouseUp()
.checkPosition(start, {dx:100})
})
You can do x or y movements in the test, my divider is either horizontal or vertical (can it be anything else?)
The calculation on position isn't exact, so I've added close.to
assertion in /cypress/support/e2e.js
.
const closeTo = (_chai, utils) => {
function assertIscloseTo(expected, delta, msg) {
msg = msg || utils.flag(this, 'message')
msg = msg ? `${msg}: ` : ''
_chai.assert(
Math.abs(this._obj - expected) <= delta
, msg + 'expected ' + this._obj + ' to be close to ' + expected + ' +/- ' + delta
, msg + 'expected ' + this._obj + ' not to be close to ' + expected + ' +/- ' + delta
)
}
_chai.Assertion.addMethod('closeTo', assertIscloseTo)
}
chai.use(closeTo)
getClientRect()
This is just to provide some rounding on the native getBoundingClientRect()
function.
I also added centerX
and centerY
calc as it is sometimes useful to vary the mousedown location, if the React app records it's start position from the mousedown event.
function getClientRect(el) {
const bb = el.getBoundingClientRect()
return {
top: Math.round(bb.top),
bottom: Math.round(bb.bottom),
left: Math.round(bb.left),
right: Math.round(bb.right),
height: Math.round(bb.height),
width: Math.round(bb.width),
x: Math.round(bb.x),
y: Math.round(bb.y),
centerX: Math.round(bb.left + (bb.width/2)),
centerY: Math.round(bb.top + (bb.height/2)),
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.