WebDriverПодождать с тридцатьчетверкой? (Ржавый селен)

В Selenium для Python и Java можно дождаться изменения URL-адреса на определенное значение. Есть ли в крейте thirtyfour по ржавчине подобные функции?

Пример Java:

new WebDriverWait(driver, 20).Until(ExpectedConditions.UrlToBe("my-url"));

Прямо сейчас я написал вместо этого эту функцию ожидания:

use tokio::time;
use tokio::time::{Duration, Instant};
use anyhow::{bail, Context, Result};
use thirtyfour::{prelude::*, Key};

async fn wait_for_url(driver: &WebDriver, url: &str, timeout: &Duration) -> Result<()> {
    let start = Instant::now();
    loop {
        time::sleep(Duration::from_millis(500)).await;
        let current_url = driver.current_url().await?;
        if current_url.as_str() == url {
            return Ok(());
        }
        if &(time::Instant::now() - start) > timeout {
            bail!("Timeout waiting for {url}. Current url is {current_url}");
        }
    }
}

Вы проверяли документы?

JeffC 04.05.2024 16:33

@JeffC У тебя есть причина верить, что оно там? Я не смог его найти.

Chayim Friedman 04.05.2024 20:25

@JeffC Я просмотрел документацию, но я еще не очень привык к Rust и структуре документации по созданию.

thomasa88 05.05.2024 08:25
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
72
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я не смог найти в thirtyfour функцию, которая делает то, что вы хотите, и то, что вы сделали, по сути, является тем же, что делает версия Python «за капотом» (даже с тем же временем опроса), поэтому я думаю, что вам следует сделать именно это.

Вы можете сделать что-то подобное, чтобы воспроизвести поведение, которое вы получаете в Python/Java.

pub trait ExpectedDriverCondition<T> {
    async fn check(&self, driver: &WebDriver) -> WebDriverResult<T>;
}

pub struct WebDriverWait<'a> {
    handle: &'a WebDriver,
    timeout: Duration,
    sleep: Duration,
}

impl<'a> WebDriverWait<'a> {
    pub fn new(
        handle: &'a WebDriver,
        timeout: Option<Duration>,
        sleep: Option<Duration>,
    ) -> WebDriverWait {
        WebDriverWait {
            handle,
            timeout: match timeout {
                Some(timeout) => timeout,
                None => BASE_TIMEOUT,
            },
            sleep: match sleep {
                Some(sleep) => sleep,
                None => BASE_SLEEP,
            },
        }
    }

    pub async fn until<T, U>(&self, ec: &T) -> WebDriverResult<U>
    where
        T: ExpectedDriverCondition<U>,
    {
        let start = Instant::now();
        loop {
            time::sleep(self.sleep).await;

            let last_error = match ec.check(self.handle).await {
                Ok(result) => break Ok(result),
                Err(error) => error,
            };

            if &(time::Instant::now() - start) > &self.timeout {
                return Err(WebDriverError::Timeout(format!(
                    "Expected condition timed out.\n{last_error}"
                )));
            }
        }
    }
}

Для базовых таймаутов и сна вы можете использовать:

const BASE_TIMEOUT: Duration = Duration::from_secs(5);
const BASE_SLEEP: Duration = Duration::from_millis(500);

И тогда вы можете определить свои EC следующим образом:

pub mod expected_conditions {
    use super::{ExpectedCondition, ExpectedDriverCondition, Query};
    use thirtyfour::{
        error::{WebDriverError, WebDriverResult},
        prelude::{By, WebDriver, WebElement},
    };

    pub struct UrlToBe<'a>(pub &'a String);

    impl<'a> ExpectedDriverCondition<()> for UrlToBe<'a> {
        async fn check(&self, driver: &WebDriver) -> WebDriverResult<()> {
            let current_url = driver.current_url().await?;

            if current_url.as_str() == self.0 {
                return Ok(());
            } else {
                return Err(WebDriverError::CustomError("URLs don't match".into()));
            }
        }
    }
}

Чтобы создать ожидание, вы можете сделать:

WebDriverWait::new(driver, Some(time::Duration::from_secs(60 * 60)), None)
            .until(&expected_conditions::UrlToBe(&self.url))
            .await?;

Таким образом, вы можете создавать больше EC по мере необходимости.

Кроме того, в качестве краткого примечания: поскольку WebDriver и WebElement имеют общие черты, вам, вероятно, придется определить WebElementWait и WebDriverWait с разными EC для каждого из них.

Я новичок в Rust, поэтому не знаю, является ли это идиоматическим способом, но я использовал его для проекта, и до сих пор он работал отлично.

Надеюсь, поможет!

Другие вопросы по теме

Похожие вопросы

Сбой Python Selenium4 ChromeDriver в небезголовом режиме (работает в безголовом режиме): selenium.common.Exceptions.SessionNotCreatedException
SeleniumBase – невозможно выбрать значение из раскрывающегося списка, используя значение, текст, индекс
Как очистить таблицу в фрейм данных с помощью селена/запросов/красивого супа?
Как изменить пункт назначения с «Microsoft Print to pdf» на «сохранить как pdf» в опции предварительного просмотра печати с помощью Python Selenium?
Как щелкнуть значок печати с помощью селена Python?
Попытка использовать Python и Selenium, чтобы щелкнуть ползунок/флажок
Как нажать кнопку в раскрывающемся меню, используя селен в моем Java-приложении?
Является ли элемент присутствующего метода сломанным?
Как установить прокси с параметрами Selenium при подключении к Google-Chrome, созданному из командной строки
Запуск нескольких экземпляров селена приводит к ошибке соединения