• Stars
    star
    1,915
  • Rank 24,206 (Top 0.5 %)
  • Language
    Java
  • License
    BSD 2-Clause "Sim...
  • Created over 12 years ago
  • Updated almost 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Ghost Driver is an implementation of the Remote WebDriver Wire protocol, using PhantomJS as back-end

Release FOSSA Status

Ghost Driver

Ghost Driver is a pure JavaScript implementation of the WebDriver Wire Protocol for PhantomJS. It's a Remote WebDriver that uses PhantomJS as back-end.

GhostDriver is designed to be integral part of PhantomJS itself, but it's developed in isolation and progress is tracked by this Repository.

  • Current GhostDriver stable version: see releases
  • PhantomJS-integrated version is "1.2.0" (detro@2af7099a9) : contained in PhantomJS "2.1.1"
  • Current PhantomJSDriver Java bindings stable version: see Maven

For more info, please take a look at the changelog.

The project was created and is lead by Ivan De Marino.

IRC channel: #phantomjs-ghostdriver.

Setup

  • Download latest stable PhantomJS from here
  • Selenium version ">= 3.1.0"

THAT'S IT!! Because of latest stable GhostDriver being embedded in PhantomJS, you shouldn't need anything else to get started.

Register GhostDriver with a Selenium Grid hub

  1. Launch the grid server, which listens on 4444 by default: java -jar /path/to/selenium-server-standalone-<SELENIUM VERSION>.jar -role hub
  2. Register with the hub: phantomjs --webdriver=8080 --webdriver-selenium-grid-hub=http://127.0.0.1:4444
  3. Now you can use your normal webdriver client with http://127.0.0.1:4444 and just request browserName: phantomjs

(Java) Bindings

This project provides WebDriver bindings for Java under the name PhantomJSDriver. Here is the JavaDoc.

Bindings for other languages (C#, Python, Ruby, ...) are developed and maintained under the same name within the Selenium project itself.

Include Java Bindings in your Maven project

For versions >= 2.0.0, add the following to your pom.xml:

<repositories>
  <repository>
      <id>jitpack.io</id>
      <url>https://jitpack.io</url>
  </repository>
</repositories>
<dependency>
    <groupId>com.github.detro</groupId>
    <artifactId>ghostdriver</artifactId>
    <version>2.1.0</version>
</dependency>

Include Java Bindings in your Gradle project

Just add the following to your build.gradle:

allprojects {
  repositories {
    maven { url 'https://jitpack.io' }
  }
}
dependencies {
    ...
    testCompile 'com.github.detro:ghostdriver:2.1.0'
    ...
}

Alternative: how to use it via RemoteWebDriver

Launching PhantomJS in Remote WebDriver mode it's simple:

$ phantomjs --webdriver=PORT

Once started, you can use any RemoteWebDriver implementation to send commands to it. I advice to take a look to the /test directory for examples.

F.A.Q.

What extra WebDriver capabilities GhostDriver offers?

  • GhostDriver extra Capabilities
    • phantomjs.page.settings.SETTING = VALUE - Configure page.settings on PhantomJS internal page objects (windows in WebDriver context) (see reference)
    • phantomjs.page.customHeaders.HEADER = VALUE - Add extra HTTP Headers when loading a URL (see reference)
    • phantomjs.page.whitelist - an array of regex expressions of urls to accept. eg. ['my-awesome-website.com']
    • phantomjs.page.blacklist - array of regex expressions of urls to ignore. The blacklist overrides the whitelist. eg. ['google.com', 'github.com']
    • unhandledPromptBehavior - set to dismiss to automatically dismiss all user prompts or set to accept to automatically accept all user prompts
    • loggingPrefs - ghostdriver has two logs browser and har. The logs default to "OFF". follow the DesiredCapabilities documentation to enable the logs.
  • PhantomJSDriver Java-binding Capabilities
    • phantomjs.binary.path - Specify path to PhantomJS executable to use
    • phantomjs.ghostdriver.path - Specify path to GhostDriver main/src.js script to use; allows to use a different version of GhostDriver then the one embed in PhantomJS
    • phantomjs.cli.args - Specify command line arguments to pass to the PhantomJS executable
    • phantomjs.ghostdriver.cli.args - Specify command line argument to pass to GhostDriver (works only in tandem with phantomjs.ghostdriver.path)

Want to help? Read on!

GhostDriver pushed the evolution of PhantomJS from the start. All the features required by PhantomJS to fit GhostDriver were designed to still feel "consistent" and "at home" with PhantomJS alone.

To drive that effort, I worked on a PhantomJS fork, and then pushed changes to PhantomJS master once agreed with the rest of the team on the changes.

If you are planning to contribute, that is the PhantomJS you should use.

Run validation tests

Here I show how to clone this repo and kick start the (Java) tests. You need Java SDK to run them. ghostdriver requires Java 1.8.

  1. git clone https://github.com/detro/ghostdriver.git
  2. Configure phantomjs_exec_path inside ghostdriver/test/config.ini to point at the build of PhantomJS you just did
  3. cd ghostdriver/test/java; ./gradlew test

Alternative: Run GhostDriver yourself and launch tests against that instance

  1. phantomjs --webdriver=PORT
  2. Configure driver inside ghostdriver/test/config.ini to point at the URL http://localhost:PORT
  3. cd ghostdriver/test/java; ./gradlew test

Project Directory Structure

Here follows the output of the tree -hd -L 3 command, trimmed of files and "build directories":

.
├── [ 102]  binding
│   └── [ 510]  java
│       ├── [ 204]  build
│       ├── [ 136]  gradle
│       ├── [ 884]  jars            <--- JARs containing Binding, related Source and related JavaDoc
│       └── [ 102]  src             <--- Java Binding Source
├── [ 442]  src                     <--- GhostDriver JavaScript core source
│   ├── [ 306]  request_handlers    <--- JavaScript "classes/functions" that handle HTTP Requests
│   └── [ 204]  third_party         <--- Third party/utility code
│       └── [2.0K]  webdriver-atoms <--- WebDriver Atoms, automatically imported from the Selenium project
├── [ 204]  test
│   ├── [ 476]  java                <--- Java Tests
│   │   ├── [ 136]  gradle
│   │   ├── [ 136]  out
│   │   └── [ 102]  src
│   ├── [ 238]  python              <--- Python Tests
│   │   └── [ 102]  utils
│   └── [ 340]  testcase-issue_240
└── [ 238]  tools                   <--- Tools (import/export)
    └── [ 136]  atoms_build_dir

20 directories

WebDriver Atoms

Being GhostDriver a WebDriver implementation, it embeds the standard/default WebDriver Atoms to operate inside open webpages. In the specific, the Atoms cover scenarios where the "native" PhantomJS require('webpage') don't stretch.

Documentation about how those work can be found here and here.

How are those Atoms making their way into GhostDriver? If you look inside the /tools directory you can find a bash script: /tools/import_atoms.sh. That script accepts the path to a Selenium local repo, runs the CrazyFunBuild to produce the compressed/minified Atoms, grabs those and copies them over to the /src/third_party/webdriver-atoms directory.

The Atoms original source lives inside the Selenium repo in the subtree of /javascript. To understand how the build works, you need to spend a bit of time reading about CrazyFunBuild: worth your time if you want to contribute to GhostDriver (or any WebDriver, as a matter of fact).

One thing it's important to mention, is that CrazyFunBuild relies on the content of build.desc file to understand what and how to build it. Those files define what exactly is built and what it depends on. In the case of the Atoms, the word "build" means "run Google Closure Compiler over a set of files and compress functions into Atoms". The definition of the Atoms that GhostDriver uses lives at /tools/atoms_build_dir/build.desc.

Let's take this small portion of our build.desc:

js_library(name = "deps",
  srcs = "*.js",
  deps = ["//javascript/atoms:deps",
          "//javascript/webdriver/atoms:deps"])

js_fragment(name = "get_element_from_cache",
  module = "bot.inject.cache",
  function = "bot.inject.cache.getElement",
  deps = [ "//javascript/atoms:deps" ])

js_library(name = "build_atoms",
  deps = [
    ...
    "//javascript/webdriver/atoms:execute_script",
    ...
  ]

The first part (js_library(name = "deps"...) declares what are the dependency of this build.desc: with that CrazyFunBuild knows what to build before fulfilling our build.

The second part (js_fragment(...) defines an Atom: the get_element_from_cache is going to be the name of an Atom to build; it can be found in the module bot.inject.cache and is realised by the function named bot.inject.cache.getElement.

The third part (js_library(name = "build_atoms"...) is a list of the Atoms (either defined by something like the second part or in one of the files we declared as dependency) that we want to build.

If you reached this stage in understanding the Atoms, you are ready to go further by yourself.

Contributions and/or Bug Report

You can contribute by testing GhostDriver, reporting bugs and issues, or submitting Pull Requests. Any help is welcome, but bear in mind the following base principles:

  • Issue reporting requires a reproducible example, otherwise will most probably be closed without warning
  • Squash your commits by theme: I prefer a clean, readable log
  • Maintain consistency with the code-style you are surrounded by
  • If you are going to make a big, substantial change, let's discuss it first
  • I HATE CoffeeScript: assume I'm going to laugh off any "contribution" that contains such aberrational crap!
  • Open Source is NOT a democracy (and I mean it!)

License

GhostDriver is distributed under BSD License.

FOSSA Status

Release names

See here.

More Repositories

1

consoleplusplus

Console++ - enhance your console
JavaScript
140
star
2

phantomjs-jasminexml-example

PhantomJS - Jasmine XML - Example Project Layout
JavaScript
41
star
3

jasmine-jsreporter

Jasmine JS Reporter - The purpose of this reporter is to make it easier to extract informations about the executed Test Results, without having to parse the DOM. The results are just a plain JavaScript Object (aka JSON)..
JavaScript
19
star
4

coding-exercises

The kind of stuff a Developer will meet in his life when he is 1) studying for exams 2) preparing for interview 3) having fun. Nothing structured or organized: just plain C, C++ and possibly other languages to come.
C
15
star
5

.bashrc.d

My personal ~/.bashrc.d
Shell
11
star
6

qtoolbox

qtoolbox is a set of tools for everyday Qt development
C++
9
star
7

gredirector

Permanent Redirect URLs (HTTP 301 Status Code) through Google App Engine
Python
6
star
8

srvzio

An helpful crate to implement services
Rust
6
star
9

browsermob-proxy-client

Java client library to install, launch and control a BrowserMob Proxy exclusively via it's REST API
Java
5
star
10

node-caronte-proxy

Simple HTTP(S) Proxy, suitable to test proxying during development
JavaScript
5
star
11

sulfur

Sulfur - Just one more level of abstraction
Java
4
star
12

rock-paper-scissors

Implementation of Rock-Paper-Scissors as Java based webapp, made of a RESTful API + WebUI
Java
3
star
13

QDetroBro

Qt on S60 based Browser. It's experimental, non-functionally complete (not even trying to), and rips off code from the great Qt Labs example applications.
C++
2
star
14

detro.github.io

ivandemarino.me blog, pages and more madness
Less
2
star
15

bytes_parser

A simple wrapper to parse primitive Rust types from a slice of bytes.
Rust
2
star
16

CronExplainer

This is a simple utility, written in Java and using Gradle, that accepts as input arguments a line of Cron configuration, and prints out an _"explaination"_ for it.
Java
1
star
17

go-checkit

Go
1
star
18

timesince.js

Forward Counter (JavaScript utility)
JavaScript
1
star
19

jsonconf

JSON based configuration utility with some cool features
Java
1
star
20

detro

1
star