Skip to content

Releases: seleniumbase/SeleniumBase

Change how headless Firefox runs on Linux

01 Sep 07:52
04235ab
Compare
Choose a tag to compare

Change how headless Firefox runs on Linux

  • This reverts a change made in version 1.65.0.
    -- The old way (and now) may need Xvfb installed.

The one with: "All Your Base Are Belong To Us"

01 Sep 05:57
03b8fba
Compare
Choose a tag to compare

The one with: "All Your Base Are Belong To Us"

  • Add set_text_content() for updating text on any website:
    -- See https://youtu.be/1s-Tj65AKZA for the demo video!
    -- (SeleniumBase/examples/hack_the_planet.py)
  • Improve the Python APIs for IntroJS website tours.
  • Add a pytest --xvfb option to run tests using an Xvfb virtual display:
    -- Uses a virtual display without using a browser's built-in headless mode.
  • Add method: get_value() to get the value from an input field.
  • Add an arg to decide if methods should scroll automatically.
  • Update Python dependencies:
    -- typing-extensions>=3.10.0.2
    -- pluggy==0.13.1;python_version<"3.6"
    -- pluggy==1.0.0;python_version>="3.6"
    -- pytest==6.2.5;python_version>="3.6"
    -- traitlets==5.1.0;python_version>="3.7"
    -- ipython==7.27.0;python_version>="3.7"
    -- platformdirs==2.3.0;python_version>="3.6"
    -- rich==10.9.0;python_version>="3.6"

Fix & update the automatic ChromeDriver repair/upgrade script

24 Aug 19:31
a244324
Compare
Choose a tag to compare

Fix & update the automatic ChromeDriver repair/upgrade script

  • Fix the automatic chromedriver repair/upgrade script:
    -- A folder might need to be created first in some scenarios.
  • Auto-upgrade chromedriver on "Chrome version must be between":
    -- Previously, only on "This version of ChromeDriver only supports".
    -- (This repair only happens on Mac/Win and NON-headless Linux runs.)
  • Refresh Python dependencies:
    -- cryptography==3.4.8;python_version>="3.6"
  • Update a test created by sbase mkdir DIR.

Dialog Boxes and more

24 Aug 04:40
2cad947
Compare
Choose a tag to compare

Dialog Boxes and more

  • Add New Feature: SeleniumBase Dialog Boxes.
  • Add custom timeout option for self.assert_no_404_errors().
  • Add a default Chromium option for disabling notifications.
  • Auto-repair ChromeDriver to sync with Chrome (Mac/Win only).
  • Add self.is_attribute_present(selector, attribute, value=None).
  • Update the error message for fixing a SeleniumBase install.
  • Add self.wait_for_attribute_not_present(selector, attribute, value=None).
  • Add self.assert_attribute_not_present(selector, attribute, value=None).
  • Add keyboard shortcuts to MasterQA mode.
  • Add "--slowmo" as an alternative to "--slow-mode".
  • Add "--screenshot" as an alternative to "--save-screenshot".
  • Update the favicon link in generated reports.
  • Add additional shortcuts for partial_link_text selectors.
  • Update methods for getting the link text from selectors.
  • Add "&" as a shortcut for a single-syllable "name" selector.
  • Update Python dependencies.

🛂 Dialog Boxes 🛂

SeleniumBase Dialog Boxes let your users provide input in the middle of automation scripts.

  • This feature utilizes the jquery-confirm library.
  • A Python API is used to call the JavaScript API.

SeleniumBase

↕️ (Example: dialog_box_tour.py) ↕️

SeleniumBase

Here's how to run that example:

cd examples/dialog_boxes
pytest test_dialog_boxes.py

Here's a code snippet from that:

self.open("https://xkcd.com/1920/")
skip_button = ["SKIP", "red"]  # Can be a [text, color] list or tuple.
buttons = ["Fencing", "Football", "Metaball", "Go/Chess", skip_button]
message = "Choose a sport:"
choice = self.get_jqc_button_input(message, buttons)
if choice == "Fencing":
    self.open("https://xkcd.com/1424/")
  • You can create forms that include buttons and input fields.

Here's a simple form with only buttons as input:

choice = self.get_jqc_button_input("Ready?", ["YES", "NO"])
print(choice)  # This prints "YES" or "NO"

# You may want to customize the color of buttons:
buttons = [("YES", "green"), ("NO", "red")]
choice = self.get_jqc_button_input("Ready?", buttons)

Here's a simple form with an input field:

text = self.get_jqc_text_input("Enter text:", ["Search"])
print(text)  # This prints the text entered

This form has an input field and buttons:

message = "Type your name and choose a language:"
buttons = ["Python", "JavaScript"]
text, choice = self.get_jqc_form_inputs(message, buttons)
print("Your name is: %s" % text)
print("You picked %s!" % choice)

You can customize options if you want:

# Themes: bootstrap, modern, material, supervan, light, dark, seamless
options = [("theme", "modern"), ("width", "50%")]
self.get_jqc_text_input("You Won!", ["OK"], options)

Default options can be set with set_jqc_theme():

self.set_jqc_theme("light", color="green", width="38%")

# To reset jqc theme settings to factory defaults:
self.reset_jqc_theme()

All methods for Dialog Boxes:

self.get_jqc_button_input(message, buttons, options=None)

self.get_jqc_text_input(message, button=None, options=None)

self.get_jqc_form_inputs(message, buttons, options=None)

self.set_jqc_theme(theme, color=None, width=None)

self.reset_jqc_theme()

self.activate_jquery_confirm()  # Automatic for jqc methods

Detailed method summaries for Dialog Boxes:

self.get_jqc_button_input(message, buttons, options=None)
"""
Pop up a jquery-confirm box and return the text of the button clicked.
If running in headless mode, the last button text is returned.
@Params
message: The message to display in the jquery-confirm dialog.
buttons: A list of tuples for text and color.
    Example: [("Yes!", "green"), ("No!", "red")]
    Available colors: blue, green, red, orange, purple, default, dark.
    A simple text string also works: "My Button". (Uses default color.)
options: A list of tuples for options to set.
    Example: [("theme", "bootstrap"), ("width", "450px")]
    Available theme options: bootstrap, modern, material, supervan,
                             light, dark, and seamless.
    Available colors: (For the BORDER color, NOT the button color.)
        "blue", "default", "green", "red", "purple", "orange", "dark".
    Example option for changing the border color: ("color", "default")
    Width can be set using percent or pixels. Eg: "36.0%", "450px".
"""

self.get_jqc_text_input(message, button=None, options=None)
"""
Pop up a jquery-confirm box and return the text submitted by the input.
If running in headless mode, the text returned is "" by default.
@Params
message: The message to display in the jquery-confirm dialog.
button: A 2-item list or tuple for text and color. Or just the text.
    Example: ["Submit", "blue"] -> (default button if not specified)
    Available colors: blue, green, red, orange, purple, default, dark.
    A simple text string also works: "My Button". (Uses default color.)
options: A list of tuples for options to set.
    Example: [("theme", "bootstrap"), ("width", "450px")]
    Available theme options: bootstrap, modern, material, supervan,
                             light, dark, and seamless.
    Available colors: (For the BORDER color, NOT the button color.)
        "blue", "default", "green", "red", "purple", "orange", "dark".
    Example option for changing the border color: ("color", "default")
    Width can be set using percent or pixels. Eg: "36.0%", "450px".
"""

self.get_jqc_form_inputs(message, buttons, options=None)
"""
Pop up a jquery-confirm box and return the input/button texts as tuple.
If running in headless mode, returns the ("", buttons[-1][0]) tuple.
@Params
message: The message to display in the jquery-confirm dialog.
buttons: A list of tuples for text and color.
    Example: [("Yes!", "green"), ("No!", "red")]
    Available colors: blue, green, red, orange, purple, default, dark.
    A simple text string also works: "My Button". (Uses default color.)
options: A list of tuples for options to set.
    Example: [("theme", "bootstrap"), ("width", "450px")]
    Available theme options: bootstrap, modern, material, supervan,
                             light, dark, and seamless.
    Available colors: (For the BORDER color, NOT the button color.)
        "blue", "default", "green", "red", "purple", "orange", "dark".
    Example option for changing the border color: ("color", "default")
    Width can be set using percent or pixels. Eg: "36.0%", "450px".
"""

self.set_jqc_theme(theme, color=None, width=None)
""" Sets the default jquery-confirm theme and width (optional).
Available themes: "bootstrap", "modern", "material", "supervan",
                  "light", "dark", and "seamless".
Available colors: (This sets the BORDER color, NOT the button color.)
    "blue", "default", "green", "red", "purple", "orange", "dark".
Width can be set using percent or pixels. Eg: "36.0%", "450px".
"""

self.reset_jqc_theme()
""" Resets the jqc theme settings to factory defaults. """

self.activate_jquery_confirm()  # Automatic for jqc methods
""" See https://craftpip.github.io/jquery-confirm/ for usage. """

✅ 🛂 Automated/Manual Hybrid Mode (MasterQA)

MasterQA uses SeleniumBase Dialog Boxes to speed up manual testing by having automation perform all the browser actions while the manual tester handles validation. See the MasterQA GitHub page for examples.

Update the instant page-object-generator tool

11 Aug 15:55
03e2e9a
Compare
Choose a tag to compare

Update the instant page-object-generator tool

This tool is used to replace selectors in tests with page objects.
Here's an example of how it works on this existing file: (https://github.com/seleniumbase/SeleniumBase/blob/master/examples/basic_test.py)

from seleniumbase import BaseCase

class MyTestClass(BaseCase):
    def test_basics(self):
        self.open("https://store.xkcd.com/search")
        self.type('input[name="q"]', "xkcd book\n")
        self.assert_text("xkcd book", "div.results")
        self.open("https://xkcd.com/353/")
        self.click('a[rel="license"]')
        self.go_back()
        self.click_link("About")
        self.click_link("comic #249")
        self.assert_element('img[alt*="Chess"]')

Now run sbase objectify basic_test.py:

sbase objectify basic_test.py 
>>> ["page_objects.py"] was created!
>>> ["page_objects.py"] was updated!
>>> ["basic_test.py"] was updated!

Output:
Here's what the page_objects.py file now looks like:

class Page(object):
    html = "html"
    css_1 = 'input[name="q"]'
    css_2 = "div.results"
    css_3 = 'a[rel="license"]'
    css_4 = 'img[alt*="Chess"]'

Here's what basic_test.py now looks like:

from .page_objects import Page
from seleniumbase import BaseCase

class MyTestClass(BaseCase):
    def test_basics(self):
        self.open("https://store.xkcd.com/search")
        self.type(Page.css_1, "xkcd book\n")
        self.assert_text("xkcd book", Page.css_2)
        self.open("https://xkcd.com/353/")
        self.click(Page.css_3)
        self.go_back()
        self.click_link("About")
        self.click_link("comic #249")
        self.assert_element(Page.css_4)

If the page_objects.py file already exists, it will get updated with new selectors when running sbase objectify FILE or sbase extract-objects FILE (assuming new selectors are found).

For more information on SeleniumBase console scripts, see: https://seleniumbase.io/seleniumbase/console_scripts/ReadMe/

Updates and refactoring

09 Aug 22:43
62300a4
Compare
Choose a tag to compare

Updates and refactoring

  • Improve and refactor sbase print FILE:
    -- Printing Markdown files is improved (Will use fancy formatting if not numbered).
    -- Older versions of Python will now print files (but not with color or line numbers).
  • Update output of sbase mkfile FILE.py:
    -- This is used to easily create a new test file:
from seleniumbase import BaseCase


class MyTestClass(BaseCase):
    def test_base(self):
        self.open("data:text/html,<p>Hello<br><input></p>")
        self.type("input", "Goodbye")  # selector, text
        self.click("body p")  # selector
        self.assert_element("html > body")  # selector
        self.assert_text("Hello", "body p")  # text, selector
  • Fix self.assert_raises():
    -- (The earlier version called self.assertRaises() without a return.)
  • Add self.assert_in() and self.assert_not_in():
    -- (These are duplicates for self.assertIn() and self.assertNotIn().)
  • Refresh Python dependencies:
    -- pip>=21.2.3;python_version>="3.6"
    -- wheel>=0.37.0
    -- virtualenv>=20.7.1

Update driver installation options

06 Aug 00:55
92e49fe
Compare
Choose a tag to compare

Update driver installation options

  • Add a shortcut that installs one version below the latest chromedriver:
    -- sbase install chromedriver latest-1
    -- (because sometimes the latest chromedriver gets ahead of the latest version of Chrome)
  • Add a script that installs the chromedriver version that matches the installed Chrome:
    -- (https://github.com/seleniumbase/SeleniumBase/blob/master/examples/upgrade_chromedriver.py)
  • Refresh Python dependencies:
    -- ipython==7.26.0;python_version>="3.7"
    -- rich==10.7.0;python_version>="3.6"

Update Python dependencies

31 Jul 16:09
bfbefca
Compare
Choose a tag to compare

Update Python dependencies

  • pip>=21.2.2;python_version>="3.6"
  • charset-normalizer==2.0.4;python_version>="3.6"
  • virtualenv>=20.7.0

Fix issue with the ":contains()" selector and Demo Mode

30 Jul 01:35
1c31605
Compare
Choose a tag to compare

Fix issue with the :contains() selector and Demo Mode

  • Fix issue causing Demo Mode highlighting to not work when using a multi-syllable :contains() selector.

Reliability and other improvements

29 Jul 15:52
67f6293
Compare
Choose a tag to compare

Reliability and other improvements

  • Improve reliability of self.click_nth_visible_element(...)
  • Improve reliability of self.set_value(...)
  • Keep self._print(...) from printing during multithreaded runs:
    -- (Prevent garbled text on the console output)
  • Update Python dependencies:
    -- pip>=21.2.1;python_version>="3.6"
    -- platformdirs==2.2.0;python_version>="3.6"