cypress-example-recipes icon indicating copy to clipboard operation
cypress-example-recipes copied to clipboard

Example of drag and drop to element

Open CreatedBySeb opened this issue 7 years ago • 20 comments
trafficstars

I think it would make sense to have a third example in the drag and drop recipe which shows how straightforward it is in Cypress to drag one element to another. A colleague of mine was trying to figure this out for a while, before I noticed that you could just use something like this:

cy.get(".drag-handle")
    .trigger("mousedown", { which: 1 })

cy.get(".drag-target")
    .trigger("mousemove")
    .trigger("mouseup")

Drag and drop that is this straightforward to use is a massive advantage of Cypress compared to other testing frameworks, so it would make sense to have this information more readily available in the recipe for people using Cypress with a mindset from a less intuitive framework.

CreatedBySeb avatar Jul 25 '18 13:07 CreatedBySeb

I wasn't sure if I that was addressed to me or a maintainer, but if it's addressed to me sure thing.

CreatedBySeb avatar Jul 30 '18 08:07 CreatedBySeb

I just used this method, and it works without a hitch. Definitely should be in the guide.

freedomflyer avatar Dec 18 '18 19:12 freedomflyer

Yes, this is open to be picked up by anyone to add to the docs. 🙌

jennifer-shehane avatar Dec 19 '18 02:12 jennifer-shehane

I tried to make a PR here: https://github.com/cypress-io/cypress-example-recipes/pull/221

but unfortunately the test fails (no balls are dropped into the hoop)

alfonsocheng avatar Jan 11 '19 06:01 alfonsocheng

Also, this doesn't seem to work when using react-dnd (7.0.2). Someone posted a workaround here: https://github.com/cypress-io/cypress/issues/1752 which won't work for me either :-(

Kadrian avatar Mar 04 '19 16:03 Kadrian

I think it would make sense to have a third example in the drag and drop recipe which shows how straightforward it is in Cypress to drag one element to another. A colleague of mine was trying to figure this out for a while, before I noticed that you could just use something like this:

cy.get(".drag-handle")
    .trigger("mousedown", { which: 1 })

cy.get(".drag-target")
    .trigger("mousemove")
    .trigger("mouseup")

Drag and drop that is this straightforward to use is a massive advantage of Cypress compared to other testing frameworks, so it would make sense to have this information more readily available in the recipe for people using Cypress with a mindset from a less intuitive framework.

I have tried this approach with absolutely no effect whatsoever.

hellfireSteve avatar Mar 22 '19 15:03 hellfireSteve

I have just tried it and works perfectly.. (cypress 3.2.0)

gor181 avatar May 09 '19 07:05 gor181

@Kadrian I'm facing the same problem, did you got any solution??

fboechats avatar Oct 01 '19 19:10 fboechats

how do we drag a CSV file and drop it the application?

BavithraDuraisamy avatar Oct 18 '19 09:10 BavithraDuraisamy

What worked for me is to change which : 1 to button: 0. Not sure if there is anything specific to my application (it's dependency on jQuery). Thanks to the great docs by cypress.

cy.get(`source-element-to-be-dragged`)
   .trigger("mousedown", { button: 0 }); // <-- was not working when using which : 1 
cy.wait(500); //not a fan of arbitrary waiting, but this is giving a smooth transition to the drag-and-drop action
cy.get(`target-element-to-drop`)
   .trigger("mousemove")
   .trigger('mouseleave');  // <-- have issues with mouseup. Hence using mouseleave + a dummy action below to finish the drop event.
// Important: Since mouse leave is not a complete mouse event, had to do some other dummy click to complete the drop part.
cy.get('some-other-dummy-element-outside-the-grid').click();

@fboechats, @Kadrian , @hellfireSteve I invite you to try this and let me know how it goes.

pravynandas avatar Feb 13 '20 17:02 pravynandas

Can it done using x,y index of screen instead of target element? Just a thought, it would be more useful.

Saharshdeep avatar Apr 02 '20 09:04 Saharshdeep

Here's my solution. Use button 0, not 1, Force every click, don't forget to click on the target element before mouseup. This will work for some not for others but I hope it helps!

cy.visit("/your-page");
    cy.get("yourSelector")
      .trigger("mousedown", { button: 0 }, { force: true })
      .trigger("mousemove", 200, -200, { force: true })
    cy.get("yourTargetForDrop").click()
      .trigger("mouseup", { force: true });

josephgroark avatar Apr 15 '20 12:04 josephgroark

These guys https://github.com/4teamwork/cypress-drag-drop literally trigger drag-n-drop stuff. The only that works for my project

askirmas avatar May 06 '20 22:05 askirmas

@josephgroark quick question, why do you have to do this?

don't forget to click on the target element before mouseup.

It does seem necessary, but it doesn't make any intuitive sense to me because a real user wouldn't click before releasing the mouse button.

vicatcu avatar May 18 '20 16:05 vicatcu

For me, doing drag and drop with react-dnd, neither this recipe or the @4tw/cypress-drag-drop plugin was working.

My case was dragging the first element of a list down two places, reordering the list. What ended up solving my case was this

cy.get(".list__first-item")
  .trigger("dragstart")
  .trigger("dragleave");

cy.get(".list__third-item")
  .trigger("dragenter")
  .trigger("dragover")
  .trigger("drop")
  .trigger("dragend");

mikaelrss avatar May 29 '20 10:05 mikaelrss

Getting drag and drop to work in a test requires we reproduce the mouse events that the component is expecting.

As mentioned in https://github.com/cypress-io/cypress/issues/845, this can be quite difficult if you don't know the underlying code, and is why there isn't one solution that works for everything.

For me, the only solution that worked with an older version of jQuery UI draggable items was:

  cy.get('.drag-handle')
    .click()
    .trigger("mousedown", { which: 1, pageX: 0, pageY: 0 });

  cy.get(".drag-target")
    .trigger("mousemove", 50, 0)
    .trigger("mouseup");

dmacfarlane avatar Jun 24 '20 22:06 dmacfarlane

This is my solution:

 cy.get('@AssetClass')
      .trigger("mousedown", { button: 0 }); // <-- was not working when using which : 1 
 cy.get('@dropZone')
      .trigger("mousemove") // optional
      .click({force: true}); // The dropzone seems to be not visible for Cypress

The .click() command is really important to use it.

gfilomena avatar Sep 17 '20 11:09 gfilomena

My solution for a custom command with Typescript testing an Angular app, based on pravynandas post:

declare namespace Cypress {
  interface Chainable {
    /**
     * Custom command to drag an element onto antother one
     * @param targetElement The target element to drop the element on, or a selector to pick an element
     */
    dragTo(targetElement: Cypress.Chainable<JQuery<HTMLElement>> | string): void;
  }
}

Cypress.Commands.add(
  'dragTo',
  {
    prevSubject: 'element',
  },
  function (
    subject: JQuery,
    targetElement: Cypress.Chainable<JQuery<HTMLElement>> | string
  ) {
    if (typeof targetElement == 'string') {
      cy.wrap(subject).should('have.attr', 'cdkdrag'); // angular specific, optional check
      cy.get(targetElement).should('have.attr', 'cdkdroplist'); // angular specific, optional check

      cy.wrap(subject).trigger('mousedown', { button: 0 });
      cy.wait(500);
      cy.get(targetElement).trigger('mousemove').trigger('mouseleave');
      cy.get(targetElement).click().click();
    } else {
      cy.wrap(subject).should('have.attr', 'cdkdrag'); // angular specific, optional check
      targetElement.should('have.attr', 'cdkdroplist'); // angular specific, optional check

      cy.wrap(subject).trigger('mousedown', { button: 0 });
      cy.wait(500);
      targetElement.trigger('mousemove').trigger('mouseleave');
      targetElement.click().click();
    }
  }
);

m1212e avatar Jul 15 '21 11:07 m1212e

After many hours of trying combinations of the various solutions above...

I was able to find a solution for VueDraggable 2.24.3 with Cypress v7.7.0 -

cy.get('@from')
    .trigger('pointerdown', { button: 0 })
    .trigger('dragstart');
 cy.get('@to')
      .trigger('dragover')
      .trigger('drop');

lukeawillson avatar Sep 13 '21 23:09 lukeawillson

After many hours of trying combinations of the various solutions above...

I was able to find a solution for VueDraggable 2.24.3 with Cypress v7.7.0 -

cy.get('@from')
    .trigger('pointerdown', { button: 0 })
    .trigger('dragstart');
 cy.get('@to')
      .trigger('dragover')
      .trigger('drop');

Can confirm this works for Cypress v7.7.0 and if you are using django-admin-sortable2!

avelosa avatar Apr 30 '22 00:04 avelosa

This is my solution:

 cy.get('@AssetClass')
      .trigger("mousedown", { button: 0 }); // <-- was not working when using which : 1 
 cy.get('@dropZone')
      .trigger("mousemove") // optional
      .click({force: true}); // The dropzone seems to be not visible for Cypress

The .click() command is really important to use it.

This one works with Material CDK drag and drop. Thanks for sharing @gfilomena 👍

aleixsuau avatar Sep 22 '22 16:09 aleixsuau

.trigger('dragover')
      .trigger('drop')

You are a life savior!!! I can confirm this works on Vue with VueDraggableNext 2.1.1 and Cypress v12

dericlima avatar Mar 29 '23 07:03 dericlima