5

Here are the details of my Development Environment:

-Visual Studio 2012 Ultimate with Update 4

-Google Chrome Version 40.0.2214.94 m

-Windows 7 Professional with 32-bit Operating System

My Google Chrome browser's User Agent String is:

Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36

The C# code in my Automated UI test code is as follows:

var options = new PhantomJSOptions();

// Chrome User Agent ( Chrome Version 40.0.2214.94 m ) 
options.AddAdditionalCapability("phantomjs.page.settings.userAgent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36");

driver = new OpenQA.Selenium.PhantomJS.PhantomJSDriver(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\packages\PhantomJS.1.9.8\tools\phantomjs"), options);

url = new Uri("http://localhost:2816/");

IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(90.00));

wait.Until(ExpectedConditions.ElementIsClickable( By.XPath("//a[text()='Users']")));

IWebElement btn = waitArg.Until<IWebElement>((d) => {
 try{ 
 return d.FindElement( By.XPath("//a[text()='Users']") );
 }
 catch {

        return null;
    }  
  });

  btn.Click();

Unfortunately the above code is having a tough time finding the elements. I believe that if I could configure the PhantomJS driver used in my code to more closely emulate my Google Chrome Version 40.0.2214.94 m browser that is on my desktop then the Automated UI test code should be able to give more consistent and accurate testing results whenever the tests are run.

Could someone please suggest if I could make some modifications to the following code that will more closely emulate my Google Chrome Version 40.0.2214.94 m browser?

var options = new PhantomJSOptions();

// Chrome User Agent ( Chrome Version 40.0.2214.94 m ) 
 options.AddAdditionalCapability("phantomjs.page.settings.userAgent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36");

 driver = new OpenQA.Selenium.PhantomJS.PhantomJSDriver(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\packages\PhantomJS.1.9.8\tools\phantomjs"), options);

Update With Answer with help of @artjom-b

        var options = new PhantomJSOptions();

        options.AddAdditionalCapability("phantomjs.page.settings.userAgent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36");


        var service = PhantomJSDriverService.CreateDefaultService(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\packages\PhantomJS.1.9.8\tools\phantomjs"));

        service.SslProtocol = "any";
        driver = new PhantomJSDriver(service, options);
        url = new Uri("http://localhost:2816/");

        // 1280, height: 1024
        // @artjom-b strongly recommened that the Driver's Window Size be quite large.  Let's set the Window Size to quite large. 
        driver.Manage().Window.Size = new System.Drawing.Size(1280, 1024); // Size is a type in assembly "System.Drawing"
CS Lewis
  • 489
  • 8
  • 30
  • 1
    This is more like a problem with your application. PhantomJS is not, and never has been sold as, a replacement for a full browser like Chrome. It's clear something your application is doing isn't playing well with PhantomJS. – Arran Feb 03 '15 at 22:43

1 Answers1

7

PhantomJS is a standalone (headless) browser. You cannot configure it, so that it behaves like Chrome. There is simply nothing to configure when it comes to the rendering engine. There are some things you can do, so that PhantomJS behaves like an desktop browser.

The first thing is to set the viewport size to something big. PhantomJS run by default with a viewport of 400x300. The vieport expands for fixed width sites, but stays small for responsive sites. Depending on how the sites are written, some elements may be hidden and cannot be clicked on.
See: Setting screen size in PhantomJS C# being driven by Selenium

The second thing to do is to set the user agent string to something that approximates its capabilities best. PhantomJS 1.x is based on an old fork of QtWebKit. Chrome 13 is said to be most compatible with it.
Why does it matter? Some sites uses some "experimental" JavaScript when they encounter a new user agent. Use an old/matching user agent string so that sites which do this won't send funky JavaScript or other strange things that PhantomJS can't understand. Google does/did this for example.
User agent string:

Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41 Safari/535.1

PhantomJS 1.x uses SSLv3 by default and if the server doesn't support this (because of the POODLE vulnerability), the connection fails. Use any so that PhantomJS accepts all SSL/TLS connections that it understands.
See: A: Selenium Webdriver + PhantomJS remains at about:blank for a specific site

PhantomJS 1.x doesn't support Function.prototype.bind among other things. The selenium language bindings for C# support executing PhantomJS script snippets (not page script) through PhantomJSDriver.ExecutePhantomJS() which makes it possible to run a shim to retrofit PhantomJS with some necessary functions. Relevant commit as provided in the comments.

There are some things that you can't really do something about:

  • Clicking on a download link won't download anything. PhantomJS doesn't trigger downloads (and has maximum duration of 30 seconds for a manual download using XHR).
  • PDFs cannot be opened.
Community
  • 1
  • 1
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • Thx for the reply post. The User Agent String that you mentioned still only allows the PhantomJSDriver to find some of the elements. I suppose that it is difficult to configure PhantomJSDriver in such a way that it can only approximately emulate Google Chrome. However, if my attempts to implement the test code give these "false failure". "False Failure" in the sense that the PhantomJSDriver throws errors about failing to find elements then I would rather take a more practical approach by using a User Agent String that is more accurate. Could you please provide me with one? – CS Lewis Feb 03 '15 at 22:03
  • 1
    The user agent string rarely does anything. Most websites don't care about the user agent string. You definetly need to change the default viewport size, check that your selectors are correct, take screenshots to verify that the element is actually there, try to enable error reporting to see possible PhantomJS errors like bind or other. – Artjom B. Feb 03 '15 at 22:08
  • Thx. I use the following code for options: var options = new PhantomJSOptions(); options.AddAdditionalCapability("phantomjs.page.settings.userAgent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36"); You are correct in stating that the Window Size used by the PhantomJSDriver is important. Here is what I implemented: driver.Manage().Window.Size = new System.Drawing.Size(1280, 1024); – CS Lewis Feb 03 '15 at 23:04
  • As a point of interest, the .NET bindings **do**, in fact, support execution of PhantomJS-scoped script snippets. You just have to use the concrete `PhantomJSDriver` object, instead of the more common, and cross-browser, `IWebDriver` interface. – JimEvans Feb 04 '15 at 14:13
  • 2
    @ArtjomB. I'm not sure what you mean by "providing an SO link," but this feature has been in the .NET bindings for almost exactly a year as of this writing. You can see the commit where it was added in the GitHub mirror of the project's source code at https://github.com/SeleniumHQ/selenium/commit/72760b0c3283f9933d5ef32b657ee9a3aba99aa7 – JimEvans Feb 04 '15 at 19:43
  • @JimEvans Thanks, that is very helpful. I used the docs from [here](http://selenium.googlecode.com/git/docs/api/dotnet/index.html) where there is no such function. – Artjom B. Feb 04 '15 at 19:51