#![cfg(feature = "cdp-backend")]
use async_trait::async_trait;
use crate::error::Result;
use crate::render::session::BrowserSessionLike;
pub mod state;
pub use state::RenderState;
#[async_trait]
pub trait RenderPhase: Send + Sync {
fn name(&self) -> &'static str;
async fn run(&self, session: &dyn BrowserSessionLike, state: &mut RenderState) -> Result<()>;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::render::session::tests::MockBrowserSession;
use parking_lot::Mutex;
use std::sync::Arc;
struct RecordingPhase {
name: &'static str,
runs: Arc<Mutex<Vec<&'static str>>>,
}
#[async_trait]
impl RenderPhase for RecordingPhase {
fn name(&self) -> &'static str {
self.name
}
async fn run(
&self,
_session: &dyn BrowserSessionLike,
_state: &mut RenderState,
) -> Result<()> {
self.runs.lock().push(self.name);
Ok(())
}
}
#[tokio::test]
async fn phases_run_in_order_with_mock_session() {
let runs: Arc<Mutex<Vec<&'static str>>> = Arc::new(Mutex::new(Vec::new()));
let phases: Vec<Box<dyn RenderPhase>> = vec![
Box::new(RecordingPhase {
name: "pre",
runs: runs.clone(),
}),
Box::new(RecordingPhase {
name: "post",
runs: runs.clone(),
}),
Box::new(RecordingPhase {
name: "settle",
runs: runs.clone(),
}),
];
let session = MockBrowserSession::new();
let mut state = RenderState::default();
for phase in &phases {
phase.run(&session, &mut state).await.unwrap();
}
assert_eq!(*runs.lock(), vec!["pre", "post", "settle"]);
}
}