-
-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add cy.realDnd command #17
base: main
Are you sure you want to change the base?
Conversation
I would love to get this landed - anything in particular that I could help with? |
I stopped in the implementation because it has some underlying problems with pupeteer itself. Just 3 actions touch -> touchMove -> touchEnd don't behave as drag and drop for some reason. But if you will find a solution that would be perfect! |
I didn't yet have time to look into this yet - it seems that you have been testing this with native In our app, we are implementing drag & drop in a custom way, using pointer events, and a solution similar to yours works just OK for us: Custom `cy.drag` commandimport { fireCdpCommand } from 'cypress-real-events/fireCdpCommand';
import { getCypressElementCoordinates } from 'cypress-real-events/getCypressElementCoordinates';
type Point = { x: number; y: number };
const clamp = (v: number, min: number, max: number) =>
Math.min(Math.max(v, min), max);
const getDirection = (start: number, end: number) => {
switch (true) {
case end > start:
return 1;
case end < start:
return -1;
default:
return 0;
}
};
export const drag = (
subject: JQuery<HTMLElement>,
options: { target: () => Cypress.Chainable<JQuery<HTMLElement>> },
) => {
const { target } = options;
const sourceCoordinates = getCypressElementCoordinates(subject, 'center');
cy.wrap(subject).realMouseDown();
return target()
.then(async ($target) => {
const targetCoordinates = getCypressElementCoordinates($target, 'center');
const direction = {
x: getDirection(sourceCoordinates.x, targetCoordinates.x),
y: getDirection(sourceCoordinates.y, targetCoordinates.y),
};
const clampPoint = (point: Point): Point => ({
x: clamp(point.x, sourceCoordinates.x, targetCoordinates.x),
y: clamp(point.y, sourceCoordinates.y, targetCoordinates.y),
});
// just fire a single pointermove event very close to ther source point
await fireCdpCommand('Input.dispatchMouseEvent', {
type: 'mouseMoved',
button: 'left',
pointerType: 'mouse',
...clampPoint({
x: sourceCoordinates.x + direction.x * 1,
y: sourceCoordinates.y + direction.y * 1,
}),
});
let nextPoint = { ...sourceCoordinates };
while (true) {
// this doesn't move in a straight line at the moment but the movement line shouldn't matter for most of our scenarios
// we just progress at each axis with a 10px step until we reach the target point on a given axis
// when target points are met on both axes then we exit the "movement" phase
nextPoint = clampPoint({
x: nextPoint.x + direction.x * 10,
y: nextPoint.y + direction.y * 10,
});
if (
nextPoint.x === targetCoordinates.x &&
nextPoint.y === targetCoordinates.y
) {
break;
}
await fireCdpCommand('Input.dispatchMouseEvent', {
type: 'mouseMoved',
button: 'left',
pointerType: 'mouse',
...nextPoint,
});
}
return $target;
})
.then(($target) => {
cy.wrap($target).realMouseUp();
return $target;
});
}; So maybe even if this doesn't work for I see that there is an experimental |
Yes please! Or can we have a |
Hey @dmtrKovalenko ! Please let me know if there's anything I can help with on this one or with realMouseMove ! |
@drecali any interest in picking this up? I see you're contributing to |
Closes #11