Bug 1396821 - [webdriver][WIP] Removing custom implementations from rustc_serialize. draft
authorHenrik Skupin <mail@hskupin.info>
Mon, 18 Jun 2018 05:09:46 +0200
changeset 812188 eda6cad47cb25ed081b2f6af7a56b03cf27d6c73
parent 812187 09f96d9d3eee2eb1df241329a54122424fcd2221
push id114482
push userbmo:hskupin@gmail.com
push dateThu, 28 Jun 2018 18:50:46 +0000
bugs1396821
milestone63.0a1
Bug 1396821 - [webdriver][WIP] Removing custom implementations from rustc_serialize. Not done yet... MozReview-Commit-ID: CKoseo1mkQX
testing/webdriver/src/actions.rs
testing/webdriver/src/capabilities.rs
testing/webdriver/src/command.rs
testing/webdriver/src/common.rs
testing/webdriver/src/error.rs
testing/webdriver/src/response.rs
--- a/testing/webdriver/src/actions.rs
+++ b/testing/webdriver/src/actions.rs
@@ -1,20 +1,19 @@
 use common::WebElement;
-use serde::{Deserialize, Deserializer};
-use serde::ser::{Serialize, Serializer};
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
 use serde_json::{self, Value, Map};
 use std::default::Default;
 
 #[derive(Debug, PartialEq, Serialize, Deserialize)]
 pub struct ActionsParameters {
     pub actions: Vec<ActionSequence>
 }
 
-// TODO remove
+// TODO remove once command.rs is fixed
 impl<'a> From<&'a ActionsParameters> for Value {
     fn from(params: &'a ActionsParameters) -> Value {
         let mut data = Map::new();
         // TODO: Remove workaround
         let json = serde_json::to_string(&params).unwrap();
         data.insert("actions".to_owned(), serde_json::from_str(&json).unwrap());
         Value::Object(data)
     }
@@ -167,17 +166,17 @@ pub struct PointerMoveAction {
 }
 
 #[cfg(test)]
 mod test {
     use serde_json;
     use super::*;
 
     #[test]
-    fn test_action_parameters() {
+    fn test_deserialize_action_parameters() {
         let expected = ActionsParameters {
             actions: vec!{
                 ActionSequence {
                     id: Some("none".into()),
                     actions: ActionsType::Null {
                         actions: vec!{
                             NullActionItem::General (
                                 GeneralAction::Pause ( PauseAction { duration: 1 } )
@@ -195,17 +194,17 @@ mod test {
             }]
         }"#;
 
         let actual: ActionsParameters = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_action_sequence_null() {
+    fn test_deserialize_action_sequence_null() {
         let expected = ActionSequence {
             id: Some("none".into()),
             actions: ActionsType::Null {
                 actions: vec!{
                     NullActionItem::General (
                         GeneralAction::Pause ( PauseAction { duration: 1 } )
                     )
                 }
@@ -217,17 +216,17 @@ mod test {
             "actions": {"actions": [{"type": "pause", "duration": 1}]}
         }"#;
 
         let actual: ActionSequence = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_action_sequence_key() {
+    fn test_deserialize_action_sequence_key() {
         let expected = ActionSequence {
             id: Some("some_key".into()),
             actions: ActionsType::Key {
                 actions: vec!{
                     KeyActionItem::Key (
                         KeyAction::Down ( KeyDownAction { value: String::from("f") } )
                     )
                 }
@@ -239,17 +238,17 @@ mod test {
             "actions": {"actions": [{"type": "keyDown", "value": "f"}]}
         }"#;
 
         let actual: ActionSequence = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_action_sequence_pointer() {
+    fn test_deserialize_action_sequence_pointer() {
         let expected = ActionSequence {
             id: Some("some_pointer".into()),
             actions: ActionsType::Pointer {
                 parameters: PointerActionParameters {
                     pointer_type: PointerType::Mouse
                 },
                 actions: vec!{
                     PointerActionItem::Pointer (
@@ -283,47 +282,47 @@ mod test {
                 ]
             }
         }"#;
         let actual: ActionSequence = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_actions_type_null() {
+    fn test_deserialize_actions_type_null() {
         let expected = ActionsType::Null {
             actions: vec!{
                 NullActionItem::General (
                     GeneralAction::Pause ( PauseAction { duration: 1 } )
                 )
             }
         };
 
         let data = r#"{"actions": [{"type": "pause", "duration":1}]}"#;
         let actual: ActionsType = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_actions_type_key() {
+    fn test_deserialize_actions_type_key() {
         let expected = ActionsType::Key {
             actions: vec!{
                 KeyActionItem::Key (
                     KeyAction::Down ( KeyDownAction { value: String::from("f") } )
                 )
             }
         };
 
         let data = r#"{"actions": [{"type": "keyDown", "value": "f"}]}"#;
         let actual: ActionsType = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_actions_type_pointer() {
+    fn test_deserialize_actions_type_pointer() {
         let expected = ActionsType::Pointer {
             parameters: PointerActionParameters {
                 pointer_type: PointerType::Mouse
             },
             actions: vec!{
                 PointerActionItem::Pointer (
                     PointerAction::Down ( PointerDownAction { button: 1 } )
                 )
@@ -335,312 +334,310 @@ mod test {
             "actions": [
                 {"type": "pointerDown", "button": 1}
             ]}"#;
         let actual: ActionsType = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_null_action_item_general() {
+    fn test_deserialize_null_action_item_general() {
         let expected = NullActionItem::General ( GeneralAction::Pause (
             PauseAction { duration: 1 }
         ));
 
         let data = r#"{"type": "pause", "duration": 1}"#;
         let actual: NullActionItem = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_null_action_item_invalid_type() {
+    fn test_deserialize_null_action_item_invalid_type() {
         let data = r#"{"type": "invalid"}"#;
         assert!(serde_json::from_str::<NullActionItem>(&data).is_err());
     }
 
     #[test]
-    fn test_key_action_item_general() {
+    fn test_deserialize_key_action_item_general() {
         let expected = KeyActionItem::General ( GeneralAction::Pause (
             PauseAction { duration: 1 }
         ));
 
         let data = r#"{"type": "pause", "duration": 1}"#;
         let actual: KeyActionItem = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_key_action_item_key() {
+    fn test_deserialize_key_action_item_key() {
         let expected = KeyActionItem::Key ( KeyAction::Down (
             KeyDownAction { value: String::from("f") }
         ));
 
         let data = r#"{"type": "keyDown", "value": "f"}"#;
         let actual: KeyActionItem = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_key_action_item_invalid_type() {
+    fn test_deserialize_key_action_item_invalid_type() {
         let data = r#"{"type": "invalid"}"#;
         assert!(serde_json::from_str::<KeyActionItem>(&data).is_err());
     }
 
     #[test]
-    fn test_key_action_down() {
+    fn test_deserialize_key_action_down() {
         let expected = KeyAction::Down ( KeyDownAction { value: String::from("f") } );
 
         let data = r#"{"type": "keyDown", "value": "f"}"#;
         let actual: KeyAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_key_action_up() {
+    fn test_deserialize_key_action_up() {
         let expected = KeyAction::Up ( KeyUpAction { value: String::from("f") } );
 
         let data = r#"{"type": "keyUp", "value": "f"}"#;
         let actual: KeyAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_key_action_invalid_type() {
+    fn test_deserialize_key_action_invalid_type() {
         let data = r#"{"type": "invalid", "value": "f"}"#;
         assert!(serde_json::from_str::<KeyAction>(&data).is_err());
     }
 
     #[test]
-    fn test_key_action_missing_type() {
+    fn test_deserialize_key_action_missing_type() {
         let data = r#"{"value": "f"}"#;
         assert!(serde_json::from_str::<KeyAction>(&data).is_err());
     }
 
     #[test]
-    fn test_key_down_action() {
+    fn test_deserialize_key_down_action() {
         let expected = KeyDownAction { value: String::from("f") };
 
         let data = r#"{"type": "keyDown", "value": "f"}"#;
         let actual: KeyDownAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_key_down_action_missing_value() {
+    fn test_deserialize_key_down_action_missing_value() {
         let data = r#"{"type": "keyDown"}"#;
         assert!(serde_json::from_str::<KeyDownAction>(&data).is_err());
     }
 
     #[test]
-    fn test_key_up_action() {
+    fn test_deserialize_key_up_action() {
         let expected = KeyUpAction { value: String::from("f") };
 
         let data = r#"{"type": "keyUp", "value": "f"}"#;
         let actual: KeyUpAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_key_up_action_missing_value() {
+    fn test_deserialize_key_up_action_missing_value() {
         let data = r#"{"type": "keyDown"}"#;
         assert!(serde_json::from_str::<KeyUpAction>(&data).is_err());
     }
 
     #[test]
-    fn test_pointer_action_item_general() {
+    fn test_deserialize_pointer_action_item_general() {
         let expected = PointerActionItem::General ( GeneralAction::Pause (
             PauseAction { duration: 1 }
         ));
 
         let data = r#"{"type": "pause", "duration": 1}"#;
         let actual: PointerActionItem = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pointer_action_item_pointer() {
+    fn test_deserialize_pointer_action_item_pointer() {
         let expected = PointerActionItem::Pointer ( PointerAction::Cancel );
 
         let data = r#"{"type": "pointerCancel"}"#;
         let actual: PointerActionItem = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pointer_action_item_invalid_type() {
+    fn test_deserialize_pointer_action_item_invalid_type() {
         let data = r#"{"type": "pointerInvalid"}"#;
         assert!(serde_json::from_str::<PointerActionItem>(&data).is_err());
     }
 
     #[test]
-    fn test_pointer_action_parameters() {
+    fn test_deserialize_pointer_action_parameters() {
         let expected = PointerActionParameters { pointer_type: PointerType::Mouse};
 
         let data = r#"{"pointerType": "mouse"}"#;
         let actual: PointerActionParameters = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_general_action_pause() {
+    fn test_deserialize_general_action_pause() {
         let expected = GeneralAction::Pause ( PauseAction { duration: 1 } );
 
         let data = r#"{"type": "pause", "duration": 1}"#;
         let actual: GeneralAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pause_action() {
+    fn test_deserialize_pause_action() {
         let expected = PauseAction { duration: 1 };
 
         let data = r#"{"duration": 1}"#;
         let actual: PauseAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pause_action_missing_duration() {
+    fn test_deserialize_pause_action_missing_duration() {
         let data = r#"{}"#;
         assert!(serde_json::from_str::<PauseAction>(&data).is_err());
     }
 
     #[test]
-    fn test_pointer_action_cancel() {
+    fn test_deserialize_pointer_action_cancel() {
         let expected = PointerAction::Cancel;
 
         let data = r#"{"type": "pointerCancel"}"#;
         let actual: PointerAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pointer_action_down() {
+    fn test_deserialize_pointer_action_down() {
         let expected = PointerAction::Down ( PointerDownAction { button: 1} );
 
         let data = r#"{"type": "pointerDown", "button": 1}"#;
         let actual: PointerAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pointer_action_up() {
+    fn test_deserialize_pointer_action_up() {
         let expected = PointerAction::Up ( PointerUpAction { button: 1} );
 
         let data = r#"{"type": "pointerUp", "button": 1}"#;
         let actual: PointerAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pointer_action_move() {
+    fn test_deserialize_pointer_action_move() {
         let expected = PointerAction::Move ( PointerMoveAction {
             duration:  None,
             origin: PointerOrigin::Pointer,
             x: None,
             y: None,
         });
 
         let data = r#"{"type": "pointerMove", "origin": "pointer"}"#;
         let actual: PointerAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pointer_action_invaid_type() {
+    fn test_deserialize_pointer_action_invaid_type() {
         let data = r#"{"type": "pointerInvald"}"#;
         assert!(serde_json::from_str::<PointerAction>(&data).is_err());
     }
 
     #[test]
-    fn test_pointer_action_missing_type() {
+    fn test_deserialize_pointer_action_missing_type() {
         let data = r#"{"button": 1}"#;
         assert!(serde_json::from_str::<PointerAction>(&data).is_err());
     }
 
     #[test]
-    fn test_pointer_down_action() {
+    fn test_deserialize_pointer_down_action() {
         let expected = PointerDownAction { button: 1 };
 
         let data = r#"{"button": 1}"#;
         let actual: PointerDownAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pointer_down_action_invalid_field() {
+    fn test_deserialize_pointer_down_action_invalid_field() {
         let data = r#"{"duration": 100}"#;
         assert!(serde_json::from_str::<PointerDownAction>(&data).is_err());
     }
 
     #[test]
-    fn test_pointer_down_action_missing_button_field() {
+    fn test_deserialize_pointer_down_action_missing_button_field() {
         let data = r#"{}"#;
         assert!(serde_json::from_str::<PointerDownAction>(&data).is_err());
     }
 
     #[test]
-    fn test_pointer_up_action() {
+    fn test_deserialize_pointer_up_action() {
         let expected = PointerUpAction { button: 1 };
 
         let data = r#"{"button": 1}"#;
         let actual: PointerUpAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pointer_up_action_invalid_field() {
+    fn test_deserialize_pointer_up_action_invalid_field() {
         let data = r#"{"duration": 100}"#;
         assert!(serde_json::from_str::<PointerUpAction>(&data).is_err());
     }
 
     #[test]
-    fn test_pointer_up_action_missing_button_field() {
+    fn test_deserialize_pointer_up_action_missing_button_field() {
         let data = r#"{}"#;
         assert!(serde_json::from_str::<PointerUpAction>(&data).is_err());
     }
 
     #[test]
-    fn test_pointer_move_action() {
+    fn test_deserialize_pointer_move_action() {
         let expected = PointerMoveAction {
             duration: Some(100),
             origin: PointerOrigin::Pointer,
             x: Some(5),
             y: Some(10),
         };
 
         let data = r#"{"duration": 100, "origin": "pointer", "x": 5, "y": 10}"#;
         let actual: PointerMoveAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pointer_move_action_missing_origin_field() {
+    fn test_deserialize_pointer_move_action_missing_origin_field() {
         let data = r#"{"duration": 100, "x": 5, "y": 10}"#;
         assert!(serde_json::from_str::<PointerMoveAction>(&data).is_err());
     }
 
     #[test]
-    fn test_pointer_move_action_missing_optional_fields() {
+    fn test_deserialize_pointer_move_action_missing_optional_fields() {
         let expected = PointerMoveAction {
             duration: None,
             origin: PointerOrigin::Pointer,
             x: None,
             y: None,
         };
 
         let data = r#"{"origin": "pointer"}"#;
         let actual: PointerMoveAction = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pointer_origin() {
-        // TODO: Fix with maybe custom serialize / deserialze method
-        // similar like https://github.com/serde-rs/serde/issues/751#issuecomment-277580700
+    fn test_deserialize_pointer_origin() {
         let data = r#"{"element-6066-11e4-a52e-4f735466cecf":"elem"}"#;
         let actual: PointerOrigin = serde_json::from_str(&data).unwrap();
         let expected = PointerOrigin::Element(WebElement { id: "elem".into() });
         assert_eq!(expected, actual);
 
         let data = r#""pointer""#;
         let actual: PointerOrigin = serde_json::from_str(&data).unwrap();
         let expected = PointerOrigin::Pointer;
@@ -648,23 +645,23 @@ mod test {
 
         let data = r#""viewport""#;
         let actual: PointerOrigin = serde_json::from_str(&data).unwrap();
         let expected = PointerOrigin::Viewport;
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pointer_origin_invalid_type() {
+    fn test_deserialize_pointer_origin_invalid_type() {
         let data = r#""invalid""#;
         assert!(serde_json::from_str::<PointerOrigin>(&data).is_err());
     }
 
     #[test]
-    fn test_pointer_type() {
+    fn test_deserialize_pointer_type() {
         let data = r#""mouse""#;
         let actual: PointerType = serde_json::from_str(&data).unwrap();
         let expected = PointerType::Mouse;
         assert_eq!(expected, actual);
 
         let data = r#""pen""#;
         let actual: PointerType = serde_json::from_str(&data).unwrap();
         let expected = PointerType::Pen;
@@ -672,13 +669,13 @@ mod test {
 
         let data = r#""touch""#;
         let actual: PointerType = serde_json::from_str(&data).unwrap();
         let expected = PointerType::Touch;
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_pointer_type_invalid_type() {
+    fn test_deserialize_pointer_type_invalid_type() {
         let data = r#""invalid""#;
         assert!(serde_json::from_str::<PointerType>(&data).is_err());
     }
 }
--- a/testing/webdriver/src/capabilities.rs
+++ b/testing/webdriver/src/capabilities.rs
@@ -57,34 +57,33 @@ pub trait CapabilitiesMatching {
     ///
     /// Takes a BrowserCapabilites object and returns a set of capabilites that
     /// are valid for that browser, if any, or None if there are no matching
     /// capabilities.
     fn match_browser<T: BrowserCapabilities>(&self, browser_capabilities: &mut T)
                                              -> WebDriverResult<Option<Capabilities>>;
 }
 
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-pub struct SpecNewSessionParametersWrapper {
-    capabilities: SpecNewSessionParameters
-}
+// #[derive(Debug, PartialEq, Serialize, Deserialize)]
+// pub struct SpecNewSessionParametersWrapper {
+//     capabilities: SpecNewSessionParameters
+// }
+
+// impl From<SpecNewSessionParametersWrapper> for SpecNewSessionParameters {
+//     fn from(wrapper: SpecNewSessionParametersWrapper) -> SpecNewSessionParameters {
+//         wrapper.capabilities
+//     }
+// }
 
 #[derive(Debug, PartialEq, Serialize, Deserialize)]
 pub struct SpecNewSessionParameters {
     pub alwaysMatch: Capabilities,
     pub firstMatch: Vec<Capabilities>,
 }
 
-impl From<SpecNewSessionParametersWrapper> for SpecNewSessionParameters {
-    fn from(wrapper: SpecNewSessionParametersWrapper) -> SpecNewSessionParameters {
-        wrapper.capabilities
-    }
-}
-
-
 impl SpecNewSessionParameters {
     fn validate<T: BrowserCapabilities>(&self,
                                         mut capabilities: Capabilities,
                                         browser_capabilities: &T) -> WebDriverResult<Capabilities> {
         // Filter out entries with the value `null`
         let null_entries = capabilities
             .iter()
             .filter(|&(_, ref value)| **value == Value::Null)
@@ -492,24 +491,50 @@ impl<'a> From<&'a LegacyNewSessionParame
         data.insert("requiredCapabilities".to_owned(), Value::Object(params.required.clone()));
         Value::Object(data)
     }
 }
 
 #[cfg(test)]
 mod tests {
     use serde_json::{self, Value};
-    use super::{SpecNewSessionParameters, WebDriverResult};
+    use super::*;
 
     fn validate_proxy(value: &str) -> WebDriverResult<()> {
         let data = serde_json::from_str::<Value>(value).unwrap();
         SpecNewSessionParameters::validate_proxy(&data)
     }
 
     #[test]
+    fn test_deserialize_spec_new_session_parameters_always() {
+        let data = r#"{"alwaysMatch":{"foo": "bar"}"#;
+        let actual: SpecNewSessionParameters = serde_json::from_str(&data).unwrap();
+        let mut expected = SpecNewSessionParameters {
+            alwaysMatch: Capabilities::new(),
+            firstMatch: vec!{ Capabilities::new() }
+        };
+        expected.alwaysMatch.insert("foo".into(), "bar".into());
+        assert_eq!(actual, expected);
+    }
+
+    #[test]
+    fn test_deserialize_spec_new_session_parameters_first() {
+        let data = r#"{"firstMatch":[{"foo": "bar"}]}"#;
+        let actual: SpecNewSessionParameters = serde_json::from_str(&data).unwrap();
+        let mut expected = SpecNewSessionParameters {
+            alwaysMatch: Capabilities::new(),
+            firstMatch: vec!{ Capabilities::new() }
+        };
+        println!("{:?}", actual);
+        assert!(false);
+        //expected.firstMatch.push({"foo".into(): Value::String("bar")});
+        //assert_eq!(actual, expected);
+    }
+
+    #[test]
     fn test_validate_proxy() {
         // proxy hosts
         validate_proxy("{\"httpProxy\": \"127.0.0.1\"}").unwrap();
         validate_proxy("{\"httpProxy\": \"127.0.0.1:\"}").unwrap();
         validate_proxy("{\"httpProxy\": \"127.0.0.1:3128\"}").unwrap();
         validate_proxy("{\"httpProxy\": \"localhost\"}").unwrap();
         validate_proxy("{\"httpProxy\": \"localhost:3128\"}").unwrap();
         validate_proxy("{\"httpProxy\": \"[2001:db8::1]\"}").unwrap();
--- a/testing/webdriver/src/command.rs
+++ b/testing/webdriver/src/command.rs
@@ -1,10 +1,10 @@
 use actions::ActionsParameters;
-use capabilities::{SpecNewSessionParametersWrapper, SpecNewSessionParameters, LegacyNewSessionParameters,
+use capabilities::{SpecNewSessionParameters, LegacyNewSessionParameters,
                    CapabilitiesMatching, BrowserCapabilities, Capabilities};
 use common::{Date, WebElement, FrameId, LocatorStrategy};
 use error::{WebDriverResult, WebDriverError, ErrorStatus};
 use httpapi::{Route, WebDriverExtensionRoute, VoidWebDriverExtensionRoute};
 use regex::Captures;
 use serde_json::{self, Value, Map};
 use std::convert::From;
 
@@ -102,17 +102,17 @@ impl<U: WebDriverExtensionRoute> WebDriv
                      params: &Captures,
                      raw_body: &str,
                      requires_body: bool)
                      -> WebDriverResult<WebDriverMessage<U>> {
         let session_id = WebDriverMessage::<U>::get_session_id(params);
         let body_data = try!(WebDriverMessage::<U>::decode_body(raw_body, requires_body));
         let command = match match_type {
             Route::NewSession => {
-                let parameters: NewSessionParametersWrapper = serde_json::from_str(raw_body)?;
+                let parameters: NewSessionParameters = serde_json::from_str(raw_body)?;
                 WebDriverCommand::NewSession(parameters.into())
             },
             Route::DeleteSession => WebDriverCommand::DeleteSession,
             Route::Get => {
                 let parameters: GetParameters = serde_json::from_str(raw_body)?;
                 WebDriverCommand::Get(parameters)
             },
             Route::GetCurrentUrl => WebDriverCommand::GetCurrentUrl,
@@ -440,47 +440,40 @@ impl <U:WebDriverExtensionRoute> From<We
 
 /// Wrapper around the two supported variants of new session paramters
 ///
 /// The Spec variant is used for storing spec-compliant parameters whereas
 /// the legacy variant is used to store desiredCapabilities/requiredCapabilities
 /// parameters, and is intended to minimise breakage as we transition users to
 /// the spec design.
 
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(untagged)]
-pub enum NewSessionParametersWrapper {
-    Spec(SpecNewSessionParametersWrapper),
-    Legacy(LegacyNewSessionParameters),
-}
-
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
 pub enum NewSessionParameters {
     Spec(SpecNewSessionParameters),
+    #[serde(rename = "capabilities")]
     Legacy(LegacyNewSessionParameters),
 }
 
-impl From<NewSessionParametersWrapper> for NewSessionParameters {
-    fn from(wrapper: NewSessionParametersWrapper) -> NewSessionParameters {
-        match wrapper {
-            NewSessionParametersWrapper::Spec(x) => NewSessionParameters::Spec(x.into()),
-            NewSessionParametersWrapper::Legacy(x) => NewSessionParameters::Legacy(x)
-        }
-    }
-}
+// impl From<NewSessionParametersWrapper> for NewSessionParameters {
+//     fn from(wrapper: NewSessionParametersWrapper) -> NewSessionParameters {
+//         match wrapper {
+//             NewSessionParametersWrapper::Spec(x) => NewSessionParameters::Spec(x.into()),
+//             NewSessionParametersWrapper::Legacy(x) => NewSessionParameters::Legacy(x)
+//         }
+//     }
+// }
 
-
-impl <'a> From<&'a NewSessionParameters> for Value {
-    fn from(params: &'a NewSessionParameters) -> Value {
-        match *params {
-            NewSessionParameters::Spec(ref x) => x.into(),
-            NewSessionParameters::Legacy(ref x) => x.into()
-        }
-    }
-}
+// impl <'a> From<&'a NewSessionParameters> for Value {
+//     fn from(params: &'a NewSessionParameters) -> Value {
+//         match *params {
+//             NewSessionParameters::Spec(ref x) => x.into(),
+//             NewSessionParameters::Legacy(ref x) => x.into()
+//         }
+//     }
+// }
 
 impl CapabilitiesMatching for NewSessionParameters {
     fn match_browser<T: BrowserCapabilities>(&self, browser_capabilities: &mut T)
                                              -> WebDriverResult<Option<Capabilities>> {
         match self {
             &NewSessionParameters::Spec(ref x) => x.match_browser(browser_capabilities),
             &NewSessionParameters::Legacy(ref x) => x.match_browser(browser_capabilities)
         }
@@ -666,75 +659,81 @@ pub struct TakeScreenshotParameters {
 }
 
 #[cfg(test)]
 mod tests {
     use serde_json;
     use super::*;
 
     #[test]
-    fn test_take_screenshot_no_element() {
+    fn test_deserialize_take_screenshot_no_element() {
+        let data = r#"{"element": null}"#;
+
         let expected = TakeScreenshotParameters { element: None };
 
-        let data = r#"{"element": null}"#;
         let actual: TakeScreenshotParameters = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_take_screenshot_with_element() {
+    fn test_deserialize_take_screenshot_with_element() {
+        let data = r#"{"element": {"element-6066-11e4-a52e-4f735466cecf":"elem"}}"#;
+
         let expected = TakeScreenshotParameters {
             element: Some(WebElement { id: "elem".into() }),
         };
 
-        let data = r#"{"element": {"element-6066-11e4-a52e-4f735466cecf":"elem"}}"#;
         let actual: TakeScreenshotParameters = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_window_rect() {
+    fn test_deserialize_window_rect_with_values() {
+        let data = r#"{"x": 0, "y": 1, "width": 2, "height": 3}"#;
+
         let expected = WindowRectParameters {
             x: Some(0i32),
             y: Some(1i32),
             width: Some(2i32),
             height: Some(3i32),
         };
 
-        let data = r#"{"x": 0, "y": 1, "width": 2, "height": 3}"#;
         let actual: WindowRectParameters = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_window_rect_nullable() {
+    fn test_deserialize_window_rect_without_values() {
+        let data = r#"{"x": null, "y": null, "width": null, "height": null}"#;
+
         let expected = WindowRectParameters {
-            x: Some(0i32),
+            x: None,
             y: None,
-            width: Some(2i32),
+            width: None,
             height: None,
         };
 
-        let data = r#"{"x": 0, "y": null, "width": 2, "height": null}"#;
         let actual: WindowRectParameters = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_window_rect_missing_fields() {
+    fn test_deserialize_window_rect_missing_fields() {
+        let data = r#"{}"#;
+
         let expected = WindowRectParameters {
-            x: Some(0i32),
+            x: None,
             y: None,
-            width: Some(2i32),
+            width: None,
             height: None,
         };
 
-        let data = r#"{"x": 0, "width": 2}"#;
         let actual: WindowRectParameters = serde_json::from_str(&data).unwrap();
         assert_eq!(expected, actual);
     }
 
     #[test]
-    fn test_window_rect_floats() {
+    fn test_deserialize_window_rect_floats() {
         let data = r#"{"x": 1.1, "y": 2.2, "width": 3.3, "height": 4.4}"#;
+
         assert!(serde_json::from_str::<WindowRectParameters>(&data).is_err());
     }
 }
--- a/testing/webdriver/src/common.rs
+++ b/testing/webdriver/src/common.rs
@@ -1,83 +1,43 @@
-use serde_json::{Value, Map};
+use serde_json::Value;
 use std::convert::From;
 
+// TODO: Add custom errors to serde
 use error::{WebDriverResult, WebDriverError, ErrorStatus};
 
 pub static ELEMENT_KEY: &'static str = "element-6066-11e4-a52e-4f735466cecf";
 pub static FRAME_KEY: &'static str = "frame-075b-4da1-b6ba-e579c2d3230a";
 pub static WINDOW_KEY: &'static str = "window-fcc6-11e5-b4f8-330a88ab9d7f";
 
 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
 pub struct Date(pub u64);
 
 impl Date {
     pub fn new(timestamp: u64) -> Date {
         Date(timestamp)
     }
 }
 
+// TODO: to be removed once command.rs is fixed
 impl From<Date> for Value {
     fn from(date: Date) -> Value {
         let Date(x) = date;
         x.into()
     }
 }
 
 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
-pub struct WebElement {
-    #[serde(rename="element-6066-11e4-a52e-4f735466cecf")]
-    pub id: String
-}
-
-impl WebElement {
-    pub fn new(id: String) -> WebElement {
-        WebElement {
-            id: id
-        }
-    }
-
-    pub fn from_json(data: &Value) -> WebDriverResult<WebElement> {
-        let object = try_opt!(data.as_object(),
-                              ErrorStatus::InvalidArgument,
-                              "Could not convert webelement to object");
-        let id_value = try_opt!(object.get(ELEMENT_KEY),
-                                ErrorStatus::InvalidArgument,
-                                "Could not find webelement key");
-
-        let id = try_opt!(id_value.as_str(),
-                          ErrorStatus::InvalidArgument,
-                          "Could not convert web element to string").to_string();
-
-        Ok(WebElement::new(id))
-    }
-}
-
-impl <'a> From<&'a WebElement> for Value {
-    fn from(elem: &'a WebElement) -> Value {
-        let mut data = Map::new();
-        data.insert(ELEMENT_KEY.to_string(), elem.id.clone().into());
-        Value::Object(data)
-    }
-}
-
-impl <T> From<T> for WebElement
-    where T: Into<String> {
-    fn from(data: T) -> WebElement {
-        WebElement::new(data.into())
-    }
-}
-
-#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(untagged)]
 pub enum FrameId {
     Short(u16),
     Element(WebElement)
 }
 
+// TODO: to be removed once command.rs is fixed
 impl From<FrameId> for Value {
     fn from(frame_id: FrameId) -> Value {
         match frame_id {
             FrameId::Short(x) => {
                 Value::Number(x.into())
             },
             FrameId::Element(ref x) => {
                 Value::String(x.id.clone())
@@ -95,35 +55,235 @@ pub enum LocatorStrategy {
     #[serde(rename = "partial link text")]
     PartialLinkText,
     #[serde(rename = "tag name")]
     TagName,
     #[serde(rename = "xpath")]
     XPath,
 }
 
-impl LocatorStrategy {
-    pub fn from_json(body: &Value) -> WebDriverResult<LocatorStrategy> {
-        match try_opt!(body.as_str(),
-                       ErrorStatus::InvalidArgument,
-                       "Expected locator strategy as string") {
-            "css selector" => Ok(LocatorStrategy::CSSSelector),
-            "link text" => Ok(LocatorStrategy::LinkText),
-            "partial link text" => Ok(LocatorStrategy::PartialLinkText),
-            "tag name" => Ok(LocatorStrategy::TagName),
-            "xpath" => Ok(LocatorStrategy::XPath),
-            x => Err(WebDriverError::new(ErrorStatus::InvalidArgument,
-                                         format!("Unknown locator strategy {}", x)))
-        }
-    }
-}
+// impl LocatorStrategy {
+//     pub fn from_json(body: &Value) -> WebDriverResult<LocatorStrategy> {
+//         match try_opt!(body.as_str(),
+//                        ErrorStatus::InvalidArgument,
+//                        "Expected locator strategy as string") {
+//             "css selector" => Ok(LocatorStrategy::CSSSelector),
+//             "link text" => Ok(LocatorStrategy::LinkText),
+//             "partial link text" => Ok(LocatorStrategy::PartialLinkText),
+//             "tag name" => Ok(LocatorStrategy::TagName),
+//             "xpath" => Ok(LocatorStrategy::XPath),
+//             x => Err(WebDriverError::new(ErrorStatus::InvalidArgument,
+//                                          format!("Unknown locator strategy {}", x)))
+//         }
+//     }
+// }
 
 impl From<LocatorStrategy> for Value {
     fn from(strategy: LocatorStrategy) -> Value {
         match strategy {
             LocatorStrategy::CSSSelector => "css selector",
             LocatorStrategy::LinkText => "link text",
             LocatorStrategy::PartialLinkText => "partial link text",
             LocatorStrategy::TagName => "tag name",
             LocatorStrategy::XPath => "xpath"
         }.into()
     }
 }
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct WebElement {
+    #[serde(rename="element-6066-11e4-a52e-4f735466cecf")]
+    pub id: String
+}
+
+impl WebElement {
+    pub fn new(id: String) -> WebElement {
+        WebElement {
+            id: id
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use serde_json;
+    use super::*;
+
+    #[test]
+    fn test_deserialize_date() {
+        let data = r#"1234"#;
+
+        let date = Date(1234);
+        let actual: Date = serde_json::from_str(&data).unwrap();
+        assert_eq!(actual, date);
+    }
+
+    #[test]
+    fn test_deserialize_date_invalid() {
+        let data = r#""2018-01-01""#;
+        // TODO: User correct error type
+        assert!(serde_json::from_str::<Date>(&data).is_err());
+    }
+
+    #[test]
+    fn test_serialize_date() {
+        let expected = r#"1234"#;
+
+        let date = Date(1234);
+        assert_eq!(serde_json::to_string(&date).unwrap(), expected);
+    }
+
+    #[test]
+    fn test_deserialize_frame_id_short() {
+        let data = r#"1234"#;
+
+        let frame_id = FrameId::Short ( 1234 );
+        let actual: FrameId = serde_json::from_str(&data).unwrap();
+        assert_eq!(actual, frame_id);
+    }
+
+    #[test]
+    fn test_deserialize_frame_id_webelement() {
+        let data = r#"{"element-6066-11e4-a52e-4f735466cecf":"elem"}"#;
+
+        let frame_id = FrameId::Element ( WebElement::new("elem".into()) );
+        let actual: FrameId = serde_json::from_str(&data).unwrap();
+        assert_eq!(actual, frame_id);
+    }
+
+    #[test]
+    fn test_deserialize_frame_id_invalid() {
+        let data = r#"true"#;
+        // TODO: User correct error type
+        assert!(serde_json::from_str::<FrameId>(&data).is_err());
+    }
+
+    #[test]
+    fn test_serialize_frame_id_short() {
+        let expected = r#"1234"#;
+
+        let frame_id = FrameId::Short ( 1234 );
+        assert_eq!(serde_json::to_string(&frame_id).unwrap(), expected);
+    }
+
+    #[test]
+    fn test_serialize_frame_id_webelement() {
+        let expected = r#"{"element-6066-11e4-a52e-4f735466cecf":"elem"}"#;
+
+        let frame_id = FrameId::Element ( WebElement::new("elem".into()) );
+        assert_eq!(serde_json::to_string(&frame_id).unwrap(), expected);
+    }
+
+    #[test]
+    fn test_deserialize_locator_strategy_css_selector() {
+        let data = r#""css selector""#;
+
+        let strategy = LocatorStrategy::CSSSelector;
+        let actual: LocatorStrategy = serde_json::from_str(&data).unwrap();
+
+        assert_eq!(actual, strategy);
+    }
+
+    #[test]
+    fn test_deserialize_locator_strategy_link_text() {
+        let data = r#""link text""#;
+
+        let strategy = LocatorStrategy::LinkText;
+        let actual: LocatorStrategy = serde_json::from_str(&data).unwrap();
+
+        assert_eq!(actual, strategy);
+    }
+
+    #[test]
+    fn test_deserialize_locator_strategy_partial_link_text() {
+        let data = r#""partial link text""#;
+
+        let strategy = LocatorStrategy::PartialLinkText;
+        let actual: LocatorStrategy = serde_json::from_str(&data).unwrap();
+
+        assert_eq!(actual, strategy);
+    }
+
+    #[test]
+    fn test_deserialize_locator_strategy_tag_name() {
+        let data = r#""tag name""#;
+
+        let strategy = LocatorStrategy::TagName;
+        let actual: LocatorStrategy = serde_json::from_str(&data).unwrap();
+
+        assert_eq!(actual, strategy);
+    }
+
+    #[test]
+    fn test_deserialize_locator_strategy_xpath() {
+        let data = r#""xpath""#;
+
+        let strategy = LocatorStrategy::XPath;
+        let actual: LocatorStrategy = serde_json::from_str(&data).unwrap();
+
+        assert_eq!(actual, strategy);
+    }
+
+    #[test]
+    fn test_deserialize_locator_strategy_invalid() {
+        let data = r#""foo""#;
+        assert!(serde_json::from_str::<LocatorStrategy>(&data).is_err());
+    }
+
+    #[test]
+    fn test_serialize_locator_strategy_css_selector() {
+        let expected = r#""css selector""#;
+        let strategy = LocatorStrategy::CSSSelector;
+        assert_eq!(serde_json::to_string(&strategy).unwrap(), expected);
+    }
+
+    #[test]
+    fn test_serialize_locator_strategy_link_text() {
+        let expected = r#""link text""#;
+        let strategy = LocatorStrategy::LinkText;
+        assert_eq!(serde_json::to_string(&strategy).unwrap(), expected);
+    }
+
+    #[test]
+    fn test_serialize_locator_strategy_partial_link_text() {
+        let expected = r#""partial link text""#;
+        let strategy = LocatorStrategy::PartialLinkText;
+        assert_eq!(serde_json::to_string(&strategy).unwrap(), expected);
+    }
+
+    #[test]
+    fn test_serialize_locator_strategy_tag_name() {
+        let expected = r#""tag name""#;
+        let strategy = LocatorStrategy::TagName;
+        assert_eq!(serde_json::to_string(&strategy).unwrap(), expected);
+    }
+
+    #[test]
+    fn test_serialize_locator_strategy_xpath() {
+        let expected = r#""xpath""#;
+        let strategy = LocatorStrategy::XPath;
+        assert_eq!(serde_json::to_string(&strategy).unwrap(), expected);
+    }
+
+    #[test]
+    fn test_deserialize_webelement() {
+        let data = r#"{"element-6066-11e4-a52e-4f735466cecf":"elem"}"#;
+
+        let elem = WebElement::new("elem".into());
+        let actual: WebElement = serde_json::from_str(&data).unwrap();
+        assert_eq!(actual, elem);
+    }
+
+    #[test]
+    fn test_deserialize_webelement_invalid() {
+        let data = r#"{"elem-6066-11e4-a52e-4f735466cecf":"elem"}"#;
+        // TODO: User correct error type
+        assert!(serde_json::from_str::<WebElement>(&data).is_err());
+    }
+
+    #[test]
+    fn test_serialize_webelement() {
+        let expected = r#"{"element-6066-11e4-a52e-4f735466cecf":"elem"}"#;
+
+        let elem = WebElement::new("elem".into());
+        assert_eq!(serde_json::to_string(&elem).unwrap(), expected);
+    }
+}
--- a/testing/webdriver/src/error.rs
+++ b/testing/webdriver/src/error.rs
@@ -1,18 +1,19 @@
 use hyper::status::StatusCode;
 use base64::DecodeError;
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
+use serde_json::{Value, Error as SerdeError};
 use std::borrow::Cow;
 use std::convert::From;
 use std::error::Error;
 use std::fmt;
 use std::io;
-use serde_json::{self, Value, Error as SerdeError, Map};
 
-#[derive(Debug, PartialEq, Serialize)]
+#[derive(Debug, PartialEq)]
 pub enum ErrorStatus {
     /// The [`ElementClick`] command could not be completed because the
     /// [element] receiving the events is obscuring the element that was
     /// requested clicked.
     ///
     /// [`ElementClick`]:
     /// ../command/enum.WebDriverCommand.html#variant.ElementClick
     /// [element]: ../common/struct.WebElement.html
@@ -134,16 +135,66 @@ pub enum ErrorStatus {
 
     UnknownPath,
 
     /// Indicates that a [command] that should have executed properly is not
     /// currently supported.
     UnsupportedOperation,
 }
 
+impl<'de> Deserialize<'de> for ErrorStatus {
+    fn deserialize<D>(deserializer: D) -> Result<ErrorStatus, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        use self::ErrorStatus::*;
+
+        let error_status = match Deserialize::deserialize(deserializer)? {
+            "element click intercepted" => ElementClickIntercepted,
+            "element not interactable" | "element not visible" => ElementNotInteractable,
+            "element not selectable" => ElementNotSelectable,
+            "insecure certificate" => InsecureCertificate,
+            "invalid argument" => InvalidArgument,
+            "invalid cookie domain" => InvalidCookieDomain,
+            "invalid coordinates" | "invalid element coordinates" => InvalidCoordinates,
+            "invalid element state" => InvalidElementState,
+            "invalid selector" => InvalidSelector,
+            "invalid session id" => InvalidSessionId,
+            "javascript error" => JavascriptError,
+            "move target out of bounds" => MoveTargetOutOfBounds,
+            "no such alert" => NoSuchAlert,
+            "no such element" => NoSuchElement,
+            "no such frame" => NoSuchFrame,
+            "no such window" => NoSuchWindow,
+            "script timeout" => ScriptTimeout,
+            "session not created" => SessionNotCreated,
+            "stale element reference" => StaleElementReference,
+            "timeout" => Timeout,
+            "unable to capture screen" => UnableToCaptureScreen,
+            "unable to set cookie" => UnableToSetCookie,
+            "unexpected alert open" => UnexpectedAlertOpen,
+            "unknown command" => UnknownCommand,
+            "unknown error" => UnknownError,
+            "unsupported operation" => UnsupportedOperation,
+            _ => UnknownError,
+        };
+
+        Ok(error_status)
+    }
+}
+
+impl Serialize for ErrorStatus {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        self.error_code().serialize(serializer)
+    }
+}
+
 impl ErrorStatus {
     /// Returns the string serialisation of the error type.
     pub fn error_code(&self) -> &'static str {
         use self::ErrorStatus::*;
         match *self {
             ElementClickIntercepted => "element click intercepted",
             ElementNotInteractable => "element not interactable",
             ElementNotSelectable => "element not selectable",
@@ -209,109 +260,91 @@ impl ErrorStatus {
             UnknownError => InternalServerError,
             UnknownMethod => MethodNotAllowed,
             UnknownPath => NotFound,
             UnsupportedOperation => InternalServerError,
         }
     }
 }
 
-/// Deserialises error type from string.
-impl From<String> for ErrorStatus {
-    fn from(s: String) -> ErrorStatus {
-        use self::ErrorStatus::*;
-        match &*s {
-            "element click intercepted" => ElementClickIntercepted,
-            "element not interactable" | "element not visible" => ElementNotInteractable,
-            "element not selectable" => ElementNotSelectable,
-            "insecure certificate" => InsecureCertificate,
-            "invalid argument" => InvalidArgument,
-            "invalid cookie domain" => InvalidCookieDomain,
-            "invalid coordinates" | "invalid element coordinates" => InvalidCoordinates,
-            "invalid element state" => InvalidElementState,
-            "invalid selector" => InvalidSelector,
-            "invalid session id" => InvalidSessionId,
-            "javascript error" => JavascriptError,
-            "move target out of bounds" => MoveTargetOutOfBounds,
-            "no such alert" => NoSuchAlert,
-            "no such element" => NoSuchElement,
-            "no such frame" => NoSuchFrame,
-            "no such window" => NoSuchWindow,
-            "script timeout" => ScriptTimeout,
-            "session not created" => SessionNotCreated,
-            "stale element reference" => StaleElementReference,
-            "timeout" => Timeout,
-            "unable to capture screen" => UnableToCaptureScreen,
-            "unable to set cookie" => UnableToSetCookie,
-            "unexpected alert open" => UnexpectedAlertOpen,
-            "unknown command" => UnknownCommand,
-            "unknown error" => UnknownError,
-            "unsupported operation" => UnsupportedOperation,
-            _ => UnknownError,
-        }
-    }
-}
-
 pub type WebDriverResult<T> = Result<T, WebDriverError>;
 
-#[derive(Debug, Serialize)]
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(remote = "Self")]
 pub struct WebDriverError {
     pub error: ErrorStatus,
     pub message: Cow<'static, str>,
     pub stack: Cow<'static, str>,
+    pub data: Option<Value>,
+    #[serde(skip)]
     pub delete_session: bool,
 }
 
+impl Serialize for WebDriverError {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        #[derive(Serialize)]
+        struct Wrapper<'a> {
+            #[serde(with = "WebDriverError")]
+            value: &'a WebDriverError,
+        }
+
+        Wrapper { value: self }.serialize(serializer)
+    }
+}
+
+impl<'de> Deserialize<'de> for WebDriverError {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        #[derive(Deserialize)]
+        struct Wrapper {
+            #[serde(with = "WebDriverError")]
+            value: WebDriverError,
+        }
+
+        Wrapper::deserialize(deserializer).map(|wrapper| wrapper.value)
+    }
+}
+
 impl WebDriverError {
     pub fn new<S>(error: ErrorStatus, message: S) -> WebDriverError
         where S: Into<Cow<'static, str>>
     {
         WebDriverError {
             error: error,
             message: message.into(),
             stack: "".into(),
+            data: None,
             delete_session: false,
         }
     }
 
     pub fn new_with_stack<S>(error: ErrorStatus, message: S, stack: S) -> WebDriverError
         where S: Into<Cow<'static, str>>
     {
         WebDriverError {
             error: error,
             message: message.into(),
             stack: stack.into(),
+            data: None,
             delete_session: false,
         }
     }
 
     pub fn error_code(&self) -> &'static str {
         self.error.error_code()
     }
 
     pub fn http_status(&self) -> StatusCode {
         self.error.http_status()
     }
-
-    pub fn to_json_string(&self) -> String {
-        serde_json::to_string(&Value::from(self)).unwrap()
-    }
-}
-
-impl <'a> From<&'a WebDriverError> for Value {
-    fn from(err: &'a WebDriverError) -> Value {
-        let mut data = Map::new();
-        data.insert("error".into(), err.error_code().into());
-        data.insert("message".into(), err.message.clone().into());
-        data.insert("stacktrace".into(),
-                    format!("{:?}", err.stack).into());
-        let mut wrapper = Map::new();
-        wrapper.insert("value".into(), Value::Object(data));
-        Value::Object(wrapper)
-    }
 }
 
 impl Error for WebDriverError {
     fn description(&self) -> &str {
         self.error_code()
     }
 
     fn cause(&self) -> Option<&Error> {
@@ -343,8 +376,108 @@ impl From<DecodeError> for WebDriverErro
     }
 }
 
 impl From<Box<Error>> for WebDriverError {
     fn from(err: Box<Error>) -> WebDriverError {
         WebDriverError::new(ErrorStatus::UnknownError, err.description().to_string())
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use serde_json;
+    use super::*;
+
+    #[test]
+    fn test_deserialize_webdriver_error_with_optional() {
+        let data = r#"{"value":{"error":"unknown error","message":"foo bar","stack":"foo\nbar","data":"foobar"}}"#;
+
+        let error = WebDriverError {
+            error: ErrorStatus::UnknownError,
+            message: "foo bar".into(),
+            stack: "foo\nbar".into(),
+            data: Some("foobar".into()),
+            delete_session: false,
+        };
+
+        let actual: WebDriverError = serde_json::from_str(&data).unwrap();
+        assert_eq!(actual, error);
+    }
+
+    #[test]
+    fn test_deserialize_webdriver_error_without_optional() {
+        let data = r#"{"value":{"error":"unknown error","message":"foo bar","stack":"foo\nbar","data":null}}"#;
+
+        let error = WebDriverError {
+            error: ErrorStatus::UnknownError,
+            message: "foo bar".into(),
+            stack: "foo\nbar".into(),
+            data: None,
+            delete_session: false,
+        };
+
+
+        let actual: WebDriverError = serde_json::from_str(&data).unwrap();
+        assert_eq!(actual, error);
+    }
+
+    #[test]
+    fn test_deserialize_webdriver_error_invalid() {
+        let data = r#"{"error":"unknown","message":"foo bar","stack":"foo\nbar","data":null}"#;
+        assert!(serde_json::from_str::<WebDriverError>(&data).is_err());
+    }
+
+    #[test]
+    fn test_serialize_webdriver_error_with_optional() {
+        let expected = r#"{"value":{"error":"unknown error","message":"foo bar","stack":"foo\nbar","data":"foobar"}}"#;
+
+        let error = WebDriverError {
+            error: ErrorStatus::UnknownError,
+            message: "foo bar".into(),
+            stack: "foo\nbar".into(),
+            data: Some("foobar".into()),
+            delete_session: true,
+        };
+
+        assert_eq!(serde_json::to_string(&error).unwrap(), expected);
+    }
+
+    #[test]
+    fn test_serialize_webdriver_error_without_optional() {
+        let expected = r#"{"value":{"error":"unknown error","message":"foo bar","stack":"foo\nbar","data":null}}"#;
+
+        let error = WebDriverError {
+            error: ErrorStatus::UnknownError,
+            message: "foo bar".into(),
+            stack: "foo\nbar".into(),
+            data: None,
+            delete_session: false,
+        };
+
+        assert_eq!(serde_json::to_string(&error).unwrap(), expected);
+    }
+
+    #[test]
+    fn test_deserialize_error_status_specific() {
+        let error = ErrorStatus::InvalidSessionId;
+
+        let data = format!(r#""{}""#, error.error_code());
+        let actual: ErrorStatus = serde_json::from_str(&data).unwrap();
+        assert_eq!(actual, ErrorStatus::InvalidSessionId);
+    }
+
+    #[test]
+    fn test_deserialize_error_status_unknown() {
+        let data = r#""foo bar""#;
+        let actual: ErrorStatus = serde_json::from_str(&data).unwrap();
+        assert_eq!(actual, ErrorStatus::UnknownError);
+    }
+
+    #[test]
+    fn test_serialize_error_status() {
+        let error = ErrorStatus::UnknownError;
+        let expected = format!(r#""{}""#, error.error_code());
+
+
+        assert_eq!(serde_json::to_string(&error).unwrap(), expected);
+    }
+}
\ No newline at end of file
--- a/testing/webdriver/src/response.rs
+++ b/testing/webdriver/src/response.rs
@@ -1,10 +1,10 @@
 use common::Date;
-use serde::ser::{Serialize, Serializer};
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
 use serde_json::Value;
 
 #[derive(Debug, Serialize)]
 #[serde(untagged, remote = "Self")]
 pub enum WebDriverResponse {
     CloseWindow(CloseWindowResponse),
     Cookie(CookieResponse),
     Cookies(CookiesResponse),
@@ -27,21 +27,45 @@ impl Serialize for WebDriverResponse {
             #[serde(with = "WebDriverResponse")]
             value: &'a WebDriverResponse,
         }
 
         Wrapper { value: self }.serialize(serializer)
     }
 }
 
-#[derive(Debug, Serialize)]
+impl<'de> Deserialize<'de> for WebDriverResponse {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        #[derive(Deserialize)]
+        struct Wrapper {
+            #[serde(with = "WebDriverResponse")]
+            value: WebDriverResponse,
+        }
+
+        Wrapper::deserialize(deserializer).map(|wrapper| wrapper.value)
+    }
+}
+
+#[derive(Debug)]
 pub struct CloseWindowResponse {
     pub window_handles: Vec<String>,
 }
 
+impl Serialize for CloseWindowResponse {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        self.window_handles.serialize(serializer)
+    }
+}
+
 impl CloseWindowResponse {
     pub fn new(handles: Vec<String>) -> CloseWindowResponse {
         CloseWindowResponse { window_handles: handles }
     }
 }
 
 #[derive(Clone, Debug, PartialEq, Serialize)]
 pub struct CookieResponse {
@@ -64,19 +88,28 @@ impl CookieResponse {
             domain: domain,
             expiry: expiry,
             secure: secure,
             httpOnly: http_only
         }
     }
 }
 
-#[derive(Debug, Serialize)]
+#[derive(Debug)]
 pub struct CookiesResponse {
-    pub value: Vec<CookieResponse>,
+    pub cookies: Vec<CookieResponse>,
+}
+
+impl Serialize for CookiesResponse {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        self.cookies.serialize(serializer)
+    }
 }
 
 #[derive(Debug, Serialize)]
 pub struct ElementRectResponse {
     /// X axis position of the top-left corner of the element relative
     // to the current browsing context’s document element in CSS reference
     // pixels.
     pub x: f64,
@@ -137,21 +170,30 @@ impl TimeoutsResponse {
         TimeoutsResponse {
             script: script,
             pageLoad: page_load,
             implicit: implicit,
         }
     }
 }
 
-#[derive(Debug, Serialize)]
+#[derive(Debug)]
 pub struct ValueResponse {
     pub value: Value
 }
 
+impl Serialize for ValueResponse {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        self.value.serialize(serializer)
+    }
+}
+
 impl ValueResponse {
     pub fn new(value: Value) -> ValueResponse {
         ValueResponse {
             value: value
         }
     }
 }
 
@@ -178,100 +220,120 @@ pub struct WindowRectResponse {
     pub height: i32,
 }
 
 #[cfg(test)]
 mod tests {
     use serde_json;
     use super::*;
 
-    //#[test]
+    #[test]
     fn test_serialize_close_window_response() {
         let expected = r#"{"value":["1234"]}"#;
 
         let response = WebDriverResponse::CloseWindow(
             CloseWindowResponse::new(vec!["1234".into()]));
         assert_eq!(serde_json::to_string(&response).unwrap(), expected);
     }
 
     #[test]
-    fn test_serialize_cookie_response() {
+    fn test_serialize_cookie_response_with_optional() {
+        let expected = r#"{"value":{"name":"foo","value":"bar","path":"/","domain":"foo.bar","expiry":123,"secure":true,"httpOnly":false}}"#;
+
+        let response = WebDriverResponse::Cookie(CookieResponse {
+            name: "foo".into(),
+            value: "bar".into(),
+            path: Some("/".into()),
+            domain: Some("foo.bar".into()),
+            expiry: Some(Date::new(123)),
+            secure: true,
+            httpOnly: false,
+            });
+        assert_eq!(serde_json::to_string(&response).unwrap(), expected);
+    }
+
+    #[test]
+    fn test_serialize_cookie_response_without_optional() {
         let expected = r#"{"value":{"name":"foo","value":"bar","path":"/","domain":null,"expiry":null,"secure":true,"httpOnly":false}}"#;
 
         let response = WebDriverResponse::Cookie(CookieResponse {
             name: "foo".into(),
             value: "bar".into(),
             path: Some("/".into()),
             domain: None,
             expiry: None,
             secure: true,
             httpOnly: false,
             });
         assert_eq!(serde_json::to_string(&response).unwrap(), expected);
     }
 
-    //#[test]
+    #[test]
     fn test_serialize_cookies_response() {
         let expected = r#"{"value":[{"name":"name","value":"value","path":"/","domain":null,"expiry":null,"secure":true,"httpOnly":false}]}"#;
 
         let response = WebDriverResponse::Cookies(CookiesResponse {
-            value: vec![
+            cookies: vec![
                 CookieResponse {
                     name: "name".into(),
                     value: "value".into(),
                     path: Some("/".into()),
                     domain: None,
                     expiry: None,
                     secure: true,
                     httpOnly: false,
                 }
             ]});
         assert_eq!(serde_json::to_string(&response).unwrap(), expected);
     }
 
     #[test]
     fn test_serialize_delete_session_response() {
-        // TODO
+        let expected = r#"{"value":null}"#;
+
+        let response = WebDriverResponse::DeleteSession;
+        assert_eq!(serde_json::to_string(&response).unwrap(), expected);
     }
 
     #[test]
     fn test_serialize_element_rect_response() {
         let expected = r#"{"value":{"x":0.0,"y":1.0,"width":2.0,"height":3.0}}"#;
 
         let response = WebDriverResponse::ElementRect(
             ElementRectResponse {
                 x: 0f64,
                 y: 1f64,
                 width: 2f64,
                 height: 3f64,
             });
         assert_eq!(serde_json::to_string(&response).unwrap(), expected);
     }
 
-    //#[test]
-    fn test_serialize_generic_response() {
+    #[test]
+    fn test_serialize_generic_value_response() {
         let expected = r#"{"value":{"example":["test"]}}"#;
 
         let mut value = serde_json::Map::new();
         value.insert("example".into(), Value::Array(
             vec![Value::String("test".into())]));
 
         let response = WebDriverResponse::Generic(
             ValueResponse::new(Value::Object(value)));
 
         assert_eq!(serde_json::to_string(&response).unwrap(), expected);
     }
 
     #[test]
     fn test_serialize_new_session_response() {
         let expected = r#"{"value":{"sessionId":"id","capabilities":{}}}"#;
 
-        let response = WebDriverResponse::NewSession(NewSessionResponse::new(
-            "id".into(),
-            Value::Object(serde_json::Map::new())
+        let response = WebDriverResponse::NewSession(
+            NewSessionResponse::new(
+                "id".into(),
+                Value::Object(serde_json::Map::new())
         ));
         assert_eq!(serde_json::to_string(&response).unwrap(), expected);
     }
 
     #[test]
     fn test_serialize_timeouts_response() {
         let expected = r#"{"value":{"script":1,"pageLoad":2,"implicit":3}}"#;
 
@@ -297,22 +359,9 @@ mod tests {
                 x: 0i32,
                 y: 1i32,
                 width: 2i32,
                 height: 3i32,
             });
 
         assert_eq!(serde_json::to_string(&response).unwrap(), expected);
     }
-
-    #[test]
-    fn test_serialize_value_response() {
-        let expected = r#"{"value":{"example":["test"]}}"#;
-
-        let mut value = serde_json::Map::new();
-        value.insert("example".into(), Value::Array(
-            vec![Value::String("test".into())]));
-
-        let response = ValueResponse::new(Value::Object(value));
-
-        assert_eq!(expected, serde_json::to_string(&response).unwrap());
-    }
 }