Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support querying numeric HTML properties from elements::Element::prop() #289

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
48 changes: 41 additions & 7 deletions src/elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,20 +223,54 @@ impl Element {
///
/// `Ok(None)` is returned if the element does not have the given property.
///
/// Boolean properties such as "checked" will be returned as the String "true" or "false".
///
/// See [13.3 Get Element Property](https://www.w3.org/TR/webdriver1/#get-element-property)
/// of the WebDriver standard.
///
/// [property]: https://www.ecma-international.org/ecma-262/5.1/#sec-8.12.1
///
/// Example:
///
/// ```
/// # use fantoccini::{ClientBuilder, error, Locator};
/// # use serde_json::{json, Number};
/// # async fn no_search_results() -> Result<(), error::CmdError> {
/// // Define capabilities of client...
/// # let capabilities = json!({})
/// # .as_object()
/// # .unwrap()
/// # .to_owned();
/// #
/// // Create client...
/// # let client = ClientBuilder::native()
/// # .capabilities(capabilities)
/// # .connect("http://127.0.0.1:4444")
/// # .await.unwrap();
/// #
/// // Perform some kind of search on the website that we don't expect any results from...
///
/// let search_matches = client
/// .wait()
/// .for_element(Locator::Css("#search-matches"))
/// .await?;
///
/// let num_search_matches = search_matches
/// .prop("childElementCount")
/// .await?
/// .expect("expected there to be some value for childElementCount property")
/// .as_u64()
/// .expect("expected childElementCount to be an integer value");
///
/// assert_eq!(num_search_matches, 0);
/// #
/// # Ok(())
/// # };
/// ```
#[cfg_attr(docsrs, doc(alias = "Get Element Property"))]
pub async fn prop(&self, prop: &str) -> Result<Option<String>, error::CmdError> {
pub async fn prop(&self, prop: &str) -> Result<Option<Json>, error::CmdError> {
let cmd = WebDriverCommand::GetElementProperty(self.element.clone(), prop.to_string());
match self.client.issue(cmd).await? {
Json::String(v) => Ok(Some(v)),
Json::Bool(b) => Ok(Some(b.to_string())),
Json::Null => Ok(None),
v => Err(error::CmdError::NotW3C(v)),
v => Ok(Some(v)),
}
}

Expand Down Expand Up @@ -336,7 +370,7 @@ impl Element {
#[cfg_attr(docsrs, doc(alias = "outerHTML"))]
pub async fn html(&self, inner: bool) -> Result<String, error::CmdError> {
let prop = if inner { "innerHTML" } else { "outerHTML" };
Ok(self.prop(prop).await?.unwrap())
Ok(self.prop(prop).await?.unwrap().to_string())
}
}

Expand Down
26 changes: 25 additions & 1 deletion tests/elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,32 @@ async fn element_prop(c: Client, port: u16) -> Result<(), error::CmdError> {
c.goto(&sample_url).await?;
let elem = c.find(Locator::Id("checkbox-option-1")).await?;
assert_eq!(elem.prop("id").await?.unwrap(), "checkbox-option-1");
assert_eq!(elem.prop("checked").await?.unwrap(), "false");

assert_eq!(
elem.prop("checked")
.await?
.expect(
"expected checked property to exist on HTML element with ID 'checkbox-option-1'"
)
.as_bool()
.expect("expected checked property to be a boolean value"),
false,
);

assert!(elem.attr("invalid-property").await?.is_none());

let elem = c.find(Locator::Id("content")).await?;
assert_eq!(
elem.prop("childElementCount")
.await?
.expect(
"expected childElementCount property to exist on HTML element with ID 'content'"
)
.as_u64()
.expect("expected childElementCount property to be an integer value"),
5,
);

Ok(())
}

Expand Down
4 changes: 2 additions & 2 deletions tests/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ async fn send_keys_and_clear_input_inner(c: Client, port: u16) -> Result<(), err
.await?
.expect("input should have value prop")
.as_str(),
"foobar"
Some("foobar")
);

e.clear().await?;
Expand All @@ -538,7 +538,7 @@ async fn send_keys_and_clear_input_inner(c: Client, port: u16) -> Result<(), err
.await?
.expect("input should have value prop")
.as_str(),
""
Some("")
);

let c = e.client();
Expand Down