tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

actions.rs (41985B)


      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 icu_segmenter::GraphemeClusterSegmenter;
      7 use serde::de::{self, Deserialize, Deserializer};
      8 use serde::ser::{Serialize, Serializer};
      9 use serde_json::Value;
     10 use std::default::Default;
     11 use std::f64;
     12 
     13 #[derive(Debug, PartialEq, Serialize, Deserialize)]
     14 pub struct ActionSequence {
     15    pub id: String,
     16    #[serde(flatten)]
     17    pub actions: ActionsType,
     18 }
     19 
     20 #[derive(Debug, PartialEq, Serialize, Deserialize)]
     21 #[serde(tag = "type")]
     22 pub enum ActionsType {
     23    #[serde(rename = "none")]
     24    Null { actions: Vec<NullActionItem> },
     25    #[serde(rename = "key")]
     26    Key { actions: Vec<KeyActionItem> },
     27    #[serde(rename = "pointer")]
     28    Pointer {
     29        #[serde(default)]
     30        parameters: PointerActionParameters,
     31        actions: Vec<PointerActionItem>,
     32    },
     33    #[serde(rename = "wheel")]
     34    Wheel { actions: Vec<WheelActionItem> },
     35 }
     36 
     37 #[derive(Debug, PartialEq, Serialize, Deserialize)]
     38 #[serde(untagged)]
     39 pub enum NullActionItem {
     40    General(GeneralAction),
     41 }
     42 
     43 #[derive(Debug, PartialEq, Serialize, Deserialize)]
     44 #[serde(tag = "type")]
     45 pub enum GeneralAction {
     46    #[serde(rename = "pause")]
     47    Pause(PauseAction),
     48 }
     49 
     50 #[derive(Debug, PartialEq, Serialize, Deserialize)]
     51 pub struct PauseAction {
     52    #[serde(
     53        default,
     54        skip_serializing_if = "Option::is_none",
     55        deserialize_with = "deserialize_to_option_u64"
     56    )]
     57    pub duration: Option<u64>,
     58 }
     59 
     60 #[derive(Debug, PartialEq, Serialize, Deserialize)]
     61 #[serde(untagged)]
     62 pub enum KeyActionItem {
     63    General(GeneralAction),
     64    Key(KeyAction),
     65 }
     66 
     67 #[derive(Debug, PartialEq, Serialize, Deserialize)]
     68 #[serde(tag = "type")]
     69 pub enum KeyAction {
     70    #[serde(rename = "keyDown")]
     71    Down(KeyDownAction),
     72    #[serde(rename = "keyUp")]
     73    Up(KeyUpAction),
     74 }
     75 
     76 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
     77 pub struct KeyDownAction {
     78    #[serde(deserialize_with = "deserialize_key_action_value")]
     79    pub value: String,
     80 }
     81 
     82 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
     83 pub struct KeyUpAction {
     84    #[serde(deserialize_with = "deserialize_key_action_value")]
     85    pub value: String,
     86 }
     87 
     88 fn deserialize_key_action_value<'de, D>(deserializer: D) -> Result<String, D::Error>
     89 where
     90    D: Deserializer<'de>,
     91 {
     92    String::deserialize(deserializer).map(|value| {
     93        // Only a single Unicode grapheme cluster is allowed
     94        if GraphemeClusterSegmenter::new().segment_str(&value).count() != 2 {
     95            return Err(de::Error::custom(format!(
     96                "'{}' should only contain a single Unicode code point",
     97                value
     98            )));
     99        }
    100 
    101        Ok(value)
    102    })?
    103 }
    104 
    105 #[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
    106 #[serde(rename_all = "lowercase")]
    107 pub enum PointerType {
    108    #[default]
    109    Mouse,
    110    Pen,
    111    Touch,
    112 }
    113 
    114 #[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
    115 pub struct PointerActionParameters {
    116    #[serde(rename = "pointerType")]
    117    pub pointer_type: PointerType,
    118 }
    119 
    120 #[derive(Debug, PartialEq, Serialize, Deserialize)]
    121 #[serde(untagged)]
    122 pub enum PointerActionItem {
    123    General(GeneralAction),
    124    Pointer(PointerAction),
    125 }
    126 
    127 #[derive(Debug, PartialEq, Serialize, Deserialize)]
    128 #[serde(tag = "type")]
    129 pub enum PointerAction {
    130    #[serde(rename = "pointerCancel")]
    131    Cancel,
    132    #[serde(rename = "pointerDown")]
    133    Down(PointerDownAction),
    134    #[serde(rename = "pointerMove")]
    135    Move(PointerMoveAction),
    136    #[serde(rename = "pointerUp")]
    137    Up(PointerUpAction),
    138 }
    139 
    140 #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
    141 pub struct PointerDownAction {
    142    pub button: u64,
    143    #[serde(
    144        default,
    145        skip_serializing_if = "Option::is_none",
    146        deserialize_with = "deserialize_to_option_u64"
    147    )]
    148    pub width: Option<u64>,
    149    #[serde(
    150        default,
    151        skip_serializing_if = "Option::is_none",
    152        deserialize_with = "deserialize_to_option_u64"
    153    )]
    154    pub height: Option<u64>,
    155    #[serde(
    156        default,
    157        skip_serializing_if = "Option::is_none",
    158        deserialize_with = "deserialize_to_pressure"
    159    )]
    160    pub pressure: Option<f64>,
    161    #[serde(
    162        default,
    163        skip_serializing_if = "Option::is_none",
    164        deserialize_with = "deserialize_to_tangential_pressure"
    165    )]
    166    pub tangentialPressure: Option<f64>,
    167    #[serde(
    168        default,
    169        skip_serializing_if = "Option::is_none",
    170        deserialize_with = "deserialize_to_tilt"
    171    )]
    172    pub tiltX: Option<i64>,
    173    #[serde(
    174        default,
    175        skip_serializing_if = "Option::is_none",
    176        deserialize_with = "deserialize_to_tilt"
    177    )]
    178    pub tiltY: Option<i64>,
    179    #[serde(
    180        default,
    181        skip_serializing_if = "Option::is_none",
    182        deserialize_with = "deserialize_to_twist"
    183    )]
    184    pub twist: Option<u64>,
    185    #[serde(
    186        default,
    187        skip_serializing_if = "Option::is_none",
    188        deserialize_with = "deserialize_to_altitude_angle"
    189    )]
    190    pub altitudeAngle: Option<f64>,
    191    #[serde(
    192        default,
    193        skip_serializing_if = "Option::is_none",
    194        deserialize_with = "deserialize_to_azimuth_angle"
    195    )]
    196    pub azimuthAngle: Option<f64>,
    197 }
    198 
    199 #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
    200 pub struct PointerMoveAction {
    201    #[serde(
    202        default,
    203        skip_serializing_if = "Option::is_none",
    204        deserialize_with = "deserialize_to_option_u64"
    205    )]
    206    pub duration: Option<u64>,
    207    #[serde(default)]
    208    pub origin: PointerOrigin,
    209    pub x: f64,
    210    pub y: f64,
    211    #[serde(
    212        default,
    213        skip_serializing_if = "Option::is_none",
    214        deserialize_with = "deserialize_to_option_u64"
    215    )]
    216    pub width: Option<u64>,
    217    #[serde(
    218        default,
    219        skip_serializing_if = "Option::is_none",
    220        deserialize_with = "deserialize_to_option_u64"
    221    )]
    222    pub height: Option<u64>,
    223    #[serde(
    224        default,
    225        skip_serializing_if = "Option::is_none",
    226        deserialize_with = "deserialize_to_pressure"
    227    )]
    228    pub pressure: Option<f64>,
    229    #[serde(
    230        default,
    231        skip_serializing_if = "Option::is_none",
    232        deserialize_with = "deserialize_to_tangential_pressure"
    233    )]
    234    pub tangentialPressure: Option<f64>,
    235    #[serde(
    236        default,
    237        skip_serializing_if = "Option::is_none",
    238        deserialize_with = "deserialize_to_tilt"
    239    )]
    240    pub tiltX: Option<i64>,
    241    #[serde(
    242        default,
    243        skip_serializing_if = "Option::is_none",
    244        deserialize_with = "deserialize_to_tilt"
    245    )]
    246    pub tiltY: Option<i64>,
    247    #[serde(
    248        default,
    249        skip_serializing_if = "Option::is_none",
    250        deserialize_with = "deserialize_to_twist"
    251    )]
    252    pub twist: Option<u64>,
    253    #[serde(
    254        default,
    255        skip_serializing_if = "Option::is_none",
    256        deserialize_with = "deserialize_to_altitude_angle"
    257    )]
    258    pub altitudeAngle: Option<f64>,
    259    #[serde(
    260        default,
    261        skip_serializing_if = "Option::is_none",
    262        deserialize_with = "deserialize_to_azimuth_angle"
    263    )]
    264    pub azimuthAngle: Option<f64>,
    265 }
    266 
    267 #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
    268 pub struct PointerUpAction {
    269    pub button: u64,
    270    #[serde(
    271        default,
    272        skip_serializing_if = "Option::is_none",
    273        deserialize_with = "deserialize_to_option_u64"
    274    )]
    275    pub width: Option<u64>,
    276    #[serde(
    277        default,
    278        skip_serializing_if = "Option::is_none",
    279        deserialize_with = "deserialize_to_option_u64"
    280    )]
    281    pub height: Option<u64>,
    282    #[serde(
    283        default,
    284        skip_serializing_if = "Option::is_none",
    285        deserialize_with = "deserialize_to_pressure"
    286    )]
    287    pub pressure: Option<f64>,
    288    #[serde(
    289        default,
    290        skip_serializing_if = "Option::is_none",
    291        deserialize_with = "deserialize_to_tangential_pressure"
    292    )]
    293    pub tangentialPressure: Option<f64>,
    294    #[serde(
    295        default,
    296        skip_serializing_if = "Option::is_none",
    297        deserialize_with = "deserialize_to_tilt"
    298    )]
    299    pub tiltX: Option<i64>,
    300    #[serde(
    301        default,
    302        skip_serializing_if = "Option::is_none",
    303        deserialize_with = "deserialize_to_tilt"
    304    )]
    305    pub tiltY: Option<i64>,
    306    #[serde(
    307        default,
    308        skip_serializing_if = "Option::is_none",
    309        deserialize_with = "deserialize_to_twist"
    310    )]
    311    pub twist: Option<u64>,
    312    #[serde(
    313        default,
    314        skip_serializing_if = "Option::is_none",
    315        deserialize_with = "deserialize_to_altitude_angle"
    316    )]
    317    pub altitudeAngle: Option<f64>,
    318    #[serde(
    319        default,
    320        skip_serializing_if = "Option::is_none",
    321        deserialize_with = "deserialize_to_azimuth_angle"
    322    )]
    323    pub azimuthAngle: Option<f64>,
    324 }
    325 
    326 #[derive(Clone, Debug, Default, PartialEq, Serialize)]
    327 pub enum PointerOrigin {
    328    #[serde(
    329        rename = "element-6066-11e4-a52e-4f735466cecf",
    330        serialize_with = "serialize_webelement_id"
    331    )]
    332    Element(WebElement),
    333    #[serde(rename = "pointer")]
    334    Pointer,
    335    #[serde(rename = "viewport")]
    336    #[default]
    337    Viewport,
    338 }
    339 
    340 // TODO: The custom deserializer can be removed once the support of the legacy
    341 // ELEMENT key has been removed from Selenium bindings
    342 // See: https://github.com/SeleniumHQ/selenium/issues/6393
    343 impl<'de> Deserialize<'de> for PointerOrigin {
    344    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    345    where
    346        D: Deserializer<'de>,
    347    {
    348        let value = Value::deserialize(deserializer)?;
    349        if let Some(web_element) = value.get(ELEMENT_KEY) {
    350            String::deserialize(web_element)
    351                .map(|id| PointerOrigin::Element(WebElement(id)))
    352                .map_err(de::Error::custom)
    353        } else if value == "pointer" {
    354            Ok(PointerOrigin::Pointer)
    355        } else if value == "viewport" {
    356            Ok(PointerOrigin::Viewport)
    357        } else {
    358            Err(de::Error::custom(format!(
    359                "unknown value `{}`, expected `pointer`, `viewport`, or `element-6066-11e4-a52e-4f735466cecf`",
    360                value
    361            )))
    362        }
    363    }
    364 }
    365 
    366 #[derive(Debug, PartialEq, Serialize, Deserialize)]
    367 #[serde(untagged)]
    368 pub enum WheelActionItem {
    369    General(GeneralAction),
    370    Wheel(WheelAction),
    371 }
    372 
    373 #[derive(Debug, PartialEq, Serialize, Deserialize)]
    374 #[serde(tag = "type")]
    375 pub enum WheelAction {
    376    #[serde(rename = "scroll")]
    377    Scroll(WheelScrollAction),
    378 }
    379 
    380 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
    381 pub struct WheelScrollAction {
    382    #[serde(
    383        default,
    384        skip_serializing_if = "Option::is_none",
    385        deserialize_with = "deserialize_to_option_u64"
    386    )]
    387    pub duration: Option<u64>,
    388    #[serde(default)]
    389    pub origin: PointerOrigin,
    390    pub x: Option<i64>,
    391    pub y: Option<i64>,
    392    pub deltaX: Option<i64>,
    393    pub deltaY: Option<i64>,
    394 }
    395 
    396 fn serialize_webelement_id<S>(element: &WebElement, serializer: S) -> Result<S::Ok, S::Error>
    397 where
    398    S: Serializer,
    399 {
    400    element.to_string().serialize(serializer)
    401 }
    402 
    403 fn deserialize_to_option_i64<'de, D>(deserializer: D) -> Result<Option<i64>, D::Error>
    404 where
    405    D: Deserializer<'de>,
    406 {
    407    Option::deserialize(deserializer)?
    408        .ok_or_else(|| de::Error::custom("invalid type: null, expected i64"))
    409 }
    410 
    411 fn deserialize_to_option_u64<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
    412 where
    413    D: Deserializer<'de>,
    414 {
    415    Option::deserialize(deserializer)?
    416        .ok_or_else(|| de::Error::custom("invalid type: null, expected i64"))
    417 }
    418 
    419 fn deserialize_to_option_f64<'de, D>(deserializer: D) -> Result<Option<f64>, D::Error>
    420 where
    421    D: Deserializer<'de>,
    422 {
    423    Option::deserialize(deserializer)?
    424        .ok_or_else(|| de::Error::custom("invalid type: null, expected f64"))
    425 }
    426 
    427 fn deserialize_to_pressure<'de, D>(deserializer: D) -> Result<Option<f64>, D::Error>
    428 where
    429    D: Deserializer<'de>,
    430 {
    431    let opt_value = deserialize_to_option_f64(deserializer)?;
    432    if let Some(value) = opt_value {
    433        if !(0f64..=1.0).contains(&value) {
    434            return Err(de::Error::custom(format!("{} is outside range 0-1", value)));
    435        }
    436    };
    437    Ok(opt_value)
    438 }
    439 
    440 fn deserialize_to_tangential_pressure<'de, D>(deserializer: D) -> Result<Option<f64>, D::Error>
    441 where
    442    D: Deserializer<'de>,
    443 {
    444    let opt_value = deserialize_to_option_f64(deserializer)?;
    445    if let Some(value) = opt_value {
    446        if !(-1.0..=1.0).contains(&value) {
    447            return Err(de::Error::custom(format!(
    448                "{} is outside range -1-1",
    449                value
    450            )));
    451        }
    452    };
    453    Ok(opt_value)
    454 }
    455 
    456 fn deserialize_to_tilt<'de, D>(deserializer: D) -> Result<Option<i64>, D::Error>
    457 where
    458    D: Deserializer<'de>,
    459 {
    460    let opt_value = deserialize_to_option_i64(deserializer)?;
    461    if let Some(value) = opt_value {
    462        if !(-90..=90).contains(&value) {
    463            return Err(de::Error::custom(format!(
    464                "{} is outside range -90-90",
    465                value
    466            )));
    467        }
    468    };
    469    Ok(opt_value)
    470 }
    471 
    472 fn deserialize_to_twist<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
    473 where
    474    D: Deserializer<'de>,
    475 {
    476    let opt_value = deserialize_to_option_u64(deserializer)?;
    477    if let Some(value) = opt_value {
    478        if !(0..=359).contains(&value) {
    479            return Err(de::Error::custom(format!(
    480                "{} is outside range 0-359",
    481                value
    482            )));
    483        }
    484    };
    485    Ok(opt_value)
    486 }
    487 
    488 fn deserialize_to_altitude_angle<'de, D>(deserializer: D) -> Result<Option<f64>, D::Error>
    489 where
    490    D: Deserializer<'de>,
    491 {
    492    let opt_value = deserialize_to_option_f64(deserializer)?;
    493    if let Some(value) = opt_value {
    494        if !(0f64..=f64::consts::FRAC_PI_2).contains(&value) {
    495            return Err(de::Error::custom(format!(
    496                "{} is outside range 0-PI/2",
    497                value
    498            )));
    499        }
    500    };
    501    Ok(opt_value)
    502 }
    503 
    504 fn deserialize_to_azimuth_angle<'de, D>(deserializer: D) -> Result<Option<f64>, D::Error>
    505 where
    506    D: Deserializer<'de>,
    507 {
    508    let opt_value = deserialize_to_option_f64(deserializer)?;
    509    if let Some(value) = opt_value {
    510        if !(0f64..=f64::consts::TAU).contains(&value) {
    511            return Err(de::Error::custom(format!(
    512                "{} is outside range 0-2*PI",
    513                value
    514            )));
    515        }
    516    };
    517    Ok(opt_value)
    518 }
    519 
    520 #[cfg(test)]
    521 mod test {
    522    use super::*;
    523    use crate::test::{assert_de, assert_ser_de};
    524    use serde_json::{self, json, Value};
    525 
    526    #[test]
    527    fn test_json_action_sequence_null() {
    528        let json = json!({
    529            "id": "some_key",
    530            "type": "none",
    531            "actions": [{
    532                "type": "pause",
    533                "duration": 1,
    534            }]
    535        });
    536        let seq = ActionSequence {
    537            id: "some_key".into(),
    538            actions: ActionsType::Null {
    539                actions: vec![NullActionItem::General(GeneralAction::Pause(PauseAction {
    540                    duration: Some(1),
    541                }))],
    542            },
    543        };
    544 
    545        assert_ser_de(&seq, json);
    546    }
    547 
    548    #[test]
    549    fn test_json_action_sequence_key() {
    550        let json = json!({
    551            "id": "some_key",
    552            "type": "key",
    553            "actions": [
    554                {"type": "keyDown", "value": "f"},
    555            ],
    556        });
    557        let seq = ActionSequence {
    558            id: "some_key".into(),
    559            actions: ActionsType::Key {
    560                actions: vec![KeyActionItem::Key(KeyAction::Down(KeyDownAction {
    561                    value: String::from("f"),
    562                }))],
    563            },
    564        };
    565 
    566        assert_ser_de(&seq, json);
    567    }
    568 
    569    #[test]
    570    fn test_json_action_sequence_pointer() {
    571        let json = json!({
    572            "id": "some_pointer",
    573            "type": "pointer",
    574            "parameters": {
    575                "pointerType": "mouse"
    576            },
    577            "actions": [
    578                {"type": "pointerDown", "button": 0},
    579                {"type": "pointerMove", "origin": "pointer", "x": 10.5, "y": 20.5},
    580                {"type": "pointerUp", "button": 0},
    581            ]
    582        });
    583        let seq = ActionSequence {
    584            id: "some_pointer".into(),
    585            actions: ActionsType::Pointer {
    586                parameters: PointerActionParameters {
    587                    pointer_type: PointerType::Mouse,
    588                },
    589                actions: vec![
    590                    PointerActionItem::Pointer(PointerAction::Down(PointerDownAction {
    591                        button: 0,
    592                        ..Default::default()
    593                    })),
    594                    PointerActionItem::Pointer(PointerAction::Move(PointerMoveAction {
    595                        origin: PointerOrigin::Pointer,
    596                        duration: None,
    597                        x: 10.5,
    598                        y: 20.5,
    599                        ..Default::default()
    600                    })),
    601                    PointerActionItem::Pointer(PointerAction::Up(PointerUpAction {
    602                        button: 0,
    603                        ..Default::default()
    604                    })),
    605                ],
    606            },
    607        };
    608 
    609        assert_ser_de(&seq, json);
    610    }
    611 
    612    #[test]
    613    fn test_json_action_sequence_id_missing() {
    614        let json = json!({
    615            "type": "key",
    616            "actions": [],
    617        });
    618        assert!(serde_json::from_value::<ActionSequence>(json).is_err());
    619    }
    620 
    621    #[test]
    622    fn test_json_action_sequence_id_null() {
    623        let json = json!({
    624            "id": null,
    625            "type": "key",
    626            "actions": [],
    627        });
    628        assert!(serde_json::from_value::<ActionSequence>(json).is_err());
    629    }
    630 
    631    #[test]
    632    fn test_json_action_sequence_actions_missing() {
    633        assert!(serde_json::from_value::<ActionSequence>(json!({"id": "3"})).is_err());
    634    }
    635 
    636    #[test]
    637    fn test_json_action_sequence_actions_null() {
    638        let json = json!({
    639            "id": "3",
    640            "actions": null,
    641        });
    642        assert!(serde_json::from_value::<ActionSequence>(json).is_err());
    643    }
    644 
    645    #[test]
    646    fn test_json_action_sequence_actions_invalid_type() {
    647        let json = json!({
    648            "id": "3",
    649            "actions": "foo",
    650        });
    651        assert!(serde_json::from_value::<ActionSequence>(json).is_err());
    652    }
    653 
    654    #[test]
    655    fn test_json_actions_type_null() {
    656        let json = json!({
    657            "type": "none",
    658            "actions": [{
    659                "type": "pause",
    660                "duration": 1,
    661            }],
    662        });
    663        let null = ActionsType::Null {
    664            actions: vec![NullActionItem::General(GeneralAction::Pause(PauseAction {
    665                duration: Some(1),
    666            }))],
    667        };
    668 
    669        assert_ser_de(&null, json);
    670    }
    671 
    672    #[test]
    673    fn test_json_actions_type_key() {
    674        let json = json!({
    675            "type": "key",
    676            "actions": [{
    677                "type": "keyDown",
    678                "value": "f",
    679            }],
    680        });
    681        let key = ActionsType::Key {
    682            actions: vec![KeyActionItem::Key(KeyAction::Down(KeyDownAction {
    683                value: String::from("f"),
    684            }))],
    685        };
    686 
    687        assert_ser_de(&key, json);
    688    }
    689 
    690    #[test]
    691    fn test_json_actions_type_pointer() {
    692        let json = json!({
    693        "type": "pointer",
    694        "parameters": {"pointerType": "mouse"},
    695        "actions": [
    696            {"type": "pointerDown", "button": 1},
    697        ]});
    698        let pointer = ActionsType::Pointer {
    699            parameters: PointerActionParameters {
    700                pointer_type: PointerType::Mouse,
    701            },
    702            actions: vec![PointerActionItem::Pointer(PointerAction::Down(
    703                PointerDownAction {
    704                    button: 1,
    705                    ..Default::default()
    706                },
    707            ))],
    708        };
    709 
    710        assert_ser_de(&pointer, json);
    711    }
    712 
    713    #[test]
    714    fn test_json_actions_type_pointer_with_parameters_missing() {
    715        let json = json!({
    716        "type": "pointer",
    717        "actions": [
    718            {"type": "pointerDown", "button": 1},
    719        ]});
    720        let pointer = ActionsType::Pointer {
    721            parameters: PointerActionParameters {
    722                pointer_type: PointerType::Mouse,
    723            },
    724            actions: vec![PointerActionItem::Pointer(PointerAction::Down(
    725                PointerDownAction {
    726                    button: 1,
    727                    ..Default::default()
    728                },
    729            ))],
    730        };
    731 
    732        assert_de(&pointer, json);
    733    }
    734 
    735    #[test]
    736    fn test_json_actions_type_pointer_with_parameters_invalid_type() {
    737        let json = json!({
    738        "type": "pointer",
    739        "parameters": null,
    740        "actions": [
    741            {"type":"pointerDown", "button": 1},
    742        ]});
    743        assert!(serde_json::from_value::<ActionsType>(json).is_err());
    744    }
    745 
    746    #[test]
    747    fn test_json_actions_type_invalid() {
    748        let json = json!({"actions": [{"foo": "bar"}]});
    749        assert!(serde_json::from_value::<ActionsType>(json).is_err());
    750    }
    751 
    752    #[test]
    753    fn test_json_null_action_item_general() {
    754        let pause =
    755            NullActionItem::General(GeneralAction::Pause(PauseAction { duration: Some(1) }));
    756        assert_ser_de(&pause, json!({"type": "pause", "duration": 1}));
    757    }
    758 
    759    #[test]
    760    fn test_json_null_action_item_invalid_type() {
    761        assert!(serde_json::from_value::<NullActionItem>(json!({"type": "invalid"})).is_err());
    762    }
    763 
    764    #[test]
    765    fn test_json_general_action_pause() {
    766        let pause = GeneralAction::Pause(PauseAction { duration: Some(1) });
    767        assert_ser_de(&pause, json!({"type": "pause", "duration": 1}));
    768    }
    769 
    770    #[test]
    771    fn test_json_general_action_pause_with_duration_missing() {
    772        let pause = GeneralAction::Pause(PauseAction { duration: None });
    773        assert_ser_de(&pause, json!({"type": "pause"}));
    774    }
    775 
    776    #[test]
    777    fn test_json_general_action_pause_with_duration_null() {
    778        let json = json!({"type": "pause", "duration": null});
    779        assert!(serde_json::from_value::<GeneralAction>(json).is_err());
    780    }
    781 
    782    #[test]
    783    fn test_json_general_action_pause_with_duration_invalid_type() {
    784        let json = json!({"type": "pause", "duration":" foo"});
    785        assert!(serde_json::from_value::<GeneralAction>(json).is_err());
    786    }
    787 
    788    #[test]
    789    fn test_json_general_action_pause_with_duration_negative() {
    790        let json = json!({"type": "pause", "duration": -30});
    791        assert!(serde_json::from_value::<GeneralAction>(json).is_err());
    792    }
    793 
    794    #[test]
    795    fn test_json_key_action_item_general() {
    796        let pause = KeyActionItem::General(GeneralAction::Pause(PauseAction { duration: Some(1) }));
    797        assert_ser_de(&pause, json!({"type": "pause", "duration": 1}));
    798    }
    799 
    800    #[test]
    801    fn test_json_key_action_item_key() {
    802        let key_down = KeyActionItem::Key(KeyAction::Down(KeyDownAction {
    803            value: String::from("f"),
    804        }));
    805        assert_ser_de(&key_down, json!({"type": "keyDown", "value": "f"}));
    806    }
    807 
    808    #[test]
    809    fn test_json_key_action_item_invalid_type() {
    810        assert!(serde_json::from_value::<KeyActionItem>(json!({"type": "invalid"})).is_err());
    811    }
    812 
    813    #[test]
    814    fn test_json_key_action_missing_subtype() {
    815        assert!(serde_json::from_value::<KeyAction>(json!({"value": "f"})).is_err());
    816    }
    817 
    818    #[test]
    819    fn test_json_key_action_wrong_subtype() {
    820        let json = json!({"type": "pause", "value": "f"});
    821        assert!(serde_json::from_value::<KeyAction>(json).is_err());
    822    }
    823 
    824    #[test]
    825    fn test_json_key_action_down() {
    826        let key_down = KeyAction::Down(KeyDownAction {
    827            value: "f".to_string(),
    828        });
    829        assert_ser_de(&key_down, json!({"type": "keyDown", "value": "f"}));
    830    }
    831 
    832    #[test]
    833    fn test_json_key_action_down_with_value_unicode() {
    834        let key_down = KeyAction::Down(KeyDownAction {
    835            value: "à".to_string(),
    836        });
    837        assert_ser_de(&key_down, json!({"type": "keyDown", "value": "à"}));
    838    }
    839 
    840    #[test]
    841    fn test_json_key_action_down_with_value_unicode_encoded() {
    842        let key_down = KeyAction::Down(KeyDownAction {
    843            value: "à".to_string(),
    844        });
    845        assert_de(&key_down, json!({"type": "keyDown", "value": "\u{00E0}"}));
    846    }
    847 
    848    #[test]
    849    fn test_json_key_action_down_with_value_missing() {
    850        assert!(serde_json::from_value::<KeyAction>(json!({"type": "keyDown"})).is_err());
    851    }
    852 
    853    #[test]
    854    fn test_json_key_action_down_with_value_null() {
    855        let json = json!({"type": "keyDown", "value": null});
    856        assert!(serde_json::from_value::<KeyAction>(json).is_err());
    857    }
    858 
    859    #[test]
    860    fn test_json_key_action_down_with_value_invalid_type() {
    861        let json = json!({"type": "keyDown", "value": ["f", "o", "o"]});
    862        assert!(serde_json::from_value::<KeyAction>(json).is_err());
    863    }
    864 
    865    #[test]
    866    fn test_json_key_action_down_with_multiple_code_points() {
    867        let json = json!({"type": "keyDown", "value": "fo"});
    868        assert!(serde_json::from_value::<KeyAction>(json).is_err());
    869    }
    870 
    871    #[test]
    872    fn test_json_key_action_up() {
    873        let key_up = KeyAction::Up(KeyUpAction {
    874            value: "f".to_string(),
    875        });
    876        assert_ser_de(&key_up, json!({"type": "keyUp", "value": "f"}));
    877    }
    878 
    879    #[test]
    880    fn test_json_key_action_up_with_value_unicode() {
    881        let key_up = KeyAction::Up(KeyUpAction {
    882            value: "à".to_string(),
    883        });
    884        assert_ser_de(&key_up, json!({"type":"keyUp", "value": "à"}));
    885    }
    886 
    887    #[test]
    888    fn test_json_key_action_up_with_value_unicode_encoded() {
    889        let key_up = KeyAction::Up(KeyUpAction {
    890            value: "à".to_string(),
    891        });
    892        assert_de(&key_up, json!({"type": "keyUp", "value": "\u{00E0}"}));
    893    }
    894 
    895    #[test]
    896    fn test_json_key_action_up_with_value_missing() {
    897        assert!(serde_json::from_value::<KeyAction>(json!({"type": "keyUp"})).is_err());
    898    }
    899 
    900    #[test]
    901    fn test_json_key_action_up_with_value_null() {
    902        let json = json!({"type": "keyUp", "value": null});
    903        assert!(serde_json::from_value::<KeyAction>(json).is_err());
    904    }
    905 
    906    #[test]
    907    fn test_json_key_action_up_with_value_invalid_type() {
    908        let json = json!({"type": "keyUp", "value": ["f","o","o"]});
    909        assert!(serde_json::from_value::<KeyAction>(json).is_err());
    910    }
    911 
    912    #[test]
    913    fn test_json_key_action_up_with_multiple_code_points() {
    914        let json = json!({"type": "keyUp", "value": "fo"});
    915        assert!(serde_json::from_value::<KeyAction>(json).is_err());
    916    }
    917 
    918    #[test]
    919    fn test_json_pointer_action_item_general() {
    920        let pause =
    921            PointerActionItem::General(GeneralAction::Pause(PauseAction { duration: Some(1) }));
    922        assert_ser_de(&pause, json!({"type": "pause", "duration": 1}));
    923    }
    924 
    925    #[test]
    926    fn test_json_pointer_action_item_pointer() {
    927        let cancel = PointerActionItem::Pointer(PointerAction::Cancel);
    928        assert_ser_de(&cancel, json!({"type": "pointerCancel"}));
    929    }
    930 
    931    #[test]
    932    fn test_json_pointer_action_item_invalid() {
    933        assert!(serde_json::from_value::<PointerActionItem>(json!({"type": "invalid"})).is_err());
    934    }
    935 
    936    #[test]
    937    fn test_json_pointer_action_parameters_mouse() {
    938        let mouse = PointerActionParameters {
    939            pointer_type: PointerType::Mouse,
    940        };
    941        assert_ser_de(&mouse, json!({"pointerType": "mouse"}));
    942    }
    943 
    944    #[test]
    945    fn test_json_pointer_action_parameters_pen() {
    946        let pen = PointerActionParameters {
    947            pointer_type: PointerType::Pen,
    948        };
    949        assert_ser_de(&pen, json!({"pointerType": "pen"}));
    950    }
    951 
    952    #[test]
    953    fn test_json_pointer_action_parameters_touch() {
    954        let touch = PointerActionParameters {
    955            pointer_type: PointerType::Touch,
    956        };
    957        assert_ser_de(&touch, json!({"pointerType": "touch"}));
    958    }
    959 
    960    #[test]
    961    fn test_json_pointer_action_item_invalid_type() {
    962        let json = json!({"type": "pointerInvalid"});
    963        assert!(serde_json::from_value::<PointerActionItem>(json).is_err());
    964    }
    965 
    966    #[test]
    967    fn test_json_pointer_action_missing_subtype() {
    968        assert!(serde_json::from_value::<PointerAction>(json!({"button": 1})).is_err());
    969    }
    970 
    971    #[test]
    972    fn test_json_pointer_action_invalid_subtype() {
    973        let json = json!({"type": "invalid", "button": 1});
    974        assert!(serde_json::from_value::<PointerAction>(json).is_err());
    975    }
    976 
    977    #[test]
    978    fn test_json_pointer_action_cancel() {
    979        assert_ser_de(&PointerAction::Cancel, json!({"type": "pointerCancel"}));
    980    }
    981 
    982    #[test]
    983    fn test_json_pointer_action_down() {
    984        let pointer_down = PointerAction::Down(PointerDownAction {
    985            button: 1,
    986            ..Default::default()
    987        });
    988        assert_ser_de(&pointer_down, json!({"type": "pointerDown", "button": 1}));
    989    }
    990 
    991    #[test]
    992    fn test_json_pointer_action_down_with_button_missing() {
    993        let json = json!({"type": "pointerDown"});
    994        assert!(serde_json::from_value::<PointerAction>(json).is_err());
    995    }
    996 
    997    #[test]
    998    fn test_json_pointer_action_down_with_button_null() {
    999        let json = json!({
   1000            "type": "pointerDown",
   1001            "button": null,
   1002        });
   1003        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1004    }
   1005 
   1006    #[test]
   1007    fn test_json_pointer_action_down_with_button_invalid_type() {
   1008        let json = json!({
   1009            "type": "pointerDown",
   1010            "button": "foo",
   1011        });
   1012        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1013    }
   1014 
   1015    #[test]
   1016    fn test_json_pointer_action_down_with_button_negative() {
   1017        let json = json!({
   1018            "type": "pointerDown",
   1019            "button": -30,
   1020        });
   1021        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1022    }
   1023 
   1024    #[test]
   1025    fn test_json_pointer_action_move() {
   1026        let json = json!({
   1027            "type": "pointerMove",
   1028            "duration": 100,
   1029            "origin": "viewport",
   1030            "x": 5.5,
   1031            "y": 10.5,
   1032        });
   1033        let pointer_move = PointerAction::Move(PointerMoveAction {
   1034            duration: Some(100),
   1035            origin: PointerOrigin::Viewport,
   1036            x: 5.5,
   1037            y: 10.5,
   1038            ..Default::default()
   1039        });
   1040 
   1041        assert_ser_de(&pointer_move, json);
   1042    }
   1043 
   1044    #[test]
   1045    fn test_json_pointer_action_move_missing_subtype() {
   1046        let json = json!({
   1047            "duration": 100,
   1048            "origin": "viewport",
   1049            "x": 5.5,
   1050            "y": 10.5,
   1051        });
   1052        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1053    }
   1054 
   1055    #[test]
   1056    fn test_json_pointer_action_move_wrong_subtype() {
   1057        let json = json!({
   1058            "type": "pointerUp",
   1059            "duration": 100,
   1060            "origin": "viewport",
   1061            "x": 5.5,
   1062            "y": 10.5,
   1063        });
   1064        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1065    }
   1066 
   1067    #[test]
   1068    fn test_json_pointer_action_move_with_duration_missing() {
   1069        let json = json!({
   1070            "type": "pointerMove",
   1071            "origin": "viewport",
   1072            "x": 5.5,
   1073            "y": 10.5,
   1074        });
   1075        let pointer_move = PointerAction::Move(PointerMoveAction {
   1076            duration: None,
   1077            origin: PointerOrigin::Viewport,
   1078            x: 5.5,
   1079            y: 10.5,
   1080            ..Default::default()
   1081        });
   1082 
   1083        assert_ser_de(&pointer_move, json);
   1084    }
   1085 
   1086    #[test]
   1087    fn test_json_pointer_action_move_with_duration_null() {
   1088        let json = json!({
   1089            "type": "pointerMove",
   1090            "duration": null,
   1091            "origin": "viewport",
   1092            "x": 5.5,
   1093            "y": 10.5,
   1094        });
   1095        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1096    }
   1097 
   1098    #[test]
   1099    fn test_json_pointer_action_move_with_duration_invalid_type() {
   1100        let json = json!({
   1101            "type": "pointerMove",
   1102            "duration": "invalid",
   1103            "origin": "viewport",
   1104            "x": 5.5,
   1105            "y": 10.5,
   1106        });
   1107        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1108    }
   1109 
   1110    #[test]
   1111    fn test_json_pointer_action_move_with_duration_negative() {
   1112        let json = json!({
   1113            "type": "pointerMove",
   1114            "duration": -30,
   1115            "origin": "viewport",
   1116            "x": 5.5,
   1117            "y": 10.5,
   1118        });
   1119        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1120    }
   1121 
   1122    #[test]
   1123    fn test_json_pointer_action_move_with_origin_missing() {
   1124        let json = json!({
   1125            "type": "pointerMove",
   1126            "duration": 100,
   1127            "x": 5.5,
   1128            "y": 10.5,
   1129        });
   1130        let pointer_move = PointerAction::Move(PointerMoveAction {
   1131            duration: Some(100),
   1132            origin: PointerOrigin::Viewport,
   1133            x: 5.5,
   1134            y: 10.5,
   1135            ..Default::default()
   1136        });
   1137 
   1138        assert_de(&pointer_move, json);
   1139    }
   1140 
   1141    #[test]
   1142    fn test_json_pointer_action_move_with_origin_webelement() {
   1143        let json = json!({
   1144            "type": "pointerMove",
   1145            "duration": 100,
   1146            "origin": {ELEMENT_KEY: "elem"},
   1147            "x": 5.5,
   1148            "y": 10.5,
   1149        });
   1150        let pointer_move = PointerAction::Move(PointerMoveAction {
   1151            duration: Some(100),
   1152            origin: PointerOrigin::Element(WebElement("elem".into())),
   1153            x: 5.5,
   1154            y: 10.5,
   1155            ..Default::default()
   1156        });
   1157 
   1158        assert_ser_de(&pointer_move, json);
   1159    }
   1160 
   1161    #[test]
   1162    fn test_json_pointer_action_move_with_origin_webelement_and_legacy_element() {
   1163        let json = json!({
   1164            "type": "pointerMove",
   1165            "duration": 100,
   1166            "origin": {ELEMENT_KEY: "elem"},
   1167            "x": 5.5,
   1168            "y": 10.5,
   1169        });
   1170        let pointer_move = PointerAction::Move(PointerMoveAction {
   1171            duration: Some(100),
   1172            origin: PointerOrigin::Element(WebElement("elem".into())),
   1173            x: 5.5,
   1174            y: 10.5,
   1175            ..Default::default()
   1176        });
   1177 
   1178        assert_de(&pointer_move, json);
   1179    }
   1180 
   1181    #[test]
   1182    fn test_json_pointer_action_move_with_origin_only_legacy_element() {
   1183        let json = json!({
   1184            "type": "pointerMove",
   1185            "duration": 100,
   1186            "origin": {ELEMENT_KEY: "elem"},
   1187            "x": 5,
   1188            "y": 10,
   1189        });
   1190        assert!(serde_json::from_value::<PointerOrigin>(json).is_err());
   1191    }
   1192 
   1193    #[test]
   1194    fn test_json_pointer_action_move_with_x_null() {
   1195        let json = json!({
   1196            "type": "pointerMove",
   1197            "duration": 100,
   1198            "origin": "viewport",
   1199            "x": null,
   1200            "y": 10,
   1201        });
   1202        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1203    }
   1204 
   1205    #[test]
   1206    fn test_json_pointer_action_move_with_x_invalid_type() {
   1207        let json = json!({
   1208            "type": "pointerMove",
   1209            "duration": 100,
   1210            "origin": "viewport",
   1211            "x": "invalid",
   1212            "y": 10,
   1213        });
   1214        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1215    }
   1216 
   1217    #[test]
   1218    fn test_json_pointer_action_move_with_y_null() {
   1219        let json = json!({
   1220            "type": "pointerMove",
   1221            "duration": 100,
   1222            "origin": "viewport",
   1223            "x": 5,
   1224            "y": null,
   1225        });
   1226        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1227    }
   1228 
   1229    #[test]
   1230    fn test_json_pointer_action_move_with_y_invalid_type() {
   1231        let json = json!({
   1232            "type": "pointerMove",
   1233            "duration": 100,
   1234            "origin": "viewport",
   1235            "x": 5,
   1236            "y": "invalid",
   1237        });
   1238        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1239    }
   1240 
   1241    #[test]
   1242    fn test_json_pointer_action_up() {
   1243        let pointer_up = PointerAction::Up(PointerUpAction {
   1244            button: 1,
   1245            ..Default::default()
   1246        });
   1247        assert_ser_de(&pointer_up, json!({"type": "pointerUp", "button": 1}));
   1248    }
   1249 
   1250    #[test]
   1251    fn test_json_pointer_action_up_with_button_missing() {
   1252        assert!(serde_json::from_value::<PointerAction>(json!({"type": "pointerUp"})).is_err());
   1253    }
   1254 
   1255    #[test]
   1256    fn test_json_pointer_action_up_with_button_null() {
   1257        let json = json!({
   1258            "type": "pointerUp",
   1259            "button": null,
   1260        });
   1261        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1262    }
   1263 
   1264    #[test]
   1265    fn test_json_pointer_action_up_with_button_invalid_type() {
   1266        let json = json!({
   1267            "type": "pointerUp",
   1268            "button": "foo",
   1269        });
   1270        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1271    }
   1272 
   1273    #[test]
   1274    fn test_json_pointer_action_up_with_button_negative() {
   1275        let json = json!({
   1276            "type": "pointerUp",
   1277            "button": -30,
   1278        });
   1279        assert!(serde_json::from_value::<PointerAction>(json).is_err());
   1280    }
   1281 
   1282    #[test]
   1283    fn test_json_pointer_origin_pointer() {
   1284        assert_ser_de(&PointerOrigin::Pointer, json!("pointer"));
   1285    }
   1286 
   1287    #[test]
   1288    fn test_json_pointer_origin_viewport() {
   1289        assert_ser_de(&PointerOrigin::Viewport, json!("viewport"));
   1290    }
   1291 
   1292    #[test]
   1293    fn test_json_pointer_origin_web_element() {
   1294        let element = PointerOrigin::Element(WebElement("elem".into()));
   1295        assert_ser_de(&element, json!({ELEMENT_KEY: "elem"}));
   1296    }
   1297 
   1298    #[test]
   1299    fn test_json_pointer_origin_invalid_type() {
   1300        assert!(serde_json::from_value::<PointerOrigin>(json!("invalid")).is_err());
   1301    }
   1302 
   1303    #[test]
   1304    fn test_json_pointer_type_mouse() {
   1305        assert_ser_de(&PointerType::Mouse, json!("mouse"));
   1306    }
   1307 
   1308    #[test]
   1309    fn test_json_pointer_type_pen() {
   1310        assert_ser_de(&PointerType::Pen, json!("pen"));
   1311    }
   1312 
   1313    #[test]
   1314    fn test_json_pointer_type_touch() {
   1315        assert_ser_de(&PointerType::Touch, json!("touch"));
   1316    }
   1317 
   1318    #[test]
   1319    fn test_json_pointer_type_invalid_type() {
   1320        assert!(serde_json::from_value::<PointerType>(json!("invalid")).is_err());
   1321    }
   1322 
   1323    #[test]
   1324    fn test_pointer_properties() {
   1325        // Ideally these would be seperate tests, but it was too much boilerplate to write
   1326        // and adding a macro seemed like overkill.
   1327        for actionType in ["pointerUp", "pointerDown", "pointerMove"] {
   1328            for (prop_name, value, is_valid) in [
   1329                ("pressure", Value::from(0), true),
   1330                ("pressure", Value::from(0.5), true),
   1331                ("pressure", Value::from(1), true),
   1332                ("pressure", Value::from(1.1), false),
   1333                ("pressure", Value::from(-0.1), false),
   1334                ("tangentialPressure", Value::from(-1), true),
   1335                ("tangentialPressure", Value::from(0), true),
   1336                ("tangentialPressure", Value::from(1.0), true),
   1337                ("tangentialPressure", Value::from(-1.1), false),
   1338                ("tangentialPressure", Value::from(1.1), false),
   1339                ("tiltX", Value::from(-90), true),
   1340                ("tiltX", Value::from(0), true),
   1341                ("tiltX", Value::from(45), true),
   1342                ("tiltX", Value::from(90), true),
   1343                ("tiltX", Value::from(0.5), false),
   1344                ("tiltX", Value::from(-91), false),
   1345                ("tiltX", Value::from(91), false),
   1346                ("tiltY", Value::from(-90), true),
   1347                ("tiltY", Value::from(0), true),
   1348                ("tiltY", Value::from(45), true),
   1349                ("tiltY", Value::from(90), true),
   1350                ("tiltY", Value::from(0.5), false),
   1351                ("tiltY", Value::from(-91), false),
   1352                ("tiltY", Value::from(91), false),
   1353                ("twist", Value::from(0), true),
   1354                ("twist", Value::from(180), true),
   1355                ("twist", Value::from(359), true),
   1356                ("twist", Value::from(360), false),
   1357                ("twist", Value::from(-1), false),
   1358                ("twist", Value::from(23.5), false),
   1359                ("altitudeAngle", Value::from(0), true),
   1360                ("altitudeAngle", Value::from(f64::consts::FRAC_PI_4), true),
   1361                ("altitudeAngle", Value::from(f64::consts::FRAC_PI_2), true),
   1362                (
   1363                    "altitudeAngle",
   1364                    Value::from(f64::consts::FRAC_PI_2 + 0.1),
   1365                    false,
   1366                ),
   1367                ("altitudeAngle", Value::from(-f64::consts::FRAC_PI_4), false),
   1368                ("azimuthAngle", Value::from(0), true),
   1369                ("azimuthAngle", Value::from(f64::consts::PI), true),
   1370                ("azimuthAngle", Value::from(f64::consts::TAU), true),
   1371                ("azimuthAngle", Value::from(f64::consts::TAU + 0.01), false),
   1372                ("azimuthAngle", Value::from(-f64::consts::FRAC_PI_4), false),
   1373            ] {
   1374                let mut json = serde_json::Map::new();
   1375                json.insert("type".into(), actionType.into());
   1376                if actionType != "pointerMove" {
   1377                    json.insert("button".into(), Value::from(0));
   1378                } else {
   1379                    json.insert("x".into(), Value::from(0));
   1380                    json.insert("y".into(), Value::from(0));
   1381                }
   1382                json.insert(prop_name.into(), value);
   1383                println!("{:?}", json);
   1384                let deserialized = serde_json::from_value::<PointerAction>(json.into());
   1385                if is_valid {
   1386                    assert!(deserialized.is_ok());
   1387                } else {
   1388                    assert!(deserialized.is_err());
   1389                }
   1390            }
   1391        }
   1392    }
   1393 }