diff --git a/README.rst b/README.rst
index 8a177cf..80a9a68 100644
--- a/README.rst
+++ b/README.rst
@@ -13,7 +13,7 @@ Requirements
============
* `lettuce `_
-* `selenium 2.8 or higher `_
+* `selenium 2.30 or higher `_
Setting Up lettuce_webdriver
============================
@@ -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
=====
diff --git a/lettuce_webdriver/__init__.py b/lettuce_webdriver/__init__.py
index 792d600..d33a0a4 100644
--- a/lettuce_webdriver/__init__.py
+++ b/lettuce_webdriver/__init__.py
@@ -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');
+} catch (e) {
+}
+ """)
diff --git a/lettuce_webdriver/django.py b/lettuce_webdriver/django.py
index e49e06f..8466870 100644
--- a/lettuce_webdriver/django.py
+++ b/lettuce_webdriver/django.py
@@ -2,6 +2,12 @@
Django-specific extensions
"""
+import socket
+import urlparse
+
+from lettuce import step
+from lettuce.django import server
+
def site_url(url):
"""
diff --git a/lettuce_webdriver/tests/__init__.py b/lettuce_webdriver/tests/__init__.py
index 6de91dd..a7f15b0 100644
--- a/lettuce_webdriver/tests/__init__.py
+++ b/lettuce_webdriver/tests/__init__.py
@@ -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()
diff --git a/lettuce_webdriver/tests/browsers.yaml b/lettuce_webdriver/tests/browsers.yaml
new file mode 100644
index 0000000..a8d1831
--- /dev/null
+++ b/lettuce_webdriver/tests/browsers.yaml
@@ -0,0 +1,2 @@
+firefox:
+ webdriver: firefox
diff --git a/requirements.txt b/requirements.txt
index b15aa60..08583ac 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
+PyYAML==3.10
fuzzywuzzy==0.2
lettuce==0.2.19
nose==1.3.0
diff --git a/setup.py b/setup.py
index db099b5..a07a89f 100644
--- a/setup.py
+++ b/setup.py
@@ -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',
@@ -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",
)