viewpoint_core/page/locator/debug/
mod.rs1use std::time::Duration;
6
7use tracing::{debug, instrument};
8
9use super::Locator;
10use crate::error::LocatorError;
11
12impl Locator<'_> {
13 #[instrument(level = "debug", skip(self), fields(selector = ?self.selector))]
32 pub async fn highlight(&self) -> Result<(), LocatorError> {
33 self.highlight_for(Duration::from_secs(2)).await
34 }
35
36 #[instrument(level = "debug", skip(self), fields(selector = ?self.selector))]
46 pub async fn highlight_for(&self, duration: Duration) -> Result<(), LocatorError> {
47 self.wait_for_actionable().await?;
48
49 debug!(?duration, "Highlighting element");
50
51 let js = format!(
53 r"(function() {{
54 const elements = {selector};
55 if (elements.length === 0) return {{ found: false }};
56
57 const el = elements[0];
58 const originalOutline = el.style.outline;
59 const originalOutlineOffset = el.style.outlineOffset;
60 const originalTransition = el.style.transition;
61
62 // Apply highlight with animation
63 el.style.transition = 'outline 0.2s ease-in-out';
64 el.style.outline = '3px solid #ff00ff';
65 el.style.outlineOffset = '2px';
66
67 // Store original styles for restoration
68 el.__viewpoint_original_outline = originalOutline;
69 el.__viewpoint_original_outline_offset = originalOutlineOffset;
70 el.__viewpoint_original_transition = originalTransition;
71
72 return {{ found: true }};
73 }})()",
74 selector = self.selector.to_js_expression()
75 );
76
77 let result = self.evaluate_js(&js).await?;
78 let found = result.get("found").and_then(serde_json::Value::as_bool).unwrap_or(false);
79 if !found {
80 return Err(LocatorError::NotFound(format!("{:?}", self.selector)));
81 }
82
83 tokio::time::sleep(duration).await;
85
86 let cleanup_js = format!(
88 r"(function() {{
89 const elements = {selector};
90 if (elements.length === 0) return;
91
92 const el = elements[0];
93 el.style.outline = el.__viewpoint_original_outline || '';
94 el.style.outlineOffset = el.__viewpoint_original_outline_offset || '';
95 el.style.transition = el.__viewpoint_original_transition || '';
96
97 delete el.__viewpoint_original_outline;
98 delete el.__viewpoint_original_outline_offset;
99 delete el.__viewpoint_original_transition;
100 }})()",
101 selector = self.selector.to_js_expression()
102 );
103
104 let _ = self.evaluate_js(&cleanup_js).await;
106
107 Ok(())
108 }
109}