Skip to content

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

Open
johnDeSilencio wants to merge 8 commits intojonhoo:mainfrom
johnDeSilencio:feature/support-numeric-properties
Open

Support querying numeric HTML properties from elements::Element::prop()#289
johnDeSilencio wants to merge 8 commits intojonhoo:mainfrom
johnDeSilencio:feature/support-numeric-properties

Conversation

@johnDeSilencio
Copy link

@johnDeSilencio johnDeSilencio commented Mar 2, 2025

Preface

Hi, Jon! Longtime fan of yours. Your Crust of Rust series was HUGE for me going from a beginner Rust developer to more intermediate (I've got a long way to go before the rank of "master" 😄). Thank you for all the amazing work you do and how you give back to the community!

Problem

I'm building my own personal portfolio website. One of the features of the application is a terminal emulator, letting you run fake commands on the website.

One of the commands is clear, which clears the screen and the history of all previous commands. To write a functional test for this feature, I'd like to be able to tell that my <div id="previous-commands> has no children which I check through the childElementCount property.

However, when I try use fantoccini::elements::Element::prop("childElementCount"), I get the following error:

...webdriver returned non-conforming response: Number(0)

2025-03-01-162717_hyprshot

Proposed Solution

It appears that the fantoccini::elements::Element::prop method currently only handles Strings, Bools, and Null values from serde_json and returns an error for everything else. This PR also supports matching serde_json::Number to support getting numeric properties like childElementCount.

Tests

I've also added another assert_eq!() to the element_test function. Let me know if you'd like me to add more test coverage or to find another way to support numeric HTML properties.

Functional Tests

I used this fork in the E2E tests for my website and now my functional tests pass:

image

Copy link
Owner

@jonhoo jonhoo left a comment

Choose a reason for hiding this comment

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

Thank you^2!

Arguably, prop should just return a serde_json::Value instead of coercing everything to a string. I'm honestly not quite sure why I made it be string only 🤔 I think it's because attribute can only return strings, and I guess I incorrectly assumed that the same would apply to prop. But property values can be "any ECMAScript language type". Given we're going to have to cut a breaking change for #285 anyway, let's maybe just go ahead and change prop to return serde_json::Value right now?

@johnDeSilencio
Copy link
Author

Hey, Jon!

I've made the change you suggested so that prop() now returns a serde_json::Value. I also added a doc comment example to the prop() method, but feel free to let me know if you think I should take it out or change it

@johnDeSilencio johnDeSilencio requested a review from jonhoo March 10, 2025 00:10
Copy link
Owner

@jonhoo jonhoo left a comment

Choose a reason for hiding this comment

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

That looks way better, thank you! One more question/change and then I think we're good!

src/elements.rs Outdated
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())
Copy link
Owner

Choose a reason for hiding this comment

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

I wonder if we should be a bit more principled here and instead of .unwrap().to_string() specifically match for Some(Json::String and error anything else?

@jonhoo
Copy link
Owner

jonhoo commented Mar 22, 2025

Some of the tests in CI seem unhappy 🤔

@jonhoo
Copy link
Owner

jonhoo commented Mar 22, 2025

Ah, some of the CI is just racy: fixed in #293. Merging in main should fix those.

@jonhoo jonhoo mentioned this pull request Mar 29, 2025
@jonhoo
Copy link
Owner

jonhoo commented Jun 14, 2025

@johnDeSilencio Gentle nudge on this — it's very close to getting over the line!

// 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
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
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!

@johnDeSilencio
Copy link
Author

johnDeSilencio commented Jul 10, 2025

The prodigal PR author returns 😅

I've merged up my branch with the most recent work on main. I've also made the change to the Element::html() method that you suggested. Wasn't sure exactly what variant of error::CmdError to return. Feel free to let me know if you think a different variant would be more appropriate!


As a side note, I want to apologize for taking so long to get back to you and to this PR. My personal life got kinda hectic, and I let this PR fall through the cracks. Totally my fault that this change missed v0.22. Thank you for your patience and the gentle reminder last month 😃

Moving forward, I've gotten my schedule mapped out pretty well in self-hosted CalDav calendars (shout-out to Stalwart), so if I do submit future PRs, the turn-around time should be significantly less than 4 months!

@johnDeSilencio johnDeSilencio requested a review from jonhoo July 14, 2025 05:41
Copy link
Owner

@jonhoo jonhoo left a comment

Choose a reason for hiding this comment

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

No worries at all — it happens to all of us from time to time!

As for releasing this, I think I'll then bundle this with #275 in a 0.23, but that does mean it may take a little while to get out :)

// 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
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!

@codecov
Copy link

codecov bot commented Jul 19, 2025

Codecov Report

❌ Patch coverage is 33.33333% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.52%. Comparing base (a2457c7) to head (5499fb2).

Files with missing lines Patch % Lines
src/elements.rs 33.33% 4 Missing ⚠️
Additional details and impacted files
Files with missing lines Coverage Δ
src/elements.rs 58.80% <33.33%> (+1.19%) ⬆️

... and 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@johnDeSilencio
Copy link
Author

No worries at all — it happens to all of us from time to time!

As for releasing this, I think I'll then bundle this with #275 in a 0.23, but that does mean it may take a little while to get out :)

Thanks for understanding! And yeah, no rush on the release either :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants