1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use crate::common::{WebElement, ELEMENT_KEY};
6 use serde::de::{self, Deserialize, Deserializer};
7 use serde::ser::{Serialize, Serializer};
8 use serde_json::Value;
9 use std::default::Default;
10 use unicode_segmentation::UnicodeSegmentation;
11 
12 #[derive(Debug, PartialEq, Serialize, Deserialize)]
13 pub struct ActionSequence {
14     pub id: String,
15     #[serde(flatten)]
16     pub actions: ActionsType,
17 }
18 
19 #[derive(Debug, PartialEq, Serialize, Deserialize)]
20 #[serde(tag = "type")]
21 pub enum ActionsType {
22     #[serde(rename = "none")]
23     Null { actions: Vec<NullActionItem> },
24     #[serde(rename = "key")]
25     Key { actions: Vec<KeyActionItem> },
26     #[serde(rename = "pointer")]
27     Pointer {
28         #[serde(default)]
29         parameters: PointerActionParameters,
30         actions: Vec<PointerActionItem>,
31     },
32 }
33 
34 #[derive(Debug, PartialEq, Serialize, Deserialize)]
35 #[serde(untagged)]
36 pub enum NullActionItem {
37     General(GeneralAction),
38 }
39 
40 #[derive(Debug, PartialEq, Serialize, Deserialize)]
41 #[serde(tag = "type")]
42 pub enum GeneralAction {
43     #[serde(rename = "pause")]
44     Pause(PauseAction),
45 }
46 
47 #[derive(Debug, PartialEq, Serialize, Deserialize)]
48 pub struct PauseAction {
49     #[serde(
50         default,
51         skip_serializing_if = "Option::is_none",
52         deserialize_with = "deserialize_to_option_u64"
53     )]
54     pub duration: Option<u64>,
55 }
56 
57 #[derive(Debug, PartialEq, Serialize, Deserialize)]
58 #[serde(untagged)]
59 pub enum KeyActionItem {
60     General(GeneralAction),
61     Key(KeyAction),
62 }
63 
64 #[derive(Debug, PartialEq, Serialize, Deserialize)]
65 #[serde(tag = "type")]
66 pub enum KeyAction {
67     #[serde(rename = "keyDown")]
68     Down(KeyDownAction),
69     #[serde(rename = "keyUp")]
70     Up(KeyUpAction),
71 }
72 
73 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
74 pub struct KeyDownAction {
75     #[serde(deserialize_with = "deserialize_key_action_value")]
76     pub value: String,
77 }
78 
79 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
80 pub struct KeyUpAction {
81     #[serde(deserialize_with = "deserialize_key_action_value")]
82     pub value: String,
83 }
84 
deserialize_key_action_value<'de, D>(deserializer: D) -> Result<String, D::Error> where D: Deserializer<'de>,85 fn deserialize_key_action_value<'de, D>(deserializer: D) -> Result<String, D::Error>
86 where
87     D: Deserializer<'de>,
88 {
89     String::deserialize(deserializer).map(|value| {
90         // Only a single Unicode grapheme cluster is allowed
91         if value.graphemes(true).count() != 1 {
92             return Err(de::Error::custom(format!(
93                 "'{}' should only contain a single Unicode code point",
94                 value
95             )));
96         }
97 
98         Ok(value)
99     })?
100 }
101 
102 #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
103 #[serde(rename_all = "lowercase")]
104 pub enum PointerType {
105     Mouse,
106     Pen,
107     Touch,
108 }
109 
110 impl Default for PointerType {
default() -> PointerType111     fn default() -> PointerType {
112         PointerType::Mouse
113     }
114 }
115 
116 #[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
117 pub struct PointerActionParameters {
118     #[serde(rename = "pointerType")]
119     pub pointer_type: PointerType,
120 }
121 
122 #[derive(Debug, PartialEq, Serialize, Deserialize)]
123 #[serde(untagged)]
124 pub enum PointerActionItem {
125     General(GeneralAction),
126     Pointer(PointerAction),
127 }
128 
129 #[derive(Debug, PartialEq, Serialize, Deserialize)]
130 #[serde(tag = "type")]
131 pub enum PointerAction {
132     #[serde(rename = "pointerCancel")]
133     Cancel,
134     #[serde(rename = "pointerDown")]
135     Down(PointerDownAction),
136     #[serde(rename = "pointerMove")]
137     Move(PointerMoveAction),
138     #[serde(rename = "pointerUp")]
139     Up(PointerUpAction),
140 }
141 
142 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
143 pub struct PointerDownAction {
144     pub button: u64,
145 }
146 
147 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
148 pub struct PointerMoveAction {
149     #[serde(
150         default,
151         skip_serializing_if = "Option::is_none",
152         deserialize_with = "deserialize_to_option_u64"
153     )]
154     pub duration: Option<u64>,
155     #[serde(default)]
156     pub origin: PointerOrigin,
157     #[serde(
158         default,
159         skip_serializing_if = "Option::is_none",
160         deserialize_with = "deserialize_to_option_i64"
161     )]
162     pub x: Option<i64>,
163     #[serde(
164         default,
165         skip_serializing_if = "Option::is_none",
166         deserialize_with = "deserialize_to_option_i64"
167     )]
168     pub y: Option<i64>,
169 }
170 
171 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
172 pub struct PointerUpAction {
173     pub button: u64,
174 }
175 
176 #[derive(Clone, Debug, PartialEq, Serialize)]
177 pub enum PointerOrigin {
178     #[serde(
179         rename = "element-6066-11e4-a52e-4f735466cecf",
180         serialize_with = "serialize_webelement_id"
181     )]
182     Element(WebElement),
183     #[serde(rename = "pointer")]
184     Pointer,
185     #[serde(rename = "viewport")]
186     Viewport,
187 }
188 
189 impl Default for PointerOrigin {
default() -> PointerOrigin190     fn default() -> PointerOrigin {
191         PointerOrigin::Viewport
192     }
193 }
194 
195 // TODO: The custom deserializer can be removed once the support of the legacy
196 // ELEMENT key has been removed from Selenium bindings
197 // See: https://github.com/SeleniumHQ/selenium/issues/6393
198 impl<'de> Deserialize<'de> for PointerOrigin {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,199     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
200     where
201         D: Deserializer<'de>,
202     {
203         let value = Value::deserialize(deserializer)?;
204         if let Some(web_element) = value.get(ELEMENT_KEY) {
205             String::deserialize(web_element)
206                 .map(|id| PointerOrigin::Element(WebElement(id)))
207                 .map_err(de::Error::custom)
208         } else if value == "pointer" {
209             Ok(PointerOrigin::Pointer)
210         } else if value == "viewport" {
211             Ok(PointerOrigin::Viewport)
212         } else {
213             Err(de::Error::custom(format!(
214                 "unknown value `{}`, expected `pointer`, `viewport`, or `element-6066-11e4-a52e-4f735466cecf`",
215                 value.to_string()
216             )))
217         }
218     }
219 }
220 
serialize_webelement_id<S>(element: &WebElement, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,221 fn serialize_webelement_id<S>(element: &WebElement, serializer: S) -> Result<S::Ok, S::Error>
222 where
223     S: Serializer,
224 {
225     element.to_string().serialize(serializer)
226 }
227 
deserialize_to_option_i64<'de, D>(deserializer: D) -> Result<Option<i64>, D::Error> where D: Deserializer<'de>,228 fn deserialize_to_option_i64<'de, D>(deserializer: D) -> Result<Option<i64>, D::Error>
229 where
230     D: Deserializer<'de>,
231 {
232     Option::deserialize(deserializer)?
233         .ok_or_else(|| de::Error::custom("invalid type: null, expected i64"))
234 }
235 
deserialize_to_option_u64<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error> where D: Deserializer<'de>,236 fn deserialize_to_option_u64<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
237 where
238     D: Deserializer<'de>,
239 {
240     Option::deserialize(deserializer)?
241         .ok_or_else(|| de::Error::custom("invalid type: null, expected i64"))
242 }
243 
244 #[cfg(test)]
245 mod test {
246     use super::*;
247     use crate::test::{assert_de, assert_ser_de};
248     use serde_json::{self, json};
249 
250     #[test]
test_json_action_sequence_null()251     fn test_json_action_sequence_null() {
252         let json = json!({
253             "id": "some_key",
254             "type": "none",
255             "actions": [{
256                 "type": "pause",
257                 "duration": 1,
258             }]
259         });
260         let seq = ActionSequence {
261             id: "some_key".into(),
262             actions: ActionsType::Null {
263                 actions: vec![NullActionItem::General(GeneralAction::Pause(PauseAction {
264                     duration: Some(1),
265                 }))],
266             },
267         };
268 
269         assert_ser_de(&seq, json);
270     }
271 
272     #[test]
test_json_action_sequence_key()273     fn test_json_action_sequence_key() {
274         let json = json!({
275             "id": "some_key",
276             "type": "key",
277             "actions": [
278                 {"type": "keyDown", "value": "f"},
279             ],
280         });
281         let seq = ActionSequence {
282             id: "some_key".into(),
283             actions: ActionsType::Key {
284                 actions: vec![KeyActionItem::Key(KeyAction::Down(KeyDownAction {
285                     value: String::from("f"),
286                 }))],
287             },
288         };
289 
290         assert_ser_de(&seq, json);
291     }
292 
293     #[test]
test_json_action_sequence_pointer()294     fn test_json_action_sequence_pointer() {
295         let json = json!({
296             "id": "some_pointer",
297             "type": "pointer",
298             "parameters": {
299                 "pointerType": "mouse"
300             },
301             "actions": [
302                 {"type": "pointerDown", "button": 0},
303                 {"type": "pointerMove", "origin": "pointer", "x": 10, "y": 20},
304                 {"type": "pointerUp", "button": 0},
305             ]
306         });
307         let seq = ActionSequence {
308             id: "some_pointer".into(),
309             actions: ActionsType::Pointer {
310                 parameters: PointerActionParameters {
311                     pointer_type: PointerType::Mouse,
312                 },
313                 actions: vec![
314                     PointerActionItem::Pointer(PointerAction::Down(PointerDownAction {
315                         button: 0,
316                     })),
317                     PointerActionItem::Pointer(PointerAction::Move(PointerMoveAction {
318                         origin: PointerOrigin::Pointer,
319                         duration: None,
320                         x: Some(10),
321                         y: Some(20),
322                     })),
323                     PointerActionItem::Pointer(PointerAction::Up(PointerUpAction { button: 0 })),
324                 ],
325             },
326         };
327 
328         assert_ser_de(&seq, json);
329     }
330 
331     #[test]
test_json_action_sequence_id_missing()332     fn test_json_action_sequence_id_missing() {
333         let json = json!({
334             "type": "key",
335             "actions": [],
336         });
337         assert!(serde_json::from_value::<ActionSequence>(json).is_err());
338     }
339 
340     #[test]
test_json_action_sequence_id_null()341     fn test_json_action_sequence_id_null() {
342         let json = json!({
343             "id": null,
344             "type": "key",
345             "actions": [],
346         });
347         assert!(serde_json::from_value::<ActionSequence>(json).is_err());
348     }
349 
350     #[test]
test_json_action_sequence_actions_missing()351     fn test_json_action_sequence_actions_missing() {
352         assert!(serde_json::from_value::<ActionSequence>(json!({"id": "3"})).is_err());
353     }
354 
355     #[test]
test_json_action_sequence_actions_null()356     fn test_json_action_sequence_actions_null() {
357         let json = json!({
358             "id": "3",
359             "actions": null,
360         });
361         assert!(serde_json::from_value::<ActionSequence>(json).is_err());
362     }
363 
364     #[test]
test_json_action_sequence_actions_invalid_type()365     fn test_json_action_sequence_actions_invalid_type() {
366         let json = json!({
367             "id": "3",
368             "actions": "foo",
369         });
370         assert!(serde_json::from_value::<ActionSequence>(json).is_err());
371     }
372 
373     #[test]
test_json_actions_type_null()374     fn test_json_actions_type_null() {
375         let json = json!({
376             "type": "none",
377             "actions": [{
378                 "type": "pause",
379                 "duration": 1,
380             }],
381         });
382         let null = ActionsType::Null {
383             actions: vec![NullActionItem::General(GeneralAction::Pause(PauseAction {
384                 duration: Some(1),
385             }))],
386         };
387 
388         assert_ser_de(&null, json);
389     }
390 
391     #[test]
test_json_actions_type_key()392     fn test_json_actions_type_key() {
393         let json = json!({
394             "type": "key",
395             "actions": [{
396                 "type": "keyDown",
397                 "value": "f",
398             }],
399         });
400         let key = ActionsType::Key {
401             actions: vec![KeyActionItem::Key(KeyAction::Down(KeyDownAction {
402                 value: String::from("f"),
403             }))],
404         };
405 
406         assert_ser_de(&key, json);
407     }
408 
409     #[test]
test_json_actions_type_pointer()410     fn test_json_actions_type_pointer() {
411         let json = json!({
412         "type": "pointer",
413         "parameters": {"pointerType": "mouse"},
414         "actions": [
415             {"type": "pointerDown", "button": 1},
416         ]});
417         let pointer = ActionsType::Pointer {
418             parameters: PointerActionParameters {
419                 pointer_type: PointerType::Mouse,
420             },
421             actions: vec![PointerActionItem::Pointer(PointerAction::Down(
422                 PointerDownAction { button: 1 },
423             ))],
424         };
425 
426         assert_ser_de(&pointer, json);
427     }
428 
429     #[test]
test_json_actions_type_pointer_with_parameters_missing()430     fn test_json_actions_type_pointer_with_parameters_missing() {
431         let json = json!({
432         "type": "pointer",
433         "actions": [
434             {"type": "pointerDown", "button": 1},
435         ]});
436         let pointer = ActionsType::Pointer {
437             parameters: PointerActionParameters {
438                 pointer_type: PointerType::Mouse,
439             },
440             actions: vec![PointerActionItem::Pointer(PointerAction::Down(
441                 PointerDownAction { button: 1 },
442             ))],
443         };
444 
445         assert_de(&pointer, json);
446     }
447 
448     #[test]
test_json_actions_type_pointer_with_parameters_invalid_type()449     fn test_json_actions_type_pointer_with_parameters_invalid_type() {
450         let json = json!({
451         "type": "pointer",
452         "parameters": null,
453         "actions": [
454             {"type":"pointerDown", "button": 1},
455         ]});
456         assert!(serde_json::from_value::<ActionsType>(json).is_err());
457     }
458 
459     #[test]
test_json_actions_type_invalid()460     fn test_json_actions_type_invalid() {
461         let json = json!({"actions": [{"foo": "bar"}]});
462         assert!(serde_json::from_value::<ActionsType>(json).is_err());
463     }
464 
465     #[test]
test_json_null_action_item_general()466     fn test_json_null_action_item_general() {
467         let pause =
468             NullActionItem::General(GeneralAction::Pause(PauseAction { duration: Some(1) }));
469         assert_ser_de(&pause, json!({"type": "pause", "duration": 1}));
470     }
471 
472     #[test]
test_json_null_action_item_invalid_type()473     fn test_json_null_action_item_invalid_type() {
474         assert!(serde_json::from_value::<NullActionItem>(json!({"type": "invalid"})).is_err());
475     }
476 
477     #[test]
test_json_general_action_pause()478     fn test_json_general_action_pause() {
479         let pause = GeneralAction::Pause(PauseAction { duration: Some(1) });
480         assert_ser_de(&pause, json!({"type": "pause", "duration": 1}));
481     }
482 
483     #[test]
test_json_general_action_pause_with_duration_missing()484     fn test_json_general_action_pause_with_duration_missing() {
485         let pause = GeneralAction::Pause(PauseAction { duration: None });
486         assert_ser_de(&pause, json!({"type": "pause"}));
487     }
488 
489     #[test]
test_json_general_action_pause_with_duration_null()490     fn test_json_general_action_pause_with_duration_null() {
491         let json = json!({"type": "pause", "duration": null});
492         assert!(serde_json::from_value::<GeneralAction>(json).is_err());
493     }
494 
495     #[test]
test_json_general_action_pause_with_duration_invalid_type()496     fn test_json_general_action_pause_with_duration_invalid_type() {
497         let json = json!({"type": "pause", "duration":" foo"});
498         assert!(serde_json::from_value::<GeneralAction>(json).is_err());
499     }
500 
501     #[test]
test_json_general_action_pause_with_duration_negative()502     fn test_json_general_action_pause_with_duration_negative() {
503         let json = json!({"type": "pause", "duration": -30});
504         assert!(serde_json::from_value::<GeneralAction>(json).is_err());
505     }
506 
507     #[test]
test_json_key_action_item_general()508     fn test_json_key_action_item_general() {
509         let pause = KeyActionItem::General(GeneralAction::Pause(PauseAction { duration: Some(1) }));
510         assert_ser_de(&pause, json!({"type": "pause", "duration": 1}));
511     }
512 
513     #[test]
test_json_key_action_item_key()514     fn test_json_key_action_item_key() {
515         let key_down = KeyActionItem::Key(KeyAction::Down(KeyDownAction {
516             value: String::from("f"),
517         }));
518         assert_ser_de(&key_down, json!({"type": "keyDown", "value": "f"}));
519     }
520 
521     #[test]
test_json_key_action_item_invalid_type()522     fn test_json_key_action_item_invalid_type() {
523         assert!(serde_json::from_value::<KeyActionItem>(json!({"type": "invalid"})).is_err());
524     }
525 
526     #[test]
test_json_key_action_missing_subtype()527     fn test_json_key_action_missing_subtype() {
528         assert!(serde_json::from_value::<KeyAction>(json!({"value": "f"})).is_err());
529     }
530 
531     #[test]
test_json_key_action_wrong_subtype()532     fn test_json_key_action_wrong_subtype() {
533         let json = json!({"type": "pause", "value": "f"});
534         assert!(serde_json::from_value::<KeyAction>(json).is_err());
535     }
536 
537     #[test]
test_json_key_action_down()538     fn test_json_key_action_down() {
539         let key_down = KeyAction::Down(KeyDownAction {
540             value: "f".to_string(),
541         });
542         assert_ser_de(&key_down, json!({"type": "keyDown", "value": "f"}));
543     }
544 
545     #[test]
test_json_key_action_down_with_value_unicode()546     fn test_json_key_action_down_with_value_unicode() {
547         let key_down = KeyAction::Down(KeyDownAction {
548             value: "à".to_string(),
549         });
550         assert_ser_de(&key_down, json!({"type": "keyDown", "value": "à"}));
551     }
552 
553     #[test]
test_json_key_action_down_with_value_unicode_encoded()554     fn test_json_key_action_down_with_value_unicode_encoded() {
555         let key_down = KeyAction::Down(KeyDownAction {
556             value: "à".to_string(),
557         });
558         assert_de(&key_down, json!({"type": "keyDown", "value": "\u{00E0}"}));
559     }
560 
561     #[test]
test_json_key_action_down_with_value_missing()562     fn test_json_key_action_down_with_value_missing() {
563         assert!(serde_json::from_value::<KeyAction>(json!({"type": "keyDown"})).is_err());
564     }
565 
566     #[test]
test_json_key_action_down_with_value_null()567     fn test_json_key_action_down_with_value_null() {
568         let json = json!({"type": "keyDown", "value": null});
569         assert!(serde_json::from_value::<KeyAction>(json).is_err());
570     }
571 
572     #[test]
test_json_key_action_down_with_value_invalid_type()573     fn test_json_key_action_down_with_value_invalid_type() {
574         let json = json!({"type": "keyDown", "value": ["f", "o", "o"]});
575         assert!(serde_json::from_value::<KeyAction>(json).is_err());
576     }
577 
578     #[test]
test_json_key_action_down_with_multiple_code_points()579     fn test_json_key_action_down_with_multiple_code_points() {
580         let json = json!({"type": "keyDown", "value": "fo"});
581         assert!(serde_json::from_value::<KeyAction>(json).is_err());
582     }
583 
584     #[test]
test_json_key_action_up()585     fn test_json_key_action_up() {
586         let key_up = KeyAction::Up(KeyUpAction {
587             value: "f".to_string(),
588         });
589         assert_ser_de(&key_up, json!({"type": "keyUp", "value": "f"}));
590     }
591 
592     #[test]
test_json_key_action_up_with_value_unicode()593     fn test_json_key_action_up_with_value_unicode() {
594         let key_up = KeyAction::Up(KeyUpAction {
595             value: "à".to_string(),
596         });
597         assert_ser_de(&key_up, json!({"type":"keyUp", "value": "à"}));
598     }
599 
600     #[test]
test_json_key_action_up_with_value_unicode_encoded()601     fn test_json_key_action_up_with_value_unicode_encoded() {
602         let key_up = KeyAction::Up(KeyUpAction {
603             value: "à".to_string(),
604         });
605         assert_de(&key_up, json!({"type": "keyUp", "value": "\u{00E0}"}));
606     }
607 
608     #[test]
test_json_key_action_up_with_value_missing()609     fn test_json_key_action_up_with_value_missing() {
610         assert!(serde_json::from_value::<KeyAction>(json!({"type": "keyUp"})).is_err());
611     }
612 
613     #[test]
test_json_key_action_up_with_value_null()614     fn test_json_key_action_up_with_value_null() {
615         let json = json!({"type": "keyUp", "value": null});
616         assert!(serde_json::from_value::<KeyAction>(json).is_err());
617     }
618 
619     #[test]
test_json_key_action_up_with_value_invalid_type()620     fn test_json_key_action_up_with_value_invalid_type() {
621         let json = json!({"type": "keyUp", "value": ["f","o","o"]});
622         assert!(serde_json::from_value::<KeyAction>(json).is_err());
623     }
624 
625     #[test]
test_json_key_action_up_with_multiple_code_points()626     fn test_json_key_action_up_with_multiple_code_points() {
627         let json = json!({"type": "keyUp", "value": "fo"});
628         assert!(serde_json::from_value::<KeyAction>(json).is_err());
629     }
630 
631     #[test]
test_json_pointer_action_item_general()632     fn test_json_pointer_action_item_general() {
633         let pause =
634             PointerActionItem::General(GeneralAction::Pause(PauseAction { duration: Some(1) }));
635         assert_ser_de(&pause, json!({"type": "pause", "duration": 1}));
636     }
637 
638     #[test]
test_json_pointer_action_item_pointer()639     fn test_json_pointer_action_item_pointer() {
640         let cancel = PointerActionItem::Pointer(PointerAction::Cancel);
641         assert_ser_de(&cancel, json!({"type": "pointerCancel"}));
642     }
643 
644     #[test]
test_json_pointer_action_item_invalid()645     fn test_json_pointer_action_item_invalid() {
646         assert!(serde_json::from_value::<PointerActionItem>(json!({"type": "invalid"})).is_err());
647     }
648 
649     #[test]
test_json_pointer_action_parameters_mouse()650     fn test_json_pointer_action_parameters_mouse() {
651         let mouse = PointerActionParameters {
652             pointer_type: PointerType::Mouse,
653         };
654         assert_ser_de(&mouse, json!({"pointerType": "mouse"}));
655     }
656 
657     #[test]
test_json_pointer_action_parameters_pen()658     fn test_json_pointer_action_parameters_pen() {
659         let pen = PointerActionParameters {
660             pointer_type: PointerType::Pen,
661         };
662         assert_ser_de(&pen, json!({"pointerType": "pen"}));
663     }
664 
665     #[test]
test_json_pointer_action_parameters_touch()666     fn test_json_pointer_action_parameters_touch() {
667         let touch = PointerActionParameters {
668             pointer_type: PointerType::Touch,
669         };
670         assert_ser_de(&touch, json!({"pointerType": "touch"}));
671     }
672 
673     #[test]
test_json_pointer_action_item_invalid_type()674     fn test_json_pointer_action_item_invalid_type() {
675         let json = json!({"type": "pointerInvalid"});
676         assert!(serde_json::from_value::<PointerActionItem>(json).is_err());
677     }
678 
679     #[test]
test_json_pointer_action_missing_subtype()680     fn test_json_pointer_action_missing_subtype() {
681         assert!(serde_json::from_value::<PointerAction>(json!({"button": 1})).is_err());
682     }
683 
684     #[test]
test_json_pointer_action_invalid_subtype()685     fn test_json_pointer_action_invalid_subtype() {
686         let json = json!({"type": "invalid", "button": 1});
687         assert!(serde_json::from_value::<PointerAction>(json).is_err());
688     }
689 
690     #[test]
test_json_pointer_action_cancel()691     fn test_json_pointer_action_cancel() {
692         assert_ser_de(&PointerAction::Cancel, json!({"type": "pointerCancel"}));
693     }
694 
695     #[test]
test_json_pointer_action_down()696     fn test_json_pointer_action_down() {
697         let pointer_down = PointerAction::Down(PointerDownAction { button: 1 });
698         assert_ser_de(&pointer_down, json!({"type": "pointerDown", "button": 1}));
699     }
700 
701     #[test]
test_json_pointer_action_down_with_button_missing()702     fn test_json_pointer_action_down_with_button_missing() {
703         let json = json!({"type": "pointerDown"});
704         assert!(serde_json::from_value::<PointerAction>(json).is_err());
705     }
706 
707     #[test]
test_json_pointer_action_down_with_button_null()708     fn test_json_pointer_action_down_with_button_null() {
709         let json = json!({
710             "type": "pointerDown",
711             "button": null,
712         });
713         assert!(serde_json::from_value::<PointerAction>(json).is_err());
714     }
715 
716     #[test]
test_json_pointer_action_down_with_button_invalid_type()717     fn test_json_pointer_action_down_with_button_invalid_type() {
718         let json = json!({
719             "type": "pointerDown",
720             "button": "foo",
721         });
722         assert!(serde_json::from_value::<PointerAction>(json).is_err());
723     }
724 
725     #[test]
test_json_pointer_action_down_with_button_negative()726     fn test_json_pointer_action_down_with_button_negative() {
727         let json = json!({
728             "type": "pointerDown",
729             "button": -30,
730         });
731         assert!(serde_json::from_value::<PointerAction>(json).is_err());
732     }
733 
734     #[test]
test_json_pointer_action_move()735     fn test_json_pointer_action_move() {
736         let json = json!({
737             "type": "pointerMove",
738             "duration": 100,
739             "origin": "viewport",
740             "x": 5,
741             "y": 10,
742         });
743         let pointer_move = PointerAction::Move(PointerMoveAction {
744             duration: Some(100),
745             origin: PointerOrigin::Viewport,
746             x: Some(5),
747             y: Some(10),
748         });
749 
750         assert_ser_de(&pointer_move, json);
751     }
752 
753     #[test]
test_json_pointer_action_move_missing_subtype()754     fn test_json_pointer_action_move_missing_subtype() {
755         let json = json!({
756             "duration": 100,
757             "origin": "viewport",
758             "x": 5,
759             "y": 10,
760         });
761         assert!(serde_json::from_value::<PointerAction>(json).is_err());
762     }
763 
764     #[test]
test_json_pointer_action_move_wrong_subtype()765     fn test_json_pointer_action_move_wrong_subtype() {
766         let json = json!({
767             "type": "pointerUp",
768             "duration": 100,
769             "origin": "viewport",
770             "x": 5,
771             "y": 10,
772         });
773         assert!(serde_json::from_value::<PointerAction>(json).is_err());
774     }
775 
776     #[test]
test_json_pointer_action_move_with_duration_missing()777     fn test_json_pointer_action_move_with_duration_missing() {
778         let json = json!({
779             "type": "pointerMove",
780             "origin": "viewport",
781             "x": 5,
782             "y": 10,
783         });
784         let pointer_move = PointerAction::Move(PointerMoveAction {
785             duration: None,
786             origin: PointerOrigin::Viewport,
787             x: Some(5),
788             y: Some(10),
789         });
790 
791         assert_ser_de(&pointer_move, json);
792     }
793 
794     #[test]
test_json_pointer_action_move_with_duration_null()795     fn test_json_pointer_action_move_with_duration_null() {
796         let json = json!({
797             "type": "pointerMove",
798             "duration": null,
799             "origin": "viewport",
800             "x": 5,
801             "y": 10,
802         });
803         assert!(serde_json::from_value::<PointerAction>(json).is_err());
804     }
805 
806     #[test]
test_json_pointer_action_move_with_duration_invalid_type()807     fn test_json_pointer_action_move_with_duration_invalid_type() {
808         let json = json!({
809             "type": "pointerMove",
810             "duration": "invalid",
811             "origin": "viewport",
812             "x": 5,
813             "y": 10,
814         });
815         assert!(serde_json::from_value::<PointerAction>(json).is_err());
816     }
817 
818     #[test]
test_json_pointer_action_move_with_duration_negative()819     fn test_json_pointer_action_move_with_duration_negative() {
820         let json = json!({
821             "type": "pointerMove",
822             "duration": -30,
823             "origin": "viewport",
824             "x": 5,
825             "y": 10,
826         });
827         assert!(serde_json::from_value::<PointerAction>(json).is_err());
828     }
829 
830     #[test]
test_json_pointer_action_move_with_origin_missing()831     fn test_json_pointer_action_move_with_origin_missing() {
832         let json = json!({
833             "type": "pointerMove",
834             "duration": 100,
835             "x": 5,
836             "y": 10,
837         });
838         let pointer_move = PointerAction::Move(PointerMoveAction {
839             duration: Some(100),
840             origin: PointerOrigin::Viewport,
841             x: Some(5),
842             y: Some(10),
843         });
844 
845         assert_de(&pointer_move, json);
846     }
847 
848     #[test]
test_json_pointer_action_move_with_origin_webelement()849     fn test_json_pointer_action_move_with_origin_webelement() {
850         let json = json!({
851             "type": "pointerMove",
852             "duration": 100,
853             "origin": {ELEMENT_KEY: "elem"},
854             "x": 5,
855             "y": 10,
856         });
857         let pointer_move = PointerAction::Move(PointerMoveAction {
858             duration: Some(100),
859             origin: PointerOrigin::Element(WebElement("elem".into())),
860             x: Some(5),
861             y: Some(10),
862         });
863 
864         assert_ser_de(&pointer_move, json);
865     }
866 
867     #[test]
test_json_pointer_action_move_with_origin_webelement_and_legacy_element()868     fn test_json_pointer_action_move_with_origin_webelement_and_legacy_element() {
869         let json = json!({
870             "type": "pointerMove",
871             "duration": 100,
872             "origin": {ELEMENT_KEY: "elem"},
873             "x": 5,
874             "y": 10,
875         });
876         let pointer_move = PointerAction::Move(PointerMoveAction {
877             duration: Some(100),
878             origin: PointerOrigin::Element(WebElement("elem".into())),
879             x: Some(5),
880             y: Some(10),
881         });
882 
883         assert_de(&pointer_move, json);
884     }
885 
886     #[test]
test_json_pointer_action_move_with_origin_only_legacy_element()887     fn test_json_pointer_action_move_with_origin_only_legacy_element() {
888         let json = json!({
889             "type": "pointerMove",
890             "duration": 100,
891             "origin": {ELEMENT_KEY: "elem"},
892             "x": 5,
893             "y": 10,
894         });
895         assert!(serde_json::from_value::<PointerOrigin>(json).is_err());
896     }
897 
898     #[test]
test_json_pointer_action_move_with_x_missing()899     fn test_json_pointer_action_move_with_x_missing() {
900         let json = json!({
901             "type": "pointerMove",
902             "duration": 100,
903             "origin": "viewport",
904             "y": 10,
905         });
906         let pointer_move = PointerAction::Move(PointerMoveAction {
907             duration: Some(100),
908             origin: PointerOrigin::Viewport,
909             x: None,
910             y: Some(10),
911         });
912 
913         assert_ser_de(&pointer_move, json);
914     }
915 
916     #[test]
test_json_pointer_action_move_with_x_null()917     fn test_json_pointer_action_move_with_x_null() {
918         let json = json!({
919             "type": "pointerMove",
920             "duration": 100,
921             "origin": "viewport",
922             "x": null,
923             "y": 10,
924         });
925         assert!(serde_json::from_value::<PointerAction>(json).is_err());
926     }
927 
928     #[test]
test_json_pointer_action_move_with_x_invalid_type()929     fn test_json_pointer_action_move_with_x_invalid_type() {
930         let json = json!({
931             "type": "pointerMove",
932             "duration": 100,
933             "origin": "viewport",
934             "x": "invalid",
935             "y": 10,
936         });
937         assert!(serde_json::from_value::<PointerAction>(json).is_err());
938     }
939 
940     #[test]
test_json_pointer_action_move_with_y_missing()941     fn test_json_pointer_action_move_with_y_missing() {
942         let json = json!({
943             "type": "pointerMove",
944             "duration": 100,
945             "origin": "viewport",
946             "x": 5,
947         });
948         let pointer_move = PointerAction::Move(PointerMoveAction {
949             duration: Some(100),
950             origin: PointerOrigin::Viewport,
951             x: Some(5),
952             y: None,
953         });
954 
955         assert_ser_de(&pointer_move, json);
956     }
957 
958     #[test]
test_json_pointer_action_move_with_y_null()959     fn test_json_pointer_action_move_with_y_null() {
960         let json = json!({
961             "type": "pointerMove",
962             "duration": 100,
963             "origin": "viewport",
964             "x": 5,
965             "y": null,
966         });
967         assert!(serde_json::from_value::<PointerAction>(json).is_err());
968     }
969 
970     #[test]
test_json_pointer_action_move_with_y_invalid_type()971     fn test_json_pointer_action_move_with_y_invalid_type() {
972         let json = json!({
973             "type": "pointerMove",
974             "duration": 100,
975             "origin": "viewport",
976             "x": 5,
977             "y": "invalid",
978         });
979         assert!(serde_json::from_value::<PointerAction>(json).is_err());
980     }
981 
982     #[test]
test_json_pointer_action_up()983     fn test_json_pointer_action_up() {
984         let pointer_up = PointerAction::Up(PointerUpAction { button: 1 });
985         assert_ser_de(&pointer_up, json!({"type": "pointerUp", "button": 1}));
986     }
987 
988     #[test]
test_json_pointer_action_up_with_button_missing()989     fn test_json_pointer_action_up_with_button_missing() {
990         assert!(serde_json::from_value::<PointerAction>(json!({"type": "pointerUp"})).is_err());
991     }
992 
993     #[test]
test_json_pointer_action_up_with_button_null()994     fn test_json_pointer_action_up_with_button_null() {
995         let json = json!({
996             "type": "pointerUp",
997             "button": null,
998         });
999         assert!(serde_json::from_value::<PointerAction>(json).is_err());
1000     }
1001 
1002     #[test]
test_json_pointer_action_up_with_button_invalid_type()1003     fn test_json_pointer_action_up_with_button_invalid_type() {
1004         let json = json!({
1005             "type": "pointerUp",
1006             "button": "foo",
1007         });
1008         assert!(serde_json::from_value::<PointerAction>(json).is_err());
1009     }
1010 
1011     #[test]
test_json_pointer_action_up_with_button_negative()1012     fn test_json_pointer_action_up_with_button_negative() {
1013         let json = json!({
1014             "type": "pointerUp",
1015             "button": -30,
1016         });
1017         assert!(serde_json::from_value::<PointerAction>(json).is_err());
1018     }
1019 
1020     #[test]
test_json_pointer_origin_pointer()1021     fn test_json_pointer_origin_pointer() {
1022         assert_ser_de(&PointerOrigin::Pointer, json!("pointer"));
1023     }
1024 
1025     #[test]
test_json_pointer_origin_viewport()1026     fn test_json_pointer_origin_viewport() {
1027         assert_ser_de(&PointerOrigin::Viewport, json!("viewport"));
1028     }
1029 
1030     #[test]
test_json_pointer_origin_web_element()1031     fn test_json_pointer_origin_web_element() {
1032         let element = PointerOrigin::Element(WebElement("elem".into()));
1033         assert_ser_de(&element, json!({ELEMENT_KEY: "elem"}));
1034     }
1035 
1036     #[test]
test_json_pointer_origin_invalid_type()1037     fn test_json_pointer_origin_invalid_type() {
1038         assert!(serde_json::from_value::<PointerOrigin>(json!("invalid")).is_err());
1039     }
1040 
1041     #[test]
test_json_pointer_type_mouse()1042     fn test_json_pointer_type_mouse() {
1043         assert_ser_de(&PointerType::Mouse, json!("mouse"));
1044     }
1045 
1046     #[test]
test_json_pointer_type_pen()1047     fn test_json_pointer_type_pen() {
1048         assert_ser_de(&PointerType::Pen, json!("pen"));
1049     }
1050 
1051     #[test]
test_json_pointer_type_touch()1052     fn test_json_pointer_type_touch() {
1053         assert_ser_de(&PointerType::Touch, json!("touch"));
1054     }
1055 
1056     #[test]
test_json_pointer_type_invalid_type()1057     fn test_json_pointer_type_invalid_type() {
1058         assert!(serde_json::from_value::<PointerType>(json!("invalid")).is_err());
1059     }
1060 }
1061