Listen for console message with chromiumoxide

52 Views Asked by At

For the purpose of creating a test suite, I am using chromiumoxide and trying to execute some Javascript which contains console.assert statements and to listen for errors and any error messages. For example, the below executes a console.assert statement which throws an error. I would like to collect that error and it's message. In the docs I was able to find some types that seemed relevant to this task, eg CdpEvent, but I wasn't able to get any further than that.

use chromiumoxide::browser::{Browser, BrowserConfig};
use futures::StreamExt;
use tokio;

#[tokio::test]
async fn check_javascript() -> Result<(), Box<dyn std::error::Error>> {
    let (mut browser, mut handler) = Browser::launch(BrowserConfig::builder().build()?).await?;
    let handle = tokio::task::spawn(async move {
        while let Some(h) = handler.next().await {
            match h {
                Ok(_) => continue,
                Err(_) => break,
            }
        }
    });
    let page = browser.new_page("about:blank").await?;

    page.evaluate_expression("console.assert(2 === 3, { msg: 'numbers do not match' });").await?;
    
    browser.close().await?;
    handle.await?;
    Ok(())
}
1

There are 1 best solutions below

0
On BEST ANSWER

We need to enable breakpoints on all exceptions (that includes console.asserts), and attach an event listener for "paused in debugger" events. I was unable to find how to extract the message, though.

use std::error::Error;
use std::sync::Arc;

use chromiumoxide::browser::{Browser, BrowserConfig};
use chromiumoxide::cdp::js_protocol::debugger::*;
use futures::StreamExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
    let (mut browser, mut handler) = Browser::launch(BrowserConfig::builder().build()?).await?;
    let handle = tokio::task::spawn(async move {
        while let Some(h) = handler.next().await {
            match h {
                Ok(_) => continue,
                Err(_) => break,
            }
        }
    });
    let page = browser.new_page("about:blank").await?;
    page.enable_debugger().await?;

    let mut events = page.event_listener::<EventPaused>().await?;
    let events_handle = tokio::spawn({
        let page = page.clone();
        async move {
            while let Some(event) = events.next().await {
                if event.reason == PausedReason::Assert {
                    dbg!(event);
                }

                page.execute(ResumeParams::default()).await?;
            }

            Ok::<(), Box<dyn Error + Send + Sync>>(())
        }
    });

    page.execute(SetPauseOnExceptionsParams {
        state: SetPauseOnExceptionsState::All,
    })
    .await?;

    page.evaluate_expression("console.assert(2 === 3, { msg: 'numbers do not match' });")
        .await?;

    browser.close().await?;
    handle.await?;
    events_handle.await??;
    Ok(())
}