rustenium 1.1.9

A modern, robust, high-performance WebDriver BiDi automation library for Rust
Documentation
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::Mutex;

use rustenium_bidi_definitions::browsing_context::types::{BrowsingContext, Locator};
use rustenium_bidi_definitions::script::types::{Handle, NodeRemoteValue, SharedId};
use rustenium_core::transport::ConnectionTransport;
use rustenium_core::BidiSession;

use crate::error::node::{NodeActionError, NodeInputError, NodeMouseError, NodeScreenshotError};
use crate::input::{BidiKeyboard, BidiMouse, Keyboard, Mouse, MouseClickOptions, MouseMoveOptions};
use crate::nodes::bidi::node::BidiNode;
use crate::nodes::node::{Node, NodeScreenShotOptions, NodeType};
use crate::nodes::NodePosition;


pub struct FirefoxNode<T: ConnectionTransport, M: Mouse + Send + Sync = BidiMouse<T>, K: Keyboard + Send + Sync = BidiKeyboard<T>> {
    bidi_node: BidiNode<T>,
    children: Vec<FirefoxNode<T, M, K>>,
    mouse: Arc<M>,
    keyboard: Arc<K>,
}

impl<T: ConnectionTransport, M: Mouse + Send + Sync, K: Keyboard + Send + Sync> std::fmt::Debug for FirefoxNode<T, M, K> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.bidi_node.fmt(f)
    }
}

impl<T: ConnectionTransport, M: Mouse + Send + Sync + 'static, K: Keyboard + Send + Sync + 'static> FirefoxNode<T, M, K> {
    pub fn from_bidi(
        raw_bidi_node: NodeRemoteValue,
        locator: Locator,
        session: Arc<Mutex<BidiSession<T>>>,
        context: BrowsingContext,
        mouse: Arc<M>,
        keyboard: Arc<K>,
    ) -> Self {
        let bidi_node = BidiNode::new(raw_bidi_node, locator.clone(), session.clone(), context.clone());

        let children = bidi_node.children.iter()
            .map(|bidi_child| {
                FirefoxNode::from_bidi(
                    bidi_child.get_raw_node_ref().clone(),
                    locator.clone(),
                    session.clone(),
                    context.clone(),
                    mouse.clone(),
                    keyboard.clone(),
                )
            })
            .collect();

        Self { bidi_node, children, mouse, keyboard }
    }

    pub async fn mouse_move(&mut self) -> Result<(), NodeMouseError> {
        self.bidi_node
            .mouse_move(self.mouse.as_ref(), MouseMoveOptions::default())
            .await
            .map_err(NodeMouseError::from)
    }

    pub async fn mouse_move_with_options(&mut self, options: MouseMoveOptions) -> Result<(), NodeMouseError> {
        self.bidi_node
            .mouse_move(self.mouse.as_ref(), options)
            .await
            .map_err(NodeMouseError::from)
    }

    pub async fn mouse_click(&mut self) -> Result<(), NodeMouseError> {
        self.bidi_node
            .mouse_click(self.mouse.as_ref(), MouseClickOptions::default())
            .await
            .map_err(NodeMouseError::from)
    }

    pub async fn mouse_click_with_options(&mut self, options: MouseClickOptions) -> Result<(), NodeMouseError> {
        self.bidi_node
            .mouse_click(self.mouse.as_ref(), options)
            .await
            .map_err(NodeMouseError::from)
    }
}

impl<T: ConnectionTransport, M: Mouse + Send + Sync + 'static, K: Keyboard + Send + Sync + 'static> Node for FirefoxNode<T, M, K> {
    #[allow(refining_impl_trait)]
    fn get_children_nodes(&self) -> &Vec<FirefoxNode<T, M, K>> {
        &self.children
    }

    fn get_bidi_locator(&self) -> &Locator {
        &self.bidi_node.locator
    }

    fn get_local_name(&self) -> Option<&str> {
        self.bidi_node.get_local_name()
    }

    fn get_node_type(&self) -> Option<NodeType> {
        self.bidi_node.get_node_type()
    }

    async fn get_inner_text(&self) -> String {
        self.bidi_node.get_inner_text().await.unwrap()
    }

    async fn get_text_content(&self) -> String {
        self.bidi_node.get_text_content().await.unwrap()
    }

    async fn get_html(&self) -> String {
        self.bidi_node.get_inner_html().await.unwrap()
    }

    fn get_attribute(&self, attribute_name: &str) -> Option<serde_json::Value> {
        self.bidi_node.get_attribute(attribute_name)
    }

    fn get_attributes(&self) -> HashMap<String, serde_json::Value> {
        self.bidi_node.get_attributes()
    }

    async fn get_position(&mut self) -> Option<&NodePosition> {
        self.bidi_node.get_position().await.unwrap_or(None)
    }

    fn get_context_id(&self) -> &BrowsingContext {
        &self.bidi_node.context_id
    }

    fn get_shared_id(&self) -> Option<&SharedId> {
        self.bidi_node.get_raw_node_ref().shared_id.as_ref()
    }

    fn get_handle(&self) -> &Option<Handle> {
        &self.bidi_node.get_raw_node_ref().handle
    }

    fn set_position(&mut self, position: NodePosition) -> () {
        self.bidi_node.position = Some(position);
    }

    async fn scroll_into_view(&self) -> Result<(), NodeActionError> {
        self.bidi_node.scroll_into_view().await.map_err(NodeActionError::from)
    }

    async fn is_visible(&self) -> Result<bool, NodeActionError> {
        self.bidi_node.is_visible().await.map_err(NodeActionError::from)
    }

    async fn delete(&self) -> Result<(), NodeActionError> {
        self.bidi_node.delete().await.map_err(NodeActionError::from)
    }

    async fn mouse_move(&mut self) -> Result<(), NodeMouseError> {
        self.bidi_node
            .mouse_move(self.mouse.as_ref(), MouseMoveOptions::default())
            .await
            .map_err(NodeMouseError::from)
    }

    async fn mouse_move_with_options(&mut self, options: MouseMoveOptions) -> Result<(), NodeMouseError> {
        self.bidi_node
            .mouse_move(self.mouse.as_ref(), options)
            .await
            .map_err(NodeMouseError::from)
    }

    async fn mouse_click(&mut self) -> Result<(), NodeMouseError> {
        self.bidi_node
            .mouse_click(self.mouse.as_ref(), MouseClickOptions::default())
            .await
            .map_err(NodeMouseError::from)
    }

    async fn mouse_click_with_options(&mut self, options: MouseClickOptions) -> Result<(), NodeMouseError> {
        self.bidi_node
            .mouse_click(self.mouse.as_ref(), options)
            .await
            .map_err(NodeMouseError::from)
    }

    async fn screenshot(&mut self) -> Result<String, NodeScreenshotError> {
        self.bidi_node
            .screenshot(NodeScreenShotOptions::default())
            .await
            .map_err(NodeScreenshotError::from)
    }

    async fn screenshot_with_options(&mut self, options: NodeScreenShotOptions) -> Result<String, NodeScreenshotError> {
        self.bidi_node
            .screenshot(options)
            .await
            .map_err(NodeScreenshotError::from)
    }

    async fn type_text(&mut self, text: String) -> Result<(), NodeInputError> {
        self.bidi_node
            .type_text(self.keyboard.as_ref(), text)
            .await
            .map_err(NodeInputError::from)
    }
}