Skip to content

page.find_element hangs on invisible element #292

@silenthill7

Description

@silenthill7

For replicating the issue, the element in the browser can be found with querySelector but it returns false when checkVisibility() is called on it (document.querySelector('.exampleButton').checkVisibility(); returns false)

page.find_element (I'm guessing by design from what I've read on issues before) endlessly waits for the element to become visible

Is there a way to timeout the find_element function or is there another function that does the same but doesn't wait for the element to become visible?

I have made my own function which is supposed to wait for the element to become visible except it has a timeout option, this can't be implemented though because find_element already endlessly waits for the element to become visible. Here is the function I made, similar to another one that was made in a separate issue:

#[async_trait]
pub trait PageExtensions {
    async fn wait_for_visible_element(
        &self,
        selector: &str,
        timeout_millis: usize,
    ) -> Option<Element>;
}

#[async_trait]
impl PageExtensions for Page {
    async fn wait_for_visible_element(
        &self,
        selector: &str,
        timeout_millis: usize,
    ) -> Option<Element> {
        let mut time = 0;
        loop {
            match self.find_element(selector).await {
                Ok(e) => {
                    // Check visibility
                    let Ok(res) = e
                        .call_js_fn("function() { return this.checkVisibility(); }", false)
                        .await
                    else {
                        continue;
                    };
                    if !res
                        .result
                        .r#type
                        .eq(&chromiumoxide::cdp::js_protocol::runtime::RemoteObjectType::Boolean)
                    {
                        continue;
                    }
                    if res.result.value.and_then(|v| v.as_bool()) != Some(true) {
                        continue;
                    }
                    return Some(e);
                }
                Err(_) => {
                    std::thread::sleep(Duration::from_millis(50));
                    time += 50;
                    if time >= timeout_millis {
                        // Element doesn't exist or didn't become visible
                        return None;
                    }
                }
            }
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug:1-repro-availableBug reproduction is availablekind:bugAn unexpected problem or behaviourtopic:interfaceRelated to the interface exposed to the user

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions