mod operations;
mod time_value;
pub use time_value::TimeValue;
use std::sync::Arc;
use tracing::{debug, instrument};
use viewpoint_cdp::CdpConnection;
use viewpoint_js::js;
use crate::error::PageError;
use super::clock_script::CLOCK_MOCK_SCRIPT;
#[derive(Debug)]
pub struct Clock<'a> {
connection: &'a Arc<CdpConnection>,
session_id: &'a str,
installed: bool,
}
impl<'a> Clock<'a> {
pub(crate) fn new(connection: &'a Arc<CdpConnection>, session_id: &'a str) -> Self {
Self {
connection,
session_id,
installed: false,
}
}
#[instrument(level = "debug", skip(self))]
pub async fn install(&mut self) -> Result<(), PageError> {
self.inject_clock_library().await?;
self.evaluate(js! { window.__viewpointClock.install() })
.await?;
self.installed = true;
debug!("Clock installed");
Ok(())
}
#[instrument(level = "debug", skip(self))]
pub async fn uninstall(&mut self) -> Result<(), PageError> {
self.evaluate(js! { window.__viewpointClock && window.__viewpointClock.uninstall() })
.await?;
self.installed = false;
debug!("Clock uninstalled");
Ok(())
}
async fn inject_clock_library(&self) -> Result<(), PageError> {
self.evaluate(CLOCK_MOCK_SCRIPT).await?;
Ok(())
}
pub(super) async fn evaluate(&self, expression: &str) -> Result<(), PageError> {
use viewpoint_cdp::protocol::runtime::EvaluateParams;
let _: serde_json::Value = self
.connection
.send_command(
"Runtime.evaluate",
Some(EvaluateParams {
expression: expression.to_string(),
object_group: None,
include_command_line_api: None,
silent: None,
context_id: None,
return_by_value: Some(true),
await_promise: Some(false),
}),
Some(self.session_id),
)
.await?;
Ok(())
}
pub(super) async fn evaluate_value<T: serde::de::DeserializeOwned>(
&self,
expression: &str,
) -> Result<T, PageError> {
use viewpoint_cdp::protocol::runtime::EvaluateParams;
#[derive(serde::Deserialize)]
struct EvalResult {
result: ResultValue,
}
#[derive(serde::Deserialize)]
struct ResultValue {
value: serde_json::Value,
}
let result: EvalResult = self
.connection
.send_command(
"Runtime.evaluate",
Some(EvaluateParams {
expression: expression.to_string(),
object_group: None,
include_command_line_api: None,
silent: None,
context_id: None,
return_by_value: Some(true),
await_promise: Some(false),
}),
Some(self.session_id),
)
.await?;
serde_json::from_value(result.result.value)
.map_err(|e| PageError::EvaluationFailed(format!("Failed to deserialize result: {e}")))
}
}