From b6c956af161a8208252b4538f59bee2cd8f6762c Mon Sep 17 00:00:00 2001 From: sourabhpataskar Date: Tue, 18 Mar 2014 15:10:39 +0530 Subject: [PATCH 001/147] Updated given code Removed self.assertIn("Google", driver.title) from given code because when we search for "selenium" keyword in http://www.python.org it is not getting redirected to Google.com. So given example is failing because of "self.assertIn("Python", driver.title)" --- source/getting-started.rst | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index b60e2bb..a9b874f 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -20,7 +20,6 @@ from Python like this. elem = driver.find_element_by_name("q") elem.send_keys("selenium") elem.send_keys(Keys.RETURN) - assert "Google" in driver.title driver.close() The above script can be saved into a file (eg:- @@ -78,10 +77,7 @@ keyboard. Special keys can be send using `Keys` class imported from elem.send_keys("selenium") elem.send_keys(Keys.RETURN) -After submission of the page, you should be reached in the Google -site:: - - assert "Google" in driver.title +After submission of the page, you should get the resulf if there is any:: Finally, the browser window is closed. You can also call `quit` method instead of `close`. The `quit` will exit entire browser where @@ -119,7 +115,6 @@ for `python.org` search functionality:: elem = driver.find_element_by_name("q") elem.send_keys("selenium") elem.send_keys(Keys.RETURN) - self.assertIn("Google", driver.title) def tearDown(self): self.driver.close() @@ -215,10 +210,8 @@ keyboard. Special keys can be send using `Keys` class imported from elem.send_keys("selenium") elem.send_keys(Keys.RETURN) -After submission of the page, you should be reached in the Google -site. You can confirm it by asserting "Google" in the title:: - - self.assertIn("Google", driver.title) +After submission of the page, you should get result as per search if +there is any. The `tearDown` method will get called after every test method. This is a place to do all cleanup actions. In the current method, the From 766f7bb6f7592f8dc7c455e1368f6b69728b8138 Mon Sep 17 00:00:00 2001 From: sourabhpataskar Date: Tue, 18 Mar 2014 15:16:20 +0530 Subject: [PATCH 002/147] Update getting-started.rst --- source/getting-started.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index a9b874f..3b0ef05 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -77,7 +77,7 @@ keyboard. Special keys can be send using `Keys` class imported from elem.send_keys("selenium") elem.send_keys(Keys.RETURN) -After submission of the page, you should get the resulf if there is any:: +After submission of the page, you should get the result if there is any:: Finally, the browser window is closed. You can also call `quit` method instead of `close`. The `quit` will exit entire browser where From 525f8e85fd79f29e211b0f87cf9b073685157d4a Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 19 Mar 2014 17:44:12 +0530 Subject: [PATCH 003/147] use Python 3 --- source/installation.rst | 63 +++++++++++++---------------------------- 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/source/installation.rst b/source/installation.rst index 3a96769..3bf9e92 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.6, 2.7, 3.2 and 3.3. +Python versions are 2.7, 3.2, 3.3 and 3.4. This documentation explains Selenium 2 WebDriver API. Selenium 1 / Selenium RC API is not covered here. @@ -23,19 +23,19 @@ Downloading Python bindings for Selenium ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can download Python bindings for Selenium from the `PyPI page for -selenium package `_. You can -also use `easy_install -`_ or `pip -`_ to install the bindings:: - - easy_install selenium - -or:: +selenium package `_. However, +a better approach would be to use +`pip `_ to +install the selenium package. Python 3.4 has pip available in the +`standard library `_. +Once you have pip installed, you can install selenium like this:: pip install selenium You may consider using `virtualenv `_ -to create isolated Python environments. +to create isolated Python environments. Python 3.4 has `pyvenv +`_ +which is almost same as virtualenv. Detailed instructions for Windows users @@ -45,46 +45,21 @@ Detailed instructions for Windows users You should have internet connection to perform this installation. -1. Install Python 2.7 using the `MSI available in python.org download +1. Install Python 3.4 using the `MSI available in python.org download page `_. -2. Create a folder named ``C:\seltests`` - -3. Download `virtualenv - `_ - tar ball inside ``C:\seltests`` and extract it. Ensure the tar bal has been extracted - to ``C:\seltests\virtualenv-1.10.1`` folder (To extract you can use WinZip or 7-zip) - -4. Start a command prompt (using the ``cmd.exe`` program), then change - to the ``C:\seltests\virtualenv-1.10.1`` folder and run the ``virtualenv.py`` script - as given below. +2. Start a command prompt using the ``cmd.exe`` program and run the + ``pip`` command as given below to install `selenium`. :: + + C:\Python34\Scripts\pip.exe install selenium - C: - cd C:\seltests\virtualenv-1.10.1 - C:\Python27\python.exe virtualenv.py C:\seltests\selenv - - - This step will create a folder named ``C:\seltests\selenv`` which - contains a virtual Python. - -5. Use the ``pip`` command as given below to install `selenium` - - :: - - C:\seltests\selenv\Scripts\pip.exe install selenium - - Now installation has been completed! You can proceed to test your - Selenium scripts. - -Now you can run your test scripts using the virtual Python. For -example, if you have created a Selenium based script and saved it inside -``C:\seltests\my_selenium_script.py``, you can run it like this. - -:: +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:\seltests\selenv\Scripts\python.exe C:\seltests\my_selenium_script.py + C:\Python34\python.exe C:\my_selenium_script.py Downloading Selenium server From 5eda577daf86122c638cd1a1f1f99a4a35a9f56a Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 19 Mar 2014 18:00:36 +0530 Subject: [PATCH 004/147] Create setup.py --- setup.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 setup.py diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..35b84b5 --- /dev/null +++ b/setup.py @@ -0,0 +1,14 @@ +from setuptools import setup, find_packages + +setup(name="selenium-python-docs", + version="0.0.0", + description="", + packages=find_packages(), + include_package_data=True, + zip_safe=False, + author='Baiju Muthukadan', + install_requires=['setuptools', + 'selenium', + 'Sphinx', + ], + ) From 509695946c5b275400f8e60ac8e8bf48e9b33710 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 19 Mar 2014 18:03:43 +0530 Subject: [PATCH 005/147] better sentence --- source/installation.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/installation.rst b/source/installation.rst index 3bf9e92..e60964b 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -12,7 +12,7 @@ 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 +WebDrivers like Firefox, Ie, Chrome, Remote etc. The current supported Python versions are 2.7, 3.2, 3.3 and 3.4. This documentation explains Selenium 2 WebDriver API. Selenium @@ -28,7 +28,7 @@ a better approach would be to use `pip `_ to install the selenium package. Python 3.4 has pip available in the `standard library `_. -Once you have pip installed, you can install selenium like this:: +Using `pip`, you can install selenium like this:: pip install selenium From 370a73ad6992e9724f0b5f1dea79529de939b76a Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 19 Mar 2014 18:11:24 +0530 Subject: [PATCH 006/147] Python 2.7 is given as the minimum version --- source/getting-started.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 3b0ef05..753b3d0 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -191,9 +191,6 @@ in it:: self.assertIn("Python", driver.title) -.. note:: - - The `assertIn` API is only available in Python 2.7 and above. WebDriver offers a number of ways to find elements using one of the `find_element_by_*` methods. For example, the input text element can From 5cdc42cb37852d3c8a887250f043bd48862bbf30 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 19 Mar 2014 18:14:04 +0530 Subject: [PATCH 007/147] use 'driver' consistently --- source/waits.rst | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/source/waits.rst b/source/waits.rst index e5d9920..92c2f8d 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -37,12 +37,12 @@ accomplished. from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0 from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0 - ff = webdriver.Firefox() - ff.get("http://somedomain/url_that_delays_loading") + driver = webdriver.Firefox() + driver.get("http://somedomain/url_that_delays_loading") try: - element = WebDriverWait(ff, 10).until(EC.presence_of_element_located((By.ID, "myDynamicElement"))) + element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "myDynamicElement"))) finally: - ff.quit() + driver.quit() This waits up to 10 seconds before throwing a TimeoutException or if @@ -101,9 +101,7 @@ implicit wait is set for the life of the WebDriver object instance. from selenium import webdriver - ff = webdriver.Firefox() - ff.implicitly_wait(10) # seconds - ff.get("http://somedomain/url_that_delays_loading") - myDynamicElement = ff.find_element_by_id("myDynamicElement") - - + driver = webdriver.Firefox() + driver.implicitly_wait(10) # seconds + driver.get("http://somedomain/url_that_delays_loading") + myDynamicElement = driver.find_element_by_id("myDynamicElement") From 3ae4e4a4ee93f7366b24b82fec48b46d3127d6cb Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 19 Mar 2014 18:18:33 +0530 Subject: [PATCH 008/147] update year --- source/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/conf.py b/source/conf.py index 2d52c05..253f3fd 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-2013, Baiju Muthukadan' +copyright = u'2011-2014, 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 @@ -222,7 +222,7 @@ epub_title = u'Selenium Python Bindings' epub_author = u'Baiju Muthukadan' epub_publisher = u'Baiju Muthukadan' -epub_copyright = u'2010-2011, Baiju Muthukadan' +epub_copyright = u'2011-2014, Baiju Muthukadan' # The language of the text. It defaults to the language option # or en if the language is not set. From cc98625b83bcad77e665620be8aa82370fade3e9 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 20 Mar 2014 19:51:43 +0530 Subject: [PATCH 009/147] Locating Elements by Tag Name --- source/locating-elements.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/source/locating-elements.rst b/source/locating-elements.rst index 4baec26..afb654a 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -208,3 +208,26 @@ 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') + +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 give tag name will be returned. +If no element has a matching tag name, a ``NoSuchElementException`` +will be raised. + +For instance, conside this page source:: + + + +

Welcome

+

Site content goes here.

+ + + +The heading (h1) element can be located like this:: + + heading1 = driver.find_element_by_tag_name('h1') + + From 5b740122e8abd0697221f341c73c45e060c7aadc Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 20 Mar 2014 19:56:44 +0530 Subject: [PATCH 010/147] Locating Elements by Class Name --- source/locating-elements.rst | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/source/locating-elements.rst b/source/locating-elements.rst index afb654a..5f71a2f 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -193,7 +193,7 @@ strategy, the first element with the link text value matching the location will be returned. If no element has a matching link text attribute, a ``NoSuchElementException`` will be raised. -For instance, conside this page source:: +For instance, consider this page source:: @@ -230,4 +230,23 @@ The heading (h1) element can be located like this:: heading1 = driver.find_element_by_tag_name('h1') - + +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, +a ``NoSuchElementException`` will be raised. + +For instance, consider this page source:: + + + +

Site content goes here.

+ + + +The "p" element can be located like this:: + + content = driver.find_element_by_class_name('content') From 5ae959584173ae5ac592dbebfd9894a518dd16eb Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 20 Mar 2014 20:11:42 +0530 Subject: [PATCH 011/147] Locating Elements by CSS selectors --- source/locating-elements.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/source/locating-elements.rst b/source/locating-elements.rst index 5f71a2f..c8bbfa5 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -250,3 +250,26 @@ For instance, consider this page source:: The "p" element can be located like this:: content = driver.find_element_by_class_name('content') + +Locating Elements by CSS Selectors +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use this when you want to locate an element by CSS selector syntaxt. +With this strategy, the first element with the matching CSS selector +will be returned. If no element has a matching CSS selector, +a ``NoSuchElementException`` will be raised. + +For instance, consider this page source:: + + + +

Site content goes here.

+ + + +The "p" element can be located like this:: + + content = driver.find_element_by_css_selector('p.content') + +`SouceLabs has a good documentation `_ +on CSS selectors. From ada16b388b17a9304a81ccfecc221928941b929f Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 20 Mar 2014 20:16:01 +0530 Subject: [PATCH 012/147] beginners can skip section --- source/installation.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/installation.rst b/source/installation.rst index e60964b..586e896 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -69,7 +69,8 @@ Downloading Selenium server The Selenium server is only required, if you want to use the remote WebDriver. See the :ref:`selenium-remote-webdriver` section for - more details. + 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. From 3c65a4d5d4587b37ee42ad870a4eb9c1a4aef191 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 20 Mar 2014 20:19:12 +0530 Subject: [PATCH 013/147] indentation fix --- source/navigating.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/navigating.rst b/source/navigating.rst index 0f7ed28..5b6948c 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -110,7 +110,7 @@ This will deselect all OPTIONs from the first 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("xpath")) + select = Select(driver.find_element_by_xpath("xpath")) all_selected_options = select.all_selected_options To get all available options:: From d09c778a69ac9366cd2363beae2e469854c5ea26 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 30 Mar 2014 10:34:47 -0700 Subject: [PATCH 014/147] Update faq.rst Fixed some typos --- source/faq.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/faq.rst b/source/faq.rst index 25cefc2..a9cf0a2 100644 --- a/source/faq.rst +++ b/source/faq.rst @@ -19,15 +19,14 @@ Chrome WebDriver like this:: driver = webdriver.Chrome(executable_path="/path/to/chromedriver") -The rest of the example should work as given in other other -documentation. +The rest of the example should work as given in other documentation. Does Selenium 2 supports XPath 2.0 ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Ref: http://seleniumhq.org/docs/03_webdriver.html#how-xpath-works-in-webdriver -Selenium delegate XPath queries down to the browser's own XPath +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. From 168ef7737a9ec2c01036f69f1a4738e5e4f54ea7 Mon Sep 17 00:00:00 2001 From: Michael Redman Date: Thu, 3 Apr 2014 12:41:07 -0700 Subject: [PATCH 015/147] Update locating-elements.rst changed SouceLabs has a good documentation to Sauce Labs has good documentation --- 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 c8bbfa5..a7545a9 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -271,5 +271,5 @@ The "p" element can be located like this:: content = driver.find_element_by_css_selector('p.content') -`SouceLabs has a good documentation `_ +`Sauce Labs has good documentation `_ on CSS selectors. From ca44705f04fc603d8aba227567e73b0b3485ab6f Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 4 Apr 2014 22:22:05 +0530 Subject: [PATCH 016/147] use print function --- source/faq.rst | 3 ++- source/navigating.rst | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/faq.rst b/source/faq.rst index 25cefc2..823d118 100644 --- a/source/faq.rst +++ b/source/faq.rst @@ -71,7 +71,8 @@ Another way to find content type is using the `requests `_ module, you can use it like this:: import requests - print requests.head('http://www.python.org').headers['content-type'] + 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`` diff --git a/source/navigating.rst b/source/navigating.rst index 5b6948c..54a2cec 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -80,7 +80,7 @@ drop down, and you can use "setSelected" to set something like an 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") + print("Value is: %s" % option.get_attribute("value")) option.click() This will find the first "SELECT" element on the page, and cycle @@ -241,4 +241,4 @@ domain that the cookie will be valid for: # And now output all the available cookies for the current URL all_cookies = driver.get_cookies() for cookie_name, cookie_value in all_cookies.items(): - print "%s -> %s", cookie_name, cookie_value + print("%s -> %s", cookie_name, cookie_value) From f9a081317d0029da8fdcfb231479c3d43606c73c Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 4 Apr 2014 22:43:31 +0530 Subject: [PATCH 017/147] typo --- source/waits.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/waits.rst b/source/waits.rst index 92c2f8d..f92a6a7 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -12,11 +12,11 @@ this issue. Waiting provides some time interval between actions performed - mostly locating element or any other operation with the element. -Selenium webdriver two types of waits - implicit & explicit. An -explicit wait makes WebDriver to wait for a certain condition to occur -before proceeding further with executions. An implicit wait makes -WebDriver to poll the DOM for a certain amount of time when trying to -locate an element. +Selenium Webdriver provides two types of waits - implicit & explicit. +An explicit wait makes WebDriver to wait for a certain condition to +occur before proceeding further with executions. An implicit wait +makes WebDriver to poll the DOM for a certain amount of time when +trying to locate an element. Explicit Waits From babd1b1b13469f26d88ec0d22a63cde4047efd8f Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 4 Apr 2014 22:46:11 +0530 Subject: [PATCH 018/147] 80 char max per line for code (better for PDF) --- source/waits.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/waits.rst b/source/waits.rst index f92a6a7..2031d64 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -34,13 +34,15 @@ accomplished. from selenium import webdriver from selenium.webdriver.common.by import By - from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0 - from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0 + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Firefox() driver.get("http://somedomain/url_that_delays_loading") try: - element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "myDynamicElement"))) + element = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.ID, "myDynamicElement")) + ) finally: driver.quit() From 1a7ec55d9d19fe6ac0cb2c15be3676645f43f40a Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 4 Apr 2014 22:55:18 +0530 Subject: [PATCH 019/147] copyright notice --- source/index.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/index.rst b/source/index.rst index a66bb22..7dbc74e 100644 --- a/source/index.rst +++ b/source/index.rst @@ -3,6 +3,8 @@ Selenium with Python ******************** :Author: `Baiju Muthukadan `_ +:License: This document is licensed under a `Creative Commons Attribution-ShareAlike 4.0 International License +`_. .. note:: From 93a5442528d9d88a88f88f0afd5f58c90dfa7a60 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 4 Apr 2014 23:08:12 +0530 Subject: [PATCH 020/147] break URL --- source/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/index.rst b/source/index.rst index 7dbc74e..4faf575 100644 --- a/source/index.rst +++ b/source/index.rst @@ -3,8 +3,8 @@ Selenium with Python ******************** :Author: `Baiju Muthukadan `_ -:License: This document is licensed under a `Creative Commons Attribution-ShareAlike 4.0 International License -`_. +:License: This document is licensed under a + `Creative Commons Attribution-ShareAlike 4.0 International License `_. .. note:: From 7916119c9c649f38a5eb10b60becb714ec72e958 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 6 Apr 2014 13:14:01 -0700 Subject: [PATCH 021/147] Update faq.rst Fixed few typos, a little bit formatting --- source/faq.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/faq.rst b/source/faq.rst index a9cf0a2..386a0f0 100644 --- a/source/faq.rst +++ b/source/faq.rst @@ -1,6 +1,6 @@ .. _faq: -Appendix: Frequently asked questions +Appendix: Frequently Asked Questions ------------------------------------ Another FAQ: https://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions @@ -21,7 +21,7 @@ Chrome WebDriver like this:: The rest of the example should work as given in other documentation. -Does Selenium 2 supports XPath 2.0 ? +Does Selenium 2 support XPath 2.0 ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Ref: http://seleniumhq.org/docs/03_webdriver.html#how-xpath-works-in-webdriver @@ -57,6 +57,7 @@ How to auto save files using custom Firefox profile ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Ref: http://stackoverflow.com/questions/1176348/access-to-file-download-dialog-in-firefox + Ref: http://blog.codecentric.de/en/2010/07/file-downloads-with-selenium-mission-impossible/ The first step is to identify the type of file you want to auto save. From eb59aecb64806613392264c0cdcfe451a97193dc Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 9 Apr 2014 12:31:17 +0530 Subject: [PATCH 022/147] Update README.rst --- README.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 8011e01..11bc46d 100644 --- a/README.rst +++ b/README.rst @@ -8,4 +8,6 @@ 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 more than a dozen community members has contributed to this +project (See the closed pull requests). I encourage contributors +to add more sections and make it good documentation! From 1ab5700ca988953d70631a75f4fda379ef363ba6 Mon Sep 17 00:00:00 2001 From: Shmele Date: Wed, 9 Apr 2014 21:23:18 +0800 Subject: [PATCH 023/147] fix typo --- source/navigating.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/navigating.rst b/source/navigating.rst index 54a2cec..484cb07 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -90,9 +90,8 @@ 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 "Select", which provides useful methods for -interacting with these. +interacting with these:: -:: from selenium.webdriver.support.ui import Select select = Select(driver.find_element_by_name('name')) select.select_by_index(index) From 74c6c9086ecab3810077c614577e214207e4a764 Mon Sep 17 00:00:00 2001 From: Scorypto Date: Fri, 18 Jul 2014 14:48:34 +0530 Subject: [PATCH 024/147] Update getting-started.rst --- source/getting-started.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 753b3d0..162e233 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -195,7 +195,7 @@ in it:: 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 findind elements is available in the +method. Detailed explanation of finding elements is available in the :ref:`locating-elements` chapter:: elem = driver.find_element_by_name("q") From 64c9c8c965ff73698f75795458c7871dc04a3dec Mon Sep 17 00:00:00 2001 From: Lacy Morrow Date: Wed, 30 Jul 2014 00:06:20 -0700 Subject: [PATCH 025/147] Added FAQ: How to upload files? --- source/faq.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/faq.rst b/source/faq.rst index c031e6b..4266371 100644 --- a/source/faq.rst +++ b/source/faq.rst @@ -100,6 +100,13 @@ content type. 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. + How to use firebug with Firefox ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 5b3a12a4e91ec58b6f2f58d64a6dcafd9571f920 Mon Sep 17 00:00:00 2001 From: Deep Sukhwani Date: Sun, 14 Sep 2014 15:11:11 +0530 Subject: [PATCH 026/147] Update getting-started.rst On line 172 added "The test case method should always start with characters `test`" because I was very confused myself at first when I created a test case whose name did not start with letters 'test' and my test was not running at all. --- source/getting-started.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 162e233..b492316 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -169,7 +169,7 @@ 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 first line inside this 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. From 8406736275cb0497219a9c694d9eb695c0c5fffb Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Sat, 20 Sep 2014 15:12:12 +0530 Subject: [PATCH 027/147] expand API with more common APIs --- source/api.rst | 35 +++++++++++++++++++++++++++++++++++ source/locating-elements.rst | 26 +++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/source/api.rst b/source/api.rst index ad29c12..7e80d2a 100644 --- a/source/api.rst +++ b/source/api.rst @@ -109,6 +109,41 @@ Special Keys :show-inheritance: +Locate elements By +~~~~~~~~~~~~~~~~~~ + +These are the attributes which can be used to locate elements. See +the :ref:`locating-elements` chapter for example usages. + +.. automodule:: selenium.webdriver.common.by + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + + +Desired Capabilities +~~~~~~~~~~~~~~~~~~~~ + +See the :ref:`selenium-remote-webdriver` section for example usages of desired capabilities. + +.. automodule:: selenium.webdriver.common.desired_capabilities + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + + +Utilities +~~~~~~~~~ + +.. automodule:: selenium.webdriver.common.utils + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + + Firefox WebDriver ~~~~~~~~~~~~~~~~~ diff --git a/source/locating-elements.rst b/source/locating-elements.rst index a7545a9..37981a9 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -28,6 +28,30 @@ 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 with locators in page objects. These +are the two private methods: `find_element` and `find_elements`. + +Example usage:: + + from selenium.webdriver.common.by import By + + driver.find_element(By.XPATH, '//button[text()="Some text"]') + driver.find_elements(By.XPATH, '//button') + + +These are the attributes available for `By` class:: + + ID = "id" + XPATH = "xpath" + LINK_TEXT = "link text" + PARTIAL_LINK_TEXT = "partial link text" + NAME = "name" + TAG_NAME = "tag name" + CLASS_NAME = "class name" + CSS_SELECTOR = "css selector" + + Locating by Id ~~~~~~~~~~~~~~ @@ -270,6 +294,6 @@ For instance, consider this page source:: 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. From bc64eb9e7e628d14a32f5af02e7bc612b211235f Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Sat, 20 Sep 2014 15:26:50 +0530 Subject: [PATCH 028/147] search pycon instead of selenium --- source/getting-started.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index b492316..2686e35 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -18,7 +18,7 @@ from Python like this. driver.get("http://www.python.org") assert "Python" in driver.title elem = driver.find_element_by_name("q") - elem.send_keys("selenium") + elem.send_keys("pycon") elem.send_keys(Keys.RETURN) driver.close() @@ -74,7 +74,7 @@ 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("selenium") + elem.send_keys("pycon") elem.send_keys(Keys.RETURN) After submission of the page, you should get the result if there is any:: @@ -113,7 +113,7 @@ for `python.org` search functionality:: driver.get("http://www.python.org") self.assertIn("Python", driver.title) elem = driver.find_element_by_name("q") - elem.send_keys("selenium") + elem.send_keys("pycon") elem.send_keys(Keys.RETURN) def tearDown(self): @@ -204,7 +204,7 @@ 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("selenium") + elem.send_keys("pycon") elem.send_keys(Keys.RETURN) After submission of the page, you should get result as per search if From eb2c1be9af0b6b070faabb3a9be0d8ba13ed9bff Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Sat, 20 Sep 2014 15:43:49 +0530 Subject: [PATCH 029/147] bring back assertion --- source/getting-started.rst | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 2686e35..fe34d4d 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -20,6 +20,7 @@ from Python like this. 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 driver.close() The above script can be saved into a file (eg:- @@ -77,7 +78,10 @@ keyboard. Special keys can be send using `Keys` class imported from elem.send_keys("pycon") elem.send_keys(Keys.RETURN) -After submission of the page, you should get the result if there is any:: +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 where @@ -114,6 +118,7 @@ for `python.org` search functionality:: self.assertIn("Python", driver.title) elem = driver.find_element_by_name("q") elem.send_keys("pycon") + assert "No results found." not in driver.page_source elem.send_keys(Keys.RETURN) def tearDown(self): @@ -208,7 +213,10 @@ keyboard. Special keys can be send using `Keys` class imported from elem.send_keys(Keys.RETURN) After submission of the page, you should get result as per search if -there is any. +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 From acc5d657af9ab811094617bd3df0c04e0fbe9733 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Sat, 20 Sep 2014 16:14:47 +0530 Subject: [PATCH 030/147] page objects chapter --- source/index.rst | 1 + source/page-objects.rst | 100 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 source/page-objects.rst diff --git a/source/index.rst b/source/index.rst index 4faf575..7bb6733 100644 --- a/source/index.rst +++ b/source/index.rst @@ -20,6 +20,7 @@ Selenium with Python navigating locating-elements waits + page-objects api faq diff --git a/source/page-objects.rst b/source/page-objects.rst new file mode 100644 index 0000000..8f1ab64 --- /dev/null +++ b/source/page-objects.rst @@ -0,0 +1,100 @@ +.. _page-objects: + +Page Objects +------------ + +.. note:: + + This chaper is a work in progress, right now I don't have time to + finish it. If anyone interested, please send pull request in + `Github `_. Here is an + example implementation of the page objects pattern: + https://github.com/baijum/pitracker/tree/master/test/acceptance + +This chapter is a tutorial introduction to use page objects design +pattern. Here is a test case which searches for a word in python.org +website and ensure some results are found. + +:: + + import unittest + from selenium import webdriver + from selenium.webdriver.common.keys import Keys + import page + + class PythonOrgSearch(unittest.TestCase): + + def setUp(self): + self.driver = webdriver.Firefox() + driver.get("http://www.python.org") + + def test_search_in_python_org(self): + main_page = page.MainPage(self.driver) + assert main_page.is_title_matches(), "python.org title doesn't match." + main_page.search_text_element = "pycon" + main_page.click_go_button() + search_results_page = page.SearchResultsPage(self.driver) + assert search_results_page.is_results_found(), "No results found." + + def tearDown(self): + self.driver.close() + + if __name__ == "__main__": + unittest.main() + +The ``page.py`` will look like this:: + + from element import BasePageElement + from locators import MainPageLocators + + class SearchTextElement(BasePageElement): + + locator = 'q' + + + class MainPage(object): + + search_text_element = SearchTextElement() + + def is_title_matches(self): + pass + + def click_go_button(self): + element = self.driver.find_element(*MainPageLocators.GO_BUTTON) + element.click() + + + class SearchResultsPage(object): + + def is_results_found(self): + pass + +The ``element.py`` will look like this:: + + from selenium.webdriver.support.ui import WebDriverWait + + + class BasePageElement(object): + + def __set__(self, obj, value): + driver = obj.driver + WebDriverWait(driver, 100).until( + lambda driver: driver.find_element_by_id(self.locator)) + driver.find_element_by_id(self.locator).send_keys(value) + + def __get__(self, obj, owner): + driver = obj.driver + WebDriverWait(driver, 100).until( + lambda driver: driver.find_element_by_id(self.locator)) + element = driver.find_element_by_id(self.locator) + return element.get_attribute("value") + +The ``locators.py`` will look like this:: + + from selenium.webdriver.common.by import By + + class MainPageLocators(object): + GO_BUTTON = (By.ID, 'submit') + + class SearchResultsPageLocators(object): + pass From fcb7b2ac2ba63f8185e2cebd1ac0ccd35504538f Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Sat, 20 Sep 2014 16:23:06 +0530 Subject: [PATCH 031/147] base page --- source/page-objects.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index 8f1ab64..ea213c4 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -52,7 +52,13 @@ The ``page.py`` will look like this:: locator = 'q' - class MainPage(object): + class BasePage(object): + + def __init__(self, driver): + self.driver = driver + + + class MainPage(BasePage): search_text_element = SearchTextElement() @@ -64,7 +70,7 @@ The ``page.py`` will look like this:: element.click() - class SearchResultsPage(object): + class SearchResultsPage(BasePage): def is_results_found(self): pass From bbbdfd74122be48759244d4fe9c7bdd68f1d347e Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Sat, 20 Sep 2014 16:30:37 +0530 Subject: [PATCH 032/147] break lengthy line --- source/getting-started.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index fe34d4d..f125304 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -174,9 +174,9 @@ 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. :: From d5fc6628c83d6efc47ca7dd28d3974481c63e55a Mon Sep 17 00:00:00 2001 From: Yao Zuo Date: Tue, 14 Oct 2014 19:25:35 +0800 Subject: [PATCH 033/147] fix two typos --- source/locating-elements.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/locating-elements.rst b/source/locating-elements.rst index 37981a9..6db0186 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -60,7 +60,7 @@ 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. -For instance, conside this page source:: +For instance, consider this page source:: @@ -237,7 +237,7 @@ 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 give tag name will be returned. +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. From b6d23cd7ecd41ac79318966b4fcfd9d885ef53f8 Mon Sep 17 00:00:00 2001 From: brunogabuzomeu Date: Fri, 17 Oct 2014 11:07:38 +0200 Subject: [PATCH 034/147] Cookies mechanism changed --- source/navigating.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source/navigating.rst b/source/navigating.rst index 484cb07..b3660c0 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -234,10 +234,9 @@ domain 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 = {"key": "value"}) + cookie = {‘name’ : ‘foo’, ‘value’ : ‘bar’} driver.add_cookie(cookie) # And now output all the available cookies for the current URL - all_cookies = driver.get_cookies() - for cookie_name, cookie_value in all_cookies.items(): - print("%s -> %s", cookie_name, cookie_value) + driver.get_cookies() + From 2ee95bf456abbaeaa6cb544ea375ca112546c204 Mon Sep 17 00:00:00 2001 From: crimier Date: Tue, 18 Nov 2014 21:07:09 +0200 Subject: [PATCH 035/147] Completed code in page-objects.rst --- source/page-objects.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index ea213c4..8dbd09b 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -5,8 +5,8 @@ Page Objects .. note:: - This chaper is a work in progress, right now I don't have time to - finish it. If anyone interested, please send pull request in + Code in this chapter works and is quite self-descriptive, but a little description wouldn't hurt. + If anyone interested, please send pull request in `Github `_. Here is an example implementation of the page objects pattern: https://github.com/baijum/pitracker/tree/master/test/acceptance @@ -63,7 +63,7 @@ The ``page.py`` will look like this:: search_text_element = SearchTextElement() def is_title_matches(self): - pass + return "Python" in self.driver.title def click_go_button(self): element = self.driver.find_element(*MainPageLocators.GO_BUTTON) @@ -73,7 +73,8 @@ The ``page.py`` will look like this:: class SearchResultsPage(BasePage): def is_results_found(self): - pass + #Probably should search for this text in the specific page element, but as for now it works fine + return "No results found." not in self.driver.page_source The ``element.py`` will look like this:: @@ -85,14 +86,14 @@ The ``element.py`` will look like this:: def __set__(self, obj, value): driver = obj.driver WebDriverWait(driver, 100).until( - lambda driver: driver.find_element_by_id(self.locator)) - driver.find_element_by_id(self.locator).send_keys(value) + lambda driver: driver.find_element_by_name(self.locator)) + driver.find_element_by_name(self.locator).send_keys(value) def __get__(self, obj, owner): driver = obj.driver WebDriverWait(driver, 100).until( - lambda driver: driver.find_element_by_id(self.locator)) - element = driver.find_element_by_id(self.locator) + lambda driver: driver.find_element_by_name(self.locator)) + element = driver.find_element_by_name(self.locator) return element.get_attribute("value") The ``locators.py`` will look like this:: From d16803c9fa679ca3317a37980c362c38347aed80 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 20 Nov 2014 10:07:48 +0530 Subject: [PATCH 036/147] remove unused import --- source/page-objects.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index 8dbd09b..86bbdcf 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -19,7 +19,6 @@ website and ensure some results are found. import unittest from selenium import webdriver - from selenium.webdriver.common.keys import Keys import page class PythonOrgSearch(unittest.TestCase): From 49aa8a89c2ad660c6f15f547b7bab6f6333aa89f Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 20 Nov 2014 10:22:39 +0530 Subject: [PATCH 037/147] expand introduction and add sections --- source/page-objects.rst | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index 86bbdcf..0d3bf7f 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -5,15 +5,24 @@ Page Objects .. note:: - Code in this chapter works and is quite self-descriptive, but a little description wouldn't hurt. - If anyone interested, please send pull request in - `Github `_. Here is an - example implementation of the page objects pattern: + Code in this chapter works and is quite self-descriptive, but a + little description wouldn't hurt. If anyone interested, please + send pull request in `Github + `_. Here is an example + implementation of the page objects pattern: https://github.com/baijum/pitracker/tree/master/test/acceptance -This chapter is a tutorial introduction to use page objects design -pattern. Here is a test case which searches for a word in python.org -website and ensure some results are found. +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 interating. Page objects reduces the +amount of duplicated code and if the user interface changes, the fix +need only changes in one place. + +Test case +~~~~~~~~~ + +Here is a test case which searches for a word in python.org website +and ensure some results are found. :: @@ -41,6 +50,9 @@ website and ensure some results are found. if __name__ == "__main__": unittest.main() +Page object classes +~~~~~~~~~~~~~~~~~~~ + The ``page.py`` will look like this:: from element import BasePageElement @@ -75,6 +87,9 @@ The ``page.py`` will look like this:: #Probably should search for this text in the specific page element, but as for now it works fine return "No results found." not in self.driver.page_source +Page elements +~~~~~~~~~~~~~ + The ``element.py`` will look like this:: from selenium.webdriver.support.ui import WebDriverWait @@ -95,6 +110,9 @@ The ``element.py`` will look like this:: element = driver.find_element_by_name(self.locator) return element.get_attribute("value") +Locators +~~~~~~~~ + The ``locators.py`` will look like this:: from selenium.webdriver.common.by import By From f7188286efefd2e939cca7bdd87714a6969d2fbe Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Thu, 20 Nov 2014 10:24:38 +0530 Subject: [PATCH 038/147] break long line --- source/page-objects.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index 0d3bf7f..039cfd4 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -84,7 +84,8 @@ The ``page.py`` will look like this:: class SearchResultsPage(BasePage): def is_results_found(self): - #Probably should search for this text in the specific page element, but as for now it works fine + # Probably should search for this text in the specific page + # element, but as for now it works fine return "No results found." not in self.driver.page_source Page elements From 2baa2b2be1208732321abfcd99e6d89bacf39518 Mon Sep 17 00:00:00 2001 From: Mieszko Date: Fri, 28 Nov 2014 10:22:17 +0100 Subject: [PATCH 039/147] Some cleaning --- source/getting-started.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index f125304..103e3be 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -84,8 +84,8 @@ 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 where -as `close` will close one tab, but if it just one tab, by default most +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() @@ -96,7 +96,7 @@ 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 choices as +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 @@ -137,7 +137,7 @@ You can run the above test case from a shell like this:: OK -The above results shows that, the test has been successfully +The above result shows that the test has been successfully completed. @@ -160,7 +160,7 @@ provide keys in the keyboard like RETURN, F1, ALT etc. 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:: +that this is a test case:: class PythonOrgSearch(unittest.TestCase): @@ -221,9 +221,9 @@ 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 entire browser, where as `close` -will close a tab, but if it is just one tab, by default most browser -will exit entirely.:: +`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,12 +243,12 @@ 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 looks like +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 +The above line says that you can use this URL for connecting to remote WebDriver. Here are some examples:: from selenium.webdriver.common.desired_capabilities import DesiredCapabilities From df7568f77bc98b6ab75c42d661f5a1c4f0be4d5e Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Sat, 29 Nov 2014 13:54:52 +0530 Subject: [PATCH 040/147] more contributors --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 11bc46d..8008196 100644 --- a/README.rst +++ b/README.rst @@ -8,6 +8,6 @@ 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 more than a dozen community members has contributed to this +So far more around 20 community members has contributed to this project (See the closed pull requests). I encourage contributors -to add more sections and make it good documentation! +to add more sections and make it a good documentation! From 977c82353b3c4caddb2bdd7004dd5415cc00b8b9 Mon Sep 17 00:00:00 2001 From: bschwagg Date: Fri, 19 Dec 2014 18:19:34 -0800 Subject: [PATCH 041/147] Allow python test to run with webdriver.Chrome() Access the driver object through self. This allows the Chrome browser to work. --- source/page-objects.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index 039cfd4..ba441de 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -34,7 +34,7 @@ and ensure some results are found. def setUp(self): self.driver = webdriver.Firefox() - driver.get("http://www.python.org") + self.driver.get("http://www.python.org") def test_search_in_python_org(self): main_page = page.MainPage(self.driver) From 06db392ed0d3a9f825991941396410d8a640b295 Mon Sep 17 00:00:00 2001 From: geoffwild11 Date: Fri, 9 Jan 2015 13:55:40 -0600 Subject: [PATCH 042/147] Update getting-started.rst Lines: elem.send_keys(Keys.RETURN) assert "No results found." not in driver.page_source Lines were opposite in the tutorial on the site as the exist. Gave an error when example shows success. Having tutorial set this way makes sure that desired result happens --- source/getting-started.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 103e3be..5744d4e 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -118,8 +118,9 @@ for `python.org` search functionality:: self.assertIn("Python", driver.title) elem = driver.find_element_by_name("q") elem.send_keys("pycon") - assert "No results found." not in driver.page_source elem.send_keys(Keys.RETURN) + assert "No results found." not in driver.page_source + def tearDown(self): self.driver.close() From 20d7686f97e0eb5456f325fee24ca89757d56853 Mon Sep 17 00:00:00 2001 From: Lazar-T Date: Wed, 25 Feb 2015 19:31:33 +0100 Subject: [PATCH 043/147] Update navigating.rst --- source/navigating.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/navigating.rst b/source/navigating.rst index b3660c0..ccad626 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -189,7 +189,7 @@ Popup dialogs ~~~~~~~~~~~~~ Selenium WebDriver has built-in support for handling popup dialog -boxes. After you've triggerd and action that would open a popup, you +boxes. After you've triggerd action that would open a popup, you can access the alert with the following:: alert = driver.switch_to_alert() From ec3ee4b061f682fb11378c2251591a81850b09c6 Mon Sep 17 00:00:00 2001 From: Lazar-T Date: Wed, 25 Feb 2015 19:35:58 +0100 Subject: [PATCH 044/147] Update waits.rst --- source/waits.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/waits.rst b/source/waits.rst index 2031d64..328f324 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -56,7 +56,7 @@ ExpectedCondition types. **Expected Conditions** -There are some common conditions that are frequently come across when +There are some common conditions that are frequent when automating web browsers. Listed below are Implementations of each. Selenium Python binding provides some convienence methods so you don't have to code an expected_condition class yourself or create your From 700d3b5d48707ba4cb8e9f24fc789a83fe007c63 Mon Sep 17 00:00:00 2001 From: Lazar-T Date: Wed, 25 Feb 2015 19:41:36 +0100 Subject: [PATCH 045/147] Update page-objects.rst --- 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 ba441de..e43aa46 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -6,8 +6,8 @@ Page Objects .. note:: Code in this chapter works and is quite self-descriptive, but a - little description wouldn't hurt. If anyone interested, please - send pull request in `Github + little description wouldn't hurt. If anyone is interested, please + send pull request on `Github `_. Here is an example implementation of the page objects pattern: https://github.com/baijum/pitracker/tree/master/test/acceptance From 3fd26de07c4d378be7cc02041c9a879a44ca8c9c Mon Sep 17 00:00:00 2001 From: kasenoshi Date: Fri, 27 Feb 2015 01:29:07 +0800 Subject: [PATCH 046/147] Update locating-elements.rst fix some typos --- source/locating-elements.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/locating-elements.rst b/source/locating-elements.rst index 6db0186..11de21d 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -85,7 +85,7 @@ 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. -For instance, conside this page source:: +For instance, consider this page source:: @@ -133,7 +133,7 @@ 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, conside this page source:: +For instance, consider this page source:: @@ -241,7 +241,7 @@ 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, conside this page source:: +For instance, consider this page source:: From 24a67e03aa42758e55e2b89b5f6460582ac65d67 Mon Sep 17 00:00:00 2001 From: "Sam E. Lawrence" Date: Thu, 16 Apr 2015 17:01:45 -0400 Subject: [PATCH 047/147] Update getting-started.rst -- minor typo / grammar fix. --- source/getting-started.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 5744d4e..af118a7 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -267,7 +267,7 @@ remote WebDriver. Here are some examples:: desired_capabilities=DesiredCapabilities.HTMLUNITWITHJS) The desired capabilities is a dictionary, so instead of using the -default dictionaries, you can specifies the values explicitly:: +default dictionaries, you can specify the values explicitly:: driver = webdriver.Remote( command_executor='http://127.0.0.1:4444/wd/hub', From ff1150786ae062da89ecd89e2cb46f6c78b94ad7 Mon Sep 17 00:00:00 2001 From: Andrei Taylor Date: Tue, 21 Apr 2015 09:29:09 -0700 Subject: [PATCH 048/147] Corrects an error in drag and drop Missing call to the perform function. --- source/navigating.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/navigating.rst b/source/navigating.rst index ccad626..bdf993f 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -143,8 +143,7 @@ amount, or on to another element:: from selenium.webdriver import ActionChains action_chains = ActionChains(driver) - action_chains.drag_and_drop(element, target) - + action_chains.drag_and_drop(element, target).perform() Moving between windows and frames ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 8ac6314ea5b755caec751594a026507764a22915 Mon Sep 17 00:00:00 2001 From: Francisco Puga Date: Fri, 29 May 2015 18:23:10 +0200 Subject: [PATCH 049/147] Adds the webdriver import To allow that the example works with copy & paste without modifying anything the webdriver import is needed. --- source/getting-started.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/source/getting-started.rst b/source/getting-started.rst index af118a7..e23fbff 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -252,6 +252,7 @@ this:: 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 driver = webdriver.Remote( From 4e5152d67106f2900e01555e20255287bb65a885 Mon Sep 17 00:00:00 2001 From: Kaiser Khan Date: Fri, 11 Sep 2015 15:18:30 +1000 Subject: [PATCH 050/147] Added pydocs and comments to clarify intent to newbies. --- source/page-objects.rst | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index e43aa46..d6f938e 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -31,18 +31,29 @@ and ensure some results are found. import page class PythonOrgSearch(unittest.TestCase): + """A sample test class to show how page object works""" def setUp(self): self.driver = webdriver.Firefox() 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. + """ + + #Load the main page. In this case the home page of Python.og. 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." - main_page.search_text_element = "pycon" - main_page.click_go_button() + #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) - assert search_results_page.is_results_found(), "No results found." + #Verifies that the results page is not empty + assert search_results_page.is_results_found(), "No results found." def tearDown(self): self.driver.close() @@ -59,29 +70,37 @@ The ``page.py`` will look like this:: from locators import MainPageLocators class SearchTextElement(BasePageElement): + """This class gets the search text from the specified locator""" + #The locator for search box where search string is entered locator = 'q' class BasePage(object): + """Base class to initialize the base page that will be called from all pages""" def __init__(self, driver): self.driver = driver class MainPage(BasePage): + """Home page action methods come here. I.e. Python.org""" + #Declares a variable that will contain the retrieved text search_text_element = SearchTextElement() 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() class SearchResultsPage(BasePage): + """Search results page action methods come here""" def is_results_found(self): # Probably should search for this text in the specific page @@ -97,14 +116,17 @@ The ``element.py`` will look like this:: class BasePageElement(object): + """Base page class that is initialized on every page object class.""" 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)) 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)) @@ -119,7 +141,9 @@ The ``locators.py`` will look like this:: from selenium.webdriver.common.by import By 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""" pass From 2d2d9dae0505f2e7f25b8ee2ec04d6365df37a75 Mon Sep 17 00:00:00 2001 From: Nik Nyby Date: Mon, 5 Oct 2015 13:28:02 -0400 Subject: [PATCH 051/147] small grammar fix --- source/waits.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/waits.rst b/source/waits.rst index 328f324..31f9fcb 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -22,7 +22,7 @@ trying to locate an element. Explicit Waits ~~~~~~~~~~~~~~ -An explicit waits is code you define to wait for a certain condition +An explicit wait is code you define to wait for a certain condition to occur before proceeding further in the code. The worst 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 From 3916618938791effd2fd60efbf86b718a43ea018 Mon Sep 17 00:00:00 2001 From: Etun Date: Mon, 2 Nov 2015 16:18:33 +0200 Subject: [PATCH 052/147] orthographic mistake fixed and description added orthographic mistake fixed for 'interating' an explanation added why to use Page Object pattern. --- source/page-objects.rst | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index d6f938e..40c51e7 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -14,9 +14,14 @@ 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 interating. Page objects reduces the -amount of duplicated code and if the user interface changes, the fix -need only changes in one place. +interface that your test is interacting. + +Benefits of using page object pattern: + +* Creating reusable code that can be shared across multiple test cases +* Reducing the amount of duplicated code +* If the user interface changes, the fix needs changes in only one place + Test case ~~~~~~~~~ @@ -64,6 +69,8 @@ and ensure 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 implementsation is created. + The ``page.py`` will look like this:: from element import BasePageElement @@ -136,6 +143,8 @@ The ``element.py`` will look like this:: 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. + The ``locators.py`` will look like this:: from selenium.webdriver.common.by import By From a7baddc91a4ed7604d281ad3e93b327026764630 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Mon, 9 Nov 2015 21:18:08 +0530 Subject: [PATCH 053/147] remove note --- source/page-objects.rst | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index 40c51e7..0d6a235 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -3,15 +3,6 @@ Page Objects ------------ -.. note:: - - Code in this chapter works and is quite self-descriptive, but a - little description wouldn't hurt. If anyone is interested, please - send pull request on `Github - `_. Here is an example - implementation of the page objects pattern: - https://github.com/baijum/pitracker/tree/master/test/acceptance - 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. @@ -69,7 +60,9 @@ and ensure 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 implementsation 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 implementsation is created. The ``page.py`` will look like this:: @@ -143,7 +136,9 @@ The ``element.py`` will look like this:: 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:: From 91c1bf48ea3ab4f3ed329eb5f5bf7cac8e6e8407 Mon Sep 17 00:00:00 2001 From: Kojo Idrissa Date: Fri, 11 Dec 2015 11:47:28 -0600 Subject: [PATCH 054/147] fixed 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 11de21d..2327467 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -3,7 +3,7 @@ Locating Elements ----------------- -There are vaious strategies to locate elements in a page. You can use +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: From cc59cd7c05c133426396935143399581d3a19a98 Mon Sep 17 00:00:00 2001 From: Gorvely Date: Sat, 12 Dec 2015 00:06:31 +0100 Subject: [PATCH 055/147] Fix typos #Load the main page. In this case the home page of Python.og. to #Load the main page. In this case the home page of Python.org. --- source/page-objects.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index 0d6a235..d266052 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -40,7 +40,7 @@ and ensure some results are found. the results were not empty. """ - #Load the main page. In this case the home page of Python.og. + #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." From f215590c240ee5472c4c4a094831e6d096284536 Mon Sep 17 00:00:00 2001 From: Nik Nyby Date: Fri, 18 Dec 2015 13:48:11 -0500 Subject: [PATCH 056/147] Fix typo: syntaxt -> syntax --- 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 2327467..6b01249 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -278,7 +278,7 @@ 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 syntaxt. +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, a ``NoSuchElementException`` will be raised. From 6337499f62af2e2fa31c16d0141ad7f8120c803e Mon Sep 17 00:00:00 2001 From: Nik Nyby Date: Wed, 23 Dec 2015 01:32:58 -0500 Subject: [PATCH 057/147] Fix broken link to chromedriver downloads --- source/faq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/faq.rst b/source/faq.rst index 4266371..38178d4 100644 --- a/source/faq.rst +++ b/source/faq.rst @@ -9,7 +9,7 @@ How to use ChromeDriver ? ~~~~~~~~~~~~~~~~~~~~~~~~~ Download the latest `chromedriver from download page -`_. Unzip the +`_. Unzip the file:: unzip chromedriver_linux32_x.x.x.x.zip From 6cb8022d20aece5cc4929a2261fc6eefad5be525 Mon Sep 17 00:00:00 2001 From: Stuart McCoLL Date: Wed, 30 Dec 2015 15:00:45 +0000 Subject: [PATCH 058/147] Fix broken link to W3Schools XPath tutorial --- 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 6b01249..316f386 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -189,7 +189,7 @@ The "Clear" button element can be located like this:: These examples cover some basics, but in order to learn more, the following references are recommended: -* `W3Schools XPath Tutorial `_ +* `W3Schools XPath Tutorial `_ * `W3C XPath Recommendation `_ * `XPath Tutorial `_ From 2b46339af122df210b8fd07e9b591e6831f318fc Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 13 Jan 2016 11:56:27 +0530 Subject: [PATCH 059/147] 30+ contributors --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 8008196..bf7bea2 100644 --- a/README.rst +++ b/README.rst @@ -8,6 +8,6 @@ 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 more around 20 community members has contributed to this +So far more around 30 community members has contributed to this project (See the closed pull requests). I encourage contributors to add more sections and make it a good documentation! From a14ee7d266856b8b049f161dc3c9bab4ecc03061 Mon Sep 17 00:00:00 2001 From: Matthew Krueger Date: Tue, 1 Mar 2016 18:24:20 -1000 Subject: [PATCH 060/147] Correct minor typo on line 106 Fixed a minor type on line 106 from 'as it occur' to 'as it occurs'. --- 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 316f386..d87dc20 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -103,7 +103,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 occur before the "Clear" +This will give the "Login" button as it occurs before the "Clear" button:: continue = driver.find_element_by_name('continue') From 96b029eace1f309115235871ad165be0a044351d Mon Sep 17 00:00:00 2001 From: jose pita Date: Sun, 20 Mar 2016 16:41:00 +0100 Subject: [PATCH 061/147] Update page-objects.rst fix typo on "implementsation" to "implementation" --- source/page-objects.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index d266052..6863db1 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -62,7 +62,7 @@ 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 implementsation is created. +code and technical implementation is created. The ``page.py`` will look like this:: From a90807e669e52fbd8d7d5370ccc534669fd6edd7 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 23 Mar 2016 13:39:12 +0530 Subject: [PATCH 062/147] unused files --- source/glossary.rst | 5 ----- source/references.rst | 14 -------------- source/test-design.rst | 28 ---------------------------- 3 files changed, 47 deletions(-) delete mode 100644 source/glossary.rst delete mode 100644 source/references.rst delete mode 100644 source/test-design.rst diff --git a/source/glossary.rst b/source/glossary.rst deleted file mode 100644 index c5d5290..0000000 --- a/source/glossary.rst +++ /dev/null @@ -1,5 +0,0 @@ -.. _glossary: - -Glossary --------- - diff --git a/source/references.rst b/source/references.rst deleted file mode 100644 index 069ce8e..0000000 --- a/source/references.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _references: - -References ----------- - -- Official API: http://selenium.googlecode.com/svn/trunk/docs/api/py/index.html - -- Blog post explaining how to use headless X for running Selenium - tests: - http://coreygoldberg.blogspot.com/2011/06/python-headless-selenium-webdriver.html - -- Jenkins plugin for headless Selenium tests: - https://wiki.jenkins-ci.org/display/JENKINS/Xvnc+Plugin - diff --git a/source/test-design.rst b/source/test-design.rst deleted file mode 100644 index f9083cb..0000000 --- a/source/test-design.rst +++ /dev/null @@ -1,28 +0,0 @@ -.. _test-design: - -Test Design Considerations --------------------------- - -Page Objects -~~~~~~~~~~~~ - -Page objects is a design pattern used for web automated testing. - -.. - Typical structure recommended. - - tests/pageobject/page.py - tests/pageobject/element.py - tests/package1/locators.py - tests/pakage1/page/somepage.py - tests/pakage1/test_something.py - tests/package2/locators.py - tests/pakage2/page/somepage.py - tests/pakage2/test_something.py - -Few links: - -1. http://code.google.com/p/selenium/wiki/PageObjects -2. http://www.theautomatedtester.co.uk/tutorials/selenium/page-object-pattern.htm -3. http://pragprog.com/magazines/2010-08/page-objects-in-python -4. http://docs.seleniumhq.org/docs/06_test_design_considerations.jsp From 71040b8881a5a1240822e3f99493ee4574ec357e Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 23 Mar 2016 13:39:29 +0530 Subject: [PATCH 063/147] use 3.5 --- source/installation.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/source/installation.rst b/source/installation.rst index 586e896..649bed4 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.2, 3.3 and 3.4. +Python versions are 2.7, 3.2 and above. This documentation explains Selenium 2 WebDriver API. Selenium 1 / Selenium RC API is not covered here. @@ -23,18 +23,18 @@ Downloading Python bindings for Selenium ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can download Python bindings for Selenium from the `PyPI page for -selenium package `_. However, +selenium package `_. However, a better approach would be to use -`pip `_ to -install the selenium package. Python 3.4 has pip available in the -`standard library `_. +`pip `_ to +install the selenium package. Python 3.5 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.4 has `pyvenv -`_ +to create isolated Python environments. Python 3.5 has `pyvenv +`_ which is almost same as virtualenv. @@ -45,7 +45,7 @@ Detailed instructions for Windows users You should have internet connection to perform this installation. -1. Install Python 3.4 using the `MSI available in python.org download +1. Install Python 3.5 using the `MSI available in python.org download page `_. 2. Start a command prompt using the ``cmd.exe`` program and run the @@ -53,13 +53,13 @@ Detailed instructions for Windows users :: - C:\Python34\Scripts\pip.exe 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:\Python34\python.exe C:\my_selenium_script.py + C:\Python35\python.exe C:\my_selenium_script.py Downloading Selenium server From 66fc30db9c62afcd0a1b5997ef103e31864d2111 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Sat, 23 Apr 2016 08:39:49 +0530 Subject: [PATCH 064/147] simple title - avoid duplicate --- 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 e23fbff..16afa01 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -31,8 +31,8 @@ The above script can be saved into a file (eg:- The `python` which you are running should have the `selenium` module installed. -Walk through of the example -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example Explained +~~~~~~~~~~~~~~~~~ The `selenium.webdriver` module provides all the WebDriver implementations. Currently supported WebDriver implementations are From 2c85dd14637515ce4305bbcbf078caae4522a7b7 Mon Sep 17 00:00:00 2001 From: Nik Nyby Date: Tue, 24 May 2016 13:08:59 -0400 Subject: [PATCH 065/147] remove broken link to official documentation the official documentation is not online anymore --- source/api.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/source/api.rst b/source/api.rst index 7e80d2a..b2fd24b 100644 --- a/source/api.rst +++ b/source/api.rst @@ -3,12 +3,6 @@ WebDriver API ------------- -.. note:: - - This is not an official documentation. Official API documentation - is available `here - `_. - This chapter cover all the interfaces of Selenium WebDriver. From a30ec56a39a193a2791b8f50bdbd7fc4928b28e8 Mon Sep 17 00:00:00 2001 From: Nik Nyby Date: Tue, 24 May 2016 13:37:08 -0400 Subject: [PATCH 066/147] Update api.rst --- source/api.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/api.rst b/source/api.rst index b2fd24b..f41c680 100644 --- a/source/api.rst +++ b/source/api.rst @@ -3,6 +3,12 @@ WebDriver API ------------- +.. note:: + + This is not an official documentation. Official API documentation + is available `here + `_. + This chapter cover all the interfaces of Selenium WebDriver. From 04f9d4cdbf3c479fde8c4913678abaaf8518acc7 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 3 Jun 2016 10:13:07 +0530 Subject: [PATCH 067/147] new domain --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index bf7bea2..f05271d 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ Selenium Python Bindings Documentation ====================================== -https://selenium-python.readthedocs.org +https://selenium-python.readthedocs.io NOTE: THIS IS NOT AN OFFICIAL DOCUMENTATION From 161cf16d23b8d5371abf38cbc55745f5146605a4 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 3 Jun 2016 10:13:49 +0530 Subject: [PATCH 068/147] https --- source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/index.rst b/source/index.rst index 7bb6733..1324958 100644 --- a/source/index.rst +++ b/source/index.rst @@ -2,7 +2,7 @@ Selenium with Python ******************** -:Author: `Baiju Muthukadan `_ +:Author: `Baiju Muthukadan `_ :License: This document is licensed under a `Creative Commons Attribution-ShareAlike 4.0 International License `_. From 257de9060674daf7294171f92d467bc39a02cb5f Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Fri, 3 Jun 2016 10:19:05 +0530 Subject: [PATCH 069/147] update link --- source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/index.rst b/source/index.rst index 1324958..0d9c771 100644 --- a/source/index.rst +++ b/source/index.rst @@ -10,7 +10,7 @@ Selenium with Python This is not an official documentation. Official API documentation is available `here - `_. + `_. .. toctree:: :numbered: From 5f835de33fee2a75b6862e76ae1ebe649dc4d91a Mon Sep 17 00:00:00 2001 From: Andrew Abraham Date: Tue, 7 Jun 2016 12:17:28 -0700 Subject: [PATCH 070/147] Fix tutorial example by clearing input before sending keys --- source/getting-started.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 16afa01..53e7030 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -18,6 +18,7 @@ from Python like this. driver.get("http://www.python.org") assert "Python" in driver.title elem = driver.find_element_by_name("q") + elem.clear() elem.send_keys("pycon") elem.send_keys(Keys.RETURN) assert "No results found." not in driver.page_source @@ -36,7 +37,7 @@ 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 +Firefox, Chrome, IE and Remote. The `Keys` class provide keys in the keyboard like RETURN, F1, ALT etc. :: @@ -73,8 +74,11 @@ method. Detailed explanation of finding elements is available in the 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`:: +`selenium.webdriver.common.keys`. To be safe, we'll first clear any +prepopulated 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) From bcdca9afd9e69db3463f0d7294d58818f5497245 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 15 Jun 2016 14:46:44 +0530 Subject: [PATCH 071/147] code block --- source/getting-started.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 53e7030..6891431 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -76,7 +76,7 @@ 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`. To be safe, we'll first clear any prepopulated text in the input field (e.g. "Search") so it doesn't -affect our search results. +affect our search results:: elem.clear() elem.send_keys("pycon") From fdb168d7cbc449e49609b7b7ce9084a2a901c25c Mon Sep 17 00:00:00 2001 From: Peter Bittner Date: Mon, 11 Jul 2016 11:53:26 +0200 Subject: [PATCH 072/147] Update link to official Selenium FAQs --- source/faq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/faq.rst b/source/faq.rst index 38178d4..b7f865a 100644 --- a/source/faq.rst +++ b/source/faq.rst @@ -3,7 +3,7 @@ Appendix: Frequently Asked Questions ------------------------------------ -Another FAQ: https://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions +Another FAQ: https://github.com/SeleniumHQ/selenium/wiki/Frequently-Asked-Questions How to use ChromeDriver ? ~~~~~~~~~~~~~~~~~~~~~~~~~ From 88d3533adfbb53167b685d61b68fb7002cdcf300 Mon Sep 17 00:00:00 2001 From: Jonathan Agustin Date: Sun, 18 Dec 2016 22:09:45 -0800 Subject: [PATCH 073/147] Fixed grammar --- source/getting-started.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/getting-started.rst b/source/getting-started.rst index 6891431..4f3020d 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -73,7 +73,7 @@ method. Detailed explanation of finding elements is available in the 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 +keyboard. Special keys can be sent using `Keys` class imported from `selenium.webdriver.common.keys`. To be safe, we'll first clear any prepopulated text in the input field (e.g. "Search") so it doesn't affect our search results:: From b313423ce288080f0f86ef422fc06985a8893de4 Mon Sep 17 00:00:00 2001 From: h4rvey Date: Thu, 9 Feb 2017 07:15:23 +0000 Subject: [PATCH 074/147] Added drivers document added driver document this file from http://seleniumhq.github.io/selenium/docs/api/py/ --- source/installation.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/source/installation.rst b/source/installation.rst index 649bed4..598c2d5 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -37,6 +37,26 @@ to create isolated Python environments. Python 3.5 has `pyvenv `_ which is almost same as virtualenv. +Drivers +~~~~~~~ + +Selenium requires a driver to interface with the chosen browser. Firefox, +for example, requires `geckodriver `_, which needs to be installed before the below examples can be run. Make sure it's in your `PATH`, e. g., place it in `/usr/bin` or `/usr/local/bin`. + +Failure to observe this step will give you an error `selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH.` + +Other supported browsers will have their own drivers available. Links to some of the more popular browser drivers follow. + ++--------------+-----------------------------------------------------------------------+ +| **Chrome**: | https://sites.google.com/a/chromium.org/chromedriver/downloads | ++--------------+-----------------------------------------------------------------------+ +| **Edge**: | https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ | ++--------------+-----------------------------------------------------------------------+ +| **Firefox**: | https://github.com/mozilla/geckodriver/releases | ++--------------+-----------------------------------------------------------------------+ +| **Safari**: | https://webkit.org/blog/6900/webdriver-support-in-safari-10/ | ++--------------+-----------------------------------------------------------------------+ + Detailed instructions for Windows users ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 09abf56163a541e1a5e2b7674a7bf9bf42522178 Mon Sep 17 00:00:00 2001 From: Roger Erens Date: Tue, 7 Feb 2017 21:50:11 +0100 Subject: [PATCH 075/147] Improve the explanation of waits --- source/waits.rst | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/source/waits.rst b/source/waits.rst index 31f9fcb..5ab750d 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -4,18 +4,18 @@ Waits ----- These days most of the web apps are using AJAX techniques. When a -page is loaded to browser, the elements within that page may load at -different time intervals. This makes locating elements difficult, if -the element is not present in the DOM, it will raise -`ElementNotVisibleException` exception. Using waits, we can solve -this issue. Waiting provides some time interval between actions -performed - mostly locating element or any other operation with the +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 to wait for a certain condition to -occur before proceeding further with executions. An implicit wait -makes WebDriver to poll the DOM for a certain amount of time when +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. @@ -23,7 +23,7 @@ Explicit Waits ~~~~~~~~~~~~~~ An explicit wait is code you define to wait for a certain condition -to occur before proceeding further in the code. The worst case of +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 @@ -47,8 +47,8 @@ accomplished. driver.quit() -This waits up to 10 seconds before throwing a TimeoutException or if -it finds the element will return it in 0 - 10 seconds. WebDriverWait +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 @@ -56,8 +56,8 @@ ExpectedCondition types. **Expected Conditions** -There are some common conditions that are frequent when -automating web browsers. Listed below are Implementations of +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 convienence methods so you don't have to code an expected_condition class yourself or create your own utility package for them. @@ -72,7 +72,7 @@ own utility package for them. - text_to_be_present_in_element_value - frame_to_be_available_and_switch_to_it - invisibility_of_element_located -- element_to_be_clickable - it is Displayed and Enabled. +- element_to_be_clickable - staleness_of - element_to_be_selected - element_located_to_be_selected @@ -85,7 +85,7 @@ own utility package for them. from selenium.webdriver.support import expected_conditions as EC wait = WebDriverWait(driver, 10) - element = wait.until(EC.element_to_be_clickable((By.ID,'someid'))) + 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. @@ -94,10 +94,10 @@ to use with WebDriverWait. Implicit Waits ~~~~~~~~~~~~~~ -An implicit wait is to tell WebDriver to poll the DOM for a certain -amount of time when trying to find an element or elements if they are +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 -implicit wait is set for the life of the WebDriver object instance. +implicit wait is set for the life of the WebDriver object. :: From 70307ffdde0300e882cbd9a7412c5ef8fca585ea Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Tue, 21 Feb 2017 19:32:24 +0530 Subject: [PATCH 076/147] update versions --- source/installation.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/installation.rst b/source/installation.rst index 598c2d5..a973da6 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.2 and above. +Python versions are 2.7, 3.5 and above. This documentation explains Selenium 2 WebDriver API. Selenium 1 / Selenium RC API is not covered here. @@ -26,15 +26,15 @@ You can download Python bindings for Selenium from the `PyPI page for selenium package `_. However, a better approach would be to use `pip `_ to -install the selenium package. Python 3.5 has pip available in the -`standard library `_. +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.5 has `pyvenv -`_ +to create isolated Python environments. Python 3.6 has `pyvenv +`_ which is almost same as virtualenv. Drivers @@ -65,7 +65,7 @@ Detailed instructions for Windows users You should have internet connection to perform this installation. -1. Install Python 3.5 using the `MSI available in python.org download +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 From f0b3b80d67e162ab950ea3328cbd88eba76228ef Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Wed, 26 Apr 2017 14:31:33 +0530 Subject: [PATCH 077/147] remote web driver not required --- source/installation.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/installation.rst b/source/installation.rst index a973da6..9393ba1 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -87,8 +87,8 @@ 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 + **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. From 311018b6e8b967dcd44ae1dcd5648974da8ae802 Mon Sep 17 00:00:00 2001 From: Huyanh Hoang Date: Mon, 22 May 2017 21:57:50 -0700 Subject: [PATCH 078/147] Link expected conditions hyperlink to driver API --- source/waits.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/waits.rst b/source/waits.rst index 5ab750d..5cc5fdd 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -58,7 +58,7 @@ ExpectedCondition types. 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 convienence methods so you +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. From 72c911f437a8843fe4f28af522724c0317abb58a Mon Sep 17 00:00:00 2001 From: Raffaele Mancuso Date: Sun, 2 Jul 2017 14:33:04 +0200 Subject: [PATCH 079/147] Update locating-elements.rst --- 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 d87dc20..d8abba8 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -189,7 +189,7 @@ The "Clear" button element can be located like this:: These examples cover some basics, but in order to learn more, the following references are recommended: -* `W3Schools XPath Tutorial `_ +* `W3Schools XPath Tutorial `_ * `W3C XPath Recommendation `_ * `XPath Tutorial `_ From e92efacb589d293539561467f7f7fa51068a3913 Mon Sep 17 00:00:00 2001 From: Edu Calleja Date: Tue, 1 Aug 2017 13:19:11 +1200 Subject: [PATCH 080/147] Added custom wait conditions --- source/waits.rst | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/source/waits.rst b/source/waits.rst index 5cc5fdd..f421319 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -90,6 +90,34 @@ own utility package for them. The expected_conditions module contains a set of predefined conditions to use with WebDriverWait. +You can always create your own conditions when none of the previous convenience +methods fit your requirements. You only need to create a class +which __call__ method returns False when the condition isn't meet. + + +:: + + class element_has_css_class(object): + """ An expectation for checking that an element has a particular css class. + locator - used to find the element + returns the WebElement once it has the particular css class + """ + def __init__(self, locator, css_class): + self.locator = locator + self.css_class = css_class + + def __call__(self, driver): + element = driver.find_element(*self.locator) # Finding the referenced element + if self.css_class in element.get_attribute("class"): + return element + else: + return False + + # Wait until an element with id='myNewInput' has class 'myCSSClass' + wait = WebDriverWait(driver, 10) + element = wait.until(element_has_css_class((By.ID, 'myNewInput'), "myCSSClass")) + + Implicit Waits ~~~~~~~~~~~~~~ From c50c0627413b38fe1a3fa02c1aea39981fd9ea96 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Mon, 14 Aug 2017 11:09:06 +0530 Subject: [PATCH 081/147] update links --- source/locating-elements.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/locating-elements.rst b/source/locating-elements.rst index d87dc20..a218b78 100644 --- a/source/locating-elements.rst +++ b/source/locating-elements.rst @@ -189,7 +189,7 @@ The "Clear" button element can be located like this:: These examples cover some basics, but in order to learn more, the following references are recommended: -* `W3Schools XPath Tutorial `_ +* `W3Schools XPath Tutorial `_ * `W3C XPath Recommendation `_ * `XPath Tutorial `_ @@ -199,9 +199,9 @@ There are also 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 `_ - +* `Firebug `_ - XPath suggestions are just one of the many powerful features of this very useful add-on. * `XPath Helper @@ -295,5 +295,5 @@ The "p" element can be located like this:: content = driver.find_element_by_css_selector('p.content') -`Sauce Labs has good documentation `_ +`Sauce Labs has good documentation `_ on CSS selectors. From e000c4660ecf76d4a06e4f4f0c51dc35177606e4 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Mon, 14 Aug 2017 11:21:46 +0530 Subject: [PATCH 082/147] new theme! --- source/_static/logo.png | Bin 0 -> 25192 bytes source/conf.py | 21 ++++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 source/_static/logo.png diff --git a/source/_static/logo.png b/source/_static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..cd765bdc0df46f63d9a5b6207dd6e0b07f562fd8 GIT binary patch literal 25192 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 dM; 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 qY@-|v Date: Mon, 14 Aug 2017 11:52:36 +0530 Subject: [PATCH 083/147] rephrase sentence --- source/waits.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/waits.rst b/source/waits.rst index f421319..cf37d0c 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -90,15 +90,18 @@ own utility package for them. The expected_conditions module contains a set of predefined conditions to use with WebDriverWait. -You can always create your own conditions when none of the previous convenience -methods fit your requirements. You only need to create a class -which __call__ method returns False when the condition isn't meet. +**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. :: class element_has_css_class(object): - """ An expectation for checking that an element has a particular css class. + """An expectation for checking that an element has a particular css class. + locator - used to find the element returns the WebElement once it has the particular css class """ From ebef43a88a2f8b288d2d73c6824c74281db42b80 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Mon, 14 Aug 2017 12:01:14 +0530 Subject: [PATCH 084/147] update contributor notice --- README.rst | 2 +- source/index.rst | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index f05271d..0ca02aa 100644 --- a/README.rst +++ b/README.rst @@ -8,6 +8,6 @@ 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 more around 30 community members has contributed to this +So far more around 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! diff --git a/source/index.rst b/source/index.rst index 0d9c771..9cb478b 100644 --- a/source/index.rst +++ b/source/index.rst @@ -8,9 +8,15 @@ Selenium with Python .. note:: - This is not an official documentation. Official API documentation - is available `here - `_. + 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 + more around 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! + .. toctree:: :numbered: From 238f7d6c4bb57aa06d1d3fe435bc8005d9c331e6 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Mon, 14 Aug 2017 12:22:43 +0530 Subject: [PATCH 085/147] grammar --- source/api.rst | 13 +++++++------ source/getting-started.rst | 10 +++++----- source/installation.rst | 8 ++++---- source/navigating.rst | 16 ++++++++-------- source/waits.rst | 2 +- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/source/api.rst b/source/api.rst index f41c680..eba7f81 100644 --- a/source/api.rst +++ b/source/api.rst @@ -9,13 +9,13 @@ WebDriver API is available `here `_. -This chapter cover all the interfaces of Selenium WebDriver. +This chapter covers all the interfaces of Selenium WebDriver. **Recommended Import Style** -The API definitions in this chapter shows the absolute location of classes. -However the recommended import style is as given below:: +The API definitions in this chapter show the absolute location of classes. +However, the recommended import style is as given below:: from selenium import webdriver @@ -38,7 +38,8 @@ The special keys class (``Keys``) can be imported like this:: from selenium.webdriver.common.keys import Keys -The exception classes can be imported like this (Replace the ``TheNameOfTheExceptionClass`` with actual class name given below):: +The exception classes can be imported like this (Replace the ``TheNameOfTheExceptionClass`` +with the actual class name given below):: from selenium.common.exceptions import [TheNameOfTheExceptionClass] @@ -52,13 +53,13 @@ Here is an example for property: - current_url - URL of the current loaded page. + URL of the currently loaded page. Usage:: driver.current_url -Here is an example for a method: +Here is an example of a method: - close() diff --git a/source/getting-started.rst b/source/getting-started.rst index 4f3020d..0599af4 100644 --- a/source/getting-started.rst +++ b/source/getting-started.rst @@ -67,15 +67,15 @@ in it:: 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 +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 +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 -prepopulated text in the input field (e.g. "Search") so it doesn't +pre-populated text in the input field (e.g. "Search") so it doesn't affect our search results:: elem.clear() @@ -210,14 +210,14 @@ method. Detailed explanation of finding elements is available in the elem = driver.find_element_by_name("q") -Next we are sending keys, this is similar to entering keys using your +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 result as per search if +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:: diff --git a/source/installation.rst b/source/installation.rst index 9393ba1..2f2da2b 100644 --- a/source/installation.rst +++ b/source/installation.rst @@ -63,7 +63,7 @@ Detailed instructions for Windows users .. Note:: - You should have internet connection to perform this installation. + You should have an internet connection to perform this installation. 1. Install Python 3.6 using the `MSI available in python.org download page `_. @@ -87,7 +87,7 @@ Downloading Selenium server .. note:: - **The Selenium server is only required, if you want to use the remote + **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. @@ -112,13 +112,13 @@ you can start the Selenium server using this command:: java -jar selenium-server-standalone-2.x.x.jar -Replace `2.x.x` with actual version of Selenium server you downloaded +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 relative or absolute path to Selenium server jar file. +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 diff --git a/source/navigating.rst b/source/navigating.rst index bdf993f..04ecce9 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -64,7 +64,7 @@ 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 `clear` method:: +field or textarea with the `clear` method:: element.clear() @@ -73,7 +73,7 @@ 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 +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:: @@ -88,8 +88,8 @@ through each of it's 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 "Select", which provides useful methods for +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 @@ -188,12 +188,12 @@ Popup dialogs ~~~~~~~~~~~~~ Selenium WebDriver has built-in support for handling popup dialog -boxes. After you've triggerd action that would open a popup, you +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 +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. @@ -209,14 +209,14 @@ useful task. To navigate to a page, you can use `get` method:: driver.get("http://www.example.com") -To move backwards and forwards in your browser's history:: +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 behaviour of +happen when you call these methods if you're used to the behavior of one browser over another. diff --git a/source/waits.rst b/source/waits.rst index cf37d0c..821ee58 100644 --- a/source/waits.rst +++ b/source/waits.rst @@ -22,7 +22,7 @@ trying to locate an element. Explicit Waits ~~~~~~~~~~~~~~ -An explicit wait is code you define to wait for a certain condition +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 From aa3c8695b70875dc8e80385e39e365fefddc79e7 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Mon, 14 Aug 2017 12:25:48 +0530 Subject: [PATCH 086/147] typo --- README.rst | 2 +- source/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 0ca02aa..0f31993 100644 --- a/README.rst +++ b/README.rst @@ -8,6 +8,6 @@ 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 more around 40 community members have contributed to this +So far around 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! diff --git a/source/index.rst b/source/index.rst index 9cb478b..10ae73b 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 - more around 40 community members have contributed to this project + around 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! From c80a1dc465054dea67ce407418d644c13a1aa8a7 Mon Sep 17 00:00:00 2001 From: blahma Date: Wed, 25 Oct 2017 11:27:19 +0200 Subject: [PATCH 087/147] Removing unexpected indent --- source/page-objects.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/page-objects.rst b/source/page-objects.rst index 6863db1..2db1197 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -49,7 +49,7 @@ and ensure some results are found. 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." + assert search_results_page.is_results_found(), "No results found." def tearDown(self): self.driver.close() From 7a50324fd6a880e90a8094790a13c578de76d258 Mon Sep 17 00:00:00 2001 From: alvinthai Date: Tue, 21 Nov 2017 23:00:33 -0800 Subject: [PATCH 088/147] Update page-objects.rst changed __set__ function so that search entry is cleared prior to setting value currently, the __set__ function appends the text to the search entry, which has a default value of "Search" --- source/page-objects.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/source/page-objects.rst b/source/page-objects.rst index 2db1197..822b2ec 100644 --- a/source/page-objects.rst +++ b/source/page-objects.rst @@ -123,6 +123,7 @@ 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) def __get__(self, obj, owner): From 8a8a3c92b11c19207a5e4d425a5fa5015e8c8448 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Tue, 2 Jan 2018 15:51:18 +0530 Subject: [PATCH 089/147] 40+ contributors --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 0f31993..be39960 100644 --- a/README.rst +++ b/README.rst @@ -8,6 +8,6 @@ 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 around 40 community members have contributed to this +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! From 195cca0ea346a9ad94bcbfb02c54ff39a6177ac8 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Tue, 2 Jan 2018 17:58:02 +0530 Subject: [PATCH 090/147] more API end ppoints --- source/api.rst | 229 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 224 insertions(+), 5 deletions(-) diff --git a/source/api.rst b/source/api.rst index eba7f81..0424f0f 100644 --- a/source/api.rst +++ b/source/api.rst @@ -134,6 +134,24 @@ 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: + :member-order: groupwise + :show-inheritance: + +Proxy +~~~~~ + +.. automodule:: selenium.webdriver.common.proxy + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + Utilities ~~~~~~~~~ @@ -144,6 +162,24 @@ Utilities :member-order: groupwise :show-inheritance: +Service +~~~~~~~ + +.. automodule:: selenium.webdriver.common.service + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Aplication Cache +~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.common.html5.application_cache + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + Firefox WebDriver ~~~~~~~~~~~~~~~~~ @@ -154,6 +190,42 @@ Firefox WebDriver :member-order: groupwise :show-inheritance: +Firefox WebDriver Options +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.firefox.options + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Firefox WebDriver Profile +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.firefox.firefox_profile + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Firefox WebDriver Binary +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.firefox.firefox_binary + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Firefox WebDriver Extension Connection +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.firefox.extension_connection + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + Chrome WebDriver ~~~~~~~~~~~~~~~~ @@ -163,6 +235,24 @@ Chrome WebDriver :member-order: groupwise :show-inheritance: +Chrome WebDriver Options +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.chrome.options + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + + +Chrome WebDriver Service +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.chrome.service + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: Remote WebDriver ~~~~~~~~~~~~~~~~ @@ -173,9 +263,8 @@ Remote WebDriver :member-order: groupwise :show-inheritance: - -WebElement -~~~~~~~~~~ +Remote WebDriver WebElement +~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. automodule:: selenium.webdriver.remote.webelement :members: @@ -183,8 +272,117 @@ WebElement :member-order: groupwise :show-inheritance: -UI Support -~~~~~~~~~~ +Remote WebDriver Command +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.remote.command + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Remote WebDriver Error Handler +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.remote.errorhandler + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Remote WebDriver Mobile +~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.remote.mobile + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Remote WebDriver Remote Connection +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.remote.remote_connection + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Remote WebDriver Utils +~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.remote.utils + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + + +Internet Explorer WebDriver +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.ie.webdriver + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Android WebDriver +~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.android.webdriver + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Opera WebDriver +~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.opera.webdriver + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +PhantomJS WebDriver +~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.phantomjs.webdriver + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +PhantomJS WebDriver Service +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.phantomjs.service + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Safari WebDriver +~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.safari.webdriver + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Safari WebDriver Service +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.safari.service + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Select Support +~~~~~~~~~~~~~~ .. automodule:: selenium.webdriver.support.select :members: @@ -192,6 +390,9 @@ UI Support :member-order: groupwise :show-inheritance: +Wait Support +~~~~~~~~~~~~ + .. automodule:: selenium.webdriver.support.wait :members: :undoc-members: @@ -207,6 +408,24 @@ Color Support :member-order: groupwise :show-inheritance: +Event Firing WebDriver Support +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.support.event_firing_webdriver + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + +Abstract Event Listener Support +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: selenium.webdriver.support.abstract_event_listener + :members: + :undoc-members: + :member-order: groupwise + :show-inheritance: + Expected conditions Support ~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 70fff10b387f9cf935023c1016618d73d82fd374 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Tue, 2 Jan 2018 18:14:12 +0530 Subject: [PATCH 091/147] constructor docs --- source/api.rst | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/source/api.rst b/source/api.rst index 0424f0f..fa252bc 100644 --- a/source/api.rst +++ b/source/api.rst @@ -76,6 +76,7 @@ Exceptions .. automodule:: selenium.common.exceptions :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -86,6 +87,7 @@ Action Chains .. automodule:: selenium.webdriver.common.action_chains :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -96,6 +98,7 @@ Alerts .. automodule:: selenium.webdriver.common.alert :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -106,6 +109,7 @@ Special Keys .. automodule:: selenium.webdriver.common.keys :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -119,6 +123,7 @@ the :ref:`locating-elements` chapter for example usages. .. automodule:: selenium.webdriver.common.by :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -131,6 +136,7 @@ See the :ref:`selenium-remote-webdriver` section for example usages of desired c .. automodule:: selenium.webdriver.common.desired_capabilities :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -140,6 +146,7 @@ Touch Actions .. automodule:: selenium.webdriver.common.touch_actions :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -149,6 +156,7 @@ Proxy .. automodule:: selenium.webdriver.common.proxy :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -159,6 +167,7 @@ Utilities .. automodule:: selenium.webdriver.common.utils :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -168,6 +177,7 @@ Service .. automodule:: selenium.webdriver.common.service :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -177,6 +187,7 @@ Aplication Cache .. automodule:: selenium.webdriver.common.html5.application_cache :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -187,6 +198,7 @@ Firefox WebDriver .. automodule:: selenium.webdriver.firefox.webdriver :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -196,6 +208,7 @@ Firefox WebDriver Options .. automodule:: selenium.webdriver.firefox.options :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -205,6 +218,7 @@ Firefox WebDriver Profile .. automodule:: selenium.webdriver.firefox.firefox_profile :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -214,6 +228,7 @@ Firefox WebDriver Binary .. automodule:: selenium.webdriver.firefox.firefox_binary :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -223,6 +238,7 @@ Firefox WebDriver Extension Connection .. automodule:: selenium.webdriver.firefox.extension_connection :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -232,6 +248,7 @@ Chrome WebDriver .. automodule:: selenium.webdriver.chrome.webdriver :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -241,6 +258,7 @@ Chrome WebDriver Options .. automodule:: selenium.webdriver.chrome.options :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -251,6 +269,7 @@ Chrome WebDriver Service .. automodule:: selenium.webdriver.chrome.service :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -260,6 +279,7 @@ Remote WebDriver .. automodule:: selenium.webdriver.remote.webdriver :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -269,6 +289,7 @@ Remote WebDriver WebElement .. automodule:: selenium.webdriver.remote.webelement :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -278,6 +299,7 @@ Remote WebDriver Command .. automodule:: selenium.webdriver.remote.command :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -287,6 +309,7 @@ Remote WebDriver Error Handler .. automodule:: selenium.webdriver.remote.errorhandler :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -296,6 +319,7 @@ Remote WebDriver Mobile .. automodule:: selenium.webdriver.remote.mobile :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -305,6 +329,7 @@ Remote WebDriver Remote Connection .. automodule:: selenium.webdriver.remote.remote_connection :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -314,6 +339,7 @@ Remote WebDriver Utils .. automodule:: selenium.webdriver.remote.utils :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -324,6 +350,7 @@ Internet Explorer WebDriver .. automodule:: selenium.webdriver.ie.webdriver :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -333,6 +360,7 @@ Android WebDriver .. automodule:: selenium.webdriver.android.webdriver :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -342,6 +370,7 @@ Opera WebDriver .. automodule:: selenium.webdriver.opera.webdriver :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -351,6 +380,7 @@ PhantomJS WebDriver .. automodule:: selenium.webdriver.phantomjs.webdriver :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -360,6 +390,7 @@ PhantomJS WebDriver Service .. automodule:: selenium.webdriver.phantomjs.service :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -369,6 +400,7 @@ Safari WebDriver .. automodule:: selenium.webdriver.safari.webdriver :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -378,6 +410,7 @@ Safari WebDriver Service .. automodule:: selenium.webdriver.safari.service :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -387,6 +420,7 @@ Select Support .. automodule:: selenium.webdriver.support.select :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -396,6 +430,7 @@ Wait Support .. automodule:: selenium.webdriver.support.wait :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -405,6 +440,7 @@ Color Support .. automodule:: selenium.webdriver.support.color :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -414,6 +450,7 @@ Event Firing WebDriver Support .. automodule:: selenium.webdriver.support.event_firing_webdriver :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -423,6 +460,7 @@ Abstract Event Listener Support .. automodule:: selenium.webdriver.support.abstract_event_listener :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: @@ -432,5 +470,6 @@ Expected conditions Support .. automodule:: selenium.webdriver.support.expected_conditions :members: :undoc-members: + :special-members: __init__ :member-order: groupwise :show-inheritance: From 17fdec6f279664111958e25ccec0994ff6bb71dd Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Tue, 2 Jan 2018 18:17:07 +0530 Subject: [PATCH 092/147] 40+ contributors --- source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/index.rst b/source/index.rst index 10ae73b..1fa627f 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 - around 40 community members have contributed to this project + 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! From 76b26fbd4922ddce0f5bdb73ce7c96c0d1e13ef4 Mon Sep 17 00:00:00 2001 From: Baiju Muthukadan Date: Tue, 2 Jan 2018 18:27:32 +0530 Subject: [PATCH 093/147] update year --- source/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/conf.py b/source/conf.py index 581a098..316e761 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-2017, Baiju Muthukadan' +copyright = u'2011-2018, 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 @@ -237,7 +237,7 @@ epub_title = u'Selenium Python Bindings' epub_author = u'Baiju Muthukadan' epub_publisher = u'Baiju Muthukadan' -epub_copyright = u'2011-2017, Baiju Muthukadan' +epub_copyright = u'2011-2018, Baiju Muthukadan' # The language of the text. It defaults to the language option # or en if the language is not set. From cb35a8edfa27ed0c2f82bb266816f25c29e2218e Mon Sep 17 00:00:00 2001 From: Wes Gilleland Date: Sun, 21 Jan 2018 19:56:02 -0500 Subject: [PATCH 094/147] Fixed typo in the docs Aplication -> Application --- source/api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/api.rst b/source/api.rst index fa252bc..decd474 100644 --- a/source/api.rst +++ b/source/api.rst @@ -181,7 +181,7 @@ Service :member-order: groupwise :show-inheritance: -Aplication Cache +Application Cache ~~~~~~~~~~~~~~~~ .. automodule:: selenium.webdriver.common.html5.application_cache From 12826feac4fd2e53a03490ed35c1f2170b287726 Mon Sep 17 00:00:00 2001 From: Roger Erens Date: Mon, 29 Jan 2018 21:14:21 +0100 Subject: [PATCH 095/147] Fix small typos Selecting an element by id implies that the element has an id, and hence can occur only once on a page. So no need to refer to a 'first' one on the page which implies there could be multiple such elements. --- source/navigating.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/navigating.rst b/source/navigating.rst index 04ecce9..b00dbd0 100644 --- a/source/navigating.rst +++ b/source/navigating.rst @@ -84,7 +84,7 @@ drop down, and you can use "setSelected" to set something like an option.click() This will find the first "SELECT" element on the page, and cycle -through each of it's OPTIONs in turn, printing out their values, and +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 @@ -104,12 +104,12 @@ WebDriver also provides features for deselecting all the selected options:: select = Select(driver.find_element_by_id('id')) select.deselect_all() -This will deselect all OPTIONs from the first SELECT on the page. +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("xpath")) + select = Select(driver.find_element_by_xpath("//select[@name='name']")) all_selected_options = select.all_selected_options To get all available options:: From 5f62cbeeb4a039056a4a51b9ad973dd00cdd94e2 Mon Sep 17 00:00:00 2001 From: "Spencer A. Bywater" Date: Mon, 8 Oct 2018 19:43:46 -0700 Subject: [PATCH 096/147] 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 097/147] 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 098/147] 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 099/147] 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 100/147] 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 101/147] 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 102/147] 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 103/147] 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 104/147] 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 105/147] 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 106/147] 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 107/147] 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 108/147] 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 109/147] 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 110/147] 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 111/147] 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 112/147] 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 113/147] 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 114/147] 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 115/147] 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 116/147] 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 117/147] 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 118/147] 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 119/147] 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 120/147] 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 121/147] 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 122/147] 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 123/147] 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 124/147] 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 125/147] 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 126/147] 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 127/147] 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 128/147] 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 129/147] 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 130/147] 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 131/147] 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 132/147] 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 133/147] 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 134/147] 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 135/147] 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 136/147] 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 137/147] 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 138/147] 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 139/147] 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 140/147] 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 141/147] 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 142/147] 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 143/147] 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 144/147] 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 145/147] 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 146/147] 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 147/147] 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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy