Coder Social home page Coder Social logo

Comments (7)

stevepryde avatar stevepryde commented on July 21, 2024 2

Added in v0.27.2 🙂

from thirtyfour.

stevepryde avatar stevepryde commented on July 21, 2024 1

Awesome. I have some more changes I need to make to it, to make it more robust. For example currently it assumes there are no tabs already open, and that handles[1] is the new tab. Also I'd like to add a doctest for it.

I think it probably also needs a warning that this will temporarily switch the context to another tab so any selenium operations executed during this time will point at the new tab and not the existing one (in case someone tries using threads or join! etc).

from thirtyfour.

stevepryde avatar stevepryde commented on July 21, 2024 1

There isn't really a good use case for accessing the same WebDriver in multiple threads. Potentially if you were just reading elements in parallel from a static page that might be ok, but I'd consider that an edge case. So probably this doesn't need a warning for that.

from thirtyfour.

stevepryde avatar stevepryde commented on July 21, 2024

I agree that this would be a pretty handy thing to have. I think the issues you mentioned could be similar the issues I had getting the ElementQuery and ElementWaiter closures to work, so maybe there could be a nice solution.

from thirtyfour.

stevepryde avatar stevepryde commented on July 21, 2024

@bcpeinhardt Thanks to your code above I was able to implement this in WebDriverCommands.

The trick to getting the closure working seemed to be requiring a Send trait bound on all of the generic params like this:

async fn in_new_tab<F, Fut, T>(&self, f: F) -> WebDriverResult<T>
    where
        F: FnOnce() -> Fut + Send,
        Fut: Future<Output = WebDriverResult<T>> + Send,
        T: Send,

See the in_new_tab branch. I was able to do the following in a quick test (not included in the branch):

let t = driver.in_new_tab(|| async {
    driver.get("https://www.google.com").await?;
    sleep(Duration::from_secs(5)).await;
    driver.title().await
}).await?;
println!("Window title: {}", t);

Of course you can return Ok(()) from the async block as well, but this was to demonstrate passing a value back out.
The sleep was just so I could confirm that it works correctly.

Let me know if this works for you, and if so I can merge it in 🙂

from thirtyfour.

bcpeinhardt avatar bcpeinhardt commented on July 21, 2024

TOML

[package]
name = "testing_in_new_tab_web_command"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
thirtyfour = { git = "https://github.com/stevepryde/thirtyfour.git", branch = "in_new_tab"}
tokio = "1.12.0"

Code

use thirtyfour::prelude::*;
use tokio;

#[tokio::main]
async fn main() -> WebDriverResult<()> {
    let caps = DesiredCapabilities::firefox();
    let driver = WebDriver::new("http://localhost:4444/wd/hub", &caps).await?;

    let stars_count = driver
        .in_new_tab(|| async {
            driver
                .get("https://github.com/stevepryde/thirtyfour")
                .await?;
            let stars = driver
                .query(By::XPath("//a[@class=\"social-count js-social-count\"]"))
                .first()
                .await?
                .text()
                .await?;
            Ok(stars)
        })
        .await?;
    println!(
        "Thirtyfour has {} stars on github, a number which will likely grow.",
        stars_count
    );

    driver.quit().await?;

    Ok(())
}

Works like a charm!!!! This is great, thank you!!!!!

from thirtyfour.

bcpeinhardt avatar bcpeinhardt commented on July 21, 2024

Yup! Out of curiosity, what is the use case for accessing the same &WebDriver in multiple threads? In a sense, the WebDriver commands "mutate" the browser when they click a link or navigate to a new url etc, even though they have an &self in their function signatures. Combining that with the conversation we had before, where you mentioned that Selenium calls from the same driver are returned FIFO rather than asynchronously, I'm not sure what the use case for accessing the same &WebDriver across threads is.
It would be interesting if there were a way to specify setup up and tear down as blocking operations for entry and exit from a thread. In this case one would want Wake -> Switch to named handle (can drivers store named handles?) -> Make Progress -> Switch to previous handle -> Yield. I suspect a setup like this could be achieved with some funky nested threading.

from thirtyfour.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.