Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configure browser capabilities through YAML #36

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 53 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Requirements
============

* `lettuce <http://lettuce.it/>`_
* `selenium 2.8 or higher <http://pypi.python.org/pypi/selenium>`_
* `selenium 2.30 or higher <http://pypi.python.org/pypi/selenium>`_

Setting Up lettuce_webdriver
============================
Expand All @@ -24,12 +24,60 @@ learn about the additional step definitions provided by
desired::

from lettuce import before, world
from selenium import webdriver
import lettuce_webdriver.webdriver

import lettuce_webdriver

@before.all
def setup_browser():
world.browser = webdriver.Firefox()
world.browser = lettuce_webdriver.initialize('browsers.yaml', 'firefox')

@after.all
def destroy_browser():
world.browser.quit()


Where ``firefox`` is your default driver to use and ``browsers.yaml`` contains
your browser configurations::

firefox:
webdriver: firefox

remote-ie:
webdriver: ie
remote: true
host: int-selenium-hub
capabilities:
version: 10

Accepted parameters are ``webdriver``, ``remote``, ``host``, ``hub`` and
``capabilities``. ``browsers.yaml`` normalizes ``capabilities`` and
``desired_capabilities`` based on webdriver.

The default webdriver, host and hub can be overridden using the ``WEBDRIVER``,
``WEBDRIVER_HOST`` and ``WEBDRIVER_HUB`` environment variables respectively::

WEBDRIVER=remote-ie lettuce

You can use YAML includes to set configuration for a common service, e.g.
your Selenium hub, or Browserstack::

defaults:
- &browserstack
remote: true
host: hub.browserstack.com
- &browserstack_key
browserstack.user: mr.lettuce
browerstack.key: abcd1234

browserstack-ie10:
<<: *browserstack
webdriver: ie
capabilities:
<<: *browserstack_key
version: 10

The old method for setting up lettuce_webdriver, where you defined your
WebDriver yourself is still supported. Include Selenium directly and assign a
webdriver to ``world.browser``.

Usage
=====
Expand Down
126 changes: 125 additions & 1 deletion lettuce_webdriver/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,125 @@
#
"""
Lettuce Webdriver
"""

import os
import yaml

import selenium.webdriver

from lettuce import world, after

import webdriver


__all__ = ['initialize']


class ConfigError(Exception):
"""
A YAML config error
"""

pass


# pylint:disable=too-many-branches, too-many-statements
def initialize(config, default, capabilities=None):
"""
Initialize lettuce-webdriver using specified config.

Config is specified in YAML.
"""

with open(config) as file_:
data = yaml.load(file_)

try:
browser = os.environ.get('WEBDRIVER', default)
browser = data[browser]
except KeyError:
raise ConfigError("Unknown browser '{browser}'".format(
browser=browser))

remote = browser.get('remote', False)
config = {}

# determine base capabilities
try:
if browser['webdriver'] == 'ie':
caps_str = 'INTERNETEXPLORER'
else:
caps_str = browser['webdriver'].upper()

caps = getattr(selenium.webdriver.DesiredCapabilities, caps_str)
except KeyError:
raise ConfigError("Must specify 'driver'")
except AttributeError:
raise ConfigError("Unknown driver: {driver}".format(
browser['driver']))

# merge capabilities overrides
caps.update(browser.get('capabilities', {}))

if remote:
hub = None
hub_fmt = 'http://{host}:4444/wd/hub'

if 'WEBDRIVER_HUB' in os.environ:
hub = os.environ['WEBDRIVER_HUB']
elif 'WEBDRIVER_HOST' in os.environ:
hub = hub_fmt.format(host=os.environ['WEBDRIVER_HOST'])
elif 'hub' in browser:
hub = browser['hub']
elif 'host' in browser:
hub = hub_fmt.format(host=browser['host'])
elif 'command_executor' in browser:
hub = browser['command_executor']
else:
raise ConfigError("Must specify a hub or host to connect to")

config['command_executor'] = hub

if capabilities:
caps.update(capabilities)

if remote or \
browser['webdriver'] == 'chrome' or \
browser['webdriver'] == 'phantomjs':
config['desired_capabilities'] = caps
else:
config['capabilities'] = caps

# determine WebDriver
if remote:
driver = selenium.webdriver.Remote
else:
driver = browser['webdriver']

if driver == 'phantomjs':
driver = 'PhantomJS'
else:
driver = driver.capitalize()

driver = getattr(selenium.webdriver, driver)

driver = driver(**config)
driver.config = config
driver.requested_capabilities = caps

return driver


@after.each_scenario # pylint:disable=no-member
def disable_beforeunload(scenario):
"""
Disable before unload after a scenario so that the next scenario can
reload the site.
"""

world.browser.execute_script("""
try {
$(window).off('beforeunload');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this depends on JQuery being installed in and exported by the target site. I'm not really comfortable making that a requirement for lettuce_webdriver; is there a better or easier way to do this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. We can do it through raw JS. Although I've never been clear how
the multiple ways to set/unset events interact with each other in different
browsers. I'll investigate.

On 2 October 2013 04:50, Nicholas Pilon [email protected] wrote:

In lettuce_webdriver/init.py:

  • driver.config = config
  • driver.requested_capabilities = caps
  • return driver

[email protected]_scenario # pylint:disable=no-member
+def disable_beforeunload(scenario):

  • """
  • Disable before unload after a scenario so that the next scenario can
  • reload the site.
  • """
  • world.browser.execute_script("""
    +try {
  • $(window).off('beforeunload');

So, this depends on JQuery being installed in and exported by the target
site. I'm not really comfortable making that a requirement for
lettuce_webdriver; is there a better or easier way to do this?


Reply to this email directly or view it on GitHubhttps://github.com//pull/36/files#r6695360
.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may also want to add a callback to selenium that checks on each page load to see if JQuery is exposed and, if it isn't, imports and exposes it...

} catch (e) {
}
""")
6 changes: 6 additions & 0 deletions lettuce_webdriver/django.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
Django-specific extensions
"""

import socket
import urlparse

from lettuce import step
from lettuce.django import server


def site_url(url):
"""
Expand Down
9 changes: 7 additions & 2 deletions lettuce_webdriver/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
# pylint:disable=invalid-name,missing-docstring
import os

from lettuce import world

import lettuce_webdriver

here = os.path.dirname(__file__)
html_pages = os.path.join(here, 'html_pages')

def setUp():
from selenium import webdriver
world.browser = webdriver.Firefox()
world.browser = lettuce_webdriver.initialize(
os.path.join(here, 'browsers.yaml'),
'firefox')


def tearDown():
world.browser.quit()
2 changes: 2 additions & 0 deletions lettuce_webdriver/tests/browsers.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
firefox:
webdriver: firefox
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
PyYAML==3.10
fuzzywuzzy==0.2
lettuce==0.2.19
nose==1.3.0
Expand Down
14 changes: 12 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
README = open(os.path.join(here, 'README.rst')).read()
CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()

REQUIREMENTS = [
'lettuce',
'selenium >= 2.30.0',
'PyYAML',
]

TEST_REQUIREMENTS = [
'nose',
]

setup(name='lettuce_webdriver',
version=__version__,
description='Selenium webdriver extension for lettuce',
Expand All @@ -26,7 +36,7 @@
packages=find_packages(),
include_package_data=True,
zip_safe=False,
tests_require = ['lettuce', 'selenium', 'nose'],
install_requires=['lettuce','selenium>=2.30.0'],
tests_require=REQUIREMENTS + TEST_REQUIREMENTS,
install_requires=REQUIREMENTS,
test_suite="lettuce_webdriver",
)