selenium-2.48.0/0000755000076600000240000000000012605237755014063 5ustar dburnsstaff00000000000000selenium-2.48.0/MANIFEST.in0000644000076600000240000000156712556002346015621 0ustar dburnsstaff00000000000000prune * recursive-include py/selenium/webdriver *.py recursive-include py/selenium/webdriver/common *.py recursive-include py/selenium/webdriver/common/html5 *.py recursive-include py/selenium/common *.py recursive-include py/selenium/webdriver/chrome *.py recursive-include py/selenium/webdriver/opera *.py recursive-include py/selenium/webdriver/phantomjs *.py recursive-include py/selenium/webdriver/firefox *.py *.xpi *.json recursive-include py/selenium/webdriver/firefox/x86 *.so recursive-include py/selenium/webdriver/firefox/amd64 *.so recursive-include py/selenium/webdriver/ie *.py recursive-include py/selenium/webdriver/edge *.py recursive-include py/selenium/webdriver/remote *.py recursive-include py/selenium/webdriver/support *.py include py/selenium/selenium.py include py/selenium/__init__.py include py/CHANGES include py/README recursive-include selenium.egg-info * selenium-2.48.0/PKG-INFO0000644000076600000240000001362312605237755015165 0ustar dburnsstaff00000000000000Metadata-Version: 1.1 Name: selenium Version: 2.48.0 Summary: Python bindings for Selenium Home-page: https://github.com/SeleniumHQ/selenium/ Author: UNKNOWN Author-email: UNKNOWN License: UNKNOWN Description: ====================== Selenium Client Driver ====================== Introduction ============ Python language bindings for Selenium WebDriver. The `selenium` package is used automate web browser interaction from Python. +-----------+-----------------------------------------------------------------------------------+ | **Home**: | http://www.seleniumhq.org | +-----------+-----------------------------------------------------------------------------------+ | **Docs**: | `selenium package API `_ | +-----------+-----------------------------------------------------------------------------------+ | **Dev**: | https://github.com/SeleniumHQ/selenium | +-----------+-----------------------------------------------------------------------------------+ | **PyPI**: | https://pypi.python.org/pypi/selenium | +-----------+-----------------------------------------------------------------------------------+ | **IRC**: | **#selenium** channel on freenode | +-----------+-----------------------------------------------------------------------------------+ Several browsers/drivers are supported (Firefox, Chrome, Internet Explorer, PhantomJS), as well as the Remote protocol. Supported Python Versions ========================= * Python 2.6, 2.7 * Python 3.2, 3.3 Installing ========== If you have `pip `_ on your system, you can simply install or upgrade the Python bindings:: pip install -U selenium Alternately, you can download the source distribution from `PyPI `_ (e.g. selenium-2.48.tar.gz), unarchive it, and run:: python setup.py install Note: both of the methods described above install `selenium` as a system-wide package That will require administrative/root access to ther machine. You may consider using a `virtualenv `_ to create isolated Python environments instead. Example 0: ========== * open a new Firefox browser * load the page at the given URL :: from selenium import webdriver browser = webdriver.Firefox() browser.get('http://seleniumhq.org/') Example 1: ========== * open a new Firefox browser * load the Yahoo homepage * search for "seleniumhq" * close the browser :: from selenium import webdriver from selenium.webdriver.common.keys import Keys browser = webdriver.Firefox() browser.get('http://www.yahoo.com') assert 'Yahoo' in browser.title elem = browser.find_element_by_name('p') # Find the search box elem.send_keys('seleniumhq' + Keys.RETURN) browser.quit() Example 2: ========== Selenium WebDriver is often used as a basis for testing web applications. Here is a simple example uisng Python's standard `unittest `_ library: :: import unittest class GoogleTestCase(unittest.TestCase): def setUp(self): self.browser = webdriver.Firefox() self.addCleanup(self.browser.quit) def testPageTitle(self): self.browser.get('http://www.google.com') self.assertIn('Google', self.browser.title) if __name__ == '__main__': unittest.main(verbosity=2) Selenium Server (optional) ========================== For normal WebDriver scripts (non-Remote), the Java server is not needed. However, to use Selenium Webdriver Remote or the legacy Selenium API (Selenium-RC), you need to also run the Selenium server. The server requires a Java Runtime Environment (JRE). Download the server separately, from: http://selenium-release.storage.googleapis.com/2.48/selenium-server-standalone-2.48.0.jar Run the server from the command line:: java -jar selenium-server-standalone-2.48.8.jar Then run your Python client scripts. Use The Source Luke! ==================== View source code online at https://github.com/SeleniumHQ/selenium/tree/master/py/ Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: MacOS :: MacOS X Classifier: Topic :: Software Development :: Testing Classifier: Topic :: Software Development :: Libraries Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 selenium-2.48.0/py/0000755000076600000240000000000012605237755014513 5ustar dburnsstaff00000000000000selenium-2.48.0/py/CHANGES0000644000076600000240000003077312604471537015515 0ustar dburnsstaff00000000000000Selenium 2.48.0 * Update error pulling to match spec when we encounter a spec compliant browser. * Disable tests that are not working with Marionette when running Marionette tests * Add the ability to run python marionette tests * Python 3 compatibility for remote Authorization * changing casing of children finding tests Selenium 2.47.3 * Bring back py 3 support Selenium 2.47.2 * Fix running Edge driver locally on win10 * adding repr to WebDriver and WebElement Selenium 2.47.1 * Fix the issue of deleting the profile when shutting down Firefox * WebElement __eq__ compares against more types * Issues fixed: 850 Selenium 2.47.0 * Add in support for when communicating with a Spec compliant browsers * Initial support for Edge using EdgeDriver * Issues fixed: 818 Selenium 2.46.1 * Adding ability to make remote call for webelement screenshots in accordance to the W3C spec * Adding api to authenticate HTTP Auth modal dialogs via driver.switch_to.alert (beta) * Add rebeccapurple to Color Object * Add element screenshot * Add service handler and minimal update to driver to use service for Marionette * Add the ability to start FirefoxDriver backed with Marionette via a capability * support socket timeout for connections * free_port checks if port is available on all interfaces * Allow error handling to handle both current errors and w3c errors * Update find_elements to match spec * phantomjs: service: remove unused import of signal * phantomjs: add port information to WebDriverException * Issues fixed (Github): 478, 612, 734, 780 Selenium 2.46.0 * Firefox support up to 38 * BlackBerry browser support * remove Presto-Opera support * firefox extension extraction fixes * process management fixes with phantomjs * Comparing remote web element for equality does not require a remote command * Issues Fixed: (gcode) 8493, 8521, 8498, 8274, 8497, 5923 * Issues Fixed: (github) 401 Selenium 2.45.0 * Firefox support up to 35, support for native events up to 34. * Make Opera driver support also the new Blink based Opera * README: Fix the Yahoo example * WebElement docstring fixes * Add debugger_address option to the ChromeDriver options list to optionally instruct ChromeDriver to wait for the target devtools instance to be started at a given host:ip * Set default value for PhantomJS process reference * Allow setting of FileDetector for send_keys * Pass info to TimeoutException in WebDriverWait * Issues Fixed: 8065, 8310, 8539 Selenium 2.44.0 * (previous release person forgot to add release notes! DAVID!) Selenium 2.43.0 * Expand WebElement.get_attribute API docs * firefox may be installed without admininstrator privileges and therefore there may be no HKEY_LOCAL_MACHINE entry. Issue #7784 * UnexpectedAlertPresentException should contain the alert text in python too. Issue #7745 * don't mutate the global 'ignored exceptions', take a copy of the globally specified ones, change the global to be a tuple instead. Issue #7725 * raise exception when the firefox binary isn't actually found, which usually implies the upgrade failed (on windows) Issue #6092 ,#6847 * Fixing NameError: global name 'options' is not defined. * Remove unused import subprocess.PIPE * Redirect Firefox output to /dev/null by default Fixes Issue #7677 * More flexible management of http timeouts in Selenium RC python client * Generate Python API docs for selenium.webdriver.chrome.options. Fixes issue #7471 * Use 127.0.0.1 as localhost name resolving might fail on some systems Selenium 2.42.1 * Fixed Py3 issues * Make firefox_binary.py and firefox_profile.py not executable * Make exceptions Python 3 compatible Selenium 2.42 * Support for Firefox 29 Native Events * "remote_url" and "remote_browser" parameters for "./go test_remote". * missing __init__ in new android module * issue #7304 Fix memory leak caused by __del__ in PhantomJS * File upload using remotedriver on python3 * Updating xpi install to align with mozprofile * command_executor should also support unicode strings as well. Selenium 2.41 * Support for Firefox 28 * deprecating switch_to_* in favour of driver.switch_to.* Selenium 2.40 * Support for Firefox 27 * Fixes related to http connection * Fix for phantomjs running on windows #6736 Selenium 2.39 * Support for Firefox 26 Selenium 2.38.4 * keep-alive can't be used for phantomjs / IE, fix for that and tested for py3 :) Selenium 2.38.3 * really supporting py3 :) Selenium 2.38.2 * py3 support (once again) Selenium 2.38.1 * fix packaging problem where firefox/webdriver_prefs.json was missing Selenium 2.38 * Support for Firefox 25 * FirefoxProfile now using common webdriver.json instead of having our own copy in py - behavior change to the preferences is that they now should be treated like raw types rather than strings and allow the json library to translate the types appropriated (e.g. True => true) * Set proper 'Accept' request header so that Python bindings work with some old WebDriver implementations that reply 404 to requests with no 'Accept' set. * handle redirect response explicitly (since switching to using keep-alive) * phantomjs service needs to really kill the spawned process Issue #5921 * removing old api endpoints from command listing * using keep-alive for remote connection * adjusting phantomjs subprocess.Popen * ActionsChains.send_keys should use /keys endpoint Issue #6348 * fix TypeError in chrome_options.extensions for Python3.x * Other Bugs Fixed: #6531, #6513, #4569, #6454 Selenium 2.37.2 * fix regression added with unicode fix * Bug fix #6360 Selenium 2.37.1 * fix find_elements on webelement using unicode locators and py 2.7 Selenium 2.37 * repackage with fix for Firefox native events on Linux * fix issue with unicode By locators w/ python 2.7 #6430 Selenium 2.36 * Added Safari WebDriver. Fixes issue 5352. * fix platform for safari caps * Convert all offsets/coordinates/speeds into integers * Fix drag and drop by offset behaviour * Fix initialization of Proxy by capabilities when proxyType is set * Enable SOCKS proxy support * Validation of passed locator for find_element(s) methods #5690 * Adding support for /status, /sessions commands * Doc fixes * ability to set Chrome extensions by using base64 encoded strings #4013 * fix logic regarding Select.select_by_visible_text #3910 * Bugs fixed: #6165, #6231 Selenium 2.35 * Remove duplicate 'get screenshot as file' methods. Add method 'get_screenshot_as_png' * fixing UnicodeEncodeError on get attribute of webelement Selenium 2.34 * Corrected webdriverbackedselenium session handling. Fixes issue 4283 * Corrected use of basestring for python 3. Fixes issue 5924 * Support for Firefox 22 * Added support for logging from the browser * corrected proxy handling on FirefoxProfile * Corrected handling of chrome extensions. Fixes issue 5762 Selenium 2.33 * getText() ignores elements in the * Adding both official and informal string representations to Color object. * Replace distutils.dir_util by shutil * Allow finding firefox binary at ProgramFiles(x86) on windows(64 bit) * Py3 compatible winreg import and content-type access Selenium 2.32 * Support for FF20 Native Events * Python 3 support * Misc Python 3 patches * Allow easy FirefoxBinary subclassing Selenium 2.31 * Support for FF19 native events * web element equality is now in conformance with other language bindings Selenium 2.30 * Allow env to be specified for the chromedriver service * Allow log path to be specified for phantomjs driver service. * Bug Fixes: 4608 4940 4974 5034 5075 Selenium 2.29 * Allow subclassing of driver and have the ability to send_keys Issue 4877, 5017 * Simplifying save_screenshot and allow phantomjs to take screenshots Selenium 2.28 * "null" can now be passed to executeScript * Add transparent and extended colour keywords to color support module. Fixes issue 4866 Selenium 2.27 * Added support for phantomjs / ghostdriver * Fix python client, avoid duplicate chrome option items after reusing options class. Fixes Issue 4744. * adding colour support to Python. fixes issue 4623 * Adding log_path/service_log_path as named kwargs for chrome Selenium 2.26 * Added location_when_scrolled_into_view - Bug 4357 * Added new expected_conditions support module to be used with WebDriverWait Selenium 2.25 * Jython 2.7 Support - Bug 3988 * EventFiringWebDriver added to Support module - Bug 2267 * Added IEDriverServer logging that can be accessed via desired capabilities * Fixed by data being passed into find_elements - bug 3735 * Removed deprecated ChromeDriver items around desiredcapabilites in favour of chrome options * Added default values for a number of action_chains calls Selenium 2.24 * Removing the ctypes approach of invoking IEDriver, you will need to download the IEDriverServer from https://code.google.com/p/selenium/downloads/list Selenium 2.23 * Support for FF13 native events Selenium 2.22 * Moving IEDriver to be able to use IEDriverServer Selenium 2.21.3 * Fix for File Upload to remote servers * Better handling of typing in input=file. Bug 3831, 3736 * Better handling of unicode URLS Bug 3740 Selenium 2.21.2 * Fix typing to file input when not using Selenium Server. Bug 3736 Selenium 2.21.1 * focusmanager.testmode messes with native events, removing it. Selenium 2.21 * Local File upload capabilities for non-remote browser * Adding maximize_window api call * Updating default firefox profile to set focusmanager.testmode to true see https://bugzilla.mozilla.org/show_bug.cgi?id=704583 * bugs fixed: 3506, 3528, 3607 Selenium 2.20 * disable native events for FF on Mac by default * fix webdriverwait to execute at least once when using 0 timeout * Fixed Issue 3438 Selenium 2.19 * WebDriverBackedSelenium is now avalaible to all languages * Addon installation fixes Selenium 2.18 * Proxy capabilities passing Selenium 2.17 * OperaDriver can now be invoked by webdriver.Opera() * Support has been added for ChomeOptions. This deprecates support passing in DesiredCapabilities * Proxy class to tell the browser a proxy is in use. Currently only for Firefox Selenium 2.16 * bug fixes Selenium 2.15 * bug fixes Selenium 2.14 * Fix for LD_PRELOAD being polluted by WebDriver * Added Orientation API * A fix for Error Handling Selenium 2.13 * Fixed switch_to_window so that it didnt crash Firefox Bug 2633 * Fixed Screenshot handling to work in all browsers. Bug 2829 * Force Firefox to the Foreground Selenium 2.12 * Added Select as a support pacakge * Added Beta window size / position api's * Bug Fixes Selenium 2.11.0 2.11.1 * no changes just packaging Selenum 2.10 * "Choose which apps" dialog has been disabled * Bug Fixes Selenium 2.9 * Bug Fixes * Documentation Selenium 2.8 * Actions updates * Bug Fixes Selenium 2.6 * Documentation fixes Selenium 2.5 * Fixed x64 IE Support * Bug Fixes Selenium 2.4 * Bug Fixes * x64 IE Support * Added WebDriverWait as a support package Selenium 2.3 * Bug Fixes Selenium 2.2 * Ability to get screenshots from Exceptions if they are given * Access to Remote StackTrace on error Selenium 2.1 * Bug Fixes Selenium 2 * Removed toggle() and select() Selenium 2 RC 3 * Added Opera to Desired Capabilities * Removed deprecrated methods * Deprecated toggle() and select() methods. This will be removed in the next release Selenium 2 Beta 4 * Fix for using existing Firefox Profiles * Alerts Support in IE * Fix to dictionary returned from size * Deprecated value property. Use the get_attribute("value") method * Deprecated get_page_source method. Use page_source property * Deprecated get_current_window_handle. Use current_window_handle property * Deprecated get_window_handles. Use window_handles property * Ability to install extensions into profiles * Added Location to the WebElement * ChromeDriver rewritten to use new built in mechanism * Added Advanced User Interaction API. Only Available for HTMLUnit at the moment * Profiles now delete their temp folders when driver.quit() is called Selenium 2 Beta 3 * Accept Untrusted Certificates in Firefox * Fixed Screenshots * Added DesiredCapabilities to simplify choosing Drivers * Fixed Firefox Profile creation * Added Firefox 4 support * DocStrings Improvements Selenium 2 Beta 2 * New bindings landed. Change webdriver namespace to "selenium.webdriver" * Ability to move to default content * Implicit Waits * Change the API to use properties instead of get_x * Changed the Element Finding to match other languages * Added ability to execute asynchronous scripts from the driver * Ability to get rendered element size * Ability to get CSS Value on a webelement * Corrected Element finding from the element * Alert and Prompt handling * Improved IEDriver * Basic Authentication support for Selenium 2 * Ability to have multiple Firefox instances selenium-2.48.0/py/README0000644000076600000240000001004612604471537015371 0ustar dburnsstaff00000000000000====================== Selenium Client Driver ====================== Introduction ============ Python language bindings for Selenium WebDriver. The `selenium` package is used automate web browser interaction from Python. +-----------+-----------------------------------------------------------------------------------+ | **Home**: | http://www.seleniumhq.org | +-----------+-----------------------------------------------------------------------------------+ | **Docs**: | `selenium package API `_ | +-----------+-----------------------------------------------------------------------------------+ | **Dev**: | https://github.com/SeleniumHQ/selenium | +-----------+-----------------------------------------------------------------------------------+ | **PyPI**: | https://pypi.python.org/pypi/selenium | +-----------+-----------------------------------------------------------------------------------+ | **IRC**: | **#selenium** channel on freenode | +-----------+-----------------------------------------------------------------------------------+ Several browsers/drivers are supported (Firefox, Chrome, Internet Explorer, PhantomJS), as well as the Remote protocol. Supported Python Versions ========================= * Python 2.6, 2.7 * Python 3.2, 3.3 Installing ========== If you have `pip `_ on your system, you can simply install or upgrade the Python bindings:: pip install -U selenium Alternately, you can download the source distribution from `PyPI `_ (e.g. selenium-2.48.tar.gz), unarchive it, and run:: python setup.py install Note: both of the methods described above install `selenium` as a system-wide package That will require administrative/root access to ther machine. You may consider using a `virtualenv `_ to create isolated Python environments instead. Example 0: ========== * open a new Firefox browser * load the page at the given URL :: from selenium import webdriver browser = webdriver.Firefox() browser.get('http://seleniumhq.org/') Example 1: ========== * open a new Firefox browser * load the Yahoo homepage * search for "seleniumhq" * close the browser :: from selenium import webdriver from selenium.webdriver.common.keys import Keys browser = webdriver.Firefox() browser.get('http://www.yahoo.com') assert 'Yahoo' in browser.title elem = browser.find_element_by_name('p') # Find the search box elem.send_keys('seleniumhq' + Keys.RETURN) browser.quit() Example 2: ========== Selenium WebDriver is often used as a basis for testing web applications. Here is a simple example uisng Python's standard `unittest `_ library: :: import unittest class GoogleTestCase(unittest.TestCase): def setUp(self): self.browser = webdriver.Firefox() self.addCleanup(self.browser.quit) def testPageTitle(self): self.browser.get('http://www.google.com') self.assertIn('Google', self.browser.title) if __name__ == '__main__': unittest.main(verbosity=2) Selenium Server (optional) ========================== For normal WebDriver scripts (non-Remote), the Java server is not needed. However, to use Selenium Webdriver Remote or the legacy Selenium API (Selenium-RC), you need to also run the Selenium server. The server requires a Java Runtime Environment (JRE). Download the server separately, from: http://selenium-release.storage.googleapis.com/2.48/selenium-server-standalone-2.48.0.jar Run the server from the command line:: java -jar selenium-server-standalone-2.48.8.jar Then run your Python client scripts. Use The Source Luke! ==================== View source code online at https://github.com/SeleniumHQ/selenium/tree/master/py/ selenium-2.48.0/py/selenium/0000755000076600000240000000000012605237755016334 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/__init__.py0000644000076600000240000000151312604471537020442 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from selenium import selenium __version__ = "2.48.0" selenium-2.48.0/py/selenium/common/0000755000076600000240000000000012605237755017624 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/common/__init__.py0000644000076600000240000000145512551302002021714 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from . import exceptions selenium-2.48.0/py/selenium/common/exceptions.py0000644000076600000240000001564212551302002022341 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. """ Exceptions that may happen in all the webdriver code. """ class WebDriverException(Exception): """ Base webdriver exception. """ def __init__(self, msg=None, screen=None, stacktrace=None): self.msg = msg self.screen = screen self.stacktrace = stacktrace def __str__(self): exception_msg = "Message: %s\n" % self.msg if self.screen is not None: exception_msg += "Screenshot: available via screen\n" if self.stacktrace is not None: stacktrace = "\n".join(self.stacktrace) exception_msg += "Stacktrace:\n%s" % stacktrace return exception_msg class ErrorInResponseException(WebDriverException): """ Thrown when an error has occurred on the server side. This may happen when communicating with the firefox extension or the remote driver server. """ def __init__(self, response, msg): WebDriverException.__init__(self, msg) self.response = response class InvalidSwitchToTargetException(WebDriverException): """ Thrown when frame or window target to be switched doesn't exist. """ pass class NoSuchFrameException(InvalidSwitchToTargetException): """ Thrown when frame target to be switched doesn't exist. """ pass class NoSuchWindowException(InvalidSwitchToTargetException): """ Thrown when window target to be switched doesn't exist. To find the current set of active window handles, you can get a list of the active window handles in the following way:: print driver.window_handles """ pass class NoSuchElementException(WebDriverException): """ Thrown when element could not be found. If you encounter this exception, you may want to check the following: * Check your selector used in your find_by... * Element may not yet be on the screen at the time of the find operation, (webpage is still loading) see selenium.webdriver.support.wait.WebDriverWait() for how to write a wait wrapper to wait for an element to appear. """ pass class NoSuchAttributeException(WebDriverException): """ Thrown when the attribute of element could not be found. You may want to check if the attribute exists in the particular browser you are testing against. Some browsers may have different property names for the same property. (IE8's .innerText vs. Firefox .textContent) """ pass class StaleElementReferenceException(WebDriverException): """ Thrown when a reference to an element is now "stale". Stale means the element no longer appears on the DOM of the page. Possible causes of StaleElementReferenceException include, but not limited to: * You are no longer on the same page, or the page may have refreshed since the element was located. * The element may have been removed and re-added to the screen, since it was located. Such as an element being relocated. This can happen typically with a javascript framework when values are updated and the node is rebuilt. * Element may have been inside an iframe or another context which was refreshed. """ pass class InvalidElementStateException(WebDriverException): """ """ pass class UnexpectedAlertPresentException(WebDriverException): """ Thrown when an unexpected alert is appeared. Usually raised when when an expected modal is blocking webdriver form executing any more commands. """ def __init__(self, msg=None, screen=None, stacktrace=None, alert_text=None): super(UnexpectedAlertPresentException, self).__init__(msg, screen, stacktrace) self.alert_text = alert_text def __str__(self): return "Alert Text: %s\n%s" % (self.alert_text, str(super(WebDriverException, self))) class NoAlertPresentException(WebDriverException): """ Thrown when switching to no presented alert. This can be caused by calling an operation on the Alert() class when an alert is not yet on the screen. """ pass class ElementNotVisibleException(InvalidElementStateException): """ Thrown when an element is present on the DOM, but it is not visible, and so is not able to be interacted with. Most commonly encountered when trying to click or read text of an element that is hidden from view. """ pass class ElementNotSelectableException(InvalidElementStateException): """ Thrown when trying to select an unselectable element. For example, selecting a 'script' element. """ pass class InvalidCookieDomainException(WebDriverException): """ Thrown when attempting to add a cookie under a different domain than the current URL. """ pass class UnableToSetCookieException(WebDriverException): """ Thrown when a driver fails to set a cookie. """ pass class RemoteDriverServerException(WebDriverException): """ """ pass class TimeoutException(WebDriverException): """ Thrown when a command does not complete in enough time. """ pass class MoveTargetOutOfBoundsException(WebDriverException): """ Thrown when the target provided to the `ActionsChains` move() method is invalid, i.e. out of document. """ pass class UnexpectedTagNameException(WebDriverException): """ Thrown when a support class did not get an expected web element. """ pass class InvalidSelectorException(NoSuchElementException): """ Thrown when the selector which is used to find an element does not return a WebElement. Currently this only happens when the selector is an xpath expression and it is either syntactically invalid (i.e. it is not a xpath expression) or the expression does not select WebElements (e.g. "count(//input)"). """ pass class ImeNotAvailableException(WebDriverException): """ Thrown when IME support is not available. This exception is thrown for every IME-related method call if IME support is not available on the machine. """ pass class ImeActivationFailedException(WebDriverException): """ Thrown when activating an IME engine has failed. """ pass selenium-2.48.0/py/selenium/selenium.py0000644000076600000240000023047012551302002020507 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from __future__ import unicode_literals __docformat__ = "restructuredtext en" try: import http.client as http_client except ImportError: import httplib as http_client try: import urllib.parse as urllib_parse except ImportError: import urllib as urllib_parse class selenium(object): """ Defines an object that runs Selenium commands. **Element Locators** Element Locators tell Selenium which HTML element a command refers to. The format of a locator is: \ *locatorType*\ **=**\ \ *argument* We support the following strategies for locating elements: * \ **identifier**\ =\ *id*: Select the element with the specified @id attribute. If no match is found, select the first element whose @name attribute is \ *id*. (This is normally the default; see below.) * \ **id**\ =\ *id*: Select the element with the specified @id attribute. * \ **name**\ =\ *name*: Select the first element with the specified @name attribute. * username * name=username The name may optionally be followed by one or more \ *element-filters*, separated from the name by whitespace. If the \ *filterType* is not specified, \ **value**\ is assumed. * name=flavour value=chocolate * \ **dom**\ =\ *javascriptExpression*: Find an element by evaluating the specified string. This allows you to traverse the HTML Document Object Model using JavaScript. Note that you must not return a value in this string; simply make it the last expression in the block. * dom=document.forms['myForm'].myDropdown * dom=document.images[56] * dom=function foo() { return document.links[1]; }; foo(); * \ **xpath**\ =\ *xpathExpression*: Locate an element using an XPath expression. * xpath=//img[@alt='The image alt text'] * xpath=//table[@id='table1']//tr[4]/td[2] * xpath=//a[contains(@href,'#id1')] * xpath=//a[contains(@href,'#id1')]/@class * xpath=(//table[@class='stylee'])//th[text()='theHeaderText']/../td * xpath=//input[@name='name2' and @value='yes'] * xpath=//\*[text()="right"] * \ **link**\ =\ *textPattern*: Select the link (anchor) element which contains text matching the specified \ *pattern*. * link=The link text * \ **css**\ =\ *cssSelectorSyntax*: Select the element using css selectors. Please refer to CSS2 selectors, CSS3 selectors for more information. You can also check the TestCssLocators test in the selenium test suite for an example of usage, which is included in the downloaded selenium core package. * css=a[href="#id3"] * css=span#firstChild + span Currently the css selector locator supports all css1, css2 and css3 selectors except namespace in css3, some pseudo classes(:nth-of-type, :nth-last-of-type, :first-of-type, :last-of-type, :only-of-type, :visited, :hover, :active, :focus, :indeterminate) and pseudo elements(::first-line, ::first-letter, ::selection, ::before, ::after). * \ **ui**\ =\ *uiSpecifierString*: Locate an element by resolving the UI specifier string to another locator, and evaluating it. See the Selenium UI-Element Reference for more details. * ui=loginPages::loginButton() * ui=settingsPages::toggle(label=Hide Email) * ui=forumPages::postBody(index=2)//a[2] Without an explicit locator prefix, Selenium uses the following default strategies: * \ **dom**\ , for locators starting with "document." * \ **xpath**\ , for locators starting with "//" * \ **identifier**\ , otherwise **Element Filters** Element filters can be used with a locator to refine a list of candidate elements. They are currently used only in the 'name' element-locator. Filters look much like locators, ie. \ *filterType*\ **=**\ \ *argument* Supported element-filters are: \ **value=**\ \ *valuePattern* Matches elements based on their values. This is particularly useful for refining a list of similarly-named toggle-buttons. \ **index=**\ \ *index* Selects a single element based on its position in the list (offset from zero). **String-match Patterns** Various Pattern syntaxes are available for matching string values: * \ **glob:**\ \ *pattern*: Match a string against a "glob" (aka "wildmat") pattern. "Glob" is a kind of limited regular-expression syntax typically used in command-line shells. In a glob pattern, "\*" represents any sequence of characters, and "?" represents any single character. Glob patterns match against the entire string. * \ **regexp:**\ \ *regexp*: Match a string using a regular-expression. The full power of JavaScript regular-expressions is available. * \ **regexpi:**\ \ *regexpi*: Match a string using a case-insensitive regular-expression. * \ **exact:**\ \ *string*: Match a string exactly, verbatim, without any of that fancy wildcard stuff. If no pattern prefix is specified, Selenium assumes that it's a "glob" pattern. For commands that return multiple values (such as verifySelectOptions), the string being matched is a comma-separated list of the return values, where both commas and backslashes in the values are backslash-escaped. When providing a pattern, the optional matching syntax (i.e. glob, regexp, etc.) is specified once, as usual, at the beginning of the pattern. """ ### This part is hard-coded in the XSL def __init__(self, host, port, browserStartCommand, browserURL, http_timeout=90): self.host = host self.port = port self.browserStartCommand = browserStartCommand self.browserURL = browserURL self.sessionId = None self.extensionJs = "" self.http_timeout = http_timeout def setExtensionJs(self, extensionJs): self.extensionJs = extensionJs def start(self, browserConfigurationOptions=None, driver=None): start_args = [self.browserStartCommand, self.browserURL, self.extensionJs] if browserConfigurationOptions: start_args.append(browserConfigurationOptions) if driver: start_args.append('webdriver.remote.sessionid=%s' % driver.session_id) # Sessions can take a while to start, specially in grid environments self.http_timeout *= 5 result = self.get_string("getNewBrowserSession", start_args) self.http_timeout /= 5 try: self.sessionId = result except ValueError: raise Exception(result) def stop(self): self.do_command("testComplete", []) self.sessionId = None def do_command(self, verb, args): conn = http_client.HTTPConnection(self.host, self.port, timeout=self.http_timeout) try: body = 'cmd=' + urllib_parse.quote_plus(unicode(verb).encode('utf-8')) for i in range(len(args)): body += '&' + unicode(i+1) + '=' + \ urllib_parse.quote_plus(unicode(args[i]).encode('utf-8')) if (None != self.sessionId): body += "&sessionId=" + unicode(self.sessionId) headers = { "Content-Type": "application/x-www-form-urlencoded; charset=utf-8" } conn.request("POST", "/selenium-server/driver/", body, headers) response = conn.getresponse() data = unicode(response.read(), "UTF-8") if (not data.startswith('OK')): raise Exception(data) return data finally: conn.close() def get_string(self, verb, args): result = self.do_command(verb, args) return result[3:] def get_string_array(self, verb, args): csv = self.get_string(verb, args) if not csv: return [] token = "" tokens = [] escape = False for i in range(len(csv)): letter = csv[i] if (escape): token = token + letter escape = False continue if (letter == '\\'): escape = True elif (letter == ','): tokens.append(token) token = "" else: token = token + letter tokens.append(token) return tokens def get_number(self, verb, args): return int(self.get_string(verb, args)) def get_number_array(self, verb, args): string_array = self.get_string_array(verb, args) num_array = [] for i in string_array: num_array.append(int(i)) return num_array def get_boolean(self, verb, args): boolstr = self.get_string(verb, args) if ("true" == boolstr): return True if ("false" == boolstr): return False raise ValueError("result is neither 'true' nor 'false': " + boolstr) def get_boolean_array(self, verb, args): boolarr = self.get_string_array(verb, args) for i, boolstr in enumerate(boolarr): if ("true" == boolstr): boolarr[i] = True continue if ("false" == boolstr): boolarr[i] = False continue raise ValueError("result is neither 'true' nor 'false': " + boolarr[i]) return boolarr def click(self,locator): """ Clicks on a link, button, checkbox or radio button. If the click action causes a new page to load (like a link usually does), call waitForPageToLoad. 'locator' is an element locator """ self.do_command("click", [locator,]) def double_click(self,locator): """ Double clicks on a link, button, checkbox or radio button. If the double click action causes a new page to load (like a link usually does), call waitForPageToLoad. 'locator' is an element locator """ self.do_command("doubleClick", [locator,]) def context_menu(self,locator): """ Simulates opening the context menu for the specified element (as might happen if the user "right-clicked" on the element). 'locator' is an element locator """ self.do_command("contextMenu", [locator,]) def click_at(self,locator,coordString): """ Clicks on a link, button, checkbox or radio button. If the click action causes a new page to load (like a link usually does), call waitForPageToLoad. 'locator' is an element locator 'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator. """ self.do_command("clickAt", [locator,coordString,]) def double_click_at(self,locator,coordString): """ Doubleclicks on a link, button, checkbox or radio button. If the action causes a new page to load (like a link usually does), call waitForPageToLoad. 'locator' is an element locator 'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator. """ self.do_command("doubleClickAt", [locator,coordString,]) def context_menu_at(self,locator,coordString): """ Simulates opening the context menu for the specified element (as might happen if the user "right-clicked" on the element). 'locator' is an element locator 'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator. """ self.do_command("contextMenuAt", [locator,coordString,]) def fire_event(self,locator,eventName): """ Explicitly simulate an event, to trigger the corresponding "on\ *event*" handler. 'locator' is an element locator 'eventName' is the event name, e.g. "focus" or "blur" """ self.do_command("fireEvent", [locator,eventName,]) def focus(self,locator): """ Move the focus to the specified element; for example, if the element is an input field, move the cursor to that field. 'locator' is an element locator """ self.do_command("focus", [locator,]) def key_press(self,locator,keySequence): """ Simulates a user pressing and releasing a key. 'locator' is an element locator 'keySequence' is Either be a string("\" followed by the numeric keycode of the key to be pressed, normally the ASCII value of that key), or a single character. For example: "w", "\119". """ self.do_command("keyPress", [locator,keySequence,]) def shift_key_down(self): """ Press the shift key and hold it down until doShiftUp() is called or a new page is loaded. """ self.do_command("shiftKeyDown", []) def shift_key_up(self): """ Release the shift key. """ self.do_command("shiftKeyUp", []) def meta_key_down(self): """ Press the meta key and hold it down until doMetaUp() is called or a new page is loaded. """ self.do_command("metaKeyDown", []) def meta_key_up(self): """ Release the meta key. """ self.do_command("metaKeyUp", []) def alt_key_down(self): """ Press the alt key and hold it down until doAltUp() is called or a new page is loaded. """ self.do_command("altKeyDown", []) def alt_key_up(self): """ Release the alt key. """ self.do_command("altKeyUp", []) def control_key_down(self): """ Press the control key and hold it down until doControlUp() is called or a new page is loaded. """ self.do_command("controlKeyDown", []) def control_key_up(self): """ Release the control key. """ self.do_command("controlKeyUp", []) def key_down(self,locator,keySequence): """ Simulates a user pressing a key (without releasing it yet). 'locator' is an element locator 'keySequence' is Either be a string("\" followed by the numeric keycode of the key to be pressed, normally the ASCII value of that key), or a single character. For example: "w", "\119". """ self.do_command("keyDown", [locator,keySequence,]) def key_up(self,locator,keySequence): """ Simulates a user releasing a key. 'locator' is an element locator 'keySequence' is Either be a string("\" followed by the numeric keycode of the key to be pressed, normally the ASCII value of that key), or a single character. For example: "w", "\119". """ self.do_command("keyUp", [locator,keySequence,]) def mouse_over(self,locator): """ Simulates a user hovering a mouse over the specified element. 'locator' is an element locator """ self.do_command("mouseOver", [locator,]) def mouse_out(self,locator): """ Simulates a user moving the mouse pointer away from the specified element. 'locator' is an element locator """ self.do_command("mouseOut", [locator,]) def mouse_down(self,locator): """ Simulates a user pressing the left mouse button (without releasing it yet) on the specified element. 'locator' is an element locator """ self.do_command("mouseDown", [locator,]) def mouse_down_right(self,locator): """ Simulates a user pressing the right mouse button (without releasing it yet) on the specified element. 'locator' is an element locator """ self.do_command("mouseDownRight", [locator,]) def mouse_down_at(self,locator,coordString): """ Simulates a user pressing the left mouse button (without releasing it yet) at the specified location. 'locator' is an element locator 'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator. """ self.do_command("mouseDownAt", [locator,coordString,]) def mouse_down_right_at(self,locator,coordString): """ Simulates a user pressing the right mouse button (without releasing it yet) at the specified location. 'locator' is an element locator 'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator. """ self.do_command("mouseDownRightAt", [locator,coordString,]) def mouse_up(self,locator): """ Simulates the event that occurs when the user releases the mouse button (i.e., stops holding the button down) on the specified element. 'locator' is an element locator """ self.do_command("mouseUp", [locator,]) def mouse_up_right(self,locator): """ Simulates the event that occurs when the user releases the right mouse button (i.e., stops holding the button down) on the specified element. 'locator' is an element locator """ self.do_command("mouseUpRight", [locator,]) def mouse_up_at(self,locator,coordString): """ Simulates the event that occurs when the user releases the mouse button (i.e., stops holding the button down) at the specified location. 'locator' is an element locator 'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator. """ self.do_command("mouseUpAt", [locator,coordString,]) def mouse_up_right_at(self,locator,coordString): """ Simulates the event that occurs when the user releases the right mouse button (i.e., stops holding the button down) at the specified location. 'locator' is an element locator 'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator. """ self.do_command("mouseUpRightAt", [locator,coordString,]) def mouse_move(self,locator): """ Simulates a user pressing the mouse button (without releasing it yet) on the specified element. 'locator' is an element locator """ self.do_command("mouseMove", [locator,]) def mouse_move_at(self,locator,coordString): """ Simulates a user pressing the mouse button (without releasing it yet) on the specified element. 'locator' is an element locator 'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator. """ self.do_command("mouseMoveAt", [locator,coordString,]) def type(self,locator,value): """ Sets the value of an input field, as though you typed it in. Can also be used to set the value of combo boxes, check boxes, etc. In these cases, value should be the value of the option selected, not the visible text. 'locator' is an element locator 'value' is the value to type """ self.do_command("type", [locator,value,]) def type_keys(self,locator,value): """ Simulates keystroke events on the specified element, as though you typed the value key-by-key. This is a convenience method for calling keyDown, keyUp, keyPress for every character in the specified string; this is useful for dynamic UI widgets (like auto-completing combo boxes) that require explicit key events. Unlike the simple "type" command, which forces the specified value into the page directly, this command may or may not have any visible effect, even in cases where typing keys would normally have a visible effect. For example, if you use "typeKeys" on a form element, you may or may not see the results of what you typed in the field. In some cases, you may need to use the simple "type" command to set the value of the field and then the "typeKeys" command to send the keystroke events corresponding to what you just typed. 'locator' is an element locator 'value' is the value to type """ self.do_command("typeKeys", [locator,value,]) def set_speed(self,value): """ Set execution speed (i.e., set the millisecond length of a delay which will follow each selenium operation). By default, there is no such delay, i.e., the delay is 0 milliseconds. 'value' is the number of milliseconds to pause after operation """ self.do_command("setSpeed", [value,]) def get_speed(self): """ Get execution speed (i.e., get the millisecond length of the delay following each selenium operation). By default, there is no such delay, i.e., the delay is 0 milliseconds. See also setSpeed. """ return self.get_string("getSpeed", []) def get_log(self): """ Get RC logs associated with current session. """ return self.get_string("getLog", []) def check(self,locator): """ Check a toggle-button (checkbox/radio) 'locator' is an element locator """ self.do_command("check", [locator,]) def uncheck(self,locator): """ Uncheck a toggle-button (checkbox/radio) 'locator' is an element locator """ self.do_command("uncheck", [locator,]) def select(self,selectLocator,optionLocator): """ Select an option from a drop-down using an option locator. Option locators provide different ways of specifying options of an HTML Select element (e.g. for selecting a specific option, or for asserting that the selected option satisfies a specification). There are several forms of Select Option Locator. * \ **label**\ =\ *labelPattern*: matches options based on their labels, i.e. the visible text. (This is the default.) * label=regexp:^[Oo]ther * \ **value**\ =\ *valuePattern*: matches options based on their values. * value=other * \ **id**\ =\ *id*: matches options based on their ids. * id=option1 * \ **index**\ =\ *index*: matches an option based on its index (offset from zero). * index=2 If no option locator prefix is provided, the default behaviour is to match on \ **label**\ . 'selectLocator' is an element locator identifying a drop-down menu 'optionLocator' is an option locator (a label by default) """ self.do_command("select", [selectLocator,optionLocator,]) def add_selection(self,locator,optionLocator): """ Add a selection to the set of selected options in a multi-select element using an option locator. @see #doSelect for details of option locators 'locator' is an element locator identifying a multi-select box 'optionLocator' is an option locator (a label by default) """ self.do_command("addSelection", [locator,optionLocator,]) def remove_selection(self,locator,optionLocator): """ Remove a selection from the set of selected options in a multi-select element using an option locator. @see #doSelect for details of option locators 'locator' is an element locator identifying a multi-select box 'optionLocator' is an option locator (a label by default) """ self.do_command("removeSelection", [locator,optionLocator,]) def remove_all_selections(self,locator): """ Unselects all of the selected options in a multi-select element. 'locator' is an element locator identifying a multi-select box """ self.do_command("removeAllSelections", [locator,]) def submit(self,formLocator): """ Submit the specified form. This is particularly useful for forms without submit buttons, e.g. single-input "Search" forms. 'formLocator' is an element locator for the form you want to submit """ self.do_command("submit", [formLocator,]) def open(self,url,ignoreResponseCode=True): """ Opens an URL in the test frame. This accepts both relative and absolute URLs. The "open" command waits for the page to load before proceeding, ie. the "AndWait" suffix is implicit. \ *Note*: The URL must be on the same domain as the runner HTML due to security restrictions in the browser (Same Origin Policy). If you need to open an URL on another domain, use the Selenium Server to start a new browser session on that domain. 'url' is the URL to open; may be relative or absolute 'ignoreResponseCode' if set to true: doesnt send ajax HEAD/GET request; if set to false: sends ajax HEAD/GET request to the url and reports error code if any as response to open. """ self.do_command("open", [url,ignoreResponseCode]) def open_window(self,url,windowID): """ Opens a popup window (if a window with that ID isn't already open). After opening the window, you'll need to select it using the selectWindow command. This command can also be a useful workaround for bug SEL-339. In some cases, Selenium will be unable to intercept a call to window.open (if the call occurs during or before the "onLoad" event, for example). In those cases, you can force Selenium to notice the open window's name by using the Selenium openWindow command, using an empty (blank) url, like this: openWindow("", "myFunnyWindow"). 'url' is the URL to open, which can be blank 'windowID' is the JavaScript window ID of the window to select """ self.do_command("openWindow", [url,windowID,]) def select_window(self,windowID): """ Selects a popup window using a window locator; once a popup window has been selected, all commands go to that window. To select the main window again, use null as the target. Window locators provide different ways of specifying the window object: by title, by internal JavaScript "name," or by JavaScript variable. * \ **title**\ =\ *My Special Window*: Finds the window using the text that appears in the title bar. Be careful; two windows can share the same title. If that happens, this locator will just pick one. * \ **name**\ =\ *myWindow*: Finds the window using its internal JavaScript "name" property. This is the second parameter "windowName" passed to the JavaScript method window.open(url, windowName, windowFeatures, replaceFlag) (which Selenium intercepts). * \ **var**\ =\ *variableName*: Some pop-up windows are unnamed (anonymous), but are associated with a JavaScript variable name in the current application window, e.g. "window.foo = window.open(url);". In those cases, you can open the window using "var=foo". If no window locator prefix is provided, we'll try to guess what you mean like this: 1.) if windowID is null, (or the string "null") then it is assumed the user is referring to the original window instantiated by the browser). 2.) if the value of the "windowID" parameter is a JavaScript variable name in the current application window, then it is assumed that this variable contains the return value from a call to the JavaScript window.open() method. 3.) Otherwise, selenium looks in a hash it maintains that maps string names to window "names". 4.) If \ *that* fails, we'll try looping over all of the known windows to try to find the appropriate "title". Since "title" is not necessarily unique, this may have unexpected behavior. If you're having trouble figuring out the name of a window that you want to manipulate, look at the Selenium log messages which identify the names of windows created via window.open (and therefore intercepted by Selenium). You will see messages like the following for each window as it is opened: ``debug: window.open call intercepted; window ID (which you can use with selectWindow()) is "myNewWindow"`` In some cases, Selenium will be unable to intercept a call to window.open (if the call occurs during or before the "onLoad" event, for example). (This is bug SEL-339.) In those cases, you can force Selenium to notice the open window's name by using the Selenium openWindow command, using an empty (blank) url, like this: openWindow("", "myFunnyWindow"). 'windowID' is the JavaScript window ID of the window to select """ self.do_command("selectWindow", [windowID,]) def select_pop_up(self,windowID): """ Simplifies the process of selecting a popup window (and does not offer functionality beyond what ``selectWindow()`` already provides). * If ``windowID`` is either not specified, or specified as "null", the first non-top window is selected. The top window is the one that would be selected by ``selectWindow()`` without providing a ``windowID`` . This should not be used when more than one popup window is in play. * Otherwise, the window will be looked up considering ``windowID`` as the following in order: 1) the "name" of the window, as specified to ``window.open()``; 2) a javascript variable which is a reference to a window; and 3) the title of the window. This is the same ordered lookup performed by ``selectWindow`` . 'windowID' is an identifier for the popup window, which can take on a number of different meanings """ self.do_command("selectPopUp", [windowID,]) def deselect_pop_up(self): """ Selects the main window. Functionally equivalent to using ``selectWindow()`` and specifying no value for ``windowID``. """ self.do_command("deselectPopUp", []) def select_frame(self,locator): """ Selects a frame within the current window. (You may invoke this command multiple times to select nested frames.) To select the parent frame, use "relative=parent" as a locator; to select the top frame, use "relative=top". You can also select a frame by its 0-based index number; select the first frame with "index=0", or the third frame with "index=2". You may also use a DOM expression to identify the frame you want directly, like this: ``dom=frames["main"].frames["subframe"]`` 'locator' is an element locator identifying a frame or iframe """ self.do_command("selectFrame", [locator,]) def get_whether_this_frame_match_frame_expression(self,currentFrameString,target): """ Determine whether current/locator identify the frame containing this running code. This is useful in proxy injection mode, where this code runs in every browser frame and window, and sometimes the selenium server needs to identify the "current" frame. In this case, when the test calls selectFrame, this routine is called for each frame to figure out which one has been selected. The selected frame will return true, while all others will return false. 'currentFrameString' is starting frame 'target' is new frame (which might be relative to the current one) """ return self.get_boolean("getWhetherThisFrameMatchFrameExpression", [currentFrameString,target,]) def get_whether_this_window_match_window_expression(self,currentWindowString,target): """ Determine whether currentWindowString plus target identify the window containing this running code. This is useful in proxy injection mode, where this code runs in every browser frame and window, and sometimes the selenium server needs to identify the "current" window. In this case, when the test calls selectWindow, this routine is called for each window to figure out which one has been selected. The selected window will return true, while all others will return false. 'currentWindowString' is starting window 'target' is new window (which might be relative to the current one, e.g., "_parent") """ return self.get_boolean("getWhetherThisWindowMatchWindowExpression", [currentWindowString,target,]) def wait_for_pop_up(self,windowID,timeout): """ Waits for a popup window to appear and load up. 'windowID' is the JavaScript window "name" of the window that will appear (not the text of the title bar) If unspecified, or specified as "null", this command will wait for the first non-top window to appear (don't rely on this if you are working with multiple popups simultaneously). 'timeout' is a timeout in milliseconds, after which the action will return with an error. If this value is not specified, the default Selenium timeout will be used. See the setTimeout() command. """ self.do_command("waitForPopUp", [windowID,timeout,]) def choose_cancel_on_next_confirmation(self): """ By default, Selenium's overridden window.confirm() function will return true, as if the user had manually clicked OK; after running this command, the next call to confirm() will return false, as if the user had clicked Cancel. Selenium will then resume using the default behavior for future confirmations, automatically returning true (OK) unless/until you explicitly call this command for each confirmation. Take note - every time a confirmation comes up, you must consume it with a corresponding getConfirmation, or else the next selenium operation will fail. """ self.do_command("chooseCancelOnNextConfirmation", []) def choose_ok_on_next_confirmation(self): """ Undo the effect of calling chooseCancelOnNextConfirmation. Note that Selenium's overridden window.confirm() function will normally automatically return true, as if the user had manually clicked OK, so you shouldn't need to use this command unless for some reason you need to change your mind prior to the next confirmation. After any confirmation, Selenium will resume using the default behavior for future confirmations, automatically returning true (OK) unless/until you explicitly call chooseCancelOnNextConfirmation for each confirmation. Take note - every time a confirmation comes up, you must consume it with a corresponding getConfirmation, or else the next selenium operation will fail. """ self.do_command("chooseOkOnNextConfirmation", []) def answer_on_next_prompt(self,answer): """ Instructs Selenium to return the specified answer string in response to the next JavaScript prompt [window.prompt()]. 'answer' is the answer to give in response to the prompt pop-up """ self.do_command("answerOnNextPrompt", [answer,]) def go_back(self): """ Simulates the user clicking the "back" button on their browser. """ self.do_command("goBack", []) def refresh(self): """ Simulates the user clicking the "Refresh" button on their browser. """ self.do_command("refresh", []) def close(self): """ Simulates the user clicking the "close" button in the titlebar of a popup window or tab. """ self.do_command("close", []) def is_alert_present(self): """ Has an alert occurred? This function never throws an exception """ return self.get_boolean("isAlertPresent", []) def is_prompt_present(self): """ Has a prompt occurred? This function never throws an exception """ return self.get_boolean("isPromptPresent", []) def is_confirmation_present(self): """ Has confirm() been called? This function never throws an exception """ return self.get_boolean("isConfirmationPresent", []) def get_alert(self): """ Retrieves the message of a JavaScript alert generated during the previous action, or fail if there were no alerts. Getting an alert has the same effect as manually clicking OK. If an alert is generated but you do not consume it with getAlert, the next Selenium action will fail. Under Selenium, JavaScript alerts will NOT pop up a visible alert dialog. Selenium does NOT support JavaScript alerts that are generated in a page's onload() event handler. In this case a visible dialog WILL be generated and Selenium will hang until someone manually clicks OK. """ return self.get_string("getAlert", []) def get_confirmation(self): """ Retrieves the message of a JavaScript confirmation dialog generated during the previous action. By default, the confirm function will return true, having the same effect as manually clicking OK. This can be changed by prior execution of the chooseCancelOnNextConfirmation command. If an confirmation is generated but you do not consume it with getConfirmation, the next Selenium action will fail. NOTE: under Selenium, JavaScript confirmations will NOT pop up a visible dialog. NOTE: Selenium does NOT support JavaScript confirmations that are generated in a page's onload() event handler. In this case a visible dialog WILL be generated and Selenium will hang until you manually click OK. """ return self.get_string("getConfirmation", []) def get_prompt(self): """ Retrieves the message of a JavaScript question prompt dialog generated during the previous action. Successful handling of the prompt requires prior execution of the answerOnNextPrompt command. If a prompt is generated but you do not get/verify it, the next Selenium action will fail. NOTE: under Selenium, JavaScript prompts will NOT pop up a visible dialog. NOTE: Selenium does NOT support JavaScript prompts that are generated in a page's onload() event handler. In this case a visible dialog WILL be generated and Selenium will hang until someone manually clicks OK. """ return self.get_string("getPrompt", []) def get_location(self): """ Gets the absolute URL of the current page. """ return self.get_string("getLocation", []) def get_title(self): """ Gets the title of the current page. """ return self.get_string("getTitle", []) def get_body_text(self): """ Gets the entire text of the page. """ return self.get_string("getBodyText", []) def get_value(self,locator): """ Gets the (whitespace-trimmed) value of an input field (or anything else with a value parameter). For checkbox/radio elements, the value will be "on" or "off" depending on whether the element is checked or not. 'locator' is an element locator """ return self.get_string("getValue", [locator,]) def get_text(self,locator): """ Gets the text of an element. This works for any element that contains text. This command uses either the textContent (Mozilla-like browsers) or the innerText (IE-like browsers) of the element, which is the rendered text shown to the user. 'locator' is an element locator """ return self.get_string("getText", [locator,]) def highlight(self,locator): """ Briefly changes the backgroundColor of the specified element yellow. Useful for debugging. 'locator' is an element locator """ self.do_command("highlight", [locator,]) def get_eval(self,script): """ Gets the result of evaluating the specified JavaScript snippet. The snippet may have multiple lines, but only the result of the last line will be returned. Note that, by default, the snippet will run in the context of the "selenium" object itself, so ``this`` will refer to the Selenium object. Use ``window`` to refer to the window of your application, e.g. ``window.document.getElementById('foo')`` If you need to use a locator to refer to a single element in your application page, you can use ``this.browserbot.findElement("id=foo")`` where "id=foo" is your locator. 'script' is the JavaScript snippet to run """ return self.get_string("getEval", [script,]) def is_checked(self,locator): """ Gets whether a toggle-button (checkbox/radio) is checked. Fails if the specified element doesn't exist or isn't a toggle-button. 'locator' is an element locator pointing to a checkbox or radio button """ return self.get_boolean("isChecked", [locator,]) def get_table(self,tableCellAddress): """ Gets the text from a cell of a table. The cellAddress syntax tableLocator.row.column, where row and column start at 0. 'tableCellAddress' is a cell address, e.g. "foo.1.4" """ return self.get_string("getTable", [tableCellAddress,]) def get_selected_labels(self,selectLocator): """ Gets all option labels (visible text) for selected options in the specified select or multi-select element. 'selectLocator' is an element locator identifying a drop-down menu """ return self.get_string_array("getSelectedLabels", [selectLocator,]) def get_selected_label(self,selectLocator): """ Gets option label (visible text) for selected option in the specified select element. 'selectLocator' is an element locator identifying a drop-down menu """ return self.get_string("getSelectedLabel", [selectLocator,]) def get_selected_values(self,selectLocator): """ Gets all option values (value attributes) for selected options in the specified select or multi-select element. 'selectLocator' is an element locator identifying a drop-down menu """ return self.get_string_array("getSelectedValues", [selectLocator,]) def get_selected_value(self,selectLocator): """ Gets option value (value attribute) for selected option in the specified select element. 'selectLocator' is an element locator identifying a drop-down menu """ return self.get_string("getSelectedValue", [selectLocator,]) def get_selected_indexes(self,selectLocator): """ Gets all option indexes (option number, starting at 0) for selected options in the specified select or multi-select element. 'selectLocator' is an element locator identifying a drop-down menu """ return self.get_string_array("getSelectedIndexes", [selectLocator,]) def get_selected_index(self,selectLocator): """ Gets option index (option number, starting at 0) for selected option in the specified select element. 'selectLocator' is an element locator identifying a drop-down menu """ return self.get_string("getSelectedIndex", [selectLocator,]) def get_selected_ids(self,selectLocator): """ Gets all option element IDs for selected options in the specified select or multi-select element. 'selectLocator' is an element locator identifying a drop-down menu """ return self.get_string_array("getSelectedIds", [selectLocator,]) def get_selected_id(self,selectLocator): """ Gets option element ID for selected option in the specified select element. 'selectLocator' is an element locator identifying a drop-down menu """ return self.get_string("getSelectedId", [selectLocator,]) def is_something_selected(self,selectLocator): """ Determines whether some option in a drop-down menu is selected. 'selectLocator' is an element locator identifying a drop-down menu """ return self.get_boolean("isSomethingSelected", [selectLocator,]) def get_select_options(self,selectLocator): """ Gets all option labels in the specified select drop-down. 'selectLocator' is an element locator identifying a drop-down menu """ return self.get_string_array("getSelectOptions", [selectLocator,]) def get_attribute(self,attributeLocator): """ Gets the value of an element attribute. The value of the attribute may differ across browsers (this is the case for the "style" attribute, for example). 'attributeLocator' is an element locator followed by an @ sign and then the name of the attribute, e.g. "foo@bar" """ return self.get_string("getAttribute", [attributeLocator,]) def is_text_present(self,pattern): """ Verifies that the specified text pattern appears somewhere on the rendered page shown to the user. 'pattern' is a pattern to match with the text of the page """ return self.get_boolean("isTextPresent", [pattern,]) def is_element_present(self,locator): """ Verifies that the specified element is somewhere on the page. 'locator' is an element locator """ return self.get_boolean("isElementPresent", [locator,]) def is_visible(self,locator): """ Determines if the specified element is visible. An element can be rendered invisible by setting the CSS "visibility" property to "hidden", or the "display" property to "none", either for the element itself or one if its ancestors. This method will fail if the element is not present. 'locator' is an element locator """ return self.get_boolean("isVisible", [locator,]) def is_editable(self,locator): """ Determines whether the specified input element is editable, ie hasn't been disabled. This method will fail if the specified element isn't an input element. 'locator' is an element locator """ return self.get_boolean("isEditable", [locator,]) def get_all_buttons(self): """ Returns the IDs of all buttons on the page. If a given button has no ID, it will appear as "" in this array. """ return self.get_string_array("getAllButtons", []) def get_all_links(self): """ Returns the IDs of all links on the page. If a given link has no ID, it will appear as "" in this array. """ return self.get_string_array("getAllLinks", []) def get_all_fields(self): """ Returns the IDs of all input fields on the page. If a given field has no ID, it will appear as "" in this array. """ return self.get_string_array("getAllFields", []) def get_attribute_from_all_windows(self,attributeName): """ Returns every instance of some attribute from all known windows. 'attributeName' is name of an attribute on the windows """ return self.get_string_array("getAttributeFromAllWindows", [attributeName,]) def dragdrop(self,locator,movementsString): """ deprecated - use dragAndDrop instead 'locator' is an element locator 'movementsString' is offset in pixels from the current location to which the element should be moved, e.g., "+70,-300" """ self.do_command("dragdrop", [locator,movementsString,]) def set_mouse_speed(self,pixels): """ Configure the number of pixels between "mousemove" events during dragAndDrop commands (default=10). Setting this value to 0 means that we'll send a "mousemove" event to every single pixel in between the start location and the end location; that can be very slow, and may cause some browsers to force the JavaScript to timeout. If the mouse speed is greater than the distance between the two dragged objects, we'll just send one "mousemove" at the start location and then one final one at the end location. 'pixels' is the number of pixels between "mousemove" events """ self.do_command("setMouseSpeed", [pixels,]) def get_mouse_speed(self): """ Returns the number of pixels between "mousemove" events during dragAndDrop commands (default=10). """ return self.get_number("getMouseSpeed", []) def drag_and_drop(self,locator,movementsString): """ Drags an element a certain distance and then drops it 'locator' is an element locator 'movementsString' is offset in pixels from the current location to which the element should be moved, e.g., "+70,-300" """ self.do_command("dragAndDrop", [locator,movementsString,]) def drag_and_drop_to_object(self,locatorOfObjectToBeDragged,locatorOfDragDestinationObject): """ Drags an element and drops it on another element 'locatorOfObjectToBeDragged' is an element to be dragged 'locatorOfDragDestinationObject' is an element whose location (i.e., whose center-most pixel) will be the point where locatorOfObjectToBeDragged is dropped """ self.do_command("dragAndDropToObject", [locatorOfObjectToBeDragged,locatorOfDragDestinationObject,]) def window_focus(self): """ Gives focus to the currently selected window """ self.do_command("windowFocus", []) def window_maximize(self): """ Resize currently selected window to take up the entire screen """ self.do_command("windowMaximize", []) def get_all_window_ids(self): """ Returns the IDs of all windows that the browser knows about. """ return self.get_string_array("getAllWindowIds", []) def get_all_window_names(self): """ Returns the names of all windows that the browser knows about. """ return self.get_string_array("getAllWindowNames", []) def get_all_window_titles(self): """ Returns the titles of all windows that the browser knows about. """ return self.get_string_array("getAllWindowTitles", []) def get_html_source(self): """ Returns the entire HTML source between the opening and closing "html" tags. """ return self.get_string("getHtmlSource", []) def set_cursor_position(self,locator,position): """ Moves the text cursor to the specified position in the given input element or textarea. This method will fail if the specified element isn't an input element or textarea. 'locator' is an element locator pointing to an input element or textarea 'position' is the numerical position of the cursor in the field; position should be 0 to move the position to the beginning of the field. You can also set the cursor to -1 to move it to the end of the field. """ self.do_command("setCursorPosition", [locator,position,]) def get_element_index(self,locator): """ Get the relative index of an element to its parent (starting from 0). The comment node and empty text node will be ignored. 'locator' is an element locator pointing to an element """ return self.get_number("getElementIndex", [locator,]) def is_ordered(self,locator1,locator2): """ Check if these two elements have same parent and are ordered siblings in the DOM. Two same elements will not be considered ordered. 'locator1' is an element locator pointing to the first element 'locator2' is an element locator pointing to the second element """ return self.get_boolean("isOrdered", [locator1,locator2,]) def get_element_position_left(self,locator): """ Retrieves the horizontal position of an element 'locator' is an element locator pointing to an element OR an element itself """ return self.get_number("getElementPositionLeft", [locator,]) def get_element_position_top(self,locator): """ Retrieves the vertical position of an element 'locator' is an element locator pointing to an element OR an element itself """ return self.get_number("getElementPositionTop", [locator,]) def get_element_width(self,locator): """ Retrieves the width of an element 'locator' is an element locator pointing to an element """ return self.get_number("getElementWidth", [locator,]) def get_element_height(self,locator): """ Retrieves the height of an element 'locator' is an element locator pointing to an element """ return self.get_number("getElementHeight", [locator,]) def get_cursor_position(self,locator): """ Retrieves the text cursor position in the given input element or textarea; beware, this may not work perfectly on all browsers. Specifically, if the cursor/selection has been cleared by JavaScript, this command will tend to return the position of the last location of the cursor, even though the cursor is now gone from the page. This is filed as SEL-243. This method will fail if the specified element isn't an input element or textarea, or there is no cursor in the element. 'locator' is an element locator pointing to an input element or textarea """ return self.get_number("getCursorPosition", [locator,]) def get_expression(self,expression): """ Returns the specified expression. This is useful because of JavaScript preprocessing. It is used to generate commands like assertExpression and waitForExpression. 'expression' is the value to return """ return self.get_string("getExpression", [expression,]) def get_xpath_count(self,xpath): """ Returns the number of nodes that match the specified xpath, eg. "//table" would give the number of tables. 'xpath' is the xpath expression to evaluate. do NOT wrap this expression in a 'count()' function; we will do that for you. """ return self.get_number("getXpathCount", [xpath,]) def get_css_count(self,css): """ Returns the number of nodes that match the specified css selector, eg. "css=table" would give the number of tables. 'css' is the css selector to evaluate. do NOT wrap this expression in a 'count()' function; we will do that for you. """ return self.get_number("getCssCount", [css,]) def assign_id(self,locator,identifier): """ Temporarily sets the "id" attribute of the specified element, so you can locate it in the future using its ID rather than a slow/complicated XPath. This ID will disappear once the page is reloaded. 'locator' is an element locator pointing to an element 'identifier' is a string to be used as the ID of the specified element """ self.do_command("assignId", [locator,identifier,]) def allow_native_xpath(self,allow): """ Specifies whether Selenium should use the native in-browser implementation of XPath (if any native version is available); if you pass "false" to this function, we will always use our pure-JavaScript xpath library. Using the pure-JS xpath library can improve the consistency of xpath element locators between different browser vendors, but the pure-JS version is much slower than the native implementations. 'allow' is boolean, true means we'll prefer to use native XPath; false means we'll only use JS XPath """ self.do_command("allowNativeXpath", [allow,]) def ignore_attributes_without_value(self,ignore): """ Specifies whether Selenium will ignore xpath attributes that have no value, i.e. are the empty string, when using the non-native xpath evaluation engine. You'd want to do this for performance reasons in IE. However, this could break certain xpaths, for example an xpath that looks for an attribute whose value is NOT the empty string. The hope is that such xpaths are relatively rare, but the user should have the option of using them. Note that this only influences xpath evaluation when using the ajaxslt engine (i.e. not "javascript-xpath"). 'ignore' is boolean, true means we'll ignore attributes without value at the expense of xpath "correctness"; false means we'll sacrifice speed for correctness. """ self.do_command("ignoreAttributesWithoutValue", [ignore,]) def wait_for_condition(self,script,timeout): """ Runs the specified JavaScript snippet repeatedly until it evaluates to "true". The snippet may have multiple lines, but only the result of the last line will be considered. Note that, by default, the snippet will be run in the runner's test window, not in the window of your application. To get the window of your application, you can use the JavaScript snippet ``selenium.browserbot.getCurrentWindow()``, and then run your JavaScript in there 'script' is the JavaScript snippet to run 'timeout' is a timeout in milliseconds, after which this command will return with an error """ self.do_command("waitForCondition", [script,timeout,]) def set_timeout(self,timeout): """ Specifies the amount of time that Selenium will wait for actions to complete. Actions that require waiting include "open" and the "waitFor\*" actions. The default timeout is 30 seconds. 'timeout' is a timeout in milliseconds, after which the action will return with an error """ self.do_command("setTimeout", [timeout,]) def wait_for_page_to_load(self,timeout): """ Waits for a new page to load. You can use this command instead of the "AndWait" suffixes, "clickAndWait", "selectAndWait", "typeAndWait" etc. (which are only available in the JS API). Selenium constantly keeps track of new pages loading, and sets a "newPageLoaded" flag when it first notices a page load. Running any other Selenium command after turns the flag to false. Hence, if you want to wait for a page to load, you must wait immediately after a Selenium command that caused a page-load. 'timeout' is a timeout in milliseconds, after which this command will return with an error """ self.do_command("waitForPageToLoad", [timeout,]) def wait_for_frame_to_load(self,frameAddress,timeout): """ Waits for a new frame to load. Selenium constantly keeps track of new pages and frames loading, and sets a "newPageLoaded" flag when it first notices a page load. See waitForPageToLoad for more information. 'frameAddress' is FrameAddress from the server side 'timeout' is a timeout in milliseconds, after which this command will return with an error """ self.do_command("waitForFrameToLoad", [frameAddress,timeout,]) def get_cookie(self): """ Return all cookies of the current page under test. """ return self.get_string("getCookie", []) def get_cookie_by_name(self,name): """ Returns the value of the cookie with the specified name, or throws an error if the cookie is not present. 'name' is the name of the cookie """ return self.get_string("getCookieByName", [name,]) def is_cookie_present(self,name): """ Returns true if a cookie with the specified name is present, or false otherwise. 'name' is the name of the cookie """ return self.get_boolean("isCookiePresent", [name,]) def create_cookie(self,nameValuePair,optionsString): """ Create a new cookie whose path and domain are same with those of current page under test, unless you specified a path for this cookie explicitly. 'nameValuePair' is name and value of the cookie in a format "name=value" 'optionsString' is options for the cookie. Currently supported options include 'path', 'max_age' and 'domain'. the optionsString's format is "path=/path/, max_age=60, domain=.foo.com". The order of options are irrelevant, the unit of the value of 'max_age' is second. Note that specifying a domain that isn't a subset of the current domain will usually fail. """ self.do_command("createCookie", [nameValuePair,optionsString,]) def delete_cookie(self,name,optionsString): """ Delete a named cookie with specified path and domain. Be careful; to delete a cookie, you need to delete it using the exact same path and domain that were used to create the cookie. If the path is wrong, or the domain is wrong, the cookie simply won't be deleted. Also note that specifying a domain that isn't a subset of the current domain will usually fail. Since there's no way to discover at runtime the original path and domain of a given cookie, we've added an option called 'recurse' to try all sub-domains of the current domain with all paths that are a subset of the current path. Beware; this option can be slow. In big-O notation, it operates in O(n\*m) time, where n is the number of dots in the domain name and m is the number of slashes in the path. 'name' is the name of the cookie to be deleted 'optionsString' is options for the cookie. Currently supported options include 'path', 'domain' and 'recurse.' The optionsString's format is "path=/path/, domain=.foo.com, recurse=true". The order of options are irrelevant. Note that specifying a domain that isn't a subset of the current domain will usually fail. """ self.do_command("deleteCookie", [name,optionsString,]) def delete_all_visible_cookies(self): """ Calls deleteCookie with recurse=true on all cookies visible to the current page. As noted on the documentation for deleteCookie, recurse=true can be much slower than simply deleting the cookies using a known domain/path. """ self.do_command("deleteAllVisibleCookies", []) def set_browser_log_level(self,logLevel): """ Sets the threshold for browser-side logging messages; log messages beneath this threshold will be discarded. Valid logLevel strings are: "debug", "info", "warn", "error" or "off". To see the browser logs, you need to either show the log window in GUI mode, or enable browser-side logging in Selenium RC. 'logLevel' is one of the following: "debug", "info", "warn", "error" or "off" """ self.do_command("setBrowserLogLevel", [logLevel,]) def run_script(self,script): """ Creates a new "script" tag in the body of the current test window, and adds the specified text into the body of the command. Scripts run in this way can often be debugged more easily than scripts executed using Selenium's "getEval" command. Beware that JS exceptions thrown in these script tags aren't managed by Selenium, so you should probably wrap your script in try/catch blocks if there is any chance that the script will throw an exception. 'script' is the JavaScript snippet to run """ self.do_command("runScript", [script,]) def add_location_strategy(self,strategyName,functionDefinition): """ Defines a new function for Selenium to locate elements on the page. For example, if you define the strategy "foo", and someone runs click("foo=blah"), we'll run your function, passing you the string "blah", and click on the element that your function returns, or throw an "Element not found" error if your function returns null. We'll pass three arguments to your function: * locator: the string the user passed in * inWindow: the currently selected window * inDocument: the currently selected document The function must return null if the element can't be found. 'strategyName' is the name of the strategy to define; this should use only letters [a-zA-Z] with no spaces or other punctuation. 'functionDefinition' is a string defining the body of a function in JavaScript. For example: ``return inDocument.getElementById(locator);`` """ self.do_command("addLocationStrategy", [strategyName,functionDefinition,]) def capture_entire_page_screenshot(self,filename,kwargs): """ Saves the entire contents of the current window canvas to a PNG file. Contrast this with the captureScreenshot command, which captures the contents of the OS viewport (i.e. whatever is currently being displayed on the monitor), and is implemented in the RC only. Currently this only works in Firefox when running in chrome mode, and in IE non-HTA using the EXPERIMENTAL "Snapsie" utility. The Firefox implementation is mostly borrowed from the Screengrab! Firefox extension. Please see http://www.screengrab.org and http://snapsie.sourceforge.net/ for details. 'filename' is the path to the file to persist the screenshot as. No filename extension will be appended by default. Directories will not be created if they do not exist, and an exception will be thrown, possibly by native code. 'kwargs' is a kwargs string that modifies the way the screenshot is captured. Example: "background=#CCFFDD" Currently valid options: * background the background CSS for the HTML document. This may be useful to set for capturing screenshots of less-than-ideal layouts, for example where absolute positioning causes the calculation of the canvas dimension to fail and a black background is exposed (possibly obscuring black text). """ self.do_command("captureEntirePageScreenshot", [filename,kwargs,]) def rollup(self,rollupName,kwargs): """ Executes a command rollup, which is a series of commands with a unique name, and optionally arguments that control the generation of the set of commands. If any one of the rolled-up commands fails, the rollup is considered to have failed. Rollups may also contain nested rollups. 'rollupName' is the name of the rollup command 'kwargs' is keyword arguments string that influences how the rollup expands into commands """ self.do_command("rollup", [rollupName,kwargs,]) def add_script(self,scriptContent,scriptTagId): """ Loads script content into a new script tag in the Selenium document. This differs from the runScript command in that runScript adds the script tag to the document of the AUT, not the Selenium document. The following entities in the script content are replaced by the characters they represent: < > & The corresponding remove command is removeScript. 'scriptContent' is the Javascript content of the script to add 'scriptTagId' is (optional) the id of the new script tag. If specified, and an element with this id already exists, this operation will fail. """ self.do_command("addScript", [scriptContent,scriptTagId,]) def remove_script(self,scriptTagId): """ Removes a script tag from the Selenium document identified by the given id. Does nothing if the referenced tag doesn't exist. 'scriptTagId' is the id of the script element to remove. """ self.do_command("removeScript", [scriptTagId,]) def use_xpath_library(self,libraryName): """ Allows choice of one of the available libraries. 'libraryName' is name of the desired library Only the following three can be chosen: * "ajaxslt" - Google's library * "javascript-xpath" - Cybozu Labs' faster library * "default" - The default library. Currently the default library is "ajaxslt" . If libraryName isn't one of these three, then no change will be made. """ self.do_command("useXpathLibrary", [libraryName,]) def set_context(self,context): """ Writes a message to the status bar and adds a note to the browser-side log. 'context' is the message to be sent to the browser """ self.do_command("setContext", [context,]) def attach_file(self,fieldLocator,fileLocator): """ Sets a file input (upload) field to the file listed in fileLocator 'fieldLocator' is an element locator 'fileLocator' is a URL pointing to the specified file. Before the file can be set in the input field (fieldLocator), Selenium RC may need to transfer the file to the local machine before attaching the file in a web page form. This is common in selenium grid configurations where the RC server driving the browser is not the same machine that started the test. Supported Browsers: Firefox ("\*chrome") only. """ self.do_command("attachFile", [fieldLocator,fileLocator,]) def capture_screenshot(self,filename): """ Captures a PNG screenshot to the specified file. 'filename' is the absolute path to the file to be written, e.g. "c:\blah\screenshot.png" """ self.do_command("captureScreenshot", [filename,]) def capture_screenshot_to_string(self): """ Capture a PNG screenshot. It then returns the file as a base 64 encoded string. """ return self.get_string("captureScreenshotToString", []) def captureNetworkTraffic(self, type): """ Returns the network traffic seen by the browser, including headers, AJAX requests, status codes, and timings. When this function is called, the traffic log is cleared, so the returned content is only the traffic seen since the last call. 'type' is The type of data to return the network traffic as. Valid values are: json, xml, or plain. """ return self.get_string("captureNetworkTraffic", [type,]) def capture_network_traffic(self, type): return self.captureNetworkTraffic(type) def addCustomRequestHeader(self, key, value): """ Tells the Selenium server to add the specificed key and value as a custom outgoing request header. This only works if the browser is configured to use the built in Selenium proxy. 'key' the header name. 'value' the header value. """ return self.do_command("addCustomRequestHeader", [key,value,]) def add_custom_request_header(self, key, value): return self.addCustomRequestHeader(key, value) def capture_entire_page_screenshot_to_string(self,kwargs): """ Downloads a screenshot of the browser current window canvas to a based 64 encoded PNG file. The \ *entire* windows canvas is captured, including parts rendered outside of the current view port. Currently this only works in Mozilla and when running in chrome mode. 'kwargs' is A kwargs string that modifies the way the screenshot is captured. Example: "background=#CCFFDD". This may be useful to set for capturing screenshots of less-than-ideal layouts, for example where absolute positioning causes the calculation of the canvas dimension to fail and a black background is exposed (possibly obscuring black text). """ return self.get_string("captureEntirePageScreenshotToString", [kwargs,]) def shut_down_selenium_server(self): """ Kills the running Selenium Server and all browser sessions. After you run this command, you will no longer be able to send commands to the server; you can't remotely start the server once it has been stopped. Normally you should prefer to run the "stop" command, which terminates the current browser session, rather than shutting down the entire server. """ self.do_command("shutDownSeleniumServer", []) def retrieve_last_remote_control_logs(self): """ Retrieve the last messages logged on a specific remote control. Useful for error reports, especially when running multiple remote controls in a distributed environment. The maximum number of log messages that can be retrieve is configured on remote control startup. """ return self.get_string("retrieveLastRemoteControlLogs", []) def key_down_native(self,keycode): """ Simulates a user pressing a key (without releasing it yet) by sending a native operating system keystroke. This function uses the java.awt.Robot class to send a keystroke; this more accurately simulates typing a key on the keyboard. It does not honor settings from the shiftKeyDown, controlKeyDown, altKeyDown and metaKeyDown commands, and does not target any particular HTML element. To send a keystroke to a particular element, focus on the element first before running this command. 'keycode' is an integer keycode number corresponding to a java.awt.event.KeyEvent; note that Java keycodes are NOT the same thing as JavaScript keycodes! """ self.do_command("keyDownNative", [keycode,]) def key_up_native(self,keycode): """ Simulates a user releasing a key by sending a native operating system keystroke. This function uses the java.awt.Robot class to send a keystroke; this more accurately simulates typing a key on the keyboard. It does not honor settings from the shiftKeyDown, controlKeyDown, altKeyDown and metaKeyDown commands, and does not target any particular HTML element. To send a keystroke to a particular element, focus on the element first before running this command. 'keycode' is an integer keycode number corresponding to a java.awt.event.KeyEvent; note that Java keycodes are NOT the same thing as JavaScript keycodes! """ self.do_command("keyUpNative", [keycode,]) def key_press_native(self,keycode): """ Simulates a user pressing and releasing a key by sending a native operating system keystroke. This function uses the java.awt.Robot class to send a keystroke; this more accurately simulates typing a key on the keyboard. It does not honor settings from the shiftKeyDown, controlKeyDown, altKeyDown and metaKeyDown commands, and does not target any particular HTML element. To send a keystroke to a particular element, focus on the element first before running this command. 'keycode' is an integer keycode number corresponding to a java.awt.event.KeyEvent; note that Java keycodes are NOT the same thing as JavaScript keycodes! """ self.do_command("keyPressNative", [keycode,]) selenium-2.48.0/py/selenium/webdriver/0000755000076600000240000000000012605237755020325 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/__init__.py0000644000076600000240000000311012604471537022426 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from .firefox.webdriver import WebDriver as Firefox from .firefox.firefox_profile import FirefoxProfile from .chrome.webdriver import WebDriver as Chrome from .chrome.options import Options as ChromeOptions from .ie.webdriver import WebDriver as Ie from .edge.webdriver import WebDriver as Edge from .opera.webdriver import WebDriver as Opera from .safari.webdriver import WebDriver as Safari from .blackberry.webdriver import WebDriver as BlackBerry from .phantomjs.webdriver import WebDriver as PhantomJS from .android.webdriver import WebDriver as Android from .remote.webdriver import WebDriver as Remote from .common.desired_capabilities import DesiredCapabilities from .common.action_chains import ActionChains from .common.touch_actions import TouchActions from .common.proxy import Proxy __version__ = '2.48.0' selenium-2.48.0/py/selenium/webdriver/android/0000755000076600000240000000000012605237755021745 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/android/__init__.py0000644000076600000240000000142412551302002024031 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/android/webdriver.py0000644000076600000240000000331012551302002024257 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities class WebDriver(RemoteWebDriver): """ Simple RemoteWebDriver wrapper to start connect to Selendroid's WebView app For more info on getting started with Selendroid http://selendroid.io/mobileWeb.html """ def __init__(self, host="localhost", port=4444, desired_capabilities=DesiredCapabilities.ANDROID): """ Creates a new instance of Selendroid using the WebView app :Args: - host - location of where selendroid is running - port - port that selendroid is running on - desired_capabilities: Dictionary object with capabilities """ RemoteWebDriver.__init__(self, command_executor="http://%s:%d/wd/hub" % (host, port), desired_capabilities=desired_capabilities) selenium-2.48.0/py/selenium/webdriver/blackberry/0000755000076600000240000000000012605237755022445 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/blackberry/__init__.py0000644000076600000240000000142312551302002024530 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/blackberry/webdriver.py0000644000076600000240000001134612551302002024767 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 os import platform import time import subprocess from selenium.webdriver.remote.command import Command from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver from selenium.common.exceptions import WebDriverException from selenium.webdriver.support.ui import WebDriverWait LOAD_TIMEOUT = 5 class WebDriver(RemoteWebDriver): """ Controls the BlackBerry Browser and allows you to drive it. :Args: - device_password - password for the BlackBerry device or emulator you are trying to drive - bb_tools_dir path to the blackberry-deploy executable. If the default is used it assumes it is in the $PATH - hostip - the ip for the device you are trying to drive. Falls back to 169.254.0.1 which is the default ip used - port - the port being used for WebDriver on device. defaults to 1338 - desired_capabilities: Dictionary object with non-browser specific capabilities only, such as "proxy" or "loggingPref". Note: To get blackberry-deploy you will need to install the BlackBerry WebWorks SDK - the default install will put it in the $PATH for you. Download at https://developer.blackberry.com/html5/downloads/ """ def __init__(self, device_password, bb_tools_dir=None, hostip='169.254.0.1', port=1338, desired_capabilities={}): remote_addr = 'http://{}:{}'.format(hostip, port) filename = 'blackberry-deploy' if platform.system() == "Windows": filename += '.bat' if bb_tools_dir is not None: if os.path.isdir(bb_tools_dir): bb_deploy_location = os.path.join(bb_tools_dir, filename) if not os.path.isfile(bb_deploy_location): raise WebDriverException('Invalid blackberry-deploy location: {}'.format(bb_deploy_location)) else: raise WebDriverException('Invalid blackberry tools location, must be a directory: {}'.format(bb_tools_dir)) else: bb_deploy_location = filename """ Now launch the BlackBerry browser before allowing anything else to run. """ try: launch_args = [bb_deploy_location, '-launchApp', str(hostip), '-package-name', 'sys.browser', '-package-id', 'gYABgJYFHAzbeFMPCCpYWBtHAm0', '-password', str(device_password)] with open(os.devnull, 'w') as fp: p = subprocess.Popen(launch_args, stdout=fp) returncode = p.wait() if returncode == 0: # wait for the BlackBerry10 browser to load. is_running_args = [bb_deploy_location, '-isAppRunning', str(hostip), '-package-name', 'sys.browser', '-package-id', 'gYABgJYFHAzbeFMPCCpYWBtHAm0', '-password', str(device_password)] WebDriverWait(None, LOAD_TIMEOUT)\ .until(lambda x: subprocess.check_output(is_running_args) .find('result::true'), message='waiting for BlackBerry10 browser to load') RemoteWebDriver.__init__(self, command_executor=remote_addr, desired_capabilities=desired_capabilities) else: raise WebDriverException('blackberry-deploy failed to launch browser') except Exception as e: raise WebDriverException('Something went wrong launching blackberry-deploy', stacktrace=getattr(e, 'stacktrace', None)) def quit(self): """ Closes the browser and shuts down the """ try: RemoteWebDriver.quit(self) except http_client.BadStatusLine: pass selenium-2.48.0/py/selenium/webdriver/chrome/0000755000076600000240000000000012605237755021602 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/chrome/__init__.py0000644000076600000240000000142312551302002023665 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/chrome/options.py0000755000076600000240000001225112555770564023657 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 os from selenium.webdriver.common.desired_capabilities import DesiredCapabilities import base64 class Options(object): def __init__(self): self._binary_location = '' self._arguments = [] self._extension_files = [] self._extensions = [] self._experimental_options = {} self._debugger_address = None @property def binary_location(self): """ Returns the location of the binary otherwise an empty string """ return self._binary_location @binary_location.setter def binary_location(self, value): """ Allows you to set where the chromium binary lives :Args: - value: path to the Chromium binary """ self._binary_location = value @property def debugger_address(self): """ Returns the address of the remote devtools instance """ return self._debugger_address @debugger_address.setter def debugger_address(self, value): """ Allows you to set the address of the remote devtools instance that the ChromeDriver instance will try to connect to during an active wait. :Args: - value: address of remote devtools instance if any (hostname[:port]) """ self._debugger_address = value @property def arguments(self): """ Returns a list of arguments needed for the browser """ return self._arguments def add_argument(self, argument): """ Adds an argument to the list :Args: - Sets the arguments """ if argument: self._arguments.append(argument) else: raise ValueError("argument can not be null") @property def extensions(self): """ Returns a list of encoded extensions that will be loaded into chrome """ encoded_extensions = [] for ext in self._extension_files: file_ = open(ext, 'rb') # Should not use base64.encodestring() which inserts newlines every # 76 characters (per RFC 1521). Chromedriver has to remove those # unnecessary newlines before decoding, causing performance hit. encoded_extensions.append(base64.b64encode(file_.read()).decode('UTF-8')) file_.close() return encoded_extensions + self._extensions def add_extension(self, extension): """ Adds the path to the extension to a list that will be used to extract it to the ChromeDriver :Args: - extension: path to the *.crx file """ if extension: if os.path.exists(extension): self._extension_files.append(extension) else: raise IOError("Path to the extension doesn't exist") else: raise ValueError("argument can not be null") def add_encoded_extension(self, extension): """ Adds Base64 encoded string with extension data to a list that will be used to extract it to the ChromeDriver :Args: - extension: Base64 encoded string with extension data """ if extension: self._extensions.append(extension) else: raise ValueError("argument can not be null") @property def experimental_options(self): """ Returns a dictionary of experimental options for chrome. """ return self._experimental_options def add_experimental_option(self, name, value): """ Adds an experimental option which is passed to chrome. Args: name: The experimental option name. value: The option value. """ self._experimental_options[name] = value def to_capabilities(self): """ Creates a capabilities with all the options that have been set and returns a dictionary with everything """ chrome = DesiredCapabilities.CHROME.copy() chrome_options = self.experimental_options.copy() chrome_options["extensions"] = self.extensions if self.binary_location: chrome_options["binary"] = self.binary_location chrome_options["args"] = self.arguments if self.debugger_address: chrome_options["debuggerAddress"] = self.debugger_address chrome["chromeOptions"] = chrome_options return chrome selenium-2.48.0/py/selenium/webdriver/chrome/remote_connection.py0000644000076600000240000000217212562175176025670 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from selenium.webdriver.remote.remote_connection import RemoteConnection class ChromeRemoteConnection(RemoteConnection): def __init__(self, remote_server_addr, keep_alive=True): RemoteConnection.__init__(self, remote_server_addr, keep_alive) self._commands["launchApp"] = ('POST', '/session/$sessionId/chromium/launch_app') selenium-2.48.0/py/selenium/webdriver/chrome/service.py0000644000076600000240000001061012551302002023564 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 os import errno import subprocess from subprocess import PIPE 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 the ChromeDriver """ def __init__(self, executable_path, port=0, service_args=None, log_path=None, env=None): """ Creates a new instance of the Service :Args: - executable_path : Path to the ChromeDriver - port : Port the service is running on - service_args : List of args to pass to the chromedriver service - log_path : Path for the chromedriver service to log to""" self.port = port self.path = executable_path self.service_args = service_args or [] if log_path: self.service_args.append('--log-path=%s' % log_path) if self.port == 0: self.port = utils.free_port() self.env = env def start(self): """ Starts the ChromeDriver Service. :Exceptions: - WebDriverException : Raised either when it cannot find the executable, when it does not have permissions for the executable, or when it cannot connect to the service. - Possibly other Exceptions in rare circumstances (OSError, etc). """ env = self.env or os.environ try: self.process = subprocess.Popen([ self.path, "--port=%d" % self.port] + self.service_args, env=env, stdout=PIPE, stderr=PIPE) except OSError as err: docs_msg = "Please see " \ "https://sites.google.com/a/chromium.org/chromedriver/home" if err.errno == errno.ENOENT: raise WebDriverException( "'%s' executable needs to be in PATH. %s" % ( os.path.basename(self.path), docs_msg) ) elif err.errno == errno.EACCES: raise WebDriverException( "'%s' executable may have wrong permissions. %s" % ( os.path.basename(self.path), docs_msg) ) else: raise count = 0 while not utils.is_connectable(self.port): count += 1 time.sleep(1) if count == 30: raise WebDriverException("Can not connect to the '" + os.path.basename(self.path) + "'") @property def service_url(self): """ Gets the url of the ChromeDriver Service """ return "http://localhost:%d" % self.port def stop(self): """ Tells the ChromeDriver to stop and cleans up the process """ #If its dead dont worry if self.process is None: return #Tell the Server to die! try: from urllib import request as url_request except ImportError: import urllib2 as url_request url_request.urlopen("http://127.0.0.1:%d/shutdown" % self.port) count = 0 while utils.is_connectable(self.port): if count == 30: break count += 1 time.sleep(1) #Tell the Server to properly die in case try: if self.process: self.process.stdout.close() self.process.stderr.close() self.process.kill() self.process.wait() except OSError: # kill may not be available under windows environment pass selenium-2.48.0/py/selenium/webdriver/chrome/webdriver.py0000644000076600000240000000706112576065613024150 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 from selenium.webdriver.remote.command import Command from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver from selenium.common.exceptions import WebDriverException from .remote_connection import ChromeRemoteConnection from .service import Service from .options import Options class WebDriver(RemoteWebDriver): """ Controls the ChromeDriver and allows you to drive the browser. You will need to download the ChromeDriver executable from http://chromedriver.storage.googleapis.com/index.html """ def __init__(self, executable_path="chromedriver", port=0, chrome_options=None, service_args=None, desired_capabilities=None, service_log_path=None): """ Creates a new instance of the chrome driver. Starts the service and then creates new instance of chrome driver. :Args: - 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". - chrome_options: this takes an instance of ChromeOptions """ if chrome_options is None: # desired_capabilities stays as passed in if desired_capabilities is None: desired_capabilities = self.create_options().to_capabilities() else: if desired_capabilities is None: desired_capabilities = chrome_options.to_capabilities() else: desired_capabilities.update(chrome_options.to_capabilities()) self.service = Service(executable_path, port=port, service_args=service_args, log_path=service_log_path) self.service.start() try: RemoteWebDriver.__init__(self, command_executor=ChromeRemoteConnection( remote_server_addr=self.service.service_url), desired_capabilities=desired_capabilities) except: self.quit() raise self._is_remote = False def launch_app(self, id): """Launches Chrome app specified by id.""" return self.execute("launchApp", {'id': id}) def quit(self): """ Closes the browser and shuts down the ChromeDriver executable that is started when starting the ChromeDriver """ try: RemoteWebDriver.quit(self) except: # We don't care about the message because something probably has gone wrong pass finally: self.service.stop() def create_options(self): return Options() selenium-2.48.0/py/selenium/webdriver/common/0000755000076600000240000000000012605237755021615 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/common/__init__.py0000644000076600000240000000142312551302002023700 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/common/action_chains.py0000755000076600000240000002331612551302002024753 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. """ The ActionChains implementation, """ from selenium.webdriver.remote.command import Command from selenium.webdriver.common.keys import Keys class ActionChains(object): """ ActionChains are a way to automate low level interactions such as mouse movements, mouse button actions, key press, and context menu interactions. This is useful for doing more complex actions like hover over and drag and drop. Generate user actions. When you call methods for actions on the ActionChains object, the actions are stored in a queue in the ActionChains object. When you call perform(), the events are fired in the order they are queued up. ActionChains can be used in a chain pattern:: menu = driver.find_element_by_css_selector(".nav") hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1") ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform() Or actions can be queued up one by one, then performed.:: menu = driver.find_element_by_css_selector(".nav") hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1") actions = ActionChains(driver) actions.move_to_element(menu) actions.click(hidden_submenu) actions.perform() Either way, the actions are performed in the order they are called, one after another. """ def __init__(self, driver): """ Creates a new ActionChains. :Args: - driver: The WebDriver instance which performs user actions. """ self._driver = driver self._actions = [] def perform(self): """ Performs all stored actions. """ for action in self._actions: action() def click(self, on_element=None): """ Clicks an element. :Args: - on_element: The element to click. If None, clicks on current mouse position. """ if on_element: self.move_to_element(on_element) self._actions.append(lambda: self._driver.execute(Command.CLICK, {'button': 0})) return self def click_and_hold(self, on_element=None): """ Holds down the left mouse button on an element. :Args: - on_element: The element to mouse down. If None, clicks on current mouse position. """ if on_element: self.move_to_element(on_element) self._actions.append(lambda: self._driver.execute(Command.MOUSE_DOWN, {})) return self def context_click(self, on_element=None): """ Performs a context-click (right click) on an element. :Args: - on_element: The element to context-click. If None, clicks on current mouse position. """ if on_element: self.move_to_element(on_element) self._actions.append(lambda: self._driver.execute(Command.CLICK, {'button': 2})) return self def double_click(self, on_element=None): """ Double-clicks an element. :Args: - on_element: The element to double-click. If None, clicks on current mouse position. """ if on_element: self.move_to_element(on_element) self._actions.append(lambda: self._driver.execute(Command.DOUBLE_CLICK, {})) return self def drag_and_drop(self, source, target): """ Holds down the left mouse button on the source element, then moves to the target element and releases the mouse button. :Args: - source: The element to mouse down. - target: The element to mouse up. """ self.click_and_hold(source) self.release(target) return self def drag_and_drop_by_offset(self, source, xoffset, yoffset): """ Holds down the left mouse button on the source element, then moves to the target offset and releases the mouse button. :Args: - source: The element to mouse down. - xoffset: X offset to move to. - yoffset: Y offset to move to. """ self.click_and_hold(source) self.move_by_offset(xoffset, yoffset) self.release() return self def key_down(self, value, element=None): """ Sends a key press only, without releasing it. Should only be used with modifier keys (Control, Alt and Shift). :Args: - value: The modifier key to send. Values are defined in `Keys` class. - element: The element to send keys. If None, sends a key to current focused element. Example, pressing ctrl+c:: ActionChains(driver).key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform() """ if element: self.click(element) self._actions.append(lambda: self._driver.execute(Command.SEND_KEYS_TO_ACTIVE_ELEMENT, { "value": self._keys_to_typing(value) })) return self def key_up(self, value, element=None): """ Releases a modifier key. :Args: - value: The modifier key to send. Values are defined in Keys class. - element: The element to send keys. If None, sends a key to current focused element. Example, pressing ctrl+c:: ActionChains(driver).key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform() """ if element: self.click(element) self._actions.append(lambda: self._driver.execute(Command.SEND_KEYS_TO_ACTIVE_ELEMENT, { "value": self._keys_to_typing(value) })) return self def move_by_offset(self, xoffset, yoffset): """ Moving the mouse to an offset from current mouse position. :Args: - xoffset: X offset to move to, as a positive or negative integer. - yoffset: Y offset to move to, as a positive or negative integer. """ self._actions.append(lambda: self._driver.execute(Command.MOVE_TO, { 'xoffset': int(xoffset), 'yoffset': int(yoffset)})) return self def move_to_element(self, to_element): """ Moving the mouse to the middle of an element. :Args: - to_element: The WebElement to move to. """ self._actions.append(lambda: self._driver.execute(Command.MOVE_TO, {'element': to_element.id})) return self def move_to_element_with_offset(self, to_element, xoffset, yoffset): """ Move the mouse by an offset of the specified element. Offsets are relative to the top-left corner of the element. :Args: - to_element: The WebElement to move to. - xoffset: X offset to move to. - yoffset: Y offset to move to. """ self._actions.append(lambda: self._driver.execute(Command.MOVE_TO, { 'element': to_element.id, 'xoffset': int(xoffset), 'yoffset': int(yoffset)})) return self def release(self, on_element=None): """ Releasing a held mouse button on an element. :Args: - on_element: The element to mouse up. If None, releases on current mouse position. """ if on_element: self.move_to_element(on_element) self._actions.append(lambda: self._driver.execute(Command.MOUSE_UP, {})) return self def send_keys(self, *keys_to_send): """ Sends keys to current focused element. :Args: - keys_to_send: The keys to send. Modifier keys constants can be found in the 'Keys' class. """ self._actions.append(lambda: self._driver.execute(Command.SEND_KEYS_TO_ACTIVE_ELEMENT, { 'value': self._keys_to_typing(keys_to_send)})) return self def send_keys_to_element(self, element, *keys_to_send): """ Sends keys to an element. :Args: - element: The element to send keys. - keys_to_send: The keys to send. Modifier keys constants can be found in the 'Keys' class. """ self._actions.append(lambda: element.send_keys(*keys_to_send)) return self def _keys_to_typing(self, value): typing = [] for val in value: if isinstance(val, Keys): typing.append(val) elif isinstance(val, int): val = str(val) for i in range(len(val)): typing.append(val[i]) else: for i in range(len(val)): typing.append(val[i]) return typing # Context manager so ActionChains can be used in a 'with .. as' statements. def __enter__(self): return self # Return created instance of self. def __exit__(self, _type, _value, _traceback): pass # Do nothing, does not require additional cleanup. selenium-2.48.0/py/selenium/webdriver/common/alert.py0000644000076600000240000000575712552013370023276 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. """ The Alert implementation. """ from selenium.webdriver.remote.command import Command class Alert(object): """ Allows to work with alerts. Use this class to interact with alert prompts. It contains methods for dismissing, accepting, inputting, and getting text from alert prompts. Accepting / Dismissing alert prompts:: Alert(driver).accept() Alert(driver).dismiss() Inputting a value into an alert prompt: name_prompt = Alert(driver) name_prompt.send_keys("Willian Shakesphere") name_prompt.accept() Reading a the text of a prompt for verification: alert_text = Alert(driver).text self.assertEqual("Do you wish to quit?", alert_text) """ def __init__(self, driver): """ Creates a new Alert. :Args: - driver: The WebDriver instance which performs user actions. """ self.driver = driver @property def text(self): """ Gets the text of the Alert. """ return self.driver.execute(Command.GET_ALERT_TEXT)["value"] def dismiss(self): """ Dismisses the alert available. """ self.driver.execute(Command.DISMISS_ALERT) def accept(self): """ Accepts the alert available. Usage:: Alert(driver).accept() # Confirm a alert dialog. """ self.driver.execute(Command.ACCEPT_ALERT) def send_keys(self, keysToSend): """ Send Keys to the Alert. :Args: - keysToSend: The text to be sent to Alert. """ self.driver.execute(Command.SET_ALERT_VALUE, {'text': keysToSend}) def authenticate(self, username, password): """ Send the username / password to an Authenticated dialog (like with Basic HTTP Auth). Implicitly 'clicks ok' Usage:: driver.switch_to.alert.authenticate('cheese', 'secretGouda') :Args: -username: string to be set in the username section of the dialog -password: string to be set in the password section of the dialog """ self.driver.execute(Command.SET_ALERT_CREDENTIALS, {'username':username, 'password':password}) self.accept() selenium-2.48.0/py/selenium/webdriver/common/by.py0000755000076600000240000000237312551302002022563 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. """ The By implementation. """ class By(object): """ Set of supported locator strategies. """ ID = "id" XPATH = "xpath" LINK_TEXT = "link text" PARTIAL_LINK_TEXT = "partial link text" NAME = "name" TAG_NAME = "tag name" CLASS_NAME = "class name" CSS_SELECTOR = "css selector" @classmethod def is_valid(cls, by): for attr in dir(cls): if by == getattr(cls, attr): return True return False selenium-2.48.0/py/selenium/webdriver/common/desired_capabilities.py0000755000076600000240000000665312605232133026315 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. """ The Desired Capabilities implementation. """ class DesiredCapabilities(object): """ Set of default supported desired capabilities. Use this as a starting point for creating a desired capabilities object for requesting remote webdrivers for connecting to selenium server or selenium grid. Usage Example: from selenium import webdriver selenium_grid_url = "http://198.0.0.1:4444/wd/hub" # Create a desired capabilities object as a starting point. capabilities = DesiredCapabilities.FIREFOX.copy() capabilities['platform'] = "WINDOWS" capabilities['version'] = "10" # Instantiate an instance of Remote WebDriver with the desired capabilities. driver = webdriver.Remote(desired_capabilities=capabilities, command_executor=selenium_grid_url) Note: Always use '.copy()' on the DesiredCapabilities object to avoid the side effects of altering the Global class instance. """ FIREFOX = { "browserName": "firefox", "version": "", "platform": "ANY", "javascriptEnabled": True, "marionette": False, } INTERNETEXPLORER = { "browserName": "internet explorer", "version": "", "platform": "WINDOWS", "javascriptEnabled": True, } EDGE = { "browserName": "MicrosoftEdge", "version": "", "platform": "WINDOWS" } CHROME = { "browserName": "chrome", "version": "", "platform": "ANY", "javascriptEnabled": True, } OPERA = { "browserName": "opera", "version": "", "platform": "ANY", "javascriptEnabled": True, } SAFARI = { "browserName": "safari", "version": "", "platform": "ANY", "javascriptEnabled": True, } HTMLUNIT = { "browserName": "htmlunit", "version": "", "platform": "ANY", } HTMLUNITWITHJS = { "browserName": "htmlunit", "version": "firefox", "platform": "ANY", "javascriptEnabled": True, } IPHONE = { "browserName": "iPhone", "version": "", "platform": "MAC", "javascriptEnabled": True, } IPAD = { "browserName": "iPad", "version": "", "platform": "MAC", "javascriptEnabled": True, } ANDROID = { "browserName": "android", "version": "", "platform": "ANDROID", "javascriptEnabled": True, } PHANTOMJS = { "browserName":"phantomjs", "version": "", "platform": "ANY", "javascriptEnabled": True, } selenium-2.48.0/py/selenium/webdriver/common/html5/0000755000076600000240000000000012605237755022646 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/common/html5/__init__.py0000644000076600000240000000142312551302002024731 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/common/html5/application_cache.py0000644000076600000240000000265112551302002026624 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. """ The ApplicationCache implementaion. """ from selenium.webdriver.remote.command import Command class ApplicationCache(object): """ """ UNCACHED = 0 IDLE = 1 CHECKING = 2 DOWNLOADING = 3 UPDATE_READY = 4 OBSOLETE = 5 def __init__(self, driver): """ Creates a new Aplication Cache. :Args: - driver: The WebDriver instance which performs user actions. """ self.driver = driver @property def status(self): """ Returns a current status of application cache. """ return self.driver.execute(Command.GET_APP_CACHE_STATUS)['value'] selenium-2.48.0/py/selenium/webdriver/common/keys.py0000644000076600000240000000527412551302002023124 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. """ The Keys implementation. """ from __future__ import unicode_literals class Keys(object): """ Set of special keys codes. """ NULL = '\ue000' CANCEL = '\ue001' # ^break HELP = '\ue002' BACKSPACE = '\ue003' BACK_SPACE = BACKSPACE TAB = '\ue004' CLEAR = '\ue005' RETURN = '\ue006' ENTER = '\ue007' SHIFT = '\ue008' LEFT_SHIFT = SHIFT CONTROL = '\ue009' LEFT_CONTROL = CONTROL ALT = '\ue00a' LEFT_ALT = ALT PAUSE = '\ue00b' ESCAPE = '\ue00c' SPACE = '\ue00d' PAGE_UP = '\ue00e' PAGE_DOWN = '\ue00f' END = '\ue010' HOME = '\ue011' LEFT = '\ue012' ARROW_LEFT = LEFT UP = '\ue013' ARROW_UP = UP RIGHT = '\ue014' ARROW_RIGHT = RIGHT DOWN = '\ue015' ARROW_DOWN = DOWN INSERT = '\ue016' DELETE = '\ue017' SEMICOLON = '\ue018' EQUALS = '\ue019' NUMPAD0 = '\ue01a' # number pad keys NUMPAD1 = '\ue01b' NUMPAD2 = '\ue01c' NUMPAD3 = '\ue01d' NUMPAD4 = '\ue01e' NUMPAD5 = '\ue01f' NUMPAD6 = '\ue020' NUMPAD7 = '\ue021' NUMPAD8 = '\ue022' NUMPAD9 = '\ue023' MULTIPLY = '\ue024' ADD = '\ue025' SEPARATOR = '\ue026' SUBTRACT = '\ue027' DECIMAL = '\ue028' DIVIDE = '\ue029' F1 = '\ue031' # function keys F2 = '\ue032' F3 = '\ue033' F4 = '\ue034' F5 = '\ue035' F6 = '\ue036' F7 = '\ue037' F8 = '\ue038' F9 = '\ue039' F10 = '\ue03a' F11 = '\ue03b' F12 = '\ue03c' META = '\ue03d' COMMAND = '\ue03d' selenium-2.48.0/py/selenium/webdriver/common/proxy.py0000755000076600000240000002416012551302002023330 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. """ The Proxy implementation. """ class ProxyTypeFactory: """ Factory for proxy types. """ @staticmethod def make(ff_value, string): return {'ff_value': ff_value, 'string': string} class ProxyType: """ Set of possible types of proxy. Each proxy type has 2 properties: 'ff_value' is value of Firefox profile preference, 'string' is id of proxy type. """ DIRECT = ProxyTypeFactory.make(0, 'DIRECT') # Direct connection, no proxy (default on Windows). MANUAL = ProxyTypeFactory.make(1, 'MANUAL') # Manual proxy settings (e.g., for httpProxy). PAC = ProxyTypeFactory.make(2, 'PAC') # Proxy autoconfiguration from URL. RESERVED_1 = ProxyTypeFactory.make(3, 'RESERVED1') # Never used. AUTODETECT = ProxyTypeFactory.make(4, 'AUTODETECT') # Proxy autodetection (presumably with WPAD). SYSTEM = ProxyTypeFactory.make(5, 'SYSTEM') # Use system settings (default on Linux). UNSPECIFIED = ProxyTypeFactory.make(6, 'UNSPECIFIED') # Not initialized (for internal use). @classmethod def load(cls, value): if isinstance(value, dict) and 'string' in value: value = value['string'] value = str(value).upper() for attr in dir(cls): attr_value = getattr(cls, attr) if isinstance(attr_value, dict) and 'string' in attr_value and \ attr_value['string'] is not None and attr_value['string'] == value: return attr_value raise Exception("No proxy type is found for %s" % (value)) class Proxy(object): """ Proxy contains information about proxy type and necessary proxy settings. """ proxyType = ProxyType.UNSPECIFIED autodetect = False ftpProxy = '' httpProxy = '' noProxy = '' proxyAutoconfigUrl = '' sslProxy = '' socksProxy = '' socksUsername = '' socksPassword = '' def __init__(self, raw=None): """ Creates a new Proxy. :Args: - raw: raw proxy data. If None, default class values are used. """ if raw is not None: if 'proxyType' in raw and raw['proxyType'] is not None: self.proxy_type = ProxyType.load(raw['proxyType']) if 'ftpProxy' in raw and raw['ftpProxy'] is not None: self.ftp_proxy = raw['ftpProxy'] if 'httpProxy' in raw and raw['httpProxy'] is not None: self.http_proxy = raw['httpProxy'] if 'noProxy' in raw and raw['noProxy'] is not None: self.no_proxy = raw['noProxy'] if 'proxyAutoconfigUrl' in raw and raw['proxyAutoconfigUrl'] is not None: self.proxy_autoconfig_url = raw['proxyAutoconfigUrl'] if 'sslProxy' in raw and raw['sslProxy'] is not None: self.sslProxy = raw['sslProxy'] if 'autodetect' in raw and raw['autodetect'] is not None: self.auto_detect = raw['autodetect'] if 'socksProxy' in raw and raw['socksProxy'] is not None: self.socksProxy = raw['socksProxy'] if 'socksUsername' in raw and raw['socksUsername'] is not None: self.socksUsername = raw['socksUsername'] if 'socksPassword' in raw and raw['socksPassword'] is not None: self.socksPassword = raw['socksPassword'] @property def proxy_type(self): """ Returns proxy type as `ProxyType`. """ return self.proxyType @proxy_type.setter def proxy_type(self, value): """ Sets proxy type. :Args: - value: The proxy type. """ self._verify_proxy_type_compatibility(value) self.proxyType = value @property def auto_detect(self): """ Returns autodetect setting. """ return self.autodetect @auto_detect.setter def auto_detect(self, value): """ Sets autodetect setting. :Args: - value: The autodetect value. """ if isinstance(value, bool): if self.autodetect is not value: self._verify_proxy_type_compatibility(ProxyType.AUTODETECT) self.proxyType = ProxyType.AUTODETECT self.autodetect = value else: raise ValueError("Autodetect proxy value needs to be a boolean") @property def ftp_proxy(self): """ Returns ftp proxy setting. """ return self.ftpProxy @ftp_proxy.setter def ftp_proxy(self, value): """ Sets ftp proxy setting. :Args: - value: The ftp proxy value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.ftpProxy = value @property def http_proxy(self): """ Returns http proxy setting. """ return self.httpProxy @http_proxy.setter def http_proxy(self, value): """ Sets http proxy setting. :Args: - value: The http proxy value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.httpProxy = value @property def no_proxy(self): """ Returns noproxy setting. """ return self.noProxy @no_proxy.setter def no_proxy(self, value): """ Sets noproxy setting. :Args: - value: The noproxy value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.noProxy = value @property def proxy_autoconfig_url(self): """ Returns proxy autoconfig url setting. """ return self.proxyAutoconfigUrl @proxy_autoconfig_url.setter def proxy_autoconfig_url(self, value): """ Sets proxy autoconfig url setting. :Args: - value: The proxy autoconfig url value. """ self._verify_proxy_type_compatibility(ProxyType.PAC) self.proxyType = ProxyType.PAC self.proxyAutoconfigUrl = value @property def ssl_proxy(self): """ Returns https proxy setting. """ return self.sslProxy @ssl_proxy.setter def ssl_proxy(self, value): """ Sets https proxy setting. :Args: - value: The https proxy value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.sslProxy = value @property def socks_proxy(self): """ Returns socks proxy setting. """ return self.socksProxy @socks_proxy.setter def socks_proxy(self, value): """ Sets socks proxy setting. :Args: - value: The socks proxy value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.socksProxy = value @property def socks_username(self): """ Returns socks proxy username setting. """ return self.socksUsername @socks_username.setter def socks_username(self, value): """ Sets socks proxy username setting. :Args: - value: The socks proxy username value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.socksUsername = value @property def socks_password(self): """ Returns socks proxy password setting. """ return self.socksPassword @socks_password.setter def socks_password(self, value): """ Sets socks proxy password setting. :Args: - value: The socks proxy password value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.socksPassword = value def _verify_proxy_type_compatibility(self, compatibleProxy): if self.proxyType != ProxyType.UNSPECIFIED and self.proxyType != compatibleProxy: raise Exception(" Specified proxy type (%s) not compatible with current setting (%s)" % \ (compatibleProxy, self.proxyType)) def add_to_capabilities(self, capabilities): """ Adds proxy information as capability in specified capabilities. :Args: - capabilities: The capabilities to which proxy will be added. """ proxy_caps = {} proxy_caps['proxyType'] = self.proxyType['string'] if self.autodetect: proxy_caps['autodetect'] = self.autodetect if self.ftpProxy: proxy_caps['ftpProxy'] = self.ftpProxy if self.httpProxy: proxy_caps['httpProxy'] = self.httpProxy if self.proxyAutoconfigUrl: proxy_caps['proxyAutoconfigUrl'] = self.proxyAutoconfigUrl if self.sslProxy: proxy_caps['sslProxy'] = self.sslProxy if self.noProxy: proxy_caps['noProxy'] = self.noProxy if self.socksProxy: proxy_caps['socksProxy'] = self.socksProxy if self.socksUsername: proxy_caps['socksUsername'] = self.socksUsername if self.socksPassword: proxy_caps['socksPassword'] = self.socksPassword capabilities['proxy'] = proxy_caps selenium-2.48.0/py/selenium/webdriver/common/touch_actions.py0000755000076600000240000001351612551302002025014 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. """ The Touch Actions implementation """ from selenium.webdriver.remote.command import Command class TouchActions(object): """ Generate touch actions. Works like ActionChains; actions are stored in the TouchActions object and are fired with perform(). """ def __init__(self, driver): """ Creates a new TouchActions object. :Args: - driver: The WebDriver instance which performs user actions. It should be with touchscreen enabled. """ self._driver = driver self._actions = [] def perform(self): """ Performs all stored actions. """ for action in self._actions: action() def tap(self, on_element): """ Taps on a given element. :Args: - on_element: The element to tap. """ self._actions.append(lambda: self._driver.execute(Command.SINGLE_TAP, {'element': on_element.id})) return self def double_tap(self, on_element): """ Double taps on a given element. :Args: - on_element: The element to tap. """ self._actions.append(lambda: self._driver.execute(Command.DOUBLE_TAP, {'element': on_element.id})) return self def tap_and_hold(self, xcoord, ycoord): """ Touch down at given coordinates. :Args: - xcoord: X Coordinate to touch down. - ycoord: Y Coordinate to touch down. """ self._actions.append(lambda: self._driver.execute(Command.TOUCH_DOWN, { 'x': int(xcoord), 'y': int(ycoord)})) return self def move(self, xcoord, ycoord): """ Move held tap to specified location. :Args: - xcoord: X Coordinate to move. - ycoord: Y Coordinate to move. """ self._actions.append(lambda: self._driver.execute(Command.TOUCH_MOVE, { 'x': int(xcoord), 'y': int(ycoord)})) return self def release(self, xcoord, ycoord): """ Release previously issued tap 'and hold' command at specified location. :Args: - xcoord: X Coordinate to release. - ycoord: Y Coordinate to release. """ self._actions.append(lambda: self._driver.execute(Command.TOUCH_UP, { 'x': int(xcoord), 'y': int(ycoord)})) return self def scroll(self, xoffset, yoffset): """ Touch and scroll, moving by xoffset and yoffset. :Args: - xoffset: X offset to scroll to. - yoffset: Y offset to scroll to. """ self._actions.append(lambda: self._driver.execute(Command.TOUCH_SCROLL, { 'xoffset': int(xoffset), 'yoffset': int(yoffset)})) return self def scroll_from_element(self, on_element, xoffset, yoffset): """ Touch and scroll starting at on_element, moving by xoffset and yoffset. :Args: - on_element: The element where scroll starts. - xoffset: X offset to scroll to. - yoffset: Y offset to scroll to. """ self._actions.append(lambda: self._driver.execute(Command.TOUCH_SCROLL, { 'element': on_element.id, 'xoffset': int(xoffset), 'yoffset': int(yoffset)})) return self def long_press(self, on_element): """ Long press on an element. :Args: - on_element: The element to long press. """ self._actions.append(lambda: self._driver.execute(Command.LONG_PRESS, {'element': on_element.id})) return self def flick(self, xspeed, yspeed): """ Flicks, starting anywhere on the screen. :Args: - xspeed: The X speed in pixels per second. - yspeed: The Y speed in pixels per second. """ self._actions.append(lambda: self._driver.execute(Command.FLICK, { 'xspeed': int(xspeed), 'yspeed': int(yspeed)})) return self def flick_element(self, on_element, xoffset, yoffset, speed): """ Flick starting at on_element, and moving by the xoffset and yoffset with specified speed. :Args: - on_element: Flick will start at center of element. - xoffset: X offset to flick to. - yoffset: Y offset to flick to. - speed: Pixels per second to flick. """ self._actions.append(lambda: self._driver.execute(Command.FLICK, { 'element': on_element.id, 'xoffset': int(xoffset), 'yoffset': int(yoffset), 'speed': int(speed)})) return self # Context manager so TouchActions can be used in a 'with .. as' statements. def __enter__(self): return self # Return created instance of self. def __exit__(self, _type, _value, _traceback): pass # Do nothing, does not require additional cleanup.selenium-2.48.0/py/selenium/webdriver/common/utils.py0000644000076600000240000000405212552013370023312 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. """ The Utils methods. """ import socket def free_port(): """ Determines a free port using sockets. """ free_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) free_socket.bind(('0.0.0.0', 0)) free_socket.listen(5) port = free_socket.getsockname()[1] free_socket.close() return port def is_connectable(port): """ Tries to connect to the server at port to see if it is running. :Args: - port: The port to connect. """ try: socket_ = socket.socket(socket.AF_INET, socket.SOCK_STREAM) socket_.settimeout(1) socket_.connect(("127.0.0.1", port)) result = True except socket.error: result = False finally: socket_.close() return result def is_url_connectable(port): """ Tries to connect to the HTTP server at /status path and specified port to see if it responds successfully. :Args: - port: The port to connect. """ try: from urllib import request as url_request except ImportError: import urllib2 as url_request try: res = url_request.urlopen("http://127.0.0.1:%s/status" % port) if res.getcode() == 200: return True else: return False except: return False selenium-2.48.0/py/selenium/webdriver/edge/0000755000076600000240000000000012605237755021231 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/edge/__init__.py0000644000076600000240000000142312556002346023331 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/edge/options.py0000644000076600000240000000312412556002346023265 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from selenium.webdriver.common.desired_capabilities import DesiredCapabilities class Options(object): def __init__(self): self._page_load_strategy = "normal" @property def page_load_strategy(self): return self._page_load_strategy @page_load_strategy.setter def page_load_strategy(self, value): if value not in ['normal', 'eager', 'none']: raise ValueError("Page Load Strategy should be 'normal', 'eager' or 'none'.") self._page_load_strategy = value def to_capabilities(self): """ Creates a capabilities with all the options that have been set and returns a dictionary with everything """ edge = DesiredCapabilities.EDGE.copy() edge['pageLoadStrategy'] = self._page_load_strategy return edge selenium-2.48.0/py/selenium/webdriver/edge/service.py0000644000076600000240000000632012576065613023243 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 from subprocess import PIPE 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 the EdgeDriver """ def __init__(self, executable_path, port=0): """ Creates a new instance of the Service :Args: - executable_path : Path to the EdgeDriver - port : Port the service is running on """ self.path = executable_path self.port = port if self.port == 0: self.port = utils.free_port() def start(self): """ Starts the EdgeDriver Service. :Exceptions: - WebDriverException : Raised either when it can't start the service or when it can't connect to the service """ try: cmd = [self.path, "--port=%d" % self.port] self.process = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE) except TypeError: raise except: raise WebDriverException( "The EdgeDriver executable needs to be available in the path. " "Please download from http://go.microsoft.com/fwlink/?LinkId=619687 ") count = 0 while not utils.is_connectable(self.port): count += 1 time.sleep(1) if count == 30: raise WebDriverException("Can not connect to the EdgeDriver") def stop(self): """ Tells the EdgeDriver to stop and cleans up the process """ #If its dead dont worry if self.process is None: return #Tell the Server to die! try: from urllib import request as url_request except ImportError: import urllib2 as url_request url_request.urlopen("http://127.0.0.1:%d/shutdown" % self.port) count = 0 while utils.is_connectable(self.port): if count == 30: break count += 1 time.sleep(1) #Tell the Server to properly die in case try: if self.process: self.process.stdout.close() self.process.stderr.close() self.process.kill() self.process.wait() except WindowsError: # kill may not be available under windows environment pass selenium-2.48.0/py/selenium/webdriver/edge/webdriver.py0000644000076600000240000000354012576065613023575 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from selenium.webdriver.common import utils from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver from selenium.webdriver.remote.remote_connection import RemoteConnection from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from .service import Service class WebDriver(RemoteWebDriver): def __init__(self, executable_path='MicrosoftWebDriver.exe', capabilities=None, port=0): self.port = port if self.port == 0: self.port = utils.free_port() self.edge_service = Service(executable_path, port=self.port) self.edge_service.start() if capabilities is None: capabilities = DesiredCapabilities.EDGE RemoteWebDriver.__init__( self, command_executor=RemoteConnection('http://localhost:%d' % self.port, resolve_ip=False), desired_capabilities=capabilities) self._is_remote = False def quit(self): RemoteWebDriver.quit(self) self.edge_service.stop() selenium-2.48.0/py/selenium/webdriver/firefox/0000755000076600000240000000000012605237755021767 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/firefox/__init__.py0000644000076600000240000000142312551302002024052 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/firefox/amd64/0000755000076600000240000000000012605237755022702 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/firefox/extension_connection.py0000644000076600000240000000543612551302002026556 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 logging import time from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.common import utils from selenium.webdriver.remote.command import Command from selenium.webdriver.remote.remote_connection import RemoteConnection from selenium.webdriver.firefox.firefox_binary import FirefoxBinary LOGGER = logging.getLogger(__name__) PORT = 0 # HOST = None _URL = "" class ExtensionConnection(RemoteConnection): def __init__(self, host, firefox_profile, firefox_binary=None, timeout=30): self.profile = firefox_profile self.binary = firefox_binary HOST = host if self.binary is None: self.binary = FirefoxBinary() if HOST is None: HOST = "127.0.0.1" PORT = utils.free_port() self.profile.port = PORT self.profile.update_preferences() self.profile.add_extension() self.binary.launch_browser(self.profile) _URL = "http://%s:%d/hub" % (HOST, PORT) RemoteConnection.__init__( self, _URL, keep_alive=True) def quit(self, sessionId=None): self.execute(Command.QUIT, {'sessionId':sessionId}) while self.is_connectable(): LOGGER.info("waiting to quit") time.sleep(1) def connect(self): """Connects to the extension and retrieves the session id.""" return self.execute(Command.NEW_SESSION, {'desiredCapabilities': DesiredCapabilities.FIREFOX}) @classmethod def connect_and_quit(self): """Connects to an running browser and quit immediately.""" self._request('%s/extensions/firefox/quit' % _URL) @classmethod def is_connectable(self): """Trys to connect to the extension but do not retrieve context.""" utils.is_connectable(self.profile.port) class ExtensionConnectionError(Exception): """An internal error occurred int the extension. Might be caused by bad input or bugs in webdriver """ pass selenium-2.48.0/py/selenium/webdriver/firefox/firefox_binary.py0000644000076600000240000002003612572134514025340 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 os import platform from subprocess import Popen, STDOUT from selenium.common.exceptions import WebDriverException from selenium.webdriver.common import utils import time class FirefoxBinary(object): NO_FOCUS_LIBRARY_NAME = "x_ignore_nofocus.so" def __init__(self, firefox_path=None, log_file=None): """ Creates a new instance of Firefox binary. :Args: - firefox_path - Path to the Firefox executable. By default, it will be detected from the standard locations. - log_file - A file object to redirect the firefox process output to. It can be sys.stdout. Please note that with parallel run the output won't be synchronous. By default, it will be redirected to /dev/null. """ self._start_cmd = firefox_path # We used to default to subprocess.PIPE instead of /dev/null, but after # a while the pipe would fill up and Firefox would freeze. self._log_file = log_file or open(os.devnull, "wb") self.command_line = None if self._start_cmd is None: self._start_cmd = self._get_firefox_start_cmd() if not self._start_cmd.strip(): raise Exception("Failed to find firefox binary. You can set it by specifying the path to 'firefox_binary':\n\nfrom selenium.webdriver.firefox.firefox_binary import FirefoxBinary\n\n" + "binary = FirefoxBinary('/path/to/binary')\ndriver = webdriver.Firefox(firefox_binary=binary)") # Rather than modifying the environment of the calling Python process # copy it and modify as needed. self._firefox_env = os.environ.copy() self._firefox_env["MOZ_CRASHREPORTER_DISABLE"] = "1" self._firefox_env["MOZ_NO_REMOTE"] = "1" self._firefox_env["NO_EM_RESTART"] = "1" def add_command_line_options(self, *args): self.command_line = args def launch_browser(self, profile): """Launches the browser for the given profile name. It is assumed the profile already exists. """ self.profile = profile self._start_from_profile_path(self.profile.path) self._wait_until_connectable() def kill(self): """Kill the browser. This is useful when the browser is stuck. """ if self.process: self.process.kill() self.process.wait() def _start_from_profile_path(self, path): self._firefox_env["XRE_PROFILE_PATH"] = path if platform.system().lower() == 'linux': self._modify_link_library_path() command = [self._start_cmd, "-foreground"] if self.command_line is not None: for cli in self.command_line: command.append(cli) self.process = Popen( command, stdout=self._log_file, stderr=STDOUT, env=self._firefox_env) def _wait_until_connectable(self): """Blocks until the extension is connectable in the firefox.""" count = 0 while not utils.is_connectable(self.profile.port): if self.process.poll() is not None: # Browser has exited raise WebDriverException("The browser appears to have exited " "before we could connect. If you specified a log_file in " "the FirefoxBinary constructor, check it for details.") if count == 30: self.kill() raise WebDriverException("Can't load the profile. Profile " "Dir: %s If you specified a log_file in the " "FirefoxBinary constructor, check it for details.") count += 1 time.sleep(1) return True def _find_exe_in_registry(self): try: from _winreg import OpenKey, QueryValue, HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER except ImportError: from winreg import OpenKey, QueryValue, HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER import shlex keys = ( r"SOFTWARE\Classes\FirefoxHTML\shell\open\command", r"SOFTWARE\Classes\Applications\firefox.exe\shell\open\command" ) command = "" for path in keys: try: key = OpenKey(HKEY_LOCAL_MACHINE, path) command = QueryValue(key, "") break except OSError: try: key = OpenKey(HKEY_CURRENT_USER, path) command = QueryValue(key, "") break except OSError: pass else: return "" if not command: return "" return shlex.split(command)[0] def _get_firefox_start_cmd(self): """Return the command to start firefox.""" start_cmd = "" if platform.system() == "Darwin": start_cmd = ("/Applications/Firefox.app/Contents/MacOS/firefox-bin") elif platform.system() == "Windows": start_cmd = (self._find_exe_in_registry() or self._default_windows_location()) elif platform.system() == 'Java' and os._name == 'nt': start_cmd = self._default_windows_location() else: for ffname in ["firefox", "iceweasel"]: start_cmd = self.which(ffname) if start_cmd is not None: break else: # couldn't find firefox on the system path raise RuntimeError("Could not find firefox in your system PATH." + " Please specify the firefox binary location or install firefox") return start_cmd def _default_windows_location(self): program_files = [os.getenv("PROGRAMFILES", r"C:\Program Files"), os.getenv("PROGRAMFILES(X86)", r"C:\Program Files (x86)")] for path in program_files: binary_path = os.path.join(path, r"Mozilla Firefox\firefox.exe") if os.access(binary_path, os.X_OK): return binary_path return "" def _modify_link_library_path(self): existing_ld_lib_path = os.environ.get('LD_LIBRARY_PATH', '') new_ld_lib_path = self._extract_and_check( self.profile, self.NO_FOCUS_LIBRARY_NAME, "x86", "amd64") new_ld_lib_path += existing_ld_lib_path self._firefox_env["LD_LIBRARY_PATH"] = new_ld_lib_path self._firefox_env['LD_PRELOAD'] = self.NO_FOCUS_LIBRARY_NAME def _extract_and_check(self, profile, no_focus_so_name, x86, amd64): paths = [x86, amd64] built_path = "" for path in paths: library_path = os.path.join(profile.path, path) if not os.path.exists(library_path): os.makedirs(library_path) import shutil shutil.copy(os.path.join(os.path.dirname(__file__), path, self.NO_FOCUS_LIBRARY_NAME), library_path) built_path += library_path + ":" return built_path def which(self, fname): """Returns the fully qualified path by searching Path of the given name""" for pe in os.environ['PATH'].split(os.pathsep): checkname = os.path.join(pe, fname) if os.access(checkname, os.X_OK) and not os.path.isdir(checkname): return checkname return None selenium-2.48.0/py/selenium/webdriver/firefox/firefox_profile.py0000644000076600000240000003451512551302002025505 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from __future__ import with_statement import base64 import copy import json import os import re import shutil import sys import tempfile import zipfile try: from cStringIO import StringIO as BytesIO except ImportError: from io import BytesIO from xml.dom import minidom from selenium.webdriver.common.proxy import ProxyType from selenium.common.exceptions import WebDriverException WEBDRIVER_EXT = "webdriver.xpi" WEBDRIVER_PREFERENCES = "webdriver_prefs.json" EXTENSION_NAME = "fxdriver@googlecode.com" class AddonFormatError(Exception): """Exception for not well-formed add-on manifest files""" class FirefoxProfile(object): ANONYMOUS_PROFILE_NAME = "WEBDRIVER_ANONYMOUS_PROFILE" DEFAULT_PREFERENCES = None def __init__(self, profile_directory=None): """ Initialises a new instance of a Firefox Profile :args: - profile_directory: Directory of profile that you want to use. This defaults to None and will create a new directory when object is created. """ if not FirefoxProfile.DEFAULT_PREFERENCES: with open(os.path.join(os.path.dirname(__file__), WEBDRIVER_PREFERENCES)) as default_prefs: FirefoxProfile.DEFAULT_PREFERENCES = json.load(default_prefs) self.default_preferences = copy.deepcopy( FirefoxProfile.DEFAULT_PREFERENCES['mutable']) self.native_events_enabled = True self.profile_dir = profile_directory self.tempfolder = None if self.profile_dir is None: self.profile_dir = self._create_tempfolder() else: self.tempfolder = tempfile.mkdtemp() newprof = os.path.join(self.tempfolder, "webdriver-py-profilecopy") shutil.copytree(self.profile_dir, newprof, ignore=shutil.ignore_patterns("parent.lock", "lock", ".parentlock")) self.profile_dir = newprof self._read_existing_userjs(os.path.join(self.profile_dir, "user.js")) self.extensionsDir = os.path.join(self.profile_dir, "extensions") self.userPrefs = os.path.join(self.profile_dir, "user.js") #Public Methods def set_preference(self, key, value): """ sets the preference that we want in the profile. """ self.default_preferences[key] = value def add_extension(self, extension=WEBDRIVER_EXT): self._install_extension(extension) def update_preferences(self): for key, value in FirefoxProfile.DEFAULT_PREFERENCES['frozen'].items(): self.default_preferences[key] = value self._write_user_prefs(self.default_preferences) #Properties @property def path(self): """ Gets the profile directory that is currently being used """ return self.profile_dir @property def port(self): """ Gets the port that WebDriver is working on """ return self._port @port.setter def port(self, port): """ Sets the port that WebDriver will be running on """ if not isinstance(port, int): raise WebDriverException("Port needs to be an integer") try: port = int(port) if port < 1 or port > 65535: raise WebDriverException("Port number must be in the range 1..65535") except (ValueError, TypeError) as e: raise WebDriverException("Port needs to be an integer") self._port = port self.set_preference("webdriver_firefox_port", self._port) @property def accept_untrusted_certs(self): return self.default_preferences["webdriver_accept_untrusted_certs"] @accept_untrusted_certs.setter def accept_untrusted_certs(self, value): if value not in [True, False]: raise WebDriverException("Please pass in a Boolean to this call") self.set_preference("webdriver_accept_untrusted_certs", value) @property def assume_untrusted_cert_issuer(self): return self.default_preferences["webdriver_assume_untrusted_issuer"] @assume_untrusted_cert_issuer.setter def assume_untrusted_cert_issuer(self, value): if value not in [True, False]: raise WebDriverException("Please pass in a Boolean to this call") self.set_preference("webdriver_assume_untrusted_issuer", value) @property def native_events_enabled(self): return self.default_preferences['webdriver_enable_native_events'] @native_events_enabled.setter def native_events_enabled(self, value): if value not in [True, False]: raise WebDriverException("Please pass in a Boolean to this call") self.set_preference("webdriver_enable_native_events", value) @property def encoded(self): """ A zipped, base64 encoded string of profile directory for use with remote WebDriver JSON wire protocol """ fp = BytesIO() zipped = zipfile.ZipFile(fp, 'w', zipfile.ZIP_DEFLATED) path_root = len(self.path) + 1 # account for trailing slash for base, dirs, files in os.walk(self.path): for fyle in files: filename = os.path.join(base, fyle) zipped.write(filename, filename[path_root:]) zipped.close() return base64.b64encode(fp.getvalue()).decode('UTF-8') def set_proxy(self, proxy): import warnings warnings.warn( "This method has been deprecated. Please pass in the proxy object to the Driver Object", DeprecationWarning) if proxy is None: raise ValueError("proxy can not be None") if proxy.proxy_type is ProxyType.UNSPECIFIED: return self.set_preference("network.proxy.type", proxy.proxy_type['ff_value']) if proxy.proxy_type is ProxyType.MANUAL: self.set_preference("network.proxy.no_proxies_on", proxy.no_proxy) self._set_manual_proxy_preference("ftp", proxy.ftp_proxy) self._set_manual_proxy_preference("http", proxy.http_proxy) self._set_manual_proxy_preference("ssl", proxy.ssl_proxy) self._set_manual_proxy_preference("socks", proxy.socks_proxy) elif proxy.proxy_type is ProxyType.PAC: self.set_preference("network.proxy.autoconfig_url", proxy.proxy_autoconfig_url) def _set_manual_proxy_preference(self, key, setting): if setting is None or setting is '': return host_details = setting.split(":") self.set_preference("network.proxy.%s" % key, host_details[0]) if len(host_details) > 1: self.set_preference("network.proxy.%s_port" % key, int(host_details[1])) def _create_tempfolder(self): """ Creates a temp folder to store User.js and the extension """ return tempfile.mkdtemp() def _write_user_prefs(self, user_prefs): """ writes the current user prefs dictionary to disk """ with open(self.userPrefs, "w") as f: for key, value in user_prefs.items(): f.write('user_pref("%s", %s);\n' % (key, json.dumps(value))) def _read_existing_userjs(self, userjs): import warnings PREF_RE = re.compile(r'user_pref\("(.*)",\s(.*)\)') try: with open(userjs) as f: for usr in f: matches = re.search(PREF_RE, usr) try: self.default_preferences[matches.group(1)] = json.loads(matches.group(2)) except: warnings.warn("(skipping) failed to json.loads existing preference: " + matches.group(1) + matches.group(2)) except: # The profile given hasn't had any changes made, i.e no users.js pass def _install_extension(self, addon, unpack=True): """ Installs addon from a filepath, url or directory of addons in the profile. - path: url, path to .xpi, or directory of addons - unpack: whether to unpack unless specified otherwise in the install.rdf """ if addon == WEBDRIVER_EXT: addon = os.path.join(os.path.dirname(__file__), WEBDRIVER_EXT) tmpdir = None xpifile = None if addon.endswith('.xpi'): tmpdir = tempfile.mkdtemp(suffix='.' + os.path.split(addon)[-1]) compressed_file = zipfile.ZipFile(addon, 'r') for name in compressed_file.namelist(): if name.endswith('/'): if not os.path.isdir(os.path.join(tmpdir, name)): os.makedirs(os.path.join(tmpdir, name)) else: if not os.path.isdir(os.path.dirname(os.path.join(tmpdir, name))): os.makedirs(os.path.dirname(os.path.join(tmpdir, name))) data = compressed_file.read(name) with open(os.path.join(tmpdir, name), 'wb') as f: f.write(data) xpifile = addon addon = tmpdir # determine the addon id addon_details = self._addon_details(addon) addon_id = addon_details.get('id') assert addon_id, 'The addon id could not be found: %s' % addon # copy the addon to the profile extensions_path = os.path.join(self.profile_dir, 'extensions') addon_path = os.path.join(extensions_path, addon_id) if not unpack and not addon_details['unpack'] and xpifile: if not os.path.exists(extensions_path): os.makedirs(extensions_path) shutil.copy(xpifile, addon_path + '.xpi') else: if not os.path.exists(addon_path): shutil.copytree(addon, addon_path, symlinks=True) # remove the temporary directory, if any if tmpdir: shutil.rmtree(tmpdir) def _addon_details(self, addon_path): """ Returns a dictionary of details about the addon. :param addon_path: path to the add-on directory or XPI Returns:: {'id': u'rainbow@colors.org', # id of the addon 'version': u'1.4', # version of the addon 'name': u'Rainbow', # name of the addon 'unpack': False } # whether to unpack the addon """ details = { 'id': None, 'unpack': False, 'name': None, 'version': None } def get_namespace_id(doc, url): attributes = doc.documentElement.attributes namespace = "" for i in range(attributes.length): if attributes.item(i).value == url: if ":" in attributes.item(i).name: # If the namespace is not the default one remove 'xlmns:' namespace = attributes.item(i).name.split(':')[1] + ":" break return namespace def get_text(element): """Retrieve the text value of a given node""" rc = [] for node in element.childNodes: if node.nodeType == node.TEXT_NODE: rc.append(node.data) return ''.join(rc).strip() if not os.path.exists(addon_path): raise IOError('Add-on path does not exist: %s' % addon_path) try: if zipfile.is_zipfile(addon_path): # Bug 944361 - We cannot use 'with' together with zipFile because # it will cause an exception thrown in Python 2.6. try: compressed_file = zipfile.ZipFile(addon_path, 'r') manifest = compressed_file.read('install.rdf') finally: compressed_file.close() elif os.path.isdir(addon_path): with open(os.path.join(addon_path, 'install.rdf'), 'r') as f: manifest = f.read() else: raise IOError('Add-on path is neither an XPI nor a directory: %s' % addon_path) except (IOError, KeyError) as e: raise AddonFormatError(str(e), sys.exc_info()[2]) try: doc = minidom.parseString(manifest) # Get the namespaces abbreviations em = get_namespace_id(doc, 'http://www.mozilla.org/2004/em-rdf#') rdf = get_namespace_id(doc, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#') description = doc.getElementsByTagName(rdf + 'Description').item(0) if description is None: description = doc.getElementsByTagName('Description').item(0) for node in description.childNodes: # Remove the namespace prefix from the tag for comparison entry = node.nodeName.replace(em, "") if entry in details.keys(): details.update({entry: get_text(node)}) if details.get('id') is None: for i in range(description.attributes.length): attribute = description.attributes.item(i) if attribute.name == em + 'id': details.update({'id': attribute.value}) except Exception as e: raise AddonFormatError(str(e), sys.exc_info()[2]) # turn unpack into a true/false value if isinstance(details['unpack'], str): details['unpack'] = details['unpack'].lower() == 'true' # If no ID is set, the add-on is invalid if details.get('id') is None: raise AddonFormatError('Add-on id could not be found.') return details selenium-2.48.0/py/selenium/webdriver/firefox/service.py0000644000076600000240000000726612567657104024015 0ustar dburnsstaff00000000000000#!/usr/bin/python # # Copyright 2011 Webdriver_name committers # Copyright 2011 Google Inc. # # 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 os import subprocess from subprocess import PIPE 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 the GeckoDriver """ def __init__(self, executable_path, firefox_binary=None, port=0, service_args=None, log_path=None, env=None): """ Creates a new instance of the Service :Args: - executable_path : Path to the GeckoDriver - port : Port the service is running on - service_args : List of args to pass to the Geckodriver service - log_path : Path for the GeckoDriver service to log to""" self.port = port self.path = executable_path self.firefox_binary = firefox_binary self.service_args = service_args or [] if self.port == 0: self.port = utils.free_port() self.env = env def start(self): """ Starts the GeckoDriver "wires" Service. :Exceptions: - WebDriverException : Raised either when it can't start the service or when it can't connect to the service """ env = self.env or os.environ self.log_file = file("geckodriver.log", "w") try: #import pdb; pdb.set_trace() self.process = subprocess.Popen([ self.path, "-b", self.firefox_binary, '--webdriver-port', "%d" % self.port], env=env, stdout=self.log_file, stderr=self.log_file) except Exception as e: raise WebDriverException( "'" + os.path.basename(self.path) + "' executable needs to be \ available in the path.\n %s" % str(e)) count = 0 while not utils.is_connectable(self.port): count += 1 time.sleep(1) if count == 30: raise WebDriverException("Can not connect to the '" + os.path.basename(self.path) + "'") @property def service_url(self): """ Gets the url of the GeckoDriver Service """ return "http://localhost:%d" % self.port def stop(self): """ Tells the GeckoDriver to stop and cleans up the process """ #If its dead dont worry if self.process is None: return #Tell the Server to die! '''try: from urllib import request as url_request except ImportError: import urllib2 as url_request url_request.urlopen("http://127.0.0.1:%d/shutdown" % self.port) count = 0 while utils.is_connectable(self.port): if count == 30: break count += 1 time.sleep(1) ''' #Tell the Server to properly die in case try: if self.process: self.process.kill() self.process.wait() except OSError: # kill may not be available under windows environment pass selenium-2.48.0/py/selenium/webdriver/firefox/webdriver.py0000644000076600000240000000727612605232133024327 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. try: import http.client as http_client except ImportError: import httplib as http_client import shutil import socket import sys from .firefox_binary import FirefoxBinary from .service import Service from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.firefox.extension_connection import ExtensionConnection from selenium.webdriver.firefox.firefox_profile import FirefoxProfile from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver class WebDriver(RemoteWebDriver): # There is no native event support on Mac NATIVE_EVENTS_ALLOWED = sys.platform != "darwin" def __init__(self, firefox_profile=None, firefox_binary=None, timeout=30, capabilities=None, proxy=None, executable_path='wires'): self.binary = firefox_binary self.profile = firefox_profile if self.profile is None: self.profile = FirefoxProfile() self.profile.native_events_enabled = ( self.NATIVE_EVENTS_ALLOWED and self.profile.native_events_enabled) if capabilities is None: capabilities = DesiredCapabilities.FIREFOX if "marionette" in capabilities and capabilities['marionette'] is True: # Let's use Marionette! WOOOOHOOOOO! if "binary" in capabilities: self.binary = capabilities["binary"] self.service = Service(executable_path, firefox_binary=self.binary) self.service.start() RemoteWebDriver.__init__(self, command_executor=self.service.service_url, desired_capabilities=capabilities, keep_alive=True) else: # Oh well... sometimes the old way is the best way. if self.binary is None: self.binary = FirefoxBinary() if proxy is not None: proxy.add_to_capabilities(capabilities) RemoteWebDriver.__init__(self, command_executor=ExtensionConnection("127.0.0.1", self.profile, self.binary, timeout), desired_capabilities=capabilities, keep_alive=True) self._is_remote = False def quit(self): """Quits the driver and close every associated window.""" try: RemoteWebDriver.quit(self) except (http_client.BadStatusLine, socket.error): # Happens if Firefox shutsdown before we've read the response from # the socket. pass if "specificationLevel" in self.capabilities: self.service.stop() else: self.binary.kill() try: shutil.rmtree(self.profile.path) if self.profile.tempfolder is not None: shutil.rmtree(self.profile.tempfolder) except Exception as e: print(str(e)) @property def firefox_profile(self): return self.profile selenium-2.48.0/py/selenium/webdriver/firefox/webdriver_prefs.json0000644000076600000240000000564512605237754026063 0ustar dburnsstaff00000000000000{ "frozen": { "app.update.auto": false, "app.update.enabled": false, "browser.displayedE10SNotice": 4, "browser.download.manager.showWhenStarting": false, "browser.EULA.override": true, "browser.EULA.3.accepted": true, "browser.link.open_external": 2, "browser.link.open_newwindow": 2, "browser.offline": false, "browser.reader.detectedFirstArticle": true, "browser.safebrowsing.enabled": false, "browser.safebrowsing.malware.enabled": false, "browser.search.update": false, "browser.selfsupport.url" : "", "browser.sessionstore.resume_from_crash": false, "browser.shell.checkDefaultBrowser": false, "browser.tabs.warnOnClose": false, "browser.tabs.warnOnOpen": false, "datareporting.healthreport.service.enabled": false, "datareporting.healthreport.uploadEnabled": false, "datareporting.healthreport.service.firstRun": false, "datareporting.healthreport.logging.consoleEnabled": false, "datareporting.policy.dataSubmissionEnabled": false, "datareporting.policy.dataSubmissionPolicyAccepted": false, "devtools.errorconsole.enabled": true, "dom.disable_open_during_load": false, "extensions.autoDisableScopes": 10, "extensions.blocklist.enabled": false, "extensions.logging.enabled": true, "extensions.update.enabled": false, "extensions.update.notifyUser": false, "javascript.enabled": true, "network.manage-offline-status": false, "network.http.phishy-userpass-length": 255, "offline-apps.allow_by_default": true, "prompts.tab_modal.enabled": false, "security.csp.enable": false, "security.fileuri.origin_policy": 3, "security.fileuri.strict_origin_policy": false, "security.warn_entering_secure": false, "security.warn_entering_secure.show_once": false, "security.warn_entering_weak": false, "security.warn_entering_weak.show_once": false, "security.warn_leaving_secure": false, "security.warn_leaving_secure.show_once": false, "security.warn_submit_insecure": false, "security.warn_viewing_mixed": false, "security.warn_viewing_mixed.show_once": false, "signon.rememberSignons": false, "toolkit.networkmanager.disable": true, "toolkit.telemetry.prompted": 2, "toolkit.telemetry.enabled": false, "toolkit.telemetry.rejected": true, "xpinstall.signatures.required": false }, "mutable": { "browser.dom.window.dump.enabled": true, "browser.newtab.url": "about:blank", "browser.newtabpage.enabled": false, "browser.startup.page": 0, "browser.startup.homepage": "about:blank", "dom.max_chrome_script_run_time": 30, "dom.max_script_run_time": 30, "dom.report_all_js_exceptions": true, "javascript.options.showInConsole": true, "network.http.max-connections-per-server": 10, "startup.homepage_welcome_url": "about:blank", "webdriver_accept_untrusted_certs": true, "webdriver_assume_untrusted_issuer": true } } selenium-2.48.0/py/selenium/webdriver/firefox/x86/0000755000076600000240000000000012605237755022414 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/ie/0000755000076600000240000000000012605237755020722 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/ie/__init__.py0000644000076600000240000000142312551302002023005 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/ie/service.py0000644000076600000240000001002712551302002022706 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 from subprocess import PIPE 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 the IEDriver """ def __init__(self, executable_path, port=0, host=None, log_level=None, log_file=None): """ Creates a new instance of the Service :Args: - executable_path : Path to the IEDriver - port : Port the service is running on - host : IP address the service port is bound - log_level : Level of logging of service, may be "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE". Default is "FATAL". - log_file : Target of logging of service, may be "stdout", "stderr" or file path. Default is "stdout".""" self.port = port self.path = executable_path if self.port == 0: self.port = utils.free_port() self.host = host self.log_level = log_level self.log_file = log_file def start(self): """ Starts the IEDriver Service. :Exceptions: - WebDriverException : Raised either when it can't start the service or when it can't connect to the service """ try: cmd = [self.path, "--port=%d" % self.port] if self.host is not None: cmd.append("--host=%s" % self.host) if self.log_level is not None: cmd.append("--log-level=%s" % self.log_level) if self.log_file is not None: cmd.append("--log-file=%s" % self.log_file) self.process = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE) except TypeError: raise except: raise WebDriverException( "IEDriver executable needs to be available in the path. " "Please download from http://selenium-release.storage.googleapis.com/index.html " "and read up at https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver") count = 0 while not utils.is_url_connectable(self.port): count += 1 time.sleep(1) if count == 30: raise WebDriverException("Can not connect to the IEDriver") def stop(self): """ Tells the IEDriver to stop and cleans up the process """ #If its dead dont worry if self.process is None: return #Tell the Server to die! try: from urllib import request as url_request except ImportError: import urllib2 as url_request url_request.urlopen("http://127.0.0.1:%d/shutdown" % self.port) count = 0 while utils.is_connectable(self.port): if count == 30: break count += 1 time.sleep(1) #Tell the Server to properly die in case try: if self.process: self.process.stdout.close() self.process.stderr.close() self.process.kill() self.process.wait() except WindowsError: # kill may not be available under windows environment pass selenium-2.48.0/py/selenium/webdriver/ie/webdriver.py0000644000076600000240000000432712551302002023245 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from selenium.webdriver.common import utils from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.remote.command import Command from selenium.common.exceptions import WebDriverException import base64 from .service import Service DEFAULT_TIMEOUT = 30 DEFAULT_PORT = 0 DEFAULT_HOST = None DEFAULT_LOG_LEVEL = None DEFAULT_LOG_FILE = None class WebDriver(RemoteWebDriver): def __init__(self, executable_path='IEDriverServer.exe', capabilities=None, port=DEFAULT_PORT, timeout=DEFAULT_TIMEOUT, host=DEFAULT_HOST, log_level=DEFAULT_LOG_LEVEL, log_file=DEFAULT_LOG_FILE): self.port = port if self.port == 0: self.port = utils.free_port() self.host = host self.log_level = log_level self.log_file = log_file self.iedriver = Service(executable_path, port=self.port, host=self.host, log_level=self.log_level, log_file=self.log_file) self.iedriver.start() if capabilities is None: capabilities = DesiredCapabilities.INTERNETEXPLORER RemoteWebDriver.__init__( self, command_executor='http://localhost:%d' % self.port, desired_capabilities=capabilities) self._is_remote = False def quit(self): RemoteWebDriver.quit(self) self.iedriver.stop() selenium-2.48.0/py/selenium/webdriver/opera/0000755000076600000240000000000012605237755021433 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/opera/__init__.py0000644000076600000240000000142312551302002023516 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/opera/options.py0000644000076600000240000000647112551302002023462 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from selenium.webdriver.chrome.options import Options as ChromeOptions from selenium.webdriver.common.desired_capabilities import DesiredCapabilities class Options(ChromeOptions): def __init__(self): ChromeOptions.__init__(self) self._android_package_name = '' self._android_device_socket = '' self._android_command_line_file = '' @property def android_package_name(self): """ Returns the name of the Opera package """ return self._android_package_name @android_package_name.setter def android_package_name(self, value): """ Allows you to set the package name :Args: - value: devtools socket name """ self._android_package_name = value @property def android_device_socket(self): """ Returns the name of the devtools socket """ return self._android_device_socket @android_device_socket.setter def android_device_socket(self, value): """ Allows you to set the devtools socket name :Args: - value: devtools socket name """ self._android_device_socket = value @property def android_command_line_file(self): """ Returns the path of the command line file """ return self._android_command_line_file @android_command_line_file.setter def android_command_line_file(self, value): """ Allows you to set where the command line file lives :Args: - value: command line file path """ self._android_command_line_file = value def to_capabilities(self): """ Creates a capabilities with all the options that have been set and returns a dictionary with everything """ capabilities = ChromeOptions.to_capabilities(self) capabilities.update(DesiredCapabilities.OPERA) opera_options = capabilities["operaOptions"] = \ capabilities.pop("chromeOptions") if self.android_package_name: opera_options["androidPackage"] = self.android_package_name if self.android_device_socket: opera_options["androidDeviceSocket"] = self.android_device_socket if self.android_command_line_file: opera_options["androidCommandLineFile"] = \ self.android_command_line_file return capabilities class AndroidOptions(Options): def __init__(self): Options.__init__(self) self.android_package_name = 'com.opera.browser' selenium-2.48.0/py/selenium/webdriver/opera/webdriver.py0000644000076600000240000000643012551302002023753 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. try: import http.client as http_client except ImportError: import httplib as http_client import os from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver from selenium.webdriver.chrome.webdriver import WebDriver as ChromiumDriver from .options import Options class OperaDriver(ChromiumDriver): """Controls the new OperaDriver and allows you to drive the Opera browser based on Chromium.""" def __init__(self, executable_path=None, port=0, opera_options=None, service_args=None, desired_capabilities=None, service_log_path=None): """ Creates a new instance of the operadriver. Starts the service and then creates new instance of operadriver. :Args: - 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". - chrome_options: this takes an instance of ChromeOptions """ executable_path = (executable_path if executable_path is not None else "operadriver") ChromiumDriver.__init__(self, executable_path=executable_path, port=port, chrome_options=opera_options, service_args=service_args, desired_capabilities=desired_capabilities, service_log_path=service_log_path) def create_options(self): return Options() class WebDriver(OperaDriver): class ServiceType: CHROMIUM = 2 def __init__(self, desired_capabilities=None, executable_path=None, port=0, service_log_path=None, service_args=None, opera_options=None): OperaDriver.__init__(self, executable_path=executable_path, port=port, opera_options=opera_options, service_args=service_args, desired_capabilities=desired_capabilities, service_log_path=service_log_path) selenium-2.48.0/py/selenium/webdriver/phantomjs/0000755000076600000240000000000012605237755022330 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/phantomjs/__init__.py0000644000076600000240000000142312551302002024413 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/phantomjs/service.py0000755000076600000240000000737512556232172024352 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 platform 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, port=0, service_args=None, log_path=None): """ Creates a new instance of the Service :Args: - executable_path : Path to PhantomJS binary - port : Port the service is running on - service_args : A List of other command line options to pass to PhantomJS - log_path: Path for PhantomJS service to log to """ 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 = [] else: self.service_args=service_args[:] self.service_args.insert(0, self.path) self.service_args.append("--webdriver=%d" % self.port) self.process = None if not log_path: log_path = "ghostdriver.log" self._log = open(log_path, 'w') def __del__(self): # subprocess.Popen doesn't send signal on __del__; # we have to try to stop the launched process. self.stop() def start(self): """ Starts PhantomJS with GhostDriver. :Exceptions: - WebDriverException : Raised either when it can't start the service or when it can't connect to the service. """ try: self.process = subprocess.Popen(self.service_args, stdin=subprocess.PIPE, close_fds=platform.system() != 'Windows', stdout=self._log, stderr=self._log) except Exception as e: raise WebDriverException("Unable to start phantomjs with ghostdriver: %s" % e) count = 0 while not utils.is_connectable(self.port): count += 1 time.sleep(1) if count == 30: raise WebDriverException( "Can not connect to GhostDriver on port {}".format(self.port)) @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.stdin.close() self.process.kill() self.process.wait() self.process = None except OSError: # kill may not be available under windows environment pass selenium-2.48.0/py/selenium/webdriver/phantomjs/webdriver.py0000644000076600000240000000565112551302002024654 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 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, executable_path="phantomjs", port=0, desired_capabilities=DesiredCapabilities.PHANTOMJS, service_args=None, service_log_path=None): """ Creates a new instance of the PhantomJS / Ghostdriver. Starts the service and then creates new instance of the driver. :Args: - 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". - service_args : A List of command line arguments to pass to PhantomJS - service_log_path: Path for phantomjs service to log to. """ self.service = Service(executable_path, port=port, service_args=service_args, log_path=service_log_path) self.service.start() try: RemoteWebDriver.__init__(self, command_executor=self.service.service_url, desired_capabilities=desired_capabilities) except: self.quit() raise self._is_remote = False 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() selenium-2.48.0/py/selenium/webdriver/remote/0000755000076600000240000000000012605237755021620 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/remote/__init__.py0000644000076600000240000000142312551302002023703 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/remote/command.py0000644000076600000240000001312312555540270023601 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. class Command(object): """ Defines constants for the standard WebDriver commands. While these constants have no meaning in and of themselves, they are used to marshal commands through a service that implements WebDriver's remote wire protocol: https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol """ # Keep in sync with org.openqa.selenium.remote.DriverCommand STATUS = "status" NEW_SESSION = "newSession" GET_ALL_SESSIONS = "getAllSessions" DELETE_SESSION = "deleteSession" CLOSE = "close" QUIT = "quit" GET = "get" GO_BACK = "goBack" GO_FORWARD = "goForward" REFRESH = "refresh" ADD_COOKIE = "addCookie" GET_COOKIE = "getCookie" GET_ALL_COOKIES = "getCookies" DELETE_COOKIE = "deleteCookie" DELETE_ALL_COOKIES = "deleteAllCookies" FIND_ELEMENT = "findElement" FIND_ELEMENTS = "findElements" FIND_CHILD_ELEMENT = "findChildElement" FIND_CHILD_ELEMENTS = "findChildElements" CLEAR_ELEMENT = "clearElement" CLICK_ELEMENT = "clickElement" SEND_KEYS_TO_ELEMENT = "sendKeysToElement" SEND_KEYS_TO_ACTIVE_ELEMENT = "sendKeysToActiveElement" SUBMIT_ELEMENT = "submitElement" UPLOAD_FILE = "uploadFile" GET_CURRENT_WINDOW_HANDLE = "getCurrentWindowHandle" GET_WINDOW_HANDLES = "getWindowHandles" GET_WINDOW_SIZE = "getWindowSize" W3C_GET_WINDOW_SIZE = "w3cGetWindowSize" GET_WINDOW_POSITION = "getWindowPosition" SET_WINDOW_SIZE = "setWindowSize" W3C_SET_WINDOW_SIZE = "w3cSetWindowSize" SET_WINDOW_POSITION = "setWindowPosition" SWITCH_TO_WINDOW = "switchToWindow" SWITCH_TO_FRAME = "switchToFrame" SWITCH_TO_PARENT_FRAME = "switchToParentFrame" GET_ACTIVE_ELEMENT = "getActiveElement" GET_CURRENT_URL = "getCurrentUrl" GET_PAGE_SOURCE = "getPageSource" GET_TITLE = "getTitle" EXECUTE_SCRIPT = "executeScript" GET_ELEMENT_TEXT = "getElementText" GET_ELEMENT_VALUE = "getElementValue" GET_ELEMENT_TAG_NAME = "getElementTagName" SET_ELEMENT_SELECTED = "setElementSelected" IS_ELEMENT_SELECTED = "isElementSelected" IS_ELEMENT_ENABLED = "isElementEnabled" IS_ELEMENT_DISPLAYED = "isElementDisplayed" GET_ELEMENT_LOCATION = "getElementLocation" GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW = "getElementLocationOnceScrolledIntoView" GET_ELEMENT_SIZE = "getElementSize" GET_ELEMENT_RECT = "getElementRect" GET_ELEMENT_ATTRIBUTE = "getElementAttribute" GET_ELEMENT_VALUE_OF_CSS_PROPERTY = "getElementValueOfCssProperty" ELEMENT_EQUALS = "elementEquals" SCREENSHOT = "screenshot" ELEMENT_SCREENSHOT = "elementScreenshot" IMPLICIT_WAIT = "implicitlyWait" EXECUTE_ASYNC_SCRIPT = "executeAsyncScript" SET_SCRIPT_TIMEOUT = "setScriptTimeout" SET_TIMEOUTS = "setTimeouts" MAXIMIZE_WINDOW = "windowMaximize" W3C_MAXIMIZE_WINDOW = "w3cMaximizeWindow" GET_LOG = "getLog" GET_AVAILABLE_LOG_TYPES = "getAvailableLogTypes" #Alerts DISMISS_ALERT = "dismissAlert" ACCEPT_ALERT = "acceptAlert" SET_ALERT_VALUE = "setAlertValue" GET_ALERT_TEXT = "getAlertText" SET_ALERT_CREDENTIALS = "setAlertCredentials" # Advanced user interactions CLICK = "mouseClick" DOUBLE_CLICK = "mouseDoubleClick" MOUSE_DOWN = "mouseButtonDown" MOUSE_UP = "mouseButtonUp" MOVE_TO = "mouseMoveTo" # Screen Orientation SET_SCREEN_ORIENTATION = "setScreenOrientation" GET_SCREEN_ORIENTATION = "getScreenOrientation" # Touch Actions SINGLE_TAP = "touchSingleTap" TOUCH_DOWN = "touchDown" TOUCH_UP = "touchUp" TOUCH_MOVE = "touchMove" TOUCH_SCROLL = "touchScroll" DOUBLE_TAP = "touchDoubleTap" LONG_PRESS = "touchLongPress" FLICK = "touchFlick" #HTML 5 EXECUTE_SQL = "executeSql" GET_LOCATION = "getLocation" SET_LOCATION = "setLocation" GET_APP_CACHE = "getAppCache" GET_APP_CACHE_STATUS = "getAppCacheStatus" CLEAR_APP_CACHE = "clearAppCache" GET_LOCAL_STORAGE_ITEM = "getLocalStorageItem" REMOVE_LOCAL_STORAGE_ITEM = "removeLocalStorageItem" GET_LOCAL_STORAGE_KEYS = "getLocalStorageKeys" SET_LOCAL_STORAGE_ITEM = "setLocalStorageItem" CLEAR_LOCAL_STORAGE = "clearLocalStorage" GET_LOCAL_STORAGE_SIZE = "getLocalStorageSize" GET_SESSION_STORAGE_ITEM = "getSessionStorageItem" REMOVE_SESSION_STORAGE_ITEM = "removeSessionStorageItem" GET_SESSION_STORAGE_KEYS = "getSessionStorageKeys" SET_SESSION_STORAGE_ITEM = "setSessionStorageItem" CLEAR_SESSION_STORAGE = "clearSessionStorage" GET_SESSION_STORAGE_SIZE = "getSessionStorageSize" # Mobile GET_NETWORK_CONNECTION = "getNetworkConnection" SET_NETWORK_CONNECTION = "setNetworkConnection" CURRENT_CONTEXT_HANDLE = "getCurrentContextHandle" CONTEXT_HANDLES = "getContextHandles" SWITCH_TO_CONTEXT = "switchToContext" selenium-2.48.0/py/selenium/webdriver/remote/errorhandler.py0000644000076600000240000002031112603572056024650 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from selenium.common.exceptions import ElementNotSelectableException from selenium.common.exceptions import ElementNotVisibleException from selenium.common.exceptions import InvalidCookieDomainException from selenium.common.exceptions import InvalidElementStateException from selenium.common.exceptions import InvalidSelectorException from selenium.common.exceptions import ImeNotAvailableException from selenium.common.exceptions import ImeActivationFailedException from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import NoSuchFrameException from selenium.common.exceptions import NoSuchWindowException from selenium.common.exceptions import StaleElementReferenceException from selenium.common.exceptions import UnableToSetCookieException from selenium.common.exceptions import UnexpectedAlertPresentException from selenium.common.exceptions import NoAlertPresentException from selenium.common.exceptions import ErrorInResponseException from selenium.common.exceptions import TimeoutException from selenium.common.exceptions import WebDriverException from selenium.common.exceptions import MoveTargetOutOfBoundsException try: basestring except NameError: # Python 3.x basestring = str class ErrorCode(object): """ Error codes defined in the WebDriver wire protocol. """ # Keep in sync with org.openqa.selenium.remote.ErrorCodes and errorcodes.h SUCCESS = 0 NO_SUCH_ELEMENT = [7, 'no such element'] NO_SUCH_FRAME = [8, 'no such frame'] UNKNOWN_COMMAND = [9, 'unknown command'] STALE_ELEMENT_REFERENCE = [10, 'stale element reference'] ELEMENT_NOT_VISIBLE = [11, 'element not visible'] INVALID_ELEMENT_STATE = [12, 'invalid element state'] UNKNOWN_ERROR = [13, 'unknown error'] ELEMENT_IS_NOT_SELECTABLE = [15, 'element not selectable'] JAVASCRIPT_ERROR = [17, 'javascript error'] XPATH_LOOKUP_ERROR = [19, 'invalid selector'] TIMEOUT = [21, 'timeout'] NO_SUCH_WINDOW = [23, 'no such window'] INVALID_COOKIE_DOMAIN = [24, 'invalid cookie domain'] UNABLE_TO_SET_COOKIE = [25, 'unable to set cookie'] UNEXPECTED_ALERT_OPEN = [26, 'unexpected alert open'] NO_ALERT_OPEN = [27, 'no such alert'] SCRIPT_TIMEOUT = [28, 'script timeout'] INVALID_ELEMENT_COORDINATES = [29, 'invalid element coordinates'] IME_NOT_AVAILABLE = [30, 'ime not available'] IME_ENGINE_ACTIVATION_FAILED = [31, 'ime engine activation failed'] INVALID_SELECTOR = [32, 'invalid selector'] MOVE_TARGET_OUT_OF_BOUNDS = [34, 'move target out of bounds'] INVALID_XPATH_SELECTOR = [51, 'invalid selector'] INVALID_XPATH_SELECTOR_RETURN_TYPER = [52, 'invalid selector'] METHOD_NOT_ALLOWED = [405, 'unsupported operation'] class ErrorHandler(object): """ Handles errors returned by the WebDriver server. """ def check_response(self, response): """ Checks that a JSON response from the WebDriver does not have an error. :Args: - response - The JSON response from the WebDriver server as a dictionary object. :Raises: If the response contains an error message. """ status = response.get('status', None) if status is None or status == ErrorCode.SUCCESS: return value = None message = response.get("message", "") screen = response.get("screen", "") stacktrace = None if isinstance(status, int): value_json = response.get('value', None) if value_json and isinstance(value_json, basestring): import json value = json.loads(value_json) status = value['error'] message = value['message'] exception_class = ErrorInResponseException if status in ErrorCode.NO_SUCH_ELEMENT: exception_class = NoSuchElementException elif status in ErrorCode.NO_SUCH_FRAME: exception_class = NoSuchFrameException elif status in ErrorCode.NO_SUCH_WINDOW: exception_class = NoSuchWindowException elif status in ErrorCode.STALE_ELEMENT_REFERENCE: exception_class = StaleElementReferenceException elif status in ErrorCode.ELEMENT_NOT_VISIBLE: exception_class = ElementNotVisibleException elif status in ErrorCode.INVALID_ELEMENT_STATE: exception_class = InvalidElementStateException elif status in ErrorCode.INVALID_SELECTOR \ or status in ErrorCode.INVALID_XPATH_SELECTOR \ or status in ErrorCode.INVALID_XPATH_SELECTOR_RETURN_TYPER: exception_class = InvalidSelectorException elif status in ErrorCode.ELEMENT_IS_NOT_SELECTABLE: exception_class = ElementNotSelectableException elif status in ErrorCode.INVALID_COOKIE_DOMAIN: exception_class = WebDriverException elif status in ErrorCode.UNABLE_TO_SET_COOKIE: exception_class = WebDriverException elif status in ErrorCode.TIMEOUT: exception_class = TimeoutException elif status in ErrorCode.SCRIPT_TIMEOUT: exception_class = TimeoutException elif status in ErrorCode.UNKNOWN_ERROR: exception_class = WebDriverException elif status in ErrorCode.UNEXPECTED_ALERT_OPEN: exception_class = UnexpectedAlertPresentException elif status in ErrorCode.NO_ALERT_OPEN: exception_class = NoAlertPresentException elif status in ErrorCode.IME_NOT_AVAILABLE: exception_class = ImeNotAvailableException elif status in ErrorCode.IME_ENGINE_ACTIVATION_FAILED: exception_class = ImeActivationFailedException elif status in ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS: exception_class = MoveTargetOutOfBoundsException else: exception_class = WebDriverException value = response['value'] if isinstance(value, basestring): if exception_class == ErrorInResponseException: raise exception_class(response, value) raise exception_class(value) message = '' if 'message' in value: message = value['message'] screen = None if 'screen' in value: screen = value['screen'] stacktrace = None if 'stackTrace' in value and value['stackTrace']: stacktrace = [] try: for frame in value['stackTrace']: line = self._value_or_default(frame, 'lineNumber', '') file = self._value_or_default(frame, 'fileName', '') if line: file = "%s:%s" % (file, line) meth = self._value_or_default(frame, 'methodName', '') if 'className' in frame: meth = "%s.%s" % (frame['className'], meth) msg = " at %s (%s)" msg = msg % (meth, file) stacktrace.append(msg) except TypeError: pass if exception_class == ErrorInResponseException: raise exception_class(response, message) elif exception_class == UnexpectedAlertPresentException and 'alert' in value: raise exception_class(message, screen, stacktrace, value['alert'].get('text')) raise exception_class(message, screen, stacktrace) def _value_or_default(self, obj, key, default): return obj[key] if key in obj else default selenium-2.48.0/py/selenium/webdriver/remote/file_detector.py0000644000076600000240000000375012551302002024761 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 abc import os from selenium.webdriver.common.keys import Keys class FileDetector(object): """ Used for identifying whether a sequence of chars represents the path to a file. """ __metaclass__ = abc.ABCMeta @abc.abstractmethod def is_local_file(self, *keys): return class UselessFileDetector(FileDetector): """ A file detector that never finds anything. """ def is_local_file(self, *keys): return None class LocalFileDetector(FileDetector): """ Detects files on the local disk. """ def is_local_file(self, *keys): file_path = '' typing = [] for val in keys: if isinstance(val, Keys): typing.append(val) elif isinstance(val, int): val = val.__str__() for i in range(len(val)): typing.append(val[i]) else: for i in range(len(val)): typing.append(val[i]) file_path = ''.join(typing) if file_path is '': return None try: if os.path.isfile(file_path): return file_path except: pass return None selenium-2.48.0/py/selenium/webdriver/remote/mobile.py0000644000076600000240000000531512551302002023417 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from .command import Command from selenium.common.exceptions import WebDriverException class Mobile(object): class ConnectionType(object): def __init__(self, mask): self.mask = mask @property def airplane_mode(self): return self.mask % 2 == 1 @property def wifi(self): return (self.mask / 2) % 2 == 1 @property def data(self): return (self.mask / 4) > 0 ALL_NETWORK = ConnectionType(6) WIFI_NETWORK = ConnectionType(2) DATA_NETWORK = ConnectionType(4) AIRPLANE_MODE = ConnectionType(1) def __init__(self, driver): self._driver = driver @property def network_connection(self): return self.ConnectionType(self._driver.execute(Command.GET_NETWORK_CONNECTION)['value']) def set_network_connection(self, network): """ Set the network connection for the remote device. Example of setting airplane mode: driver.mobile.set_network_connection(driver.mobile.AIRPLANE_MODE) """ mode = network.mask if isinstance(network, self.ConnectionType) else network return self.ConnectionType(self._driver.execute(Command.SET_NETWORK_CONNECTION, {'name':'network_connection', 'parameters':{'type': mode}})['value']) @property def context(self): """ returns the current context (Native or WebView). """ return self._driver.execute(Command.CURRENT_CONTEXT_HANDLE) @property def contexts(self): """ returns a list of available contexts """ return self._driver.execute(Command.CONTEXT_HANDLES) @context.setter def context(self, new_context): """ sets the current context """ self._driver.execute(Command.SWITCH_TO_CONTEXT, {"name": new_context}) selenium-2.48.0/py/selenium/webdriver/remote/remote_connection.py0000644000076600000240000005303412603472735025706 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 logging import socket import string import base64 try: import http.client as httplib from urllib import request as url_request from urllib import parse except ImportError: # above is available in py3+, below is py2.7 import httplib as httplib import urllib2 as url_request import urlparse as parse from .command import Command from .errorhandler import ErrorCode from . import utils LOGGER = logging.getLogger(__name__) class Request(url_request.Request): """ Extends the url_request.Request to support all HTTP request types. """ def __init__(self, url, data=None, method=None): """ Initialise a new HTTP request. :Args: - url - String for the URL to send the request to. - data - Data to send with the request. """ if method is None: method = data is not None and 'POST' or 'GET' elif method != 'POST' and method != 'PUT': data = None self._method = method url_request.Request.__init__(self, url, data=data) def get_method(self): """ Returns the HTTP method used by this request. """ return self._method class Response(object): """ Represents an HTTP response. """ def __init__(self, fp, code, headers, url): """ Initialise a new Response. :Args: - fp - The response body file object. - code - The HTTP status code returned by the server. - headers - A dictionary of headers returned by the server. - url - URL of the retrieved resource represented by this Response. """ self.fp = fp self.read = fp.read self.code = code self.headers = headers self.url = url def close(self): """ Close the response body file object. """ self.read = None self.fp = None def info(self): """ Returns the response headers. """ return self.headers def geturl(self): """ Returns the URL for the resource returned in this response. """ return self.url class HttpErrorHandler(url_request.HTTPDefaultErrorHandler): """ A custom HTTP error handler. Used to return Response objects instead of raising an HTTPError exception. """ def http_error_default(self, req, fp, code, msg, headers): """ Default HTTP error handler. :Args: - req - The original Request object. - fp - The response body file object. - code - The HTTP status code returned by the server. - msg - The HTTP status message returned by the server. - headers - The response headers. :Returns: A new Response object. """ return Response(fp, code, headers, req.get_full_url()) class RemoteConnection(object): """A connection with the Remote WebDriver server. Communicates with the server using the WebDriver wire protocol: https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol""" _timeout = socket._GLOBAL_DEFAULT_TIMEOUT @classmethod def get_timeout(cls): """ :Returns: Timeout value in seconds for all http requests made to the Remote Connection """ return None if cls._timeout == socket._GLOBAL_DEFAULT_TIMEOUT else cls._timeout @classmethod def set_timeout(cls, timeout): """ Override the default timeout :Args: - timeout - timeout value for http requests in seconds """ cls._timeout = timeout @classmethod def reset_timeout(cls): """ Reset the http request timeout to socket._GLOBAL_DEFAULT_TIMEOUT """ cls._timeout = socket._GLOBAL_DEFAULT_TIMEOUT def __init__(self, remote_server_addr, keep_alive=False, resolve_ip=True): # Attempt to resolve the hostname and get an IP address. self.keep_alive = keep_alive parsed_url = parse.urlparse(remote_server_addr) addr = "" if parsed_url.hostname and resolve_ip: try: netloc = socket.gethostbyname(parsed_url.hostname) addr = netloc if parsed_url.port: netloc += ':%d' % parsed_url.port if parsed_url.username: auth = parsed_url.username if parsed_url.password: auth += ':%s' % parsed_url.password netloc = '%s@%s' % (auth, netloc) remote_server_addr = parse.urlunparse( (parsed_url.scheme, netloc, parsed_url.path, parsed_url.params, parsed_url.query, parsed_url.fragment)) except socket.gaierror: LOGGER.info('Could not get IP address for host: %s' % parsed_url.hostname) self._url = remote_server_addr if keep_alive: self._conn = httplib.HTTPConnection( str(addr), str(parsed_url.port), timeout=self._timeout) self._commands = { Command.STATUS: ('GET', '/status'), Command.NEW_SESSION: ('POST', '/session'), Command.GET_ALL_SESSIONS: ('GET', '/sessions'), Command.QUIT: ('DELETE', '/session/$sessionId'), Command.GET_CURRENT_WINDOW_HANDLE: ('GET', '/session/$sessionId/window_handle'), Command.GET_WINDOW_HANDLES: ('GET', '/session/$sessionId/window_handles'), Command.GET: ('POST', '/session/$sessionId/url'), Command.GO_FORWARD: ('POST', '/session/$sessionId/forward'), Command.GO_BACK: ('POST', '/session/$sessionId/back'), Command.REFRESH: ('POST', '/session/$sessionId/refresh'), Command.EXECUTE_SCRIPT: ('POST', '/session/$sessionId/execute'), Command.GET_CURRENT_URL: ('GET', '/session/$sessionId/url'), Command.GET_TITLE: ('GET', '/session/$sessionId/title'), Command.GET_PAGE_SOURCE: ('GET', '/session/$sessionId/source'), Command.SCREENSHOT: ('GET', '/session/$sessionId/screenshot'), Command.ELEMENT_SCREENSHOT: ('GET', '/session/$sessionId/screenshot/$id'), Command.FIND_ELEMENT: ('POST', '/session/$sessionId/element'), Command.FIND_ELEMENTS: ('POST', '/session/$sessionId/elements'), Command.GET_ACTIVE_ELEMENT: ('POST', '/session/$sessionId/element/active'), Command.FIND_CHILD_ELEMENT: ('POST', '/session/$sessionId/element/$id/element'), Command.FIND_CHILD_ELEMENTS: ('POST', '/session/$sessionId/element/$id/elements'), Command.CLICK_ELEMENT: ('POST', '/session/$sessionId/element/$id/click'), Command.CLEAR_ELEMENT: ('POST', '/session/$sessionId/element/$id/clear'), Command.SUBMIT_ELEMENT: ('POST', '/session/$sessionId/element/$id/submit'), Command.GET_ELEMENT_TEXT: ('GET', '/session/$sessionId/element/$id/text'), Command.SEND_KEYS_TO_ELEMENT: ('POST', '/session/$sessionId/element/$id/value'), Command.SEND_KEYS_TO_ACTIVE_ELEMENT: ('POST', '/session/$sessionId/keys'), Command.UPLOAD_FILE: ('POST', "/session/$sessionId/file"), Command.GET_ELEMENT_VALUE: ('GET', '/session/$sessionId/element/$id/value'), Command.GET_ELEMENT_TAG_NAME: ('GET', '/session/$sessionId/element/$id/name'), Command.IS_ELEMENT_SELECTED: ('GET', '/session/$sessionId/element/$id/selected'), Command.SET_ELEMENT_SELECTED: ('POST', '/session/$sessionId/element/$id/selected'), Command.IS_ELEMENT_ENABLED: ('GET', '/session/$sessionId/element/$id/enabled'), Command.IS_ELEMENT_DISPLAYED: ('GET', '/session/$sessionId/element/$id/displayed'), Command.GET_ELEMENT_LOCATION: ('GET', '/session/$sessionId/element/$id/location'), Command.GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW: ('GET', '/session/$sessionId/element/$id/location_in_view'), Command.GET_ELEMENT_SIZE: ('GET', '/session/$sessionId/element/$id/size'), Command.GET_ELEMENT_RECT: ('GET', '/session/$sessionId/element/$id/rect'), Command.GET_ELEMENT_ATTRIBUTE: ('GET', '/session/$sessionId/element/$id/attribute/$name'), Command.ELEMENT_EQUALS: ('GET', '/session/$sessionId/element/$id/equals/$other'), Command.GET_ALL_COOKIES: ('GET', '/session/$sessionId/cookie'), Command.ADD_COOKIE: ('POST', '/session/$sessionId/cookie'), Command.DELETE_ALL_COOKIES: ('DELETE', '/session/$sessionId/cookie'), Command.DELETE_COOKIE: ('DELETE', '/session/$sessionId/cookie/$name'), Command.SWITCH_TO_FRAME: ('POST', '/session/$sessionId/frame'), Command.SWITCH_TO_PARENT_FRAME: ('POST', '/session/$sessionId/frame/parent'), Command.SWITCH_TO_WINDOW: ('POST', '/session/$sessionId/window'), Command.CLOSE: ('DELETE', '/session/$sessionId/window'), Command.GET_ELEMENT_VALUE_OF_CSS_PROPERTY: ('GET', '/session/$sessionId/element/$id/css/$propertyName'), Command.IMPLICIT_WAIT: ('POST', '/session/$sessionId/timeouts/implicit_wait'), Command.EXECUTE_ASYNC_SCRIPT: ('POST', '/session/$sessionId/execute_async'), Command.SET_SCRIPT_TIMEOUT: ('POST', '/session/$sessionId/timeouts/async_script'), Command.SET_TIMEOUTS: ('POST', '/session/$sessionId/timeouts'), Command.DISMISS_ALERT: ('POST', '/session/$sessionId/dismiss_alert'), Command.ACCEPT_ALERT: ('POST', '/session/$sessionId/accept_alert'), Command.SET_ALERT_VALUE: ('POST', '/session/$sessionId/alert_text'), Command.GET_ALERT_TEXT: ('GET', '/session/$sessionId/alert_text'), Command.SET_ALERT_CREDENTIALS: ('POST', '/session/$sessionId/alert/credentials'), Command.CLICK: ('POST', '/session/$sessionId/click'), Command.DOUBLE_CLICK: ('POST', '/session/$sessionId/doubleclick'), Command.MOUSE_DOWN: ('POST', '/session/$sessionId/buttondown'), Command.MOUSE_UP: ('POST', '/session/$sessionId/buttonup'), Command.MOVE_TO: ('POST', '/session/$sessionId/moveto'), Command.GET_WINDOW_SIZE: ('GET', '/session/$sessionId/window/$windowHandle/size'), Command.W3C_GET_WINDOW_SIZE: ('GET', '/session/$sessionId/window/size'), Command.SET_WINDOW_SIZE: ('POST', '/session/$sessionId/window/$windowHandle/size'), Command.W3C_SET_WINDOW_SIZE: ('POST', '/session/$sessionId/window/size'), Command.GET_WINDOW_POSITION: ('GET', '/session/$sessionId/window/$windowHandle/position'), Command.SET_WINDOW_POSITION: ('POST', '/session/$sessionId/window/$windowHandle/position'), Command.MAXIMIZE_WINDOW: ('POST', '/session/$sessionId/window/$windowHandle/maximize'), Command.W3C_MAXIMIZE_WINDOW: ('POST', '/session/$sessionId/window/maximize'), Command.SET_SCREEN_ORIENTATION: ('POST', '/session/$sessionId/orientation'), Command.GET_SCREEN_ORIENTATION: ('GET', '/session/$sessionId/orientation'), Command.SINGLE_TAP: ('POST', '/session/$sessionId/touch/click'), Command.TOUCH_DOWN: ('POST', '/session/$sessionId/touch/down'), Command.TOUCH_UP: ('POST', '/session/$sessionId/touch/up'), Command.TOUCH_MOVE: ('POST', '/session/$sessionId/touch/move'), Command.TOUCH_SCROLL: ('POST', '/session/$sessionId/touch/scroll'), Command.DOUBLE_TAP: ('POST', '/session/$sessionId/touch/doubleclick'), Command.LONG_PRESS: ('POST', '/session/$sessionId/touch/longclick'), Command.FLICK: ('POST', '/session/$sessionId/touch/flick'), Command.EXECUTE_SQL: ('POST', '/session/$sessionId/execute_sql'), Command.GET_LOCATION: ('GET', '/session/$sessionId/location'), Command.SET_LOCATION: ('POST', '/session/$sessionId/location'), Command.GET_APP_CACHE: ('GET', '/session/$sessionId/application_cache'), Command.GET_APP_CACHE_STATUS: ('GET', '/session/$sessionId/application_cache/status'), Command.CLEAR_APP_CACHE: ('DELETE', '/session/$sessionId/application_cache/clear'), Command.GET_NETWORK_CONNECTION: ('GET', '/session/$sessionId/network_connection'), Command.SET_NETWORK_CONNECTION: ('POST', '/session/$sessionId/network_connection'), Command.GET_LOCAL_STORAGE_ITEM: ('GET', '/session/$sessionId/local_storage/key/$key'), Command.REMOVE_LOCAL_STORAGE_ITEM: ('DELETE', '/session/$sessionId/local_storage/key/$key'), Command.GET_LOCAL_STORAGE_KEYS: ('GET', '/session/$sessionId/local_storage'), Command.SET_LOCAL_STORAGE_ITEM: ('POST', '/session/$sessionId/local_storage'), Command.CLEAR_LOCAL_STORAGE: ('DELETE', '/session/$sessionId/local_storage'), Command.GET_LOCAL_STORAGE_SIZE: ('GET', '/session/$sessionId/local_storage/size'), Command.GET_SESSION_STORAGE_ITEM: ('GET', '/session/$sessionId/session_storage/key/$key'), Command.REMOVE_SESSION_STORAGE_ITEM: ('DELETE', '/session/$sessionId/session_storage/key/$key'), Command.GET_SESSION_STORAGE_KEYS: ('GET', '/session/$sessionId/session_storage'), Command.SET_SESSION_STORAGE_ITEM: ('POST', '/session/$sessionId/session_storage'), Command.CLEAR_SESSION_STORAGE: ('DELETE', '/session/$sessionId/session_storage'), Command.GET_SESSION_STORAGE_SIZE: ('GET', '/session/$sessionId/session_storage/size'), Command.GET_LOG: ('POST', '/session/$sessionId/log'), Command.GET_AVAILABLE_LOG_TYPES: ('GET', '/session/$sessionId/log/types'), Command.CURRENT_CONTEXT_HANDLE: ('GET', '/session/$sessionId/context'), Command.CONTEXT_HANDLES: ('GET', '/session/$sessionId/contexts'), Command.SWITCH_TO_CONTEXT: ('POST', '/session/$sessionId/context'), } def execute(self, command, params): """ Send a command to the remote server. Any path subtitutions required for the URL mapped to the command should be included in the command parameters. :Args: - command - A string specifying the command to execute. - params - A dictionary of named parameters to send with the command as its JSON payload. """ command_info = self._commands[command] assert command_info is not None, 'Unrecognised command %s' % command data = utils.dump_json(params) path = string.Template(command_info[1]).substitute(params) url = '%s%s' % (self._url, path) return self._request(command_info[0], url, body=data) def _request(self, method, url, body=None): """ Send an HTTP request to the remote server. :Args: - method - A string for the HTTP method to send the request with. - url - A string for the URL to send the request to. - body - A string for request body. Ignored unless method is POST or PUT. :Returns: A dictionary with the server's parsed JSON response. """ LOGGER.debug('%s %s %s' % (method, url, body)) parsed_url = parse.urlparse(url) if self.keep_alive: headers = {"Connection": 'keep-alive', method: parsed_url.path, "User-Agent": "Python http auth", "Content-type": "application/json;charset=\"UTF-8\"", "Accept": "application/json"} if parsed_url.username: auth = base64.standard_b64encode(('%s:%s' % (parsed_url.username, parsed_url.password)).encode('ascii')).decode('ascii').replace('\n', '') headers["Authorization"] = "Basic %s" % auth if body and method != 'POST' and method != 'PUT': body = None try: self._conn.request(method, parsed_url.path, body, headers) resp = self._conn.getresponse() except (httplib.HTTPException, socket.error): self._conn.close() raise statuscode = resp.status else: password_manager = None if parsed_url.username: netloc = parsed_url.hostname if parsed_url.port: netloc += ":%s" % parsed_url.port cleaned_url = parse.urlunparse((parsed_url.scheme, netloc, parsed_url.path, parsed_url.params, parsed_url.query, parsed_url.fragment)) password_manager = url_request.HTTPPasswordMgrWithDefaultRealm() password_manager.add_password(None, "%s://%s" % (parsed_url.scheme, netloc), parsed_url.username, parsed_url.password) request = Request(cleaned_url, data=body.encode('utf-8'), method=method) else: request = Request(url, data=body.encode('utf-8'), method=method) request.add_header('Accept', 'application/json') request.add_header('Content-Type', 'application/json;charset=UTF-8') if password_manager: opener = url_request.build_opener(url_request.HTTPRedirectHandler(), HttpErrorHandler(), url_request.HTTPBasicAuthHandler(password_manager)) else: opener = url_request.build_opener(url_request.HTTPRedirectHandler(), HttpErrorHandler()) resp = opener.open(request, timeout=self._timeout) statuscode = resp.code if not hasattr(resp, 'getheader'): if hasattr(resp.headers, 'getheader'): resp.getheader = lambda x: resp.headers.getheader(x) elif hasattr(resp.headers, 'get'): resp.getheader = lambda x: resp.headers.get(x) data = resp.read() try: if 300 <= statuscode < 304: return self._request('GET', resp.getheader('location')) body = data.decode('utf-8').replace('\x00', '').strip() if 399 < statuscode < 500: return {'status': statuscode, 'value': body} content_type = [] if resp.getheader('Content-Type') is not None: content_type = resp.getheader('Content-Type').split(';') if not any([x.startswith('image/png') for x in content_type]): try: data = utils.load_json(body.strip()) except ValueError: if 199 < statuscode < 300: status = ErrorCode.SUCCESS else: status = ErrorCode.UNKNOWN_ERROR return {'status': status, 'value': body.strip()} assert type(data) is dict, ( 'Invalid server response body: %s' % body) # Some of the drivers incorrectly return a response # with no 'value' field when they should return null. if 'value' not in data: data['value'] = None return data else: data = {'status': 0, 'value': body.strip()} return data finally: LOGGER.debug("Finished Request") resp.close() selenium-2.48.0/py/selenium/webdriver/remote/switch_to.py0000644000076600000240000000570612556005013024166 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from .command import Command from selenium.webdriver.common.alert import Alert class SwitchTo: def __init__(self, driver): self._driver = driver @property def active_element(self): """ Returns the element with focus, or BODY if nothing has focus. :Usage: element = driver.switch_to.active_element """ return self._driver.execute(Command.GET_ACTIVE_ELEMENT)['value'] @property def alert(self): """ Switches focus to an alert on the page. :Usage: alert = driver.switch_to.alert """ return Alert(self._driver) def default_content(self): """ Switch focus to the default frame. :Usage: driver.switch_to.default_content() """ self._driver.execute(Command.SWITCH_TO_FRAME, {'id': None}) def frame(self, frame_reference): """ Switches focus to the specified frame, by index, name, or webelement. :Args: - frame_reference: The name of the window to switch to, an integer representing the index, or a webelement that is an (i)frame to switch to. :Usage: driver.switch_to.frame('frame_name') driver.switch_to.frame(1) driver.switch_to.frame(driver.find_elements_by_tag_name("iframe")[0]) """ self._driver.execute(Command.SWITCH_TO_FRAME, {'id': frame_reference}) def parent_frame(self): """ Switches focus to the parent context. If the current context is the top level browsing context, the context remains unchanged. :Usage: driver.switch_to.parent_frame() """ self._driver.execute(Command.SWITCH_TO_PARENT_FRAME) def window(self, window_name): """ Switches focus to the specified window. :Args: - window_name: The name or window handle of the window to switch to. :Usage: driver.switch_to.window('main') """ data = {'name': window_name} if self._driver.w3c: data = {'handle': window_name} self._driver.execute(Command.SWITCH_TO_WINDOW, data) selenium-2.48.0/py/selenium/webdriver/remote/utils.py0000644000076600000240000000713712551302002023314 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 json import logging import os import tempfile import zipfile from selenium.common.exceptions import NoSuchElementException LOGGER = logging.getLogger(__name__) def format_json(json_struct): return json.dumps(json_struct, indent=4) def dump_json(json_struct): return json.dumps(json_struct) def load_json(s): return json.loads(s) def handle_find_element_exception(e): if ("Unable to find" in e.response["value"]["message"] or "Unable to locate" in e.response["value"]["message"]): raise NoSuchElementException("Unable to locate element:") else: raise e def return_value_if_exists(resp): if resp and "value" in resp: return resp["value"] def get_root_parent(elem): parent = elem.parent while True: try: parent.parent parent = parent.parent except AttributeError: return parent def unzip_to_temp_dir(zip_file_name): """Unzip zipfile to a temporary directory. The directory of the unzipped files is returned if success, otherwise None is returned. """ if not zip_file_name or not os.path.exists(zip_file_name): return None zf = zipfile.ZipFile(zip_file_name) if zf.testzip() is not None: return None # Unzip the files into a temporary directory LOGGER.info("Extracting zipped file: %s" % zip_file_name) tempdir = tempfile.mkdtemp() try: # Create directories that don't exist for zip_name in zf.namelist(): # We have no knowledge on the os where the zipped file was # created, so we restrict to zip files with paths without # charactor "\" and "/". name = (zip_name.replace("\\", os.path.sep). replace("/", os.path.sep)) dest = os.path.join(tempdir, name) if (name.endswith(os.path.sep) and not os.path.exists(dest)): os.mkdir(dest) LOGGER.debug("Directory %s created." % dest) # Copy files for zip_name in zf.namelist(): # We have no knowledge on the os where the zipped file was # created, so we restrict to zip files with paths without # charactor "\" and "/". name = (zip_name.replace("\\", os.path.sep). replace("/", os.path.sep)) dest = os.path.join(tempdir, name) if not (name.endswith(os.path.sep)): LOGGER.debug("Copying file %s......" % dest) outfile = open(dest, 'wb') outfile.write(zf.read(zip_name)) outfile.close() LOGGER.debug("File %s copied." % dest) LOGGER.info("Unzipped file can be found at %s" % tempdir) return tempdir except IOError as err: LOGGER.error("Error in extracting webdriver.xpi: %s" % err) return None selenium-2.48.0/py/selenium/webdriver/remote/webdriver.py0000755000076600000240000007166712576065613024206 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. """The WebDriver implementation.""" import base64 import warnings from .command import Command from .webelement import WebElement from .remote_connection import RemoteConnection from .errorhandler import ErrorHandler from .switch_to import SwitchTo from .mobile import Mobile from .file_detector import FileDetector, LocalFileDetector from selenium.common.exceptions import WebDriverException from selenium.common.exceptions import InvalidSelectorException from selenium.webdriver.common.by import By from selenium.webdriver.common.html5.application_cache import ApplicationCache try: str = basestring except NameError: pass class WebDriver(object): """ Controls a browser by sending commands to a remote server. This server is expected to be running the WebDriver wire protocol as defined at https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol :Attributes: - session_id - String ID of the browser session started and controlled by this WebDriver. - capabilities - Dictionaty of effective capabilities of this browser session as returned by the remote server. See https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities - command_executor - remote_connection.RemoteConnection object used to execute commands. - error_handler - errorhandler.ErrorHandler object used to handle errors. """ def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities=None, browser_profile=None, proxy=None, keep_alive=False): """ Create a new driver that will issue commands using the wire protocol. :Args: - command_executor - Either a string representing URL of the remote server or a custom remote_connection.RemoteConnection object. Defaults to 'http://127.0.0.1:4444/wd/hub'. - desired_capabilities - A dictionary of capabilities to request when starting the browser session. Required parameter. - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. Optional. - proxy - A selenium.webdriver.common.proxy.Proxy object. The browser session will be started with given proxy settings, if possible. Optional. - keep_alive - Whether to configure remote_connection.RemoteConnection to use HTTP keep-alive. Defaults to False. """ if desired_capabilities is None: raise WebDriverException("Desired Capabilities can't be None") if not isinstance(desired_capabilities, dict): raise WebDriverException("Desired Capabilities must be a dictionary") if proxy is not None: proxy.add_to_capabilities(desired_capabilities) self.command_executor = command_executor if type(self.command_executor) is bytes or isinstance(self.command_executor, str): self.command_executor = RemoteConnection(command_executor, keep_alive=keep_alive) self._is_remote = True self.session_id = None self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() self.start_session(desired_capabilities, browser_profile) self._switch_to = SwitchTo(self) self._mobile = Mobile(self) self.file_detector = LocalFileDetector() def __repr__(self): return '<{0.__module__}.{0.__name__} (session="{1}")>'.format( type(self), self.session_id) @property def mobile(self): return self._mobile @property def name(self): """Returns the name of the underlying browser for this instance. :Usage: - driver.name """ if 'browserName' in self.capabilities: return self.capabilities['browserName'] else: raise KeyError('browserName not specified in session capabilities') def start_client(self): """ Called before starting a new session. This method may be overridden to define custom startup behavior. """ pass def stop_client(self): """ Called after executing a quit command. This method may be overridden to define custom shutdown behavior. """ pass def start_session(self, desired_capabilities, browser_profile=None): """ Creates a new session with the desired capabilities. :Args: - browser_name - The name of the browser to request. - version - Which browser version to request. - platform - Which platform to request the browser on. - javascript_enabled - Whether the new session should support JavaScript. - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. """ if browser_profile: desired_capabilities['firefox_profile'] = browser_profile.encoded response = self.execute(Command.NEW_SESSION, { 'desiredCapabilities': desired_capabilities, }) self.session_id = response['sessionId'] self.capabilities = response['value'] # Quick check to see if we have a W3C Compliant browser self.w3c = "specificationLevel" in self.capabilities def _wrap_value(self, value): if isinstance(value, dict): converted = {} for key, val in value.items(): converted[key] = self._wrap_value(val) return converted elif isinstance(value, WebElement): return {'ELEMENT': value.id, 'element-6066-11e4-a52e-4f735466cecf': value.id} elif isinstance(value, list): return list(self._wrap_value(item) for item in value) else: return value def create_web_element(self, element_id): """ Creates a web element with the specified element_id. """ return WebElement(self, element_id, w3c=self.w3c) def _unwrap_value(self, value): if isinstance(value, dict) and ('ELEMENT' in value or 'element-6066-11e4-a52e-4f735466cecf' in value): wrapped_id = value.get('ELEMENT', None) if wrapped_id: return self.create_web_element(value['ELEMENT']) else: return self.create_web_element(value['element-6066-11e4-a52e-4f735466cecf']) elif isinstance(value, list): return list(self._unwrap_value(item) for item in value) else: return value def execute(self, driver_command, params=None): """ Sends a command to be executed by a command.CommandExecutor. :Args: - driver_command: The name of the command to execute as a string. - params: A dictionary of named parameters to send with the command. :Returns: The command's JSON response loaded into a dictionary object. """ if self.session_id is not None: if not params: params = {'sessionId': self.session_id} elif 'sessionId' not in params: params['sessionId'] = self.session_id params = self._wrap_value(params) response = self.command_executor.execute(driver_command, params) if response: self.error_handler.check_response(response) response['value'] = self._unwrap_value( response.get('value', None)) return response # If the server doesn't send a response, assume the command was # a success return {'success': 0, 'value': None, 'sessionId': self.session_id} def get(self, url): """ Loads a web page in the current browser session. """ self.execute(Command.GET, {'url': url}) @property def title(self): """Returns the title of the current page. :Usage: driver.title """ resp = self.execute(Command.GET_TITLE) return resp['value'] if resp['value'] is not None else "" def find_element_by_id(self, id_): """Finds an element by id. :Args: - id\_ - The id of the element to be found. :Usage: driver.find_element_by_id('foo') """ return self.find_element(by=By.ID, value=id_) def find_elements_by_id(self, id_): """ Finds multiple elements by id. :Args: - id\_ - The id of the elements to be found. :Usage: driver.find_elements_by_id('foo') """ return self.find_elements(by=By.ID, value=id_) def find_element_by_xpath(self, xpath): """ Finds an element by xpath. :Args: - xpath - The xpath locator of the element to find. :Usage: driver.find_element_by_xpath('//div/td[1]') """ return self.find_element(by=By.XPATH, value=xpath) def find_elements_by_xpath(self, xpath): """ Finds multiple elements by xpath. :Args: - xpath - The xpath locator of the elements to be found. :Usage: driver.find_elements_by_xpath("//div[contains(@class, 'foo')]") """ return self.find_elements(by=By.XPATH, value=xpath) def find_element_by_link_text(self, link_text): """ Finds an element by link text. :Args: - link_text: The text of the element to be found. :Usage: driver.find_element_by_link_text('Sign In') """ return self.find_element(by=By.LINK_TEXT, value=link_text) def find_elements_by_link_text(self, text): """ Finds elements by link text. :Args: - link_text: The text of the elements to be found. :Usage: driver.find_elements_by_link_text('Sign In') """ return self.find_elements(by=By.LINK_TEXT, value=text) def find_element_by_partial_link_text(self, link_text): """ Finds an element by a partial match of its link text. :Args: - link_text: The text of the element to partially match on. :Usage: driver.find_element_by_partial_link_text('Sign') """ return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_elements_by_partial_link_text(self, link_text): """ Finds elements by a partial match of their link text. :Args: - link_text: The text of the element to partial match on. :Usage: driver.find_element_by_partial_link_text('Sign') """ return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_element_by_name(self, name): """ Finds an element by name. :Args: - name: The name of the element to find. :Usage: driver.find_element_by_name('foo') """ return self.find_element(by=By.NAME, value=name) def find_elements_by_name(self, name): """ Finds elements by name. :Args: - name: The name of the elements to find. :Usage: driver.find_elements_by_name('foo') """ return self.find_elements(by=By.NAME, value=name) def find_element_by_tag_name(self, name): """ Finds an element by tag name. :Args: - name: The tag name of the element to find. :Usage: driver.find_element_by_tag_name('foo') """ return self.find_element(by=By.TAG_NAME, value=name) def find_elements_by_tag_name(self, name): """ Finds elements by tag name. :Args: - name: The tag name the use when finding elements. :Usage: driver.find_elements_by_tag_name('foo') """ return self.find_elements(by=By.TAG_NAME, value=name) def find_element_by_class_name(self, name): """ Finds an element by class name. :Args: - name: The class name of the element to find. :Usage: driver.find_element_by_class_name('foo') """ return self.find_element(by=By.CLASS_NAME, value=name) def find_elements_by_class_name(self, name): """ Finds elements by class name. :Args: - name: The class name of the elements to find. :Usage: driver.find_elements_by_class_name('foo') """ return self.find_elements(by=By.CLASS_NAME, value=name) def find_element_by_css_selector(self, css_selector): """ Finds an element by css selector. :Args: - css_selector: The css selector to use when finding elements. :Usage: driver.find_element_by_css_selector('#foo') """ return self.find_element(by=By.CSS_SELECTOR, value=css_selector) def find_elements_by_css_selector(self, css_selector): """ Finds elements by css selector. :Args: - css_selector: The css selector to use when finding elements. :Usage: driver.find_elements_by_css_selector('.foo') """ return self.find_elements(by=By.CSS_SELECTOR, value=css_selector) def execute_script(self, script, *args): """ Synchronously Executes JavaScript in the current window/frame. :Args: - script: The JavaScript to execute. - \*args: Any applicable arguments for your JavaScript. :Usage: driver.execute_script('document.title') """ converted_args = list(args) return self.execute(Command.EXECUTE_SCRIPT, {'script': script, 'args':converted_args})['value'] def execute_async_script(self, script, *args): """ Asynchronously Executes JavaScript in the current window/frame. :Args: - script: The JavaScript to execute. - \*args: Any applicable arguments for your JavaScript. :Usage: driver.execute_async_script('document.title') """ converted_args = list(args) return self.execute(Command.EXECUTE_ASYNC_SCRIPT, {'script': script, 'args':converted_args})['value'] @property def current_url(self): """ Gets the URL of the current page. :Usage: driver.current_url """ return self.execute(Command.GET_CURRENT_URL)['value'] @property def page_source(self): """ Gets the source of the current page. :Usage: driver.page_source """ return self.execute(Command.GET_PAGE_SOURCE)['value'] def close(self): """ Closes the current window. :Usage: driver.close() """ self.execute(Command.CLOSE) def quit(self): """ Quits the driver and closes every associated window. :Usage: driver.quit() """ try: self.execute(Command.QUIT) finally: self.stop_client() @property def current_window_handle(self): """ Returns the handle of the current window. :Usage: driver.current_window_handle """ return self.execute(Command.GET_CURRENT_WINDOW_HANDLE)['value'] @property def window_handles(self): """ Returns the handles of all windows within the current session. :Usage: driver.window_handles """ return self.execute(Command.GET_WINDOW_HANDLES)['value'] def maximize_window(self): """ Maximizes the current window that webdriver is using """ command = Command.MAXIMIZE_WINDOW if self.w3c: command = Command.W3C_MAXIMIZE_WINDOW self.execute(command, {"windowHandle": "current"}) @property def switch_to(self): return self._switch_to #Target Locators def switch_to_active_element(self): """ Deprecated use driver.switch_to.active_element """ warnings.warn("use driver.switch_to.active_element instead", DeprecationWarning) return self._switch_to.active_element def switch_to_window(self, window_name): """ Deprecated use driver.switch_to.window """ warnings.warn("use driver.switch_to.window instead", DeprecationWarning) self._switch_to.window(window_name) def switch_to_frame(self, frame_reference): """ Deprecated use driver.switch_to.frame """ warnings.warn("use driver.switch_to.frame instead", DeprecationWarning) self._switch_to.frame(frame_reference) def switch_to_default_content(self): """ Deprecated use driver.switch_to.default_content """ warnings.warn("use driver.switch_to.default_content instead", DeprecationWarning) self._switch_to.default_content() def switch_to_alert(self): """ Deprecated use driver.switch_to.alert """ warnings.warn("use driver.switch_to.alert instead", DeprecationWarning) return self._switch_to.alert #Navigation def back(self): """ Goes one step backward in the browser history. :Usage: driver.back() """ self.execute(Command.GO_BACK) def forward(self): """ Goes one step forward in the browser history. :Usage: driver.forward() """ self.execute(Command.GO_FORWARD) def refresh(self): """ Refreshes the current page. :Usage: driver.refresh() """ self.execute(Command.REFRESH) # Options def get_cookies(self): """ Returns a set of dictionaries, corresponding to cookies visible in the current session. :Usage: driver.get_cookies() """ return self.execute(Command.GET_ALL_COOKIES)['value'] def get_cookie(self, name): """ Get a single cookie by name. Returns the cookie if found, None if not. :Usage: driver.get_cookie('my_cookie') """ cookies = self.get_cookies() for cookie in cookies: if cookie['name'] == name: return cookie return None def delete_cookie(self, name): """ Deletes a single cookie with the given name. :Usage: driver.delete_cookie('my_cookie') """ self.execute(Command.DELETE_COOKIE, {'name': name}) def delete_all_cookies(self): """ Delete all cookies in the scope of the session. :Usage: driver.delete_all_cookies() """ self.execute(Command.DELETE_ALL_COOKIES) def add_cookie(self, cookie_dict): """ Adds a cookie to your current session. :Args: - cookie_dict: A dictionary object, with required keys - "name" and "value"; optional keys - "path", "domain", "secure", "expiry" Usage: driver.add_cookie({'name' : 'foo', 'value' : 'bar'}) driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/'}) driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/', 'secure':True}) """ self.execute(Command.ADD_COOKIE, {'cookie': cookie_dict}) # Timeouts def implicitly_wait(self, time_to_wait): """ Sets a sticky timeout to implicitly wait for an element to be found, or a command to complete. This method only needs to be called one time per session. To set the timeout for calls to execute_async_script, see set_script_timeout. :Args: - time_to_wait: Amount of time to wait (in seconds) :Usage: driver.implicitly_wait(30) """ if self.w3c: self.execute(Command.SET_TIMEOUTS, {'ms': float(time_to_wait) * 1000, 'type':'implicit'}) else: self.execute(Command.IMPLICIT_WAIT, {'ms': float(time_to_wait) * 1000}) def set_script_timeout(self, time_to_wait): """ Set the amount of time that the script should wait during an execute_async_script call before throwing an error. :Args: - time_to_wait: The amount of time to wait (in seconds) :Usage: driver.set_script_timeout(30) """ if self.w3c: self.execute(Command.SET_TIMEOUTS, {'ms': float(time_to_wait) * 1000, 'type':'script'}) else: self.execute(Command.SET_SCRIPT_TIMEOUT, {'ms': float(time_to_wait) * 1000}) def set_page_load_timeout(self, time_to_wait): """ Set the amount of time to wait for a page load to complete before throwing an error. :Args: - time_to_wait: The amount of time to wait :Usage: driver.set_page_load_timeout(30) """ self.execute(Command.SET_TIMEOUTS, {'ms': float(time_to_wait) * 1000, 'type':'page load'}) def find_element(self, by=By.ID, value=None): """ 'Private' method used by the find_element_by_* methods. :Usage: Use the corresponding find_element_by_* instead of this. :rtype: WebElement """ if not By.is_valid(by) or not isinstance(value, str): raise InvalidSelectorException("Invalid locator values passed in") if self.w3c: if by == By.ID: by = By.CSS_SELECTOR value = '[id="%s"]' % value elif by == By.TAG_NAME: by = By.CSS_SELECTOR elif by == By.CLASS_NAME: by = By.CSS_SELECTOR value = ".%s" % value elif by == By.NAME: by = By.CSS_SELECTOR value = '[name="%s"]' % value return self.execute(Command.FIND_ELEMENT, {'using': by, 'value': value})['value'] def find_elements(self, by=By.ID, value=None): """ 'Private' method used by the find_elements_by_* methods. :Usage: Use the corresponding find_elements_by_* instead of this. :rtype: list of WebElement """ if not By.is_valid(by) or not isinstance(value, str): raise InvalidSelectorException("Invalid locator values passed in") if self.w3c: if by == By.ID: by = By.CSS_SELECTOR value = '[id="%s"]' % value elif by == By.TAG_NAME: by = By.CSS_SELECTOR elif by == By.CLASS_NAME: by = By.CSS_SELECTOR value = ".%s" % value elif by == By.NAME: by = By.CSS_SELECTOR value = '[name="%s"]' % value return self.execute(Command.FIND_ELEMENTS, {'using': by, 'value': value})['value'] @property def desired_capabilities(self): """ returns the drivers current desired capabilities being used """ return self.capabilities def get_screenshot_as_file(self, filename): """ Gets the screenshot of the current window. Returns False if there is any IOError, else returns True. Use full paths in your filename. :Args: - filename: The full path you wish to save your screenshot to. :Usage: driver.get_screenshot_as_file('/Screenshots/foo.png') """ png = self.get_screenshot_as_png() try: with open(filename, 'wb') as f: f.write(png) except IOError: return False finally: del png return True save_screenshot = get_screenshot_as_file def get_screenshot_as_png(self): """ Gets the screenshot of the current window as a binary data. :Usage: driver.get_screenshot_as_png() """ return base64.b64decode(self.get_screenshot_as_base64().encode('ascii')) def get_screenshot_as_base64(self): """ Gets the screenshot of the current window as a base64 encoded string which is useful in embedded images in HTML. :Usage: driver.get_screenshot_as_base64() """ return self.execute(Command.SCREENSHOT)['value'] def set_window_size(self, width, height, windowHandle='current'): """ Sets the width and height of the current window. (window.resizeTo) :Args: - width: the width in pixels to set the window to - height: the height in pixels to set the window to :Usage: driver.set_window_size(800,600) """ command = Command.SET_WINDOW_SIZE if self.w3c: command = Command.W3C_SET_WINDOW_SIZE self.execute(command, {'width': int(width), 'height': int(height), 'windowHandle': windowHandle}) def get_window_size(self, windowHandle='current'): """ Gets the width and height of the current window. :Usage: driver.get_window_size() """ command = Command.GET_WINDOW_SIZE if self.w3c: command = Command.W3C_GET_WINDOW_SIZE size = self.execute(command, {'windowHandle': windowHandle}) if size.get('value', None) != None: return size['value'] else: return size def set_window_position(self, x, y, windowHandle='current'): """ Sets the x,y position of the current window. (window.moveTo) :Args: - x: the x-coordinate in pixels to set the window position - y: the y-coordinate in pixels to set the window position :Usage: driver.set_window_position(0,0) """ self.execute(Command.SET_WINDOW_POSITION, {'x': int(x), 'y': int(y), 'windowHandle': windowHandle}) def get_window_position(self, windowHandle='current'): """ Gets the x,y position of the current window. :Usage: driver.get_window_position() """ return self.execute(Command.GET_WINDOW_POSITION, {'windowHandle': windowHandle})['value'] @property def file_detector(self): return self._file_detector @file_detector.setter def file_detector(self, detector): """ Set the file detector to be used when sending keyboard input. By default, this is set to a file detector that does nothing. see FileDetector see LocalFileDetector see UselessFileDetector :Args: - detector: The detector to use. Must not be None. """ if detector == None: raise WebDriverException("You may not set a file detector that is null") if not isinstance(detector, FileDetector): raise WebDriverException("Detector has to be instance of FileDetector") self._file_detector = detector; @property def orientation(self): """ Gets the current orientation of the device :Usage: orientation = driver.orientation """ return self.execute(Command.GET_SCREEN_ORIENTATION)['value'] @orientation.setter def orientation(self, value): """ Sets the current orientation of the device :Args: - value: orientation to set it to. :Usage: driver.orientation = 'landscape' """ allowed_values = ['LANDSCAPE', 'PORTRAIT'] if value.upper() in allowed_values: self.execute(Command.SET_SCREEN_ORIENTATION, {'orientation': value}) else: raise WebDriverException("You can only set the orientation to 'LANDSCAPE' and 'PORTRAIT'") @property def application_cache(self): """ Returns a ApplicationCache Object to interact with the browser app cache""" return ApplicationCache(self) @property def log_types(self): """ Gets a list of the available log types :Usage: driver.log_types """ return self.execute(Command.GET_AVAILABLE_LOG_TYPES)['value'] def get_log(self, log_type): """ Gets the log for a given log type :Args: - log_type: type of log that which will be returned :Usage: driver.get_log('browser') driver.get_log('driver') driver.get_log('client') driver.get_log('server') """ return self.execute(Command.GET_LOG, {'type': log_type})['value'] selenium-2.48.0/py/selenium/webdriver/remote/webelement.py0000755000076600000240000004210612604564544024325 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 hashlib from numbers import Number import os import zipfile try: from StringIO import StringIO as IOStream except ImportError: # 3+ from io import BytesIO as IOStream import base64 from .command import Command from selenium.common.exceptions import WebDriverException from selenium.common.exceptions import InvalidSelectorException from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys try: str = basestring except NameError: pass class WebElement(object): """Represents a DOM element. Generally, all interesting operations that interact with a document will be performed through this interface. All method calls will do a freshness check to ensure that the element reference is still valid. This essentially determines whether or not the element is still attached to the DOM. If this test fails, then an ``StaleElementReferenceException`` is thrown, and all future calls to this instance will fail.""" def __init__(self, parent, id_, w3c=False): self._parent = parent self._id = id_ self._w3c = w3c def __repr__(self): return '<{0.__module__}.{0.__name__} (session="{1}", element="{2}")>'.format( type(self), self._parent.session_id, self._id) @property def tag_name(self): """This element's ``tagName`` property.""" return self._execute(Command.GET_ELEMENT_TAG_NAME)['value'] @property def text(self): """The text of the element.""" return self._execute(Command.GET_ELEMENT_TEXT)['value'] def click(self): """Clicks the element.""" self._execute(Command.CLICK_ELEMENT) def submit(self): """Submits a form.""" self._execute(Command.SUBMIT_ELEMENT) def clear(self): """Clears the text if it's a text entry element.""" self._execute(Command.CLEAR_ELEMENT) def get_attribute(self, name): """Gets the given attribute or property of the element. This method will first try to return the value of a property with the given name. If a property with that name doesn't exist, it returns the value of the attribute with the same name. If there's no attribute with that name, ``None`` is returned. Values which are considered truthy, that is equals "true" or "false", are returned as booleans. All other non-``None`` values are returned as strings. For attributes or properties which do not exist, ``None`` is returned. :Args: - name - Name of the attribute/property to retrieve. Example:: # Check if the "active" CSS class is applied to an element. is_active = "active" in target_element.get_attribute("class") """ resp = self._execute(Command.GET_ELEMENT_ATTRIBUTE, {'name': name}) attributeValue = '' if resp['value'] is None: attributeValue = None else: attributeValue = resp['value'] if name != 'value' and attributeValue.lower() in ('true', 'false'): attributeValue = attributeValue.lower() return attributeValue def is_selected(self): """Returns whether the element is selected. Can be used to check if a checkbox or radio button is selected. """ return self._execute(Command.IS_ELEMENT_SELECTED)['value'] def is_enabled(self): """Returns whether the element is enabled.""" return self._execute(Command.IS_ELEMENT_ENABLED)['value'] def find_element_by_id(self, id_): """Finds element within this element's children by ID. :Args: - id_ - ID of child element to locate. """ return self.find_element(by=By.ID, value=id_) def find_elements_by_id(self, id_): """Finds a list of elements within this element's children by ID. :Args: - id_ - Id of child element to find. """ return self.find_elements(by=By.ID, value=id_) def find_element_by_name(self, name): """Finds element within this element's children by name. :Args: - name - name property of the element to find. """ return self.find_element(by=By.NAME, value=name) def find_elements_by_name(self, name): """Finds a list of elements within this element's children by name. :Args: - name - name property to search for. """ return self.find_elements(by=By.NAME, value=name) def find_element_by_link_text(self, link_text): """Finds element within this element's children by visible link text. :Args: - link_text - Link text string to search for. """ return self.find_element(by=By.LINK_TEXT, value=link_text) def find_elements_by_link_text(self, link_text): """Finds a list of elements within this element's children by visible link text. :Args: - link_text - Link text string to search for. """ return self.find_elements(by=By.LINK_TEXT, value=link_text) def find_element_by_partial_link_text(self, link_text): """Finds element within this element's children by partially visible link text. :Args: - link_text - Link text string to search for. """ return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_elements_by_partial_link_text(self, link_text): """Finds a list of elements within this element's children by link text. :Args: - link_text - Link text string to search for. """ return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_element_by_tag_name(self, name): """Finds element within this element's children by tag name. :Args: - name - name of html tag (eg: h1, a, span) """ return self.find_element(by=By.TAG_NAME, value=name) def find_elements_by_tag_name(self, name): """Finds a list of elements within this element's children by tag name. :Args: - name - name of html tag (eg: h1, a, span) """ return self.find_elements(by=By.TAG_NAME, value=name) def find_element_by_xpath(self, xpath): """Finds element by xpath. :Args: xpath - xpath of element to locate. "//input[@class='myelement']" Note: The base path will be relative to this element's location. This will select the first link under this element. :: myelement.find_elements_by_xpath(".//a") However, this will select the first link on the page. :: myelement.find_elements_by_xpath("//a") """ return self.find_element(by=By.XPATH, value=xpath) def find_elements_by_xpath(self, xpath): """Finds elements within the element by xpath. :Args: - xpath - xpath locator string. Note: The base path will be relative to this element's location. This will select all links under this element. :: myelement.find_elements_by_xpath(".//a") However, this will select all links in the page itself. :: myelement.find_elements_by_xpath("//a") """ return self.find_elements(by=By.XPATH, value=xpath) def find_element_by_class_name(self, name): """Finds element within this element's children by class name. :Args: - name - class name to search for. """ return self.find_element(by=By.CLASS_NAME, value=name) def find_elements_by_class_name(self, name): """Finds a list of elements within this element's children by class name. :Args: - name - class name to search for. """ return self.find_elements(by=By.CLASS_NAME, value=name) def find_element_by_css_selector(self, css_selector): """Finds element within this element's children by CSS selector. :Args: - css_selector - CSS selctor string, ex: 'a.nav#home' """ return self.find_element(by=By.CSS_SELECTOR, value=css_selector) def find_elements_by_css_selector(self, css_selector): """Finds a list of elements within this element's children by CSS selector. :Args: - css_selector - CSS selctor string, ex: 'a.nav#home' """ return self.find_elements(by=By.CSS_SELECTOR, value=css_selector) def send_keys(self, *value): """Simulates typing into the element. :Args: - value - A string for typing, or setting form fields. For setting file inputs, this could be a local file path. Use this to send simple key events or to fill out form fields:: form_textfield = driver.find_element_by_name('username') form_textfield.send_keys("admin") This can also be used to set file inputs. :: file_input = driver.find_element_by_name('profilePic') file_input.send_keys("path/to/profilepic.gif") # Generally it's better to wrap the file path in one of the methods # in os.path to return the actual path to support cross OS testing. # file_input.send_keys(os.path.abspath("path/to/profilepic.gif")) """ # transfer file to another machine only if remote driver is used # the same behaviour as for java binding if self.parent._is_remote: local_file = self.parent.file_detector.is_local_file(*value) if local_file is not None: value = self._upload(local_file) typing = [] for val in value: if isinstance(val, Keys): typing.append(val) elif isinstance(val, Number): val = val.__str__() for i in range(len(val)): typing.append(val[i]) else: for i in range(len(val)): typing.append(val[i]) self._execute(Command.SEND_KEYS_TO_ELEMENT, {'value': typing}) # RenderedWebElement Items def is_displayed(self): """Whether the element is visible to a user.""" return self._execute(Command.IS_ELEMENT_DISPLAYED)['value'] @property def location_once_scrolled_into_view(self): """THIS PROPERTY MAY CHANGE WITHOUT WARNING. Use this to discover where on the screen an element is so that we can click it. This method should cause the element to be scrolled into view. Returns the top lefthand corner location on the screen, or ``None`` if the element is not visible. """ return self._execute(Command.GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW)['value'] @property def size(self): """The size of the element.""" size = self._execute(Command.GET_ELEMENT_SIZE)['value'] new_size = {} new_size["height"] = size["height"] new_size["width"] = size["width"] return new_size def value_of_css_property(self, property_name): """The value of a CSS property.""" return self._execute(Command.GET_ELEMENT_VALUE_OF_CSS_PROPERTY, {'propertyName': property_name})['value'] @property def location(self): """The location of the element in the renderable canvas.""" old_loc = self._execute(Command.GET_ELEMENT_LOCATION)['value'] new_loc = {"x": old_loc['x'], "y": old_loc['y']} return new_loc @property def rect(self): """A dictionary with the size and location of the element.""" return self._execute(Command.GET_ELEMENT_RECT)['value'] @property def screenshot_as_base64(self): """ Gets the screenshot of the current element as a base64 encoded string. :Usage: img_b64 = element.screenshot_as_base64 """ return self._execute(Command.ELEMENT_SCREENSHOT)['value'] @property def screenshot_as_png(self): """ Gets the screenshot of the current element as a binary data. :Usage: element_png = element.screenshot_as_png """ return base64.b64decode(self.screenshot_as_base64.encode('ascii')) def screenshot(self, filename): """ Gets the screenshot of the current element. Returns False if there is any IOError, else returns True. Use full paths in your filename. :Args: - filename: The full path you wish to save your screenshot to. :Usage: element.screenshot('/Screenshots/foo.png') """ png = self.screenshot_as_png try: with open(filename, 'wb') as f: f.write(png) except IOError: return False finally: del png return True @property def parent(self): """Internal reference to the WebDriver instance this element was found from.""" return self._parent @property def id(self): """Internal ID used by selenium. This is mainly for internal use. Simple use cases such as checking if 2 webelements refer to the same element, can be done using ``==``:: if element1 == element2: print("These 2 are equal") """ return self._id def __eq__(self, element): return hasattr(element, 'id') and self._id == element.id def __ne__(self, element): return not self.__eq__(element) # Private Methods def _execute(self, command, params=None): """Executes a command against the underlying HTML element. Args: command: The name of the command to _execute as a string. params: A dictionary of named parameters to send with the command. Returns: The command's JSON response loaded into a dictionary object. """ if not params: params = {} params['id'] = self._id return self._parent.execute(command, params) def find_element(self, by=By.ID, value=None): if not By.is_valid(by) or not isinstance(value, str): raise InvalidSelectorException("Invalid locator values passed in") if self._w3c: if by == By.ID: by = By.CSS_SELECTOR value = '[id="%s"]' % value elif by == By.TAG_NAME: by = By.CSS_SELECTOR elif by == By.CLASS_NAME: by = By.CSS_SELECTOR value = ".%s" % value elif by == By.NAME: by = By.CSS_SELECTOR value = '[name="%s"]' % value return self._execute(Command.FIND_CHILD_ELEMENT, {"using": by, "value": value})['value'] def find_elements(self, by=By.ID, value=None): if not By.is_valid(by) or not isinstance(value, str): raise InvalidSelectorException("Invalid locator values passed in") if self._w3c: if by == By.ID: by = By.CSS_SELECTOR value = '[id="%s"]' % value elif by == By.TAG_NAME: by = By.CSS_SELECTOR elif by == By.CLASS_NAME: by = By.CSS_SELECTOR value = ".%s" % value elif by == By.NAME: by = By.CSS_SELECTOR value = '[name="%s"]' % value return self._execute(Command.FIND_CHILD_ELEMENTS, {"using": by, "value": value})['value'] def __hash__(self): return int(hashlib.md5(self._id.encode('utf-8')).hexdigest(), 16) def _upload(self, filename): fp = IOStream() zipped = zipfile.ZipFile(fp, 'w', zipfile.ZIP_DEFLATED) zipped.write(filename, os.path.split(filename)[1]) zipped.close() content = base64.encodestring(fp.getvalue()) if not isinstance(content, str): content = content.decode('utf-8') try: return self._execute(Command.UPLOAD_FILE, {'file': content})['value'] except WebDriverException as e: if "Unrecognized command: POST" in e.__str__(): return filename elif "Command not found: POST " in e.__str__(): return filename elif '{"status":405,"value":["GET","HEAD","DELETE"]}' in e.__str__(): return filename else: raise e selenium-2.48.0/py/selenium/webdriver/safari/0000755000076600000240000000000012605237755021572 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/safari/__init__.py0000644000076600000240000000142312551302002023655 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/safari/service.py0000644000076600000240000000547712551302002023573 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from os import devnull import subprocess from subprocess import PIPE 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 the SafariDriver """ def __init__(self, executable_path, port=0, quiet=False): """ Creates a new instance of the Service :Args: - executable_path : Path to the SafariDriver - port : Port the service is running on """ self.port = port self.path = executable_path if self.port == 0: self.port = utils.free_port() self.quiet = quiet def start(self): """ Starts the SafariDriver Service. :Exceptions: - WebDriverException : Raised either when it can't start the service or when it can't connect to the service """ kwargs = dict() if self.quiet: devnull_out = open(devnull, 'w') kwargs.update(stdout=devnull_out, stderr=devnull_out) try: self.process = subprocess.Popen(["java", "-jar", self.path, "-port", "%s" % self.port], **kwargs) except: raise WebDriverException( "SafariDriver executable needs to be available in the path.") time.sleep(10) count = 0 while not utils.is_connectable(self.port): count += 1 time.sleep(1) if count == 30: raise WebDriverException("Can not connect to the SafariDriver") @property def service_url(self): """ Gets the url of the SafariDriver Service """ return "http://localhost:%d/wd/hub" % self.port def stop(self): """ Tells the SafariDriver to stop and cleans up the process """ # If it's dead don't worry if self.process is None: return self.process.kill() self.process.wait() selenium-2.48.0/py/selenium/webdriver/safari/webdriver.py0000644000076600000240000000536212551302002024115 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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 try: import http.client as http_client except ImportError: import httplib as http_client import os from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver from .service import Service class WebDriver(RemoteWebDriver): """ Controls the SafariDriver and allows you to drive the browser. """ def __init__(self, executable_path=None, port=0, desired_capabilities=DesiredCapabilities.SAFARI, quiet=False): """ Creates a new instance of the Safari driver. Starts the service and then creates new instance of Safari Driver. :Args: - executable_path - path to the executable. If the default is used it assumes the executable is in the Environment Variable SELENIUM_SERVER_JAR - port - port you would like the service to run, if left as 0, a free port will be found. - desired_capabilities: Dictionary object with desired capabilities (Can be used to provide various Safari switches). """ if executable_path is None: try: executable_path = os.environ["SELENIUM_SERVER_JAR"] except: raise Exception("No executable path given, please add one to Environment Variable \ 'SELENIUM_SERVER_JAR'") self.service = Service(executable_path, port=port, quiet=quiet) self.service.start() RemoteWebDriver.__init__(self, command_executor=self.service.service_url, desired_capabilities=desired_capabilities) self._is_remote = False def quit(self): """ Closes the browser and shuts down the SafariDriver executable that is started when starting the SafariDriver """ try: RemoteWebDriver.quit(self) except http_client.BadStatusLine: pass finally: self.service.stop() selenium-2.48.0/py/selenium/webdriver/support/0000755000076600000240000000000012605237755022041 5ustar dburnsstaff00000000000000selenium-2.48.0/py/selenium/webdriver/support/__init__.py0000644000076600000240000000142412551302002024125 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. selenium-2.48.0/py/selenium/webdriver/support/abstract_event_listener.py0000644000076600000240000000371312551302002027302 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. class AbstractEventListener(object): """ Event listener must subclass and implement this fully or partially """ def before_navigate_to(self, url, driver): pass def after_navigate_to(self, url, driver): pass def before_navigate_back(self, driver): pass def after_navigate_back(self, driver): pass def before_navigate_forward(self, driver): pass def after_navigate_forward(self, driver): pass def before_find(self, by, value, driver): pass def after_find(self, by, value, driver): pass def before_click(self, element, driver): pass def after_click(self, element, driver): pass def before_change_value_of(self, element, driver): pass def after_change_value_of(self, element, driver): pass def before_execute_script(self, script, driver): pass def after_execute_script(self, script, driver): pass def before_close(self, driver): pass def after_close(self, driver): pass def before_quit(self, driver): pass def after_quit(self, driver): pass def on_exception(self, exception, driver): pass selenium-2.48.0/py/selenium/webdriver/support/color.py0000644000076600000240000002620712551302002023512 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. RGB_PATTERN = r"^\s*rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)\s*$" RGB_PCT_PATTERN = r"^\s*rgb\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*\)\s*$" RGBA_PATTERN = r"^\s*rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|1|0\.\d+)\s*\)\s*$" RGBA_PCT_PATTERN = r"^\s*rgba\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(0|1|0\.\d+)\s*\)\s*$" HEX_PATTERN = r"#([A-Fa-f0-9]{2})([A-Fa-f0-9]{2})([A-Fa-f0-9]{2})" HEX3_PATTERN = r"#([A-Fa-f0-9])([A-Fa-f0-9])([A-Fa-f0-9])" HSL_PATTERN = r"^\s*hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)\s*$" HSLA_PATTERN = r"^\s*hsla\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*(0|1|0\.\d+)\s*\)\s*$" class Color(object): """ Color conversion support class Example: .. code-block:: python from selenium.webdriver.support.color import Color print(Color.from_string('#00ff33').rgba) print(Color.from_string('rgb(1, 255, 3)').hex) print(Color.from_string('blue').rgba) """ @staticmethod def from_string(str_): import re class Matcher(object): def __init__(self): self.match_obj = None def match(self, pattern, str_): self.match_obj = re.match(pattern, str_) return self.match_obj @property def groups(self): return () if self.match_obj is None else self.match_obj.groups() m = Matcher() if m.match(RGB_PATTERN, str_): return Color(*m.groups) elif m.match(RGB_PCT_PATTERN, str_): rgb = tuple([float(each) / 100 * 255 for each in m.groups]) return Color(*rgb) elif m.match(RGBA_PATTERN, str_): return Color(*m.groups) elif m.match(RGBA_PCT_PATTERN, str_): rgba = tuple([float(each) / 100 * 255 for each in m.groups[:3]] + [m.groups[3]]) return Color(*rgba) elif m.match(HEX_PATTERN, str_): rgb = tuple([int(each, 16) for each in m.groups]) return Color(*rgb) elif m.match(HEX3_PATTERN, str_): rgb = tuple([int(each * 2, 16) for each in m.groups]) return Color(*rgb) elif m.match(HSL_PATTERN, str_) or m.match(HSLA_PATTERN, str_): return Color._from_hsl(*m.groups) elif str_.upper() in Colors.keys(): return Colors[str_.upper()] else: raise ValueError("Could not convert %s into color" % str_) @staticmethod def _from_hsl(h, s, l, a=1): h = float(h) / 360 s = float(s) / 100 l = float(l) / 100 if s == 0: r = l g = r b = r else: luminocity2 = l * (1 + s) if l < 0.5 else l + s - l * s luminocity1 = 2 * l - luminocity2 def hue_to_rgb(lum1, lum2, hue): if hue < 0.0: hue += 1 if hue > 1.0: hue -= 1 if hue < 1.0 / 6.0: return (lum1 + (lum2 - lum1) * 6.0 * hue) elif hue < 1.0 / 2.0: return lum2 elif hue < 2.0 / 3.0: return lum1 + (lum2 - lum1) * ((2.0 / 3.0) - hue) * 6.0 else: return lum1 r = hue_to_rgb(luminocity1, luminocity2, h + 1.0 / 3.0) g = hue_to_rgb(luminocity1, luminocity2, h) b = hue_to_rgb(luminocity1, luminocity2, h - 1.0 / 3.0) return Color(round(r * 255), round(g * 255), round(b * 255), a) def __init__(self, red, green, blue, alpha=1): self.red = int(red) self.green = int(green) self.blue = int(blue) self.alpha = "1" if float(alpha) == 1 else str(float(alpha) or 0) @property def rgb(self): return "rgb(%d, %d, %d)" % (self.red, self.green, self.blue) @property def rgba(self): return "rgba(%d, %d, %d, %s)" % (self.red, self.green, self.blue, self.alpha) @property def hex(self): return "#%02x%02x%02x" % (self.red, self.green, self.blue) def __eq__(self, other): if isinstance(other, Color): return self.rgba == other.rgba return NotImplemented def __ne__(self, other): result = self.__eq__(other) if result is NotImplemented: return result return not result def __hash__(self): return hash((self.red, self.green, self.blue, self.alpha)) def __repr__(self): return "Color(red=%d, green=%d, blue=%d, alpha=%s)" % (self.red, self.green, self.blue, self.alpha) def __str__(self): return "Color: %s" % self.rgba # Basic, extended and transparent colour keywords as defined by the W3C HTML4 spec # See http://www.w3.org/TR/css3-color/#html4 Colors = { "TRANSPARENT": Color(0, 0, 0, 0), "ALICEBLUE": Color(240, 248, 255), "ANTIQUEWHITE": Color(250, 235, 215), "AQUA": Color(0, 255, 255), "AQUAMARINE": Color(127, 255, 212), "AZURE": Color(240, 255, 255), "BEIGE": Color(245, 245, 220), "BISQUE": Color(255, 228, 196), "BLACK": Color(0, 0, 0), "BLANCHEDALMOND": Color(255, 235, 205), "BLUE": Color(0, 0, 255), "BLUEVIOLET": Color(138, 43, 226), "BROWN": Color(165, 42, 42), "BURLYWOOD": Color(222, 184, 135), "CADETBLUE": Color(95, 158, 160), "CHARTREUSE": Color(127, 255, 0), "CHOCOLATE": Color(210, 105, 30), "CORAL": Color(255, 127, 80), "CORNFLOWERBLUE": Color(100, 149, 237), "CORNSILK": Color(255, 248, 220), "CRIMSON": Color(220, 20, 60), "CYAN": Color(0, 255, 255), "DARKBLUE": Color(0, 0, 139), "DARKCYAN": Color(0, 139, 139), "DARKGOLDENROD": Color(184, 134, 11), "DARKGRAY": Color(169, 169, 169), "DARKGREEN": Color(0, 100, 0), "DARKGREY": Color(169, 169, 169), "DARKKHAKI": Color(189, 183, 107), "DARKMAGENTA": Color(139, 0, 139), "DARKOLIVEGREEN": Color(85, 107, 47), "DARKORANGE": Color(255, 140, 0), "DARKORCHID": Color(153, 50, 204), "DARKRED": Color(139, 0, 0), "DARKSALMON": Color(233, 150, 122), "DARKSEAGREEN": Color(143, 188, 143), "DARKSLATEBLUE": Color(72, 61, 139), "DARKSLATEGRAY": Color(47, 79, 79), "DARKSLATEGREY": Color(47, 79, 79), "DARKTURQUOISE": Color(0, 206, 209), "DARKVIOLET": Color(148, 0, 211), "DEEPPINK": Color(255, 20, 147), "DEEPSKYBLUE": Color(0, 191, 255), "DIMGRAY": Color(105, 105, 105), "DIMGREY": Color(105, 105, 105), "DODGERBLUE": Color(30, 144, 255), "FIREBRICK": Color(178, 34, 34), "FLORALWHITE": Color(255, 250, 240), "FORESTGREEN": Color(34, 139, 34), "FUCHSIA": Color(255, 0, 255), "GAINSBORO": Color(220, 220, 220), "GHOSTWHITE": Color(248, 248, 255), "GOLD": Color(255, 215, 0), "GOLDENROD": Color(218, 165, 32), "GRAY": Color(128, 128, 128), "GREY": Color(128, 128, 128), "GREEN": Color(0, 128, 0), "GREENYELLOW": Color(173, 255, 47), "HONEYDEW": Color(240, 255, 240), "HOTPINK": Color(255, 105, 180), "INDIANRED": Color(205, 92, 92), "INDIGO": Color(75, 0, 130), "IVORY": Color(255, 255, 240), "KHAKI": Color(240, 230, 140), "LAVENDER": Color(230, 230, 250), "LAVENDERBLUSH": Color(255, 240, 245), "LAWNGREEN": Color(124, 252, 0), "LEMONCHIFFON": Color(255, 250, 205), "LIGHTBLUE": Color(173, 216, 230), "LIGHTCORAL": Color(240, 128, 128), "LIGHTCYAN": Color(224, 255, 255), "LIGHTGOLDENRODYELLOW": Color(250, 250, 210), "LIGHTGRAY": Color(211, 211, 211), "LIGHTGREEN": Color(144, 238, 144), "LIGHTGREY": Color(211, 211, 211), "LIGHTPINK": Color(255, 182, 193), "LIGHTSALMON": Color(255, 160, 122), "LIGHTSEAGREEN": Color(32, 178, 170), "LIGHTSKYBLUE": Color(135, 206, 250), "LIGHTSLATEGRAY": Color(119, 136, 153), "LIGHTSLATEGREY": Color(119, 136, 153), "LIGHTSTEELBLUE": Color(176, 196, 222), "LIGHTYELLOW": Color(255, 255, 224), "LIME": Color(0, 255, 0), "LIMEGREEN": Color(50, 205, 50), "LINEN": Color(250, 240, 230), "MAGENTA": Color(255, 0, 255), "MAROON": Color(128, 0, 0), "MEDIUMAQUAMARINE": Color(102, 205, 170), "MEDIUMBLUE": Color(0, 0, 205), "MEDIUMORCHID": Color(186, 85, 211), "MEDIUMPURPLE": Color(147, 112, 219), "MEDIUMSEAGREEN": Color(60, 179, 113), "MEDIUMSLATEBLUE": Color(123, 104, 238), "MEDIUMSPRINGGREEN": Color(0, 250, 154), "MEDIUMTURQUOISE": Color(72, 209, 204), "MEDIUMVIOLETRED": Color(199, 21, 133), "MIDNIGHTBLUE": Color(25, 25, 112), "MINTCREAM": Color(245, 255, 250), "MISTYROSE": Color(255, 228, 225), "MOCCASIN": Color(255, 228, 181), "NAVAJOWHITE": Color(255, 222, 173), "NAVY": Color(0, 0, 128), "OLDLACE": Color(253, 245, 230), "OLIVE": Color(128, 128, 0), "OLIVEDRAB": Color(107, 142, 35), "ORANGE": Color(255, 165, 0), "ORANGERED": Color(255, 69, 0), "ORCHID": Color(218, 112, 214), "PALEGOLDENROD": Color(238, 232, 170), "PALEGREEN": Color(152, 251, 152), "PALETURQUOISE": Color(175, 238, 238), "PALEVIOLETRED": Color(219, 112, 147), "PAPAYAWHIP": Color(255, 239, 213), "PEACHPUFF": Color(255, 218, 185), "PERU": Color(205, 133, 63), "PINK": Color(255, 192, 203), "PLUM": Color(221, 160, 221), "POWDERBLUE": Color(176, 224, 230), "PURPLE": Color(128, 0, 128), "REBECCAPURPLE": Color(128, 51, 153), "RED": Color(255, 0, 0), "ROSYBROWN": Color(188, 143, 143), "ROYALBLUE": Color(65, 105, 225), "SADDLEBROWN": Color(139, 69, 19), "SALMON": Color(250, 128, 114), "SANDYBROWN": Color(244, 164, 96), "SEAGREEN": Color(46, 139, 87), "SEASHELL": Color(255, 245, 238), "SIENNA": Color(160, 82, 45), "SILVER": Color(192, 192, 192), "SKYBLUE": Color(135, 206, 235), "SLATEBLUE": Color(106, 90, 205), "SLATEGRAY": Color(112, 128, 144), "SLATEGREY": Color(112, 128, 144), "SNOW": Color(255, 250, 250), "SPRINGGREEN": Color(0, 255, 127), "STEELBLUE": Color(70, 130, 180), "TAN": Color(210, 180, 140), "TEAL": Color(0, 128, 128), "THISTLE": Color(216, 191, 216), "TOMATO": Color(255, 99, 71), "TURQUOISE": Color(64, 224, 208), "VIOLET": Color(238, 130, 238), "WHEAT": Color(245, 222, 179), "WHITE": Color(255, 255, 255), "WHITESMOKE": Color(245, 245, 245), "YELLOW": Color(255, 255, 0), "YELLOWGREEN": Color(154, 205, 50) } selenium-2.48.0/py/selenium/webdriver/support/event_firing_webdriver.py0000644000076600000240000003132312551302002027117 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from selenium.common.exceptions import WebDriverException from selenium.webdriver.common.by import By from selenium.webdriver.remote.webdriver import WebDriver from selenium.webdriver.remote.webelement import WebElement from .abstract_event_listener import AbstractEventListener def _wrap_elements(result, ef_driver): if isinstance(result, WebElement): return EventFiringWebElement(result, ef_driver) elif isinstance(result, list): return [_wrap_elements(item, ef_driver) for item in result] else: return result class EventFiringWebDriver(object): """ A wrapper around an arbitrary WebDriver instance which supports firing events """ def __init__(self, driver, event_listener): """ Creates a new instance of the EventFiringWebDriver :Args: - driver : A WebDriver instance - event_listener : Instance of a class that subclasses AbstractEventListener and implements it fully or partially Example: .. code-block:: python from selenium.webdriver import Firefox from selenium.webdriver.support.events import EventFiringWebDriver, AbstractEventListener class MyListener(AbstractEventListener): def before_navigate_to(self, url, driver): print("Before navigate to %s" % url) def after_navigate_to(self, url, driver): print("After navigate to %s" % url) driver = Firefox() ef_driver = EventFiringWebDriver(driver, MyListener()) ef_driver.get("http://www.google.co.in/") """ if not isinstance(driver, WebDriver): raise WebDriverException("A WebDriver instance must be supplied") if not isinstance(event_listener, AbstractEventListener): raise WebDriverException("Event listener must be a subclass of AbstractEventListener") self._driver = driver self._driver._wrap_value = self._wrap_value self._listener = event_listener @property def wrapped_driver(self): """Returns the WebDriver instance wrapped by this EventsFiringWebDriver""" return self._driver def get(self, url): self._dispatch("navigate_to", (url, self._driver), "get", (url, )) def back(self): self._dispatch("navigate_back", (self._driver,), "back", ()) def forward(self): self._dispatch("navigate_forward", (self._driver,), "forward", ()) def execute_script(self, script, *args): unwrapped_args = (script,) + self._unwrap_element_args(args) return self._dispatch("execute_script", (script, self._driver), "execute_script", unwrapped_args) def execute_async_script(self, script, *args): unwrapped_args = (script,) + self._unwrap_element_args(args) return self._dispatch("execute_script", (script, self._driver), "execute_async_script", unwrapped_args) def close(self): self._dispatch("close", (self._driver,), "close", ()) def quit(self): self._dispatch("quit", (self._driver,), "quit", ()) def find_element(self, by=By.ID, value=None): return self._dispatch("find", (by, value, self._driver), "find_element", (by, value)) def find_elements(self, by=By.ID, value=None): return self._dispatch("find", (by, value, self._driver), "find_elements", (by, value)) def find_element_by_id(self, id_): return self.find_element(by=By.ID, value=id_) def find_elements_by_id(self, id_): return self.find_elements(by=By.ID, value=id_) def find_element_by_xpath(self, xpath): return self.find_element(by=By.XPATH, value=xpath) def find_elements_by_xpath(self, xpath): return self.find_elements(by=By.XPATH, value=xpath) def find_element_by_link_text(self, link_text): return self.find_element(by=By.LINK_TEXT, value=link_text) def find_elements_by_link_text(self, text): return self.find_elements(by=By.LINK_TEXT, value=text) def find_element_by_partial_link_text(self, link_text): return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_elements_by_partial_link_text(self, link_text): return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_element_by_name(self, name): return self.find_element(by=By.NAME, value=name) def find_elements_by_name(self, name): return self.find_elements(by=By.NAME, value=name) def find_element_by_tag_name(self, name): return self.find_element(by=By.TAG_NAME, value=name) def find_elements_by_tag_name(self, name): return self.find_elements(by=By.TAG_NAME, value=name) def find_element_by_class_name(self, name): return self.find_element(by=By.CLASS_NAME, value=name) def find_elements_by_class_name(self, name): return self.find_elements(by=By.CLASS_NAME, value=name) def find_element_by_css_selector(self, css_selector): return self.find_element(by=By.CSS_SELECTOR, value=css_selector) def find_elements_by_css_selector(self, css_selector): return self.find_elements(by=By.CSS_SELECTOR, value=css_selector) def _dispatch(self, l_call, l_args, d_call, d_args): getattr(self._listener, "before_%s" % l_call)(*l_args) try: result = getattr(self._driver, d_call)(*d_args) except Exception as e: self._listener.on_exception(e, self._driver) raise e getattr(self._listener, "after_%s" % l_call)(*l_args) return _wrap_elements(result, self) def _unwrap_element_args(self, args): if isinstance(args, EventFiringWebElement): return args.wrapped_element elif isinstance(args, tuple): return tuple([self._unwrap_element_args(item) for item in args]) elif isinstance(args, list): return [self._unwrap_element_args(item) for item in args] else: return args def _wrap_value(self, value): if isinstance(value, EventFiringWebElement): return WebDriver._wrap_value(self._driver, value.wrapped_element) return WebDriver._wrap_value(self._driver, value) def __setattr__(self, item, value): if item.startswith("_") or not hasattr(self._driver, item): object.__setattr__(self, item, value) else: try: object.__setattr__(self._driver, item, value) except Exception as e: self._listener.on_exception(e, self._driver) raise e def __getattr__(self, name): def _wrap(*args): try: result = attrib(*args) return _wrap_elements(result, self) except Exception as e: self._listener.on_exception(e, self._driver) raise e if hasattr(self._driver, name): try: attrib = getattr(self._driver, name) if not callable(attrib): return attrib except Exception as e: self._listener.on_exception(e, self._driver) raise e return _wrap raise AttributeError(name) class EventFiringWebElement(object): """" A wrapper around WebElement instance which supports firing events """ def __init__(self, webelement, ef_driver): """ Creates a new instance of the EventFiringWebElement """ self._webelement = webelement self._ef_driver = ef_driver self._driver = ef_driver.wrapped_driver self._listener = ef_driver._listener @property def wrapped_element(self): """Returns the WebElement wrapped by this EventFiringWebElement instance""" return self._webelement def click(self): self._dispatch("click", (self._webelement, self._driver), "click", ()) def clear(self): self._dispatch("change_value_of", (self._webelement, self._driver), "clear", ()) def send_keys(self, *value): self._dispatch("change_value_of", (self._webelement, self._driver), "send_keys", value) def find_element(self, by=By.ID, value=None): return self._dispatch("find", (by, value, self._driver), "find_element", (by, value)) def find_elements(self, by=By.ID, value=None): return self._dispatch("find", (by, value, self._driver), "find_elements", (by, value)) def find_element_by_id(self, id_): return self.find_element(by=By.ID, value=id_) def find_elements_by_id(self, id_): return self.find_elements(by=By.ID, value=id_) def find_element_by_name(self, name): return self.find_element(by=By.NAME, value=name) def find_elements_by_name(self, name): return self.find_elements(by=By.NAME, value=name) def find_element_by_link_text(self, link_text): return self.find_element(by=By.LINK_TEXT, value=link_text) def find_elements_by_link_text(self, link_text): return self.find_elements(by=By.LINK_TEXT, value=link_text) def find_element_by_partial_link_text(self, link_text): return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_elements_by_partial_link_text(self, link_text): return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text) def find_element_by_tag_name(self, name): return self.find_element(by=By.TAG_NAME, value=name) def find_elements_by_tag_name(self, name): return self.find_elements(by=By.TAG_NAME, value=name) def find_element_by_xpath(self, xpath): return self.find_element(by=By.XPATH, value=xpath) def find_elements_by_xpath(self, xpath): return self.find_elements(by=By.XPATH, value=xpath) def find_element_by_class_name(self, name): return self.find_element(by=By.CLASS_NAME, value=name) def find_elements_by_class_name(self, name): return self.find_elements(by=By.CLASS_NAME, value=name) def find_element_by_css_selector(self, css_selector): return self.find_element(by=By.CSS_SELECTOR, value=css_selector) def find_elements_by_css_selector(self, css_selector): return self.find_elements(by=By.CSS_SELECTOR, value=css_selector) def _dispatch(self, l_call, l_args, d_call, d_args): getattr(self._listener, "before_%s" % l_call)(*l_args) try: result = getattr(self._webelement, d_call)(*d_args) except Exception as e: self._listener.on_exception(e, self._driver) raise e getattr(self._listener, "after_%s" % l_call)(*l_args) return _wrap_elements(result, self._ef_driver) def __setattr__(self, item, value): if item.startswith("_") or not hasattr(self._webelement, item): object.__setattr__(self, item, value) else: try: object.__setattr__(self._webelement, item, value) except Exception as e: self._listener.on_exception(e, self._driver) raise e def __getattr__(self, name): def _wrap(*args): try: result = attrib(*args) return _wrap_elements(result, self._ef_driver) except Exception as e: self._listener.on_exception(e, self._driver) raise e if hasattr(self._webelement, name): try: attrib = getattr(self._webelement, name) if not callable(attrib): return attrib except Exception as e: self._listener.on_exception(e, self._driver) raise e return _wrap raise AttributeError(name) selenium-2.48.0/py/selenium/webdriver/support/events.py0000644000076600000240000000161012551302002023667 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from .abstract_event_listener import AbstractEventListener from .event_firing_webdriver import EventFiringWebDriver selenium-2.48.0/py/selenium/webdriver/support/expected_conditions.py0000644000076600000240000002327312551302002026426 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import NoSuchFrameException from selenium.common.exceptions import StaleElementReferenceException from selenium.common.exceptions import WebDriverException from selenium.common.exceptions import NoAlertPresentException """ * Canned "Expected Conditions" which are generally useful within webdriver * tests. """ class title_is(object): """An expectation for checking the title of a page. title is the expected title, which must be an exact match returns True if the title matches, false otherwise.""" def __init__(self, title): self.title = title def __call__(self, driver): return self.title == driver.title class title_contains(object): """ An expectation for checking that the title contains a case-sensitive substring. title is the fragment of title expected returns True when the title matches, False otherwise """ def __init__(self, title): self.title = title def __call__(self, driver): return self.title in driver.title class presence_of_element_located(object): """ An expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible. locator - used to find the element returns the WebElement once it is located """ def __init__(self, locator): self.locator = locator def __call__(self, driver): return _find_element(driver, self.locator) class visibility_of_element_located(object): """ An expectation for checking that an element is present on the DOM of a page and visible. Visibility means that the element is not only displayed but also has a height and width that is greater than 0. locator - used to find the element returns the WebElement once it is located and visible """ def __init__(self, locator): self.locator = locator def __call__(self, driver): try: return _element_if_visible(_find_element(driver, self.locator)) except StaleElementReferenceException: return False class visibility_of(object): """ An expectation for checking that an element, known to be present on the DOM of a page, is visible. Visibility means that the element is not only displayed but also has a height and width that is greater than 0. element is the WebElement returns the (same) WebElement once it is visible """ def __init__(self, element): self.element = element def __call__(self, ignored): return _element_if_visible(self.element) def _element_if_visible(element, visibility=True): return element if element.is_displayed() == visibility else False class presence_of_all_elements_located(object): """ An expectation for checking that there is at least one element present on a web page. locator is used to find the element returns the list of WebElements once they are located """ def __init__(self, locator): self.locator = locator def __call__(self, driver): return _find_elements(driver, self.locator) class text_to_be_present_in_element(object): """ An expectation for checking if the given text is present in the specified element. locator, text """ def __init__(self, locator, text_): self.locator = locator self.text = text_ def __call__(self, driver): try : element_text = _find_element(driver, self.locator).text return self.text in element_text except StaleElementReferenceException: return False class text_to_be_present_in_element_value(object): """ An expectation for checking if the given text is present in the element's locator, text """ def __init__(self, locator, text_): self.locator = locator self.text = text_ def __call__(self, driver): try: element_text = _find_element(driver, self.locator).get_attribute("value") if element_text: return self.text in element_text else: return False except StaleElementReferenceException: return False class frame_to_be_available_and_switch_to_it(object): """ An expectation for checking whether the given frame is available to switch to. If the frame is available it switches the given driver to the specified frame. """ def __init__(self, locator): self.frame_locator = locator def __call__(self, driver): try: if isinstance(self.frame_locator, tuple): driver.switch_to.frame(_find_element(driver, self.frame_locator)) else: driver.switch_to.frame(self.frame_locator) return True except NoSuchFrameException: return False class invisibility_of_element_located(object): """ An Expectation for checking that an element is either invisible or not present on the DOM. locator used to find the element """ def __init__(self, locator): self.locator = locator def __call__(self, driver): try: return _element_if_visible(_find_element(driver, self.locator), False) except (NoSuchElementException, StaleElementReferenceException): # In the case of NoSuchElement, returns true because the element is # not present in DOM. The try block checks if the element is present # but is invisible. # In the case of StaleElementReference, returns true because stale # element reference implies that element is no longer visible. return True class element_to_be_clickable(object): """ An Expectation for checking an element is visible and enabled such that you can click it.""" def __init__(self, locator): self.locator = locator def __call__(self, driver): element = visibility_of_element_located(self.locator)(driver) if element and element.is_enabled(): return element else: return False class staleness_of(object): """ Wait until an element is no longer attached to the DOM. element is the element to wait for. returns False if the element is still attached to the DOM, true otherwise. """ def __init__(self, element): self.element = element def __call__(self, ignored): try: # Calling any method forces a staleness check self.element.is_enabled() return False except StaleElementReferenceException as expected: return True class element_to_be_selected(object): """ An expectation for checking the selection is selected. element is WebElement object """ def __init__(self, element): self.element = element def __call__(self, ignored): return self.element.is_selected() class element_located_to_be_selected(object): """An expectation for the element to be located is selected. locator is a tuple of (by, path)""" def __init__(self, locator): self.locator = locator def __call__(self, driver): return _find_element(driver, self.locator).is_selected() class element_selection_state_to_be(object): """ An expectation for checking if the given element is selected. element is WebElement object is_selected is a Boolean." """ def __init__(self, element, is_selected): self.element = element self.is_selected = is_selected def __call__(self, ignored): return self.element.is_selected() == self.is_selected class element_located_selection_state_to_be(object): """ An expectation to locate an element and check if the selection state specified is in that state. locator is a tuple of (by, path) is_selected is a boolean """ def __init__(self, locator, is_selected): self.locator = locator self.is_selected = is_selected def __call__(self, driver): try: element = _find_element(driver, self.locator) return element.is_selected() == self.is_selected except StaleElementReferenceException: return False class alert_is_present(object): """ Expect an alert to be present.""" def __init__(self): pass def __call__(self, driver): try: alert = driver.switch_to.alert alert.text return alert except NoAlertPresentException: return False def _find_element(driver, by): """Looks up an element. Logs and re-raises ``WebDriverException`` if thrown.""" try : return driver.find_element(*by) except NoSuchElementException as e: raise e except WebDriverException as e: raise e def _find_elements(driver, by): try : return driver.find_elements(*by) except WebDriverException as e: raise e selenium-2.48.0/py/selenium/webdriver/support/select.py0000644000076600000240000002053012551302002023644 0ustar dburnsstaff00000000000000# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you 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. from selenium.webdriver.common.by import By from selenium.common.exceptions import NoSuchElementException, UnexpectedTagNameException class Select: def __init__(self, webelement): """ Constructor. A check is made that the given element is, indeed, a SELECT tag. If it is not, then an UnexpectedTagNameException is thrown. :Args: - webelement - element SELECT element to wrap Example: from selenium.webdriver.support.ui import Select \n Select(driver.find_element_by_tag_name("select")).select_by_index(2) """ if webelement.tag_name.lower() != "select": raise UnexpectedTagNameException( "Select only works on