1 use serde::ser::{Serialize, Serializer};
2 use serde::{Deserialize, Deserializer};
3 use std::collections::HashMap;
4
5 pub static ELEMENT_KEY: &str = "element-6066-11e4-a52e-4f735466cecf";
6 pub static FRAME_KEY: &str = "frame-075b-4da1-b6ba-e579c2d3230a";
7 pub static WINDOW_KEY: &str = "window-fcc6-11e5-b4f8-330a88ab9d7f";
8
9 pub static MAX_SAFE_INTEGER: u64 = 9_007_199_254_740_991;
10
11 pub type Parameters = HashMap<String, String>;
12
13 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
14 pub struct Cookie {
15 pub name: String,
16 pub value: String,
17 pub path: Option<String>,
18 pub domain: Option<String>,
19 #[serde(default)]
20 pub secure: bool,
21 #[serde(rename = "httpOnly")]
22 pub http_only: bool,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub expiry: Option<Date>,
25 }
26
27 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
28 pub struct Date(pub u64);
29
30 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
31 #[serde(untagged)]
32 pub enum FrameId {
33 Short(u16),
34 #[serde(
35 rename = "element-6066-11e4-a52e-4f735466cecf",
36 serialize_with = "serialize_webelement_id"
37 )]
38 Element(WebElement),
39 }
40
41 // TODO(Henrik): Remove when ToMarionette trait has been fixed (Bug 1481776)
serialize_webelement_id<S>(element: &WebElement, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,42 fn serialize_webelement_id<S>(element: &WebElement, serializer: S) -> Result<S::Ok, S::Error>
43 where
44 S: Serializer,
45 {
46 element.serialize(serializer)
47 }
48
49 #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
50 pub enum LocatorStrategy {
51 #[serde(rename = "css selector")]
52 CSSSelector,
53 #[serde(rename = "link text")]
54 LinkText,
55 #[serde(rename = "partial link text")]
56 PartialLinkText,
57 #[serde(rename = "tag name")]
58 TagName,
59 #[serde(rename = "xpath")]
60 XPath,
61 }
62
63 #[derive(Clone, Debug, PartialEq)]
64 pub struct WebElement(pub String);
65
66 // private
67 #[derive(Serialize, Deserialize)]
68 struct WebElementObject {
69 #[serde(rename = "element-6066-11e4-a52e-4f735466cecf")]
70 id: String,
71 }
72
73 impl Serialize for WebElement {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,74 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: Serializer,
77 {
78 WebElementObject { id: self.0.clone() }.serialize(serializer)
79 }
80 }
81
82 impl<'de> Deserialize<'de> for WebElement {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,83 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
84 where
85 D: Deserializer<'de>,
86 {
87 Deserialize::deserialize(deserializer).map(|WebElementObject { id }| WebElement(id))
88 }
89 }
90
91 impl WebElement {
to_string(&self) -> String92 pub fn to_string(&self) -> String {
93 self.0.clone()
94 }
95 }
96
97 #[derive(Clone, Debug, PartialEq)]
98 pub struct WebFrame(pub String);
99
100 // private
101 #[derive(Serialize, Deserialize)]
102 struct WebFrameObject {
103 #[serde(rename = "frame-075b-4da1-b6ba-e579c2d3230a")]
104 id: String,
105 }
106
107 impl Serialize for WebFrame {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,108 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
109 where
110 S: Serializer,
111 {
112 WebFrameObject { id: self.0.clone() }.serialize(serializer)
113 }
114 }
115
116 impl<'de> Deserialize<'de> for WebFrame {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,117 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
118 where
119 D: Deserializer<'de>,
120 {
121 Deserialize::deserialize(deserializer).map(|WebFrameObject { id }| WebFrame(id))
122 }
123 }
124
125 #[derive(Clone, Debug, PartialEq)]
126 pub struct WebWindow(pub String);
127
128 // private
129 #[derive(Serialize, Deserialize)]
130 struct WebWindowObject {
131 #[serde(rename = "window-fcc6-11e5-b4f8-330a88ab9d7f")]
132 id: String,
133 }
134
135 impl Serialize for WebWindow {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,136 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
137 where
138 S: Serializer,
139 {
140 WebWindowObject { id: self.0.clone() }.serialize(serializer)
141 }
142 }
143
144 impl<'de> Deserialize<'de> for WebWindow {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,145 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
146 where
147 D: Deserializer<'de>,
148 {
149 Deserialize::deserialize(deserializer).map(|WebWindowObject { id }| WebWindow(id))
150 }
151 }
152
153 #[cfg(test)]
154 mod tests {
155 use super::*;
156 use crate::test::{assert_ser, assert_ser_de};
157 use serde_json::{self, json};
158
159 #[test]
test_json_date()160 fn test_json_date() {
161 assert_ser_de(&Date(1234), json!(1234));
162 }
163
164 #[test]
test_json_date_invalid()165 fn test_json_date_invalid() {
166 assert!(serde_json::from_value::<Date>(json!("2018-01-01")).is_err());
167 }
168
169 #[test]
test_json_frame_id_short()170 fn test_json_frame_id_short() {
171 assert_ser_de(&FrameId::Short(1234), json!(1234));
172 }
173
174 #[test]
test_json_frame_id_webelement()175 fn test_json_frame_id_webelement() {
176 assert_ser(
177 &FrameId::Element(WebElement("elem".into())),
178 json!({ELEMENT_KEY: "elem"}),
179 );
180 }
181
182 #[test]
test_json_frame_id_invalid()183 fn test_json_frame_id_invalid() {
184 assert!(serde_json::from_value::<FrameId>(json!(true)).is_err());
185 }
186
187 #[test]
test_json_locator_strategy_css_selector()188 fn test_json_locator_strategy_css_selector() {
189 assert_ser_de(&LocatorStrategy::CSSSelector, json!("css selector"));
190 }
191
192 #[test]
test_json_locator_strategy_link_text()193 fn test_json_locator_strategy_link_text() {
194 assert_ser_de(&LocatorStrategy::LinkText, json!("link text"));
195 }
196
197 #[test]
test_json_locator_strategy_partial_link_text()198 fn test_json_locator_strategy_partial_link_text() {
199 assert_ser_de(
200 &LocatorStrategy::PartialLinkText,
201 json!("partial link text"),
202 );
203 }
204
205 #[test]
test_json_locator_strategy_tag_name()206 fn test_json_locator_strategy_tag_name() {
207 assert_ser_de(&LocatorStrategy::TagName, json!("tag name"));
208 }
209
210 #[test]
test_json_locator_strategy_xpath()211 fn test_json_locator_strategy_xpath() {
212 assert_ser_de(&LocatorStrategy::XPath, json!("xpath"));
213 }
214
215 #[test]
test_json_locator_strategy_invalid()216 fn test_json_locator_strategy_invalid() {
217 assert!(serde_json::from_value::<LocatorStrategy>(json!("foo")).is_err());
218 }
219
220 #[test]
test_json_webelement()221 fn test_json_webelement() {
222 assert_ser_de(&WebElement("elem".into()), json!({ELEMENT_KEY: "elem"}));
223 }
224
225 #[test]
test_json_webelement_invalid()226 fn test_json_webelement_invalid() {
227 assert!(serde_json::from_value::<WebElement>(json!({"invalid": "elem"})).is_err());
228 }
229
230 #[test]
test_json_webframe()231 fn test_json_webframe() {
232 assert_ser_de(&WebFrame("frame".into()), json!({FRAME_KEY: "frame"}));
233 }
234
235 #[test]
test_json_webframe_invalid()236 fn test_json_webframe_invalid() {
237 assert!(serde_json::from_value::<WebFrame>(json!({"invalid": "frame"})).is_err());
238 }
239
240 #[test]
test_json_webwindow()241 fn test_json_webwindow() {
242 assert_ser_de(&WebWindow("window".into()), json!({WINDOW_KEY: "window"}));
243 }
244
245 #[test]
test_json_webwindow_invalid()246 fn test_json_webwindow_invalid() {
247 assert!(serde_json::from_value::<WebWindow>(json!({"invalid": "window"})).is_err());
248 }
249 }
250