4teamwork / cypress-drag-drop Goto Github PK
View Code? Open in Web Editor NEWA cypress child command for drag'n'drop support.
License: GNU General Public License v3.0
A cypress child command for drag'n'drop support.
License: GNU General Public License v3.0
I can use cy.get(...).drag but not cy.get(...).move, am i missing something ?
I use it like this :
cy.get(".titleBlock").move("center");
Ex: element is covered, we want to force:true the drag event. How do we do it?
I need to drag and drop the element which are inside the shadow DOM
drop is just string here , means we can provide only a string
cy.get('swaplist').shadow().get('.swaplist__content').drag('.list-style2__drop-indicator-end')
I've tried many workaround to make drag and drop work with Cypress (ie your drag and drop plugin also) but the only working solution is here : https://stackoverflow.com/questions/55361499/how-to-implement-drag-and-drop-in-cypress-test see @bkucera solution.
Maybe it's a good idea to integrate his solution in this plugin ?
Is it possible to add an implementation of a drag and drop function for fixtures (files/images/etc)?
Because right now it's available only for elements (due to README)
Implementation like:
const fileName = 'fileName.png';
cy.fixture(`${fileName}`).then(
picture => {
picture.drop('.photo-dropzone');
})
);
In free time I can try to do PR with function
Thanks you very much.
I am getting below error :
TypeError: Cannot read property 'getBoundingClientRect' of undefined
at Context.drag (https://www.seleniumeasy.com/__cypress/tests?p=src/support/index.ts:355:28)
The test is as simple as
cy.visit('https://www.seleniumeasy.com/test/drag-and-drop-demo.html');
cy.get('#todrag>span:nth-child(2)').drag('#mydropzone');
I have installed the node module and have added import '@4tw/cypress-drag-drop'
in command.ts
file.
I am using drag and drop on my project where in cypress version 8.4 drag and drop was working but when I updated it 9.1.0 it stopped working.
Can you please help me with it?
Thank You.
https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#dragend
Once the drag is complete, a dragend event is fired at the source of the drag (the same element that received the dragstart event
...
After the dragend event has finished propagating, the drag and drop operation is complete.
So after this.target.drop
Lines 35 to 36 in ef2f133
this.source.trigger('dragend',
with screenX
and screenY
of drop
Hey guys, I've updated using yarn to version 2.1.0 and the .drag command stop working. I change it back to version 2.0.0 and it is working again.
I couldn't check what's wrong with the new version, but hope this issue warns other people.
My test code:
cy.get(`[abc="val"]`)..drag(`#def`, {
position: "center",
force: true,
})
Drag and drop failed in Chrome (Version 89.0.4389.114 (Official Build) (x86_64))
Analysis:
I made to print clientX/Y on dragstart, dragover and drop calls:
dragstart({ clientX, clientY } = {}) {
cy.log("dragstart", clientX+', '+clientY)
return cy
.wrap(this.source)
.trigger('pointerdown', {
which: 1,
button: 0,
clientX,
clientY,
eventConstructor: 'PointerEvent',
...this.options,
})
.trigger('mousedown', {
which: 1,
button: 0,
clientX,
clientY,
eventConstructor: 'MouseEvent',
...this.options,
})
.trigger('dragstart', { dataTransfer, eventConstructor: 'DragEvent', ...this.options })
},
As shown below, "undefined" were passed.
It appears MouseEvent constructor doesn't allow undefined coordinator values. And drag-and-drop failed. The valid clientX/Y need to be passed.
Workaround:
Is there a way to apply the d&d for angular components?
The project I am testing is using Vue Draggable - which may be the issue, as I know others have had problems getting drag and drop with Cypress to work reliably with that module.
To keep it simple I'll show you the line of code that is working and one that isn't:
Working code:
cy.get('.tools-drag-panel:nth-child(${startElement})').drag('.tools-drag-panel:nth-child(${targetElement})')
Broken code:
cy.get('.tools-drag-panel div').eq(startElement-1).drag('.tools-drag-panel:nth-child(${targetElement})')
In both of these example startElement and targetElement are in a list of draggable elements which are being referred to by their numbered position, e.g. 'Drag the element in position 4 to position 8'
Similarly if the eq() methods are replaced with .first() or .last() to get the first or last element the selector might refer to, drag and drop do not work either. In the above examples eq, first and last were used as the get() method was returning an array of elements.
Thanks for this plugin! Any chance we can get support for vue-draggable like this PR is attempting to do (but hasn't gotten much traction in the cypress repo) cypress-io/cypress-example-recipes#204. Thanks!
Sometimes, this plugin never triggers an actual drag. I can't quite pinpoint the cause for this, but it seems to happen to me on a component which resizes when its dragged.
In any case, I looked through the code, and noticed that there's no assurance that the dragover event is ever called. I saw that this is b/c the dragover code is recursively called. However, as in my case, you may hit a stopping condition before even trying to dragover.
I wrote #47 to address this issue.
you have done a good job , but i wish if the position was in pixels , i mean if we have a syntaxe like this
describe('Dragtest', () => {
it('should dragndrop', () => {
cy.visit('/yourpage');
cy.get('.sourceitem').drag({bottom:'10px',left:'200px'});
});
});
Currently, I'm using this plug-in and it works fine, if there's no iframe.
Consider that my drag and drop elements are inside an iframe, then how can I use it, please guide me here.
@bierik
Thank you.
For TS users it will be useful. Now, if you use Cypress with TS you'll get this error:
Property 'drag' does not exist on type 'Chainable<JQuery<HTMLAnchorElement>>'
To enable dragging, an element must have a draggable
attribute set to true
. It is possible to set this attribute in a mouseenter
handler (alongside other functions such as css changes.) Perhaps due to the lack of support for hover
functionality in Cypress, this plugin does not emit mouseenter
, forcing changes to code to enable dnd tests.
mouseenter
handler to an undraggable elementdraggable
attribute of the element to true
source
source
element becomes draggable, is dragged successfully, unicorns, and rainbows.source
element is not dragged, causing test to failI was able to substitute my logic in mousedown
and mouseup
handlers temporarily, and successfully tested as such. However this is an insufficient solution, and serves more to illustrate the limitation of this plugin rather than a suitable alternative.
We have elements that are sensitive to where the mouse down occurs within the element. It would be nice to do the mouse down with more control (pixel offset, or position as in the drag input).
AFAIK drag
command is returning a Chainable<true>
too, I just tested it by running
cy.wrap('.source')
.drag(`.target`)
.should(() => {
// This works, you can create assertions here
});
Also, the second definition generic parameter isn't actually used and can be removed
This
Lines 15 to 17 in 4821da6
should become
drag<K extends keyof HTMLElementTagNameMap>(targetSelector: K, options?: Options): Chainable<true>
drag(targetSelectorOrAlias: string, options?: Options): Chainable<true>
Even better if
Line 134 in 4821da6
sourceWrapper
variable, so the return type of drag
command would be Chainable<Element>
as move
does
On another note, adding import '@4tw/cypress-drag-drop'
already instruct TS to pick up this package types, you don't need to tamper with tsconfig.json
at all
please allow cy.xpath to be the source
//step cy.xpath(openBalanceInactiveColumnHandle).drag(amountsActiveColumnHandle);
// error Syntax error, unrecognized expression: //div[contains(./@id, "active__field-row") and text() = ' openBalance, totalDue '];
I have made a change in index.js
if (isAttached(this.targetElement)) {
this.target
.trigger('mouseup', {
force: true, //i have added this line
which: 1,
button: 0,
but it is not reflecting in run time
I have a table of rows, I want to drag the first one and and drop it below all the others.
I have the following code
cy.get('.search__table .search__table-row:first-child .drag-row')
.move({ y: 500 });
When this code is executed, the drag-now
element's ondragstart
is fired. After that, the element is being dragged and moving on top of the final line, which fires ondragover
event. This event does nothing, it just prevent's the default event from happening, which allows me to drop items on top of the row. It also has ondragenter
event listener, which saves the location of the current drag'n drop process. In the end, the ondragend
event of the .drag-now
element is expected to fired.
However, the dragging fails mysteriously:
Exceeded maximum tries of: 5, aborting
dragover @ index.js:107
EDIT: I'm not sure if this is the reason but I noticed that the library does not trigger ondragenter
event at all.
What about dragging a non-DOM element, for example a dot drawn on the canvas? Same events, mousedown at a particular point, mousemove, mouseup, however no DOM element.
If you review the documentation for the trigger command, the options that can be passed in include coordinates from the top, left corner of the subject element where the pointer/mouse is located when the down/up/move/etc action is performed.
https://docs.cypress.io/api/commands/trigger.html#Coordinates
The drag being called on the row in the relative location of the drag handle:
cy.get(studyAct.studyactmillercontainer) // container for all of the rows in the miller column .should('be.visible') .find(studyAct.studyactmillerrow) // gets a list of all of the rows in the container .then($rows => { cy.wrap($rows).last().as('there') // alias for the last row in the list of rows cy.wrap($rows) .contains(studyAct.studyactmillerrow, 'Adverse Events') // gets a specific row based on the label text .focus() // 28, 18 is the relative location of the center of the reorder-icon that is the handle used to trigger the drag for the row element; it must be clicked to drag the row element. when using the .find('.reorder-icon') for the .drag command, the parent row is not moved .drag('@there', 28, 18, { force: true }) .wait('@graphql') // this request is not triggered cy.get('.v-progress-linear.loader').should('not.be.visible') })
The drag being called on the drag handle:
cy.get(studyAct.studyactmillercontainer) .should('be.visible') .find(studyAct.studyactmillerrow) .then($rows => { cy.wrap($rows).filter(':visible').last().as('there') cy.wrap($rows) .contains(studyAct.studyactmillerrow, 'Adverse Events') .focus() .find('.reorder-icon') .drag('@there', { force: true }) .wait('@graphql') cy.get('.v-progress-linear.loader').should('not.be.visible') })
There should be an object, and documentation on the use of the object. for passing in x,y coordinates for the trigger commands to use on triggering mouse/pointer ON a location. There should also be a separate object for use in moving TO a specific location.
Does this work with Cypress 5.6.0?
I installed the latest package and after installing it I get an error that it no longer recognized cy.
Hello everyone!
I use a lib dragula in my project and I'm trying to test it by cypress-drag-drop but it doesn't work.
Could you help me with it, how to make it works?
Thanks!
I am trying to move an element to specific coordinates and its not working. Is this an issue from plugin? Or does this work well for any scenario?
My commands.ts
is a typescript file.
When I add the line require('cypress-drag-drop');
, I get this error:
Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.ts(2580)
How can I solve this problem?
I read about the commits that you made about the force : true, but still even though the elements were being found, no action was performed, they remained where they were....
Hello,
I face some difficulties using this plugin since it is not emitting the dragend event after the drop event is executed.
I have some code that is using the dragend event and therefore my tests are not properly working. Is there any reasons why it is not part of current implementation or will you consider adding ?
Thanks,
Thibault
Hi team,
Code Snippet:
it('using npm package', () => {
cy.visit(`https://testautomationpractice.blogspot.com/`)
cy.get('div#draggable').drag('div#droppable')
});
Error:
Timed out retrying after 10000ms: cy.trigger() failed because this element:
is being covered by another element:
I've been trying for 2 days to get cypress to do pointer down, moves, and up in order to simulate a user selecting multiple items on an open layers map. I was hoping this would be the silver bullet but I'm guessing true drag/drop needs to deliver a payload to the drop zone where as my situation does not.
Do you have any thoughts on how DragSimulator could be modified to do a "simple" bounding box technique?
@bierik / @Sauloxd - we are relying on this package, and it seems that it was updated recently to support other peer versions of Cypress, but the version on npm still seems to be 1.4.0
.
Could you publish this package?
This is causing errors for us:
cypress-drag-drop/package.json
Line 48 in 089669c
Thank you for writing and maintaining this!
Hi,
I tried the new child command move.
Nevertheless, this command is not effective.
Have you a hint on why the command is not working ?
describe("Separator Test", function(){
it("should pass", function(){
cy.visit('http://localhost:8080');
cy.get('div.separator').as('separator');
cy.get('@separator').move({ x: 100, y: 100 }, {force:true})
})
})
My goal is to move the vertical separator between the two panes 100px to the right.
Trying to add a test for an app which uses react-dnd and in my case drop target
node is removed from the DOM after the drop
event is triggered.
At the time mouseup
is triggered the node is no longer in the DOM and cypress
returns an error.
CypressError: cy.trigger() failed because this element is detached from the DOM.
As I understand some implementations of DnD could listen for the drop
event, some - for mouseup
event and some for both.
According to the cypress docs on conditional testing we can not implement a condition logic to checks if drop target
node still exists in the DOM before triggering mouseup
because it has been removed from the DOM asynchronously.
Can we update the command so it accepts another parameter dropEvents
(with default value ["drop"]
) so a user can define specific event(s) to trigger?
On a separate note, not sure we need it to be an array.
If the proposed solution looks reasonable I can create a PR.
Full error:
CypressError: cy.trigger() failed because this element is detached from the DOM.
<div class="EmptyBlock_block__2auyt" data-cy="empty-block-placeholder" draggable="true"></div>
Cypress requires elements to be attached in the DOM to interact with them.
The previous command that ran was:
> cy.trigger()
This DOM element likely became detached somewhere between the previous and current command.
Common situations why this happens:
- Your JS framework re-rendered asynchronously
- Your app code reacted to an event firing and removed the element
You typically need to re-query for the element or add 'guards' which delay Cypress from running new commands.
https://on.cypress.io/element-has-detached-from-dom
All 3 subject validations failed on this subject.
I get this error when running
npm install --save-dev @4tw/cypress-drag-drop
Could not resolve dependency:
npm ERR! peer cypress@"^2.1.0 || ^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" from @4tw/[email protected]
Looks like the update was made but not published
as of 7/20/2021
cypress is now on version 8!
I am seeing issues with "mouseup" when trying to execute multiple tests together. In my scenario i have 2 Columns and wanted to drag and drop components 2 different columns or in same column (either way). 1st test passed during 2nd test it failed while executing "mouseup". I can see the component has been added in Column but trigger event has failed.
Can you please suggest why running multiple tests same time failed? What changes we need to do?
Code Snippet
it(' "Button" Component added to Canvas', () => {
cy.get('[data-cy-test="sidebar-library-basic"] [data-cy-test="button"]')
.drag(`${Column_1}`);
cy.get('button.toolbar__save-button').click();
cy.get('#f-root-content button').should('be.visible');
});
it(' "streetAutocomplete" Component added to Canvas', () => {
cy.get('[data-cy-test="sidebar-library-components"] [data-cy-test="streetAutocomplete"]')
.drag(`${Column_2}`);
cy.get('button.toolbar__save-button').click();
cy.get('#f-root-content div label')
.should('have.class', 'nexus-label--has-textfield');
});
I am getting the following error when the dragstart method is called
Uncaught TypeError: Cannot read property 'types' of undefined
This error originated from your application code, not from Cypress.
When Cypress detects uncaught errors originating from your application it will automatically fail the current test.
This behavior is configurable, and you can choose to turn this off by listening to the 'uncaught:exception' event.
https://on.cypress.io/uncaught-exception-from-application
I have the require('cypress-drag-drop) in my command.js file. I am not sure how else to debug this error. Thoughts? I am using Cypress 3.2 and Chrome version 73.
It looks like the
.drag($draggedTo, {
target: { position: 'bottomLeft' },
});
does not work currently as the code eg: here has to be adapted to the latest trigger api as in here
A sample fix would look like
this.target
.trigger('drop', this.options.target.position, {
dataTransfer,
eventConstructor: 'DragEvent',
})
I would be interested in solving this issue with your help if that works.
Also alongside, the target is typed wrong, as currently its as defined below
type Options = Partial<Cypress.ClickOptions & {
source: Cypress.ClickOptions
target: Cypress.ClickOptions
}>
Hi there,
Thanks so much for creating this awesome library. I'm currently struggling to do some basic drag and dropping and would really appreciate it if someone could point me in the right direction.
I simply want to drag an element to a target destination. However, the issue is the target destination is not rendered on the screen until the dragging begins. Therefore I get an error when doing cy.get('#myDragElement').drag('#target')
that the target element could not be found.
Is there any way within this library that I can trigger the drag event and wait for the element to appear on the screen before dropping it? What's the best way to handle this? Thanks!
Great project.
Are you planning to support Cypress 9? I'm downgrading by now just because I love this library.
npm ERR! Found: [email protected]
npm ERR! node_modules/cypress
npm ERR! dev cypress@"^9.0.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer cypress@"^2.1.0 || ^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" from @4tw/[email protected]
When executing a test of dnd, the plugin fails to emit dragenter
and dragleave
events, limiting related functionality to conditional logic with state awareness in a dragover
handler. This is particularly annoying when modifying styles amongst several potential drop targets.
dragenter
or dragleave
event handler to the drag target elementI want to copy the left column to the right, but it doesn't take effect. If only the left column is sorted, it is fine.
https://codesandbox.io/embed/strange-lovelace-8296e?fontsize=14&hidenavigation=1&theme=dark
import React, { useState } from 'react';
import { ReactSortable } from 'react-sortablejs';
export default () => {
const [list1, setList1] = useState([
{ id: 1, name: '11' },
{ id: 2, name: '22' },
]);
const [list2, setList2] = useState([
{ id: 3, name: '33' },
{ id: 4, name: '44' },
]);
return (
<div style={{ display: 'flex' }}>
<ReactSortable
list={list1}
setList={setList1}
animation={150}
group={{ name: 'cloning-group-name', pull: 'clone' }}
>
{list1.map(item => (
<div key={item.id}>{item.name}</div>
))}
</ReactSortable>{' '}
<ReactSortable
list={list2}
setList={setList2}
animation={150}
group={{ name: 'cloning-group-name', pull: 'clone' }}
>
{list2.map(item => (
<div key={item.id}>{item.name}</div>
))}
</ReactSortable>
</div>
);
};
This is OK:
cy.contains('22').then(test => {
cy.contains('11').drag(test);
});
This is not OK:
cy.contains('33').then(test => {
cy.contains('11').drag(test);
});
i wish if there were docs that explain to us how to setup this lib with cypress
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.