playwright/imp/
frame.rs

1pub(crate) use crate::imp::element_handle::Opt;
2use crate::imp::{
3    core::*,
4    element_handle::ElementHandle,
5    js_handle::JsHandle,
6    page::Page,
7    prelude::*,
8    response::Response,
9    utils::{DocumentLoadState, File, KeyboardModifier, MouseButton, Position}
10};
11use std::{collections::HashSet, iter::FromIterator};
12
13#[derive(Debug)]
14pub(crate) struct Frame {
15    channel: ChannelOwner,
16    parent_frame: Option<Weak<Frame>>,
17    var: Mutex<Variable>,
18    tx: Mutex<Option<broadcast::Sender<Evt>>>
19}
20
21#[derive(Debug)]
22struct Variable {
23    url: String,
24    name: String,
25    page: Option<Weak<Page>>,
26    child_frames: Vec<Weak<Frame>>,
27    load_states: HashSet<DocumentLoadState>
28}
29
30macro_rules! is_checked {
31    ($f: ident, $m: literal) => {
32        pub(crate) async fn $f(&self, selector: &str, timeout: Option<f64>) -> ArcResult<bool> {
33            #[skip_serializing_none]
34            #[derive(Serialize)]
35            #[serde(rename_all = "camelCase")]
36            struct Args<'a> {
37                selector: &'a str,
38                timeout: Option<f64>
39            }
40            let args = Args { selector, timeout };
41            let v = send_message!(self, $m, args);
42            let b = first(&v)
43                .ok_or(Error::InvalidParams)?
44                .as_bool()
45                .ok_or(Error::InvalidParams)?;
46            Ok(b)
47        }
48    };
49}
50
51macro_rules! eval_handle {
52    ($name:ident, $variant:ident, $t:ty) => {
53        pub(crate) async fn $name<T>(&self, expression: &str, arg: Option<T>) -> ArcResult<Weak<$t>>
54        where
55            T: Serialize
56        {
57            let handle = match self.evaluate_handle(expression, arg).await? {
58                Handle::$variant(handle) => handle,
59                _ => return Err(Error::ObjectNotFound.into())
60            };
61            Ok(handle)
62        }
63    };
64}
65
66impl Frame {
67    pub(crate) fn try_new(ctx: &Context, channel: ChannelOwner) -> Result<Self, Error> {
68        let Initializer {
69            name,
70            url,
71            parent_frame,
72            load_states
73        } = serde_json::from_value(channel.initializer.clone())?;
74        let parent_frame =
75            match parent_frame.map(|OnlyGuid { guid }| get_object!(ctx, &guid, Frame)) {
76                Some(Err(e)) => return Err(e),
77                Some(Ok(x)) => Some(x),
78                None => None
79            };
80        let var = Mutex::new(Variable {
81            url,
82            name,
83            page: None,
84            child_frames: Vec::new(),
85            load_states: HashSet::from_iter(load_states)
86        });
87        Ok(Self {
88            channel,
89            parent_frame,
90            var,
91            tx: Mutex::default()
92        })
93    }
94
95    pub(crate) fn hook_created(&self, this: Weak<Frame>) -> Result<(), Error> {
96        if let Some(parent) = &self.parent_frame {
97            upgrade(parent)?.add_child_frames(this);
98        }
99        Ok(())
100    }
101
102    pub(crate) async fn goto(&self, args: GotoArgs<'_, '_>) -> ArcResult<Option<Weak<Response>>> {
103        let v = send_message!(self, "goto", args);
104        let guid = match as_only_guid(&v) {
105            Some(g) => g,
106            None => return Ok(None)
107        };
108        let r = get_object!(self.context()?.lock().unwrap(), guid, Response)?;
109        Ok(Some(r))
110    }
111
112    pub(crate) async fn click(&self, args: ClickArgs<'_>) -> ArcResult<()> {
113        let _ = send_message!(self, "click", args);
114        Ok(())
115    }
116
117    pub(crate) async fn dblclick(&self, args: ClickArgs<'_>) -> ArcResult<()> {
118        let _ = send_message!(self, "dblclick", args);
119        Ok(())
120    }
121
122    pub(crate) async fn tap(&self, args: TapArgs<'_>) -> ArcResult<()> {
123        let _ = send_message!(self, "tap", args);
124        Ok(())
125    }
126
127    pub(crate) async fn fill(&self, args: FillArgs<'_, '_>) -> ArcResult<()> {
128        let _ = send_message!(self, "fill", args);
129        Ok(())
130    }
131
132    pub(crate) async fn focus(&self, selector: &str, timeout: Option<f64>) -> ArcResult<()> {
133        let args = SelectorTimeout { selector, timeout };
134        let _ = send_message!(self, "focus", args);
135        Ok(())
136    }
137
138    pub(crate) async fn text_content(
139        &self,
140        selector: &str,
141        timeout: Option<f64>
142    ) -> ArcResult<Option<String>> {
143        let args = SelectorTimeout { selector, timeout };
144        let v = send_message!(self, "textContent", args);
145        let s = maybe_only_str(&v)?;
146        Ok(s.map(Into::into))
147    }
148
149    pub(crate) async fn inner_text(
150        &self,
151        selector: &str,
152        timeout: Option<f64>
153    ) -> ArcResult<String> {
154        let args = SelectorTimeout { selector, timeout };
155        let v = send_message!(self, "innerText", args);
156        let s = only_str(&v)?;
157        Ok(s.into())
158    }
159
160    pub(crate) async fn inner_html(
161        &self,
162        selector: &str,
163        timeout: Option<f64>
164    ) -> ArcResult<String> {
165        let args = SelectorTimeout { selector, timeout };
166        let v = send_message!(self, "innerHTML", args);
167        let s = only_str(&v)?;
168        Ok(s.into())
169    }
170
171    pub(crate) async fn get_attribute(
172        &self,
173        selector: &str,
174        name: &str,
175        timeout: Option<f64>
176    ) -> ArcResult<Option<String>> {
177        #[skip_serializing_none]
178        #[derive(Serialize)]
179        #[serde(rename_all = "camelCase")]
180        struct Args<'a, 'b> {
181            selector: &'a str,
182            name: &'b str,
183            timeout: Option<f64>
184        }
185        let args = Args {
186            selector,
187            name,
188            timeout
189        };
190        let v = send_message!(self, "getAttribute", args);
191        let s = maybe_only_str(&v)?;
192        Ok(s.map(Into::into))
193    }
194
195    pub(crate) async fn query_selector(
196        &self,
197        selector: &str
198    ) -> ArcResult<Option<Weak<ElementHandle>>> {
199        let mut args = HashMap::new();
200        args.insert("selector", selector);
201        let v = send_message!(self, "querySelector", args);
202        let guid = match as_only_guid(&v) {
203            Some(g) => g,
204            None => return Ok(None)
205        };
206        let e = get_object!(self.context()?.lock().unwrap(), guid, ElementHandle)?;
207        Ok(Some(e))
208    }
209
210    pub(crate) async fn query_selector_all(
211        &self,
212        selector: &str
213    ) -> ArcResult<Vec<Weak<ElementHandle>>> {
214        let mut args = HashMap::new();
215        args.insert("selector", selector);
216        let v = send_message!(self, "querySelectorAll", args);
217        let first = first(&v).ok_or(Error::InvalidParams)?;
218        let elements: Vec<OnlyGuid> =
219            serde_json::from_value((*first).clone()).map_err(Error::Serde)?;
220        let es = elements
221            .into_iter()
222            .map(|OnlyGuid { guid }| {
223                get_object!(self.context()?.lock().unwrap(), &guid, ElementHandle)
224            })
225            .collect::<Result<Vec<_>, Error>>()?;
226        Ok(es)
227    }
228
229    pub(crate) async fn frame_element(&self) -> ArcResult<Weak<ElementHandle>> {
230        let v = send_message!(self, "frameElement", Map::new());
231        let guid = only_guid(&v)?;
232        let e = get_object!(self.context()?.lock().unwrap(), guid, ElementHandle)?;
233        Ok(e)
234    }
235
236    pub(crate) async fn wait_for_selector(
237        &self,
238        args: WaitForSelectorArgs<'_>
239    ) -> ArcResult<Option<Weak<ElementHandle>>> {
240        let v = send_message!(self, "waitForSelector", args);
241        let guid = match as_only_guid(&v) {
242            Some(g) => g,
243            None => return Ok(None)
244        };
245        let e = get_object!(self.context()?.lock().unwrap(), guid, ElementHandle)?;
246        Ok(Some(e))
247    }
248
249    pub(crate) async fn title(&self) -> ArcResult<String> {
250        let v = send_message!(self, "title", Map::new());
251        let s = only_str(&v)?;
252        Ok(s.to_owned())
253    }
254
255    pub(crate) async fn r#type(&self, args: TypeArgs<'_, '_>) -> ArcResult<()> {
256        let _ = send_message!(self, "type", args);
257        Ok(())
258    }
259
260    pub(crate) async fn press(&self, args: PressArgs<'_, '_>) -> ArcResult<()> {
261        let _ = send_message!(self, "press", args);
262        Ok(())
263    }
264
265    pub(crate) async fn hover(&self, args: HoverArgs<'_>) -> ArcResult<()> {
266        let _ = send_message!(self, "hover", args);
267        Ok(())
268    }
269
270    is_checked!(is_checked, "isChecked");
271    is_checked!(is_disabled, "isDisabled");
272    is_checked!(is_editable, "isEditable");
273    is_checked!(is_enabled, "isEnabled");
274    is_checked!(is_hidden, "isHidden");
275    is_checked!(is_visible, "isVisible");
276
277    pub(crate) async fn content(&self) -> ArcResult<String> {
278        let v = send_message!(self, "content", Map::new());
279        let s = only_str(&v)?;
280        Ok(s.into())
281    }
282
283    pub(crate) async fn set_content(&self, args: SetContentArgs<'_>) -> ArcResult<()> {
284        let _ = send_message!(self, "setContent", args);
285        Ok(())
286    }
287
288    pub(crate) async fn check(&self, args: CheckArgs<'_>) -> ArcResult<()> {
289        let _ = send_message!(self, "check", args);
290        Ok(())
291    }
292
293    pub(crate) async fn uncheck(&self, args: CheckArgs<'_>) -> ArcResult<()> {
294        let _ = send_message!(self, "uncheck", args);
295        Ok(())
296    }
297
298    pub(crate) async fn add_script_tag(
299        &self,
300        args: AddScriptTagArgs<'_, '_, '_>
301    ) -> ArcResult<Weak<ElementHandle>> {
302        let v = send_message!(self, "addScriptTag", args);
303        let guid = only_guid(&v)?;
304        let e = get_object!(self.context()?.lock().unwrap(), guid, ElementHandle)?;
305        Ok(e)
306    }
307
308    pub(crate) async fn add_style_tag(
309        &self,
310        content: &str,
311        url: Option<&str>
312    ) -> ArcResult<Weak<ElementHandle>> {
313        let mut args = HashMap::new();
314        args.insert("content", content);
315        if let Some(url) = url {
316            args.insert("url", url);
317        }
318        let v = send_message!(self, "addStyleTag", args);
319        let guid = only_guid(&v)?;
320        let e = get_object!(self.context()?.lock().unwrap(), guid, ElementHandle)?;
321        Ok(e)
322    }
323
324    pub(crate) async fn eval<U>(&self, expression: &str) -> ArcResult<U>
325    where
326        U: DeserializeOwned
327    {
328        self.evaluate::<(), U>(expression, None).await
329    }
330
331    pub(crate) async fn evaluate<T, U>(&self, expression: &str, arg: Option<T>) -> ArcResult<U>
332    where
333        T: Serialize,
334        U: DeserializeOwned
335    {
336        #[derive(Serialize)]
337        #[serde(rename_all = "camelCase")]
338        struct Args<'a> {
339            expression: &'a str,
340            arg: Value
341        }
342        let arg = ser::to_value(&arg).map_err(Error::SerializationPwJson)?;
343        let args = Args { expression, arg };
344        let v = send_message!(self, "evaluateExpression", args);
345        let first = first(&v).ok_or(Error::ObjectNotFound)?;
346        Ok(de::from_value(first).map_err(Error::DeserializationPwJson)?)
347    }
348
349    async fn evaluate_handle<T>(&self, expression: &str, arg: Option<T>) -> ArcResult<Handle>
350    where
351        T: Serialize
352    {
353        #[derive(Serialize)]
354        #[serde(rename_all = "camelCase")]
355        struct Args<'a> {
356            expression: &'a str,
357            arg: Value
358        }
359        let arg = ser::to_value(&arg).map_err(Error::SerializationPwJson)?;
360        let args = Args { expression, arg };
361        let v = send_message!(self, "evaluateExpressionHandle", args);
362        let guid = only_guid(&v)?;
363        let e = get_object!(self.context()?.lock().unwrap(), guid, ElementHandle)
364            .ok()
365            .map(Handle::Element);
366        let j = get_object!(self.context()?.lock().unwrap(), guid, JsHandle)
367            .ok()
368            .map(Handle::Js);
369        let h = e.or(j).ok_or(Error::ObjectNotFound)?;
370        Ok(h)
371    }
372
373    eval_handle! {evaluate_element_handle, Element, ElementHandle}
374    eval_handle! {evaluate_js_handle, Js, JsHandle}
375
376    pub(crate) async fn evaluate_on_selector<T, U>(
377        &self,
378        selector: &str,
379        expression: &str,
380        arg: Option<T>
381    ) -> ArcResult<U>
382    where
383        T: Serialize,
384        U: DeserializeOwned
385    {
386        #[derive(Serialize)]
387        #[serde(rename_all = "camelCase")]
388        struct Args<'a, 'b> {
389            selector: &'a str,
390            expression: &'b str,
391            arg: Value
392        }
393        let arg = ser::to_value(&arg).map_err(Error::SerializationPwJson)?;
394        let args = Args {
395            selector,
396            expression,
397            arg
398        };
399        let v = send_message!(self, "evalOnSelector", args);
400        let first = first(&v).ok_or(Error::ObjectNotFound)?;
401        Ok(de::from_value(first).map_err(Error::DeserializationPwJson)?)
402    }
403
404    pub(crate) async fn evaluate_on_selector_all<T, U>(
405        &self,
406        selector: &str,
407        expression: &str,
408        arg: Option<T>
409    ) -> ArcResult<U>
410    where
411        T: Serialize,
412        U: DeserializeOwned
413    {
414        #[derive(Serialize)]
415        #[serde(rename_all = "camelCase")]
416        struct Args<'a, 'b> {
417            selector: &'a str,
418            expression: &'b str,
419            arg: Value
420        }
421        let arg = ser::to_value(&arg).map_err(Error::SerializationPwJson)?;
422        let args = Args {
423            selector,
424            expression,
425            arg
426        };
427        let v = send_message!(self, "evalOnSelectorAll", args);
428        let first = first(&v).ok_or(Error::ObjectNotFound)?;
429        Ok(de::from_value(first).map_err(Error::DeserializationPwJson)?)
430    }
431
432    pub(crate) async fn dispatch_event<T>(
433        &self,
434        selector: &str,
435        r#type: &str,
436        event_init: Option<T>
437    ) -> ArcResult<()>
438    where
439        T: Serialize
440    {
441        #[derive(Serialize)]
442        #[serde(rename_all = "camelCase")]
443        struct Args<'a, 'b> {
444            selector: &'a str,
445            r#type: &'b str,
446            event_init: Value
447        }
448        let event_init = ser::to_value(&event_init).map_err(Error::SerializationPwJson)?;
449        let args = Args {
450            selector,
451            r#type,
452            event_init
453        };
454        let _ = send_message!(self, "dispatchEvent", args);
455        Ok(())
456    }
457
458    pub(crate) async fn select_option(&self, args: SelectOptionArgs<'_>) -> ArcResult<Vec<String>> {
459        let v = send_message!(self, "selectOption", args);
460        let first = first(&v).ok_or(Error::InvalidParams)?;
461        let ss = first
462            .as_array()
463            .ok_or(Error::InvalidParams)?
464            .iter()
465            .filter_map(|v| v.as_str())
466            .map(ToOwned::to_owned)
467            .collect();
468        Ok(ss)
469    }
470
471    pub(crate) async fn set_input_files(&self, args: SetInputFilesArgs<'_>) -> ArcResult<()> {
472        let _ = send_message!(self, "setInputFiles", args);
473        Ok(())
474    }
475
476    pub(crate) async fn wait_for_function(
477        &self,
478        args: WaitForFunctionArgs<'_>
479    ) -> ArcResult<Weak<JsHandle>> {
480        let v = send_message!(self, "waitForFunction", args);
481        let guid = only_guid(&v)?;
482        let h = get_object!(self.context()?.lock().unwrap(), guid, JsHandle)?;
483        Ok(h)
484    }
485}
486
487// mutable
488impl Frame {
489    pub(crate) fn url(&self) -> String { self.var.lock().unwrap().url.clone() }
490
491    pub(crate) fn name(&self) -> String { self.var.lock().unwrap().name.clone() }
492
493    pub(crate) fn page(&self) -> Option<Weak<Page>> { self.var.lock().unwrap().page.clone() }
494
495    pub(crate) fn set_page(&self, page: Weak<Page>) { self.var.lock().unwrap().page = Some(page); }
496
497    pub(crate) fn parent_frame(&self) -> Option<Weak<Frame>> { self.parent_frame.clone() }
498
499    pub(crate) fn child_frames(&self) -> Vec<Weak<Frame>> {
500        self.var.lock().unwrap().child_frames.clone()
501    }
502
503    pub(crate) fn add_child_frames(&self, child: Weak<Frame>) {
504        self.var.lock().unwrap().child_frames.push(child);
505    }
506
507    fn on_navigated(&self, ctx: &Context, params: Map<String, Value>) -> Result<(), Error> {
508        let var = &mut self.var.lock().unwrap();
509        let payload: FrameNavigatedEvent = serde_json::from_value(params.into())?;
510        {
511            var.name = payload.name.clone();
512            var.url = payload.url.clone();
513        }
514        self.emit_event(Evt::Navigated(payload));
515        if let Some(page) = var.page.as_ref().and_then(|p| p.upgrade()) {
516            let this = get_object!(ctx, self.guid(), Frame)?;
517            page.on_frame_navigated(this);
518        }
519        Ok(())
520    }
521
522    fn on_load_state(&self, params: Map<String, Value>) -> Result<(), Error> {
523        #[derive(Deserialize)]
524        #[serde(rename_all = "camelCase")]
525        enum Op {
526            Add(DocumentLoadState),
527            Remove(DocumentLoadState)
528        }
529        let op: Op = serde_json::from_value(params.into())?;
530        let load_states = &mut self.var.lock().unwrap().load_states;
531        match op {
532            Op::Add(x) => {
533                load_states.insert(x);
534                self.emit_event(Evt::LoadState(x));
535            }
536            Op::Remove(x) => {
537                load_states.remove(&x);
538            }
539        }
540        Ok(())
541    }
542}
543
544impl RemoteObject for Frame {
545    fn channel(&self) -> &ChannelOwner { &self.channel }
546    fn channel_mut(&mut self) -> &mut ChannelOwner { &mut self.channel }
547
548    fn handle_event(
549        &self,
550        ctx: &Context,
551        method: Str<Method>,
552        params: Map<String, Value>
553    ) -> Result<(), Error> {
554        match method.as_str() {
555            "navigated" => self.on_navigated(ctx, params)?,
556            "loadstate" => self.on_load_state(params)?,
557            _ => {}
558        }
559        Ok(())
560    }
561}
562
563#[derive(Debug, Clone)]
564pub(crate) enum Evt {
565    LoadState(DocumentLoadState),
566    Navigated(FrameNavigatedEvent)
567}
568
569impl EventEmitter for Frame {
570    type Event = Evt;
571
572    fn tx(&self) -> Option<broadcast::Sender<Self::Event>> { self.tx.lock().unwrap().clone() }
573
574    fn set_tx(&self, tx: broadcast::Sender<Self::Event>) { *self.tx.lock().unwrap() = Some(tx); }
575}
576
577#[derive(Debug, Clone, Copy, PartialEq)]
578pub enum EventType {
579    LoadState,
580    Navigated
581}
582
583impl IsEvent for Evt {
584    type EventType = EventType;
585
586    fn event_type(&self) -> Self::EventType {
587        match self {
588            Evt::LoadState(_) => EventType::LoadState,
589            Evt::Navigated(_) => EventType::Navigated
590        }
591    }
592}
593
594enum Handle {
595    Js(Weak<JsHandle>),
596    Element(Weak<ElementHandle>)
597}
598
599#[skip_serializing_none]
600#[derive(Serialize)]
601#[serde(rename_all = "camelCase")]
602pub(crate) struct GotoArgs<'a, 'b> {
603    url: &'a str,
604    pub(crate) timeout: Option<f64>,
605    pub(crate) wait_until: Option<DocumentLoadState>,
606    pub(crate) referer: Option<&'b str>
607}
608
609impl<'a> GotoArgs<'a, '_> {
610    pub(crate) fn new(url: &'a str) -> Self {
611        Self {
612            url,
613            timeout: Some(30000.0),
614            wait_until: None,
615            referer: None
616        }
617    }
618}
619
620#[skip_serializing_none]
621#[derive(Serialize)]
622#[serde(rename_all = "camelCase")]
623pub(crate) struct ClickArgs<'a> {
624    selector: &'a str,
625    pub(crate) modifiers: Option<Vec<KeyboardModifier>>,
626    pub(crate) position: Option<Position>,
627    pub(crate) delay: Option<f64>,
628    pub(crate) button: Option<MouseButton>,
629    /// Is ignored if dblclick
630    pub(crate) click_count: Option<i32>,
631    pub(crate) timeout: Option<f64>,
632    pub(crate) force: Option<bool>,
633    pub(crate) no_wait_after: Option<bool>,
634    pub(crate) trial: Option<bool>
635}
636
637impl<'a> ClickArgs<'a> {
638    pub(crate) fn new(selector: &'a str) -> Self {
639        Self {
640            selector,
641            modifiers: None,
642            position: None,
643            delay: None,
644            button: None,
645            /// Is ignored if dblclick
646            click_count: None,
647            timeout: Some(30000.0),
648            force: None,
649            no_wait_after: None,
650            trial: None
651        }
652    }
653}
654
655#[skip_serializing_none]
656#[derive(Serialize)]
657#[serde(rename_all = "camelCase")]
658pub(crate) struct WaitForSelectorArgs<'a> {
659    selector: &'a str,
660    pub(crate) timeout: Option<f64>,
661    pub(crate) state: Option<FrameState>
662}
663
664impl<'a> WaitForSelectorArgs<'a> {
665    pub(crate) fn new(selector: &'a str) -> Self {
666        Self {
667            selector,
668            timeout: Some(30000.0),
669            state: None
670        }
671    }
672}
673
674#[derive(Serialize)]
675#[serde(rename_all = "lowercase")]
676pub enum FrameState {
677    Attached,
678    Detached,
679    Hidden,
680    Visible
681}
682
683macro_rules! type_args {
684    ($t:ident, $f:ident) => {
685        #[derive(Serialize)]
686        #[serde(rename_all = "camelCase")]
687        pub(crate) struct $t<'a, 'b> {
688            selector: &'a str,
689            $f: &'b str,
690            pub(crate) delay: Option<f64>,
691            pub(crate) timeout: Option<f64>,
692            pub(crate) no_wait_after: Option<bool>
693        }
694
695        impl<'a, 'b> $t<'a, 'b> {
696            pub(crate) fn new(selector: &'a str, $f: &'b str) -> Self {
697                Self {
698                    selector,
699                    $f,
700                    delay: None,
701                    timeout: Some(30000.0),
702                    no_wait_after: None
703                }
704            }
705        }
706    };
707}
708
709type_args! {TypeArgs, text}
710type_args! {PressArgs, key}
711
712#[skip_serializing_none]
713#[derive(Serialize)]
714#[serde(rename_all = "camelCase")]
715pub(crate) struct HoverArgs<'a> {
716    selector: &'a str,
717    pub(crate) modifiers: Option<Vec<KeyboardModifier>>,
718    pub(crate) position: Option<Position>,
719    pub(crate) timeout: Option<f64>,
720    pub(crate) force: Option<bool>,
721    pub(crate) trial: Option<bool>
722}
723
724impl<'a> HoverArgs<'a> {
725    pub(crate) fn new(selector: &'a str) -> Self {
726        Self {
727            selector,
728            modifiers: None,
729            position: None,
730            timeout: Some(30000.0),
731            force: None,
732            trial: None
733        }
734    }
735}
736
737#[skip_serializing_none]
738#[derive(Serialize)]
739#[serde(rename_all = "camelCase")]
740pub(crate) struct SetContentArgs<'a> {
741    html: &'a str,
742    pub(crate) timeout: Option<f64>,
743    pub(crate) wait_until: Option<DocumentLoadState>
744}
745
746impl<'a> SetContentArgs<'a> {
747    pub(crate) fn new(html: &'a str) -> Self {
748        Self {
749            html,
750            timeout: Some(30000.0),
751            wait_until: None
752        }
753    }
754}
755
756#[skip_serializing_none]
757#[derive(Serialize)]
758#[serde(rename_all = "camelCase")]
759pub(crate) struct TapArgs<'a> {
760    selector: &'a str,
761    pub(crate) modifiers: Option<Vec<KeyboardModifier>>,
762    pub(crate) position: Option<Position>,
763    pub(crate) timeout: Option<f64>,
764    pub(crate) force: Option<bool>,
765    pub(crate) no_wait_after: Option<bool>,
766    pub(crate) trial: Option<bool>
767}
768
769impl<'a> TapArgs<'a> {
770    pub(crate) fn new(selector: &'a str) -> Self {
771        Self {
772            selector,
773            modifiers: None,
774            position: None,
775            timeout: Some(30000.0),
776            force: None,
777            no_wait_after: None,
778            trial: None
779        }
780    }
781}
782
783#[skip_serializing_none]
784#[derive(Serialize)]
785#[serde(rename_all = "camelCase")]
786pub(crate) struct FillArgs<'a, 'b> {
787    selector: &'a str,
788    value: &'b str,
789    pub(crate) timeout: Option<f64>,
790    pub(crate) no_wait_after: Option<bool>
791}
792
793impl<'a, 'b> FillArgs<'a, 'b> {
794    pub(crate) fn new(selector: &'a str, value: &'b str) -> Self {
795        Self {
796            selector,
797            value,
798            timeout: Some(30000.0),
799            no_wait_after: None
800        }
801    }
802}
803
804#[skip_serializing_none]
805#[derive(Serialize)]
806#[serde(rename_all = "camelCase")]
807struct SelectorTimeout<'a> {
808    selector: &'a str,
809    timeout: Option<f64>
810}
811
812#[skip_serializing_none]
813#[derive(Serialize)]
814#[serde(rename_all = "camelCase")]
815pub(crate) struct CheckArgs<'a> {
816    selector: &'a str,
817    pub(crate) position: Option<Position>,
818    pub(crate) timeout: Option<f64>,
819    pub(crate) force: Option<bool>,
820    pub(crate) no_wait_after: Option<bool>,
821    pub(crate) trial: Option<bool>
822}
823
824impl<'a> CheckArgs<'a> {
825    pub(crate) fn new(selector: &'a str) -> Self {
826        Self {
827            selector,
828            position: None,
829            timeout: Some(30000.0),
830            force: None,
831            no_wait_after: None,
832            trial: None
833        }
834    }
835}
836
837#[skip_serializing_none]
838#[derive(Serialize)]
839#[serde(rename_all = "camelCase")]
840pub(crate) struct AddScriptTagArgs<'a, 'b, 'c> {
841    content: &'a str,
842    pub(crate) url: Option<&'b str>,
843    pub(crate) r#type: Option<&'c str>
844}
845
846impl<'a, 'b, 'c> AddScriptTagArgs<'a, 'b, 'c> {
847    pub(crate) fn new(content: &'a str) -> Self {
848        Self {
849            content,
850            url: None,
851            r#type: None
852        }
853    }
854}
855
856#[skip_serializing_none]
857#[derive(Serialize)]
858#[serde(rename_all = "camelCase")]
859pub(crate) struct SelectOptionArgs<'a> {
860    selector: &'a str,
861
862    pub(crate) options: Option<Vec<Opt>>,
863    pub(crate) elements: Option<Vec<OnlyGuid>>,
864
865    pub(crate) timeout: Option<f64>,
866    pub(crate) no_wait_after: Option<bool>
867}
868
869impl<'a> SelectOptionArgs<'a> {
870    pub(crate) fn new(selector: &'a str) -> Self {
871        Self {
872            selector,
873            options: None,
874            elements: None,
875            timeout: Some(30000.0),
876            no_wait_after: None
877        }
878    }
879}
880
881#[skip_serializing_none]
882#[derive(Serialize)]
883#[serde(rename_all = "camelCase")]
884pub(crate) struct SetInputFilesArgs<'a> {
885    selector: &'a str,
886
887    pub(crate) files: Vec<File>,
888    pub(crate) timeout: Option<f64>,
889    pub(crate) no_wait_after: Option<bool>
890}
891
892impl<'a> SetInputFilesArgs<'a> {
893    pub(crate) fn new(selector: &'a str) -> Self {
894        Self {
895            selector,
896            files: Vec::new(),
897            timeout: Some(30000.0),
898            no_wait_after: None
899        }
900    }
901}
902
903#[skip_serializing_none]
904#[derive(Serialize)]
905#[serde(rename_all = "camelCase")]
906pub(crate) struct WaitForFunctionArgs<'a> {
907    expression: &'a str,
908    pub(crate) timeout: Option<f64>,
909    pub(crate) polling: Option<Polling>,
910    // XXX
911    pub(crate) arg: Option<Value>
912}
913
914pub enum Polling {
915    RequestAnimationFrame,
916    Millis(u32)
917}
918
919impl Serialize for Polling {
920    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
921    where
922        S: serde::ser::Serializer
923    {
924        match self {
925            Self::Millis(x) => x.serialize(serializer),
926            Self::RequestAnimationFrame => "raf".serialize(serializer)
927        }
928    }
929}
930
931impl<'a> WaitForFunctionArgs<'a> {
932    pub(crate) fn new(expression: &'a str) -> Self {
933        Self {
934            expression,
935            timeout: Some(30000.0),
936            polling: None,
937            arg: None
938        }
939    }
940}
941
942#[derive(Deserialize)]
943#[serde(rename_all = "camelCase")]
944struct Initializer {
945    name: String,
946    url: String,
947    parent_frame: Option<OnlyGuid>,
948    load_states: Vec<DocumentLoadState>
949}
950
951#[derive(Debug, Deserialize, Clone)]
952#[serde(rename_all = "camelCase")]
953pub struct FrameNavigatedEvent {
954    url: String,
955    name: String,
956    new_document: Option<Document>,
957    error: Option<String>
958}
959
960#[derive(Debug, Deserialize, Clone)]
961#[serde(rename_all = "camelCase")]
962pub struct Document {
963    #[serde(default)]
964    request: Value
965}
966
967#[cfg(test)]
968mod tests {
969    use super::*;
970    use crate::imp::{
971        browser::{Browser, *},
972        browser_context::BrowserContext,
973        browser_type::*,
974        page::Page,
975        playwright::Playwright
976    };
977
978    crate::runtime_test!(eval_handle, {
979        let driver = Driver::install().unwrap();
980        let conn = Connection::run(&driver).unwrap();
981        let pw = Playwright::wait_initial_object(&conn).await.unwrap();
982        let pw: Arc<Playwright> = pw.upgrade().unwrap();
983        let chromium: Arc<BrowserType> = pw.chromium().upgrade().unwrap();
984        let browser: Weak<Browser> = chromium.launch(LaunchArgs::default()).await.unwrap();
985        let browser: Arc<Browser> = browser.upgrade().unwrap();
986        let browser_context: Weak<BrowserContext> = browser
987            .new_context(NewContextArgs::default())
988            .await
989            .unwrap();
990        let browser_context: Arc<BrowserContext> = browser_context.upgrade().unwrap();
991        let page: Weak<Page> = browser_context.new_page().await.unwrap();
992        let page: Arc<Page> = page.upgrade().unwrap();
993        let frame: Weak<Frame> = page.main_frame();
994        let frame: Arc<Frame> = frame.upgrade().unwrap();
995        let _handle: Weak<JsHandle> = frame
996            .evaluate_js_handle::<()>("() => location.href", None)
997            .await
998            .unwrap();
999        let _handle: Weak<ElementHandle> = frame
1000            .evaluate_element_handle::<()>("() => document.body", None)
1001            .await
1002            .unwrap();
1003    });
1004
1005    #[test]
1006    fn serialize_enum() {
1007        let s = serde_json::to_string(&Polling::Millis(3)).unwrap();
1008        assert_eq!(s, "3");
1009        let s = serde_json::to_string(&Polling::RequestAnimationFrame).unwrap();
1010        assert_eq!(s, r#""raf""#);
1011    }
1012}