Skip to content

Commit

Permalink
LukeIS: adding phantomjs to python bindings, requires one to get both…
Browse files Browse the repository at this point in the history
… phantomjs and ghostdriver as described in ghostdriver README. Also updating the rake task to be able to run the python tests against it './go //py:phantomjs_test:run' my last run showed these pretty good results: 43 failed, 338 passed, 9 skipped, 3 xfailed in 181.52 seconds

r18141
  • Loading branch information
lukeis committed Nov 14, 2012
1 parent ba9eb76 commit c6d5144
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 12 deletions.
10 changes: 5 additions & 5 deletions py/build.desc
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ py_test(
browsers = [ "ff" ])

py_test(
name = "ghostdriver_test",
gd_specific_tests = [ "test/selenium/webdriver/ghostdriver/*_tests.py" ],
deps = [ ":test_gd" ],
browsers = [ "gd" ])
name = "phantomjs_test",
gd_specific_tests = [ "test/selenium/webdriver/phantomjs/*_tests.py" ],
deps = [ ":test_phantomjs" ],
browsers = [ "phantomjs" ])


py_test(
Expand Down Expand Up @@ -65,7 +65,7 @@ py_test(
"chrome",
"ff",
"ie",
"gd",
"phantomjs",
"remote_firefox",
"opera"
])
1 change: 1 addition & 0 deletions py/selenium/webdriver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from chrome.options import Options as ChromeOptions
from ie.webdriver import WebDriver as Ie
from opera.webdriver import WebDriver as Opera
from phantomjs.webdriver import WebDriver as PhantomJS
from remote.webdriver import WebDriver as Remote
from common.desired_capabilities import DesiredCapabilities
from common.action_chains import ActionChains
Expand Down
8 changes: 8 additions & 0 deletions py/selenium/webdriver/common/desired_capabilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,11 @@ class DesiredCapabilities(object):
"platform": "ANDROID",
"javascriptEnabled": True,
}

PHANTOMJS = {
"browserName":"phantomjs",
"version": "",
"platform": "ANY",
"javascriptEnabled": True,
}

13 changes: 13 additions & 0 deletions py/selenium/webdriver/phantomjs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2012 Software Freedom Conservancy
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
93 changes: 93 additions & 0 deletions py/selenium/webdriver/phantomjs/service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/usr/bin/python
#
# Copyright 2012 Software Freedom Conservancy
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import subprocess
import time

from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common import utils

class Service(object):
"""
Object that manages the starting and stopping of PhantomJS / Ghostdriver
"""

def __init__(self, executable_path, ghostdriver_path, port=0, service_args=None):
"""
Creates a new instance of the Service
:Args:
- executable_path : Path to the ChromeDriver
- port : Port the service is running on """

self.port = port
self.path = executable_path
self.service_args= service_args
if self.port == 0:
self.port = utils.free_port()
if self.service_args is None:
self.service_args = []
self.service_args.insert(0, self.path)
self.service_args.append(ghostdriver_path)
self.service_args.append("%d" % self.port)
self._log = open("ghostdriver.log", 'w')

def start(self):
"""
Starts the ChromeDriver Service.
:Exceptions:
- WebDriverException : Raised either when it can't start the service
or when it can't connect to the service
"""
try:
print "Starting process:", self.path
self.process = subprocess.Popen(self.service_args,
stdout=self._log, stderr=self._log)
except:
raise WebDriverException("Unable to start phantomjs with ghostdriver.")
count = 0
while not utils.is_connectable(self.port):
count += 1
time.sleep(1)
if count == 30:
raise WebDriverException("Can not connect to GhostDriver")

@property
def service_url(self):
"""
Gets the url of the GhostDriver Service
"""
return "http://localhost:%d/wd/hub" % self.port

def stop(self):
"""
Cleans up the process
"""
if self._log:
self._log.close()
self._log = None
#If its dead dont worry
if self.process is None:
return

#Tell the Server to properly die in case
try:
if self.process:
self.process.kill()
self.process.wait()
except WindowsError:
# kill may not be available under windows environment
pass
75 changes: 75 additions & 0 deletions py/selenium/webdriver/phantomjs/webdriver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/python
#
# Copyright 2012 Software freedom conservancy
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import base64
import httplib
from selenium.webdriver.remote.command import Command
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.common.exceptions import WebDriverException
from service import Service

class WebDriver(RemoteWebDriver):
"""
Wrapper to communicate with PhantomJS through Ghostdriver.
You will need to follow all the directions here:
https://github.com/detro/ghostdriver
"""

def __init__(self, ghostdriver_path, executable_path="phantomjs",
port=0, desired_capabilities=DesiredCapabilities.PHANTOMJS):
"""
Creates a new instance of the PhantomJS / Ghostdriver.
Starts the service and then creates new instance of the driver.
:Args:
- ghostdriver_path - path to ghostdriver/src/main.js
- executable_path - path to the executable. If the default is used it assumes the executable is in the $PATH
- port - port you would like the service to run, if left as 0, a free port will be found.
- desired_capabilities: Dictionary object with non-browser specific
capabilities only, such as "proxy" or "loggingPref".
"""
self.service = Service(executable_path, ghostdriver_path, port=port)
self.service.start()

try:
RemoteWebDriver.__init__(self,
command_executor=self.service.service_url,
desired_capabilities=desired_capabilities)
except:
self.quit()
raise

def quit(self):
"""
Closes the browser and shuts down the PhantomJS executable
that is started when starting the PhantomJS
"""
try:
RemoteWebDriver.quit(self)
except:
# We don't care about the message because something probably has gone wrong
pass
finally:
self.service.stop()

def __del__(self):
try:
self.service.stop()
except:
pass
14 changes: 7 additions & 7 deletions rake-tasks/browsers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,15 @@
:browser_name => "opera",
:available => opera?
},
"gd" => {
"phantomjs" => {
:python => {
:ignore => "ghostdriver",
:dir => "ghostdriver",
:file_string => "gd",
:class => "Remote",
:constructor_args => "'http://localhost:8080/wd/hub', {}"
:ignore => "phantomjs",
:dir => "phantomjs",
:file_string => "phantomjs",
:class => "PhantomJS",
:constructor_args => "'../ghostdriver/src/main.js'"
},
:browser_name => "ghostdriver",
:browser_name => "phantomjs",
},
"remote_firefox" => {
:python => {
Expand Down

0 comments on commit c6d5144

Please sign in to comment.