I am unable to scroll down in mobile page on an android device using appium. I have tried driver.scrollTo(element) , it is not scrolling down to the specified element.
I have tried using Actions class but I got an error as "Method has not been implemented yet"
I have tried another approach using Javascript but it didn't work either.
Someone give suggestion.
Here is the code:
public static void main(String[] args) throws IOException, InterruptedException {
DesiredCapabilities cap = new DesiredCapabilities();
cap.setCapability(CapabilityType.BROWSER_NAME, "Android"); //Name of mobile web browser to automate. Should be an empty string if automating an app instead.
cap.setCapability(CapabilityType.VERSION, "6.0.1");
cap.setCapability(CapabilityType.PLATFORM, "Mac");
cap.setCapability("platformName", "android");
cap.setCapability("platformVersion", "6.0.1");
cap.setCapability("deviceName", "4d00a89e4b2631e9");
cap.setCapability("app", "/Users/ds_nivedha/Downloads/flipkart.apk");
cap.setCapability("appPackage", "com.usablenet.mobile.walgreen"); //Replace with your app's package
cap.setCapability("appActivity", "com.usablenet.mobile.walgreen.AppStart"); //Replace with app's Activity
driver = new AndroidDriver<MobileElement>(new URL("http://127.0.0.1:4723/wd/hub"), cap);
driver.manage().timeouts().implicitlyWait(90, TimeUnit.SECONDS);
/* MobileElement skip= driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.support.v4.view.ViewPager[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[2]/android.widget.Button[1]"));
skip.click(); */
MobileElement skiparrow=
driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.support.v4.view.ViewPager[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[3]/android.widget.ImageButton[1]"));
skiparrow.click();
MobileElement skiparrowRefill=
driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.support.v4.view.ViewPager[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[2]/android.widget.ImageButton[1]"));
skiparrowRefill.click();
MobileElement skiparrowPaperless=
driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.support.v4.view.ViewPager[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[2]/android.widget.ImageButton[1]"));
skiparrowPaperless.click();
MobileElement done=
driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.support.v4.view.ViewPager[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[1]/android.widget.Button[1]"));
done.click();
MobileElement shopProducts=
driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.support.v7.widget.RecyclerView[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[2]/android.widget.TextView[2]"));
shopProducts.click();
MobileElement personalCare=
driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.ScrollView[1]/android.widget.LinearLayout[1]/android.widget.GridView[1]/android.widget.TextView[2]"));
personalCare.click();
MobileElement hairCare=
driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.ListView[1]/android.widget.TextView[3]"));
hairCare.click();
MobileElement stylingProduct=
driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.ListView[1]/android.widget.TextView[3]"));
stylingProduct.click();
MobileElement faroukAddToCart=
driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.webkit.WebView[1]/android.webkit.WebView[1]/android.view.View[1]/android.view.View[1]/android.view.View[1]/android.view.View[1]/android.view.View[3]/android.view.View[2]/android.view.View[1]/android.view.View[3]/android.view.View[1]/android.view.View[1]/android.view.View[4]/android.view.View[1]/android.view.View[1]/android.view.View[2]/android.widget.Button[1]"));
faroukAddToCart.click();
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//android.widget.Button[contains(#resource-id,'addToCart-cart-checkout')]")));
driver.findElement(By.xpath("//android.widget.Button[contains(#resource-id,'addToCart-cart-checkout')]")).click();
//driver.scrollTo("Proceed to checkout");
MobileElement proceedToCheckout=
driver.findElement(By.xpath("//android.widget.Button[contains(#resource-id,'proceedtocheckout')]"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", proceedToCheckout);
Thread.sleep(500);
/* Actions actions = new Actions(driver);
actions.moveToElement(proceedToCheckout);
actions.perform(); */
MobileElement checkout=
driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.webkit.WebView[1]/android.webkit.WebView[1]/android.view.View[1]/android.view.View[1]/android.view.View[1]/android.view.View[1]/android.view.View[1]/android.view.View[2]/android.view.View[2]/android.view.View[5]/android.view.View[2]/android.view.View[5]/android.view.View[1]/android.view.View[1]/android.view.View[1]/android.view.View[1]/android.view.View[1]/android.widget.Button[1]"));
checkout.click();
Use swipe method
Keep start x and end x value constant and change start y and end y values to scroll up or down
The scrollTo() method is deprecated now, you can check on the official site over here
Instead if it you can use swipe method to swipe vertically on mobile device and to check if your expected text is visible or not, in not then you can make more swipes, of course you will be using loop for doing so.
To know more about Swipe refer here
For Swipe method refer below example
public void swipingVertical() throws InterruptedException {
//Get the size of screen.
size = driver.manage().window().getSize();
System.out.println(size);
//Find swipe start and end point from screen's with and height.
//Find starty point which is at bottom side of screen.
int starty = (int) (size.height * 0.80);
//Find endy point which is at top side of screen.
int endy = (int) (size.height * 0.20);
//Find horizontal point where you wants to swipe. It is in middle of screen width.
int startx = size.width / 2;
System.out.println("starty = " + starty + " ,endy = " + endy + " , startx = " + startx);
//Swipe from Bottom to Top.
driver.swipe(startx, starty, startx, endy, 3000);
Thread.sleep(2000);
//Swipe from Top to Bottom.
driver.swipe(startx, endy, startx, starty, 3000);
Thread.sleep(2000);
}
Let me know if you face any more hurdle in this.
Related
I am trying to swipe down a modal view in iOS using Appium with java.
I have tried this two ways unsuccessfully:
JavascriptExecutor js2 = (JavascriptExecutor) driver;
HashMap<String, String> scrollObject2 = new HashMap<String, String>();
scrollObject2.put("x", "200");
scrollObject2.put("y", "550");
scrollObject2.put("direction", "down");
js2.executeScript("mobile: swipe", scrollObject2);
TouchAction action = new TouchAction(driver);
action.press(PointOption.point(200, 550)).moveTo(PointOption.point(200, 700)).release().perform();
What I am doing wrong? is another correct way to achieve this?
Thanks!
You should do it using js script executor.
No need to add coordinates like you did, just try something like this:
HashMap<String, String> scrollObject = new HashMap<>();
JavascriptExecutor js = driver;
scrollObject.put("direction", "down");
js.executeScript("mobile: scroll", scrollObject); //or "mobile: swipe"
public static void fingerSwipe(int startX, int startY, int endX, int endY, long timeInMillis){
PointerInput touchAction = new PointerInput(PointerInput.Kind.TOUCH, "touchAction");
Interaction moveToStart = touchAction.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), startX, startY);
Interaction pressDown = touchAction.createPointerDown(PointerInput.MouseButton.LEFT.asArg());
Interaction moveToEnd = touchAction.createPointerMove(Duration.ofMillis(timeInMillis), PointerInput.Origin.viewport(), endX, endY);
Interaction pressUp = touchAction.createPointerUp(PointerInput.MouseButton.LEFT.asArg());
Sequence swipe = new Sequence(touchAction, 0);
swipe.addAction(moveToStart);
swipe.addAction(pressDown);
swipe.addAction(moveToEnd);
swipe.addAction(pressUp);
driver.perform(Arrays.asList(swipe));
}
I use selenium interactions package to perform a swipe using JAVA and appium. Try using something similar to above code in WebDriverIo for Appium versions - 1.15.0 and above. You just need to pass input parameters depending upon the swipe you want to perform.
'long timeInMillis' is the time period of the swipe.
Hope you doing well,
I'm trying to dragAndDrop an element from FrameOne to FrameTwo but not able to do so.Please help me to understand the concept and what I'm doing wrong here and need to achieve the task by using Actions class only.
Here're the URLs :
https://www.w3schools.com/html/html5_draganddrop.asp
Here the element is in a div block I'm able to get all the locaters and do all other actions using Actions class but not able to drag and drop the element.
2.https://codepen.io/rjsmer/full/vvewWp
Here I'm trying to move the element from Frame one to Frame two but I'm not able to do so.
I've tried drangAndDrop(),ClickAndHold() methods,Searched so many solutions, watch videos on the same with no success.
package DragAndDropPracticeFrame;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Action;
import org.openqa.selenium.interactions.Actions;
import static io.github.bonigarcia.wdm.DriverManagerType.CHROME;
public class DragDropFrame {
public static void main(String[] args) throws InterruptedException {
WebDriverManager.getInstance(CHROME).setup();
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://codepen.io/rjsmer/full/vvewWp");
driver.switchTo().frame("result");
System.out.println("Inside First Frame.");
WebElement frameOne =
driver.findElement(By.cssSelector("iframe.dragFrame.dragDrop"));
driver.switchTo().frame(frameOne);
System.out.println("Inside Frame 3");
WebElement elementOne = driver.findElement(By.id("dragFrame-0"));
System.out.println("First element found: " + elementOne.getText());
Actions builder = new Actions(driver);
driver.switchTo().defaultContent();
System.out.println("Inside main page");
driver.switchTo().frame("result");
//System.out.println("Switched to Frame First");
WebElement frameThree =
driver.findElement(By.xpath("//iframe[#class='dropFrame dragDrop']"));
Action action =
builder.clickAndHold(elementOne)
.moveToElement(frameThree)
.release(frameThree).build();
//driver.switchTo().frame(frameTwo);
//System.out.println("Switched to frame 3");
action.perform();
//driver.switchTo().defaultContent();
//builder.perform();
}
}
Another try :
WebDriverManager.getInstance(CHROME).setup();
WebDriver driver = new ChromeDriver();
driver.get("https://codepen.io/rjsmer/full/vvewWp");
driver.switchTo().frame(0);
WebElement frameOne = driver.findElement(By.xpath("//iframe[#class='dragFrame dragDrop']"));
WebElement frameTwo = driver.findElement(By.xpath("//iframe[#class='dropFrame dragDrop']"));
driver.switchTo().frame(frameOne);
// identify element in first frame
WebElement elementOne = driver.findElement(By.id("dragFrame-0"));
// Use Actions class for tap and hold
Actions actions = new Actions(driver);
Actions action = actions.clickAndHold(elementOne);
actions.build();
action.perform();
// switch to the second frame
driver.switchTo().frame(frameTwo);
// move element to another frame
WebElement elementTwo = driver.findElement(By.xpath("//body[#class='frameBody dropFrameBody']"));
Actions actions2 = new Actions(driver);
Actions action2 = actions2.moveToElement(elementTwo);
actions2.release(elementOne);
actions2.build();
action2.perform();
Expected: The element should move to Frame 3
Actual: Nothing happened.
After many trails using Actions class, I understood that Actions class cannot be used drag and drop elements across frames. So, I switched to using Robot Class and it worked!
//Setting up chrome driver
WebDriverManager.getInstance(CHROME).setup();
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
//Redirecting to the website
driver.get("https://codepen.io/rjsmer/full/vvewWp");
Robot robot = new Robot();
robot.mouseMove(120, 300);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
Thread.sleep(2000);
robot.mouseMove(500, 320);
Thread.sleep(2000);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
The sleeps here are important as the commands are being implemented in a quick fashion and it helps the Robot class in pacing its commands accurately.
Depending on the dragFrame you want to drag, you can use the respective coordinates.
I noticed that on running above code, if you move mouse, you can see the dragged element attached to mouse. Try using Robot library and perform this with Robot library mouse actions.
See https://www.guru99.com/using-robot-api-selenium.html
I can't test this on my end as Robot library has bug on mac and i am using mac, if you are using windows, you can try:
Point browserLoc = driver.manage().window().getPosition();
driver.switchTo().frame(0);
WebElement frame1 = driver.findElement(By.xpath("//iframe[1]"));
Point frameLoc = frame1.getLocation();
driver.switchTo().frame(frame1);
Thread.sleep(1000);
WebElement listElement1 = driver.findElement(By.id("dragFrame-2"));
Point elementLoc = listElement1.getLocation();
Dimension elementSize = listElement1.getSize();
int x = elementLoc.getX() + frameLoc.getX() + browserLoc.getX() + elementSize.getWidth()/2;
int y = elementLoc.getY() + frameLoc.getY() + browserLoc.getY() + elementSize.getHeight()/2;
Robot robot = new Robot();
robot.setAutoDelay(50);
robot.mouseMove(x, y);
Actions action = new Actions(driver);
action.clickAndHold(listElement1);
Action a = action.build();
a.perform();
Thread.sleep(1000);
driver.switchTo().defaultContent();
driver.switchTo().frame(0);
WebElement frame2 = driver.findElement(By.xpath("//iframe[2]"));
Point frameLoc2 = frame2.getLocation();
driver.switchTo().frame(frame2);
WebElement frame2Body = driver.findElement(By.xpath("//body"));
Point frame2BodyLoc = frame2Body.getLocation();
Dimension frame2BodySize = frame2Body.getSize();
int x1 = frame2BodyLoc.getX() + frameLoc2.getX() + browserLoc.getX() + frame2BodySize.getWidth()/2;
int y1 = frame2BodyLoc.getY() + frameLoc2.getY() + browserLoc.getY() + frame2BodySize.getHeight()/2;
robot.setAutoDelay(50);
robot.mouseMove(x1, y1);
action.moveToElement(frame2Body);
action.release();
a = action.build();
a.perform();
What if first you identify first frame and use Actions class. There you can do tap and hold. Then switch to another frame, and use move to element.
// move to first frame
driver.switchTo().frame("frameOne");
// identify element in first frame
WebElement elementOne = driver.findElement(By.xpath(XPATH));
// Use Actions class for tap and hold
Actions actions = new Actions(driver);
Actions action = actions.clickAndHold(elementOne);
actions.build();
action.perform();
// switch to the second frame
driver.switchTo().frame("frameTwo");
// move element to another frame
Actions actions2 = new Actions(driver);
Actions action2 = actions2.moveToElement(elementTwo);
actions2.release(elementTwo);
actions2.build();
action2.perform();
For my Native Android App , I have been trying for the past 2 weeks to get appium to scroll down on my native app. I have tried driver.scrollTo("Accounts");
Then I got this error
[org.openqa.selenium.WebDriverException: CATCH_ALL: io.selendroid.server.common.exceptions.SelendroidException: method (by) not found: -android uiautomator
and many other examples that I have found. Nothing seems to work . This is the latest example that I have tried .
Using appium 1.5.2 and appium java client version: ‘3.3.0'. When I try to run the following code.
TouchAction tAction=new TouchAction(driver);
int startx = driver.findElement(By.id("line_chart_line_chart")).getLocation().getX();
int starty = driver.findElement(By.id("line_chart_line_chart")).getLocation().getY();
int endx = driver.findElement(By.id("actionBarLogo")).getLocation().getX();
int endy = driver.findElement(By.id("actionBarLogo")).getLocation().getY();
System.out.println(startx + " ::::::: " + starty + " ::::::: " + endx + " ::::::: " + endy);
// This is what the console printed out startX=560 ::::::: starty=1420 ::::::: endx=560 ::::::: endy=240
//First tap on the screen and swipe up using moveTo function
tAction.press(startx,starty).moveTo(endx,endy).release().perform();
Then I get this error message
org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. Original error: Could not proxy. Proxy
error: Could not proxy command to remote server. Original error: 404 - undefined (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 27 milliseconds
I am at a loss on what to do. In order to click on an element it has to be visible on the screen . In order for this element to appear on the screen I need to scroll down to it.
Is there something that I am doing wrong??? I just can't seem to figure it out.
You used Selendroid mode, which does not support UiAutomator By method.
You can change your appium running mode to UiAutomator by setting desired capability automationName to Appium
This function does the trick for me, put in "Accounts" for elementName when calling it in your case.
public static void scrollToElementAndroid(AndroidDriver driver, String elementName, boolean scrollDown) {
String listID = ((RemoteWebElement) driver.findElementByAndroidUIAutomator("new UiSelector().className(android.widget.ListView)")).getId();
String direction;
if (scrollDown) {
direction = "down";
} else {
direction = "up";
}
HashMap<String, String> scrollObject = new HashMap<String, String>();
scrollObject.put("direction", direction);
scrollObject.put("element", listID);
scrollObject.put("text", elementName);
driver.executeScript("mobile: scrollTo", scrollObject);
}
Use code like below:
Dimension size = driver.manage().window().getSize();
int x = size.width / 2;
int endy = (int) (size.height * 0.75);
int starty = (int) (size.height * 0.20);
driver.swipe(x, starty, x, endy, 1000);
I want to swipe in mobile web site using selenium on java.
I have tried the following code. But it doesn't help me out.
1. //Swipe Right to Left side of the Media Viewer First Page
WebElement firstPages = driver.findElement(By.id("media-list"));
TouchActions flick = new TouchActions(driver).flick(firstPages,-100,0,0);
flick.perform();
Result:- org.openqa.selenium.chrome.ChromeDriver cannot be cast to org.openqa.selenium.interactions.HasTouchScreen
2. //perform swipe gesture
TouchActions swipe = new TouchActions(driver).flick(0, -20);
swipe.perform();
3. JavascriptExecutor js = (JavascriptExecutor) driver;
HashMap<String, Double> swipeObject = new java.util.HashMap<String, Double>();
swipeObject.put("startX", 0.95);
swipeObject.put("startY", 0.5);
swipeObject.put("endX", 0.05);
swipeObject.put("endY", 0.5);
swipeObject.put("duration", 1.8);
js.executeScript("mobile: swipe", swipeObject);
}
Result: unknown error: swipe is not defined(..)
You could trigger an event via javascript eg. with jquery trigger
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("$('#media-list').trigger('swipe', {startX: 0.95})");
I have tried with below codings for swiping a mobile pages.
While running the test case, the swipe action doesn't occurs and i am also not getting any error message.
3.How can I swipe on both side from left to right and vice-versa.
1. //Swipe Right to Left side of the Media Viewer First Page
WebElement firstPages = driver.findElement(By.id("media-list"));
TouchActions flick = new TouchActions(driver).flick(firstPages,-100,0,0);
flick.perform();
2. //perform swipe gesture
TouchActions swipe = new TouchActions(driver).flick(0, -20);
swipe.perform();
Here is my code to flick pages and it is working fine for me
for (int i = 0; i <= 3; i++) {
Thread.sleep(5000);
WebElement pages = driver.findElement(By.id("action_bar_overlay_layout"));
TouchActions flick = new TouchActions(driver).flick(pages, 500, 0, 0);
flick.perform();
}
You can flick in both sides by just changing the sign of the x-parameter whose value is 500 here.