Cypress: cy.drag() & cy.mouse proposal

Created on 31 Oct 2017  路  20Comments  路  Source: cypress-io/cypress

As mention in the #845 it would be interesting to have a broader API for drag'n drop and mouse movement.

Desired behavior

It's very hard to reproduce drag'n drop using native browser events. It's much simpler to simulate how the mouse would behave. Here is a drag'n drop assertion done on nightwatch.js

    let elementToMove = '//div[@class="column"][2]'
    browser
      .url('http://grafikart.github.io/ReorderJS/index.html')
      .useXpath()
      .waitForElementVisible(elementToMove, 1000)
      .moveToElement(elementToMove, 10, 10)
      .mouseButtonDown(0)
      .moveToElement('//div[@class="column"][1]', 10, 10)
      .mouseButtonUp(0)

The API behaves at a lower level where we can control how the mouse behave. It would be nice to have something to describe generic behaviours.

cy.drag(selector: string, position: topLeft|center|topRight...., x: number, y: number)
cy.drag(selector: string, x: number, y: number)
// Maybe
cy.drag(fromSelector: string, toSelector: string) 

// Or a low level api to control the mouse
cy.mouse.moveTo(selector: string)
cy.mouse.press(button = 0)
cy.mouse.moveTo(selector: string)
cy.mouse.release()
4锔忊儯 pkdriver proposal 馃挕 drag-and-drop feature

Most helpful comment

@jennifer-shehane I'm curious about contributing to this issue, if my company gives me the time to do so. Would you be open to that? Do you have an idea of approximately how long this would take to implement?

All 20 comments

Has there been any progress on implementing something like cy.drag(fromSelector: string, toSelector: string)? It would be fantastic if that feature were implemented!

No progress has been made on this proposal yet. We are currently working on other issues.

@jennifer-shehane I'm curious about contributing to this issue, if my company gives me the time to do so. Would you be open to that? Do you have an idea of approximately how long this would take to implement?

I'm surprised that it looks like @nwshane never got his answer after such offer! Is that really the case @jennifer-shehane ?

Hey @nwshane, sorry for such a late response. We do accept contributions.

The community must be mindful that outside contributions do not completely absolve our internal team of work. We still have to ensure the proposal is within scope, well tested, documented, and deployed.

We have not sat down to discuss the implementation of this particular feature and whether it is within scope, but will attempt to move it up our Roadmap if someone if willing to help contribute.

@jennifer-shehane Thanks, I appreciate the response. We're not using cypress at my company anymore, so I don't think I'll be able to tackle this issue after all. But I hope someone does!

Have a look at my package which implements a cypress drag'n'drop child command: https://www.npmjs.com/package/cypress-drag-drop
I tested it on a Vue app using https://github.com/SortableJS/Vue.Draggable

Have a look at my package which implements a cypress drag'n'drop child command: https://www.npmjs.com/package/cypress-drag-drop
I tested it on a Vue app using https://github.com/SortableJS/Vue.Draggable

Works like expected, thank you!

Hey @bierik, could you open a pull request to add you plugin to our documentation here?

hey!
this might be useful to you in implementing HTML5 dnd:
https://github.com/PowToon/html-dnd

Hi @jennifer-shehane! I am really struggling with a similar issue. I am not trying to drag&drop a file but pull a handle from a react data grid cell to fill a column with same values.

The handle element is draggable but since there is no file involved I assume we should be doing something like in cypress docs:

cy.get('.drag-handle')
  .trigger('mousedown', { which: 1 })
  .trigger('mousemove', { clientX: 410, clientY: 200 })
  .trigger('mouseup', { force: true });

Unfortunately this doesn't work. I think that the mousemove event is not getting triggered. i have tried many different ways following suggestions from other threads, including drag&drop related solutions. None of these show the mouse moving somewhere else.

version: "cypress": "3.3.1",
browser: chrome

Any help?

@asherccohen Checkout the cypress-drag-drop plugin -> https://github.com/4teamwork/cypress-drag-drop

hi
I am trying to drop an element to an iframe
does anyone have an idea how to realise it?
I tried almost every single solution on forums including the plugin and can't figure it out yet

@asherccohen Checkout the cypress-drag-drop plugin -> https://github.com/4teamwork/cypress-drag-drop

@bierik This plugin does not work.

any update on this....?

tried manny hours to work with a solution but can-t do anything it just doesn`t fire the move event ..

Dear great community, i investigated the drag and drop functionality and noticed that it doesnt drop to the targets position.
So when the cursor wants to drop it, it drops at the origin position where the element actual was.
Workaround is to tell cypress to set all 3 position properties to the new position ->>>
Like this for example :

js cy.get( selector ) .trigger('mousedown', { button: 0 }) .wait(1500) .trigger('mousemove', { clientX: 80, clientY: 90, screenX: 80, screenY: 90, pageX: 80, pageY: 90 }) .trigger('mouseup', { force: true });

I tried to set only on of them and it failed, tried only one property at a time.

IF you set ALL 3 properties, you will actual get this to work .

If the worked, i recommend cypress team to add this to their documentation.

I've had a good experience so far using cypress for automating tests for our application but really stuck here because none of the solutions I found is working. But this really decides whether we should go with cypress or not and also for dashboard services. Waiting for a resolution on this.
Thanks in advance.

I couldn't get the trigger() methods to work with Angular's drag and drop, but running dispatchEvent directly seemed to do the trick:

export function dragElement(sourceSelector: string, targetSelector: string) {
  return cy.get(targetSelector).then((targetElms) => {
    const targetRect = targetElms[0].getBoundingClientRect();

    return cy.get(sourceSelector).then((sourceElms) => {
      const sourceRect = sourceElms[0].getBoundingClientRect();

      sourceElms[0].dispatchEvent(new MouseEvent('mousedown'));
      sourceElms[0].dispatchEvent(new MouseEvent('mousemove', { clientX: sourceRect.x + 1, clientY: sourceRect.y + 1 }));
      sourceElms[0].dispatchEvent(new MouseEvent('mousemove', { clientX: targetRect.x + 1, clientY: targetRect.y + 1 }));
      sourceElms[0].dispatchEvent(new MouseEvent('mouseup'));
    });
  });
}

// in test:

    const tableRowsSelector = 'table.mat-table > tbody > tr';
    const columnTextSelector = '.mat-column-1';

    cy.get(tableRowsSelector)
      .get(columnTextSelector)
      .should((elms) => {
        expect(elms.toArray().map((elm) => elm.innerText)).to.deep.eq(['A', 'B']);
      });

    dragElement(tableRowsSelector + ':nth-child(1)', tableRowsSelector + ':nth-child(2)').then(() => {
      cy.get(tableRowsSelector)
        .get(columnTextSelector)
        .should((elms) => {
          expect(elms.toArray().map((elm) => elm.innerText)).to.deep.eq(['B', 'A']);
        });
    });

Needing two mousemove events may be angular specific

Should one wait for this issue to be resolved? Tried all the suggestions mentioned above - none of em worked for me!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

brian-mann picture brian-mann  路  101Comments

HugoGiraudel picture HugoGiraudel  路  97Comments

kamituel picture kamituel  路  66Comments

chrisbreiding picture chrisbreiding  路  114Comments

t-zander picture t-zander  路  125Comments