From ffd491e800a3b128bbfb35bd36a67a17b8ad475f Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Thu, 26 Sep 2013 14:50:19 +1000 Subject: [PATCH 1/7] Fix django steps Need to write tests for these. --- lettuce_webdriver/django.py | 6 ++++++ 1 file changed, 6 insertions(+) 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): """ From d63351fc1e1768a372dfe48e25a1c458c6f00de0 Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Fri, 27 Sep 2013 10:19:00 +1000 Subject: [PATCH 2/7] Configure browser capabilities in a yaml file Allow the user to select their appropriate browser config via the WEBDRIVER environment variable. --- lettuce_webdriver/__init__.py | 119 +++++++++++++++++++++++++- lettuce_webdriver/tests/__init__.py | 9 +- lettuce_webdriver/tests/browsers.yaml | 2 + 3 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 lettuce_webdriver/tests/browsers.yaml diff --git a/lettuce_webdriver/__init__.py b/lettuce_webdriver/__init__.py index 792d600..ccb19ca 100644 --- a/lettuce_webdriver/__init__.py +++ b/lettuce_webdriver/__init__.py @@ -1 +1,118 @@ -# +""" +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): + """ + 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 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) + + return driver(**config) + + +@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/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 From 3896171ab6a3f5ad92474b2c740526384f5eb31c Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Fri, 27 Sep 2013 10:31:19 +1000 Subject: [PATCH 3/7] Update docs for YAML config support --- README.rst | 58 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 5 deletions(-) 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 ===== From 1680ed3e6ed8f3da0b9c3c534540e6827a47e8bd Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Fri, 27 Sep 2013 10:32:50 +1000 Subject: [PATCH 4/7] Update requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) 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 From 31c6ec025b8c79dde8ae5174235f00641ac7676d Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Fri, 27 Sep 2013 13:47:30 +1000 Subject: [PATCH 5/7] Add support for app provided capabilities --- lettuce_webdriver/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lettuce_webdriver/__init__.py b/lettuce_webdriver/__init__.py index ccb19ca..756e74b 100644 --- a/lettuce_webdriver/__init__.py +++ b/lettuce_webdriver/__init__.py @@ -24,7 +24,7 @@ class ConfigError(Exception): # pylint:disable=too-many-branches, too-many-statements -def initialize(config, default): +def initialize(config, default, capabilities=None): """ Initialize lettuce-webdriver using specified config. @@ -80,6 +80,9 @@ def initialize(config, default): config['command_executor'] = hub + if capabilities: + caps.update(capabilities) + if remote or \ browser['webdriver'] == 'chrome' or \ browser['webdriver'] == 'phantomjs': From 0c589fe7d969fcedf2973f4c829684220052c10f Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Fri, 27 Sep 2013 14:47:02 +1000 Subject: [PATCH 6/7] Set the caps on the object so we can use them later --- lettuce_webdriver/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lettuce_webdriver/__init__.py b/lettuce_webdriver/__init__.py index 756e74b..d33a0a4 100644 --- a/lettuce_webdriver/__init__.py +++ b/lettuce_webdriver/__init__.py @@ -103,7 +103,11 @@ def initialize(config, default, capabilities=None): driver = getattr(selenium.webdriver, driver) - return driver(**config) + driver = driver(**config) + driver.config = config + driver.requested_capabilities = caps + + return driver @after.each_scenario # pylint:disable=no-member From 60d1a0a7c19f7e413d2b70010d49c4052155a845 Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Tue, 1 Oct 2013 11:50:38 +1000 Subject: [PATCH 7/7] Add PyYAML to setup.py Refactor requirements lists to be more straightforward. --- setup.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) 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", )