From 5f62cbeeb4a039056a4a51b9ad973dd00cdd94e2 Mon Sep 17 00:00:00 2001 From: "Spencer A. Bywater" Date: Mon, 8 Oct 2018 19:43:46 -0700 Subject: [PATCH 01/52] Fix typo on Installation page --- source/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/installation.rst b/source/installation.rst index 2f2da2b..c0eeb4a 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -35,7 +35,7 @@ Using `pip`, you can install selenium like this:: You may consider using `virtualenv `_ to create isolated Python environments. Python 3.6 has `pyvenv `_ -which is almost same as virtualenv. +which is almost the same as virtualenv. Drivers ~~~~~~~ From aa62a1f11a64ea3b646020d9b653c958e7db88d4 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 7 Nov 2018 17:18:24 +0530 Subject: [PATCH 02/52] rst fix for title --- source/api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/api.rst b/source/api.rst index decd474..d94cc64 100644 --- a/source/api.rst +++ b/source/api.rst @@ -182,7 +182,7 @@ Service :show-inheritance: Application Cache -~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~ .. automodule:: selenium.webdriver.common.html5.application_cache :members: From ce6e618e95271d65e034dcf763ffac742227ae1b Mon Sep 17 00:00:00 2001 From: j-n-c Date: Mon, 4 Nov 2019 15:27:17 +0000 Subject: [PATCH 03/52] Corrected some text in the getting-started, locating-elements, navigating and waits pages --- source/getting-started.rst | 8 ++--- source/locating-elements.rst | 63 ++++++++++++++++++------------------ source/navigating.rst | 8 ++--- source/waits.rst | 16 ++++----- 4 files changed, 47 insertions(+), 48 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 0599af4..439682d 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -54,8 +54,8 @@ Next, the instance of Firefox WebDriver is created. The `driver.get` method will navigate to a page given by the URL. WebDriver will wait until the page has fully loaded (that is, the "onload" event has fired) before returning control to your test or -script. It's worth noting that if your page uses a lot of AJAX on -load then WebDriver may not know when it has completely loaded.:: +script. *Be aware that if your page uses a lot of AJAX on +load then WebDriver may not know when it has completely loaded*:: driver.get("http://www.python.org") @@ -191,8 +191,8 @@ local reference to the driver object created in `setUp` method. The `driver.get` method will navigate to a page given by the URL. WebDriver will wait until the page has fully loaded (that is, the "onload" event has fired) before returning control to your test or -script. It's worth noting that if your page uses a lot of AJAX on -load then WebDriver may not know when it has completely loaded.:: +script. *Be aware that if your page uses a lot of AJAX on +load then WebDriver may not know when it has completely loaded*:: driver.get("http://www.python.org") diff --git a/source/locating-elements.rst b/source/locating-elements.rst index a218b78..9c420d7 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -29,8 +29,11 @@ methods to locate elements in a page: Apart from the public methods given above, there are two private -methods which might be useful with locators in page objects. These -are the two private methods: `find_element` and `find_elements`. +methods which might be useful for locating page elements: + +- `find_element` +- `find_elements` + Example usage:: @@ -55,10 +58,10 @@ These are the attributes available for `By` class:: Locating by Id ~~~~~~~~~~~~~~ -Use this when you know `id` attribute of an element. With this -strategy, the first element with the `id` attribute value matching the -location will be returned. If no element has a matching `id` -attribute, a ``NoSuchElementException`` will be raised. +Use this when you know the `id` attribute of an element. With this +strategy, the first element with a matching `id` attribute will +be returned. If no element has a matching `id` attribute, +a ``NoSuchElementException`` will be raised. For instance, consider this page source:: @@ -80,10 +83,10 @@ The form element can be located like this:: Locating by Name ~~~~~~~~~~~~~~~~ -Use this when you know `name` attribute of an element. With this -strategy, the first element with the `name` attribute value matching -the location will be returned. If no element has a matching `name` -attribute, a ``NoSuchElementException`` will be raised. +Use this when you know the `name` attribute of an element. With this +strategy, the first element with a matching `name` attribute will +be returned. If no element has a matching `name` attribute, +a ``NoSuchElementException`` will be raised. For instance, consider this page source:: @@ -115,8 +118,8 @@ Locating by XPath XPath is the language used for locating nodes in an XML document. As HTML can be an implementation of XML (XHTML), Selenium users can leverage this powerful language to target elements in their web -applications. XPath extends beyond (as well as supporting) the simple -methods of locating by id or name attributes, and opens up all sorts +applications. XPath supports the simple methods of locating by +id or name attributes and extends them by opening up all sorts of new possibilities such as locating the third checkbox on the page. One of the main reasons for using XPath is when you don't have a @@ -157,7 +160,7 @@ The form elements can be located like this:: 2. First form element in the HTML -3. The form element with attribute named `id` and the value `loginForm` +3. The form element with attribute `id` set to `loginForm` The username element can be located like this:: @@ -165,14 +168,11 @@ The username element can be located like this:: username = driver.find_element_by_xpath("//form[@id='loginForm']/input[1]") username = driver.find_element_by_xpath("//input[@name='username']") -1. First form element with an input child element with attribute named - `name` and the value `username` +1. First form element with an input child element with `name` set to `username` -2. First input child element of the form element with attribute named - `id` and the value `loginForm` +2. First input child element of the form element with attribute `id` set to `loginForm` -3. First input element with attribute named 'name' and the value - `username` +3. First input element with attribute `name` set to `username` The "Clear" button element can be located like this:: @@ -180,11 +180,10 @@ The "Clear" button element can be located like this:: clear_button = driver.find_element_by_xpath("//form[@id='loginForm']/input[4]") -1. Input with attribute named `name` and the value `continue` and - attribute named `type` and the value `button` +1. Input with attribute `name` set to `continue` and + attribute `type` set to `button` -2. Fourth input child element of the form element with attribute named - `id` and value `loginForm` +2. Fourth input child element of the form element with attribute `id` set to `loginForm` These examples cover some basics, but in order to learn more, the following references are recommended: @@ -212,9 +211,9 @@ discovering the XPath of an element: Locating Hyperlinks by Link Text ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use this when you know link text used within an anchor tag. With this -strategy, the first element with the link text value matching the -location will be returned. If no element has a matching link text +Use this when you know the link text used within an anchor tag. With this +strategy, the first element with the link text matching the provided value +will be returned. If no element has a matching link text attribute, a ``NoSuchElementException`` will be raised. For instance, consider this page source:: @@ -258,9 +257,9 @@ The heading (h1) element can be located like this:: Locating Elements by Class Name ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use this when you want to locate an element by class attribute name. -With this strategy, the first element with the matching class attribute -name will be returned. If no element has a matching class attribute name, +Use this when you want to locate an element by class name. +With this strategy, the first element with the matching class name +attribute will be returned. If no element has a matching class name attribute, a ``NoSuchElementException`` will be raised. For instance, consider this page source:: @@ -278,9 +277,9 @@ The "p" element can be located like this:: Locating Elements by CSS Selectors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use this when you want to locate an element by CSS selector syntax. -With this strategy, the first element with the matching CSS selector -will be returned. If no element has a matching CSS selector, +Use this when you want to locate an element using CSS selector syntax. +With this strategy, the first element matching the given CSS selector +will be returned. If no element matches the provided CSS selector, a ``NoSuchElementException`` will be raised. For instance, consider this page source:: diff --git a/source/navigating.rst b/source/navigating.rst index b00dbd0..72aad3f 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -12,8 +12,8 @@ link. The normal way to do this is by calling ``get`` method: WebDriver will wait until the page has fully loaded (that is, the ``onload`` event has fired) before returning control to your test or -script. It's worth noting that if your page uses a lot of AJAX on -load then WebDriver may not know when it has completely loaded. If +script. *Be aware that if your page uses a lot of AJAX on +load then WebDriver may not know when it has completely loaded*. If you need to ensure such pages are fully loaded then you can use :ref:`waits `. @@ -223,8 +223,8 @@ one browser over another. Cookies ~~~~~~~ -Before we leave these next steps, you may be interested in -understanding how to use cookies. First of all, you need to be on the +Before moving to the next section of the tutorial, you may be interested in +understanding how to use cookies. First of all, you need to be on the domain that the cookie will be valid for: :: diff --git a/source/waits.rst b/source/waits.rst index 821ee58..f619867 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -3,7 +3,7 @@ Waits ----- -These days most of the web apps are using AJAX techniques. When a +These days, most of the web apps are using AJAX techniques. When a page is loaded by the browser, the elements within that page may load at different time intervals. This makes locating elements difficult: if an element is not yet present in the DOM, a locate function will raise @@ -47,12 +47,12 @@ accomplished. driver.quit() -This waits up to 10 seconds before throwing a TimeoutException unless -it finds the element to return within 10 seconds. WebDriverWait -by default calls the ExpectedCondition every 500 milliseconds until it -returns successfully. A successful return is for ExpectedCondition -type is Boolean return true or not null return value for all other -ExpectedCondition types. +In the code above, Selenium will wait for a maximum of 10 seconds for an element +matching the given criteria to be found. If no element is found in that time, +a TimeoutException is thrown. By default, WebDriverWait calls the +ExpectedCondition every 500 milliseconds until it returns success. +ExpectedCondition will return `true` (Boolean) in case of success or `not null` +if it fails to locate an element. **Expected Conditions** @@ -127,7 +127,7 @@ Implicit Waits An implicit wait tells WebDriver to poll the DOM for a certain amount of time when trying to find any element (or elements) -not immediately available. The default setting is 0. Once set, the +not immediately available. The default setting is 0 (zero). Once set, the implicit wait is set for the life of the WebDriver object. :: From 7939843102c1d0260c65147aeb0a22742d8eaf19 Mon Sep 17 00:00:00 2001 From: Lauro Moura Date: Mon, 6 Jul 2020 09:34:28 -0300 Subject: [PATCH 04/52] Add section on installing from source --- source/installation.rst | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/source/installation.rst b/source/installation.rst index c0eeb4a..d4165a2 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -122,3 +122,28 @@ provide a relative or absolute path to Selenium server jar file. Then, the command will look something like this:: /path/to/java -jar /path/to/selenium-server-standalone-2.x.x.jar + + +Installing from Git sources +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To build Selenium Python from the source code, clone `the official repository +`_. It contains the source code for +all official Selenium flavors, like Python, Java, Ruby and others. The Python +code resides in the ``/py`` directory. To build, you will also need the `Bazel +`_ build system. + +.. note:: + + Currently, as Selenium gets near to the 4.0.0 release, it requires Bazel 3.2.0 + (`Install instructions `_), + even though 3.3.0 is already available. + +To build a Wheel from the sources, run the following command from the repository +root:: + + bazel //py:selenium-wheel + +This command will prepare the source code with some preprocessed JS files needed +by some webdriver modules and build the ``.whl`` package inside the +``./bazel-bin/py/`` directory. Afterwards, you can use ``pip`` to install it. From 06f9b8253ab4269c2cb1d1096931ab7d98b21fd4 Mon Sep 17 00:00:00 2001 From: Mahesh Chinnagavi <52688733+maheshchinna@users.noreply.github.com> Date: Thu, 6 Aug 2020 23:25:51 +0530 Subject: [PATCH 05/52] Update navigating.rst In Popup dialogs of alert, switch_to_alert() is deprecated. So, updateded to the latest supported one "switch_to.alert" like use alert = driver.switch_to.alert instead alert = driver.switch_to_alert() --- source/navigating.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/navigating.rst b/source/navigating.rst index 72aad3f..0fca61e 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -191,7 +191,7 @@ Selenium WebDriver has built-in support for handling popup dialog boxes. After you've triggered action that would open a popup, you can access the alert with the following:: - alert = driver.switch_to_alert() + alert = driver.switch_to.alert This will return the currently open alert object. With this object, you can now accept, dismiss, read its contents or even type into a From dbc3702c5190ec3d9ad2c7d8b1b24c110fd87e78 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 21 Aug 2020 18:20:44 +0530 Subject: [PATCH 06/52] recommend venv --- source/installation.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/installation.rst b/source/installation.rst index d4165a2..487972b 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -13,7 +13,7 @@ WebDriver in an intuitive way. Selenium Python bindings provide a convenient API to access Selenium WebDrivers like Firefox, Ie, Chrome, Remote etc. The current supported -Python versions are 2.7, 3.5 and above. +Python versions are 3.5 and above. This documentation explains Selenium 2 WebDriver API. Selenium 1 / Selenium RC API is not covered here. @@ -33,8 +33,8 @@ Using `pip`, you can install selenium like this:: pip install selenium You may consider using `virtualenv `_ -to create isolated Python environments. Python 3.6 has `pyvenv -`_ +to create isolated Python environments. Python 3 has `venv +`_ which is almost the same as virtualenv. Drivers From 4a9ddcb01b9f1a3512478bf1d2aa29a2d76c8807 Mon Sep 17 00:00:00 2001 From: Surya Prashath K G <59205761+Surya9909@users.noreply.github.com> Date: Tue, 29 Sep 2020 18:39:15 +0530 Subject: [PATCH 07/52] Use pip first Add --- source/installation.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/installation.rst b/source/installation.rst index 487972b..8650720 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -22,9 +22,8 @@ This documentation explains Selenium 2 WebDriver API. Selenium Downloading Python bindings for Selenium ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can download Python bindings for Selenium from the `PyPI page for -selenium package `_. However, -a better approach would be to use + +Use `pip `_ to install the selenium package. Python 3.6 has pip available in the `standard library `_. @@ -37,6 +36,9 @@ to create isolated Python environments. Python 3 has `venv `_ which is almost the same as virtualenv. +You can also download Python bindings for Selenium from the _`PyPI page for +selenium package `_. and install manually. + Drivers ~~~~~~~ From 868d5c4d8ca1ddf9942a93ef57ef4db269162652 Mon Sep 17 00:00:00 2001 From: Surya Prashath K G <59205761+Surya9909@users.noreply.github.com> Date: Tue, 29 Sep 2020 19:30:46 +0530 Subject: [PATCH 08/52] Typo in last commit Sorry --- source/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/installation.rst b/source/installation.rst index 8650720..d67d916 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -36,7 +36,7 @@ to create isolated Python environments. Python 3 has `venv `_ which is almost the same as virtualenv. -You can also download Python bindings for Selenium from the _`PyPI page for +You can also download Python bindings for Selenium from the `PyPI page for selenium package `_. and install manually. Drivers From 3b22bced335311bbb8ca0c76d0d73d4d5db22bde Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Sun, 18 Oct 2020 09:35:21 +0530 Subject: [PATCH 09/52] 50+ contributors --- source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/index.rst b/source/index.rst index 1fa627f..2cf4bc8 100644 --- a/source/index.rst +++ b/source/index.rst @@ -13,7 +13,7 @@ Selenium with Python Github and send pull requests `_. You can also send your feedback to my email: baiju.m.mail AT gmail DOT com. So far - 40+ community members have contributed to this project + 50+ community members have contributed to this project (See the closed pull requests). I encourage contributors to add more sections and make it a good documentation! From fd73729d2107ffa93d0c8ee553459ebda678ab02 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Sun, 18 Oct 2020 10:11:22 +0530 Subject: [PATCH 10/52] Fix broken links Line width 79 chars --- source/installation.rst | 1 + source/locating-elements.rst | 120 +++++++++++++++++------------------ 2 files changed, 59 insertions(+), 62 deletions(-) diff --git a/source/installation.rst b/source/installation.rst index d67d916..6bf125e 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -59,6 +59,7 @@ Other supported browsers will have their own drivers available. Links to some of | **Safari**: | https://webkit.org/blog/6900/webdriver-support-in-safari-10/ | +--------------+-----------------------------------------------------------------------+ +For more information about driver installation, please refer the `official documentation `_. Detailed instructions for Windows users ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/source/locating-elements.rst b/source/locating-elements.rst index 9c420d7..7dc71ca 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -3,9 +3,9 @@ Locating Elements ----------------- -There are various strategies to locate elements in a page. You can use -the most appropriate one for your case. Selenium provides the following -methods to locate elements in a page: +There are various strategies to locate elements in a page. You can use the most +appropriate one for your case. Selenium provides the following methods to +locate elements in a page: - `find_element_by_id` - `find_element_by_name` @@ -28,8 +28,8 @@ methods to locate elements in a page: - `find_elements_by_css_selector` -Apart from the public methods given above, there are two private -methods which might be useful for locating page elements: +Apart from the public methods given above, there are two private methods which +might be useful for locating page elements: - `find_element` - `find_elements` @@ -58,10 +58,10 @@ These are the attributes available for `By` class:: Locating by Id ~~~~~~~~~~~~~~ -Use this when you know the `id` attribute of an element. With this -strategy, the first element with a matching `id` attribute will -be returned. If no element has a matching `id` attribute, -a ``NoSuchElementException`` will be raised. +Use this when you know the `id` attribute of an element. With this strategy, +the first element with a matching `id` attribute will be returned. If no +element has a matching `id` attribute, a ``NoSuchElementException`` will be +raised. For instance, consider this page source:: @@ -83,10 +83,10 @@ The form element can be located like this:: Locating by Name ~~~~~~~~~~~~~~~~ -Use this when you know the `name` attribute of an element. With this -strategy, the first element with a matching `name` attribute will -be returned. If no element has a matching `name` attribute, -a ``NoSuchElementException`` will be raised. +Use this when you know the `name` attribute of an element. With this strategy, +the first element with a matching `name` attribute will be returned. If no +element has a matching `name` attribute, a ``NoSuchElementException`` will be +raised. For instance, consider this page source:: @@ -115,26 +115,24 @@ button:: Locating by XPath ~~~~~~~~~~~~~~~~~ -XPath is the language used for locating nodes in an XML document. As -HTML can be an implementation of XML (XHTML), Selenium users can -leverage this powerful language to target elements in their web -applications. XPath supports the simple methods of locating by -id or name attributes and extends them by opening up all sorts -of new possibilities such as locating the third checkbox on the page. - -One of the main reasons for using XPath is when you don't have a -suitable id or name attribute for the element you wish to locate. You -can use XPath to either locate the element in absolute terms (not -advised), or relative to an element that does have an id or name -attribute. XPath locators can also be used to specify elements via -attributes other than id and name. - -Absolute XPaths contain the location of all elements from the root -(html) and as a result are likely to fail with only the slightest -adjustment to the application. By finding a nearby element with an id -or name attribute (ideally a parent element) you can locate your -target element based on the relationship. This is much less likely to -change and can make your tests more robust. +XPath is the language used for locating nodes in an XML document. As HTML can +be an implementation of XML (XHTML), Selenium users can leverage this powerful +language to target elements in their web applications. XPath supports the +simple methods of locating by id or name attributes and extends them by opening +up all sorts of new possibilities such as locating the third checkbox on the +page. + +One of the main reasons for using XPath is when you don't have a suitable id or +name attribute for the element you wish to locate. You can use XPath to either +locate the element in absolute terms (not advised), or relative to an element +that does have an id or name attribute. XPath locators can also be used to +specify elements via attributes other than id and name. + +Absolute XPaths contain the location of all elements from the root (html) and as +a result are likely to fail with only the slightest adjustment to the +application. By finding a nearby element with an id or name attribute (ideally +a parent element) you can locate your target element based on the relationship. +This is much less likely to change and can make your tests more robust. For instance, consider this page source:: @@ -170,7 +168,8 @@ The username element can be located like this:: 1. First form element with an input child element with `name` set to `username` -2. First input child element of the form element with attribute `id` set to `loginForm` +2. First input child element of the form element with attribute `id` set to + `loginForm` 3. First input element with attribute `name` set to `username` @@ -180,13 +179,14 @@ The "Clear" button element can be located like this:: clear_button = driver.find_element_by_xpath("//form[@id='loginForm']/input[4]") -1. Input with attribute `name` set to `continue` and - attribute `type` set to `button` +1. Input with attribute `name` set to `continue` and attribute `type` set to + `button` -2. Fourth input child element of the form element with attribute `id` set to `loginForm` +2. Fourth input child element of the form element with attribute `id` set to + `loginForm` -These examples cover some basics, but in order to learn more, the -following references are recommended: +These examples cover some basics, but in order to learn more, the following +references are recommended: * `W3Schools XPath Tutorial `_ * `W3C XPath Recommendation `_ @@ -194,15 +194,12 @@ following references are recommended: `_ - with interactive examples. -There are also a couple of very useful Add-ons that can assist in -discovering the XPath of an element: +Here is a couple of very useful Add-ons that can assist in discovering the XPath +of an element: -* `XPath Checker - `_ - - suggests XPath and can be used to test XPath results. -* `Firebug `_ - - XPath suggestions are just one of the many powerful features of this - very useful add-on. +* `xPath Finder + `_ - + Plugin to get the elements xPath. * `XPath Helper `_ - for Google Chrome @@ -212,9 +209,9 @@ Locating Hyperlinks by Link Text ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use this when you know the link text used within an anchor tag. With this -strategy, the first element with the link text matching the provided value -will be returned. If no element has a matching link text -attribute, a ``NoSuchElementException`` will be raised. +strategy, the first element with the link text matching the provided value will +be returned. If no element has a matching link text attribute, a +``NoSuchElementException`` will be raised. For instance, consider this page source:: @@ -235,10 +232,9 @@ The continue.html link can be located like this:: Locating Elements by Tag Name ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use this when you want to locate an element by tag name. With this -strategy, the first element with the given tag name will be returned. -If no element has a matching tag name, a ``NoSuchElementException`` -will be raised. +Use this when you want to locate an element by tag name. With this strategy, the +first element with the given tag name will be returned. If no element has a +matching tag name, a ``NoSuchElementException`` will be raised. For instance, consider this page source:: @@ -257,10 +253,10 @@ The heading (h1) element can be located like this:: Locating Elements by Class Name ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use this when you want to locate an element by class name. -With this strategy, the first element with the matching class name -attribute will be returned. If no element has a matching class name attribute, -a ``NoSuchElementException`` will be raised. +Use this when you want to locate an element by class name. With this strategy, +the first element with the matching class name attribute will be returned. If +no element has a matching class name attribute, a ``NoSuchElementException`` +will be raised. For instance, consider this page source:: @@ -277,10 +273,10 @@ The "p" element can be located like this:: Locating Elements by CSS Selectors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use this when you want to locate an element using CSS selector syntax. -With this strategy, the first element matching the given CSS selector -will be returned. If no element matches the provided CSS selector, -a ``NoSuchElementException`` will be raised. +Use this when you want to locate an element using CSS selector syntax. With +this strategy, the first element matching the given CSS selector will be +returned. If no element matches the provided CSS selector, a +``NoSuchElementException`` will be raised. For instance, consider this page source:: From 75c8b45547e479d5cb00d43247b8c336b521eac1 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Tue, 20 Oct 2020 10:51:17 +0530 Subject: [PATCH 11/52] Add list of translations Signed-off-by: Baiju Muthukadan --- source/index.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/source/index.rst b/source/index.rst index 2cf4bc8..459c690 100644 --- a/source/index.rst +++ b/source/index.rst @@ -15,7 +15,14 @@ Selenium with Python your feedback to my email: baiju.m.mail AT gmail DOT com. So far 50+ community members have contributed to this project (See the closed pull requests). I encourage contributors to add - more sections and make it a good documentation! + more sections and make it a good documentation! If you know any + translation of this document, please send a PR to update the + below list. + + **Translations:** + + - `Chinese `_ + - `Japanese `_ .. toctree:: From 6b40dff6261cad838b8beee62db942ffce658b43 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Tue, 20 Oct 2020 11:13:21 +0530 Subject: [PATCH 12/52] Make it an awesome documentation Signed-off-by: Baiju Muthukadan --- source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/index.rst b/source/index.rst index 459c690..41e7b5d 100644 --- a/source/index.rst +++ b/source/index.rst @@ -15,7 +15,7 @@ Selenium with Python your feedback to my email: baiju.m.mail AT gmail DOT com. So far 50+ community members have contributed to this project (See the closed pull requests). I encourage contributors to add - more sections and make it a good documentation! If you know any + more sections and make it an awesome documentation! If you know any translation of this document, please send a PR to update the below list. From 1d31667a92b984dc6539a96f1148288afd348189 Mon Sep 17 00:00:00 2001 From: Neha Verma Date: Thu, 22 Oct 2020 20:31:02 +0530 Subject: [PATCH 13/52] Added element selection by css feat: Additional example added to the element selection using css locator strategy. Added example for element locator strategy using css - element = driver.find_element_by_css_selector("input#passwd-id") --- source/navigating.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/source/navigating.rst b/source/navigating.rst index 0fca61e..6f6ba21 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -33,6 +33,7 @@ you could find it using any of:: element = driver.find_element_by_id("passwd-id") element = driver.find_element_by_name("passwd") element = driver.find_element_by_xpath("//input[@id='passwd-id']") + element = driver.find_element_by_css_selector("input#passwd-id") You can also look for a link by its text, but be careful! The text must be an exact match! You should also be careful when using `XPATH From d80311396b6065e32b087d3d8c2dbc492f88f3c2 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 22 Oct 2020 21:19:05 +0530 Subject: [PATCH 14/52] Add translations link --- README.rst | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index be39960..20da1c8 100644 --- a/README.rst +++ b/README.rst @@ -5,9 +5,18 @@ https://selenium-python.readthedocs.io NOTE: THIS IS NOT AN OFFICIAL DOCUMENTATION -If you would like to contribute to this documentation, you can fork -this project in Github and send pull requests. You can also send your -feedback to my email: baiju.m.mail AT gmail DOT com. -So far 40+ community members have contributed to this -project (See the closed pull requests). I encourage contributors -to add more sections and make it a good documentation! +This is not an official documentation. If you would like to +contribute to this documentation, you can `fork this project in +Github and send pull requests +`_. You can also send +your feedback to my email: baiju.m.mail AT gmail DOT com. So far +50+ community members have contributed to this project +(See the closed pull requests). I encourage contributors to add +more sections and make it an awesome documentation! If you know any +translation of this document, please send a PR to update the +below list. + +**Translations:** + +- `Chinese `_ +- `Japanese `_ From ea23c180bc8678698759ec5dd62a90008934cb0c Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 22 Oct 2020 21:20:11 +0530 Subject: [PATCH 15/52] Fix brand name --- README.rst | 2 +- source/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 20da1c8..0e9e3bd 100644 --- a/README.rst +++ b/README.rst @@ -7,7 +7,7 @@ NOTE: THIS IS NOT AN OFFICIAL DOCUMENTATION This is not an official documentation. If you would like to contribute to this documentation, you can `fork this project in -Github and send pull requests +GitHub and send pull requests `_. You can also send your feedback to my email: baiju.m.mail AT gmail DOT com. So far 50+ community members have contributed to this project diff --git a/source/index.rst b/source/index.rst index 41e7b5d..ae6821c 100644 --- a/source/index.rst +++ b/source/index.rst @@ -10,7 +10,7 @@ Selenium with Python This is not an official documentation. If you would like to contribute to this documentation, you can `fork this project in - Github and send pull requests + GitHub and send pull requests `_. You can also send your feedback to my email: baiju.m.mail AT gmail DOT com. So far 50+ community members have contributed to this project From 4c9eb4ea0a1e0e13a63be2c29ba55a3ca1533b83 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 22 Oct 2020 21:30:26 +0530 Subject: [PATCH 16/52] Set max line length to 79 --- README.rst | 18 ++-- source/api.rst | 7 +- source/faq.rst | 47 +++++----- source/getting-started.rst | 160 ++++++++++++++++------------------ source/index.rst | 18 ++-- source/installation.rst | 124 ++++++++++++++------------- source/locating-elements.rst | 14 +-- source/navigating.rst | 161 +++++++++++++++++------------------ source/page-objects.rst | 25 +++--- source/waits.rst | 73 ++++++++-------- 10 files changed, 315 insertions(+), 332 deletions(-) diff --git a/README.rst b/README.rst index 0e9e3bd..1f25ce5 100644 --- a/README.rst +++ b/README.rst @@ -5,16 +5,14 @@ https://selenium-python.readthedocs.io NOTE: THIS IS NOT AN OFFICIAL DOCUMENTATION -This is not an official documentation. If you would like to -contribute to this documentation, you can `fork this project in -GitHub and send pull requests -`_. You can also send -your feedback to my email: baiju.m.mail AT gmail DOT com. So far -50+ community members have contributed to this project -(See the closed pull requests). I encourage contributors to add -more sections and make it an awesome documentation! If you know any -translation of this document, please send a PR to update the -below list. +This is not an official documentation. If you would like to contribute to this +documentation, you can `fork this project in GitHub and send pull requests +`_. You can also send your feedback +to my email: baiju.m.mail AT gmail DOT com. So far 50+ community members have +contributed to this project (See the closed pull requests). I encourage +contributors to add more sections and make it an awesome documentation! If you +know any translation of this document, please send a PR to update the below +list. **Translations:** diff --git a/source/api.rst b/source/api.rst index d94cc64..8e91d06 100644 --- a/source/api.rst +++ b/source/api.rst @@ -5,8 +5,8 @@ WebDriver API .. note:: - This is not an official documentation. Official API documentation - is available `here + This is not an official documentation. Official API documentation is + available `here `_. This chapter covers all the interfaces of Selenium WebDriver. @@ -46,8 +46,7 @@ with the actual class name given below):: **Conventions used in the API** Some attributes are callable (or methods) and others are non-callable -(properties). All the callable attributes are ending with round -brackets. +(properties). All the callable attributes are ending with round brackets. Here is an example for property: diff --git a/source/faq.rst b/source/faq.rst index b7f865a..9de4370 100644 --- a/source/faq.rst +++ b/source/faq.rst @@ -26,10 +26,10 @@ Does Selenium 2 support XPath 2.0 ? Ref: http://seleniumhq.org/docs/03_webdriver.html#how-xpath-works-in-webdriver -Selenium delegates XPath queries down to the browser's own XPath -engine, so Selenium support XPath supports whatever the browser -supports. In browsers which don't have native XPath engines (IE -6,7,8), Selenium supports XPath 1.0 only. +Selenium delegates XPath queries down to the browser's own XPath engine, so +Selenium support XPath supports whatever the browser supports. In browsers +which don't have native XPath engines (IE 6,7,8), Selenium supports XPath 1.0 +only. How to scroll down to the bottom of a page ? @@ -37,21 +37,20 @@ How to scroll down to the bottom of a page ? Ref: http://blog.varunin.com/2011/08/scrolling-on-pages-using-selenium.html -You can use the `execute_script` method to execute javascript on the -loaded page. So, you can call the JavaScript API to scroll to the -bottom or any other position of a page. +You can use the `execute_script` method to execute javascript on the loaded +page. So, you can call the JavaScript API to scroll to the bottom or any other +position of a page. Here is an example to scroll to the bottom of a page:: driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") -The `window `_ object -in DOM has a `scrollTo -`_ method to +The `window `_ object in DOM has +a `scrollTo `_ method to scroll to any position of an opened window. The `scrollHeight -`_ is a common -property for all elements. The `document.body.scrollHeight` will give -the height of the entire body of the page. +`_ is a common property for all +elements. The `document.body.scrollHeight` will give the height of the entire +body of the page. How to auto save files using custom Firefox profile ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -74,8 +73,8 @@ Another way to find content type is using the `requests content_type = requests.head('http://www.python.org').headers['content-type'] print(content_type) -Once the content type is identified, you can use it to set the firefox -profile preference: ``browser.helperApps.neverAsk.saveToDisk`` +Once the content type is identified, you can use it to set the firefox profile +preference: ``browser.helperApps.neverAsk.saveToDisk`` Here is an example:: @@ -94,24 +93,24 @@ Here is an example:: browser.get("http://pypi.python.org/pypi/selenium") browser.find_element_by_partial_link_text("selenium-2").click() -In the above example, ``application/octet-stream`` is used as the -content type. +In the above example, ``application/octet-stream`` is used as the content type. -The ``browser.download.dir`` option specify the directory where you -want to download the files. +The ``browser.download.dir`` option specify the directory where you want to +download the files. How to upload files into file inputs ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Select the ```` element and call the ``send_keys()`` method passing -the file path, either the path relative to the test script, or an absolute path. -Keep in mind the differences in path names between Windows and Unix systems. +Select the ```` element and call the ``send_keys()`` method +passing the file path, either the path relative to the test script, or an +absolute path. Keep in mind the differences in path names between Windows and +Unix systems. How to use firebug with Firefox ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -First download the Firebug XPI file, later you call the -``add_extension`` method available for the firefox profile:: +First download the Firebug XPI file, later you call the ``add_extension`` method +available for the firefox profile:: from selenium import webdriver diff --git a/source/getting-started.rst b/source/getting-started.rst index 439682d..3480cb9 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -6,8 +6,8 @@ Getting Started Simple Usage ~~~~~~~~~~~~ -If you have installed Selenium Python bindings, you can start using it -from Python like this. +If you have installed Selenium Python bindings, you can start using it from +Python like this. :: @@ -24,21 +24,19 @@ from Python like this. assert "No results found." not in driver.page_source driver.close() -The above script can be saved into a file (eg:- -`python_org_search.py`), then it can be run like this:: +The above script can be saved into a file (eg:- `python_org_search.py`), then it +can be run like this:: python python_org_search.py -The `python` which you are running should have the `selenium` module -installed. +The `python` which you are running should have the `selenium` module installed. Example Explained ~~~~~~~~~~~~~~~~~ -The `selenium.webdriver` module provides all the WebDriver -implementations. Currently supported WebDriver implementations are -Firefox, Chrome, IE and Remote. The `Keys` class provide keys in the -keyboard like RETURN, F1, ALT etc. +The `selenium.webdriver` module provides all the WebDriver implementations. +Currently supported WebDriver implementations are Firefox, Chrome, IE and +Remote. The `Keys` class provide keys in the keyboard like RETURN, F1, ALT etc. :: @@ -51,46 +49,44 @@ Next, the instance of Firefox WebDriver is created. driver = webdriver.Firefox() -The `driver.get` method will navigate to a page given by the URL. -WebDriver will wait until the page has fully loaded (that is, the -"onload" event has fired) before returning control to your test or -script. *Be aware that if your page uses a lot of AJAX on -load then WebDriver may not know when it has completely loaded*:: +The `driver.get` method will navigate to a page given by the URL. WebDriver +will wait until the page has fully loaded (that is, the "onload" event has +fired) before returning control to your test or script. *Be aware that if your +page uses a lot of AJAX on load then WebDriver may not know when it has +completely loaded*:: driver.get("http://www.python.org") -The next line is an assertion to confirm that title has "Python" word -in it:: +The next line is an assertion to confirm that title has "Python" word in it:: assert "Python" in driver.title WebDriver offers a number of ways to find elements using one of the -`find_element_by_*` methods. For example, the input text element can -be located by its `name` attribute using `find_element_by_name` -method. A detailed explanation of finding elements is available in the -:ref:`locating-elements` chapter:: +`find_element_by_*` methods. For example, the input text element can be located +by its `name` attribute using `find_element_by_name` method. A detailed +explanation of finding elements is available in the :ref:`locating-elements` +chapter:: elem = driver.find_element_by_name("q") -Next, we are sending keys, this is similar to entering keys using your -keyboard. Special keys can be sent using `Keys` class imported from +Next, we are sending keys, this is similar to entering keys using your keyboard. +Special keys can be sent using `Keys` class imported from `selenium.webdriver.common.keys`. To be safe, we'll first clear any -pre-populated text in the input field (e.g. "Search") so it doesn't -affect our search results:: +pre-populated text in the input field (e.g. "Search") so it doesn't affect our +search results:: elem.clear() elem.send_keys("pycon") elem.send_keys(Keys.RETURN) -After submission of the page, you should get the result if there is any. -To ensure that some results are found, make an assertion:: +After submission of the page, you should get the result if there is any. To +ensure that some results are found, make an assertion:: assert "No results found." not in driver.page_source -Finally, the browser window is closed. You can also call `quit` -method instead of `close`. The `quit` will exit entire browser whereas -close` will close one tab, but if just one tab was open, by default most -browser will exit entirely.:: +Finally, the browser window is closed. You can also call `quit` method instead +of `close`. The `quit` will exit entire browser whereas close` will close one +tab, but if just one tab was open, by default most browser will exit entirely.:: driver.close() @@ -98,14 +94,14 @@ browser will exit entirely.:: Using Selenium to write tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Selenium is mostly used for writing test cases. The `selenium` -package itself doesn't provide a testing tool/framework. You can -write test cases using Python's unittest module. The other options for -a tool/framework are py.test and nose. +Selenium is mostly used for writing test cases. The `selenium` package itself +doesn't provide a testing tool/framework. You can write test cases using +Python's unittest module. The other options for a tool/framework are py.test +and nose. -In this chapter, we use `unittest` as the framework of choice. Here -is the modified example which uses unittest module. This is a test -for `python.org` search functionality:: +In this chapter, we use `unittest` as the framework of choice. Here is the +modified example which uses unittest module. This is a test for `python.org` +search functionality:: import unittest from selenium import webdriver @@ -142,20 +138,19 @@ You can run the above test case from a shell like this:: OK -The above result shows that the test has been successfully -completed. +The above result shows that the test has been successfully completed. Walk through of the example ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Initially, all the basic modules required are imported. The `unittest -`_ module is a built-in -Python based on Java's JUnit. This module provides the framework for -organizing the test cases. The `selenium.webdriver` module provides -all the WebDriver implementations. Currently supported WebDriver -implementations are Firefox, Chrome, Ie and Remote. The `Keys` class -provide keys in the keyboard like RETURN, F1, ALT etc. +`_ module is a built-in Python +based on Java's JUnit. This module provides the framework for organizing the +test cases. The `selenium.webdriver` module provides all the WebDriver +implementations. Currently supported WebDriver implementations are Firefox, +Chrome, Ie and Remote. The `Keys` class provide keys in the keyboard like +RETURN, F1, ALT etc. :: @@ -163,72 +158,68 @@ provide keys in the keyboard like RETURN, F1, ALT etc. from selenium import webdriver from selenium.webdriver.common.keys import Keys -The test case class is inherited from `unittest.TestCase`. -Inheriting from `TestCase` class is the way to tell `unittest` module -that this is a test case:: +The test case class is inherited from `unittest.TestCase`. Inheriting from +`TestCase` class is the way to tell `unittest` module that this is a test case:: class PythonOrgSearch(unittest.TestCase): -The `setUp` is part of initialization, this method will get called -before every test function which you are going to write in this test -case class. Here you are creating the instance of Firefox WebDriver. +The `setUp` is part of initialization, this method will get called before every +test function which you are going to write in this test case class. Here you +are creating the instance of Firefox WebDriver. :: def setUp(self): self.driver = webdriver.Firefox() -This is the test case method. The test case method should always start -with characters `test`. The first line inside this method create a -local reference to the driver object created in `setUp` method. +This is the test case method. The test case method should always start with +characters `test`. The first line inside this method create a local reference +to the driver object created in `setUp` method. :: def test_search_in_python_org(self): driver = self.driver -The `driver.get` method will navigate to a page given by the URL. -WebDriver will wait until the page has fully loaded (that is, the -"onload" event has fired) before returning control to your test or -script. *Be aware that if your page uses a lot of AJAX on -load then WebDriver may not know when it has completely loaded*:: +The `driver.get` method will navigate to a page given by the URL. WebDriver +will wait until the page has fully loaded (that is, the "onload" event has +fired) before returning control to your test or script. *Be aware that if your +page uses a lot of AJAX on load then WebDriver may not know when it has +completely loaded*:: driver.get("http://www.python.org") -The next line is an assertion to confirm that title has "Python" word -in it:: +The next line is an assertion to confirm that title has "Python" word in it:: self.assertIn("Python", driver.title) WebDriver offers a number of ways to find elements using one of the -`find_element_by_*` methods. For example, the input text element can -be located by its `name` attribute using `find_element_by_name` -method. Detailed explanation of finding elements is available in the -:ref:`locating-elements` chapter:: +`find_element_by_*` methods. For example, the input text element can be located +by its `name` attribute using `find_element_by_name` method. Detailed +explanation of finding elements is available in the :ref:`locating-elements` +chapter:: elem = driver.find_element_by_name("q") -Next, we are sending keys, this is similar to entering keys using your -keyboard. Special keys can be send using `Keys` class imported from +Next, we are sending keys, this is similar to entering keys using your keyboard. +Special keys can be send using `Keys` class imported from `selenium.webdriver.common.keys`:: elem.send_keys("pycon") elem.send_keys(Keys.RETURN) -After submission of the page, you should get the result as per search if -there is any. To ensure that some results are found, make an -assertion:: +After submission of the page, you should get the result as per search if there +is any. To ensure that some results are found, make an assertion:: assert "No results found." not in driver.page_source -The `tearDown` method will get called after every test method. This -is a place to do all cleanup actions. In the current method, the -browser window is closed. You can also call `quit` method instead of -`close`. The `quit` will exit the entire browser, whereas `close` -will close a tab, but if it is the only tab opened, by default most -browser will exit entirely.:: +The `tearDown` method will get called after every test method. This is a place +to do all cleanup actions. In the current method, the browser window is closed. +You can also call `quit` method instead of `close`. The `quit` will exit the +entire browser, whereas `close` will close a tab, but if it is the only tab +opened, by default most browser will exit entirely.:: def tearDown(self): self.driver.close() @@ -243,18 +234,17 @@ Final lines are some boiler plate code to run the test suite:: Using Selenium with remote WebDriver ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To use the remote WebDriver, you should have Selenium server running. -To run the server, use this command:: +To use the remote WebDriver, you should have Selenium server running. To run +the server, use this command:: java -jar selenium-server-standalone-2.x.x.jar -While running the Selenium server, you could see a message looking like -this:: +While running the Selenium server, you could see a message looking like this:: 15:43:07.541 INFO - RemoteWebDriver instances should connect to: http://127.0.0.1:4444/wd/hub -The above line says that you can use this URL for connecting to -remote WebDriver. Here are some examples:: +The above line says that you can use this URL for connecting to remote +WebDriver. Here are some examples:: from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities @@ -271,8 +261,8 @@ remote WebDriver. Here are some examples:: command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities=DesiredCapabilities.HTMLUNITWITHJS) -The desired capabilities is a dictionary, so instead of using the -default dictionaries, you can specify the values explicitly:: +The desired capabilities is a dictionary, so instead of using the default +dictionaries, you can specify the values explicitly:: driver = webdriver.Remote( command_executor='http://127.0.0.1:4444/wd/hub', diff --git a/source/index.rst b/source/index.rst index ae6821c..7d51db0 100644 --- a/source/index.rst +++ b/source/index.rst @@ -8,16 +8,14 @@ Selenium with Python .. note:: - This is not an official documentation. If you would like to - contribute to this documentation, you can `fork this project in - GitHub and send pull requests - `_. You can also send - your feedback to my email: baiju.m.mail AT gmail DOT com. So far - 50+ community members have contributed to this project - (See the closed pull requests). I encourage contributors to add - more sections and make it an awesome documentation! If you know any - translation of this document, please send a PR to update the - below list. + This is not an official documentation. If you would like to contribute to + this documentation, you can `fork this project in GitHub and send pull + requests `_. You can also send + your feedback to my email: baiju.m.mail AT gmail DOT com. So far 50+ + community members have contributed to this project (See the closed pull + requests). I encourage contributors to add more sections and make it an + awesome documentation! If you know any translation of this document, please + send a PR to update the below list. **Translations:** diff --git a/source/installation.rst b/source/installation.rst index 6bf125e..da5ecdd 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -6,48 +6,53 @@ Installation Introduction ~~~~~~~~~~~~ -Selenium Python bindings provides a simple API to write -functional/acceptance tests using Selenium WebDriver. Through -Selenium Python API you can access all functionalities of Selenium -WebDriver in an intuitive way. +Selenium Python bindings provides a simple API to write functional/acceptance +tests using Selenium WebDriver. Through Selenium Python API you can access all +functionalities of Selenium WebDriver in an intuitive way. -Selenium Python bindings provide a convenient API to access Selenium -WebDrivers like Firefox, Ie, Chrome, Remote etc. The current supported -Python versions are 3.5 and above. +Selenium Python bindings provide a convenient API to access Selenium WebDrivers +like Firefox, Ie, Chrome, Remote etc. The current supported Python versions are +3.5 and above. -This documentation explains Selenium 2 WebDriver API. Selenium -1 / Selenium RC API is not covered here. +This documentation explains Selenium 2 WebDriver API. Selenium 1 / Selenium RC +API is not covered here. Downloading Python bindings for Selenium ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use -`pip `_ to -install the selenium package. Python 3.6 has pip available in the -`standard library `_. -Using `pip`, you can install selenium like this:: +Use `pip `_ to install the selenium +package. Python 3.6 has pip available in the `standard library +`_. Using `pip`, you can +install selenium like this:: pip install selenium -You may consider using `virtualenv `_ -to create isolated Python environments. Python 3 has `venv -`_ -which is almost the same as virtualenv. +You may consider using `virtualenv `_ to create +isolated Python environments. Python 3 has `venv +`_ which is almost the same as +virtualenv. You can also download Python bindings for Selenium from the `PyPI page for -selenium package `_. and install manually. +selenium package `_. and install +manually. 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`. +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.` +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. +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 | @@ -59,7 +64,9 @@ Other supported browsers will have their own drivers available. Links to some of | **Safari**: | https://webkit.org/blog/6900/webdriver-support-in-safari-10/ | +--------------+-----------------------------------------------------------------------+ -For more information about driver installation, please refer the `official documentation `_. +For more information about driver installation, please refer the `official +documentation +`_. Detailed instructions for Windows users ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -68,18 +75,18 @@ Detailed instructions for Windows users You should have an internet connection to perform this installation. -1. Install Python 3.6 using the `MSI available in python.org download - page `_. +1. Install Python 3.6 using the `MSI available in python.org download page + `_. -2. Start a command prompt using the ``cmd.exe`` program and run the - ``pip`` command as given below to install `selenium`. +2. Start a command prompt using the ``cmd.exe`` program and run the ``pip`` + command as given below to install `selenium`. :: C:\Python35\Scripts\pip.exe install selenium -Now you can run your test scripts using Python. For example, -if you have created a Selenium based script and saved it inside +Now you can run your test scripts using Python. For example, if you have +created a Selenium based script and saved it inside ``C:\my_selenium_script.py``, you can run it like this:: C:\Python35\python.exe C:\my_selenium_script.py @@ -91,38 +98,36 @@ Downloading Selenium server .. note:: **The Selenium server is only required if you want to use the remote - WebDriver**. See the :ref:`selenium-remote-webdriver` section for - more details. If you are a beginner learning Selenium, you can - skip this section and proceed with next chapter. + WebDriver**. See the :ref:`selenium-remote-webdriver` section for more + details. If you are a beginner learning Selenium, you can skip this section + and proceed with next chapter. -Selenium server is a Java program. Java Runtime Environment (JRE) 1.6 -or newer version is recommended to run Selenium server. +Selenium server is a Java program. Java Runtime Environment (JRE) 1.6 or newer +version is recommended to run Selenium server. -You can download Selenium server 2.x from the `download page of -selenium website `_. The file name -should be something like this: -``selenium-server-standalone-2.x.x.jar``. You can always download the +You can download Selenium server 2.x from the `download page of selenium website +`_. The file name should be something like +this: ``selenium-server-standalone-2.x.x.jar``. You can always download the latest 2.x version of Selenium server. -If Java Runtime Environment (JRE) is not installed in your system, you -can download the `JRE from the Oracle website -`_. -If you are using a GNU/Linux system and have root access in your system, -you can also use your operating system instructions to install JRE. +If Java Runtime Environment (JRE) is not installed in your system, you can +download the `JRE from the Oracle website +`_. If you +are using a GNU/Linux system and have root access in your system, you can also +use your operating system instructions to install JRE. -If `java` command is available in the PATH (environment variable), -you can start the Selenium server using this command:: +If `java` command is available in the PATH (environment variable), you can start +the Selenium server using this command:: java -jar selenium-server-standalone-2.x.x.jar -Replace `2.x.x` with the actual version of Selenium server you downloaded -from the site. +Replace `2.x.x` with the actual version of Selenium server you downloaded from +the site. -If JRE is installed as a non-root user and/or if it is -not available in the PATH (environment variable), you can type the -relative or absolute path to the `java` command. Similarly, you can -provide a relative or absolute path to Selenium server jar file. -Then, the command will look something like this:: +If JRE is installed as a non-root user and/or if it is not available in the PATH +(environment variable), you can type the relative or absolute path to the `java` +command. Similarly, you can provide a relative or absolute path to Selenium +server jar file. Then, the command will look something like this:: /path/to/java -jar /path/to/selenium-server-standalone-2.x.x.jar @@ -131,16 +136,17 @@ Installing from Git sources ~~~~~~~~~~~~~~~~~~~~~~~~~~~ To build Selenium Python from the source code, clone `the official repository -`_. It contains the source code for -all official Selenium flavors, like Python, Java, Ruby and others. The Python -code resides in the ``/py`` directory. To build, you will also need the `Bazel +`_. It contains the source code for +all official Selenium flavors, like Python, Java, Ruby and others. The Python +code resides in the ``/py`` directory. To build, you will also need the `Bazel `_ build system. .. note:: Currently, as Selenium gets near to the 4.0.0 release, it requires Bazel 3.2.0 - (`Install instructions `_), - even though 3.3.0 is already available. + (`Install instructions + `_), even though 3.3.0 + is already available. To build a Wheel from the sources, run the following command from the repository root:: @@ -149,4 +155,4 @@ root:: This command will prepare the source code with some preprocessed JS files needed by some webdriver modules and build the ``.whl`` package inside the -``./bazel-bin/py/`` directory. Afterwards, you can use ``pip`` to install it. +``./bazel-bin/py/`` directory. Afterwards, you can use ``pip`` to install it. diff --git a/source/locating-elements.rst b/source/locating-elements.rst index 7dc71ca..b2dd1f4 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -106,8 +106,7 @@ The username & password elements can be located like this:: username = driver.find_element_by_name('username') password = driver.find_element_by_name('password') -This will give the "Login" button as it occurs before the "Clear" -button:: +This will give the "Login" button as it occurs before the "Clear" button:: continue = driver.find_element_by_name('continue') @@ -208,7 +207,7 @@ of an element: Locating Hyperlinks by Link Text ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use this when you know the link text used within an anchor tag. With this +Use this when you know the link text used within an anchor tag. With this strategy, the first element with the link text matching the provided value will be returned. If no element has a matching link text attribute, a ``NoSuchElementException`` will be raised. @@ -232,8 +231,8 @@ The continue.html link can be located like this:: Locating Elements by Tag Name ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use this when you want to locate an element by tag name. With this strategy, the -first element with the given tag name will be returned. If no element has a +Use this when you want to locate an element by tag name. With this strategy, +the first element with the given tag name will be returned. If no element has a matching tag name, a ``NoSuchElementException`` will be raised. For instance, consider this page source:: @@ -290,5 +289,6 @@ The "p" element can be located like this:: content = driver.find_element_by_css_selector('p.content') -`Sauce Labs has good documentation `_ -on CSS selectors. +`Sauce Labs has good documentation +`_ on CSS +selectors. diff --git a/source/navigating.rst b/source/navigating.rst index 6f6ba21..2e1c511 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -3,28 +3,26 @@ Navigating ---------- -The first thing you'll want to do with WebDriver is navigate to a -link. The normal way to do this is by calling ``get`` method: +The first thing you'll want to do with WebDriver is navigate to a link. The +normal way to do this is by calling ``get`` method: :: driver.get("http://www.google.com") -WebDriver will wait until the page has fully loaded (that is, the -``onload`` event has fired) before returning control to your test or -script. *Be aware that if your page uses a lot of AJAX on -load then WebDriver may not know when it has completely loaded*. If -you need to ensure such pages are fully loaded then you can use -:ref:`waits `. +WebDriver will wait until the page has fully loaded (that is, the ``onload`` +event has fired) before returning control to your test or script. *Be aware +that if your page uses a lot of AJAX on load then WebDriver may not know when it +has completely loaded*. If you need to ensure such pages are fully loaded then +you can use :ref:`waits `. Interacting with the page ~~~~~~~~~~~~~~~~~~~~~~~~~ -Just being able to go to places isn't terribly useful. What we'd -really like to do is to interact with the pages, or, more -specifically, the HTML elements within a page. First of all, we need -to find one. WebDriver offers a number of ways to find elements. For -example, given an element defined as:: +Just being able to go to places isn't terribly useful. What we'd really like to +do is to interact with the pages, or, more specifically, the HTML elements +within a page. First of all, we need to find one. WebDriver offers a number of +ways to find elements. For example, given an element defined as:: @@ -35,24 +33,23 @@ you could find it using any of:: element = driver.find_element_by_xpath("//input[@id='passwd-id']") element = driver.find_element_by_css_selector("input#passwd-id") -You can also look for a link by its text, but be careful! The text -must be an exact match! You should also be careful when using `XPATH -in WebDriver`. If there's more than one element that matches the -query, then only the first will be returned. If nothing can be found, -a ``NoSuchElementException`` will be raised. +You can also look for a link by its text, but be careful! The text must be an +exact match! You should also be careful when using `XPATH in WebDriver`. If +there's more than one element that matches the query, then only the first will +be returned. If nothing can be found, a ``NoSuchElementException`` will be +raised. .. TODO: Is this following paragraph correct ? -WebDriver has an "Object-based" API; we represent all types of -elements using the same interface. This means that although you may -see a lot of possible methods you could invoke when you hit your IDE's -auto-complete key combination, not all of them will make sense or be -valid. Don't worry! WebDriver will attempt to do the Right Thing, and -if you call a method that makes no sense ("setSelected()" on a "meta" -tag, for example) an exception will be raised. +WebDriver has an "Object-based" API; we represent all types of elements using +the same interface. This means that although you may see a lot of possible +methods you could invoke when you hit your IDE's auto-complete key combination, +not all of them will make sense or be valid. Don't worry! WebDriver will +attempt to do the Right Thing, and if you call a method that makes no sense +("setSelected()" on a "meta" tag, for example) an exception will be raised. -So, you've got an element. What can you do with it? First of all, you -may want to enter some text into a text field:: +So, you've got an element. What can you do with it? First of all, you may want +to enter some text into a text field:: element.send_keys("some text") @@ -60,12 +57,11 @@ You can simulate pressing the arrow keys by using the "Keys" class:: element.send_keys(" and some", Keys.ARROW_DOWN) -It is possible to call `send_keys` on any element, which makes it -possible to test keyboard shortcuts such as those used on GMail. A -side-effect of this is that typing something into a text field won't -automatically clear it. Instead, what you type will be appended to -what's already there. You can easily clear the contents of a text -field or textarea with the `clear` method:: +It is possible to call `send_keys` on any element, which makes it possible to +test keyboard shortcuts such as those used on GMail. A side-effect of this is +that typing something into a text field won't automatically clear it. Instead, +what you type will be appended to what's already there. You can easily clear +the contents of a text field or textarea with the `clear` method:: element.clear() @@ -73,10 +69,10 @@ field or textarea with the `clear` method:: Filling in forms ~~~~~~~~~~~~~~~~ -We've already seen how to enter text into a textarea or text field, -but what about the other elements? You can "toggle" the state of the -drop down, and you can use "setSelected" to set something like an -`OPTION` tag selected. Dealing with `SELECT` tags isn't too bad:: +We've already seen how to enter text into a textarea or text field, but what +about the other elements? You can "toggle" the state of the drop down, and you +can use "setSelected" to set something like an `OPTION` tag selected. Dealing +with `SELECT` tags isn't too bad:: element = driver.find_element_by_xpath("//select[@name='name']") all_options = element.find_elements_by_tag_name("option") @@ -84,14 +80,12 @@ drop down, and you can use "setSelected" to set something like an print("Value is: %s" % option.get_attribute("value")) option.click() -This will find the first "SELECT" element on the page, and cycle -through each of its OPTIONs in turn, printing out their values, and -selecting each in turn. +This will find the first "SELECT" element on the page, and cycle through each of +its OPTIONs in turn, printing out their values, and selecting each in turn. -As you can see, this isn't the most efficient -way of dealing with SELECT elements. WebDriver's support classes -include one called a "Select", which provides useful methods for -interacting with these:: +As you can see, this isn't the most efficient way of dealing with SELECT +elements. WebDriver's support classes include one called a "Select", which +provides useful methods for interacting with these:: from selenium.webdriver.support.ui import Select select = Select(driver.find_element_by_name('name')) @@ -117,18 +111,16 @@ To get all available options:: options = select.options -Once you've finished filling out the form, you probably want to submit -it. One way to do this would be to find the "submit" button and click -it:: +Once you've finished filling out the form, you probably want to submit it. One +way to do this would be to find the "submit" button and click it:: # Assume the button has the ID "submit" :) driver.find_element_by_id("submit").click() -Alternatively, WebDriver has the convenience method "submit" on every -element. If you call this on an element within a form, WebDriver will -walk up the DOM until it finds the enclosing form and then calls -submit on that. If the element isn't in a form, then the -``NoSuchElementException`` will be raised:: +Alternatively, WebDriver has the convenience method "submit" on every element. +If you call this on an element within a form, WebDriver will walk up the DOM +until it finds the enclosing form and then calls submit on that. If the element +isn't in a form, then the ``NoSuchElementException`` will be raised:: element.submit() @@ -136,8 +128,8 @@ submit on that. If the element isn't in a form, then the Drag and drop ~~~~~~~~~~~~~ -You can use drag and drop, either moving an element by a certain -amount, or on to another element:: +You can use drag and drop, either moving an element by a certain amount, or on +to another element:: element = driver.find_element_by_name("source") target = driver.find_element_by_name("target") @@ -146,24 +138,24 @@ amount, or on to another element:: action_chains = ActionChains(driver) action_chains.drag_and_drop(element, target).perform() + Moving between windows and frames ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It's rare for a modern web application not to have any frames or to be -constrained to a single window. WebDriver supports moving between -named windows using the "switch_to_window" method:: +constrained to a single window. WebDriver supports moving between named windows +using the "switch_to_window" method:: driver.switch_to_window("windowName") -All calls to ``driver`` will now be interpreted as being directed to -the particular window. But how do you know the window's name? Take a -look at the javascript or link that opened it:: +All calls to ``driver`` will now be interpreted as being directed to the +particular window. But how do you know the window's name? Take a look at the +javascript or link that opened it:: Click here to open a new window -Alternatively, you can pass a "window handle" to the -"switch_to_window()" method. Knowing this, it's possible to iterate -over every open window like so:: +Alternatively, you can pass a "window handle" to the "switch_to_window()" +method. Knowing this, it's possible to iterate over every open window like so:: for handle in driver.window_handles: driver.switch_to_window(handle) @@ -172,41 +164,42 @@ You can also swing from frame to frame (or into iframes):: driver.switch_to_frame("frameName") -It's possible to access subframes by separating the path with a dot, -and you can specify the frame by its index too. That is:: +It's possible to access subframes by separating the path with a dot, and you can +specify the frame by its index too. That is:: driver.switch_to_frame("frameName.0.child") -would go to the frame named "child" of the first subframe of the frame -called "frameName". **All frames are evaluated as if from *top*.** +would go to the frame named "child" of the first subframe of the frame called +"frameName". **All frames are evaluated as if from *top*.** -Once we are done with working on frames, we will have to come back -to the parent frame which can be done using:: +Once we are done with working on frames, we will have to come back to the parent +frame which can be done using:: driver.switch_to_default_content() + Popup dialogs ~~~~~~~~~~~~~ -Selenium WebDriver has built-in support for handling popup dialog -boxes. After you've triggered action that would open a popup, you -can access the alert with the following:: +Selenium WebDriver has built-in support for handling popup dialog boxes. After +you've triggered action that would open a popup, you can access the alert with +the following:: alert = driver.switch_to.alert -This will return the currently open alert object. With this object, -you can now accept, dismiss, read its contents or even type into a -prompt. This interface works equally well on alerts, confirms, -prompts. Refer to the API documentation for more information. +This will return the currently open alert object. With this object, you can now +accept, dismiss, read its contents or even type into a prompt. This interface +works equally well on alerts, confirms, prompts. Refer to the API documentation +for more information. Navigation: history and location ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Earlier, we covered navigating to a page using the "get" command ( -``driver.get("http://www.example.com")``) As you've seen, WebDriver -has a number of smaller, task-focused interfaces, and navigation is a -useful task. To navigate to a page, you can use `get` method:: +``driver.get("http://www.example.com")``). As you've seen, WebDriver has a +number of smaller, task-focused interfaces, and navigation is a useful task. To +navigate to a page, you can use `get` method:: driver.get("http://www.example.com") @@ -215,18 +208,17 @@ To move backward and forward in your browser's history:: driver.forward() driver.back() -Please be aware that this functionality depends entirely on the -underlying driver. It's just possible that something unexpected may -happen when you call these methods if you're used to the behavior of -one browser over another. +Please be aware that this functionality depends entirely on the underlying +driver. It's just possible that something unexpected may happen when you call +these methods if you're used to the behavior of one browser over another. Cookies ~~~~~~~ Before moving to the next section of the tutorial, you may be interested in -understanding how to use cookies. First of all, you need to be on the -domain that the cookie will be valid for: +understanding how to use cookies. First of all, you need to be on the domain +that the cookie will be valid for: :: @@ -239,4 +231,3 @@ domain that the cookie will be valid for: # And now output all the available cookies for the current URL driver.get_cookies() - diff --git a/source/page-objects.rst b/source/page-objects.rst index 822b2ec..ec81c7a 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -3,9 +3,9 @@ Page Objects ------------ -This chapter is a tutorial introduction to page objects design -pattern. A page object represents an area in the web application user -interface that your test is interacting. +This chapter is a tutorial introduction to page objects design pattern. A page +object represents an area in the web application user interface that your test +is interacting. Benefits of using page object pattern: @@ -17,8 +17,8 @@ Benefits of using page object pattern: Test case ~~~~~~~~~ -Here is a test case which searches for a word in python.org website -and ensure some results are found. +Here is a test case which searches for a word in python.org website and ensure +some results are found. :: @@ -57,12 +57,13 @@ and ensure some results are found. if __name__ == "__main__": unittest.main() + Page object classes ~~~~~~~~~~~~~~~~~~~ -The page object pattern intends creating an object for each web page. -By following this technique a layer of separation between the test -code and technical implementation is created. +The page object pattern intends creating an object for each web page. By +following this technique a layer of separation between the test code and +technical implementation is created. The ``page.py`` will look like this:: @@ -107,6 +108,7 @@ The ``page.py`` will look like this:: # element, but as for now it works fine return "No results found." not in self.driver.page_source + Page elements ~~~~~~~~~~~~~ @@ -134,12 +136,13 @@ The ``element.py`` will look like this:: element = driver.find_element_by_name(self.locator) return element.get_attribute("value") + Locators ~~~~~~~~ -One of the practices is to separate the locator strings from the place -where they are being used. In this example, locators of the same page -belong to same class. +One of the practices is to separate the locator strings from the place where +they are being used. In this example, locators of the same page belong to same +class. The ``locators.py`` will look like this:: diff --git a/source/waits.rst b/source/waits.rst index f619867..2a3f303 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -3,32 +3,29 @@ Waits ----- -These days, most of the web apps are using AJAX techniques. When a -page is loaded by the browser, the elements within that page may load at -different time intervals. This makes locating elements difficult: if -an element is not yet present in the DOM, a locate function will raise -an `ElementNotVisibleException` exception. Using waits, we can solve -this issue. Waiting provides some slack between actions -performed - mostly locating an element or any other operation with the -element. - -Selenium Webdriver provides two types of waits - implicit & explicit. -An explicit wait makes WebDriver wait for a certain condition to -occur before proceeding further with execution. An implicit wait -makes WebDriver poll the DOM for a certain amount of time when -trying to locate an element. +These days, most of the web apps are using AJAX techniques. When a page is +loaded by the browser, the elements within that page may load at different time +intervals. This makes locating elements difficult: if an element is not yet +present in the DOM, a locate function will raise an `ElementNotVisibleException` +exception. Using waits, we can solve this issue. Waiting provides some slack +between actions performed - mostly locating an element or any other operation +with the element. + +Selenium Webdriver provides two types of waits - implicit & explicit. An +explicit wait makes WebDriver wait for a certain condition to occur before +proceeding further with execution. An implicit wait makes WebDriver poll the +DOM for a certain amount of time when trying to locate an element. Explicit Waits ~~~~~~~~~~~~~~ -An explicit wait is a code you define to wait for a certain condition -to occur before proceeding further in the code. The extreme case of -this is time.sleep(), which sets the condition to an exact time period -to wait. There are some convenience methods provided that help you -write code that will wait only as long as required. WebDriverWait in -combination with ExpectedCondition is one way this can be -accomplished. +An explicit wait is a code you define to wait for a certain condition to occur +before proceeding further in the code. The extreme case of this is +time.sleep(), which sets the condition to an exact time period to wait. There +are some convenience methods provided that help you write code that will wait +only as long as required. WebDriverWait in combination with ExpectedCondition +is one way this can be accomplished. :: @@ -48,18 +45,19 @@ accomplished. In the code above, Selenium will wait for a maximum of 10 seconds for an element -matching the given criteria to be found. If no element is found in that time, -a TimeoutException is thrown. By default, WebDriverWait calls the -ExpectedCondition every 500 milliseconds until it returns success. -ExpectedCondition will return `true` (Boolean) in case of success or `not null` +matching the given criteria to be found. If no element is found in that time, a +TimeoutException is thrown. By default, WebDriverWait calls the +ExpectedCondition every 500 milliseconds until it returns success. +ExpectedCondition will return `true` (Boolean) in case of success or `not null` if it fails to locate an element. **Expected Conditions** -There are some common conditions that are frequently of use when -automating web browsers. Listed below are the names of -each. Selenium Python binding provides some `convenience methods `_ so you -don't have to code an expected_condition class yourself or create your +There are some common conditions that are frequently of use when automating web +browsers. Listed below are the names of each. Selenium Python binding provides +some `convenience methods +`_ +so you don't have to code an expected_condition class yourself or create your own utility package for them. - title_is @@ -87,14 +85,15 @@ own utility package for them. wait = WebDriverWait(driver, 10) element = wait.until(EC.element_to_be_clickable((By.ID, 'someid'))) -The expected_conditions module contains a set of predefined conditions -to use with WebDriverWait. +The expected_conditions module contains a set of predefined conditions to use +with WebDriverWait. **Custom Wait Conditions** You can also create custom wait conditions when none of the previous convenience -methods fit your requirements. A custom wait condition can be created using a class -with `__call__` method which returns `False` when the condition doesn't match. +methods fit your requirements. A custom wait condition can be created using a +class with `__call__` method which returns `False` when the condition doesn't +match. :: @@ -125,10 +124,10 @@ with `__call__` method which returns `False` when the condition doesn't match. Implicit Waits ~~~~~~~~~~~~~~ -An implicit wait tells WebDriver to poll the DOM for a certain -amount of time when trying to find any element (or elements) -not immediately available. The default setting is 0 (zero). Once set, the -implicit wait is set for the life of the WebDriver object. +An implicit wait tells WebDriver to poll the DOM for a certain amount of time +when trying to find any element (or elements) not immediately available. The +default setting is 0 (zero). Once set, the implicit wait is set for the life of +the WebDriver object. :: From 7da0ab8900f6b4fa7d0f53e63569efd765d20349 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 22 Oct 2020 21:37:17 +0530 Subject: [PATCH 17/52] Link to CSS selector docs --- source/locating-elements.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/locating-elements.rst b/source/locating-elements.rst index b2dd1f4..6797b69 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -272,9 +272,10 @@ The "p" element can be located like this:: Locating Elements by CSS Selectors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use this when you want to locate an element using CSS selector syntax. With -this strategy, the first element matching the given CSS selector will be -returned. If no element matches the provided CSS selector, a +Use this when you want to locate an element using `CSS selector +` +syntax. With this strategy, the first element matching the given CSS selector +will be returned. If no element matches the provided CSS selector, a ``NoSuchElementException`` will be raised. For instance, consider this page source:: From 257bace5654927bdd274e7194011473ed44d5c0e Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 22 Oct 2020 21:53:59 +0530 Subject: [PATCH 18/52] Fix typo --- source/locating-elements.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/locating-elements.rst b/source/locating-elements.rst index 6797b69..630f864 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -273,7 +273,7 @@ Locating Elements by CSS Selectors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use this when you want to locate an element using `CSS selector -` +`_ syntax. With this strategy, the first element matching the given CSS selector will be returned. If no element matches the provided CSS selector, a ``NoSuchElementException`` will be raised. From f557fcecc24d26a9b10d1b8341a8c4c445bce208 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 23 Oct 2020 15:21:56 +0530 Subject: [PATCH 19/52] Mention polling2 library --- source/waits.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/waits.rst b/source/waits.rst index 2a3f303..0300787 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -120,6 +120,11 @@ match. element = wait.until(element_has_css_class((By.ID, 'myNewInput'), "myCSSClass")) +.. note:: **polling2 Library** + + You may also consider using `polling2 + `_ + lirbary which you need to install separately. Implicit Waits ~~~~~~~~~~~~~~ From a8932869af9b88d0dd0e45d03a0169aec092cdd3 Mon Sep 17 00:00:00 2001 From: Neha Verma Date: Sat, 24 Oct 2020 17:56:17 +0530 Subject: [PATCH 20/52] Updated to fix grammatical and punctuation issues (#93) * Updated to fix grammatical and punctuation issues feat: Grammatical and punctuation updates 1. Added missing quote in the second instance of close at line number 88 2. Corrected walkthrough as it is a single word 3. Updated line number 152 for grammatical mistake * Added links and updated as per comments Co-authored-by: Baiju Muthukadan --- source/getting-started.rst | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 3480cb9..03d4d98 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -85,7 +85,7 @@ ensure that some results are found, make an assertion:: assert "No results found." not in driver.page_source Finally, the browser window is closed. You can also call `quit` method instead -of `close`. The `quit` will exit entire browser whereas close` will close one +of `close`. The `quit` will exit entire browser whereas `close` will close one tab, but if just one tab was open, by default most browser will exit entirely.:: driver.close() @@ -96,8 +96,8 @@ Using Selenium to write tests Selenium is mostly used for writing test cases. The `selenium` package itself doesn't provide a testing tool/framework. You can write test cases using -Python's unittest module. The other options for a tool/framework are py.test -and nose. +Python's unittest module. The other options for a tool/framework are `pytest `_ +and `nose `_. In this chapter, we use `unittest` as the framework of choice. Here is the modified example which uses unittest module. This is a test for `python.org` @@ -141,15 +141,15 @@ You can run the above test case from a shell like this:: The above result shows that the test has been successfully completed. -Walk through of the example -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Walkthrough of the example +~~~~~~~~~~~~~~~~~~~~~~~~~~ Initially, all the basic modules required are imported. The `unittest `_ module is a built-in Python based on Java's JUnit. This module provides the framework for organizing the test cases. The `selenium.webdriver` module provides all the WebDriver implementations. Currently supported WebDriver implementations are Firefox, -Chrome, Ie and Remote. The `Keys` class provide keys in the keyboard like +Chrome, IE and Remote. The `Keys` class provides keys in the keyboard like RETURN, F1, ALT etc. :: @@ -269,4 +269,3 @@ dictionaries, you can specify the values explicitly:: desired_capabilities={'browserName': 'htmlunit', 'version': '2', 'javascriptEnabled': True}) - From 24442c0fe4ac0e43fcf7afe0aa4ef87d0f293cd6 Mon Sep 17 00:00:00 2001 From: Neha Verma Date: Wed, 28 Oct 2020 00:10:23 +0530 Subject: [PATCH 21/52] Add a note about usage with IPython or Jupyter Co-authored-by: Baiju Muthukadan --- source/getting-started.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/getting-started.rst b/source/getting-started.rst index 03d4d98..3dab345 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -140,6 +140,12 @@ You can run the above test case from a shell like this:: The above result shows that the test has been successfully completed. +Note: To run the above test in IPython or Jupyter, you should pass a couple of arguments to the `main` function as shown below: +:: + + unittest.main(argv=['first-arg-is-ignored'], exit=False) + + Walkthrough of the example ~~~~~~~~~~~~~~~~~~~~~~~~~~ From 40e213ff30c95587a61ffc161003432838dcb5eb Mon Sep 17 00:00:00 2001 From: Caterina Curti Date: Mon, 8 Feb 2021 15:04:27 +1100 Subject: [PATCH 22/52] Fixed Typo (#95) --- source/waits.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/waits.rst b/source/waits.rst index 0300787..fc00b1e 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -124,7 +124,7 @@ match. You may also consider using `polling2 `_ - lirbary which you need to install separately. + library which you need to install separately. Implicit Waits ~~~~~~~~~~~~~~ From 7e47b0000f8c62a695b974f1ba4c9cbd7039fa35 Mon Sep 17 00:00:00 2001 From: Ai-Lin Liou Date: Thu, 18 Mar 2021 15:44:55 +0800 Subject: [PATCH 23/52] fix the typo (#96) --- source/locating-elements.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/locating-elements.rst b/source/locating-elements.rst index 630f864..574001c 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -73,7 +73,7 @@ For instance, consider this page source:: - + The form element can be located like this:: @@ -99,7 +99,7 @@ For instance, consider this page source:: - + The username & password elements can be located like this:: @@ -144,7 +144,7 @@ For instance, consider this page source:: - + The form elements can be located like this:: @@ -220,7 +220,7 @@ For instance, consider this page source:: Continue Cancel - + The continue.html link can be located like this:: @@ -242,7 +242,7 @@ For instance, consider this page source::

Welcome

Site content goes here.

- + The heading (h1) element can be located like this:: @@ -263,7 +263,7 @@ For instance, consider this page source::

Site content goes here.

- + The "p" element can be located like this:: @@ -284,7 +284,7 @@ For instance, consider this page source::

Site content goes here.

- + The "p" element can be located like this:: From 9e4d949b04dac2ba53d1bac533fdc0292a156fb4 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Mon, 19 Apr 2021 06:38:37 +0530 Subject: [PATCH 24/52] simplify sentences --- source/page-objects.rst | 44 ++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index ec81c7a..bd5aafb 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -3,13 +3,13 @@ Page Objects ------------ -This chapter is a tutorial introduction to page objects design pattern. A page -object represents an area in the web application user interface that your test -is interacting. +This chapter is a tutorial introduction to the Page Objects design pattern. A +page object represents an area where the test interacts within the web +application user interface. Benefits of using page object pattern: -* Creating reusable code that can be shared across multiple test cases +* Creating reusable code that can share across multiple test cases * Reducing the amount of duplicated code * If the user interface changes, the fix needs changes in only one place @@ -17,8 +17,9 @@ Benefits of using page object pattern: Test case ~~~~~~~~~ -Here is a test case which searches for a word in python.org website and ensure -some results are found. +Here is a test case that searches for a word on the `python.org` website and +ensures some results. The following section will introduce the `page` module +where the page objects will be defined. :: @@ -34,11 +35,10 @@ some results are found. self.driver.get("http://www.python.org") def test_search_in_python_org(self): - """ - Tests python.org search feature. Searches for the word "pycon" then verified that some results show up. - Note that it does not look for any particular text in search results page. This test verifies that - the results were not empty. - """ + """Tests python.org search feature. Searches for the word "pycon" then + verified that some results show up. Note that it does not look for + any particular text in search results page. This test verifies that + the results were not empty.""" #Load the main page. In this case the home page of Python.org. main_page = page.MainPage(self.driver) @@ -61,9 +61,9 @@ some results are found. Page object classes ~~~~~~~~~~~~~~~~~~~ -The page object pattern intends creating an object for each web page. By -following this technique a layer of separation between the test code and -technical implementation is created. +The page object pattern intends to create an object for each part of a web page. +This technique helps build a separation between the test code and the actual +code that interacts with the web page. The ``page.py`` will look like this:: @@ -78,7 +78,8 @@ The ``page.py`` will look like this:: class BasePage(object): - """Base class to initialize the base page that will be called from all pages""" + """Base class to initialize the base page that will be called from all + pages""" def __init__(self, driver): self.driver = driver @@ -92,10 +93,12 @@ The ``page.py`` will look like this:: def is_title_matches(self): """Verifies that the hardcoded text "Python" appears in page title""" + return "Python" in self.driver.title def click_go_button(self): """Triggers the search""" + element = self.driver.find_element(*MainPageLocators.GO_BUTTON) element.click() @@ -122,6 +125,7 @@ The ``element.py`` will look like this:: def __set__(self, obj, value): """Sets the text to the value supplied""" + driver = obj.driver WebDriverWait(driver, 100).until( lambda driver: driver.find_element_by_name(self.locator)) @@ -130,6 +134,7 @@ The ``element.py`` will look like this:: def __get__(self, obj, owner): """Gets the text of the specified object""" + driver = obj.driver WebDriverWait(driver, 100).until( lambda driver: driver.find_element_by_name(self.locator)) @@ -141,8 +146,8 @@ Locators ~~~~~~~~ One of the practices is to separate the locator strings from the place where -they are being used. In this example, locators of the same page belong to same -class. +they are getting used. In this example, locators of the same page belong to the +same class. The ``locators.py`` will look like this:: @@ -150,8 +155,11 @@ The ``locators.py`` will look like this:: class MainPageLocators(object): """A class for main page locators. All main page locators should come here""" + GO_BUTTON = (By.ID, 'submit') class SearchResultsPageLocators(object): - """A class for search results locators. All search results locators should come here""" + """A class for search results locators. All search results locators should + come here""" + pass From df08cb842307fcfe318ee369506219ad124ff102 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Mon, 19 Apr 2021 06:50:56 +0530 Subject: [PATCH 25/52] Add readthedocs configguration --- .readthedocs.yaml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..6cd6e72 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,20 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: source/conf.py + +# Optionally build your docs in additional formats such as PDF +formats: + - pdf + +# Optionally set the version of Python and requirements required to build your docs +python: + version: 3.7 + install: + - requirements: requirements.txt From 2c3b5f39dc4ec982b11c4daf51f7c531ce6135eb Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Mon, 19 Apr 2021 07:06:32 +0530 Subject: [PATCH 26/52] Add one more benefit --- source/page-objects.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/source/page-objects.rst b/source/page-objects.rst index bd5aafb..03c504d 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -9,6 +9,7 @@ application user interface. Benefits of using page object pattern: +* Easy to read test cases * Creating reusable code that can share across multiple test cases * Reducing the amount of duplicated code * If the user interface changes, the fix needs changes in only one place From 513415fc847ff6decd7ac822419fb2643a16f4fc Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Mon, 19 Apr 2021 07:17:18 +0530 Subject: [PATCH 27/52] Remove outdated TODO --- TODO.txt | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 TODO.txt diff --git a/TODO.txt b/TODO.txt deleted file mode 100644 index d571ab2..0000000 --- a/TODO.txt +++ /dev/null @@ -1,4 +0,0 @@ -- Cover basics of unittest -- XPATH (Appendix) -- Mouse over -- Complete: Test Design Considerations From 6a8866a9f9ef3b13d6f4101d35bdd0c85895512b Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 27 May 2021 12:09:05 +0530 Subject: [PATCH 28/52] whitespace fixes --- source/getting-started.rst | 11 ++++++----- source/page-objects.rst | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 3dab345..c304155 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -96,8 +96,9 @@ Using Selenium to write tests Selenium is mostly used for writing test cases. The `selenium` package itself doesn't provide a testing tool/framework. You can write test cases using -Python's unittest module. The other options for a tool/framework are `pytest `_ -and `nose `_. +Python's unittest module. The other options for a tool/framework are `pytest +`_ and `nose +`_. In this chapter, we use `unittest` as the framework of choice. Here is the modified example which uses unittest module. This is a test for `python.org` @@ -140,8 +141,8 @@ You can run the above test case from a shell like this:: The above result shows that the test has been successfully completed. -Note: To run the above test in IPython or Jupyter, you should pass a couple of arguments to the `main` function as shown below: -:: +Note: To run the above test in IPython or Jupyter, you should pass a couple of +arguments to the `main` function as shown below:: unittest.main(argv=['first-arg-is-ignored'], exit=False) @@ -190,7 +191,7 @@ to the driver object created in `setUp` method. The `driver.get` method will navigate to a page given by the URL. WebDriver will wait until the page has fully loaded (that is, the "onload" event has -fired) before returning control to your test or script. *Be aware that if your +fired) before returning control to your test or script. *Be aware that if your page uses a lot of AJAX on load then WebDriver may not know when it has completely loaded*:: diff --git a/source/page-objects.rst b/source/page-objects.rst index 03c504d..da8167e 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -19,7 +19,7 @@ Test case ~~~~~~~~~ Here is a test case that searches for a word on the `python.org` website and -ensures some results. The following section will introduce the `page` module +ensures some results. The following section will introduce the `page` module where the page objects will be defined. :: From 396a7bb5a89168585383ceb3b8f36782afdf7dae Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 28 May 2021 10:33:37 +0530 Subject: [PATCH 29/52] rearrange sections --- source/installation.rst | 110 +++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 57 deletions(-) diff --git a/source/installation.rst b/source/installation.rst index da5ecdd..5098fb7 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -18,19 +18,18 @@ This documentation explains Selenium 2 WebDriver API. Selenium 1 / Selenium RC API is not covered here. -Downloading Python bindings for Selenium -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - +Installing Python bindings for Selenium +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use `pip `_ to install the selenium -package. Python 3.6 has pip available in the `standard library -`_. Using `pip`, you can +Use `pip `_ to install the selenium +package. Python 3 has pip available in the `standard library +`_. Using `pip`, you can install selenium like this:: pip install selenium -You may consider using `virtualenv `_ to create -isolated Python environments. Python 3 has `venv +You may consider using `virtualenv `_ to +create isolated Python environments. Python 3 has `venv `_ which is almost the same as virtualenv. @@ -38,6 +37,52 @@ You can also download Python bindings for Selenium from the `PyPI page for selenium package `_. and install manually. + +Instructions for Windows users +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. Install Python 3 using the `MSI available in python.org download page + `_. + +2. Start a command prompt using the ``cmd.exe`` program and run the ``pip`` + command as given below to install `selenium`. + + :: + + C:\Python39\Scripts\pip.exe install selenium + +Now you can run your test scripts using Python. For example, if you have +created a Selenium based script and saved it inside +``C:\my_selenium_script.py``, you can run it like this:: + + C:\Python39\python.exe C:\my_selenium_script.py + + +Installing from Git sources +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To build Selenium Python from the source code, clone `the official repository +`_. It contains the source code for +all official Selenium flavors, like Python, Java, Ruby and others. The Python +code resides in the ``/py`` directory. To build, you will also need the `Bazel +`_ build system. + +.. note:: + + Currently, as Selenium gets near to the 4.0.0 release, it requires Bazel 3.2.0 + (`Install instructions + `_), even though 3.3.0 + is already available. + +To build a Wheel from the sources, run the following command from the repository +root:: + + bazel //py:selenium-wheel + +This command will prepare the source code with some preprocessed JS files needed +by some webdriver modules and build the ``.whl`` package inside the +``./bazel-bin/py/`` directory. Afterwards, you can use ``pip`` to install it. + Drivers ~~~~~~~ @@ -68,29 +113,6 @@ For more information about driver installation, please refer the `official documentation `_. -Detailed instructions for Windows users -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. Note:: - - You should have an internet connection to perform this installation. - -1. Install Python 3.6 using the `MSI available in python.org download page - `_. - -2. Start a command prompt using the ``cmd.exe`` program and run the ``pip`` - command as given below to install `selenium`. - - :: - - C:\Python35\Scripts\pip.exe install selenium - -Now you can run your test scripts using Python. For example, if you have -created a Selenium based script and saved it inside -``C:\my_selenium_script.py``, you can run it like this:: - - C:\Python35\python.exe C:\my_selenium_script.py - Downloading Selenium server ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -130,29 +152,3 @@ command. Similarly, you can provide a relative or absolute path to Selenium server jar file. Then, the command will look something like this:: /path/to/java -jar /path/to/selenium-server-standalone-2.x.x.jar - - -Installing from Git sources -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To build Selenium Python from the source code, clone `the official repository -`_. It contains the source code for -all official Selenium flavors, like Python, Java, Ruby and others. The Python -code resides in the ``/py`` directory. To build, you will also need the `Bazel -`_ build system. - -.. note:: - - Currently, as Selenium gets near to the 4.0.0 release, it requires Bazel 3.2.0 - (`Install instructions - `_), even though 3.3.0 - is already available. - -To build a Wheel from the sources, run the following command from the repository -root:: - - bazel //py:selenium-wheel - -This command will prepare the source code with some preprocessed JS files needed -by some webdriver modules and build the ``.whl`` package inside the -``./bazel-bin/py/`` directory. Afterwards, you can use ``pip`` to install it. From 6370b59ad48071c023e51d871b73847845fffc6c Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Fri, 3 Sep 2021 21:04:29 +1000 Subject: [PATCH 30/52] docs: fix simple typo, shat -> that (#98) There is a small typo in source/conf.py. Should read `that` rather than `shat`. --- source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/conf.py b/source/conf.py index 316e761..1829d9f 100644 --- a/source/conf.py +++ b/source/conf.py @@ -257,7 +257,7 @@ # The format is a list of tuples containing the path and title. #epub_pre_files = [] -# HTML files shat should be inserted after the pages created by sphinx. +# HTML files that should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_post_files = [] From 36a089b51bee2c36aacda6d914fc957c2c0c7983 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Mon, 4 Oct 2021 18:23:44 +0530 Subject: [PATCH 31/52] Update driver website link --- source/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/installation.rst b/source/installation.rst index 5098fb7..a998151 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -100,7 +100,7 @@ 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 | +| **Chrome**: | https://sites.google.com/chromium.org/driver/ | +--------------+-----------------------------------------------------------------------+ | **Edge**: | https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ | +--------------+-----------------------------------------------------------------------+ From d1ea80957f3b0c4b58d589f3639946544b0b5082 Mon Sep 17 00:00:00 2001 From: meni181818 Date: Wed, 16 Feb 2022 23:47:38 +0200 Subject: [PATCH 32/52] unittest.TestCase.assertNotIn insted of assert " not in (#100) `self.assertNotIn("No results found.", driver.page_source)` insted of `assert "No results found." not in driver.page_source`. as previous `self.assertIn("Python", driver.title)` https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertNotIn --- source/getting-started.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index c304155..d5c23d9 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -120,7 +120,7 @@ search functionality:: elem = driver.find_element_by_name("q") elem.send_keys("pycon") elem.send_keys(Keys.RETURN) - assert "No results found." not in driver.page_source + self.assertNotIn("No results found.", driver.page_source) def tearDown(self): @@ -220,7 +220,7 @@ Special keys can be send using `Keys` class imported from After submission of the page, you should get the result as per search if there is any. To ensure that some results are found, make an assertion:: - assert "No results found." not in driver.page_source + self.assertNotIn("No results found.", driver.page_source) The `tearDown` method will get called after every test method. This is a place to do all cleanup actions. In the current method, the browser window is closed. From 469d30da4e46c16681f612e3b50d6a81ec8c1226 Mon Sep 17 00:00:00 2001 From: meni181818 Date: Thu, 17 Feb 2022 10:43:01 +0200 Subject: [PATCH 33/52] unittest.TestCase.assertTrue insted of assert (#101) since we use unittet. --- source/page-objects.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index da8167e..1a59df7 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -44,13 +44,13 @@ where the page objects will be defined. #Load the main page. In this case the home page of Python.org. main_page = page.MainPage(self.driver) #Checks if the word "Python" is in title - assert main_page.is_title_matches(), "python.org title doesn't match." + self.assertTrue(main_page.is_title_matches(), "python.org title doesn't match.") #Sets the text of search textbox to "pycon" main_page.search_text_element = "pycon" main_page.click_go_button() search_results_page = page.SearchResultsPage(self.driver) #Verifies that the results page is not empty - assert search_results_page.is_results_found(), "No results found." + self.assertTrue(search_results_page.is_results_found(), "No results found.") def tearDown(self): self.driver.close() From 7a104ef7f8819959def444f4cb912714340e705b Mon Sep 17 00:00:00 2001 From: LRNKN <78888840+LRNKN@users.noreply.github.com> Date: Thu, 10 Mar 2022 18:29:24 +1030 Subject: [PATCH 34/52] Update README.rst (#102) Small wording and syntax change for project introduction text. --- README.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 1f25ce5..1710b67 100644 --- a/README.rst +++ b/README.rst @@ -3,16 +3,16 @@ Selenium Python Bindings Documentation https://selenium-python.readthedocs.io -NOTE: THIS IS NOT AN OFFICIAL DOCUMENTATION +NOTE: THIS IS NOT OFFICIAL DOCUMENTATION -This is not an official documentation. If you would like to contribute to this +This is not official documentation. If you would like to contribute to this documentation, you can `fork this project in GitHub and send pull requests `_. You can also send your feedback to my email: baiju.m.mail AT gmail DOT com. So far 50+ community members have -contributed to this project (See the closed pull requests). I encourage -contributors to add more sections and make it an awesome documentation! If you -know any translation of this document, please send a PR to update the below -list. +contributed to this project (See the 'Closed' pull requests). I encourage +contributors to add more sections to make this documentation even more awesome! +If you know any translations of this document, or would like to create new translations, +please send a PR to update the below list. **Translations:** From 3b13c2f8f864c2b4a56fb5dddebab0cd86817ad6 Mon Sep 17 00:00:00 2001 From: dysphere <30881686+dysphere@users.noreply.github.com> Date: Tue, 31 May 2022 04:02:22 -0700 Subject: [PATCH 35/52] Updated find_element method (#99) --- source/getting-started.rst | 31 +++++++++------ source/locating-elements.rst | 77 ++++++++++++++++-------------------- source/navigating.rst | 22 +++++------ 3 files changed, 64 insertions(+), 66 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index d5c23d9..62a9de2 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -13,11 +13,12 @@ Python like this. from selenium import webdriver from selenium.webdriver.common.keys import Keys + from selenium.webdriver.common.by import By driver = webdriver.Firefox() driver.get("http://www.python.org") assert "Python" in driver.title - elem = driver.find_element_by_name("q") + elem = driver.find_element(By.NAME, "q") elem.clear() elem.send_keys("pycon") elem.send_keys(Keys.RETURN) @@ -36,12 +37,14 @@ Example Explained The `selenium.webdriver` module provides all the WebDriver implementations. Currently supported WebDriver implementations are Firefox, Chrome, IE and -Remote. The `Keys` class provide keys in the keyboard like RETURN, F1, ALT etc. +Remote. The `Keys` class provide keys in the keyboard like RETURN, F1, ALT etc. +The `By` class is used to locate elements within a document. :: from selenium import webdriver from selenium.webdriver.common.keys import Keys + from selenium.webdriver.common.by import By Next, the instance of Firefox WebDriver is created. @@ -61,13 +64,13 @@ The next line is an assertion to confirm that title has "Python" word in it:: assert "Python" in driver.title -WebDriver offers a number of ways to find elements using one of the -`find_element_by_*` methods. For example, the input text element can be located -by its `name` attribute using `find_element_by_name` method. A detailed -explanation of finding elements is available in the :ref:`locating-elements` +WebDriver offers a number of ways to find elements using the +`find_element` method. For example, the input text element can be located +by its `name` attribute using the `find_element` method and using By.NAME as its first parameter. +A detailed explanation of finding elements is available in the :ref:`locating-elements` chapter:: - elem = driver.find_element_by_name("q") + elem = driver.find_element(By.NAME, "q") Next, we are sending keys, this is similar to entering keys using your keyboard. Special keys can be sent using `Keys` class imported from @@ -107,6 +110,7 @@ search functionality:: import unittest from selenium import webdriver from selenium.webdriver.common.keys import Keys + from selenium.webdriver.common.by import By class PythonOrgSearch(unittest.TestCase): @@ -117,7 +121,7 @@ search functionality:: driver = self.driver driver.get("http://www.python.org") self.assertIn("Python", driver.title) - elem = driver.find_element_by_name("q") + elem = driver.find_element(By.NAME, "q") elem.send_keys("pycon") elem.send_keys(Keys.RETURN) self.assertNotIn("No results found.", driver.page_source) @@ -157,13 +161,14 @@ based on Java's JUnit. This module provides the framework for organizing the test cases. The `selenium.webdriver` module provides all the WebDriver implementations. Currently supported WebDriver implementations are Firefox, Chrome, IE and Remote. The `Keys` class provides keys in the keyboard like -RETURN, F1, ALT etc. +RETURN, F1, ALT etc. The `By` class is used to locate elements within a document. :: import unittest from selenium import webdriver from selenium.webdriver.common.keys import Keys + from selenium.webdriver.common.by import By The test case class is inherited from `unittest.TestCase`. Inheriting from `TestCase` class is the way to tell `unittest` module that this is a test case:: @@ -202,13 +207,13 @@ The next line is an assertion to confirm that title has "Python" word in it:: self.assertIn("Python", driver.title) -WebDriver offers a number of ways to find elements using one of the -`find_element_by_*` methods. For example, the input text element can be located -by its `name` attribute using `find_element_by_name` method. Detailed +WebDriver offers a number of ways to find elements using the +`find_element` method. For example, the input text element can be located +by its `name` attribute using the `find_element` method. Detailed explanation of finding elements is available in the :ref:`locating-elements` chapter:: - elem = driver.find_element_by_name("q") + elem = driver.find_element(By.NAME, "q") Next, we are sending keys, this is similar to entering keys using your keyboard. Special keys can be send using `Keys` class imported from diff --git a/source/locating-elements.rst b/source/locating-elements.rst index 574001c..8d0ebb1 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -4,34 +4,13 @@ Locating Elements ----------------- There are various strategies to locate elements in a page. You can use the most -appropriate one for your case. Selenium provides the following methods to +appropriate one for your case. Selenium provides the following method to locate elements in a page: -- `find_element_by_id` -- `find_element_by_name` -- `find_element_by_xpath` -- `find_element_by_link_text` -- `find_element_by_partial_link_text` -- `find_element_by_tag_name` -- `find_element_by_class_name` -- `find_element_by_css_selector` - +- `find_element` **To find multiple elements (these methods will return a list):** -- `find_elements_by_name` -- `find_elements_by_xpath` -- `find_elements_by_link_text` -- `find_elements_by_partial_link_text` -- `find_elements_by_tag_name` -- `find_elements_by_class_name` -- `find_elements_by_css_selector` - - -Apart from the public methods given above, there are two private methods which -might be useful for locating page elements: - -- `find_element` - `find_elements` @@ -42,18 +21,32 @@ Example usage:: driver.find_element(By.XPATH, '//button[text()="Some text"]') driver.find_elements(By.XPATH, '//button') - +The attributes available for the `By` class are used to locate elements on a page. These are the attributes available for `By` class:: ID = "id" + NAME = "name" 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" +The 'By' class is used to specify which attribute is used to locate elements on a page. +These are the various ways the attributes are used to locate elements on a page:: + + find_element(By.ID, "id") + find_element(By.NAME, "name") + find_element(By.XPATH, "xpath") + find_element(By.LINK_TEXT, "link text") + find_element(By.PARTIAL_LINK_TEXT, "partial link text") + find_element(By.TAG_NAME, "tag name") + find_element(By.CLASS_NAME, "class name") + find_element(By.CSS_SELECTOR, "css selector") + +If you want to locate several elements with the same attribute replace find_element with find_elements. + Locating by Id ~~~~~~~~~~~~~~ @@ -77,7 +70,7 @@ For instance, consider this page source:: The form element can be located like this:: - login_form = driver.find_element_by_id('loginForm') + login_form = driver.find_element(By.ID, 'loginForm') Locating by Name @@ -103,12 +96,12 @@ For instance, consider this page source:: The username & password elements can be located like this:: - username = driver.find_element_by_name('username') - password = driver.find_element_by_name('password') + username = driver.find_element(By.NAME, 'username') + password = driver.find_element(By.NAME, 'password') This will give the "Login" button as it occurs before the "Clear" button:: - continue = driver.find_element_by_name('continue') + continue = driver.find_element(By.NAME, 'continue') Locating by XPath @@ -148,9 +141,9 @@ For instance, consider this page source:: The form elements can be located like this:: - login_form = driver.find_element_by_xpath("/html/body/form[1]") - login_form = driver.find_element_by_xpath("//form[1]") - login_form = driver.find_element_by_xpath("//form[@id='loginForm']") + login_form = driver.find_element(By.XPATH, "/html/body/form[1]") + login_form = driver.find_element(By.XPATH, "//form[1]") + login_form = driver.find_element(By.XPATH, "//form[@id='loginForm']") 1. Absolute path (would break if the HTML was changed only slightly) @@ -161,9 +154,9 @@ The form elements can be located like this:: The username element can be located like this:: - username = driver.find_element_by_xpath("//form[input/@name='username']") - username = driver.find_element_by_xpath("//form[@id='loginForm']/input[1]") - username = driver.find_element_by_xpath("//input[@name='username']") + username = driver.find_element(By.XPATH, "//form[input/@name='username']") + username = driver.find_element(By.XPATH, "//form[@id='loginForm']/input[1]") + username = driver.find_element(By.XPATH, "//input[@name='username']") 1. First form element with an input child element with `name` set to `username` @@ -174,8 +167,8 @@ The username element can be located like this:: The "Clear" button element can be located like this:: - clear_button = driver.find_element_by_xpath("//input[@name='continue'][@type='button']") - clear_button = driver.find_element_by_xpath("//form[@id='loginForm']/input[4]") + clear_button = driver.find_element(By.XPATH, "//input[@name='continue'][@type='button']") + clear_button = driver.find_element(By.XPATH, "//form[@id='loginForm']/input[4]") 1. Input with attribute `name` set to `continue` and attribute `type` set to @@ -224,8 +217,8 @@ For instance, consider this page source:: The continue.html link can be located like this:: - continue_link = driver.find_element_by_link_text('Continue') - continue_link = driver.find_element_by_partial_link_text('Conti') + continue_link = driver.find_element(By.LINK_TEXT, 'Continue') + continue_link = driver.find_element(By.PARTIAL_LINK_TEXT, 'Conti') Locating Elements by Tag Name @@ -246,7 +239,7 @@ For instance, consider this page source:: The heading (h1) element can be located like this:: - heading1 = driver.find_element_by_tag_name('h1') + heading1 = driver.find_element(By.TAG_NAME, 'h1') Locating Elements by Class Name @@ -267,7 +260,7 @@ For instance, consider this page source:: The "p" element can be located like this:: - content = driver.find_element_by_class_name('content') + content = driver.find_element(By.CLASS_NAME, 'content') Locating Elements by CSS Selectors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -288,7 +281,7 @@ For instance, consider this page source:: The "p" element can be located like this:: - content = driver.find_element_by_css_selector('p.content') + content = driver.find_element(By.CSS_SELECTOR, 'p.content') `Sauce Labs has good documentation `_ on CSS diff --git a/source/navigating.rst b/source/navigating.rst index 2e1c511..559bd99 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -28,10 +28,10 @@ ways to find elements. For example, given an element defined as:: you could find it using any of:: - element = driver.find_element_by_id("passwd-id") - element = driver.find_element_by_name("passwd") - element = driver.find_element_by_xpath("//input[@id='passwd-id']") - element = driver.find_element_by_css_selector("input#passwd-id") + element = driver.find_element(By.ID, "passwd-id") + element = driver.find_element(By.NAME, "passwd") + element = driver.find_element(By.XPATH, "//input[@id='passwd-id']") + element = driver.find_element(By.CSS_SELECTOR, "input#passwd-id") You can also look for a link by its text, but be careful! The text must be an exact match! You should also be careful when using `XPATH in WebDriver`. If @@ -74,8 +74,8 @@ about the other elements? You can "toggle" the state of the drop down, and you can use "setSelected" to set something like an `OPTION` tag selected. Dealing with `SELECT` tags isn't too bad:: - element = driver.find_element_by_xpath("//select[@name='name']") - all_options = element.find_elements_by_tag_name("option") + element = driver.find_element(By.XPATH, "//select[@name='name']") + all_options = element.find_elements(By.TAG_NAME, "option") for option in all_options: print("Value is: %s" % option.get_attribute("value")) option.click() @@ -88,7 +88,7 @@ elements. WebDriver's support classes include one called a "Select", which provides useful methods for interacting with these:: from selenium.webdriver.support.ui import Select - select = Select(driver.find_element_by_name('name')) + select = Select(driver.find_element(By.NAME, 'name')) select.select_by_index(index) select.select_by_visible_text("text") select.select_by_value(value) @@ -96,7 +96,7 @@ provides useful methods for interacting with these:: WebDriver also provides features for deselecting all the selected options:: - select = Select(driver.find_element_by_id('id')) + select = Select(driver.find_element(By.ID, 'id')) select.deselect_all() This will deselect all OPTIONs from that particular SELECT on the page. @@ -104,7 +104,7 @@ This will deselect all OPTIONs from that particular SELECT on the page. Suppose in a test, we need the list of all default selected options, Select class provides a property method that returns a list:: - select = Select(driver.find_element_by_xpath("//select[@name='name']")) + select = Select(driver.find_element(By.XPATH, "//select[@name='name']")) all_selected_options = select.all_selected_options To get all available options:: @@ -131,8 +131,8 @@ Drag and drop You can use drag and drop, either moving an element by a certain amount, or on to another element:: - element = driver.find_element_by_name("source") - target = driver.find_element_by_name("target") + element = driver.find_element(By.NAME, "source") + target = driver.find_element(By.NAME, "target") from selenium.webdriver import ActionChains action_chains = ActionChains(driver) From 341ca8c30669af259a394e119d59a78cdbb089a5 Mon Sep 17 00:00:00 2001 From: Ryan Slater Date: Wed, 24 Aug 2022 00:50:33 -0400 Subject: [PATCH 36/52] Corrected typo in docs 3.4 (#105) --- source/navigating.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/navigating.rst b/source/navigating.rst index 559bd99..e744218 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -106,7 +106,7 @@ class provides a property method that returns a list:: select = Select(driver.find_element(By.XPATH, "//select[@name='name']")) all_selected_options = select.all_selected_options - + To get all available options:: options = select.options @@ -175,7 +175,7 @@ would go to the frame named "child" of the first subframe of the frame called Once we are done with working on frames, we will have to come back to the parent frame which can be done using:: - driver.switch_to_default_content() + driver.switch_to.default_content() Popup dialogs From 54fcbcc8418c9000fcd1d747be82c539c789931d Mon Sep 17 00:00:00 2001 From: Kitty Depa Date: Mon, 12 Sep 2022 04:49:17 +0200 Subject: [PATCH 37/52] Grammar edits in the Getting Started page (#107) * Grammar edits Authored-by: kittydepa --- source/getting-started.rst | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 62a9de2..a9a38b7 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -60,7 +60,7 @@ completely loaded*:: driver.get("http://www.python.org") -The next line is an assertion to confirm that title has "Python" word in it:: +The next line is an assertion to confirm that title has the word "Python" in it:: assert "Python" in driver.title @@ -73,7 +73,7 @@ chapter:: elem = driver.find_element(By.NAME, "q") Next, we are sending keys, this is similar to entering keys using your keyboard. -Special keys can be sent using `Keys` class imported from +Special keys can be sent using the `Keys` class imported from `selenium.webdriver.common.keys`. To be safe, we'll first clear any pre-populated text in the input field (e.g. "Search") so it doesn't affect our search results:: @@ -87,9 +87,9 @@ ensure that some results are found, make an assertion:: assert "No results found." not in driver.page_source -Finally, the browser window is closed. You can also call `quit` method instead -of `close`. The `quit` will exit entire browser whereas `close` will close one -tab, but if just one tab was open, by default most browser will exit entirely.:: +Finally, the browser window is closed. You can also call the `quit` method instead +of `close`. The `quit` method will exit the browser whereas `close` will close one +tab, but if just one tab was open, by default most browsers will exit entirely.:: driver.close() @@ -104,7 +104,7 @@ Python's unittest module. The other options for a tool/framework are `pytest `_. In this chapter, we use `unittest` as the framework of choice. Here is the -modified example which uses unittest module. This is a test for `python.org` +modified example which uses the unittest module. This is a test for the `python.org` search functionality:: import unittest @@ -149,7 +149,7 @@ Note: To run the above test in IPython or Jupyter, you should pass a couple of arguments to the `main` function as shown below:: unittest.main(argv=['first-arg-is-ignored'], exit=False) - + Walkthrough of the example @@ -157,9 +157,9 @@ Walkthrough of the example Initially, all the basic modules required are imported. The `unittest `_ module is a built-in Python -based on Java's JUnit. This module provides the framework for organizing the +module based on Java's JUnit. This module provides the framework for organizing the test cases. The `selenium.webdriver` module provides all the WebDriver -implementations. Currently supported WebDriver implementations are Firefox, +implementations. Currently supported WebDriver implementations are: Firefox, Chrome, IE and Remote. The `Keys` class provides keys in the keyboard like RETURN, F1, ALT etc. The `By` class is used to locate elements within a document. @@ -171,14 +171,14 @@ RETURN, F1, ALT etc. The `By` class is used to locate elements within a document from selenium.webdriver.common.by import By The test case class is inherited from `unittest.TestCase`. Inheriting from -`TestCase` class is the way to tell `unittest` module that this is a test case:: +the `TestCase` class is the way to tell `unittest` module that this is a test case:: class PythonOrgSearch(unittest.TestCase): -The `setUp` is part of initialization, this method will get called before every +The `setUp` method is part of initialization. This method will get called before every test function which you are going to write in this test case class. Here you -are creating the instance of Firefox WebDriver. +are creating an instance of a Firefox WebDriver. :: @@ -186,7 +186,7 @@ are creating the instance of Firefox WebDriver. self.driver = webdriver.Firefox() This is the test case method. The test case method should always start with -characters `test`. The first line inside this method create a local reference +characters `test`. The first line inside this method creates a local reference to the driver object created in `setUp` method. :: @@ -202,7 +202,7 @@ completely loaded*:: driver.get("http://www.python.org") -The next line is an assertion to confirm that title has "Python" word in it:: +The next line is an assertion to confirm that title has the word "Python" in it:: self.assertIn("Python", driver.title) @@ -216,7 +216,7 @@ chapter:: elem = driver.find_element(By.NAME, "q") Next, we are sending keys, this is similar to entering keys using your keyboard. -Special keys can be send using `Keys` class imported from +Special keys can be sent using the `Keys` class imported from `selenium.webdriver.common.keys`:: elem.send_keys("pycon") @@ -229,9 +229,9 @@ is any. To ensure that some results are found, make an assertion:: The `tearDown` method will get called after every test method. This is a place to do all cleanup actions. In the current method, the browser window is closed. -You can also call `quit` method instead of `close`. The `quit` will exit the +You can also call the `quit` method instead of `close`. The `quit` method will exit the entire browser, whereas `close` will close a tab, but if it is the only tab -opened, by default most browser will exit entirely.:: +opened, by default most browsers will exit entirely.:: def tearDown(self): self.driver.close() @@ -246,7 +246,7 @@ Final lines are some boiler plate code to run the test suite:: Using Selenium with remote WebDriver ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To use the remote WebDriver, you should have Selenium server running. To run +To use the remote WebDriver, you should have the Selenium server running. To run the server, use this command:: java -jar selenium-server-standalone-2.x.x.jar @@ -255,7 +255,7 @@ While running the Selenium server, you could see a message looking like this:: 15:43:07.541 INFO - RemoteWebDriver instances should connect to: http://127.0.0.1:4444/wd/hub -The above line says that you can use this URL for connecting to remote +The above line says that you can use this URL for connecting to the remote WebDriver. Here are some examples:: from selenium import webdriver @@ -273,7 +273,7 @@ WebDriver. Here are some examples:: command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities=DesiredCapabilities.HTMLUNITWITHJS) -The desired capabilities is a dictionary, so instead of using the default +The desired capabilities is a dictionary. So instead of using the default dictionaries, you can specify the values explicitly:: driver = webdriver.Remote( From eda1ecca79be3c1a88138cc7f942a554dcf40093 Mon Sep 17 00:00:00 2001 From: amosctlee <51038877+amosctlee@users.noreply.github.com> Date: Mon, 26 Sep 2022 02:58:40 +0800 Subject: [PATCH 38/52] Update: 2.5 Using Selenium with remote WebDriver (#108) The desired_capabilities has been deprecated. Use Options instead of DesiredCapabilities. --- source/getting-started.rst | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index a9a38b7..0c345f5 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -259,25 +259,13 @@ The above line says that you can use this URL for connecting to the remote WebDriver. Here are some examples:: from selenium import webdriver - from selenium.webdriver.common.desired_capabilities import DesiredCapabilities driver = webdriver.Remote( command_executor='http://127.0.0.1:4444/wd/hub', - desired_capabilities=DesiredCapabilities.CHROME) + options=webdriver.ChromeOptions() + ) driver = webdriver.Remote( command_executor='http://127.0.0.1:4444/wd/hub', - desired_capabilities=DesiredCapabilities.OPERA) - - driver = webdriver.Remote( - command_executor='http://127.0.0.1:4444/wd/hub', - desired_capabilities=DesiredCapabilities.HTMLUNITWITHJS) - -The desired capabilities is a dictionary. So instead of using the default -dictionaries, you can specify the values explicitly:: - - driver = webdriver.Remote( - command_executor='http://127.0.0.1:4444/wd/hub', - desired_capabilities={'browserName': 'htmlunit', - 'version': '2', - 'javascriptEnabled': True}) + options=webdriver.FirefoxOptions() + ) From 0e64cdf5d3954416247f9b12d9faa8669a8ba812 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Fri, 11 Nov 2022 10:00:09 +0530 Subject: [PATCH 39/52] updated the import statement (#109) --- source/waits.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/waits.rst b/source/waits.rst index fc00b1e..1e0c50f 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -31,7 +31,7 @@ is one way this can be accomplished. from selenium import webdriver from selenium.webdriver.common.by import By - from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Firefox() From 57f644a169891b4c89cc4926e1f34848a64e3c82 Mon Sep 17 00:00:00 2001 From: Pavel Lobashov Date: Wed, 7 Dec 2022 09:07:15 +0200 Subject: [PATCH 40/52] Fix incorrect quotes in cookies example (#110) --- source/navigating.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/navigating.rst b/source/navigating.rst index e744218..2ef2597 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -226,7 +226,7 @@ that the cookie will be valid for: driver.get("http://www.example.com") # Now set the cookie. This one's valid for the entire domain - cookie = {‘name’ : ‘foo’, ‘value’ : ‘bar’} + cookie = {'name' : 'foo', 'value' : 'bar'} driver.add_cookie(cookie) # And now output all the available cookies for the current URL From 1d97c3efbb1c48965e4851f2eaa1004039da04d1 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 14 Dec 2022 10:26:04 +0530 Subject: [PATCH 41/52] Update link Signed-off-by: Baiju Muthukadan --- source/faq.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/faq.rst b/source/faq.rst index 9de4370..529b1f6 100644 --- a/source/faq.rst +++ b/source/faq.rst @@ -9,10 +9,10 @@ How to use ChromeDriver ? ~~~~~~~~~~~~~~~~~~~~~~~~~ Download the latest `chromedriver from download page -`_. Unzip the +`_. Unzip the file:: - unzip chromedriver_linux32_x.x.x.x.zip + unzip chromedriver_linux64.zip You should see a ``chromedriver`` executable. Now you can create an instance of Chrome WebDriver like this:: From 656a8b2432b2ada183c64577c5c0f5a78ee4b0ff Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 14 Dec 2022 10:46:49 +0530 Subject: [PATCH 42/52] Use new API Signed-off-by: Baiju Muthukadan --- source/navigating.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/navigating.rst b/source/navigating.rst index 2ef2597..4bf3a0c 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -144,9 +144,9 @@ Moving between windows and frames It's rare for a modern web application not to have any frames or to be constrained to a single window. WebDriver supports moving between named windows -using the "switch_to_window" method:: +using the "switch_to.window" method:: - driver.switch_to_window("windowName") + driver.switch_to.window("windowName") All calls to ``driver`` will now be interpreted as being directed to the particular window. But how do you know the window's name? Take a look at the @@ -154,20 +154,20 @@ javascript or link that opened it:: Click here to open a new window -Alternatively, you can pass a "window handle" to the "switch_to_window()" +Alternatively, you can pass a "window handle" to the "switch_to.window()" method. Knowing this, it's possible to iterate over every open window like so:: for handle in driver.window_handles: - driver.switch_to_window(handle) + driver.switch_to.window(handle) You can also swing from frame to frame (or into iframes):: - driver.switch_to_frame("frameName") + driver.switch_to.frame("frameName") It's possible to access subframes by separating the path with a dot, and you can specify the frame by its index too. That is:: - driver.switch_to_frame("frameName.0.child") + driver.switch_to.frame("frameName.0.child") would go to the frame named "child" of the first subframe of the frame called "frameName". **All frames are evaluated as if from *top*.** From af911bbdffbf9db15f8ae4d6c63d8ea8cead1e7a Mon Sep 17 00:00:00 2001 From: hitrust Date: Sun, 21 May 2023 22:34:52 +0800 Subject: [PATCH 43/52] Update navigating.rst (#111) --- source/navigating.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/navigating.rst b/source/navigating.rst index 4bf3a0c..9da1e0e 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -115,7 +115,7 @@ Once you've finished filling out the form, you probably want to submit it. One way to do this would be to find the "submit" button and click it:: # Assume the button has the ID "submit" :) - driver.find_element_by_id("submit").click() + driver.find_element(By.ID, "submit").click() Alternatively, WebDriver has the convenience method "submit" on every element. If you call this on an element within a form, WebDriver will walk up the DOM From c001ee278de0847479ae3e554b29da32bb7715c6 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Sun, 21 May 2023 20:07:50 +0530 Subject: [PATCH 44/52] Update the contributor count Signed-off-by: Baiju Muthukadan --- README.rst | 2 +- source/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 1710b67..54d9a43 100644 --- a/README.rst +++ b/README.rst @@ -8,7 +8,7 @@ NOTE: THIS IS NOT OFFICIAL DOCUMENTATION This is not official documentation. If you would like to contribute to this documentation, you can `fork this project in GitHub and send pull requests `_. You can also send your feedback -to my email: baiju.m.mail AT gmail DOT com. So far 50+ community members have +to my email: baiju.m.mail AT gmail DOT com. So far 60+ community members have contributed to this project (See the 'Closed' pull requests). I encourage contributors to add more sections to make this documentation even more awesome! If you know any translations of this document, or would like to create new translations, diff --git a/source/index.rst b/source/index.rst index 7d51db0..8507a6e 100644 --- a/source/index.rst +++ b/source/index.rst @@ -11,7 +11,7 @@ Selenium with Python This is not an official documentation. If you would like to contribute to this documentation, you can `fork this project in GitHub and send pull requests `_. You can also send - your feedback to my email: baiju.m.mail AT gmail DOT com. So far 50+ + your feedback to my email: baiju.m.mail AT gmail DOT com. So far 60+ community members have contributed to this project (See the closed pull requests). I encourage contributors to add more sections and make it an awesome documentation! If you know any translation of this document, please From e6762702f74845a5484b8e21c0c8a3027ce096c7 Mon Sep 17 00:00:00 2001 From: Max Zhenzhera <59729293+maxzhenzhera@users.noreply.github.com> Date: Sat, 30 Sep 2023 05:12:18 +0300 Subject: [PATCH 45/52] Update installation Drivers with Selenium Manager and small fixes in API (#112) * fix: correct link to selemium webdriver docs * feat: add info about selenium manager * fix: remove auto doc for modules that do no longer exist * feat: update selenium.webdriver imports --- source/api.rst | 72 +++++++++++------------------------------ source/installation.rst | 22 ++++++++++++- 2 files changed, 40 insertions(+), 54 deletions(-) diff --git a/source/api.rst b/source/api.rst index 8e91d06..1118aed 100644 --- a/source/api.rst +++ b/source/api.rst @@ -23,16 +23,32 @@ Then, you can access the classes like this:: webdriver.Firefox webdriver.FirefoxProfile + webdriver.FirefoxOptions + webdriver.FirefoxService webdriver.Chrome webdriver.ChromeOptions + webdriver.ChromeService webdriver.Ie - webdriver.Opera - webdriver.PhantomJS + webdriver.IeOptions + webdriver.IeService + webdriver.Edge + webdriver.ChromiumEdge + webdriver.EdgeOptions + webdriver.EdgeService + webdriver.Safari + webdriver.SafariOptions + webdriver.SafariService + webdriver.WebKitGTK + webdriver.WebKitGTKOptions + webdriver.WebKitGTKService + webdriver.WPEWebKit + webdriver.WPEWebKitOptions + webdriver.WPEWebKitService webdriver.Remote webdriver.DesiredCapabilities webdriver.ActionChains - webdriver.TouchActions webdriver.Proxy + webdriver.Keys The special keys class (``Keys``) can be imported like this:: @@ -139,16 +155,6 @@ See the :ref:`selenium-remote-webdriver` section for example usages of desired c :member-order: groupwise :show-inheritance: -Touch Actions -~~~~~~~~~~~~~ - -.. automodule:: selenium.webdriver.common.touch_actions - :members: - :undoc-members: - :special-members: __init__ - :member-order: groupwise - :show-inheritance: - Proxy ~~~~~ @@ -353,46 +359,6 @@ Internet Explorer WebDriver :member-order: groupwise :show-inheritance: -Android WebDriver -~~~~~~~~~~~~~~~~~ - -.. automodule:: selenium.webdriver.android.webdriver - :members: - :undoc-members: - :special-members: __init__ - :member-order: groupwise - :show-inheritance: - -Opera WebDriver -~~~~~~~~~~~~~~~ - -.. automodule:: selenium.webdriver.opera.webdriver - :members: - :undoc-members: - :special-members: __init__ - :member-order: groupwise - :show-inheritance: - -PhantomJS WebDriver -~~~~~~~~~~~~~~~~~~~ - -.. automodule:: selenium.webdriver.phantomjs.webdriver - :members: - :undoc-members: - :special-members: __init__ - :member-order: groupwise - :show-inheritance: - -PhantomJS WebDriver Service -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. automodule:: selenium.webdriver.phantomjs.service - :members: - :undoc-members: - :special-members: __init__ - :member-order: groupwise - :show-inheritance: - Safari WebDriver ~~~~~~~~~~~~~~~~ diff --git a/source/installation.rst b/source/installation.rst index a998151..343bff3 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -111,8 +111,28 @@ the more popular browser drivers follow. For more information about driver installation, please refer the `official documentation -`_. +`_. +Starting from version ``4.6.0`` (November 4, 2022) +selenium comes with **Selenium Manager** packed in distribution. + +**Selenium Manager** is a new tool that helps to get a working environment +to run **Selenium** out of the box: + +* automatically discovers, downloads, and caches the ``drivers`` + required by Selenium when these ``drivers`` are unavailable; +* automatically discovers, downloads, and caches the ``browsers`` + driven with Selenium (Chrome, Firefox, and Edge) + when these ``browsers`` are not installed in the local system. + +For example, to see the result of **Selenium Manager** work +just run any selenium script without previous driver setup +and explore `~/.cache/selenium`. + +More about **Selenium Manager** you can read in the +`documentation `_ +and +`blog `_. Downloading Selenium server ~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 9a0c8e3254bc9dbe9591d61da763a6c68104acac Mon Sep 17 00:00:00 2001 From: Carmen Alvarez Date: Thu, 16 Nov 2023 13:47:23 +0100 Subject: [PATCH 46/52] Update the page objects documentation to use the newer syntax for finding elements by name. (#113) This follows-up the changes done in https://github.com/baijum/selenium-python/pull/99 (commit 3b13c2f8f864c2b4a56fb5dddebab0cd86817ad6 ) --- source/page-objects.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index 1a59df7..e628ad7 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -118,6 +118,7 @@ Page elements The ``element.py`` will look like this:: + from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait @@ -129,17 +130,17 @@ The ``element.py`` will look like this:: driver = obj.driver WebDriverWait(driver, 100).until( - lambda driver: driver.find_element_by_name(self.locator)) - driver.find_element_by_name(self.locator).clear() - driver.find_element_by_name(self.locator).send_keys(value) + lambda driver: driver.find_element(By.NAME, self.locator)) + driver.find_element(By.NAME, self.locator).clear() + driver.find_element(By.NAME, self.locator).send_keys(value) def __get__(self, obj, owner): """Gets the text of the specified object""" driver = obj.driver WebDriverWait(driver, 100).until( - lambda driver: driver.find_element_by_name(self.locator)) - element = driver.find_element_by_name(self.locator) + lambda driver: driver.find_element(By.NAME, self.locator)) + element = driver.find_element(By.NAME, self.locator) return element.get_attribute("value") From 21f2a3a2fd8979296c0b9aee987facc1de4c3793 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 16 Nov 2023 18:24:45 +0530 Subject: [PATCH 47/52] Add build section --- .readthedocs.yaml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 6cd6e72..ef1e03e 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -5,16 +5,23 @@ # Required version: 2 +# Set the version of Python +build: + os: ubuntu-20.04 + tools: + python: "3.10" + +# Optionally set the version of Python and requirements required to build your docs +python: + version: "3.10" + install: + - requirements: requirements.txt + # Build documentation in the docs/ directory with Sphinx sphinx: configuration: source/conf.py + fail_on_warning: true # Optionally build your docs in additional formats such as PDF formats: - pdf - -# Optionally set the version of Python and requirements required to build your docs -python: - version: 3.7 - install: - - requirements: requirements.txt From 7cf91983545f55bfdc45836257bcad56c597527f Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 16 Nov 2023 18:26:33 +0530 Subject: [PATCH 48/52] Remove version from python section --- .readthedocs.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index ef1e03e..c7bb87b 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -13,7 +13,6 @@ build: # Optionally set the version of Python and requirements required to build your docs python: - version: "3.10" install: - requirements: requirements.txt From 74454219563f5b6ca6e11da66e4382e0b525eb5b Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 16 Nov 2023 18:34:26 +0530 Subject: [PATCH 49/52] Do not fail on warning --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index c7bb87b..f8d496e 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -19,7 +19,7 @@ python: # Build documentation in the docs/ directory with Sphinx sphinx: configuration: source/conf.py - fail_on_warning: true + fail_on_warning: false # Optionally build your docs in additional formats such as PDF formats: From 370686950585ba65898e585064c68e5c00b2c7fd Mon Sep 17 00:00:00 2001 From: devid Date: Tue, 5 Mar 2024 05:05:43 -0300 Subject: [PATCH 50/52] Updated the variable name to a python non-reserved word. (#115) --- source/locating-elements.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/locating-elements.rst b/source/locating-elements.rst index 8d0ebb1..7bc499e 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -101,7 +101,7 @@ The username & password elements can be located like this:: This will give the "Login" button as it occurs before the "Clear" button:: - continue = driver.find_element(By.NAME, 'continue') + continue_button = driver.find_element(By.NAME, 'continue') Locating by XPath From 81ca746c74b2eab8e04416b83935e28221cb7805 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 5 Apr 2024 13:08:35 +0530 Subject: [PATCH 51/52] Remove the nose testing tool Signed-off-by: Baiju Muthukadan --- source/getting-started.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 0c345f5..8c71e49 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -99,9 +99,8 @@ Using Selenium to write tests Selenium is mostly used for writing test cases. The `selenium` package itself doesn't provide a testing tool/framework. You can write test cases using -Python's unittest module. The other options for a tool/framework are `pytest -`_ and `nose -`_. +Python's unittest module. Alternatively, you may consider `pytest +`_ for writing tests. In this chapter, we use `unittest` as the framework of choice. Here is the modified example which uses the unittest module. This is a test for the `python.org` From d1b9190381c789fb9db8842084bf10bc857dd971 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 5 Apr 2024 13:12:47 +0530 Subject: [PATCH 52/52] Update year Signed-off-by: Baiju Muthukadan --- source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/conf.py b/source/conf.py index 1829d9f..3af276f 100644 --- a/source/conf.py +++ b/source/conf.py @@ -41,7 +41,7 @@ # General information about the project. project = u'Selenium Python Bindings' -copyright = u'2011-2018, Baiju Muthukadan' +copyright = u'2011-2024, Baiju Muthukadan' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the