A `#[derive(Querier)]` derive macro for generating the boilerplate code needed to query a collection of elements by CSS selectors using [thirtyfour](https://docs.rs/thirtyfour/latest/thirtyfour/). **This library is highly experimental, and is initially developed for internal use.** # Example ```rust use thirtyfour::prelude::*; use thirtyfour_querier_derive::Querier; #[derive(Querier)] struct PageElements { #[querier(css = "#first")] first: WebElement, #[querier(css = "#second")] second: WebElement, #[querier(all, css = "div")] all_divs: WebElement, } let page_elements = PageElements::query(&driver).await.unwrap(); ``` # Dependencies The `impl` blocks generated by the macro uses `futures` and `thirtyfour` libraries. Since the a proc macro crate can't export items, these dependencies has to be added manually by the user. This may change in future versions. # Details The `#[derive(Querier)]` macro generates an `impl` block containing an async constructor for the structure named `query`, with the following signature. ```rust pub async fn query(driver: &T) -> Result; ``` - Only structs with named fields are supported. - By default, the queries are performed without waiting. Use `#[querier(wait = num_seconds)]` to add an explicit wait. - Each field of the structure must have a `#[querier(...)]` attribute. The content of the attribute must match the type of the field in this way: | Attribute | Field Type | |------------------------------------------|---------------------------| | `#[querier(css = "...")]` | `WebElement` | | `#[querier(maybe, css = "...")]` | `Option` | | `#[querier(all, css = "...")]` | `Vec` | | `#[querier(nested, css = "...")]` | `(WebElement, Q)` | | `#[querier(maybe, nested, css = "...")]` | `Option<(WebElement, Q)>` | | `#[querier(all, nested, css = "...")]` | `Vec<(WebElement, Q)>` | The type `Q` in the table can be any type that also has `#[derive(Querier)]`. # Full Example ```rust use thirtyfour_querier_derive::Querier; use thirtyfour::prelude::*; const HTML: &str = r#" data:text/html;charset=utf-8,
"#; #[derive(Debug, Querier)] #[allow(dead_code)] struct Page { #[querier(css = "#single-element")] single_elem: WebElement, #[querier(wait = 5, css = "#single-element")] single_elem_with_wait: WebElement, #[querier(maybe, css = "#missing-element")] missing_elem: Option, #[querier(all, css = ".many-elements")] many_elems: Vec, #[querier(all, nested, css = ".many-elements")] many_elems_nested: Vec<(WebElement, SubElement)>, } #[derive(Debug, Querier)] struct SubElement { #[querier(all, css = ".nested-element")] nested_elems: Vec, } #[tokio::main] async fn main() { let driver = WebDriver::new("http://localhost:9100", DesiredCapabilities::chrome()) .await .unwrap(); // Load the html string driver.get(HTML).await.unwrap(); // Query the elements specified in `struct Page` let page = Page::query(&driver).await.unwrap(); // Count number of `.nested-element` within `many-element`s (should be 4) let mut nest_elem_count = 0; for (_, elem) in page.many_elems_nested { nest_elem_count += elem.nested_elems.len(); } assert_eq!( nest_elem_count, 4, "Number of nested-element within many-element is 4" ); } ```