A simple Application showing how to run Headless Chrome via ChromeDriver with Hound; further configuration and customisation may be required for you to adopt this application in your project.
- Run Headless Chrome directly via Exexec (which wraps Erlexec).
- Run Chrome Driver directly via Exexec as well.
- Configure Chrome Driver to talk with Headless Chrome directly via Remote Debugging.
- Expose this via a custom Hound session builder so anything Hound does can be used.
This gives us much better control over what’s run, at what time, and under what terms, instead of ceding control over spawning of child OS processes to third-party dependencies. (For example, Chrome Driver is set to detach by default — see Capabilities & Options — yet when the SIGTERM signal is sent to BEAM, only Chrome and not Chrome Driver is terminated.)
Tested with: Elixir 1.4.4, Erlang/OTP 19, HomeBrew/macOS.
➜ evadne-kennel git:(master) iex -S mix
Erlang/OTP 19 [erts-8.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.4.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Kennel.ChromeDriver.start_session
"93ed4f4cf6534b901b850bbaa99cc9ec"
iex(2)> Hound.current_session_id
"93ed4f4cf6534b901b850bbaa99cc9ec"
Then onwards with your desired Hound interaction.
For example:
iex(3)> use Hound.Helpers
Hound.Helpers
iex(4)> navigate_to "https://google.com"
nil
iex(5)> page_title()
"Google"
Please note that Chrome Driver achieves certain behaviour via an “automation” extension which needs to be loaded as Chrome is started.
This should be doable via the --load-extension argument which is then passed to Chrome, but it is currently not in place and may cause you issues and the unpacked version of such extension is currently not easily located.
You may be tempted to modify Kennel.chrome_command and pass something like this,
--load-extension="/Users/evadne/Works/Code/bayandin-chromedriver/extension"
but it will not work, because Chrome Driver explicitly bails from ChromeRemoteImpl::GetAsDesktop, so any call going through ChromeRemoteImpl::GetAsDesktop will not work (and not even tried). Therefore, methods that have to do with screenshots and window sizes do not work at the moment.
Please note that in Chrome 60 (beta out very recently), the screenshot feature may have been repaired:
With Capybara, there is a possibility to take a screenshot during your tests (or automatically on a failure). This feature results in an empty gray image on headless Chrome 59 but the proper behavior is restored on Chrome 60 (in beta as of today).
ps. As a workaround, if you really want to make screenshots, you can make a <canvas>, draw into it, then use Hound.ScriptExecution to pass the results back, like what Panic’s Coda Notes did.
-
Actually run multiple copies Chrome + Chrome Driver each with its isolated port, process space and user profile. This is because Hound’s support for multiple sessions is at least a little bit wonky.
When run against Headless Chrome,
change_session_toactually spins up a new Chrome Driver managed instance of Chrome. And callingKennel.start_sessiona second time inTask.asyncsimply times out. So the entire Sessions API in Hound is to not be used and a replacement against some kind of pooling mechanism needs to be written. -
Write a Self-Test routine within Kennel.start_session and raise error if resultant connection is no good.
This project is under the MIT license.
- Special thanks to Mr Jim Gray for identifying the relevant Hound issue that allows it to work with Headless Chrome in the first place.