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
487impl 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 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 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 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}