result.rs (5908B)
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 serde::de; 6 use serde::{Deserialize, Deserializer, Serialize, Serializer}; 7 use serde_json::Value; 8 9 use crate::common::{Cookie, Timeouts, WebElement}; 10 11 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] 12 pub struct NewWindow { 13 handle: String, 14 #[serde(rename = "type")] 15 type_hint: String, 16 } 17 18 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] 19 pub struct WindowRect { 20 pub x: i32, 21 pub y: i32, 22 pub width: i32, 23 pub height: i32, 24 } 25 26 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] 27 pub struct ElementRect { 28 pub x: f64, 29 pub y: f64, 30 pub width: f64, 31 pub height: f64, 32 } 33 34 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] 35 #[serde(untagged)] 36 pub enum MarionetteResult { 37 #[serde(deserialize_with = "from_value", serialize_with = "to_value")] 38 Bool(bool), 39 #[serde(deserialize_with = "from_value", serialize_with = "to_empty_value")] 40 Null, 41 NewWindow(NewWindow), 42 WindowRect(WindowRect), 43 ElementRect(ElementRect), 44 #[serde(deserialize_with = "from_value", serialize_with = "to_value")] 45 String(String), 46 Strings(Vec<String>), 47 #[serde(deserialize_with = "from_value", serialize_with = "to_value")] 48 WebElement(WebElement), 49 WebElements(Vec<WebElement>), 50 Cookies(Vec<Cookie>), 51 Timeouts(Timeouts), 52 } 53 54 fn to_value<T, S>(data: T, serializer: S) -> Result<S::Ok, S::Error> 55 where 56 S: Serializer, 57 T: Serialize, 58 { 59 #[derive(Serialize)] 60 struct Wrapper<T> { 61 value: T, 62 } 63 64 Wrapper { value: data }.serialize(serializer) 65 } 66 67 fn to_empty_value<S>(serializer: S) -> Result<S::Ok, S::Error> 68 where 69 S: Serializer, 70 { 71 #[derive(Serialize)] 72 struct Wrapper { 73 value: Value, 74 } 75 76 Wrapper { value: Value::Null }.serialize(serializer) 77 } 78 79 fn from_value<'de, D, T>(deserializer: D) -> Result<T, D::Error> 80 where 81 D: Deserializer<'de>, 82 T: serde::de::DeserializeOwned, 83 T: std::fmt::Debug, 84 { 85 #[derive(Debug, Deserialize)] 86 struct Wrapper<T> { 87 value: T, 88 } 89 90 let v = Value::deserialize(deserializer)?; 91 if v.is_object() { 92 let w = serde_json::from_value::<Wrapper<T>>(v).map_err(de::Error::custom)?; 93 Ok(w.value) 94 } else { 95 Err(de::Error::custom("Cannot be deserialized to struct")) 96 } 97 } 98 99 #[cfg(test)] 100 mod tests { 101 use super::*; 102 use crate::test::{assert_de, assert_ser_de, ELEMENT_KEY}; 103 use serde_json::json; 104 105 #[test] 106 fn test_boolean_response() { 107 assert_ser_de(&MarionetteResult::Bool(true), json!({"value": true})); 108 } 109 110 #[test] 111 fn test_cookies_response() { 112 let mut data = Vec::new(); 113 data.push(Cookie { 114 name: "foo".into(), 115 value: "bar".into(), 116 path: Some("/common".into()), 117 domain: Some("web-platform.test".into()), 118 secure: false, 119 http_only: false, 120 expiry: None, 121 same_site: Some("Strict".into()), 122 }); 123 assert_ser_de( 124 &MarionetteResult::Cookies(data), 125 json!([{"name":"foo","value":"bar","path":"/common","domain":"web-platform.test","secure":false,"httpOnly":false,"sameSite":"Strict"}]), 126 ); 127 } 128 129 #[test] 130 fn test_new_window_response() { 131 let data = NewWindow { 132 handle: "6442450945".into(), 133 type_hint: "tab".into(), 134 }; 135 let json = json!({"handle": "6442450945", "type": "tab"}); 136 assert_ser_de(&MarionetteResult::NewWindow(data), json); 137 } 138 139 #[test] 140 fn test_web_element_response() { 141 let data = WebElement { 142 element: "foo".into(), 143 }; 144 assert_ser_de( 145 &MarionetteResult::WebElement(data), 146 json!({"value": {ELEMENT_KEY: "foo"}}), 147 ); 148 } 149 150 #[test] 151 fn test_web_elements_response() { 152 let data = vec![ 153 WebElement { 154 element: "foo".into(), 155 }, 156 WebElement { 157 element: "bar".into(), 158 }, 159 ]; 160 assert_ser_de( 161 &MarionetteResult::WebElements(data), 162 json!([{ELEMENT_KEY: "foo"}, {ELEMENT_KEY: "bar"}]), 163 ); 164 } 165 166 #[test] 167 fn test_timeouts_response() { 168 let data = Timeouts { 169 implicit: Some(1000), 170 page_load: Some(200000), 171 script: Some(Some(60000)), 172 }; 173 assert_ser_de( 174 &MarionetteResult::Timeouts(data), 175 json!({"implicit":1000,"pageLoad":200000,"script":60000}), 176 ); 177 } 178 179 #[test] 180 fn test_string_response() { 181 assert_ser_de( 182 &MarionetteResult::String("foo".into()), 183 json!({"value": "foo"}), 184 ); 185 } 186 187 #[test] 188 fn test_strings_response() { 189 assert_ser_de( 190 &MarionetteResult::Strings(vec!["2147483649".to_string()]), 191 json!(["2147483649"]), 192 ); 193 } 194 195 #[test] 196 fn test_null_response() { 197 assert_ser_de(&MarionetteResult::Null, json!({ "value": null })); 198 } 199 200 #[test] 201 fn test_window_rect_response() { 202 let data = WindowRect { 203 x: 100, 204 y: 100, 205 width: 800, 206 height: 600, 207 }; 208 let json = json!({"x": 100, "y": 100, "width": 800, "height": 600}); 209 assert_ser_de(&MarionetteResult::WindowRect(data), json); 210 } 211 212 #[test] 213 fn test_element_rect_response() { 214 let data = ElementRect { 215 x: 8.0, 216 y: 8.0, 217 width: 148.6666717529297, 218 height: 22.0, 219 }; 220 let json = json!({"x": 8, "y": 8, "width": 148.6666717529297, "height": 22}); 221 assert_de(&MarionetteResult::ElementRect(data), json); 222 } 223 }