#[cfg(test)]
use crate::core::engine::PdfOptions;
use crate::core::engine::{EngineAdapter, EngineError};
pub async fn press_key(engine: &dyn EngineAdapter, key: &str) -> Result<(), EngineError> {
engine.keyboard_press(key).await
}
pub async fn type_text(engine: &dyn EngineAdapter, text: &str) -> Result<(), EngineError> {
engine.keyboard_type(text).await
}
pub async fn key_down(engine: &dyn EngineAdapter, key: &str) -> Result<(), EngineError> {
engine.keyboard_down(key).await
}
pub async fn key_up(engine: &dyn EngineAdapter, key: &str) -> Result<(), EngineError> {
engine.keyboard_up(key).await
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::engine::{ElementInfo, EngineError, EngineType};
use async_trait::async_trait;
use std::sync::{Arc, Mutex};
struct MockEngine {
pressed_keys: Arc<Mutex<Vec<String>>>,
typed_texts: Arc<Mutex<Vec<String>>>,
down_keys: Arc<Mutex<Vec<String>>>,
up_keys: Arc<Mutex<Vec<String>>>,
}
impl MockEngine {
fn new() -> Self {
Self {
pressed_keys: Arc::new(Mutex::new(vec![])),
typed_texts: Arc::new(Mutex::new(vec![])),
down_keys: Arc::new(Mutex::new(vec![])),
up_keys: Arc::new(Mutex::new(vec![])),
}
}
}
#[async_trait]
impl EngineAdapter for MockEngine {
fn engine_type(&self) -> EngineType {
EngineType::Fantoccini
}
async fn url(&self) -> Result<String, EngineError> {
Ok("https://example.com".to_string())
}
async fn goto(&self, _url: &str) -> Result<(), EngineError> {
Ok(())
}
async fn query_selector(
&self,
_selector: &str,
) -> Result<Option<ElementInfo>, EngineError> {
Ok(None)
}
async fn query_selector_all(
&self,
_selector: &str,
) -> Result<Vec<ElementInfo>, EngineError> {
Ok(vec![])
}
async fn count(&self, _selector: &str) -> Result<usize, EngineError> {
Ok(0)
}
async fn click(&self, _selector: &str) -> Result<(), EngineError> {
Ok(())
}
async fn fill(&self, _selector: &str, _text: &str) -> Result<(), EngineError> {
Ok(())
}
async fn type_text(&self, _selector: &str, _text: &str) -> Result<(), EngineError> {
Ok(())
}
async fn text_content(&self, _selector: &str) -> Result<Option<String>, EngineError> {
Ok(None)
}
async fn input_value(&self, _selector: &str) -> Result<Option<String>, EngineError> {
Ok(None)
}
async fn get_attribute(
&self,
_selector: &str,
_attribute: &str,
) -> Result<Option<String>, EngineError> {
Ok(None)
}
async fn is_visible(&self, _selector: &str) -> Result<bool, EngineError> {
Ok(true)
}
async fn is_enabled(&self, _selector: &str) -> Result<bool, EngineError> {
Ok(true)
}
async fn wait_for_selector(
&self,
_selector: &str,
_timeout_ms: u64,
) -> Result<(), EngineError> {
Ok(())
}
async fn scroll_into_view(&self, _selector: &str) -> Result<(), EngineError> {
Ok(())
}
async fn evaluate(&self, _script: &str) -> Result<serde_json::Value, EngineError> {
Ok(serde_json::Value::Null)
}
async fn screenshot(&self) -> Result<Vec<u8>, EngineError> {
Ok(vec![])
}
async fn bring_to_front(&self) -> Result<(), EngineError> {
Ok(())
}
async fn wait_for_navigation(&self, _timeout_ms: u64) -> Result<(), EngineError> {
Ok(())
}
async fn keyboard_press(&self, key: &str) -> Result<(), EngineError> {
self.pressed_keys.lock().unwrap().push(key.to_string());
Ok(())
}
async fn keyboard_type(&self, text: &str) -> Result<(), EngineError> {
self.typed_texts.lock().unwrap().push(text.to_string());
Ok(())
}
async fn keyboard_down(&self, key: &str) -> Result<(), EngineError> {
self.down_keys.lock().unwrap().push(key.to_string());
Ok(())
}
async fn keyboard_up(&self, key: &str) -> Result<(), EngineError> {
self.up_keys.lock().unwrap().push(key.to_string());
Ok(())
}
async fn pdf(&self, _options: PdfOptions) -> Result<Vec<u8>, EngineError> {
Err(EngineError::Browser(
"PDF not supported in mock engine".to_string(),
))
}
}
#[tokio::test]
async fn test_press_key() {
let engine = MockEngine::new();
press_key(&engine, "Escape").await.unwrap();
assert_eq!(
*engine.pressed_keys.lock().unwrap(),
vec!["Escape".to_string()]
);
}
#[tokio::test]
async fn test_type_text() {
let engine = MockEngine::new();
type_text(&engine, "Hello World").await.unwrap();
assert_eq!(
*engine.typed_texts.lock().unwrap(),
vec!["Hello World".to_string()]
);
}
#[tokio::test]
async fn test_key_down() {
let engine = MockEngine::new();
key_down(&engine, "Control").await.unwrap();
assert_eq!(
*engine.down_keys.lock().unwrap(),
vec!["Control".to_string()]
);
}
#[tokio::test]
async fn test_key_up() {
let engine = MockEngine::new();
key_up(&engine, "Control").await.unwrap();
assert_eq!(*engine.up_keys.lock().unwrap(), vec!["Control".to_string()]);
}
#[tokio::test]
async fn test_press_enter_key() {
let engine = MockEngine::new();
press_key(&engine, "Enter").await.unwrap();
assert_eq!(
*engine.pressed_keys.lock().unwrap(),
vec!["Enter".to_string()]
);
}
}