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