Using PhantomJS with Play
September 18, 2013
Play!
Play
Testing
PhantomJS
Out of the box for the Play framework, you have two options for browser based testing, Firefox or HtmlUnit.
Basically, you’ve got this test that is created for you when you generate a new Play application. Switch over the HTMLUNIT constant to FIREFOX
to begin using Firefox through webdriver.
@Test public void test() { running(testServer(3333, fakeApplication(inMemoryDatabase())), HTMLUNIT, new CallbackHtmlUnit (http://htmlunit.sourceforge.net/) does have a couple advantages over a real browser like Firefox.() { public void invoke(TestBrowser browser) { browser.goTo(“http://localhost:3333"); assertThat(browser.pageSource()).contains(“Your new application is ready.”); } }); }
- It’s Faster
- It’s headless, therefore doesn’t need a display. Useful in CI environments like Travis (https://travis-ci.org/). Yes you can use Xvfb (http://en.wikipedia.org/wiki/Xvfb) but that’s just another dependency. Also handy locally so you don’t have numerous browser windows popping up when running tests
So enter PhantomJS (http://phantomjs.org/). It’s a headless WebKit browser with a Javascript API. Being WebKit based, I’ve found that it supports Javascript much better than HtmlUnit.
So how do you integrate it into your Play application? In a few steps.
- Firstly, you need to install PhantomJS. There are a number of ways to achieve this, but I just use brew (http://brew.sh/). So I run the following command.
brew install phantomjs
On the phantomjs website (http://phantomjs.org/) there are instructions for other Operating Systems. -
Add GhostDriver (https://github.com/detro/ghostdriver) which is an implementation of WebDriver for PhantomJS. To achieve this go to your
Build.scala
and add GhostDriver.val appDependencies = Seq( // Add your project dependencies here, javaCore, javaJdbc, javaEbean, “com.github.detro.ghostdriver” % “phantomjsdriver” % “1.0.4” % “test” )
- Change the test to use GhostDriver.
public void test() { running(testServer(3333, fakeApplication(inMemoryDatabase())), org.openqa.selenium.phantomjs.PhantomJSDriver, new Callback
() { public void invoke(TestBrowser browser) { browser.goTo(“http://localhost:3333"); assertThat(browser.pageSource()).contains(“Your new application is ready.”); } }); } -
Re-run the test
$ play test
If everything has worked correctly, you should have output like the following2013-09-19 11:29:06.727 phantomjs[4326:707] *** WARNING: Method userSpaceScaleFactor in class NSView is deprecated on 10.7 and later. It should not be used in new applications. Use convertRectToBacking: instead. PhantomJS is launching GhostDriver… [INFO - 2013-09-19T01:29:06.832Z] GhostDriver - Main - running on port 15803 [INFO - 2013-09-19T01:29:06.993Z] Session [e04d1ec0-20ca-11e3-89ad-45bbd56cac5d] - _decorateNewWindow - page.settings: {“XSSAuditingEnabled”:false,“javascriptCanCloseWindows”:true,“javascriptCanOpenWindows”:true,“javascriptEnabled”:true,“loadImages”:true,“localToRemoteUrlAccessEnabled”:false,“userAgent”:“Mozilla/5.0 (Macintosh; PPC Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.2 Safari/534.34”,“webSecurityEnabled”:true} [INFO - 2013-09-19T01:29:06.993Z] Session [e04d1ec0-20ca-11e3-89ad-45bbd56cac5d] - page.customHeaders: - {} [INFO - 2013-09-19T01:29:06.993Z] Session [e04d1ec0-20ca-11e3-89ad-45bbd56cac5d] - CONSTRUCTOR - Desired Capabilities: {“platform”:“ANY”,“browserName”:“phantomjs”,“version”:“”} [INFO - 2013-09-19T01:29:06.993Z] Session [e04d1ec0-20ca-11e3-89ad-45bbd56cac5d] - CONSTRUCTOR - Negotiated Capabilities: {“browserName”:“phantomjs”,“version”:“1.9.2”,“driverName”:“ghostdriver”,“driverVersion”:“1.0.4”,“platform”:“mac-10.8 (Mountain Lion)-64bit”,“javascriptEnabled”:true,“takesScreenshot”:true,“handlesAlerts”:false,“databaseEnabled”:false,“locationContextEnabled”:false,“applicationCacheEnabled”:false,“browserConnectionEnabled”:false,“cssSelectorsEnabled”:true,“webStorageEnabled”:false,“rotatable”:false,“acceptSslCerts”:false,“nativeEvents”:true,“proxy”:{“proxyType”:“direct”}} [INFO - 2013-09-19T01:29:06.993Z] SessionManagerReqHand - _postNewSessionCommand - New Session Created: e04d1ec0-20ca-11e3-89ad-45bbd56cac5d [INFO - 2013-09-19T01:29:07.949Z] ShutdownReqHand - _handle - About to shutdown [info] IntegrationTest [info] + IntegrationTest.test [info] [info] [info] Total for test IntegrationTest [info] Finished in 0.0 seconds
- You can also take screenshots with PhantomJS, which is very useful for diagnosing failures and debugging.
@Test public void test() { running(testServer(3333, fakeApplication(inMemoryDatabase())), org.openqa.selenium.phantomjs.PhantomJSDriver.class, new Callback() { public void invoke(TestBrowser browser) { browser.goTo(“http://localhost:3333"); assertThat(browser.pageSource()).contains(“Your new application is ready.”); browser.takeScreenShot(“/tmp/screenshot.jpg”); } }); }
Happy testing!