pub use ego_tree::NodeId as StaticNodeId;
pub use headless_chrome::protocol::cdp::DOM::NodeId as DynamicNodeId;
use scraper::{ElementRef, Selector};
use super::Node;
pub enum AnyNode<'a> {
Static(scraper::ElementRef<'a>),
Dynamic(Node<'a>),
}
impl<'a> AnyNode<'a> {
pub fn node_ref(&self) -> NodeRef {
match self {
Self::Static(node) => NodeRef::Static(node.id()),
Self::Dynamic(node) => node.id(),
}
}
pub fn name(&self) -> &str {
match self {
Self::Static(node) => node.value().name(),
Self::Dynamic(node) => node.name(),
}
}
pub fn attributes(&self) -> anyhow::Result<Vec<(String, String)>> {
match self {
Self::Static(node) => Ok(node
.value()
.attrs()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect()),
Self::Dynamic(node) => node.attributes(),
}
}
pub fn text(&self) -> anyhow::Result<String> {
match self {
Self::Static(node) => Ok(node.text().collect::<Vec<_>>().join("")),
Self::Dynamic(node) => Ok(node.get_text()?),
}
}
pub fn click(&self) -> anyhow::Result<()> {
match self {
Self::Static(_) => Err(anyhow::anyhow!("Cannot click static node")),
Self::Dynamic(node) => {
node.click()?;
Ok(())
}
}
}
pub fn type_into(&self, keys: &str) -> anyhow::Result<()> {
match self {
Self::Static(_) => Err(anyhow::anyhow!("Cannot type into static node")),
Self::Dynamic(node) => {
node.send_keys(keys)?;
Ok(())
}
}
}
pub fn outer_html(&self) -> anyhow::Result<String> {
match self {
Self::Static(node) => Ok(node.html()),
Self::Dynamic(node) => Ok(node.outer_html()?),
}
}
pub fn find_child(&self, selector: &str) -> anyhow::Result<Self> {
match self {
Self::Static(node) => {
let query = Selector::parse(selector)
.map_err(|e| anyhow::anyhow!("Invalid query: {}", e))?;
Ok(Self::Static(
node.select(&query)
.next()
.ok_or_else(|| anyhow::anyhow!("No child found"))?,
))
}
Self::Dynamic(node) => Ok(Self::Dynamic(node.find_child(selector)?)),
}
}
pub fn children(&self) -> anyhow::Result<Vec<NodeRef>> {
match self {
Self::Static(node) => Ok(node
.children()
.filter_map(|child| ElementRef::wrap(child).map(|node| NodeRef::Static(node.id())))
.collect()),
Self::Dynamic(node) => node.children(),
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum NodeRef {
Static(StaticNodeId),
Dynamic(DynamicNodeId),
}