I have tried various options, but have been unable to simulate a mouse click to drag an element from one position to another in a browser using Selenium. When the test runs, I see the element get selected, but it does not move to the specified drop point. Any advice on how to test drag & drop using Selenium is immensely appreciated!
React: v16.4.2
react-beautiful-dnd: v10.0.0
Issue observed across multiple browsers: Chrome (v71.0), Firefox (v64.0.2), Edge (v42)
Here's how I defined the function in my latest attempt (variations on this theme also tried and failed):
private void dragAndDrop(WebElement dragPoint, WebElement dropPoint, WebDriver driver) {
Actions builder = new Actions(driver);
builder.clickAndHold(dragPoint).perform();
builder.pause(Duration.ofSeconds(1));
builder.moveByOffset(10,0).perform();
builder.moveToElement(dropPoint).perform();
builder.moveByOffset(10,0).perform();
builder.pause(Duration.ofSeconds(1));
builder.release();
builder.build();
builder.perform();
}
Also tried the following (same result):
private void dragAndDrop(WebElement dragPoint, WebElement dropPoint, WebDriver driver) {
Actions builder = new Actions(driver);
Action dragAndDrop = builder.dragAndDrop(dragPoint, dropPoint).build();
dragAndDrop.perform();
}
In the test, the 2 elements are identified uniquely using xpath and the function is called:
WebElement dragPoint = driver.findElement(By.xpath(".../div[3]/...(etc.)/div[@class='rst__moveHandle']"));
WebElement dropPoint = driver.findElement(By.xpath(".../div[5]/...(etc.)/div[@class='rst__moveHandle']"));
dragAndDrop(dragPoint, dropPoint, driver);
Relevant libraries:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Action;
import org.openqa.selenium.interactions.Actions;
So I just implemented this in our Ruby framework that sits on top of Selenium.
Here's what it looks like:
def drag_and_drop_to(destination)
target = self
# target and destination are Selenium::WebDriver::Elements in this case
selenium_actions(target, destination) do |target, destination|
# react-beautiful-dnd looks for a click, hold, and small movement to initiate a drag event
click_and_hold(target)
move_by(0, -5)
move_to(destination) # now that the drag has started, move to your destination
release # drop the target at it's destination
end
sleep 1 # allow for a rerender
end
The main learnings from trying to get this to work was:
release, our test runner was running assertions before the DOM had a chance to update leading to false negatives@MikaelCarpenter Yes, thank you! That worked for one aspect of the app that renders tables where rows can be dragged & dropped. Here's how the Java method ended up:
private void dragAndDrop(WebElement dragPoint, WebElement dropPoint, WebDriver driver) {
new Actions(driver)
.clickAndHold(dragPoint)
.moveByOffset(-10, 0)
.moveToElement(dropPoint)
.release()
.perform();
}
But, another section of the app renders nodes in a resource tree structure where each node is draggable. In this case, the above method does NOT work. I have not yet found a workable solution for this problem using Selenium, but I did find an alternative workaround using the UiPath Studio tool.
@MikaelCarpenter thanks for the solution, I was planning to raise a ticket for the same, Thank god I found you 馃憤
@OP - Even I had the same issue - Selenium was not able to drag drop objects,
Moving element slightly and then performing a drag operation worked.
````
Actions actions = new Actions(driver);
actions
.clickAndHold(iataCard)
.moveByOffset(0, 10)
.moveToElement(cityCard, 0, -10)
.release().build().perform();
``````
Below is a code which I performed on their template
`````
System.setProperty("webdriver.chrome.driver", "chromedriver");
WebDriver driver = new ChromeDriver();
driver.get("https://react-beautiful-dnd.netlify.com/iframe.html?selectedKind=single%20vertical%20list&selectedStory=basic");
TimeUnit.SECONDS.sleep(3);
WebElement source = driver.findElement(By.xpath("//[text()='Sometimes life is scary and dark']"));
WebElement target = driver.findElement(By.xpath("//[text()='Sucking at something is the first step towards being sorta good at something.']"));
Actions actions = new Actions(driver);
actions.clickAndHold(source).moveByOffset(0, 100).moveToElement(target, 0, 100).release().build().perform();
`````
For those looking in the future, here is how we do it using cypress.io:
https://github.com/atlassian/react-beautiful-dnd/blob/master/cypress/integration/reorder.spec.js
Please reopen if you think there is more to answer on this one
@MikaelCarpenter thanks! Your solution worked for me with a modification. My scenario was:
Adding this second item was the only way I could get the second list to update and actually include the first item. Sleeps and pauses didn't work
Not ideal at all, but was a temporary workaround for me... I'm hoping there's a better way to resolve this
Most helpful comment
So I just implemented this in our Ruby framework that sits on top of Selenium.
Here's what it looks like:
The main learnings from trying to get this to work was:
release, our test runner was running assertions before the DOM had a chance to update leading to false negatives