selenium-3.8.0/0000775000175000017500000000000013207771116013612 5ustar lucaslucas00000000000000selenium-3.8.0/README.rst0000664000175000017500000001302513207770451015303 0ustar lucaslucas00000000000000====================== Selenium Client Driver ====================== Introduction ============ Python language bindings for Selenium WebDriver. The `selenium` package is used to 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.7, 3.4+ 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-3.8.0.tar.gz), unarchive it, and run:: python setup.py install Note: You may want to consider using `virtualenv `_ to create isolated Python environments. Drivers ======= Selenium requires a driver to interface with the chosen browser. Firefox, for example, requires `geckodriver `_, which needs to be installed before the below examples can be run. Make sure it's in your `PATH`, e. g., place it in `/usr/bin` or `/usr/local/bin`. Failure to observe this step will give you an error `selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH.` Other supported browsers will have their own drivers available. Links to some of the more popular browser drivers follow. +--------------+-----------------------------------------------------------------------+ | **Chrome**: | https://sites.google.com/a/chromium.org/chromedriver/downloads | +--------------+-----------------------------------------------------------------------+ | **Edge**: | https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ | +--------------+-----------------------------------------------------------------------+ | **Firefox**: | https://github.com/mozilla/geckodriver/releases | +--------------+-----------------------------------------------------------------------+ | **Safari**: | https://webkit.org/blog/6900/webdriver-support-in-safari-10/ | +--------------+-----------------------------------------------------------------------+ Example 0: ========== * open a new Firefox browser * load the page at the given URL .. code-block:: python 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 .. code-block:: python 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: .. code-block:: python import unittest from selenium import webdriver 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/3.8/selenium-server-standalone-3.8.0.jar Run the server from the command line:: java -jar selenium-server-standalone-3.8.0.jar Then run your Python client scripts. Use The Source Luke! ==================== View source code online: +-----------+-------------------------------------------------------+ | official: | https://github.com/SeleniumHQ/selenium/tree/master/py | +-----------+-------------------------------------------------------+ selenium-3.8.0/setup.py0000775000175000017500000000714413207770451015336 0ustar lucaslucas00000000000000#!/usr/bin/env python # 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 distutils.command.install import INSTALL_SCHEMES from os.path import dirname, join, abspath from setuptools import setup from setuptools.command.install import install for scheme in INSTALL_SCHEMES.values(): scheme['data'] = scheme['purelib'] setup_args = { 'cmdclass': {'install': install}, 'name': 'selenium', 'version': "3.8.0", 'license': 'Apache 2.0', 'description': 'Python bindings for Selenium', 'long_description': open(join(abspath(dirname(__file__)), "README.rst")).read(), 'url': 'https://github.com/SeleniumHQ/selenium/', 'classifiers': ['Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX', 'Operating System :: Microsoft :: Windows', 'Operating System :: MacOS :: MacOS X', 'Topic :: Software Development :: Testing', 'Topic :: Software Development :: Libraries', 'Programming Language :: Python', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6'], 'package_dir': { 'selenium': 'selenium', 'selenium.common': 'selenium/common', 'selenium.webdriver': 'selenium/webdriver', }, 'packages': ['selenium', 'selenium.common', 'selenium.webdriver', 'selenium.webdriver.android', 'selenium.webdriver.chrome', 'selenium.webdriver.common', 'selenium.webdriver.common.html5', 'selenium.webdriver.support', 'selenium.webdriver.firefox', 'selenium.webdriver.ie', 'selenium.webdriver.edge', 'selenium.webdriver.opera', 'selenium.webdriver.phantomjs', 'selenium.webdriver.remote', 'selenium.webdriver.support', ], 'package_data': { 'selenium.webdriver.firefox': ['*.xpi', 'webdriver_prefs.json'], 'selenium.webdriver.remote': ['getAttribute.js', 'isDisplayed.js'], }, 'data_files': [('selenium/webdriver/firefox/x86', ['selenium/webdriver/firefox/x86/x_ignore_nofocus.so']), ('selenium/webdriver/firefox/amd64', ['selenium/webdriver/firefox/amd64/x_ignore_nofocus.so']), ('selenium/webdriver/remote', ['selenium/webdriver/remote/getAttribute.js']), ('selenium/webdriver/remote', ['selenium/webdriver/remote/isDisplayed.js'])], 'include_package_data': True, 'zip_safe': False } setup(**setup_args) selenium-3.8.0/selenium.egg-info/0000775000175000017500000000000013207771116017125 5ustar lucaslucas00000000000000selenium-3.8.0/selenium.egg-info/not-zip-safe0000664000175000017500000000000113207770456021361 0ustar lucaslucas00000000000000 selenium-3.8.0/selenium.egg-info/dependency_links.txt0000664000175000017500000000000113207771116023173 0ustar lucaslucas00000000000000 selenium-3.8.0/selenium.egg-info/top_level.txt0000664000175000017500000000001113207771116021647 0ustar lucaslucas00000000000000selenium selenium-3.8.0/selenium.egg-info/PKG-INFO0000664000175000017500000001706413207771116020232 0ustar lucaslucas00000000000000Metadata-Version: 1.1 Name: selenium Version: 3.8.0 Summary: Python bindings for Selenium Home-page: https://github.com/SeleniumHQ/selenium/ Author: UNKNOWN Author-email: UNKNOWN License: Apache 2.0 Description-Content-Type: UNKNOWN Description: ====================== Selenium Client Driver ====================== Introduction ============ Python language bindings for Selenium WebDriver. The `selenium` package is used to 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.7, 3.4+ 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-3.8.0.tar.gz), unarchive it, and run:: python setup.py install Note: You may want to consider using `virtualenv `_ to create isolated Python environments. Drivers ======= Selenium requires a driver to interface with the chosen browser. Firefox, for example, requires `geckodriver `_, which needs to be installed before the below examples can be run. Make sure it's in your `PATH`, e. g., place it in `/usr/bin` or `/usr/local/bin`. Failure to observe this step will give you an error `selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH.` Other supported browsers will have their own drivers available. Links to some of the more popular browser drivers follow. +--------------+-----------------------------------------------------------------------+ | **Chrome**: | https://sites.google.com/a/chromium.org/chromedriver/downloads | +--------------+-----------------------------------------------------------------------+ | **Edge**: | https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ | +--------------+-----------------------------------------------------------------------+ | **Firefox**: | https://github.com/mozilla/geckodriver/releases | +--------------+-----------------------------------------------------------------------+ | **Safari**: | https://webkit.org/blog/6900/webdriver-support-in-safari-10/ | +--------------+-----------------------------------------------------------------------+ Example 0: ========== * open a new Firefox browser * load the page at the given URL .. code-block:: python 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 .. code-block:: python 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: .. code-block:: python import unittest from selenium import webdriver 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/3.8/selenium-server-standalone-3.8.0.jar Run the server from the command line:: java -jar selenium-server-standalone-3.8.0.jar Then run your Python client scripts. Use The Source Luke! ==================== View source code online: +-----------+-------------------------------------------------------+ | official: | 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.7 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 selenium-3.8.0/selenium.egg-info/SOURCES.txt0000664000175000017500000000736313207771116021022 0ustar lucaslucas00000000000000CHANGES MANIFEST.in README.rst setup.cfg setup.py selenium/__init__.py selenium.egg-info/PKG-INFO selenium.egg-info/SOURCES.txt selenium.egg-info/dependency_links.txt selenium.egg-info/not-zip-safe selenium.egg-info/top_level.txt selenium/common/__init__.py selenium/common/exceptions.py selenium/webdriver/__init__.py selenium/webdriver/android/__init__.py selenium/webdriver/android/webdriver.py selenium/webdriver/blackberry/__init__.py selenium/webdriver/blackberry/webdriver.py selenium/webdriver/chrome/__init__.py selenium/webdriver/chrome/options.py selenium/webdriver/chrome/remote_connection.py selenium/webdriver/chrome/service.py selenium/webdriver/chrome/webdriver.py selenium/webdriver/common/__init__.py selenium/webdriver/common/action_chains.py selenium/webdriver/common/alert.py selenium/webdriver/common/by.py selenium/webdriver/common/desired_capabilities.py selenium/webdriver/common/keys.py selenium/webdriver/common/proxy.py selenium/webdriver/common/service.py selenium/webdriver/common/touch_actions.py selenium/webdriver/common/utils.py selenium/webdriver/common/actions/__init__.py selenium/webdriver/common/actions/action_builder.py selenium/webdriver/common/actions/input_device.py selenium/webdriver/common/actions/interaction.py selenium/webdriver/common/actions/key_actions.py selenium/webdriver/common/actions/key_input.py selenium/webdriver/common/actions/mouse_button.py selenium/webdriver/common/actions/pointer_actions.py selenium/webdriver/common/actions/pointer_input.py selenium/webdriver/common/html5/__init__.py selenium/webdriver/common/html5/application_cache.py selenium/webdriver/edge/__init__.py selenium/webdriver/edge/options.py selenium/webdriver/edge/service.py selenium/webdriver/edge/webdriver.py selenium/webdriver/firefox/__init__.py selenium/webdriver/firefox/extension_connection.py selenium/webdriver/firefox/firefox_binary.py selenium/webdriver/firefox/firefox_profile.py selenium/webdriver/firefox/options.py selenium/webdriver/firefox/remote_connection.py selenium/webdriver/firefox/service.py selenium/webdriver/firefox/webdriver.py selenium/webdriver/firefox/webdriver.xpi selenium/webdriver/firefox/webdriver_prefs.json selenium/webdriver/firefox/webelement.py selenium/webdriver/firefox/amd64/x_ignore_nofocus.so selenium/webdriver/firefox/x86/x_ignore_nofocus.so selenium/webdriver/ie/__init__.py selenium/webdriver/ie/options.py selenium/webdriver/ie/service.py selenium/webdriver/ie/webdriver.py selenium/webdriver/opera/__init__.py selenium/webdriver/opera/options.py selenium/webdriver/opera/webdriver.py selenium/webdriver/phantomjs/__init__.py selenium/webdriver/phantomjs/service.py selenium/webdriver/phantomjs/webdriver.py selenium/webdriver/remote/__init__.py selenium/webdriver/remote/command.py selenium/webdriver/remote/errorhandler.py selenium/webdriver/remote/file_detector.py selenium/webdriver/remote/getAttribute.js selenium/webdriver/remote/isDisplayed.js selenium/webdriver/remote/mobile.py selenium/webdriver/remote/remote_connection.py selenium/webdriver/remote/switch_to.py selenium/webdriver/remote/utils.py selenium/webdriver/remote/webdriver.py selenium/webdriver/remote/webelement.py selenium/webdriver/safari/__init__.py selenium/webdriver/safari/service.py selenium/webdriver/safari/webdriver.py selenium/webdriver/support/__init__.py selenium/webdriver/support/abstract_event_listener.py selenium/webdriver/support/color.py selenium/webdriver/support/event_firing_webdriver.py selenium/webdriver/support/events.py selenium/webdriver/support/expected_conditions.py selenium/webdriver/support/select.py selenium/webdriver/support/ui.py selenium/webdriver/support/wait.py selenium/webdriver/webkitgtk/__init__.py selenium/webdriver/webkitgtk/options.py selenium/webdriver/webkitgtk/service.py selenium/webdriver/webkitgtk/webdriver.pyselenium-3.8.0/CHANGES0000664000175000017500000005442313207301772014612 0ustar lucaslucas00000000000000Selenium 3.8.0 * Firefox options can now be imported from selenium.webdriver as FirefoxOptions (#5120) * Headless mode can now be set in Chrome Options using `set_headless` * Headless mode can now be set in Firefox Options using `set_headless` * Add the WebKitGTK WebDriver and options class (#4635) * Browser options can now be passed to remote WebDriver via the `options` parameter * Browser option parameters are now standardized across drivers as `options`. `firefox_options`, `chrome_options`, and `ie_options` are now deprecated * Added missing W3C Error Codes (#4556) * Support has been removed for Python versions 2.6 and 3.3 Selenium 3.7.0 * need to pass applicable environment variables to tox * Fix active_element for w3c drivers (#3979) * add support for minimize command * add support for fullscreen command * window rect commands should fail on firefox and remote (legacy) * Fix python backward compatibility for window commands (#4937) * Update docstrings to specify the type of path needed to install firefox addons. (#4881) * Update python chromeOptions key for capabilities (#4622) * Fix python pause action implementation (#4795) Selenium 3.6.0 * Fix package name in python webelement module (#4670) * Fix python driver examples (#3872) * No need to multiply pause by 1000 * Add pause to action chains * only check for proxyType once * lowercase proxy type for w3c payload in python #4574 * guarding against null return value from find_elements in python #4555 * remove unnecessary pytest marking, address flake8 issues * allow IE WebDriver to accept IE Options * add IE Options class * convert OSS capabilities to W3C equivalent for W3C payload * Add Safari to API docs Selenium 3.5.0 * Numerous test fixes *Iterate over capabilities in a way to support py2.7 and py3 * Fix W3C switching to window by name. * Support GeckoDriver addon install/uninstall commands #4215. * Move firefox_profile into moz:firefoxOptions. * Filter non-W3C capability names out of alwaysMatch. * Honor cmd line args passed to Service ctor (#4167) * Add expected conditions based on URL to Python Expected Conditions #4160 * Add network emulation to Chrome Python bindings (#4011) * add warning when saving incorrectly named screenshot (#4141) Selenium 3.4.3 * Fix EventFiringWebdriver and WebElement to raise AttributeError on missing attributes. (#4107) * unwrap WebElements inside dicts Selenium 3.4.2 * translate move_by_offset command to w3c * Update capabilities properly instead of assuming dict structure. Fixes #3927 * Add missing file for Chrome options to API docs. * Add Chrome options module to API docs. Selenium 3.4.1 * Add back the ability to set profile when using Firefox 45ESR. Fixes #3897 Selenium 3.4.0 * Correct usage of newSession around `firstMatch` and `alwaysMatch` * Remove superfluous capabilities that are not needed * Add expected condition that waits for all found elements to be visible (#3532) * Allow methods wrapped by EventFiringWebDriver and EventFiringWebElement (#806) * Dropping `javascriptEnabled` capability for real browsers * Use W3C check from parent object instead of assuming from capabilities * Bump example source distribution to match latest release. * Replace TypeError with KeyError in remote webdriver error handler code (#3826) * When testing Marionette use default capabilities in testing * Conform to the api of urllib2 for adding header for a request (#3803) * Add `text` key to alert#sendKeys parameters for W3C Endpoint * Location once scrolled into view should use W3C executeScript endpoint not JSONWP * Fixed the usage information in documentation of "save_screenshot". (#3804) * Add Element Not Interactable exception * Clean up imports in error handler * flake8 cleanup Selenium 3.3.3 * make w3c execute_script commands unique Selenium 3.3.2 * Update window commands to use W3C End points * Update Alert when in W3C mode to use W3C Endpoints * Update to new W3C Execute Script end points * Add setting/getting proxy details to Firefox Options * Deprecate the use of browser profile when instantiating a session * Update start session to handle the W3C New Session * Add get/set window rect commands * Add InvalidArgumentException * When passing in `text` to send_keys, make sure we send a string not array * Fix string decoding in remote connection (#3663) * Fix indentation to satisfy PEP8 * Try use old way of setting page load timeout if new way fails. Fixes #3654 * fix file uploads for Firefox * Run unit tests on Python 3.3, 3.4, and 3.5 (#3638) * Fix indentation in double_click. * Fix non-W3C page load timeout setting. Selenium 3.3.1 * Fix encoding of basic auth header when using Python 3 Fixes #3622 * Add initial unit test suite * Update W3C Timeout setting to be in line with the specification * support.ui.Select class inherits from object (#3067) * fix bug in proxy constructor that some properties are not proper set (#3459) * Fix flake8 issues (#3628) Selenium 3.3.0 ** Note ** If you are updating to this version, please also update GeckoDriver to v0.15.0 * Fix python HTTPS encoding for python driver (#3379) * Allow Firefox preferences to be set directly in Options * Fix shutdown and process termination (#3263) * Preventing exception if log_path is none or empty. Fixes #3128 * Add the W3C capability to Firefox for accepting insecure certificates * Initial implementation of Pointer Actions * Only skip tests if driver name matches a directory name. * Update calls that return a pure object with keys to look for 'value' key * Initial W3C Actions support * fix docs output directory Selenium 3.0.2 * Add support for W3C Get Active Element * Return when we use executeScript for faking WebElement.get_property * Expand user paths and resolve absolute path for Chrome extensions * Add support for verbose logging and custom path to EdgeDriver * Update TakeElementScreenshot to match WebDriver specification * Raise WebDriverException when FirefoxBinary fails to locate binary * Fix getting IP for python 3 * Write Service log to DEVNULL by default * Only attempt to remove the Firefox profile path if one was specified * Added context manager for chrome/content in Firefox Selenium 3.0.1 * Fix regressions with python 3 * Add support for Safari Technology Preview Selenium 3.0.0 * new FirefoxDriver ctor precedence logic and moz:firefoxOptions support (#2882) * Add W3C Set Window Position and W3C Get Window Position * enable log path setting from firefox webdriver (#2700) * Correct encoding of getAttribute.js and only load it once. Fixes #2785 * Encode the isDisplayed atom and only load it once Selenium 3.0.0.b3 * Use atoms for get_attribute and is_displayed when communicating with a w3c compliant remote end. * Make it possible to specialise web element Selenium 3.0.0.b2 * Updated Marionette port argument to match other drivers. Selenium 3.0.0.b1 * Fix basestring reference to work with python 3. Fixes #1820 * Correct Length conditional when filtering in PhantomJS. Fixes #1817 * Fix send keys when using PUA keys e.g. Keys.RIGHT #1839 * Fix cookie file leak in PhantomJS #1854 * Use the correct binary path when using Marionette * Fixed: Unhelpful error message when PhantomJS exits. (#2173 #2168) * Fix broken link to python documentation (#2159) * Attempt to remove Firefox profile when using Marionette * Ensure all capabilities are either within desiredCapabilities or requiredCapabilities * Correct the expected capability name for the Firefox profile * Add Firefox options to capabilities * Visibility_of_all implies it only returns elements if all visible (#2052) * Find visible elements (#2041) * Pass the firefox_profile as a desired capability in the Python client when using a remote server * Avoid checking exception details for invalid locators due to differences in server implementations * Handle capabilities better with Marionette and GeckoDriver * Updated the maxVersion of FirefoxDriver xpi maxVersion to work with Firefox 47.0.1 * Remove Selenium RC support Selenium 2.53.0 * Adding Options object for use with Python FirefoxDriver * Fixed improper usage of super in exceptions module * create a temp file for cookies in phantomjs if not specified * Pass in the executable that FirefoxBinary finds to the service if there isnt one passed in as a kwarg or capability * Applied some DRY and extracted out the keys_to_typing() * Fix deselecting options in elements, not on <%s>" % webelement.tag_name) self._el = webelement multi = self._el.get_attribute("multiple") self.is_multiple = multi and multi != "false" @property def options(self): """Returns a list of all options belonging to this select tag""" return self._el.find_elements(By.TAG_NAME, 'option') @property def all_selected_options(self): """Returns a list of all selected options belonging to this select tag""" ret = [] for opt in self.options: if opt.is_selected(): ret.append(opt) return ret @property def first_selected_option(self): """The first selected option in this select tag (or the currently selected option in a normal select)""" for opt in self.options: if opt.is_selected(): return opt raise NoSuchElementException("No options are selected") def select_by_value(self, value): """Select all options that have a value matching the argument. That is, when given "foo" this would select an option like: :Args: - value - The value to match against throws NoSuchElementException If there is no option with specisied value in SELECT """ css = "option[value =%s]" % self._escapeString(value) opts = self._el.find_elements(By.CSS_SELECTOR, css) matched = False for opt in opts: self._setSelected(opt) if not self.is_multiple: return matched = True if not matched: raise NoSuchElementException("Cannot locate option with value: %s" % value) def select_by_index(self, index): """Select the option at the given index. This is done by examing the "index" attribute of an element, and not merely by counting. :Args: - index - The option at this index will be selected throws NoSuchElementException If there is no option with specisied index in SELECT """ match = str(index) for opt in self.options: if opt.get_attribute("index") == match: self._setSelected(opt) return raise NoSuchElementException("Could not locate element with index %d" % index) def select_by_visible_text(self, text): """Select all options that display text matching the argument. That is, when given "Bar" this would select an option like: :Args: - text - The visible text to match against throws NoSuchElementException If there is no option with specisied text in SELECT """ xpath = ".//option[normalize-space(.) = %s]" % self._escapeString(text) opts = self._el.find_elements(By.XPATH, xpath) matched = False for opt in opts: self._setSelected(opt) if not self.is_multiple: return matched = True if len(opts) == 0 and " " in text: subStringWithoutSpace = self._get_longest_token(text) if subStringWithoutSpace == "": candidates = self.options else: xpath = ".//option[contains(.,%s)]" % self._escapeString(subStringWithoutSpace) candidates = self._el.find_elements(By.XPATH, xpath) for candidate in candidates: if text == candidate.text: self._setSelected(candidate) if not self.is_multiple: return matched = True if not matched: raise NoSuchElementException("Could not locate element with visible text: %s" % text) def deselect_all(self): """Clear all selected entries. This is only valid when the SELECT supports multiple selections. throws NotImplementedError If the SELECT does not support multiple selections """ if not self.is_multiple: raise NotImplementedError("You may only deselect all options of a multi-select") for opt in self.options: self._unsetSelected(opt) def deselect_by_value(self, value): """Deselect all options that have a value matching the argument. That is, when given "foo" this would deselect an option like: :Args: - value - The value to match against throws NoSuchElementException If there is no option with specisied value in SELECT """ if not self.is_multiple: raise NotImplementedError("You may only deselect options of a multi-select") matched = False css = "option[value = %s]" % self._escapeString(value) opts = self._el.find_elements(By.CSS_SELECTOR, css) for opt in opts: self._unsetSelected(opt) matched = True if not matched: raise NoSuchElementException("Could not locate element with value: %s" % value) def deselect_by_index(self, index): """Deselect the option at the given index. This is done by examing the "index" attribute of an element, and not merely by counting. :Args: - index - The option at this index will be deselected throws NoSuchElementException If there is no option with specisied index in SELECT """ if not self.is_multiple: raise NotImplementedError("You may only deselect options of a multi-select") for opt in self.options: if opt.get_attribute("index") == str(index): self._unsetSelected(opt) return raise NoSuchElementException("Could not locate element with index %d" % index) def deselect_by_visible_text(self, text): """Deselect all options that display text matching the argument. That is, when given "Bar" this would deselect an option like: :Args: - text - The visible text to match against """ if not self.is_multiple: raise NotImplementedError("You may only deselect options of a multi-select") matched = False xpath = ".//option[normalize-space(.) = %s]" % self._escapeString(text) opts = self._el.find_elements(By.XPATH, xpath) for opt in opts: self._unsetSelected(opt) matched = True if not matched: raise NoSuchElementException("Could not locate element with visible text: %s" % text) def _setSelected(self, option): if not option.is_selected(): option.click() def _unsetSelected(self, option): if option.is_selected(): option.click() def _escapeString(self, value): if '"' in value and "'" in value: substrings = value.split("\"") result = ["concat("] for substring in substrings: result.append("\"%s\"" % substring) result.append(", '\"', ") result = result[0:-1] if value.endswith('"'): result.append(", '\"'") return "".join(result) + ")" if '"' in value: return "'%s'" % value return "\"%s\"" % value def _get_longest_token(self, value): items = value.split(" ") longest = "" for item in items: if len(item) > len(longest): longest = item return longest selenium-3.8.0/selenium/webdriver/support/color.py0000644000175000017500000002620413113073540022622 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/support/expected_conditions.py0000644000175000017500000003170513144316447025552 0ustar lucaslucas00000000000000# 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 url_contains(object): """ An expectation for checking that the current url contains a case-sensitive substring. url is the fragment of url expected, returns True when the title matches, False otherwise """ def __init__(self, url): self.url = url def __call__(self, driver): return self.url in driver.current_url class url_matches(object): """An expectation for checking the current url. pattern is the expected pattern, which must be an exact match returns True if the title matches, false otherwise.""" def __init__(self, pattern): self.pattern = pattern def __call__(self, driver): import re match = re.search(self.pattern, driver.current_url) return match is not None class url_to_be(object): """An expectation for checking the current url. url is the expected url, which must be an exact match returns True if the title matches, false otherwise.""" def __init__(self, url): self.url = url def __call__(self, driver): return self.url == driver.current_url class url_changes(object): """An expectation for checking the current url. url is the expected url, which must not be an exact match returns True if the url is different, false otherwise.""" def __init__(self, url): self.url = url def __call__(self, driver): return self.url != driver.current_url 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 visibility_of_any_elements_located(object): """ An expectation for checking that there is at least one element visible 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 [element for element in _find_elements(driver, self.locator) if _element_if_visible(element)] class visibility_of_all_elements_located(object): """ An expectation for checking that all elements are present on the DOM of a page and visible. Visibility means that the elements are not only displayed but also has a height and width that is greater than 0. locator - used to find the elements returns the list of WebElements once they are located and visible """ def __init__(self, locator): self.locator = locator def __call__(self, driver): try: elements = _find_elements(driver, self.locator) for element in elements: if _element_if_visible(element, visibility=False): return False return elements except StaleElementReferenceException: return False 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: 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 number_of_windows_to_be(object): """ An expectation for the number of windows to be a certain value.""" def __init__(self, num_windows): self.num_windows = num_windows def __call__(self, driver): return len(driver.window_handles) == self.num_windows class new_window_is_opened(object): """ An expectation that a new window will be opened and have the number of windows handles increase""" def __init__(self, current_handles): self.current_handles = current_handles def __call__(self, driver): return len(driver.window_handles) > len(self.current_handles) 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-3.8.0/selenium/webdriver/support/ui.py0000644000175000017500000000153713113073540022123 0ustar lucaslucas00000000000000# 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 .select import Select # noqa from .wait import WebDriverWait # noqa selenium-3.8.0/selenium/webdriver/support/__init__.py0000644000175000017500000000142313113073540023237 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/support/wait.py0000644000175000017500000000774613113073540022462 0ustar lucaslucas00000000000000# 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 time from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import TimeoutException POLL_FREQUENCY = 0.5 # How long to sleep inbetween calls to the method IGNORED_EXCEPTIONS = (NoSuchElementException,) # exceptions ignored during calls to the method class WebDriverWait(object): def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None): """Constructor, takes a WebDriver instance and timeout in seconds. :Args: - driver - Instance of WebDriver (Ie, Firefox, Chrome or Remote) - timeout - Number of seconds before timing out - poll_frequency - sleep interval between calls By default, it is 0.5 second. - ignored_exceptions - iterable structure of exception classes ignored during calls. By default, it contains NoSuchElementException only. Example: from selenium.webdriver.support.ui import WebDriverWait \n element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) \n is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).\ \n until_not(lambda x: x.find_element_by_id("someId").is_displayed()) """ self._driver = driver self._timeout = timeout self._poll = poll_frequency # avoid the divide by zero if self._poll == 0: self._poll = POLL_FREQUENCY exceptions = list(IGNORED_EXCEPTIONS) if ignored_exceptions is not None: try: exceptions.extend(iter(ignored_exceptions)) except TypeError: # ignored_exceptions is not iterable exceptions.append(ignored_exceptions) self._ignored_exceptions = tuple(exceptions) def __repr__(self): return '<{0.__module__}.{0.__name__} (session="{1}")>'.format( type(self), self._driver.session_id) def until(self, method, message=''): """Calls the method provided with the driver as an argument until the \ return value is not False.""" screen = None stacktrace = None end_time = time.time() + self._timeout while True: try: value = method(self._driver) if value: return value except self._ignored_exceptions as exc: screen = getattr(exc, 'screen', None) stacktrace = getattr(exc, 'stacktrace', None) time.sleep(self._poll) if time.time() > end_time: break raise TimeoutException(message, screen, stacktrace) def until_not(self, method, message=''): """Calls the method provided with the driver as an argument until the \ return value is False.""" end_time = time.time() + self._timeout while True: try: value = method(self._driver) if not value: return value except self._ignored_exceptions: return True time.sleep(self._poll) if time.time() > end_time: break raise TimeoutException(message) selenium-3.8.0/selenium/webdriver/support/events.py0000644000175000017500000000163013113073540023004 0ustar lucaslucas00000000000000# 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 # noqa from .event_firing_webdriver import EventFiringWebDriver # noqa selenium-3.8.0/selenium/webdriver/support/abstract_event_listener.py0000644000175000017500000000376113113073540026420 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/support/event_firing_webdriver.py0000644000175000017500000003006613144316447026247 0ustar lucaslucas00000000000000# 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, **kwargs): try: result = attrib(*args, **kwargs) return _wrap_elements(result, self) except Exception as e: self._listener.on_exception(e, self._driver) raise try: attrib = getattr(self._driver, name) return _wrap if callable(attrib) else attrib except Exception as e: self._listener.on_exception(e, self._driver) raise 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, **kwargs): try: result = attrib(*args, **kwargs) return _wrap_elements(result, self._ef_driver) except Exception as e: self._listener.on_exception(e, self._driver) raise try: attrib = getattr(self._webelement, name) return _wrap if callable(attrib) else attrib except Exception as e: self._listener.on_exception(e, self._driver) raise selenium-3.8.0/selenium/webdriver/__init__.py0000664000175000017500000000360713207770451021544 0ustar lucaslucas00000000000000# 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 # noqa from .firefox.firefox_profile import FirefoxProfile # noqa from .firefox.options import Options as FirefoxOptions # noqa from .chrome.webdriver import WebDriver as Chrome # noqa from .chrome.options import Options as ChromeOptions # noqa from .ie.webdriver import WebDriver as Ie # noqa from .edge.webdriver import WebDriver as Edge # noqa from .opera.webdriver import WebDriver as Opera # noqa from .safari.webdriver import WebDriver as Safari # noqa from .blackberry.webdriver import WebDriver as BlackBerry # noqa from .phantomjs.webdriver import WebDriver as PhantomJS # noqa from .android.webdriver import WebDriver as Android # noqa from .webkitgtk.webdriver import WebDriver as WebKitGTK # noqa from .webkitgtk.options import Options as WebKitGTKOptions # noqa from .remote.webdriver import WebDriver as Remote # noqa from .common.desired_capabilities import DesiredCapabilities # noqa from .common.action_chains import ActionChains # noqa from .common.touch_actions import TouchActions # noqa from .common.proxy import Proxy # noqa __version__ = '3.8.0' selenium-3.8.0/selenium/webdriver/android/0000775000175000017500000000000013207771116021044 5ustar lucaslucas00000000000000selenium-3.8.0/selenium/webdriver/android/webdriver.py0000644000175000017500000000330713113073540023400 0ustar lucaslucas00000000000000# 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.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-3.8.0/selenium/webdriver/android/__init__.py0000644000175000017500000000142313113073540023143 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/common/0000775000175000017500000000000013207771116020714 5ustar lucaslucas00000000000000selenium-3.8.0/selenium/webdriver/common/utils.py0000644000175000017500000001020713113073540022414 0ustar lucaslucas00000000000000# 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 from selenium.webdriver.common.keys import Keys try: basestring except NameError: # Python 3 basestring = str 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 find_connectable_ip(host, port=None): """Resolve a hostname to an IP, preferring IPv4 addresses. We prefer IPv4 so that we don't change behavior from previous IPv4-only implementations, and because some drivers (e.g., FirefoxDriver) do not support IPv6 connections. If the optional port number is provided, only IPs that listen on the given port are considered. :Args: - host - A hostname. - port - Optional port number. :Returns: A single IP address, as a string. If any IPv4 address is found, one is returned. Otherwise, if any IPv6 address is found, one is returned. If neither, then None is returned. """ try: addrinfos = socket.getaddrinfo(host, None) except socket.gaierror: return None ip = None for family, _, _, _, sockaddr in addrinfos: connectable = True if port: connectable = is_connectable(port, sockaddr[0]) if connectable and family == socket.AF_INET: return sockaddr[0] if connectable and not ip and family == socket.AF_INET6: ip = sockaddr[0] return ip def join_host_port(host, port): """Joins a hostname and port together. This is a minimal implementation intended to cope with IPv6 literals. For example, _join_host_port('::1', 80) == '[::1]:80'. :Args: - host - A hostname. - port - An integer port. """ if ':' in host and not host.startswith('['): return '[%s]:%d' % (host, port) return '%s:%d' % (host, port) def is_connectable(port, host="localhost"): """ Tries to connect to the server at port to see if it is running. :Args: - port - The port to connect. """ socket_ = None try: socket_ = socket.create_connection((host, port), 1) result = True except socket.error: result = False finally: if socket_: 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 Exception: return False def keys_to_typing(value): """Processes the values that will be typed in the element.""" 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 selenium-3.8.0/selenium/webdriver/common/keys.py0000644000175000017500000000445313113073540022235 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/common/desired_capabilities.py0000664000175000017500000000637013201115155025411 0ustar lucaslucas00000000000000# 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", "marionette": True, "acceptInsecureCerts": True, } INTERNETEXPLORER = { "browserName": "internet explorer", "version": "", "platform": "WINDOWS", } EDGE = { "browserName": "MicrosoftEdge", "version": "", "platform": "WINDOWS" } CHROME = { "browserName": "chrome", "version": "", "platform": "ANY", } OPERA = { "browserName": "opera", "version": "", "platform": "ANY", } SAFARI = { "browserName": "safari", "version": "", "platform": "MAC", } HTMLUNIT = { "browserName": "htmlunit", "version": "", "platform": "ANY", } HTMLUNITWITHJS = { "browserName": "htmlunit", "version": "firefox", "platform": "ANY", "javascriptEnabled": True, } IPHONE = { "browserName": "iPhone", "version": "", "platform": "MAC", } IPAD = { "browserName": "iPad", "version": "", "platform": "MAC", } ANDROID = { "browserName": "android", "version": "", "platform": "ANDROID", } PHANTOMJS = { "browserName": "phantomjs", "version": "", "platform": "ANY", "javascriptEnabled": True, } WEBKITGTK = { "browserName": "MiniBrowser", "version": "", "platform": "ANY", } selenium-3.8.0/selenium/webdriver/common/html5/0000775000175000017500000000000013207771116021745 5ustar lucaslucas00000000000000selenium-3.8.0/selenium/webdriver/common/html5/__init__.py0000644000175000017500000000142313113073540024044 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/common/html5/application_cache.py0000644000175000017500000000262613113073540025741 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/common/by.py0000644000175000017500000000212713113073540021670 0ustar lucaslucas00000000000000# 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" selenium-3.8.0/selenium/webdriver/common/__init__.py0000644000175000017500000000142313113073540023013 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/common/action_chains.py0000644000175000017500000003162013164515255024072 0ustar lucaslucas00000000000000# 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, """ import time from selenium.webdriver.remote.command import Command from .utils import keys_to_typing from .actions.action_builder import ActionBuilder 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 = [] if self._driver.w3c: self.w3c_actions = ActionBuilder(driver) def perform(self): """ Performs all stored actions. """ if self._driver.w3c: self.w3c_actions.perform() else: for action in self._actions: action() def reset_actions(self): """ Clears actions that are already stored on the remote end. """ if self._driver.w3c: self._driver.execute(Command.W3C_CLEAR_ACTIONS) else: self._actions = [] def click(self, on_element=None): """ Clicks an element. :Args: - on_element: The element to click. If None, clicks on current mouse position. """ if self._driver.w3c: self.w3c_actions.pointer_action.click(on_element) self.w3c_actions.key_action.pause() self.w3c_actions.key_action.pause() else: 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 self._driver.w3c: self.w3c_actions.pointer_action.click_and_hold(on_element) self.w3c_actions.key_action.pause() if on_element: self.w3c_actions.key_action.pause() else: 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 self._driver.w3c: self.w3c_actions.pointer_action.context_click(on_element) self.w3c_actions.key_action.pause() else: 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 self._driver.w3c: self.w3c_actions.pointer_action.double_click(on_element) for _ in range(4): self.w3c_actions.key_action.pause() else: 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. """ if self._driver.w3c: self.w3c_actions.pointer_action.click_and_hold(source) \ .move_to(target) \ .release() for _ in range(3): self.w3c_actions.key_action.pause() else: 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. """ if self._driver.w3c: self.w3c_actions.pointer_action.click_and_hold(source) \ .move_to_location(xoffset, yoffset) \ .release() for _ in range(3): self.w3c_actions.key_action.pause() else: 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) if self._driver.w3c: self.w3c_actions.key_action.key_down(value) self.w3c_actions.pointer_action.pause() else: self._actions.append(lambda: self._driver.execute( Command.SEND_KEYS_TO_ACTIVE_ELEMENT, {"value": 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) if self._driver.w3c: self.w3c_actions.key_action.key_up(value) self.w3c_actions.pointer_action.pause() else: self._actions.append(lambda: self._driver.execute( Command.SEND_KEYS_TO_ACTIVE_ELEMENT, {"value": 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. """ if self._driver.w3c: self.w3c_actions.pointer_action.move_by(xoffset, yoffset) self.w3c_actions.key_action.pause() else: 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. """ if self._driver.w3c: self.w3c_actions.pointer_action.move_to(to_element) self.w3c_actions.key_action.pause() else: 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. """ if self._driver.w3c: self.w3c_actions.pointer_action.move_to(to_element, xoffset, yoffset) self.w3c_actions.key_action.pause() else: self._actions.append( lambda: self._driver.execute(Command.MOVE_TO, { 'element': to_element.id, 'xoffset': int(xoffset), 'yoffset': int(yoffset)})) return self def pause(self, seconds): """ Pause all inputs for the specified duration in seconds """ if self._driver.w3c: self.w3c_actions.pointer_action.pause(seconds) self.w3c_actions.key_action.pause(seconds) else: self._actions.append(lambda: time.sleep(seconds)) 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 self._driver.w3c: self.w3c_actions.pointer_action.release() self.w3c_actions.key_action.pause() else: 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. """ if self._driver.w3c: self.w3c_actions.key_action.send_keys(keys_to_send) else: self._actions.append(lambda: self._driver.execute( Command.SEND_KEYS_TO_ACTIVE_ELEMENT, {'value': 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. """ if self._driver.w3c: self.w3c_actions.key_action.send_keys(keys_to_send, element=element) else: self._actions.append(lambda: element.send_keys(*keys_to_send)) return self # 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-3.8.0/selenium/webdriver/common/proxy.py0000644000175000017500000002410713113073540022441 0ustar lucaslucas00000000000000# 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.socks_proxy = raw['socksProxy'] if 'socksUsername' in raw and raw['socksUsername'] is not None: self.socks_username = raw['socksUsername'] if 'socksPassword' in raw and raw['socksPassword'] is not None: self.socks_password = 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-3.8.0/selenium/webdriver/common/touch_actions.py0000644000175000017500000001353413113073540024124 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/common/alert.py0000644000175000017500000000716413113073540022373 0ustar lucaslucas00000000000000# 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.common.utils import keys_to_typing 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. """ if self.driver.w3c: return self.driver.execute(Command.W3C_GET_ALERT_TEXT)["value"] else: return self.driver.execute(Command.GET_ALERT_TEXT)["value"] def dismiss(self): """ Dismisses the alert available. """ if self.driver.w3c: self.driver.execute(Command.W3C_DISMISS_ALERT) else: self.driver.execute(Command.DISMISS_ALERT) def accept(self): """ Accepts the alert available. Usage:: Alert(driver).accept() # Confirm a alert dialog. """ if self.driver.w3c: self.driver.execute(Command.W3C_ACCEPT_ALERT) else: 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. """ if self.driver.w3c: self.driver.execute(Command.W3C_SET_ALERT_VALUE, {'value': keys_to_typing(keysToSend), 'text': keysToSend}) else: 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-3.8.0/selenium/webdriver/common/service.py0000644000175000017500000001317313113073540022721 0ustar lucaslucas00000000000000# 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 errno import os import platform import subprocess from subprocess import PIPE import time from selenium.common.exceptions import WebDriverException from selenium.webdriver.common import utils try: from subprocess import DEVNULL _HAS_NATIVE_DEVNULL = True except ImportError: DEVNULL = -3 _HAS_NATIVE_DEVNULL = False class Service(object): def __init__(self, executable, port=0, log_file=DEVNULL, env=None, start_error_message=""): self.path = executable self.port = port if self.port == 0: self.port = utils.free_port() if not _HAS_NATIVE_DEVNULL and log_file == DEVNULL: log_file = open(os.devnull, 'wb') self.start_error_message = start_error_message self.log_file = log_file self.env = env or os.environ @property def service_url(self): """ Gets the url of the Service """ return "http://%s" % utils.join_host_port('localhost', self.port) def command_line_args(self): raise NotImplemented("This method needs to be implemented in a sub class") def start(self): """ Starts the 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] cmd.extend(self.command_line_args()) self.process = subprocess.Popen(cmd, env=self.env, close_fds=platform.system() != 'Windows', stdout=self.log_file, stderr=self.log_file) except TypeError: raise except OSError as err: if err.errno == errno.ENOENT: raise WebDriverException( "'%s' executable needs to be in PATH. %s" % ( os.path.basename(self.path), self.start_error_message) ) elif err.errno == errno.EACCES: raise WebDriverException( "'%s' executable may have wrong permissions. %s" % ( os.path.basename(self.path), self.start_error_message) ) else: raise except Exception as e: raise WebDriverException( "The executable %s needs to be available in the path. %s\n%s" % (os.path.basename(self.path), self.start_error_message, str(e))) count = 0 while True: self.assert_process_still_running() if self.is_connectable(): break count += 1 time.sleep(1) if count == 30: raise WebDriverException("Can not connect to the Service %s" % self.path) def assert_process_still_running(self): return_code = self.process.poll() if return_code is not None: raise WebDriverException( 'Service %s unexpectedly exited. Status code was: %s' % (self.path, return_code) ) def is_connectable(self): return utils.is_connectable(self.port) def send_remote_shutdown_command(self): try: from urllib import request as url_request URLError = url_request.URLError except ImportError: import urllib2 as url_request import urllib2 URLError = urllib2.URLError try: url_request.urlopen("%s/shutdown" % self.service_url) except URLError: return for x in range(30): if not self.is_connectable(): break else: time.sleep(1) def stop(self): """ Stops the service. """ if self.log_file != PIPE and not (self.log_file == DEVNULL and _HAS_NATIVE_DEVNULL): try: self.log_file.close() except Exception: pass if self.process is None: return try: self.send_remote_shutdown_command() except TypeError: pass try: if self.process: for stream in [self.process.stdin, self.process.stdout, self.process.stderr]: try: stream.close() except AttributeError: pass self.process.terminate() self.process.wait() self.process.kill() self.process = None except OSError: pass def __del__(self): # `subprocess.Popen` doesn't send signal on `__del__`; # so we attempt to close the launched process when `__del__` # is triggered. try: self.stop() except Exception: pass selenium-3.8.0/selenium/webdriver/common/actions/0000775000175000017500000000000013207771116022354 5ustar lucaslucas00000000000000selenium-3.8.0/selenium/webdriver/common/actions/input_device.py0000644000175000017500000000237713113073540025403 0ustar lucaslucas00000000000000# 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 uuid class InputDevice(object): """ Describes the input device being used for the action. """ def __init__(self, name=None): if name is None: self.name = uuid.uuid4() else: self.name = name self.actions = [] def add_action(self, action): """ """ self.actions.append(action) def clear_actions(self): self.actions = [] def create_pause(self, duraton=0): pass selenium-3.8.0/selenium/webdriver/common/actions/mouse_button.py0000644000175000017500000000010613113073540025434 0ustar lucaslucas00000000000000class MouseButton(object): LEFT = 0 MIDDLE = 1 RIGHT = 2 selenium-3.8.0/selenium/webdriver/common/actions/pointer_input.py0000644000175000017500000000422013113073540025611 0ustar lucaslucas00000000000000# 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 .input_device import InputDevice from selenium.webdriver.remote.webelement import WebElement class PointerInput(InputDevice): DEFAULT_MOVE_DURATION = 250 def __init__(self, type_, name): super(PointerInput, self).__init__() self.type = type_ self.name = name def create_pointer_move(self, duration=DEFAULT_MOVE_DURATION, x=None, y=None, origin=None): action = dict(type="pointerMove", duration=duration) action["x"] = x action["y"] = y if isinstance(origin, WebElement): action["origin"] = {"element-6066-11e4-a52e-4f735466cecf": origin.id} elif origin is not None: action["origin"] = origin self.add_action(action) def create_pointer_down(self, button): self.add_action({"type": "pointerDown", "duration": 0, "button": button}) def create_pointer_up(self, button): self.add_action({"type": "pointerUp", "duration": 0, "button": button}) def create_pointer_cancel(self): self.add_action({"type": "pointerCancel"}) def create_pause(self, pause_duration): self.add_action({"type": "pause", "duration": pause_duration * 1000}) def encode(self): return {"type": self.type, "parameters": {"pointerType": self.name}, "id": self.name, "actions": [acts for acts in self.actions]} selenium-3.8.0/selenium/webdriver/common/actions/key_actions.py0000644000175000017500000000353113113073540025226 0ustar lucaslucas00000000000000# 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 .interaction import Interaction from .key_input import KeyInput from ..utils import keys_to_typing class KeyActions(Interaction): def __init__(self, source=None): if source is None: source = KeyInput() self.source = source super(KeyActions, self).__init__(source) def key_down(self, letter, element=None): return self._key_action("create_key_down", letter, element) def key_up(self, letter, element=None): return self._key_action("create_key_up", letter, element) def pause(self, duration=0): return self._key_action("create_pause", duration) def send_keys(self, text, element=None): if not isinstance(text, list): text = keys_to_typing(text) for letter in text: self.key_down(letter, element) self.key_up(letter, element) return self def _key_action(self, action, letter, element=None): meth = getattr(self.source, action) meth(letter) return self selenium-3.8.0/selenium/webdriver/common/actions/interaction.py0000644000175000017500000000242413113073540025235 0ustar lucaslucas00000000000000# 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. KEY = "key" POINTER = "pointer" NONE = "none" SOURCE_TYPES = set([KEY, POINTER, NONE]) class Interaction(object): PAUSE = "pause" def __init__(self, source): self.source = source class Pause(Interaction): def __init__(self, source, duration=0): super(Interaction, self).__init__() self.source = source self.duration = duration def encode(self): output = {"type": self.PAUSE} output["duration"] = self.duration * 1000 return output selenium-3.8.0/selenium/webdriver/common/actions/__init__.py0000644000175000017500000000142313113073540024453 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/common/actions/pointer_actions.py0000644000175000017500000000640113113073540026115 0ustar lucaslucas00000000000000# 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 interaction from .interaction import Interaction from .mouse_button import MouseButton from .pointer_input import PointerInput from selenium.webdriver.remote.webelement import WebElement class PointerActions(Interaction): def __init__(self, source=None): if source is None: source = PointerInput(interaction.POINTER, "mouse") self.source = source super(PointerActions, self).__init__(source) def pointer_down(self, button=MouseButton.LEFT): self._button_action("create_pointer_down", button=button) def pointer_up(self, button=MouseButton.LEFT): self._button_action("create_pointer_up", button=button) def move_to(self, element, x=None, y=None): if not isinstance(element, WebElement): raise AttributeError("move_to requires a WebElement") if x is not None or y is not None: el_rect = element.rect left_offset = el_rect['width'] / 2 top_offset = el_rect['height'] / 2 left = -left_offset + (x or 0) top = -top_offset + (y or 0) else: left = 0 top = 0 self.source.create_pointer_move(origin=element, x=int(left), y=int(top)) return self def move_by(self, x, y): self.source.create_pointer_move(origin=interaction.POINTER, x=int(x), y=int(y)) return self def move_to_location(self, x, y): self.source.create_pointer_move(origin='viewport', x=int(x), y=int(y)) return self def click(self, element=None): if element: self.move_to(element) self.pointer_down(MouseButton.LEFT) self.pointer_up(MouseButton.LEFT) return self def context_click(self, element=None): if element: self.move_to(element) self.pointer_down(MouseButton.RIGHT) self.pointer_up(MouseButton.RIGHT) return self def click_and_hold(self, element=None): if element: self.move_to(element) self.pointer_down() return self def release(self): self.pointer_up() return self def double_click(self, element=None): if element: self.move_to(element) self.click() self.click() def pause(self, duration=0): self.source.create_pause(duration) return self def _button_action(self, action, button=MouseButton.LEFT): meth = getattr(self.source, action) meth(button) return self selenium-3.8.0/selenium/webdriver/common/actions/action_builder.py0000644000175000017500000000525013152340567025712 0ustar lucaslucas00000000000000# 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.command import Command from . import interaction from .key_actions import KeyActions from .key_input import KeyInput from .pointer_actions import PointerActions from .pointer_input import PointerInput class ActionBuilder(object): def __init__(self, driver, mouse=None, keyboard=None): if mouse is None: mouse = PointerInput(interaction.POINTER, "mouse") if keyboard is None: keyboard = KeyInput(interaction.KEY) self.devices = [mouse, keyboard] self._key_action = KeyActions(keyboard) self._pointer_action = PointerActions(mouse) self.driver = driver def get_device_with(self, name): try: idx = self.devices.index(name) return self.devices[idx] except: pass @property def pointer_inputs(self): return [device for device in self.devices if device.type == interaction.POINTER] @property def key_inputs(self): return [device for device in self.devices if device.type == interaction.KEY] @property def key_action(self): return self._key_action @property def pointer_action(self): return self._pointer_action def add_key_input(self, name): new_input = KeyInput(name) self._add_input(new_input) return new_input def add_pointer_input(self, type_, name): new_input = PointerInput(type_, name) self._add_input(new_input) return new_input def perform(self): enc = {"actions": []} for device in self.devices: encoded = device.encode() if encoded['actions']: enc["actions"].append(encoded) self.driver.execute(Command.W3C_ACTIONS, enc) def clear_actions(self): self.driver.execute(Command.W3C_CLEAR_ACTIONS) def _add_input(self, input): self.devices.append(input) selenium-3.8.0/selenium/webdriver/common/actions/key_input.py0000644000175000017500000000336613113073540024733 0ustar lucaslucas00000000000000# 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 interaction from .input_device import InputDevice from .interaction import (Interaction, Pause) class KeyInput(InputDevice): def __init__(self, name): super(KeyInput, self).__init__() self.name = name self.type = interaction.KEY def encode(self): return {"type": self.type, "id": self.name, "actions": [acts.encode() for acts in self.actions]} def create_key_down(self, key): self.add_action(TypingInteraction(self, "keyDown", key)) def create_key_up(self, key): self.add_action(TypingInteraction(self, "keyUp", key)) def create_pause(self, pause_duration=0): self.add_action(Pause(self, pause_duration)) class TypingInteraction(Interaction): def __init__(self, source, type_, key): super(TypingInteraction, self).__init__(source) self.type = type_ self.key = key def encode(self): return {"type": self.type, "value": self.key} selenium-3.8.0/selenium/webdriver/blackberry/0000775000175000017500000000000013207771116021544 5ustar lucaslucas00000000000000selenium-3.8.0/selenium/webdriver/blackberry/webdriver.py0000644000175000017500000001140613113073540024077 0ustar lucaslucas00000000000000# 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 subprocess try: import http.client as http_client except ImportError: import httplib as http_client 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-3.8.0/selenium/webdriver/blackberry/__init__.py0000644000175000017500000000142313113073540023643 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/chrome/0000775000175000017500000000000013207771116020701 5ustar lucaslucas00000000000000selenium-3.8.0/selenium/webdriver/chrome/options.py0000664000175000017500000001350213203325736022746 0ustar lucaslucas00000000000000# 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 import os from selenium.webdriver.common.desired_capabilities import DesiredCapabilities class Options(object): KEY = "goog:chromeOptions" 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: extension_to_add = os.path.abspath(os.path.expanduser(extension)) if os.path.exists(extension_to_add): self._extension_files.append(extension_to_add) 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 @property def headless(self): """ Returns whether or not the headless argument is set """ return '--headless' in self._arguments def set_headless(self, headless=True): """ Sets the headless argument Args: headless: boolean value indicating to set the headless option """ args = {'--headless', '--disable-gpu'} if headless: self._arguments.extend(args) else: self._arguments = list(set(self._arguments) - args) 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[self.KEY] = chrome_options return chrome selenium-3.8.0/selenium/webdriver/chrome/webdriver.py0000664000175000017500000001125513201115155023235 0ustar lucaslucas00000000000000# 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 warnings from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver 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, options=None, service_args=None, desired_capabilities=None, service_log_path=None, chrome_options=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". - options: this takes an instance of ChromeOptions """ if chrome_options: warnings.warn('use options instead of chrome_options', DeprecationWarning) options = chrome_options if 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 = options.to_capabilities() else: desired_capabilities.update(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 Exception: 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 get_network_conditions(self): """ Gets Chrome network emulation settings. :Returns: A dict. For example: {'latency': 4, 'download_throughput': 2, 'upload_throughput': 2, 'offline': False} """ return self.execute("getNetworkConditions")['value'] def set_network_conditions(self, **network_conditions): """ Sets Chrome network emulation settings. :Args: - network_conditions: A dict with conditions specification. :Usage: driver.set_network_conditions( offline=False, latency=5, # additional latency (ms) download_throughput=500 * 1024, # maximal throughput upload_throughput=500 * 1024) # maximal throughput Note: 'throughput' can be used to set both (for download and upload). """ self.execute("setNetworkConditions", { 'network_conditions': network_conditions }) def quit(self): """ Closes the browser and shuts down the ChromeDriver executable that is started when starting the ChromeDriver """ try: RemoteWebDriver.quit(self) except Exception: # 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-3.8.0/selenium/webdriver/chrome/remote_connection.py0000644000175000017500000000251013144316447024763 0ustar lucaslucas00000000000000# 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') self._commands["setNetworkConditions"] = ('POST', '/session/$sessionId/chromium/network_conditions') self._commands["getNetworkConditions"] = ('GET', '/session/$sessionId/chromium/network_conditions') selenium-3.8.0/selenium/webdriver/chrome/__init__.py0000644000175000017500000000142313113073540023000 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/chrome/service.py0000644000175000017500000000343113113073540022702 0ustar lucaslucas00000000000000# 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 service class Service(service.Service): """ 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.service_args = service_args or [] if log_path: self.service_args.append('--log-path=%s' % log_path) service.Service.__init__(self, executable_path, port=port, env=env, start_error_message="Please see https://sites.google.com/a/chromium.org/chromedriver/home") def command_line_args(self): return ["--port=%d" % self.port] + self.service_args selenium-3.8.0/selenium/webdriver/firefox/0000775000175000017500000000000013207771116021066 5ustar lucaslucas00000000000000selenium-3.8.0/selenium/webdriver/firefox/amd64/0000775000175000017500000000000013207771116022001 5ustar lucaslucas00000000000000selenium-3.8.0/selenium/webdriver/firefox/options.py0000644000175000017500000001160613203327522023127 0ustar lucaslucas00000000000000# 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 InvalidArgumentException from selenium.webdriver.common.proxy import Proxy from selenium.webdriver.firefox.firefox_binary import FirefoxBinary from selenium.webdriver.firefox.firefox_profile import FirefoxProfile class Log(object): def __init__(self): self.level = None def to_capabilities(self): if self.level is not None: return {"log": {"level": self.level}} return {} class Options(object): KEY = "moz:firefoxOptions" def __init__(self): self._binary = None self._preferences = {} self._profile = None self._proxy = None self._arguments = [] self.log = Log() @property def binary(self): """Returns the FirefoxBinary instance""" return self._binary @binary.setter def binary(self, new_binary): """Sets location of the browser binary, either by string or ``FirefoxBinary`` instance. """ if not isinstance(new_binary, FirefoxBinary): new_binary = FirefoxBinary(new_binary) self._binary = new_binary @property def binary_location(self): """Returns the location of the binary.""" return self.binary._start_cmd @binary_location.setter # noqa def binary_location(self, value): """ Sets the location of the browser binary by string """ self.binary = value @property def preferences(self): """Returns a dict of preferences.""" return self._preferences def set_preference(self, name, value): """Sets a preference.""" self._preferences[name] = value @property def proxy(self): """ returns Proxy if set otherwise None.""" return self._proxy @proxy.setter def proxy(self, value): if not isinstance(value, Proxy): raise InvalidArgumentException("Only Proxy objects can be passed in.") self._proxy = value @property def profile(self): """Returns the Firefox profile to use.""" return self._profile @profile.setter def profile(self, new_profile): """Sets location of the browser profile to use, either by string or ``FirefoxProfile``. """ if not isinstance(new_profile, FirefoxProfile): new_profile = FirefoxProfile(new_profile) self._profile = new_profile @property def arguments(self): """Returns a list of browser process arguments.""" return self._arguments def add_argument(self, argument): """Add argument to be used for the browser process.""" if argument is None: raise ValueError() self._arguments.append(argument) @property def headless(self): """ Returns whether or not the headless argument is set """ return '-headless' in self._arguments def set_headless(self, headless=True): """ Sets the headless argument Args: headless: boolean value indicating to set the headless option """ if headless: self._arguments.append('-headless') elif '-headless' in self._arguments: self._arguments.remove('-headless') def to_capabilities(self): """Marshals the Firefox options to a `moz:firefoxOptions` object. """ # This intentionally looks at the internal properties # so if a binary or profile has _not_ been set, # it will defer to geckodriver to find the system Firefox # and generate a fresh profile. opts = {} if self._binary is not None: opts["binary"] = self._binary._start_cmd if len(self._preferences) > 0: opts["prefs"] = self._preferences if self._proxy is not None: self._proxy.add_to_capabilities(opts) if self._profile is not None: opts["profile"] = self._profile.encoded if len(self._arguments) > 0: opts["args"] = self._arguments opts.update(self.log.to_capabilities()) if len(opts) > 0: return {Options.KEY: opts} return {} selenium-3.8.0/selenium/webdriver/firefox/firefox_profile.py0000664000175000017500000003461213173513222024622 0ustar lucaslucas00000000000000# 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): 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 """ self.update_preferences() 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 Exception: warnings.warn("(skipping) failed to json.loads existing preference: " + matches.group(1) + matches.group(2)) except Exception: # 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, absolute 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-3.8.0/selenium/webdriver/firefox/webdriver.py0000664000175000017500000002271013201115155023420 0ustar lucaslucas00000000000000# 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 warnings try: import http.client as http_client except ImportError: import httplib as http_client try: basestring except NameError: # Python 3.x basestring = str import shutil import socket import sys from contextlib import contextmanager from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver from .extension_connection import ExtensionConnection from .firefox_binary import FirefoxBinary from .firefox_profile import FirefoxProfile from .options import Options from .remote_connection import FirefoxRemoteConnection from .service import Service from .webelement import FirefoxWebElement class WebDriver(RemoteWebDriver): # There is no native event support on Mac NATIVE_EVENTS_ALLOWED = sys.platform != "darwin" CONTEXT_CHROME = "chrome" CONTEXT_CONTENT = "content" _web_element_cls = FirefoxWebElement def __init__(self, firefox_profile=None, firefox_binary=None, timeout=30, capabilities=None, proxy=None, executable_path="geckodriver", options=None, log_path="geckodriver.log", firefox_options=None): """Starts a new local session of Firefox. Based on the combination and specificity of the various keyword arguments, a capabilities dictionary will be constructed that is passed to the remote end. The keyword arguments given to this constructor are helpers to more easily allow Firefox WebDriver sessions to be customised with different options. They are mapped on to a capabilities dictionary that is passed on to the remote end. As some of the options, such as `firefox_profile` and `options.profile` are mutually exclusive, precedence is given from how specific the setting is. `capabilities` is the least specific keyword argument, followed by `options`, followed by `firefox_binary` and `firefox_profile`. In practice this means that if `firefox_profile` and `options.profile` are both set, the selected profile instance will always come from the most specific variable. In this case that would be `firefox_profile`. This will result in `options.profile` to be ignored because it is considered a less specific setting than the top-level `firefox_profile` keyword argument. Similarily, if you had specified a `capabilities["moz:firefoxOptions"]["profile"]` Base64 string, this would rank below `options.profile`. :param firefox_profile: Instance of ``FirefoxProfile`` object or a string. If undefined, a fresh profile will be created in a temporary location on the system. :param firefox_binary: Instance of ``FirefoxBinary`` or full path to the Firefox binary. If undefined, the system default Firefox installation will be used. :param timeout: Time to wait for Firefox to launch when using the extension connection. :param capabilities: Dictionary of desired capabilities. :param proxy: The proxy settings to us when communicating with Firefox via the extension connection. :param executable_path: Full path to override which geckodriver binary to use for Firefox 47.0.1 and greater, which defaults to picking up the binary from the system path. :param options: Instance of ``options.Options``. :param log_path: Where to log information from the driver. """ if firefox_options: warnings.warn('use options instead of firefox_options', DeprecationWarning) options = firefox_options self.binary = None self.profile = None self.service = None if capabilities is None: capabilities = DesiredCapabilities.FIREFOX.copy() if options is None: options = Options() capabilities = dict(capabilities) if capabilities.get("binary"): self.binary = capabilities["binary"] # options overrides capabilities if options is not None: if options.binary is not None: self.binary = options.binary if options.profile is not None: self.profile = options.profile # firefox_binary and firefox_profile # override options if firefox_binary is not None: if isinstance(firefox_binary, basestring): firefox_binary = FirefoxBinary(firefox_binary) self.binary = firefox_binary options.binary = firefox_binary if firefox_profile is not None: if isinstance(firefox_profile, basestring): firefox_profile = FirefoxProfile(firefox_profile) self.profile = firefox_profile options.profile = firefox_profile # W3C remote # TODO(ato): Perform conformance negotiation if capabilities.get("marionette"): capabilities.pop("marionette") self.service = Service(executable_path, log_path=log_path) self.service.start() capabilities.update(options.to_capabilities()) executor = FirefoxRemoteConnection( remote_server_addr=self.service.service_url) RemoteWebDriver.__init__( self, command_executor=executor, desired_capabilities=capabilities, keep_alive=True) # Selenium remote else: if self.binary is None: self.binary = FirefoxBinary() if self.profile is None: self.profile = FirefoxProfile() # disable native events if globally disabled self.profile.native_events_enabled = ( self.NATIVE_EVENTS_ALLOWED and self.profile.native_events_enabled) if proxy is not None: proxy.add_to_capabilities(capabilities) executor = ExtensionConnection("127.0.0.1", self.profile, self.binary, timeout) RemoteWebDriver.__init__( self, command_executor=executor, 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 self.w3c: self.service.stop() else: self.binary.kill() if self.profile is not None: 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 # Extension commands: def set_context(self, context): self.execute("SET_CONTEXT", {"context": context}) @contextmanager def context(self, context): """Sets the context that Selenium commands are running in using a `with` statement. The state of the context on the server is saved before entering the block, and restored upon exiting it. :param context: Context, may be one of the class properties `CONTEXT_CHROME` or `CONTEXT_CONTENT`. Usage example:: with selenium.context(selenium.CONTEXT_CHROME): # chrome scope ... do stuff ... """ initial_context = self.execute('GET_CONTEXT').pop('value') self.set_context(context) try: yield finally: self.set_context(initial_context) def install_addon(self, path, temporary=None): """ Installs Firefox addon. Returns identifier of installed addon. This identifier can later be used to uninstall addon. :param path: Absolute path to the addon that will be installed. :Usage: driver.install_addon('/path/to/firebug.xpi') """ payload = {"path": path} if temporary is not None: payload["temporary"] = temporary return self.execute("INSTALL_ADDON", payload)["value"] def uninstall_addon(self, identifier): """ Uninstalls Firefox addon using its identifier. :Usage: driver.uninstall_addon('addon@foo.com') """ self.execute("UNINSTALL_ADDON", {"id": identifier}) selenium-3.8.0/selenium/webdriver/firefox/firefox_binary.py0000644000175000017500000002106013113073540024433 0ustar lucaslucas00000000000000# 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 WebDriverException( "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\nbinary = " "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, timeout=30): """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(timeout=timeout) 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, timeout=30): """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 >= timeout: self.kill() raise WebDriverException( "Can't load the profile. Possible firefox version mismatch. " "You must use GeckoDriver instead for Firefox 48+. Profile " "Dir: %s If you specified a log_file in the " "FirefoxBinary constructor, check it for details." % (self.profile.path)) 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" # fallback to homebrew installation for mac users if not os.path.exists(start_cmd): start_cmd = os.path.expanduser("~") + start_cmd 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-3.8.0/selenium/webdriver/firefox/remote_connection.py0000644000175000017500000000326713144316447025162 0ustar lucaslucas00000000000000# 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 FirefoxRemoteConnection(RemoteConnection): def __init__(self, remote_server_addr, keep_alive=True): RemoteConnection.__init__(self, remote_server_addr, keep_alive) self._commands["GET_CONTEXT"] = ('GET', '/session/$sessionId/moz/context') self._commands["SET_CONTEXT"] = ("POST", "/session/$sessionId/moz/context") self._commands["ELEMENT_GET_ANONYMOUS_CHILDREN"] = \ ("POST", "/session/$sessionId/moz/xbl/$id/anonymous_children") self._commands["ELEMENT_FIND_ANONYMOUS_ELEMENTS_BY_ATTRIBUTE"] = \ ("POST", "/session/$sessionId/moz/xbl/$id/anonymous_by_attribute") self._commands["INSTALL_ADDON"] = \ ("POST", "/session/$sessionId/moz/addon/install") self._commands["UNINSTALL_ADDON"] = \ ("POST", "/session/$sessionId/moz/addon/uninstall") selenium-3.8.0/selenium/webdriver/firefox/webelement.py0000644000175000017500000000374713113073540023570 0ustar lucaslucas00000000000000# 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.webelement import WebElement as RemoteWebElement class FirefoxWebElement(RemoteWebElement): @property def anonymous_children(self): """Retrieve the anonymous children of this element in an XBL context. This is only available in chrome context. See the `anonymous content documentation `_ on MDN for more information. """ return self._execute( "ELEMENT_GET_ANONYMOUS_CHILDREN", {"value": None}) def find_anonymous_element_by_attribute(self, name, value): """Retrieve an anonymous descendant with a specified attribute value. Typically used with an (arbitrary) anonid attribute to retrieve a specific anonymous child in an XBL binding. See the `anonymous content documentation `_ on MDN for more information. """ return self._execute( "ELEMENT_FIND_ANONYMOUS_ELEMENTS_BY_ATTRIBUTE", {"name": name, "value": value})["value"] selenium-3.8.0/selenium/webdriver/firefox/extension_connection.py0000644000175000017500000000547313113073540025672 0ustar lucaslucas00000000000000# 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 timeout = int(timeout) 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, timeout=timeout) _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-3.8.0/selenium/webdriver/firefox/__init__.py0000644000175000017500000000142313113073540023165 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/firefox/x86/0000775000175000017500000000000013207771116021513 5ustar lucaslucas00000000000000selenium-3.8.0/selenium/webdriver/firefox/webdriver_prefs.json0000644000175000017500000000546213164514013025147 0ustar lucaslucas00000000000000{ "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.checkCompatibility.nightly": 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.fileuri.origin_policy": 3, "security.fileuri.strict_origin_policy": false, "signon.rememberSignons": false, "toolkit.networkmanager.disable": true, "toolkit.telemetry.prompted": 2, "toolkit.telemetry.enabled": false, "toolkit.telemetry.rejected": true, "xpinstall.signatures.required": false, "xpinstall.whitelist.required": false }, "mutable": { "browser.dom.window.dump.enabled": true, "browser.laterrun.enabled": false, "browser.newtab.url": "about:blank", "browser.newtabpage.enabled": false, "browser.startup.page": 0, "browser.startup.homepage": "about:blank", "browser.startup.homepage_override.mstone": "ignore", "browser.usedOnWindows10.introURL": "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.captive-portal-service.enabled": false, "security.csp.enable": false, "startup.homepage_welcome_url": "about:blank", "startup.homepage_welcome_url.additional": "about:blank", "webdriver_accept_untrusted_certs": true, "webdriver_assume_untrusted_issuer": true } } selenium-3.8.0/selenium/webdriver/firefox/service.py0000644000175000017500000000432513165444751023107 0ustar lucaslucas00000000000000# 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 service class Service(service.Service): """Object that manages the starting and stopping of the GeckoDriver.""" def __init__(self, executable_path, port=0, service_args=None, log_path="geckodriver.log", env=None): """Creates a new instance of the GeckoDriver remote service proxy. GeckoDriver provides a HTTP interface speaking the W3C WebDriver protocol to Marionette. :param executable_path: Path to the GeckoDriver binary. :param port: Run the remote service on a specified port. Defaults to 0, which binds to a random open port of the system's choosing. :param service_args: Optional list of arguments to pass to the GeckoDriver binary. :param log_path: Optional path for the GeckoDriver to log to. Defaults to _geckodriver.log_ in the current working directory. :param env: Optional dictionary of output variables to expose in the services' environment. """ log_file = open(log_path, "a+") if log_path is not None and log_path != "" else None service.Service.__init__( self, executable_path, port=port, log_file=log_file, env=env) self.service_args = service_args or [] def command_line_args(self): return ["--port", "%d" % self.port] + self.service_args def send_remote_shutdown_command(self): pass selenium-3.8.0/selenium/webdriver/remote/0000775000175000017500000000000013207771116020717 5ustar lucaslucas00000000000000selenium-3.8.0/selenium/webdriver/remote/switch_to.py0000664000175000017500000001073113174354352023300 0ustar lucaslucas00000000000000# 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 from selenium.webdriver.common.by import By from selenium.common.exceptions import NoSuchElementException, NoSuchFrameException, NoSuchWindowException try: basestring except NameError: basestring = str 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 """ if self._driver.w3c: return self._driver.execute(Command.W3C_GET_ACTIVE_ELEMENT)['value'] else: 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]) """ if isinstance(frame_reference, basestring) and self._driver.w3c: try: frame_reference = self._driver.find_element(By.ID, frame_reference) except NoSuchElementException: try: frame_reference = self._driver.find_element(By.NAME, frame_reference) except NoSuchElementException: raise NoSuchFrameException(frame_reference) 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') """ if self._driver.w3c: self._w3c_window(window_name) return data = {'name': window_name} self._driver.execute(Command.SWITCH_TO_WINDOW, data) def _w3c_window(self, window_name): def send_handle(h): self._driver.execute(Command.SWITCH_TO_WINDOW, {'handle': h}) try: # Try using it as a handle first. send_handle(window_name) except NoSuchWindowException as e: # Check every window to try to find the given window name. original_handle = self._driver.current_window_handle handles = self._driver.window_handles for handle in handles: send_handle(handle) current_name = self._driver.execute_script('return window.name') if window_name == current_name: return send_handle(original_handle) raise e selenium-3.8.0/selenium/webdriver/remote/file_detector.py0000644000175000017500000000316713113073540024076 0ustar lucaslucas00000000000000# 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.utils import keys_to_typing 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 = ''.join(keys_to_typing(keys)) if not file_path: return None try: if os.path.isfile(file_path): return file_path except Exception: pass return None selenium-3.8.0/selenium/webdriver/remote/utils.py0000644000175000017500000000713613113073540022426 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/remote/webdriver.py0000664000175000017500000011174713201115155023262 0ustar lucaslucas00000000000000# 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 copy import warnings from contextlib import contextmanager 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 (InvalidArgumentException, WebDriverException) from selenium.webdriver.common.by import By from selenium.webdriver.common.html5.application_cache import ApplicationCache try: str = basestring except NameError: pass _W3C_CAPABILITY_NAMES = frozenset([ 'acceptInsecureCerts', 'browserName', 'browserVersion', 'platformName', 'pageLoadStrategy', 'proxy', 'setWindowRect', 'timeouts', 'unhandledPromptBehavior', ]) _OSS_W3C_CONVERSION = { 'acceptSslCerts': 'acceptInsecureCerts', 'version': 'browserVersion', 'platform': 'platformName' } def _make_w3c_caps(caps): """Makes a W3C alwaysMatch capabilities object. Filters out capability names that are not in the W3C spec. Spec-compliant drivers will reject requests containing unknown capability names. Moves the Firefox profile, if present, from the old location to the new Firefox options object. :Args: - caps - A dictionary of capabilities requested by the caller. """ caps = copy.deepcopy(caps) profile = caps.get('firefox_profile') always_match = {} if caps.get('proxy') and caps['proxy'].get('proxyType'): caps['proxy']['proxyType'] = caps['proxy']['proxyType'].lower() for k, v in caps.items(): if v and k in _OSS_W3C_CONVERSION: always_match[_OSS_W3C_CONVERSION[k]] = v.lower() if k == 'platform' else v if k in _W3C_CAPABILITY_NAMES or ':' in k: always_match[k] = v if profile: moz_opts = always_match.get('moz:firefoxOptions', {}) # If it's already present, assume the caller did that intentionally. if 'profile' not in moz_opts: # Don't mutate the original capabilities. new_opts = copy.deepcopy(moz_opts) new_opts['profile'] = profile always_match['moz:firefoxOptions'] = new_opts return {"firstMatch": [{}], "alwaysMatch": always_match} 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. """ _web_element_cls = WebElement def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities=None, browser_profile=None, proxy=None, keep_alive=False, file_detector=None, options=None): """ 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. - file_detector - Pass custom file detector object during instantiation. If None, then default LocalFileDetector() will be used. - options - instance of a driver options.Options class """ 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: warnings.warn("Please use FirefoxOptions to set proxy", DeprecationWarning) proxy.add_to_capabilities(desired_capabilities) if options is not None: desired_capabilities.update(options.to_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() if browser_profile is not None: warnings.warn("Please use FirefoxOptions to set browser profile", DeprecationWarning) self.start_session(desired_capabilities, browser_profile) self._switch_to = SwitchTo(self) self._mobile = Mobile(self) self.file_detector = file_detector or LocalFileDetector() def __repr__(self): return '<{0.__module__}.{0.__name__} (session="{1}")>'.format( type(self), self.session_id) @contextmanager def file_detector_context(self, file_detector_class, *args, **kwargs): """ Overrides the current file detector (if necessary) in limited context. Ensures the original file detector is set afterwards. Example: with webdriver.file_detector_context(UselessFileDetector): someinput.send_keys('/etc/hosts') :Args: - file_detector_class - Class of the desired file detector. If the class is different from the current file_detector, then the class is instantiated with args and kwargs and used as a file detector during the duration of the context manager. - args - Optional arguments that get passed to the file detector class during instantiation. - kwargs - Keyword arguments, passed the same way as args. """ last_detector = None if not isinstance(self.file_detector, file_detector_class): last_detector = self.file_detector self.file_detector = file_detector_class(*args, **kwargs) try: yield finally: if last_detector is not None: self.file_detector = last_detector @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, 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 not isinstance(capabilities, dict): raise InvalidArgumentException("Capabilities must be a dictionary") if browser_profile: if "moz:firefoxOptions" in capabilities: capabilities["moz:firefoxOptions"]["profile"] = browser_profile.encoded else: capabilities.update({'firefox_profile': browser_profile.encoded}) w3c_caps = _make_w3c_caps(capabilities) parameters = {"capabilities": w3c_caps, "desiredCapabilities": capabilities} response = self.execute(Command.NEW_SESSION, parameters) if 'sessionId' not in response: response = response['value'] self.session_id = response['sessionId'] self.capabilities = response.get('value') # if capabilities is none we are probably speaking to # a W3C endpoint if self.capabilities is None: self.capabilities = response.get('capabilities') # Double check to see if we have a W3C Compliant browser self.w3c = response.get('status') is None 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, self._web_element_cls): 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 self._web_element_cls(self, element_id, w3c=self.w3c) def _unwrap_value(self, value): if isinstance(value, dict): if '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']) else: for key, val in value.items(): value[key] = self._unwrap_value(val) return value 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) command = None if self.w3c: command = Command.W3C_EXECUTE_SCRIPT else: command = Command.EXECUTE_SCRIPT return self.execute(command, { '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) if self.w3c: command = Command.W3C_EXECUTE_SCRIPT_ASYNC else: command = Command.EXECUTE_ASYNC_SCRIPT return self.execute(command, { '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 """ if self.w3c: return self.execute(Command.W3C_GET_CURRENT_WINDOW_HANDLE)['value'] else: 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 """ if self.w3c: return self.execute(Command.W3C_GET_WINDOW_HANDLES)['value'] else: 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"}) def fullscreen_window(self): """ Invokes the window manager-specific 'full screen' operation """ self.execute(Command.FULLSCREEN_WINDOW) def minimize_window(self): """ Invokes the window manager-specific 'minimize' operation """ self.execute(Command.MINIMIZE_WINDOW) @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, { 'implicit': int(float(time_to_wait) * 1000)}) 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, { 'script': int(float(time_to_wait) * 1000)}) 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) """ try: self.execute(Command.SET_TIMEOUTS, { 'pageLoad': int(float(time_to_wait) * 1000)}) except WebDriverException: 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 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 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 empty list if driver returns null # See https://github.com/SeleniumHQ/selenium/issues/4555 return self.execute(Command.FIND_ELEMENTS, { 'using': by, 'value': value})['value'] or [] @property def desired_capabilities(self): """ returns the drivers current desired capabilities being used """ return self.capabilities def get_screenshot_as_file(self, filename): """ Saves a screenshot of the current window to a PNG image file. 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. This should end with a `.png` extension. :Usage: driver.get_screenshot_as_file('/Screenshots/foo.png') """ if not filename.lower().endswith('.png'): warnings.warn("name used for saved screenshot does not match file " "type. It should end with a `.png` extension", UserWarning) 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 def save_screenshot(self, filename): """ Saves a screenshot of the current window to a PNG image file. 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. This should end with a `.png` extension. :Usage: driver.save_screenshot('/Screenshots/foo.png') """ return self.get_screenshot_as_file(filename) 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) """ if self.w3c: if windowHandle != 'current': warnings.warn("Only 'current' window is supported for W3C compatibile browsers.") self.set_window_rect(width=int(width), height=int(height)) else: self.execute(Command.SET_WINDOW_SIZE, { '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: if windowHandle != 'current': warnings.warn("Only 'current' window is supported for W3C compatibile browsers.") size = self.get_window_rect() else: size = self.execute(command, {'windowHandle': windowHandle}) if size.get('value', None) is not None: size = size['value'] return {k: size[k] for k in ('width', 'height')} 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) """ if self.w3c: if windowHandle != 'current': warnings.warn("Only 'current' window is supported for W3C compatibile browsers.") return self.set_window_rect(x=int(x), y=int(y)) else: 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() """ if self.w3c: if windowHandle != 'current': warnings.warn("Only 'current' window is supported for W3C compatibile browsers.") position = self.get_window_rect() else: position = self.execute(Command.GET_WINDOW_POSITION, {'windowHandle': windowHandle})['value'] return {k: position[k] for k in ('x', 'y')} def get_window_rect(self): """ Gets the x, y coordinates of the window as well as height and width of the current window. :Usage: driver.get_window_rect() """ return self.execute(Command.GET_WINDOW_RECT)['value'] def set_window_rect(self, x=None, y=None, width=None, height=None): """ Sets the x, y coordinates of the window as well as height and width of the current window. :Usage: driver.set_window_rect(x=10, y=10) driver.set_window_rect(width=100, height=200) driver.set_window_rect(x=10, y=10, width=100, height=200) """ if (x is None and y is None) and (height is None and width is None): raise InvalidArgumentException("x and y or height and width need values") return self.execute(Command.SET_WINDOW_RECT, {"x": x, "y": y, "width": width, "height": height})['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 is 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-3.8.0/selenium/webdriver/remote/remote_connection.py0000664000175000017500000005715413174246106025016 0ustar lucaslucas00000000000000# 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 selenium.webdriver.common import utils as common_utils 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 @classmethod def get_remote_connection_headers(cls, parsed_url, keep_alive=False): """ Get headers for remote request. :Args: - parsed_url - The parsed url - keep_alive (Boolean) - Is this a keep-alive connection (default: False) """ headers = { 'Accept': 'application/json', 'Content-Type': 'application/json;charset=UTF-8', 'User-Agent': 'Python http auth' } if parsed_url.username: base64string = base64.b64encode('{0.username}:{0.password}'.format(parsed_url).encode()) headers.update({ 'Authorization': 'Basic {}'.format(base64string.decode()) }) if keep_alive: headers.update({ 'Connection': 'keep-alive' }) return headers 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 = parsed_url.hostname if parsed_url.hostname and resolve_ip: port = parsed_url.port or None if parsed_url.scheme == "https": ip = parsed_url.hostname else: ip = common_utils.find_connectable_ip(parsed_url.hostname, port=port) if ip: netloc = ip addr = netloc if parsed_url.port: netloc = common_utils.join_host_port(netloc, 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)) else: 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.W3C_GET_CURRENT_WINDOW_HANDLE: ('GET', '/session/$sessionId/window'), Command.GET_WINDOW_HANDLES: ('GET', '/session/$sessionId/window_handles'), Command.W3C_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.W3C_EXECUTE_SCRIPT: ('POST', '/session/$sessionId/execute/sync'), Command.W3C_EXECUTE_SCRIPT_ASYNC: ('POST', '/session/$sessionId/execute/async'), 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/element/$id/screenshot'), Command.FIND_ELEMENT: ('POST', '/session/$sessionId/element'), Command.FIND_ELEMENTS: ('POST', '/session/$sessionId/elements'), Command.W3C_GET_ACTIVE_ELEMENT: ('GET', '/session/$sessionId/element/active'), 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.GET_ELEMENT_PROPERTY: ('GET', '/session/$sessionId/element/$id/property/$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.W3C_DISMISS_ALERT: ('POST', '/session/$sessionId/alert/dismiss'), Command.ACCEPT_ALERT: ('POST', '/session/$sessionId/accept_alert'), Command.W3C_ACCEPT_ALERT: ('POST', '/session/$sessionId/alert/accept'), Command.SET_ALERT_VALUE: ('POST', '/session/$sessionId/alert_text'), Command.W3C_SET_ALERT_VALUE: ('POST', '/session/$sessionId/alert/text'), Command.GET_ALERT_TEXT: ('GET', '/session/$sessionId/alert_text'), Command.W3C_GET_ALERT_TEXT: ('GET', '/session/$sessionId/alert/text'), Command.SET_ALERT_CREDENTIALS: ('POST', '/session/$sessionId/alert/credentials'), Command.CLICK: ('POST', '/session/$sessionId/click'), Command.W3C_ACTIONS: ('POST', '/session/$sessionId/actions'), Command.W3C_CLEAR_ACTIONS: ('DELETE', '/session/$sessionId/actions'), 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.SET_WINDOW_SIZE: ('POST', '/session/$sessionId/window/$windowHandle/size'), Command.GET_WINDOW_POSITION: ('GET', '/session/$sessionId/window/$windowHandle/position'), Command.SET_WINDOW_POSITION: ('POST', '/session/$sessionId/window/$windowHandle/position'), Command.SET_WINDOW_RECT: ('POST', '/session/$sessionId/window/rect'), Command.GET_WINDOW_RECT: ('GET', '/session/$sessionId/window/rect'), 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'), Command.FULLSCREEN_WINDOW: ('POST', '/session/$sessionId/window/fullscreen'), Command.MINIMIZE_WINDOW: ('POST', '/session/$sessionId/window/minimize') } 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) headers = self.get_remote_connection_headers(parsed_url, self.keep_alive) if self.keep_alive: 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) for key, val in headers.items(): request.add_header(key, val) 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-3.8.0/selenium/webdriver/remote/webelement.py0000644000175000017500000004610713160347422023423 0ustar lucaslucas00000000000000# 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 import hashlib import os import pkgutil import warnings import zipfile from selenium.common.exceptions import WebDriverException from selenium.webdriver.common.by import By from selenium.webdriver.common.utils import keys_to_typing from .command import Command # Python 3 imports try: str = basestring except NameError: pass try: from StringIO import StringIO as IOStream except ImportError: # 3+ from io import BytesIO as IOStream # not relying on __package__ here as it can be `None` in some situations (see #4558) _pkg = '.'.join(__name__.split('.')[:-1]) getAttribute_js = pkgutil.get_data(_pkg, 'getAttribute.js').decode('utf8') isDisplayed_js = pkgutil.get_data(_pkg, 'isDisplayed.js').decode('utf8') 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.""" if self._w3c: form = self.find_element(By.XPATH, "./ancestor-or-self::form") self._parent.execute_script( "var e = arguments[0].ownerDocument.createEvent('Event');" "e.initEvent('submit', true, true);" "if (arguments[0].dispatchEvent(e)) { arguments[0].submit() }", form) else: 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_property(self, name): """ Gets the given property of the element. :Args: - name - Name of the property to retrieve. Example:: # Check if the "active" CSS class is applied to an element. text_length = target_element.get_property("text_length") """ try: return self._execute(Command.GET_ELEMENT_PROPERTY, {"name": name})["value"] except WebDriverException: # if we hit an end point that doesnt understand getElementProperty lets fake it return self.parent.execute_script('return arguments[0][arguments[1]]', self, name) 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") """ attributeValue = '' if self._w3c: attributeValue = self.parent.execute_script( "return (%s).apply(null, arguments);" % getAttribute_js, self, name) else: resp = self._execute(Command.GET_ELEMENT_ATTRIBUTE, {'name': name}) attributeValue = resp.get('value') if attributeValue is not None: 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) self._execute(Command.SEND_KEYS_TO_ELEMENT, {'text': "".join(keys_to_typing(value)), 'value': keys_to_typing(value)}) # RenderedWebElement Items def is_displayed(self): """Whether the element is visible to a user.""" # Only go into this conditional for browsers that don't use the atom themselves if self._w3c and self.parent.capabilities['browserName'] == 'safari': return self.parent.execute_script( "return (%s).apply(null, arguments);" % isDisplayed_js, self) else: 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. """ if self._w3c: old_loc = self._execute(Command.W3C_EXECUTE_SCRIPT, { 'script': "arguments[0].scrollIntoView(true); return arguments[0].getBoundingClientRect()", 'args': [self]})['value'] return {"x": round(old_loc['x']), "y": round(old_loc['y'])} else: return self._execute(Command.GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW)['value'] @property def size(self): """The size of the element.""" size = {} if self._w3c: size = self._execute(Command.GET_ELEMENT_RECT)['value'] else: size = self._execute(Command.GET_ELEMENT_SIZE)['value'] new_size = {"height": size["height"], "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.""" if self._w3c: old_loc = self._execute(Command.GET_ELEMENT_RECT)['value'] else: old_loc = self._execute(Command.GET_ELEMENT_LOCATION)['value'] new_loc = {"x": round(old_loc['x']), "y": round(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): """ Saves a screenshot of the current element to a PNG image file. 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. This should end with a `.png` extension. :Usage: element.screenshot('/Screenshots/foo.png') """ if not filename.lower().endswith('.png'): warnings.warn("name used for saved screenshot does not match file " "type. It should end with a `.png` extension", UserWarning) 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 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 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-3.8.0/selenium/webdriver/remote/__init__.py0000644000175000017500000000142313113073540023016 0ustar lucaslucas00000000000000# 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-3.8.0/selenium/webdriver/remote/mobile.py0000644000175000017500000000513313113073540022530 0ustar lucaslucas00000000000000# 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 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-3.8.0/selenium/webdriver/remote/command.py0000644000175000017500000001461013174235422022705 0ustar lucaslucas00000000000000# 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" W3C_GET_CURRENT_WINDOW_HANDLE = "w3cGetCurrentWindowHandle" GET_WINDOW_HANDLES = "getWindowHandles" W3C_GET_WINDOW_HANDLES = "w3cGetWindowHandles" GET_WINDOW_SIZE = "getWindowSize" W3C_GET_WINDOW_SIZE = "w3cGetWindowSize" W3C_GET_WINDOW_POSITION = "w3cGetWindowPosition" GET_WINDOW_POSITION = "getWindowPosition" SET_WINDOW_SIZE = "setWindowSize" W3C_SET_WINDOW_SIZE = "w3cSetWindowSize" SET_WINDOW_RECT = "setWindowRect" GET_WINDOW_RECT = "getWindowRect" SET_WINDOW_POSITION = "setWindowPosition" W3C_SET_WINDOW_POSITION = "w3cSetWindowPosition" SWITCH_TO_WINDOW = "switchToWindow" SWITCH_TO_FRAME = "switchToFrame" SWITCH_TO_PARENT_FRAME = "switchToParentFrame" GET_ACTIVE_ELEMENT = "getActiveElement" W3C_GET_ACTIVE_ELEMENT = "w3cGetActiveElement" GET_CURRENT_URL = "getCurrentUrl" GET_PAGE_SOURCE = "getPageSource" GET_TITLE = "getTitle" EXECUTE_SCRIPT = "executeScript" W3C_EXECUTE_SCRIPT = "w3cExecuteScript" W3C_EXECUTE_SCRIPT_ASYNC = "w3cExecuteScriptAsync" 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_PROPERTY = "getElementProperty" 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" FULLSCREEN_WINDOW = "fullscreenWindow" MINIMIZE_WINDOW = "minimizeWindow" # Alerts DISMISS_ALERT = "dismissAlert" W3C_DISMISS_ALERT = "w3cDismissAlert" ACCEPT_ALERT = "acceptAlert" W3C_ACCEPT_ALERT = "w3cAcceptAlert" SET_ALERT_VALUE = "setAlertValue" W3C_SET_ALERT_VALUE = "w3cSetAlertValue" GET_ALERT_TEXT = "getAlertText" W3C_GET_ALERT_TEXT = "w3cGetAlertText" SET_ALERT_CREDENTIALS = "setAlertCredentials" # Advanced user interactions W3C_ACTIONS = "actions" W3C_CLEAR_ACTIONS = "clearActionState" 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-3.8.0/selenium/webdriver/remote/errorhandler.py0000664000175000017500000002640013201115155023747 0ustar lucaslucas00000000000000# 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 (ElementClickInterceptedException, ElementNotInteractableException, ElementNotSelectableException, ElementNotVisibleException, ErrorInResponseException, InsecureCertificateException, InvalidCoordinatesException, InvalidElementStateException, InvalidSessionIdException, InvalidSelectorException, ImeNotAvailableException, ImeActivationFailedException, InvalidArgumentException, InvalidCookieDomainException, JavascriptException, MoveTargetOutOfBoundsException, NoSuchCookieException, NoSuchElementException, NoSuchFrameException, NoSuchWindowException, NoAlertPresentException, ScreenshotException, SessionNotCreatedException, StaleElementReferenceException, TimeoutException, UnableToSetCookieException, UnexpectedAlertPresentException, UnknownMethodException, WebDriverException) 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'] SESSION_NOT_CREATED = [33, 'session not created'] 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'] ELEMENT_NOT_INTERACTABLE = [60, 'element not interactable'] INSECURE_CERTIFICATE = ['insecure certificate'] INVALID_ARGUMENT = [61, 'invalid argument'] INVALID_COORDINATES = ['invalid coordinates'] INVALID_SESSION_ID = ['invalid session id'] NO_SUCH_COOKIE = [62, 'no such cookie'] UNABLE_TO_CAPTURE_SCREEN = [63, 'unable to capture screen'] ELEMENT_CLICK_INTERCEPTED = [64, 'element click intercepted'] UNKNOWN_METHOD = ['unknown method exception'] 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 try: value = json.loads(value_json) if len(value.keys()) == 1: value = value['value'] status = value.get('error', None) if status is None: status = value["status"] message = value["value"] if not isinstance(message, basestring): value = message message = message.get('message') else: message = value.get('message', None) except ValueError: pass 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.ELEMENT_NOT_INTERACTABLE: exception_class = ElementNotInteractableException elif status in ErrorCode.INVALID_COOKIE_DOMAIN: exception_class = InvalidCookieDomainException elif status in ErrorCode.UNABLE_TO_SET_COOKIE: exception_class = UnableToSetCookieException 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 elif status in ErrorCode.JAVASCRIPT_ERROR: exception_class = JavascriptException elif status in ErrorCode.SESSION_NOT_CREATED: exception_class = SessionNotCreatedException elif status in ErrorCode.INVALID_ARGUMENT: exception_class = InvalidArgumentException elif status in ErrorCode.NO_SUCH_COOKIE: exception_class = NoSuchCookieException elif status in ErrorCode.UNABLE_TO_CAPTURE_SCREEN: exception_class = ScreenshotException elif status in ErrorCode.ELEMENT_CLICK_INTERCEPTED: exception_class = ElementClickInterceptedException elif status in ErrorCode.INSECURE_CERTIFICATE: exception_class = InsecureCertificateException elif status in ErrorCode.INVALID_COORDINATES: exception_class = InvalidCoordinatesException elif status in ErrorCode.INVALID_SESSION_ID: exception_class = InvalidSessionIdException elif status in ErrorCode.UNKNOWN_METHOD: exception_class = UnknownMethodException else: exception_class = WebDriverException if value == '' or value is None: value = response['value'] if isinstance(value, basestring): if exception_class == ErrorInResponseException: raise exception_class(response, value) raise exception_class(value) if message == "" and '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-3.8.0/selenium/webdriver/opera/0000775000175000017500000000000013207771116020532 5ustar lucaslucas00000000000000selenium-3.8.0/selenium/webdriver/opera/options.py0000664000175000017500000000650613202664677022616 0ustar lucaslucas00000000000000# 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): KEY = "operaOptions" 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[self.KEY] = capabilities.pop(ChromeOptions.KEY, None) 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-3.8.0/selenium/webdriver/opera/webdriver.py0000664000175000017500000000625413201115155023071 0ustar lucaslucas00000000000000# 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 warnings 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, options=None, service_args=None, desired_capabilities=None, service_log_path=None, opera_options=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". - options: this takes an instance of ChromeOptions """ if opera_options: warnings.warn('use options instead of opera_options', DeprecationWarning) options = opera_options executable_path = (executable_path if executable_path is not None else "operadriver") ChromiumDriver.__init__(self, executable_path=executable_path, port=port, options=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, options=None): OperaDriver.__init__(self, executable_path=executable_path, port=port, options=options, service_args=service_args, desired_capabilities=desired_capabilities, service_log_path=service_log_path) selenium-3.8.0/selenium/webdriver/opera/__init__.py0000644000175000017500000000142313113073540022631 0ustar lucaslucas00000000000000# 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.