Does ChromeDriver support Rotatable for mobileEmulation - java

I'm testing a web app with Selenium 2.44 and ChromeDriver 2.13. I'm using Chromes mobile emulation to mock connecting from a mobile device. I need to change the screen orientation mid test from portrait to landscape and I can't seem to get it working.
Sample code for trying to augment WebDriver to Rotatable is below but it is throwing a ClassCastException when trying to cast to Rotatable. Can someone tell me if I am doing something wrong or if ChromeDriver does not support rotation?
package test;
import org.openqa.selenium.Rotatable;
import org.openqa.selenium.ScreenOrientation;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.AddRotatable;
import org.openqa.selenium.remote.Augmenter;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
System.setProperty(
"webdriver.chrome.driver",
"Path/To/chromedriver.exe"
);
Map<String, String> mobileEmulation = new HashMap<>();
mobileEmulation.put("deviceName", "Google Nexus 4");
Map<String, Object> chromeOptions = new HashMap<>();
chromeOptions.put("mobileEmulation", mobileEmulation);
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
capabilities.setCapability(CapabilityType.ROTATABLE, true);
WebDriver driver = new ChromeDriver(capabilities);
driver.get("http://m.rte.ie");
// Try and rotate
Augmenter augmenter = new Augmenter();
augmenter.addDriverAugmentation(CapabilityType.ROTATABLE, new AddRotatable());
WebDriver augmentedDriver = augmenter.augment(driver);
ScreenOrientation currentOrientation = ((Rotatable) augmentedDriver).getOrientation();
System.out.println(String.format("Current Orientation is: %s", currentOrientation));
driver.quit();
}
}
It appears as though Chrome supports switch orientation as is documented here: (https://developer.chrome.com/devtools/docs/device-mode) if you look at the section on, 'Swap dimensions'. I have tried this manually in the browser and it works fine. Just wondering if ChromeDriver does not support the Rotatable interface, is there a way to update the screen dimensions on the fly?

It was a tough one. Hope this saves a decent amount of effort for someone. As for now, ChromeDriver only supports portrait orientation in mobile emulation mode. There are no workarounds whatsoever to pass it as an option and no ability to trigger from javascript either.
Yet, there is a solution that seems to work for me. What you need to do is simply start the ChromeDriver with userAgent option which represents your device. For instance, here is what it looks like for iPad emulation:
Map<String, Object> mobileEmulation = new HashMap<>();
String userAgent = "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 " +
"(KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10";
ChromeOptions options = new ChromeOptions();
options.addArguments("--user-agent=" + userAgent);
options.addArguments("window-size=1039,859");
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
Also, you might want to set the dimensions that resemble the emulated device. It's a bit tricky, since only the window size could be set in ChromeOptions. And again, with the use of this tool: Chrome viewport dimensions plugin you can find the correct ratio for your resolution. In my case, viewport's 1024x768 correspond to 1039x859 of window-size.
P.S. it could be done only on driver start. There is no possibility to change the orientation on the fly

it seems that it accepts "deviceOrientation" as a capacity with values "portrait" and "landscape", but unfortunately this is not yet implemented.
Waiting for the same answer.

Related

Fitting objects in window screen using Selenium Java

I am trying to fit all the objects in the window (Chrome browser). Manually when I am doing it(the dimensions that I am using is 1024X786 using toggle bar, but when I am automating it using the same dimension, it's not showing the same as it was manually.
The following is the code:
driver = new ChromeDriver();
Map<String, Object> deviceMetrics = new HashMap<String, Object>();
deviceMetrics.put("width", 768);
deviceMetrics.put("height", 1024);
Map<String, Object> mobileEmulation = new HashMap<String, Object>();
mobileEmulation.put("deviceMetrics", deviceMetrics);
mobileEmulation.put("userAgent", "Mobile S");
Map<String, Object> chromeOptions = new HashMap<String, Object>();
chromeOptions.put("mobileEmulation", mobileEmulation);
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
System.out.println("Driver is now ChromeDriver");
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
The footer is getting lost in this. What I am getting is:
What I am suppose to get is this:
Another code I used is:
driver.manage().window().setSize(new Dimension(1024, 786));
Can anyone please help? Thanks
Setting the size of the window wont work if you want to fit contents of a web page in window without scroll If it's a large page.
What you will have to do is adjust the zoom level to fit all contents in window.
You can do this as shown below:
WebElement html = driver.findElement(By.tagName("html"));
html.sendKeys(Keys.chord(Keys.CONTROL, Keys.SUBTRACT));
Make sure to reset the zoom level afterwards as shown below:
html.sendKeys(Keys.chord(Keys.CONTROL, "0"));
What basically happens here is the same as what happens when you press Control and - in your keyboard while focusing on your browser.
Try it out, if this serves your purpose.
You need to pass the mobileEmulation related configuration within an instance of ChromeOptions Class as follows:
Map<String, Object> deviceMetrics = new HashMap<>();
deviceMetrics.put("width", 768);
deviceMetrics.put("height", 1024);
Map<String, Object> mobileEmulation = new HashMap<>();
mobileEmulation.put("deviceMetrics", deviceMetrics);
mobileEmulation.put("userAgent", "Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19");
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setExperimentalOption("mobileEmulation", mobileEmulation);
WebDriver driver = new ChromeDriver(chromeOptions);
Note: Testing a mobile website on a desktop using mobile emulation can be useful, but testers should be aware that there are many subtle differences such as:
Entirely different GPU, which may lead to big performance changes;
Mobile UI is not emulated (in particular, the hiding url bar affects page height);
Disambiguation popup (where you select one of a few touch targets) is not supported;
Many hardware APIs (for example, orientationchange event) are unavailable.
Reference
Mobile Emulation
tl; dr
Mobile Emulation is subject to a known issue Test testClickElement from MobileEmulationCapabilityTest class fails on Chromium for all platforms

Selenium: Not able to take complete page screenshot using aShot library

Am trying to take the complete page screenshot both horizontally and vertically using Firefox gecko driver and aShot Library.
However, the results are not as expected. Take a look:
driver.get("https://google.com");
Screenshot fpScreenshot = new AShot().shootingStrategy(ShootingStrategies.viewportPasting(1000)).takeScreenshot(driver);
ImageIO.write(fpScreenshot.getImage(),"JPEG",new File("FullPageScreenshot.jpg"));
Looked into a lot of variants but nothing is working. Interestingly, when I try using old firefox version (46), I am able to take full screenshot without any third party library. Am trying to use latest firefox and have full screenshot functionality.
Any help?
Try:
Screenshot screenshot = new AShot().shootingStrategy(ShootingStrategies.viewportPasting(ShootingStrategies.scaling(1.75f), 1000)).takeScreenshot(driver);
where 1.75f is device pixel ratio (you can run window.devicePixelRatio; in browser console to find it).
If it's still not capturing full screen, change it to 2f
While working with Selenium Java Client v3.12.0, ChromeDriver v2.40, Chrome v 67.0 using ashot-1.4.4.jar here is an example to take the complete page screenshot both horizontally and vertically using ChromeDriver and aShot Library of the url https://jquery.com/:
Code Block:
import java.io.File;
import javax.imageio.ImageIO;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import ru.yandex.qatools.ashot.AShot;
import ru.yandex.qatools.ashot.Screenshot;
import ru.yandex.qatools.ashot.shooting.ShootingStrategies;
public class ashot_CompletePage {
public static void main(String[] args) throws Exception {
System.setProperty("god.bless.you", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
options.addArguments("disable-infobars");
options.addArguments("--disable-extensions");
WebDriver driver = new ChromeDriver(options);
driver.get("https://jquery.com/");
new WebDriverWait(driver, 20).until(ExpectedConditions.titleContains("jQuery"));
Screenshot myScreenshot = new AShot().shootingStrategy(ShootingStrategies.viewportPasting(100)).takeScreenshot(driver);
ImageIO.write(myScreenshot.getImage(),"PNG",new File("./Screenshots/elementScreenshot.png"));
driver.quit();
}
}
Screenshots:
Reference
You can find a detailed discussion in How to take screenshot with Selenium WebDriver

Chrome profile to disable "Know your location" pop up

I am running my tests in Google Chrome using chromedriver.exe binary. At one particular page this pop up comes which doesn't intervene/effect with the test but client doesn't want to see it. Possible reason could be, at the failure of test case it will capture the screenshot along with this pop up.
How can I create a chrome profile or capabilities which would disable this pop up?
Something like this:
ChromeOptions options = new ChromeOptions();
options.addArguments("user-data-dir=C:/Users/user_name/AppData/Local/Google/Chrome/User Data");
Edit:
This code stopped the "Know your location" pop up to come but generated another pop up. So its only partially working.
options.addArguments("--enable-strict-powerful-feature-restrictions");
driver = new ChromeDriver(options);
Use --disable-geolocation, Chrome Options as given below:
options.addArguments("--disable-geolocation");
Also list of chrome command-line switches can be found in the below link:
http://peter.sh/experiments/chromium-command-line-switches/
Declaring in the following way worked for me.
// Declare variables
ChromeOptions options = new ChromeOptions();
Map<String, Object> prefs = new HashMap<String, Object>();
Map<String, Object> profile = new HashMap<String, Object>();
Map<String, Object> contentSettings = new HashMap<String, Object>();
// Specify the ChromeOption we need to set
contentSettings.put(“geolocation”, 1);
profile.put(“managed_default_content_settings”, contentSettings);
prefs.put(“profile”, profile);
options.setExperimentalOption(“prefs”, prefs);
// Declare the capability for ChromeOptions
caps.setCapability(ChromeOptions.CAPABILITY, options);
This code solved my problem with geolocation
options.AddUserProfilePreference("profile.default_content_setting_values.geolocation", 2);
The --disable-geolocation flag didn't do anything for me.
I am also running with incognito on, so that might be affecting some things.
I can confirm that the following python selenium code will disable the location popup
prefs = {
"profile.default_content_setting_values.geolocation": 2,
}
options.add_experimental_option("prefs", prefs)
In the interest of digging deeper.
If you need to change any setting. It can be done by comparing the "${PROFILE}Preferences" file that is saved
I'd recommend always starting with a clean profile as follows, then setting whatever preferences you want in code. to get a reproducible result.
data_dir = "tmp/remote-profile"
if os.path.exists(data_dir):
shutil.rmtree(data_dir)
options.add_argument("--user-data-dir=tmp/remote-profile")
options.add_argument('--profile-directory=Default')
In the case above the Preferences file will be in tmp/remote-profile/Default/Preferences
Add this below command line argument, which will restrict geolocation feature.
String url = "http://ctrlq.org/maps/where/";
//Chromedriver Version : 2.19.346078
System.setProperty("webdriver.chrome.driver", "CHROMEDRIVERPATH");
ChromeOptions options = new ChromeOptions();
options.addArguments("--start-maximized");
options.addArguments("--enable-strict-powerful-feature-restrictions");
WebDriver driver = new ChromeDriver(options);
driver.get(url);
And other way is after lauching the chrome browser, Through the selenium code implement below steps which will disable the geo location popup.
Go to : chrome://settings/content
Under the location select 'Do not allow any site to track your physical location' option.
Click On Done

What Firefox Driver does Selenium use?

I’m trying to use Selenium WebDriver with Eclipse and JUnit and a Firefox browser to do a series of Link tests. The trouble I’m having is the Firefox browser is opening some links in a new Window. Note: these are not Alerts.
I have the browser set to open all links in the same window, and if I navigate to the chosen links manually it does what it’s supposed to do. These are the settings of the default browser at present.
browser.link.open_newwindow; 1
browser.link.open_newwindow.disabled_in_fullscreen; true
browser.link.open_newwindow.override.external: 1
browser.link.open_newwindow.restriction; 2
When I run the same thing in Eclipse as a JUnit test from Eclipse the link opens up in a new window!
I commented out driver.close() and checked the browser that Eclipse was using and all the settings are different. There is even another setting that isn’t in my browser.
browser.link.open_newwindow; 2
browser.link.open_newwindow.disabled_in_fullscreen; false
browser.link.open_newwindow.override.external: -1
browser.link.open_newwindow.restriction; 2
browser.link.open_external 2
If I use a profile or force it to use the default profile it the browser it uses has these settings.
browser.link.open_newwindow; 2
browser.link.open_newwindow.disabled_in_fullscreen; true
browser.link.open_newwindow.override.external: 1
browser.link.open_newwindow.restriction; 2
browser.link.open_external 2
From reading previous posts I was of the understanding that Eclipse/Selenium/JUnit would use the default browser installed on my PC. Or at least the default browser profile
My Code:
import java.util.concurrent.TimeUnit;
import org.junit.*;
import static org.junit.Assert.*;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.firefox.internal.ProfilesIni;
public class Pro2 {
private WebDriver driver;
private String baseUrl;
private StringBuffer verificationErrors = new StringBuffer();
#Before
public void setUp() throws Exception {
ProfilesIni profile = new ProfilesIni();
FirefoxProfile ffprofile = profile.getProfile("default");
driver = new FirefoxDriver(ffprofile);
// driver = new FirefoxDriver();
baseUrl = "https://www.google.ie/";
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
My questions are:
Is it using a different driver(or driver profile)?
If so how do I set the config settings so that all links open in the current window?
You can modify firefox profile before you use it in your tests by calling SetPreference method of the FirefoxProfile class:
ffprofile.SetPreference("browser.link.open_newwindow", "1");

Selenium 2 chrome driver preferences java equivalent to RubyBindings

I've been looking for a way to set the driver preferences for chrome driver using java for the past two days with no luck.
I have however found a solution in ruby VIA RubyBindings and would like to know if there is a java equivalent line I can use for this.
The ruby code is the following:
profile = Selenium::WebDriver::Chrome::Profile.new
profile['download.prompt_for_download'] = false
profile['download.default_directory'] = "/path/to/dir"
driver = Selenium::WebDriver.for :chrome, :profile => profile
While searching I found that chrome does not have a profiler I could use like the FirefoxProfile class, so I started using the DesireCapabilities class instead. After further investigation into this problem I found that I could set the "switches" and "prefs" VIA capabilities.setCapabilitiy and ended up with the following:
Map<String, String> prefs = new Hashtable<String, String>();
prefs.put("download.prompt_for_download", "false");
prefs.put("download.default_directory", "/path/to/dir");
prefs.put("download.extensions_to_open", "pdf");
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability("chrome.prefs", prefs);
dr = new ChromeDriver(capabilities);
However I was not able to get this working, the default download directory was never changed to the specified directory once started. I am unsure if there is a problem with how I am trying to set this capability or if the problem lies elsewhere.
In the end I eventually used the solution proposed here:
http://dkage.wordpress.com/2012/03/10/mid-air-trick-make-selenium-download-files/
but I would like to know if it is possible to do this more cleanly but just setting the preferences directly instead of using the UI
Any help is appreciated, Thanks!
Update:
Surprisingly after updating Selenium 2 to version 2.24.1 (and to windows chrome 22), the code above with the Maps work as expected, the only problem now is that they deprecated the the use of the constructor ChromeDriver(DesiredCapabilities capabilities), and instead recommend I use the ChromeOptions class, which I cannot get working for the above scenario.
Below is the wiki page explaining the use of both ChromeOptions and DesiredCapabilities:
http://code.google.com/p/chromedriver/wiki/CapabilitiesAndSwitches
The Ruby bindings actually expands that to:
{
"download": {
"prompt_for_download": false,
"default_directory": "/path/to/dir"
}
}
Try building your Java prefs object like that and see if it works. The string vs boolean false could also be an issue.
Try this (Forgive my java which is quite rusty, but hopefully you get the idea)
Dictionary download = new Dictionary();
download["default_directory"] = "/path/to/dir";
Dictionary prefs = new Dictionary();
prefs["browser"] = download;
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability("chrome.prefs", prefs);
WebDriver driver = new ChromeDriver(capabilities);
Update: I just browsed the code and it seems that what I suggested above probably won't work. The ruby chrome profile class creates zip file with chrome profile file structure in it to support chrome preference. I couldn't find such facility code in java. There is a Firefox profile in java that does the simliar thing for firefox, but obviously that won't work for chrome. So in short, this feature is not supported yet in java.
Newer versions (I tested Chrome 44.0.2403.125, Selenium 2.47.1, and ChromeDriver 2.17.340128) work with the following:
ChromeOptions options = new ChromeOptions();
Map<String, Object> prefs = new HashMap<String, Object>();
prefs.put("download.default_directory", "/path/to/directory");
options.setExperimentalOption("prefs", prefs);
ChromeDriver chromeDriver = new ChromeDriver(options);

Categories