Actions.dragAndDropBy is not working as expected - java

I wrote following piece of code to move a draggable object on
https://jqueryui.com/draggable/
driver.get("https://jqueryui.com/draggable/");
WebElement eleFrame=driver.findElement(By.className("demo-frame"));
driver.switchTo().frame(eleFrame);
WebElement ele=driver.findElement(By.xpath("//*[#id='draggable']"));
Actions move=new Actions(driver);
move.dragAndDropBy(ele, 180, 300).release().build().perform();
This code does not move the object.
when i tried
move.clickAndHold(ele).moveByOffset(300, 100).release().build().perform();
it is working fine.I read the documnets it is saying dragAndropBy have internally same functionality as clickAndHold and then moving by some offset.
I have tested it before for both vertical/horizontal slider and it used to work fine.
Please suggest what is the problem with dragAndDropBy code. or some other functionality is actually expected out of it.
Any help will be much appreciated.

Actually it's pretty weird that move.clickAndHold(ele).moveByOffset(300, 100).release().build().perform(); is working for you... I've tried them both and they throw the same exception:
org.openqa.selenium.UnsupportedCommandException: moveto did not match a known command
However, there are open bugs in Selelnium and in geckodriver on this issue.
BTW, the only difference between the two is that you don't have the ButtonReleaseAction in your custom action.

You can use dragAndDrop() method.
Actions action = new Actions(driver);
action.dragAndDrop(sourceElement, destinationElement).build().perform();
Refere tutorial http://www.seleniumeasy.com/selenium-tutorials/drag-and-drop-using-webdriver-action-class

No need to release() When "dragAndDropBy" is used.
Try this:
move.dragAndDropBy(ele, 180, 300).build().perform();

Multiple Controls Drag and Drop to the Same Destination.
WebElement element_1 = driver.findElement(By.xpath("//li[#data-lobid='12']")); //source element 1
WebElement element_2 = driver.findElement(By.xpath("//li[#data-lobid='21']")); //source element 2
WebElement destination = driver.findElement(By.xpath(".//*[#id='lobModalPopUp']/div")); //destination path
int[] array_source = new int[]{12,21}; // create fixed array for id number of source element 1 and 2
for(int i = 0; i<array_source.length; i++) //Passing id number of source element 1 and 2 inside the for loop.
{
WebElement all_source_element = driver.findElement(By.xpath("//li[#data-lobid='"+arraylobs[i]+"']")); // getting all source element with the help of fixed array.
Actions drag = new Actions(driver);
drag.clickAndHold(all_source_element).build().perform();
Thread.sleep(3500);
drag.clickAndHold().moveToElement(destination).release(destination).build().perform();
Thread.sleep(3500);
}

driver.get("https://jqueryui.com/draggable/");
driver.switchTo().frame(0);
WebElement dragMe = driver.findElement(By.cssSelector(".ui-draggable-handle"));
new Actions(driver).dragAndDropBy(dragMe, dragMe.getLocation().getX()+100, dragMe.getLocation().getY()+100).perform();
This is how to use the dragAndDropBy(WebElement source, int xOffset, int yOffset) method provided in Actions class to perform drag and drop operations.
WebElement source: web-element that you want to drag around.
int xOffset and int yOffset are future x-axis and y-axis coordinate positions. Basically, the code gets the current x-axis and y-axis coordinate positions and adds int number to move the draggable element.
Please make sure to set up your driver properly before using this block of code.

Related

Is there a method to have two finger touch in appium?

I need to double tap with two fingers simulataneously on logo to proceed to next screen?
Yes, there exists a method to perform a double tab:
TouchActions action = new TouchActions(driver);
action.doubleTap(element);
action.perform();
You can try below code with help of touch action.
Define Mobile element as mentioned below
MobileElement mobileElement= (MobileElement) driver.findElement(by);
And pass this element to below function.
public void tapTwiceOnElement(MobileElement mobileElement) {
int halfHeight = element.getLocation().getX();
int halfWidth = element.getLocation().getY();
new TouchAction(driver).press(ElementOption.point(halfWidth,halfHeight)).release().perform().press(ElementOption.point(halfWidth,halfHeight)).release().perform();
new TouchAction(driver).press(ElementOption.point(halfWidth,halfHeight)).release().perform().press(ElementOption.point(halfWidth,halfHeight)).release().perform();
}
this is a Java code for two finger double tap, in case anyone needs it:
Preconditions: you can change withPosition to withElement and x and y values need to be predefined.
MultiTouchAction secondTwoFingerPress = new MultiTouchAction(DeviceBucket.getDriver());
secondTwoFingerPress.add(new TouchAction(DeviceBucket.getDriver())
.tap(TapOptions.tapOptions()
.withPosition(PointOption.point(xPoint, yPoint))
.withTapsCount(2)));
secondTwoFingerPress.add(new TouchAction(DeviceBucket.getDriver())
.tap(TapOptions.tapOptions()
.withPosition(PointOption.point(xPoint1, yPoint1))
.withTapsCount(2)));
secondTwoFingerPress.perform();
Based on appium documentation: https://appium.io/docs/en/writing-running-appium/touch-actions/
You can use MultiTouch gesture.
Pseudocode example of tapping with two fingers:
action0 = TouchAction().tap(el)
action1 = TouchAction().tap(el)
MultiAction().add(action0).add(action1).perform()

How to scroll screen in android native app having recyclerview using appium

I am trying to automate an app which is built using recyclerview. There are totally 10 tiles and in one screen 1st four tiles will be visible and to get other tiles I need to move the screen upward. I tried to move the screen by finding co-ordinates and "(AndroidElement)driver.findElement(MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector().resourceIdMatches(\".*id/type_text\")).setMaxSearchSwipes(5).scrollIntoView("new UiSelector().text(\"" + text + "\"))"))" this but there is slightly movement in the screen and couldn't get the remaining tiles. Is there any way to scroll to the bottom of the screen so that I can get last tile also.
Please try this. I think there's some issue in your UiScrollable..
MobileElement listItem=(MobileElement)driver.findElement(MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector()"
+ ".scrollable(true)).scrollIntoView("
+ "new UiSelector().text(\"<Mention your element text value here>\"))"));
#Sammar Ahmad, yes you were right. I was using wrong element. I constantly tried and finally worked after using co-ordinates.Code looks something like below. Created scroll() in homepage class and called the same from my test class
public void scroll(int x, int y) {
int startY = (int) (driver.manage().window().getSize().getHeight() * 0.90);
int endY = (int) (driver.manage().window().getSize().getHeight() * 0.10);
TouchAction action = new TouchAction(driver);
action.press(point(x, startY)).waitAction(waitOptions(ofSeconds(3))).moveTo(point(x, endY)).release().perform();
}
MobileElement startElement = (MobileElement) driver.findElementById("mention parent element here");
Point location = startElement.getLocation();
homepage.scroll(location.x,location.y);
MobileElement listItem=(MobileElement)driver.findElement(MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector()).scrollIntoView(text(\"<Mention your element text value here>\"))"));
You can modify #sammar's code like this to scroll to the element.

How to Automate Maps with Selenium Java? or with Page Co-Ordinates. Pleas show me is there any other way to Automate Maps

I'm Trying to capture the Co-ordinates of Maps to do some action on Maps.
wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.elementToBeClickable(By.`path`("//button[contains(text(),'Add Tract')]"))).click();
Utils.scrollUp();
Thread.sleep(10000);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("TimeZoneId")));
//Timezone is the area which I'm trying to capture the Co-Ordinates
Point point1 = timezone.getLocation();
SOP("Element's Position from left side is: "+point1.getX()+" pixels.");
SOP("Element's Position from top is: "+point1.getY()+" pixels.");
}
if your map has <canvas> tag, then try
To perform using Actions chains, below is an example C# code similar to Java
IWebElement canvas = driver.FindElement(By.Id("TimeZoneId"));
int xCo = canvas.Location.X;
int yCo = canvas.Location.Y;Actions action = new Actions(driver);
action.MoveToElement(canvas, 1 + xCo, 2 + yCo).Click().Build().Perform();
Try OpenCV
If you are testing overlays on map. use JavaScriptExecutor and by adding hooks to your code in order to perform actions in your Map.
Try with Sikuli (personally, I have not used this. Needs some research)

Unable to click a mouse hover link using Selenium WebDriver with Java

I am trying to click a mouse hover link using the code below. The webdriver (v.2.35) doesn't throw any error but the element isn't clicked. Can somebody help me figure out what's wrong?
String URL = "http://www.kgisliim.ac.in/"
String menu ="Alumni>Register"
driver.get(URL);
String[] menuItems = menu.split(">");
Actions actions = new Actions(driver);
WebElement tempElem;
for (int i =0 ; i< menuItems.length ; i++) {
tempElem = driver.findElement(By.linkText(menuItems[i].trim()));
actions.moveToElement(tempElem).build().perform();
}
actions.click();
actions.perform();
NOTE: The above code works fine in the below scenario
String URL = "http://www.flipkart.com/"
String menu ="Clothing>Jeans"
You can try this:
WebDriver driver=new FirefoxDriver();
driver.get("http://www.kgisliim.ac.in/");
Actions actions=new Actions(driver);
WebElement menuHoverLink=driver.findElement(By.linkText("Alumni"));
actions.moveToElement(menuHoverLink);
//driver.manage().timeouts().implicitlyWait(30,TimeUnit.SECONDS);
WebElement subLink=driver.findElement(By.cssSelector(".options>ul>li>a"));
actions.moveToElement(subLink);
actions.click();
actions.perform();
Since the menu on http://www.kgisliim.ac.in/ takes a second to slide out, you could add a WebDriverWait to make sure the submenu has time to become visible before moving the cursor to it. Try replacing the first line in your for loop with the following line. This will wait a maximum of 5 seconds for the submenu (but will return the WebElement as fast as possible within that time).
tempElem = new WebDriverWait(driver, 5).until(ExpectedConditions
.elementToBeClickable(By.linkText(menuItems[i].trim())));
I stumbled across a similar issue recently, with phantomJS and ghostdriver. In my case, the problem was the window size - the HTML element was outside the visible area and my mouse movements were having no effect (default size is 400x300, which is rather small).
You can check the window size with
driver.manage().window().getSize()
And you can change it with
driver.manage().window().setSize(new Dimension(width, height));

locate an element in current view

When I use the method WebElement#findElement(By) with By.cssSelector, it searches for the element through the whole page. But I want to restrict the selection by current-view-only. I don't want to allow Selenium to "use scrollbar". How can I achieve this?
The way to go for this could be in the way of getting all the elements on the page and then filtering out those out of viewport.
WebElement.getLocation() is a ground tool for this.
If you're in the left-top corner of the page (default after the load), you can use window.innerHeight and window.innerWidth (most browsers, but IE9+).
// assuming JS is enabled for this instance of driver
JavascriptExecutor js = (JavascriptExecutor)driver;
int viewportWidth = (Integer)js.executeScript("return window.innerWidth;");
int viewportHeight = (Integer)js.executeScript("return window.innerHeight;");
List<WebElement> list = driver.findElements(By.cssSelector("whatever"));
for (Iterator<WebElement> iter = list.iterator(); iter.hasNext(); ) {
WebElement elem = iter.next();
Point p = elem.getLocation();
if ((p.getX() > viewportWidth) || (p.getY() > viewportHeight)) {
iter.remove();
}
}
If you cannot say for sure that the viewport will be in its default position (at coordinates [0, 0]), you can add window.mozInnerScreenX and window.mozInnerScreenY (Firefox 3.6+ required) to the condition. Or, possibly better, window.scrollX and window.scrollY.
You also have to define whether to include partially shown elements or not and adjust the algorithm accordingly (WebElement.getSize() to the rescue!).
If you'll have trouble that after the search, the viewport changed, try to scrool back to the original position via window.scroll().

Categories