I'm trying to get the positions of Web Elements in headless chrome mode. The Problem is, the y-positions of the Elements are always Different to the y-positions in non headless mode like +36 px on one Screen and +45 on another.
Can I setup Chrome headless so the Positions are the same like in non headless Mode?
Here are my Chrome Options:
options.addArguments("headless"); // mode
options.addArguments("disable-gpu");
options.setExperimentalOption("useAutomationExtension", false);
options.addArguments("disable-infobars"); // disabling infobars
Window size is set to Screen Resolution:
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int width = (int)screenSize.getWidth();
int height = (int)screenSize.getHeight();
System.out.println("Width: " + width + " height: " + height);
driver.manage().window().setSize(new org.openqa.selenium.Dimension(width,height));
Related
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.
I have java 1.4 application that is running on server.
I need to calculate the width of strings before I create pdf files that include them.
When running the app locally (on my pc) it is o.k. , but when I run it on a server I get an error :
Exception in thread "main" java.lang.InternalError: Can't connect to X11 window server using ':0.0' as the value of the DISPLAY
variable.
at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:77)
at java.lang.Class.forName1(Native Method)
at java.lang.Class.forName(Class.java:142)
at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:72)
at java.awt.Font.initializeFont(Font.java:285)
at java.awt.Font.<init>(Font.java:319)
the code that create the problem calculate the width of a string as follows :
protected static String mCutStr(String iText , int iWidthPt , int iEstimatedNumOfChars)
{
iWidthPt = iWidthPt-4; //remove padding
AffineTransform affinetransform = new AffineTransform();
FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
Font font = new Font("Times", Font.PLAIN, 9);
int textwidth = (int)(font.getStringBounds(iText, frc).getWidth());
// System.out.println("iText="+iText+"; textwidth = "+textwidth+" iWidthPt ="+iWidthPt);
if(textwidth <= iWidthPt)
return iText;
String vTestStr = iText.substring(0 , iEstimatedNumOfChars)+">>";
textwidth = (int)(font.getStringBounds(vTestStr, frc).getWidth());
while(textwidth < iWidthPt)
{
iEstimatedNumOfChars++;
vTestStr = iText.substring(0 , iEstimatedNumOfChars)+">>";
textwidth = (int)(font.getStringBounds(vTestStr, frc).getWidth());
// System.out.println("vTestStr="+vTestStr+" textwidth = "+textwidth);
}
vTestStr = iText.substring(0 , iEstimatedNumOfChars-1)+">>";
return vTestStr;
}
Is there an other way to calc this without using AWT?
(it must support minimum java 5)
You need to run your server in headless mode. Headless mode is useful when actual Window system like X server is not available and you need to perform some AWT related functions.
Java Documentation about Headless mode
If you are using web server like tomcat search how to execute that specific server in headless mode
OR
set system environment property java.awt.headless to true
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);
Using some code from this question I have set up some code to detect when an android device is rotated. It works great for the asus tablet (4.0.3) and two simulators (4.0.3 and 2.1), but for the kindle fire (2.3.4), and droidx (2.3.4) it switches the width and height.
Code:
<script type="text/javascript">
var supportsOrientationChange = "onorientationchange" in window,orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";
window.addEventListener(orientationEvent, function() {
alert("The rotation is " + window.orientation + " and the resolution is " + screen.width + " x " + screen.height);
modRule();
}, false);
</script>
Output from asus tablet
Holding it in what looks like landscape:
The rotation is 0 and the resolution is 1280 x 800
Portrait
The rotation is -90 and the resolution is 800 x 1280
Output from Kindle Fire
Landscape
The rotation is 90 and the resolution is 600 x 819
Portrait:
The rotation is 0 and the resolution is 1024 x 395
output from droidx
landscape:
The rotation is 90 and the resolution is 320x488
Portrait:
The rotation is 0 and the resolution is 569x239
Is there a way I can
a) Make the javascript detect if it should use height instead of width or width instead of height
OR
b) Make the devices report the correct values for their width and height?
After looking for a while longer I found out that this is a bug with the 2.2 and 2.3 OS. I fixed the bug with 2.3.4 by putting this code in my app.
browser = (WebView)findViewById(R.id.webBrowser);
browser.setBackgroundColor(Color.BLACK);
WebSettings webSettings = browser.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setUserAgentString("Android " + android.os.Build.VERSION.SDK);//this is so the JavaScript knows what version of the OS I'm using
And then for detecting if I'm in landscape mode:
var uagent = navigator.userAgent.toLowerCase();
function isLandscape()
{
var width = screen.width;
var height = screen.height;
if (isBugged())
{
var temp = width;
width = height;
height = temp;
}
var landscape = width > height;
return landscape;
}
function isBugged()
{
return uagent == "android 10"
}
And if that wasn't confusing enough, when the body initially loads, it's right about if it's in landscape mode or not. So I had to bypass my own workaround.
<body onload="if(isBugged()){uagent = 'bypass';}/*code that depends on isLandscape()*/;uagent = navigator.userAgent.toLowerCase();">
It's a real pain, a lot more work than it should be. Especially since it works in 2.1 but not 2.3.4. Really frustrating, but that's what I have. At the moment, I only check for sdk 10, I'm going to add checking for the other bugged versions soon.
My friend made an application using javascript, and uploaded it to his website.
Now I'm trying to wrap it into a webview in android, and that's working fine in some ways.
The page is 480x320
But no matter what screensize I select on Android, there is a white space at the bottom on the webview. I have tried a lot of ways to make it zoom, but nothing worked.
My code at this moment is this
final WebView browser = (WebView)findViewById(R.id.webview);
browser.getSettings().setJavaScriptEnabled(true);
browser.loadUrl("http://page.xx");
I needed to scale-to-fit for the width and this variation of FunkTheMonk's answer worked well for me:
#Override
public void onPageFinished(android.webkit.WebView view, String url)
{
super.onPageFinished(view, url);
WindowManager manager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(metrics);
metrics.widthPixels /= metrics.density;
loadUrl("javascript:var scale = " + metrics.widthPixels + " / document.body.scrollWidth; document.body.style.zoom = scale;");
}
wb.loadUrl("javascript:document.body.style.zoom = "+String.valueOf(scale)+";");
Where scale is a float, which you could calculate - I think in your case you want something like the following: browser.getHeight() / 480dp.
Load this Url after your webpage has finished loading.
Can you try to add :
browser.getSettings().setBuiltInZoomControls(true);
browser.setInitialScale(1);
browser.setPadding(0, 0, 0, 0);
And see if it's working ?