use serde::{Deserialize, Serialize};
use crate::cdp::Cdp;
use crate::cdp::command::{CdpCommand, Empty};
use crate::cdp::ids::{BackendNodeId, NodeId, RemoteObjectId};
use crate::error::WebDriverResult;
#[derive(Debug, Clone, Default, Serialize)]
pub struct Enable;
impl CdpCommand for Enable {
const METHOD: &'static str = "DOM.enable";
type Returns = Empty;
}
#[derive(Debug, Clone, Default, Serialize)]
pub struct Disable;
impl CdpCommand for Disable {
const METHOD: &'static str = "DOM.disable";
type Returns = Empty;
}
#[derive(Debug, Clone, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GetDocument {
#[serde(skip_serializing_if = "Option::is_none")]
pub depth: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pierce: Option<bool>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DomNode {
pub node_id: NodeId,
pub backend_node_id: BackendNodeId,
pub node_type: u32,
pub node_name: String,
pub local_name: String,
#[serde(default)]
pub node_value: String,
pub child_node_count: Option<u32>,
pub children: Option<Vec<DomNode>>,
pub attributes: Option<Vec<String>>,
#[serde(rename = "documentURL")]
pub document_url: Option<String>,
#[serde(rename = "baseURL")]
pub base_url: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct GetDocumentResult {
pub root: DomNode,
}
impl CdpCommand for GetDocument {
const METHOD: &'static str = "DOM.getDocument";
type Returns = GetDocumentResult;
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct QuerySelector {
pub node_id: NodeId,
pub selector: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct QuerySelectorResult {
pub node_id: NodeId,
}
impl CdpCommand for QuerySelector {
const METHOD: &'static str = "DOM.querySelector";
type Returns = QuerySelectorResult;
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct QuerySelectorAll {
pub node_id: NodeId,
pub selector: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct QuerySelectorAllResult {
pub node_ids: Vec<NodeId>,
}
impl CdpCommand for QuerySelectorAll {
const METHOD: &'static str = "DOM.querySelectorAll";
type Returns = QuerySelectorAllResult;
}
#[derive(Debug, Clone, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DescribeNode {
#[serde(skip_serializing_if = "Option::is_none")]
pub node_id: Option<NodeId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub backend_node_id: Option<BackendNodeId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub object_id: Option<RemoteObjectId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub depth: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pierce: Option<bool>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct DescribeNodeResult {
pub node: DomNode,
}
impl CdpCommand for DescribeNode {
const METHOD: &'static str = "DOM.describeNode";
type Returns = DescribeNodeResult;
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RequestNode {
pub object_id: RemoteObjectId,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RequestNodeResult {
pub node_id: NodeId,
}
impl CdpCommand for RequestNode {
const METHOD: &'static str = "DOM.requestNode";
type Returns = RequestNodeResult;
}
#[derive(Debug, Clone, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ResolveNode {
#[serde(skip_serializing_if = "Option::is_none")]
pub node_id: Option<NodeId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub backend_node_id: Option<BackendNodeId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub object_group: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub execution_context_id: Option<crate::cdp::ids::ExecutionContextId>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct ResolveNodeResult {
pub object: super::runtime::RemoteObject,
}
impl CdpCommand for ResolveNode {
const METHOD: &'static str = "DOM.resolveNode";
type Returns = ResolveNodeResult;
}
#[derive(Debug, Clone, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GetBoxModel {
#[serde(skip_serializing_if = "Option::is_none")]
pub node_id: Option<NodeId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub backend_node_id: Option<BackendNodeId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub object_id: Option<RemoteObjectId>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct GetBoxModelResult {
pub model: serde_json::Value,
}
impl CdpCommand for GetBoxModel {
const METHOD: &'static str = "DOM.getBoxModel";
type Returns = GetBoxModelResult;
}
#[derive(Debug, Clone, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ScrollIntoViewIfNeeded {
#[serde(skip_serializing_if = "Option::is_none")]
pub node_id: Option<NodeId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub backend_node_id: Option<BackendNodeId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub object_id: Option<RemoteObjectId>,
}
impl CdpCommand for ScrollIntoViewIfNeeded {
const METHOD: &'static str = "DOM.scrollIntoViewIfNeeded";
type Returns = Empty;
}
#[derive(Debug)]
pub struct DomDomain<'a> {
cdp: &'a Cdp,
}
impl<'a> DomDomain<'a> {
pub(crate) fn new(cdp: &'a Cdp) -> Self {
Self {
cdp,
}
}
pub async fn enable(&self) -> WebDriverResult<()> {
self.cdp.send(Enable).await?;
Ok(())
}
pub async fn disable(&self) -> WebDriverResult<()> {
self.cdp.send(Disable).await?;
Ok(())
}
pub async fn get_document(&self) -> WebDriverResult<DomNode> {
let r = self
.cdp
.send(GetDocument {
depth: Some(-1),
pierce: None,
})
.await?;
Ok(r.root)
}
pub async fn query_selector(
&self,
node_id: NodeId,
selector: impl Into<String>,
) -> WebDriverResult<NodeId> {
let r = self
.cdp
.send(QuerySelector {
node_id,
selector: selector.into(),
})
.await?;
Ok(r.node_id)
}
pub async fn query_selector_all(
&self,
node_id: NodeId,
selector: impl Into<String>,
) -> WebDriverResult<Vec<NodeId>> {
let r = self
.cdp
.send(QuerySelectorAll {
node_id,
selector: selector.into(),
})
.await?;
Ok(r.node_ids)
}
pub async fn describe_node_for_object(
&self,
object_id: RemoteObjectId,
) -> WebDriverResult<DomNode> {
let r = self
.cdp
.send(DescribeNode {
object_id: Some(object_id),
..Default::default()
})
.await?;
Ok(r.node)
}
pub async fn request_node(&self, object_id: RemoteObjectId) -> WebDriverResult<NodeId> {
let r = self
.cdp
.send(RequestNode {
object_id,
})
.await?;
Ok(r.node_id)
}
}