Setting device name in serenity.properties file for chrome driver - selenium-chromedriver

How do I set the mobile emulation for Nexus 5 view in Serenity managed chrome driver?
I tried going through this link:
https://johnfergusonsmart.com/configuring-chromedriver-easily-with-serenity-bdd/
Which explain setting preferences for chrome.
Chrome preferences
You can also provide more advanced options using the setExperimentalOption() method:
Map<String, Object> chromePrefs = new HashMap<String, Object>();
chromePrefs.put("download.default_directory", downLoadDirectory);
chromePrefs.put("profile.default_content_settings.popups", 0);
chromePrefs.put("pdfjs.disabled", true);
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("prefs", chromePrefs);
In Serenity, you would pass these using properties prefixed with the chrome_preferences prefix, e.g.
chrome_preferences.download.default_directory = /my/download/directory
chrome_preferences.profile_default_content_settings.popups = 0
chrome_preferences.pdfjs.disabled=true
From this, I tried setting the mobileEmulation as
chrome.capabilities.mobile_emulation.device_name= Google Nexus 5
chrome.options.mobileEmulation.deviceName= Google Nexus 5
and a few other logical variants, but none of them succeeded.

The best way I found to help me in this issue it to create a custom WebDriver.
I had to create a class which extends DriverSource. And then link it to the Serenity Properties file. This will give me the driver I need.
http://www.thucydides.info/docs/serenity/#_custom_webdriver_implementations
You can add your own custom WebDriver provider by implementing the
DriverSource interface. First, you need to set up the following system
properties (e.g. in your serenity.properties file):
webdriver.driver = provided
webdriver.provided.type = mydriver
webdriver.provided.mydriver = com.acme.MyPhantomJSDriver
thucydides.driver.capabilities = mydriver
Your custom driver must implement the DriverSource interface, as shown
here:
public class MyPhantomJSDriver implements DriverSource {
#Override
public WebDriver newDriver() {
try {
DesiredCapabilities capabilities = DesiredCapabilities.phantomjs();
// Add
return new PhantomJSDriver(ResolvingPhantomJSDriverService.createDefaultService(),
capabilities);
}
catch (IOException e) {
throw new Error(e);
}
}
#Override
public boolean takesScreenshots() {
return true;
}
}
This driver will now take screenshots normally.

Related

TestNG not running #Test for Firefox Driver -- Chrome working

I am building Selenium WebDriver tests for Chrome and Firefox in Eclipse using TestNG. When I run the testng.xml file as a TestNG Suite, it opens the Firefox browser, but does not enter the #Test method in the class file. It does the #BeforeClass method just fine.
However, when I have virtually the same code but for Chrome, it works fine - it enters the #Test method and everything is golden.
Any idea why it would enter the #Test method for Chrome, but not Firefox?
Here is the code for my class:
public class TestFireFox {
private WebDriver driver;
#BeforeClass
public void beforeClass() {
System.out.println("Running TestFireFox Class");
driver = new FirefoxDriver();
System.setProperty("webdriver.gecko.driver", "geckodriver");
}
#AfterClass
public void afterClass() {
driver.quit();
}
#Test
public void verifySearchButton() {
System.out.println("Inside Verify Method");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://www.google.com");
String search_text = "Google Search";
WebElement search_button = driver.findElement(By.name("btnK"));
String text = search_button.getAttribute("value");
Assert.assertEquals(text, search_text, "Text not found!");
}
}
The problem might be the order of statements. You need setProperty before instatiate Firefox.
System.setProperty("webdriver.gecko.driver", "path\\to\\geckodriver.exe");
driver = new FirefoxDriver();

How to download a file with Selenium and ChromeDriver

I have a website to test with selenium and ChromeDriver (on windows), where I like to test the functionality to export data and import it again.
The export creates a xml file that is downloaded on ones computer. When running this with webdriver, Chrome asks me whether to keep the file or discard it, as it might be a potential threat.
How can I switch off this behavior inside my test ? Is there a chrome setting I can use, so that a file is no matter what downloaded ?
Thanks
Try this. Executed on windows
(How to control the download of files with Selenium Python bindings in Chrome)
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_experimental_option("prefs", {
"download.default_directory": r"C:\Users\xxx\downloads\Test",
"download.prompt_for_download": False,
"download.directory_upgrade": True,
"safebrowsing.enabled": True
})
The below Program will help you to download the files in Chrome with
Desired-Capabilities. It is a rich class having lot of utilities, you can go through it in your free time.
public class DownloadChromeFile {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver","./chromedriver.exe");
String downloadFilepath = "c:\\download";
HashMap<String, Object> chromePrefs = new HashMap<String, Object>();
chromePrefs.put("profile.default_content_settings.popups", 0);
chromePrefs.put("download.default_directory", downloadFilepath);
ChromeOptions options = new ChromeOptions();
HashMap<String, Object> chromeOptionsMap = new HashMap<String, Object>();
options.setExperimentalOption("prefs", chromePrefs);
options.addArguments("--test-type");
options.addArguments("--disable-extensions"); //to disable browser extension popup
DesiredCapabilities cap = DesiredCapabilities.chrome();
cap.setCapability(ChromeOptions.CAPABILITY, chromeOptionsMap);
cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true); // Bydefault it will accepts all popups.
cap.setCapability(ChromeOptions.CAPABILITY, options);
driver = new ChromeDriver(cap);
driver.get("Your Application Url");
driver.findElement(By.xpath("Export Button xpath")).click();
}
}

Multi-client remote debugging using ChromeDriver and Chrome DevTools protocol

So with Chrome 63 there is now support for Multi-client remote debugging (https://developers.google.com/web/updates/2017/10/devtools-release-notes)
What I want to achieve is use the Chrome DevTools Protocol HeapProfiler with some selenium tests. I'm running version 64 Chrome dev channel and ChromeDriver 2.33.
ChromeOptions options = newChromeOptions();
options.addArguments("--remote-debugging-port=9222");
WebDriver driver = new ChromeDriver(options);
... selenium stuff
A new chrome window will open and hang until it times out. I can confirm that the chrome window opened is chrome 64 by going to help > about google chrome to check the version.
I get this error which appears to be the the webdriver losing connection.
Exception in thread "main" org.openqa.selenium.WebDriverException: chrome not
reachable
The DevTools Protocol is working because I am able to open http://localhost:9222 in another chrome window and see debugging interface.
Has anyone been able to get these two things to work together?
Thanks :)
Here the catch was that if you pass the "remote-debugging-port" switch then chromedriver has a bug where it still internally assigns a randon port and keep trying to connect to it rather than connecting to 9222 port.
options.addArguments("--remote-debugging-port=9222");
We can solve this by skipping this command switch and let chrome decides this random port and extract this port number from chromedriver logs.
I made it work and here I have blogged it in detail.
https://medium.com/#sahajamit/selenium-chrome-dev-tools-makes-a-perfect-browser-automation-recipe-c35c7f6a2360
Selenium 4 release will have a user friendly API for Chrome DevTools protocol. I just finished implementing Network and Performance domains for the Selenium Java client. https://github.com/SeleniumHQ/selenium/pull/7212
In addition, there is a generic API for all domains in Java client that was merged a while ago. All those new features will be released probably in the next Alpha release.
This is a nice article on how to use Log:
https://codoid.com/selenium-4-chrome-devtools-log-entry-listeners/
Here is what i do to get the information needed fro remotedebugging nd additionally to prevent defining the port. I get it through the SeleniumLog-API
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
ChromeOptions options = new ChromeOptions();
options.setBinary(chromeBin);
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
LoggingPreferences logPref = new LoggingPreferences();
logPref.enable(LogType.DRIVER, Level.ALL);
driverInstance = new ChromeDriver(capabilities);
LogEntries x = driverInstance.manage().logs().get(LogType.DRIVER);
for(LogEntry e:x.getAll()){
if(e.getMessage().contains("DevTools request:")){
String url = e.getMessage().replaceFirst("DevTools request:", "").trim();
}
if(e.getMessage().contains("DevTools response:")){
String json = e.getMessage().replaceFirst("DevTools response:", "");
try {
if("page".equals(JSONUtil.get(json,"type" ))){
webSocketDebuggerUrl = JSONUtil.get(json,"webSocketDebuggerUrl" );
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
System.out.println(e.getMessage());
}
The JSONUtil i use is my own tool, so don't wonder, just replace with whatever code to extract from the jsontext.
Here's a fairly robust implementation in java using the same target tab with selenium 3.13 & cdp4j 3.0.2-SNAPSHOT. Easily translates to any language.
package com.company;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import io.webfolder.cdp.session.SessionFactory;
import org.openqa.selenium.HasCapabilities;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
public class Main {
public static void main(String[] args) {
System.setProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY, "C:\\path\\to\\chromedriver.exe");
var driver = new ChromeDriver();
try {
var cdp = findCdpEndpoint(driver);
System.out.println(cdp.toString());
try (var factory = new SessionFactory(cdp.getPort())) {
driver.navigate().to("https://google.com");
String seTargetId = getSeTargetId(cdp, driver.getTitle());
try (var session = factory.connect(seTargetId)) {
session.waitDocumentReady();
session.sendKeys("Astronauts");
driver.getKeyboard().sendKeys(Keys.RETURN);
session.wait(2000);
driver.navigate().to("http://www.google.com");
session.waitDocumentReady();
}
}
} catch (Exception ex) {
System.out.println(ex.toString());
}
driver.quit();
}
private static String getSeTargetId(URL cdp, String title) throws IOException {
for (JsonElement element : new JsonParser().parse(new InputStreamReader(cdp.openStream(), "UTF-8")).getAsJsonArray()) {
var object = element.getAsJsonObject();
if (title == null || title.isEmpty()
? object.get("type").getAsString().equalsIgnoreCase("page")
: object.get("title").getAsString().equalsIgnoreCase(title)) {
return object.get("id").getAsString();
}
}
throw new IllegalStateException("Selenium target not found.");
}
private static URL findCdpEndpoint(WebDriver driver) throws IOException {
var capChrome = (Map<?,?>) ((HasCapabilities)driver).getCapabilities().getCapability("chrome");
var userDataDir = (String) capChrome.get("userDataDir");
var port = Integer.parseInt(Files.readAllLines(Paths.get(userDataDir, "DevToolsActivePort")).get(0));
return new URL("http", "localhost", port, "/json");
}
}

CameraPreviewImageSource empty preview frame

I made cut and paste of the code below about how to use CameraPreviewImageSource and access to preview buffer frames, but do not work and it seems the frame buffer size is 0x0 reading the value of IImageSize parameter of OnPreviewFrameAvailable event.
How to get preview buffer of MediaCapture - Universal app
protected override void OnNavigatedTo(NavigationEventArgs e)
{
InitializeAsync();
}
public async void InitializeAsync()
{
_cameraPreviewImageSource = new CameraPreviewImageSource();
await _cameraPreviewImageSource.InitializeAsync(string.Empty);
var properties = await _cameraPreviewImageSource.StartPreviewAsync();
var width = 640.0;
var height = 480;
_writeableBitmap = new WriteableBitmap((int)width, (int)height);
_writeableBitmapRenderer = new WriteableBitmapRenderer(_cameraPreviewImageSource, _writeableBitmap);
Initialized = true;
_cameraPreviewImageSource.PreviewFrameAvailable += OnPreviewFrameAvailable;
}
private async void OnPreviewFrameAvailable(IImageSize args)
{
System.Diagnostics.Debug.WriteLine("ww:"+args.Size.Width+" hh:"+args.Size.Height);
// Prevent multiple rendering attempts at once
if (Initialized && !_isRendering)
{
_isRendering = true;
try
{
await _writeableBitmapRenderer.RenderAsync();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("\n\n"+ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
_isRendering = false;
}
}
Capabilities (webcam & microphone) on Package.appxmanifest has been selected
Implementing CameraPreviewImageSource on a Silverlight app works great!
I am afraid you are (were) seeing a bug in Lumia Imaging SDK 2.0.184. The problem only occured on some camera models and only on 8.1/universal applications. Silverlight applications were not affected by the problem.
The bug has been fixed in the newly released Lumia Imaging SDK 2.0.208. From release notes:
Fixed ArgumentOutOfRangeException being thrown by CameraPreviewImageSource when used with certain camera models.

webengine crash on Javafx 2.2.25

I am finding a issue when loading a html file in javafx using webEngine.
But in my case if i use java update 9 everything works fine but when i use any update after that like java update 25 with javafx version 2.2.25 ... the app crashes with EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000006e103b24, pid=7644, tid=8180.
here is what i am trying to do:
WebView webView = new WebView();
webEngine = webView.getEngine();
JSObject window = (JSObject) webEngine.executeScript("window"); // Crashes at this point but everything works fine with older version of java fx.
window.setMember("javafx", baseui);
scene = new Scene(webView, 1000, 800);
primaryStage = stage;
stage.setScene(scene);
stage.show();
stage.setIconified(true);
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>(){
#Override
public void changed(ObservableValue<? extends State> ov, State oldState, State newState) {
if(newState == State.SUCCEEDED){
JSObject window = (JSObject)webEngine.executeScript("window");
window.setMember("javafx", baseui);
}
}
});
URL urlHello = getClass().getResource("*.html"); // My HTML file
webEngine.load(urlHello.toExternalForm());
I tried solutions in this post like Platform.RunLater but of no help.
Is this bug fixed?? Any help is appreciated.
Thanks,
nitin