viewpoint_core/page/locator/builders/
fill.rs1use tracing::{debug, instrument};
4use viewpoint_cdp::protocol::input::DispatchKeyEventParams;
5
6use super::super::Locator;
7use crate::error::LocatorError;
8use crate::wait::NavigationWaiter;
9
10#[derive(Debug)]
14pub struct FillBuilder<'l, 'a> {
15 locator: &'l Locator<'a>,
16 text: String,
17 no_wait_after: bool,
19}
20
21impl<'l, 'a> FillBuilder<'l, 'a> {
22 pub(crate) fn new(locator: &'l Locator<'a>, text: &str) -> Self {
23 Self {
24 locator,
25 text: text.to_string(),
26 no_wait_after: false,
27 }
28 }
29
30 #[must_use]
35 pub fn no_wait_after(mut self, no_wait_after: bool) -> Self {
36 self.no_wait_after = no_wait_after;
37 self
38 }
39
40 #[instrument(level = "debug", skip(self), fields(selector = ?self.locator.selector))]
42 pub async fn send(self) -> Result<(), LocatorError> {
43 let navigation_waiter = if self.no_wait_after {
45 None
46 } else {
47 Some(NavigationWaiter::new(
48 self.locator.page.connection().subscribe_events(),
49 self.locator.page.session_id().to_string(),
50 self.locator.page.frame_id().to_string(),
51 ))
52 };
53
54 self.perform_fill().await?;
56
57 if let Some(waiter) = navigation_waiter {
59 if let Err(e) = waiter.wait_for_navigation_if_triggered().await {
60 debug!(error = ?e, "Navigation wait failed after fill");
61 return Err(LocatorError::WaitError(e));
62 }
63 }
64
65 Ok(())
66 }
67
68 async fn perform_fill(&self) -> Result<(), LocatorError> {
70 self.locator.wait_for_actionable().await?;
71
72 debug!(text = %self.text, "Filling element");
73
74 self.locator.focus_element().await?;
76
77 self.locator
79 .dispatch_key_event(DispatchKeyEventParams::key_down("a"))
80 .await?;
81 let mut select_all = DispatchKeyEventParams::key_down("a");
83 select_all.modifiers = Some(viewpoint_cdp::protocol::input::modifiers::CTRL);
84 self.locator.dispatch_key_event(select_all).await?;
85
86 self.locator
88 .dispatch_key_event(DispatchKeyEventParams::key_down("Backspace"))
89 .await?;
90
91 self.locator.insert_text(&self.text).await?;
93
94 Ok(())
95 }
96}
97
98impl<'l> std::future::IntoFuture for FillBuilder<'l, '_> {
99 type Output = Result<(), LocatorError>;
100 type IntoFuture =
101 std::pin::Pin<Box<dyn std::future::Future<Output = Self::Output> + Send + 'l>>;
102
103 fn into_future(self) -> Self::IntoFuture {
104 Box::pin(self.send())
105 }
106}