Skip to content
Open
54 changes: 47 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> {
Comment thread
jonhoo marked this conversation as resolved.
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,13 @@ 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())

match self.prop(prop).await? {
// Requesting `innerHTML` or `outerHTML` should normally return a string
Some(Json::String(contents)) => Ok(contents),
Some(res) => Err(error::CmdError::NotW3C(res)),
_ => Err(error::CmdError::NotW3C(Json::Null)),
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is the most appropriate error variant for the None case. Open to suggestions

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm fine with this!

}
}
}

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
Loading