Skip to content

Releases: seleniumbase/SeleniumBase

Update the script that converts SeleniumIDE exports into SeleniumBase format

20 Sep 15:14
759469a
Compare
Choose a tag to compare

Update the script that converts SeleniumIDE exports into SeleniumBase format

The following is an example of a Katalon Recorder exported file (WebDriver + unittest format).
It is messy and has unnecessary lines of code to do the task that was recorded.

# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re

class Swag(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(30)
        self.base_url = "https://www.google.com/"
        self.verificationErrors = []
        self.accept_next_alert = True
    
    def test_swag(self):
        driver = self.driver
        driver.get("https://www.saucedemo.com/")
        driver.find_element_by_id("user-name").click()
        driver.find_element_by_id("user-name").clear()
        driver.find_element_by_id("user-name").send_keys("standard_user")
        driver.find_element_by_id("password").click()
        driver.find_element_by_id("password").clear()
        driver.find_element_by_id("password").send_keys("secret_sauce")
        driver.find_element_by_id("login-button").click()
        driver.find_element_by_xpath("//div[@id='inventory_container']/div/div/div[3]/button").click()
        driver.find_element_by_css_selector("path").click()
        driver.find_element_by_link_text("CHECKOUT").click()
        driver.find_element_by_id("first-name").click()
        driver.find_element_by_id("first-name").clear()
        driver.find_element_by_id("first-name").send_keys("a")
        driver.find_element_by_id("last-name").click()
        driver.find_element_by_id("last-name").clear()
        driver.find_element_by_id("last-name").send_keys("b")
        driver.find_element_by_id("postal-code").click()
        driver.find_element_by_id("postal-code").clear()
        driver.find_element_by_id("postal-code").send_keys("12345")
        driver.find_element_by_xpath("//input[@value='CONTINUE']").click()
        driver.find_element_by_link_text("FINISH").click()
    
    def is_element_present(self, how, what):
        try: self.driver.find_element(by=how, value=what)
        except NoSuchElementException as e: return False
        return True
    
    def is_alert_present(self):
        try: self.driver.switch_to_alert()
        except NoAlertPresentException as e: return False
        return True
    
    def close_alert_and_get_its_text(self):
        try:
            alert = self.driver.switch_to_alert()
            alert_text = alert.text
            if self.accept_next_alert:
                alert.accept()
            else:
                alert.dismiss()
            return alert_text
        finally: self.accept_next_alert = True
    
    def tearDown(self):
        self.driver.quit()
        self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
    unittest.main()

This can be improved on.


After running seleniumbase convert [FILE] on it, here is the new result:

# -*- coding: utf-8 -*-
from seleniumbase import BaseCase


class Swag(BaseCase):

    def test_swag(self):
        self.open('https://www.saucedemo.com/')
        self.type('#user-name', 'standard_user')
        self.type('#password', 'secret_sauce')
        self.click('#login-button')
        self.click("//div[@id='inventory_container']/div/div/div[3]/button")
        self.click('path')
        self.click("link=CHECKOUT")
        self.type('#first-name', 'a')
        self.type('#last-name', 'b')
        self.type('#postal-code', '12345')
        self.click("//input[@value='CONTINUE']")
        self.click("link=FINISH")

This is much cleaner than the original version.
It also uses the more reliable SeleniumBase methods.


To learn more about SeleniumBase console scripts, see:

See also: https://m.youtube.com/watch?v=Sjzq9kU5kOw

Update console scripts for the page-objects generator

18 Sep 22:00
5e7013d
Compare
Choose a tag to compare

Update console scripts for the page-objects generator

  • Update the console scripts tool for generating page objects
  • Also optimize colorama / speed up console scripts output
  • Also update the Python rich requirement to version 7.0.0

(See https://www.youtube.com/watch?v=Sjzq9kU5kOw to learn how the page-objects generator works)


Summary of the console scripts' tools for generating page objects:

  ** extract-objects **

  Usage:
           seleniumbase extract-objects [SELENIUMBASE_PYTHON_FILE]
           OR:    sbase extract-objects [SELENIUMBASE_PYTHON_FILE]
  Output:
           Creates page objects based on selectors found in a
           seleniumbase Python file and saves those objects to the
           "page_objects.py" file in the same folder as the tests.

  ** inject-objects **

  Usage:
           seleniumbase inject-objects [SELENIUMBASE_PYTHON_FILE]
           OR:    sbase inject-objects [SELENIUMBASE_PYTHON_FILE]
  Options:
           -c, --comments  (Add object selectors to the comments.)
                           (Default: No added comments.)
  Output:
           Takes the page objects found in the "page_objects.py"
           file and uses those to replace matching selectors in
           the selected seleniumbase Python file.

  ** objectify **

  Usage:
           seleniumbase objectify [SELENIUMBASE_PYTHON_FILE]
           OR:    sbase objectify [SELENIUMBASE_PYTHON_FILE]
  Options:
           -c, --comments  (Add object selectors to the comments.)
                           (Default: No added comments.)
  Output:
           A modified version of the file where the selectors
           have been replaced with variable names defined in
           "page_objects.py", supporting the Page Object Pattern.

           (seleniumbase "objectify" has the same outcome as
            combining "extract-objects" with "inject-objects")

  ** revert-objects **

  Usage:
           seleniumbase revert-objects [SELENIUMBASE_PYTHON_FILE]
           OR:    sbase revert-objects [SELENIUMBASE_PYTHON_FILE]
  Options:
           -c, --comments  (Keep existing comments for the lines.)
                           (Default: No comments are kept.)
  Output:
           Reverts the changes made by "seleniumbase objectify" or
           "seleniumbase inject-objects" when run against a
           seleniumbase Python file. Objects will get replaced by
           selectors stored in the "page_objects.py" file.

Update i18n translations. Also update "pygments".

17 Sep 18:31
292786c
Compare
Choose a tag to compare

Update i18n translations. Also update pygments.

  • Add "i18n" translations for self.assert_downloaded_file(file)
  • Update the pygments Python requirement to 2.7.1

Improve file downloads - disable automation prompts

15 Sep 21:25
c904940
Compare
Choose a tag to compare

Improve file downloads - disable automation prompts

  • Prevent download prompts from appearing (On Chrome, Firefox, and Edge)
  • Update the default timeout for asserting downloaded files
  • Update the Python requirements
    -- coverage==5.3
    -- rich==6.2.0

(Actually fixed in https://github.com/seleniumbase/SeleniumBase/releases/tag/v1.49.25)

Update Python dependencies

13 Sep 16:28
17754cd
Compare
Choose a tag to compare

Update Python dependencies

  • pytest==6.0.2;python_version>="3.5"
  • pygments==2.7.0;python_version>="3.5"

Update presentation metadata and more

11 Sep 23:04
46da62b
Compare
Choose a tag to compare

Update presentation metadata and more

  • Update metadata for generated presentations (Fixes mobile view)
  • Also verify URL has fully loaded before calling assert_title(TITLE)
  • Also update the rich requirement: rich==6.1.2

Add expected methods

10 Sep 19:17
5055312
Compare
Choose a tag to compare

Add expected methods

  • Add self.clear(SELECTOR)
  • Add self.set_text(SELECTOR, TEXT)
  • Update SeleniumBase translations
  • Also set the pymysql requirement to version 0.10.1

Reasoning for the duplicate methods:

  • Although most methods that type text already clear out the text field first, and although clearing out the text field can already be done with self.type(SELECTOR, ""), I'm adding the self.clear(SELECTOR) method to avoid confusion because developers will expect that method to exist.
  • Developers would also expect there to be a self.set_text(SELECTOR, TEXT) method (even though methods already exist that do the same thing) because there's a self.get_text(SELECTOR) method and a self.set_attribute(SELECTOR, ATTRIBUTE, VALUE) method, which sound similar.

Update the display of console scripts

10 Sep 00:52
18422d3
Compare
Choose a tag to compare

Update the display of console scripts

  • Make sure to initialize colorama before using it
  • Fix display incompatibilities on different platforms

Updates to the css-to-xpath selector converter

09 Sep 15:18
Compare
Choose a tag to compare

Updates to the css-to-xpath selector converter

"""
An implementation of :py:class:`cssselect.GenericTranslator` with
XPath output that more readily converts back to CSS selectors.
The simplified examples in https://devhints.io/xpath were used as a
reference here.
"""

Another update to the xpath-to-css converter

09 Sep 05:28
0bf5179
Compare
Choose a tag to compare

Another update to the xpath-to-css converter

  • Handle the case of // in the middle of an xpath selector

Example:

self.convert_xpath_to_css("//section//p/p//div")
'section p > p div'

See the xpath cheatsheet for more details: https://devhints.io/xpath