From 1dc247d75cd26828837460e9a790409189497d83 Mon Sep 17 00:00:00 2001 From: Nupur Baghel Date: Thu, 18 Jul 2019 13:15:16 +0000 Subject: [PATCH] Bug 1564417 - Add first response types to Marionette crate. r=ato Differential Revision: https://phabricator.services.mozilla.com/D38322 --HG-- extra : moz-landing-system : lando --- testing/geckodriver/marionette/src/lib.rs | 1 + testing/geckodriver/marionette/src/message.rs | 10 +- testing/geckodriver/marionette/src/result.rs | 137 ++++++++++++++++++ testing/geckodriver/marionette/src/test.rs | 11 ++ 4 files changed, 153 insertions(+), 6 deletions(-) create mode 100644 testing/geckodriver/marionette/src/result.rs diff --git a/testing/geckodriver/marionette/src/lib.rs b/testing/geckodriver/marionette/src/lib.rs index 441059410983..30ef48d2663d 100644 --- a/testing/geckodriver/marionette/src/lib.rs +++ b/testing/geckodriver/marionette/src/lib.rs @@ -3,6 +3,7 @@ pub mod error; pub mod common; pub mod marionette; pub mod message; +pub mod result; pub mod webdriver; #[cfg(test)] diff --git a/testing/geckodriver/marionette/src/message.rs b/testing/geckodriver/marionette/src/message.rs index 64d40c7b841f..ce878622429a 100644 --- a/testing/geckodriver/marionette/src/message.rs +++ b/testing/geckodriver/marionette/src/message.rs @@ -6,6 +6,7 @@ use std::fmt; use crate::error::MarionetteError; use crate::marionette; +use crate::result::MarionetteResult; use crate::webdriver; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -47,7 +48,6 @@ enum MessageDirection { } type MessageId = u32; -type Payload = Map; #[derive(Debug, Clone, PartialEq)] struct Request(MessageId, Command); @@ -85,7 +85,7 @@ impl Serialize for Request { enum Response { Result { id: MessageId, - result: Payload, + result: MarionetteResult, }, Error { id: MessageId, @@ -172,7 +172,7 @@ impl<'de> Visitor<'de> for MessageVisitor { .ok_or_else(|| de::Error::invalid_type(Unexpected::Unit, &self))?; Response::Error { id, error } } else { - let result: Payload = seq + let result: MarionetteResult = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(3, &self))?; Response::Result { id, result } @@ -269,9 +269,7 @@ mod tests { #[test] fn test_outgoing_result() { let json = json!([1, 42, null, { "value": null }]); - // TODO: payload is currently untyped - let mut result = Map::new(); - result.insert("value".into(), Value::Null); + let result = MarionetteResult::Null; let msg = Message::Outgoing(Response::Result { id: 42, result }); assert_ser_de(&msg, json); diff --git a/testing/geckodriver/marionette/src/result.rs b/testing/geckodriver/marionette/src/result.rs new file mode 100644 index 000000000000..2263dad2e51e --- /dev/null +++ b/testing/geckodriver/marionette/src/result.rs @@ -0,0 +1,137 @@ +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde_json::Value; + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct WebElement { + #[serde(rename = "element-6066-11e4-a52e-4f735466cecf")] + element: String, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Timeouts { + implicit: u64, + #[serde(rename = "pageLoad", alias = "page load")] + page_load: u64, + script: Option, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum MarionetteResult { + #[serde(deserialize_with = "from_value", serialize_with = "to_value")] + String(String), + Timeouts(Timeouts), + #[serde(deserialize_with = "from_value", serialize_with = "to_value")] + WebElement(WebElement), + #[serde(deserialize_with = "from_value", serialize_with = "to_empty_value")] + Null, +} + +fn to_value(data: T, serializer: S) -> Result +where + S: Serializer, + T: Serialize, +{ + #[derive(Serialize)] + struct Wrapper { + value: T, + } + + Wrapper { value: data }.serialize(serializer) +} + +fn to_empty_value(serializer: S) -> Result +where + S: Serializer, +{ + #[derive(Serialize)] + struct Wrapper { + value: Value, + } + + Wrapper { value: Value::Null }.serialize(serializer) +} + +fn from_value<'de, D, T>(deserializer: D) -> Result +where + D: Deserializer<'de>, + T: serde::de::DeserializeOwned, + T: std::fmt::Debug, +{ + #[derive(Debug, Deserialize)] + struct Wrapper { + value: T, + } + + let w = Wrapper::deserialize(deserializer)?; + Ok(w.value) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::{assert_de, assert_ser_de, ELEMENT_KEY}; + use serde_json::json; + + #[test] + fn test_web_element() { + let data = WebElement { + element: "foo".into(), + }; + assert_ser_de(&data, json!({"element-6066-11e4-a52e-4f735466cecf": "foo"})); + } + + #[test] + fn test_timeouts() { + let data = Timeouts { + implicit: 1000, + page_load: 200000, + script: Some(60000), + }; + assert_ser_de( + &data, + json!({"implicit":1000,"pageLoad":200000,"script":60000}), + ); + assert_de( + &data, + json!({"implicit":1000,"page load":200000,"script":60000}), + ); + } + + #[test] + fn test_web_element_response() { + let data = WebElement { + element: "foo".into(), + }; + assert_ser_de( + &MarionetteResult::WebElement(data), + json!({"value": {ELEMENT_KEY: "foo"}}), + ); + } + + #[test] + fn test_timeouts_response() { + let data = Timeouts { + implicit: 1000, + page_load: 200000, + script: Some(60000), + }; + assert_ser_de( + &MarionetteResult::Timeouts(data), + json!({"implicit":1000,"pageLoad":200000,"script":60000}), + ); + } + + #[test] + fn test_string_response() { + assert_ser_de( + &MarionetteResult::String("foo".into()), + json!({"value": "foo"}), + ); + } + + #[test] + fn test_null_response() { + assert_ser_de(&MarionetteResult::Null, json!({ "value": null })); + } +} diff --git a/testing/geckodriver/marionette/src/test.rs b/testing/geckodriver/marionette/src/test.rs index 5ebc61fa2371..b6309a266142 100644 --- a/testing/geckodriver/marionette/src/test.rs +++ b/testing/geckodriver/marionette/src/test.rs @@ -1,3 +1,5 @@ +pub static ELEMENT_KEY: &'static str = "element-6066-11e4-a52e-4f735466cecf"; + pub fn assert_ser_de(data: &T, json: serde_json::Value) where T: std::fmt::Debug, @@ -18,3 +20,12 @@ where { assert_eq!(serde_json::to_value(data).unwrap(), json); } + +pub fn assert_de(data: &T, json: serde_json::Value) +where + T: std::fmt::Debug, + T: std::cmp::PartialEq, + T: serde::de::DeserializeOwned, +{ + assert_eq!(data, &serde_json::from_value::(json).unwrap()); +}