#web-driver #selenium #chromedriver #automation #geckodriver

thirtyfour_sync

Thirtyfour is a Selenium / WebDriver library for Rust, for automated website UI testing. This crate is the synchronous version only. For async, see the thirtyfour crate instead.

16 releases (8 breaking)

0.27.1 Jan 7, 2022
0.27.0 Nov 7, 2021
0.25.0 Jun 20, 2021
0.23.0 Mar 27, 2021
0.20.0 Nov 30, 2020

#240 in HTTP client

Download history 317/week @ 2023-12-11 205/week @ 2023-12-18 127/week @ 2023-12-25 1777/week @ 2024-01-01 1913/week @ 2024-01-08 1845/week @ 2024-01-15 2845/week @ 2024-01-22 763/week @ 2024-01-29 2590/week @ 2024-02-05 1780/week @ 2024-02-12 2138/week @ 2024-02-19 2317/week @ 2024-02-26 1583/week @ 2024-03-04 906/week @ 2024-03-11 346/week @ 2024-03-18 745/week @ 2024-03-25

4,914 downloads per month
Used in 4 crates

MIT/Apache

225KB
2.5K SLoC

Crates.io docs.rs Build Status

Thirtyfour is a Selenium / WebDriver library for Rust, for automated website UI testing.

It supports the full W3C WebDriver spec. Tested with Chrome and Firefox although any W3C-compatible WebDriver should work.

This crate provides a synchronous (i.e. not async) interface for thirtyfour. For async, see the thirtyfour crate instead.

Status: Looking for maintainer

maintenance-status

Upcoming changes to the thirtyfour project will cause it to diverge from this synchronous version. As such this project will no longer be actively maintained. Apologies for any inconvenience. If you need more information or if you're interested in taking over this project, please get in touch.

Features

  • All W3C WebDriver and WebElement methods supported
  • Create new browser session directly via WebDriver (e.g. chromedriver)
  • Create new browser session via Selenium Standalone or Grid
  • Automatically close browser session on drop
  • Find elements (via all common selectors e.g. Id, Class, CSS, Tag, XPath)
  • Send keys to elements, including key-combinations
  • Execute Javascript
  • Action Chains
  • Get and set cookies
  • Switch to frame/window/element/alert
  • Shadow DOM support
  • Alert support
  • Capture / Save screenshot of browser or individual element as PNG
  • Chrome DevTools Protocol support

Why 'thirtyfour' ?

It is named after the atomic number for the Selenium chemical element (Se).

Examples

The example assumes you have a WebDriver running at localhost:4444.

You can use chromedriver directly by downloading the chromedriver that matches your Chrome version, from here: https://chromedriver.chromium.org/downloads

Then run it like this:

chromedriver --port=4444

Example:

To run this example:

cargo run --example sync
use thirtyfour_sync::prelude::*;

fn main() -> WebDriverResult<()> {
     let caps = DesiredCapabilities::chrome();
     let driver = WebDriver::new("http://localhost:4444", &caps)?;

     // Navigate to https://wikipedia.org.
     driver.get("https://wikipedia.org")?;
     let elem_form = driver.find_element(By::Id("search-form"))?;

     // Find element from element.
     let elem_text = elem_form.find_element(By::Id("searchInput"))?;

     // Type in the search terms.
     elem_text.send_keys("selenium")?;

     // Click the search button.
     let elem_button = elem_form.find_element(By::Css("button[type='submit']"))?;
     elem_button.click()?;

     // Look for header to implicitly wait for the page to load.
     driver.find_element(By::ClassName("firstHeading"))?;
     assert_eq!(driver.title()?, "Selenium - Wikipedia");
    
     // Close the browser.
     driver.quit()?;

     Ok(())
}

Advanced element queries

ElementQuery

The WebDriver::query() and WebElement::query() methods return an ElementQuery struct.

Using ElementQuery, you can do things like:

let elem_text =
    driver.query(By::Css("match.this")).or(By::Id("orThis")).first()?;

This will execute both queries once per poll iteration and return the first one that matches. You can also filter on one or both query branches like this:

driver.query(By::Css("branch.one")).with_text("testing")
    .or(By::Id("branchTwo")).with_class("search").and_not_enabled()
    .first()?;

The all() method will return an empty Vec if no elements were found. In order to return an error in this scenario, use the all_required() method instead.

ElementQuery also allows the use of custom predicates that take a &WebElement argument and return a WebDriverResult<bool>.

As noted above, the query() method is also available on WebElement structs as well for querying elements in relation to a particular element in the DOM.

ElementWaiter

The WebElement::wait_until() method returns an ElementWaiter struct.

Using ElementWaiter you can do things like this:

elem.wait_until().displayed()?;
// You can optionally provide a nicer error message like this.
elem.wait_until().error("Timed out waiting for element to disappear").not_displayed()?;

elem.wait_until().enabled()?;
elem.wait_until().clickable()?;

And so on. See the ElementWaiter docs for the full list of predicates available.

ElementWaiter also allows the use of custom predicates that take a &WebElement argument and return a WebDriverResult<bool>.

A range of pre-defined predicates are also supplied for convenience in the thirtyfour_sync::query::conditions module.

use thirtyfour_sync::query::conditions;

elem.wait_until().conditions(vec![
    conditions::element_is_displayed(true),
    conditions::element_is_clickable(true)
])?;

These predicates (or your own) can also be supplied as filters to ElementQuery.

Running the tests for thirtyfour_sync, including doctests

You generally only need to run the tests if you plan on contributing to the development of thirtyfour_sync. If you just want to use the crate in your own project, you can skip this section.

Just like the examples above, the tests in this crate require a running instance of Selenium at http://localhost:4444.

The tests also require a small web app called thirtyfour_testapp that was purpose-built for testing the thirtyfour crate.

This can be run using docker and docker-compose.

To install docker, see https://docs.docker.com/install/ (follow the SERVER section if you're on Linux, then look for the Community Edition)

To install docker-compose, see https://docs.docker.com/compose/install/

Once you have docker-compose installed, you can start the required containers, as follows:

docker-compose up -d --build

Then, to run the tests:

cargo test -- --test-threads=1

We need to limit the tests to a single thread because the selenium server only supports 1 browser instance at a time. (You can increase this limit in the docker-compose.yml file if you want. Remember to restart the containers afterwards)

If you need to restart the docker containers:

docker-compose restart 

And finally, to remove them:

docker-compose down

LICENSE

This work is dual-licensed under MIT or Apache 2.0. You can choose either license if you use this work.

See the NOTICE file for more details.

SPDX-License-Identifier: MIT OR Apache-2.0

Dependencies

~10–28MB
~436K SLoC