'Cypress can't drag a custom angular cdkDragHandle
I'm losing sanity over this one. I have one drag and drop list in my app with a custom drag handle and cypress seems to be unable to drag it. Manually when the user drags it, it works perfectly.
Here is the simple component:
<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
<div
class="example-box"
*ngFor="let movie of movies; let index = index"
cdkDrag
>
<div
class="example-handle"
cdkDragHandle
[attr.data-cy]="'custom-drag-handle-' + index"
>
<svg width="24px" fill="currentColor" viewBox="0 0 24 24">
<path
d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z"
></path>
<path d="M0 0h24v24H0z" fill="none"></path>
</svg>
</div>
{{ movie }}
</div>
</div>
Working stackblitz.
At first, I've tried this approach with cypress:
describe("Drag and drop", () => {
beforeEach(() => cy.visit("/"));
it("should drag the first item", () => {
cy.get("[data-cy=custom-drag-handle-0]")
.trigger("mousedown")
.trigger("mousemove", {x: 0, y: 0})
.trigger("mousemove", {x: 0, y: 230})
.trigger("mouseup", {x: 0, y: 230});
});
});
In this case the cy stops and errors out on the .trigger("mousemove", {x: 0, y: 230})
step with the following error:
Timed out retrying after 4000ms: cy.trigger() failed because this element:
<div cdkdrag="" class="cdk-drag example-box ng-star-inserted" data-cy="custom-drag-handle-0" style="">...</div>
is being covered by another element:
<div cdkdrag="" class="cdk-drag example-box ng-star-inserted" data-cy="custom-drag-handle-3" style="">...</div>
Fix this problem, or use {force: true} to disable error checking.Learn more
I wasn't able to figure out why does the 4th element cover the dragged one.
The second approach I've tried was from this SO post. According to this post, the solution is to query the dragged element via the jQuery selector and to dispatch a MouseEvent. So I did exactly that:
describe("Drag and drop", () => {
beforeEach(() => cy.visit("/"));
it("should drag the first item", () => {
cy.get("[data-cy=custom-drag-handle-0]").then(() => {
const draggable = Cypress.$("[data-cy=custom-drag-handle-0]")[0];
draggable.dispatchEvent(new MouseEvent("mousedown"));
draggable.dispatchEvent(
new MouseEvent("mousemove", {
clientX: 235,
clientY: 124,
})
);
draggable.dispatchEvent(
new MouseEvent("mousemove", {
clientX: 92,
clientY: 440,
})
);
draggable.dispatchEvent(
new MouseEvent("mouseup", {
clientX: 92,
clientY: 440,
})
);
});
});
});
This time no errors, but the item wasn't dragged either. So I removed the custom handle to test it out. This time it worked, the item got dragged successfully, so it confirms that you have to dispatch Events explicitly, but it doesn't work when you have a custom handle. End this is where I got into a dead end.
Solution 1:[1]
You have to bubble up the event to the parent element, that contains the cdkDrag directive.
You can check this example in stackblitz: Programmatically drag and drop using Angular
In your cypress code, add bubbles property like this :
draggable.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
Note: For the last version of angular/components (v13.3.4), you have to add also buttons property with a value different than 0 (Values that you can use).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | anouarach |