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 std::error;
6 use std::fmt;
7 
8 use serde::{Deserialize, Serialize};
9 
10 #[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
11 #[serde(untagged)]
12 pub(crate) enum Error {
13     Marionette(MarionetteError),
14 }
15 
16 impl Error {
kind(&self) -> ErrorKind17     pub fn kind(&self) -> ErrorKind {
18         match *self {
19             Error::Marionette(ref err) => err.kind,
20         }
21     }
22 }
23 
24 impl fmt::Debug for Error {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result25     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
26         match self {
27             Error::Marionette(ref err) => fmt
28                 .debug_struct("Marionette")
29                 .field("kind", &err.kind)
30                 .field("message", &err.message)
31                 .field("stacktrace", &err.stack.clone())
32                 .finish(),
33         }
34     }
35 }
36 
37 impl fmt::Display for Error {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result38     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
39         match self {
40             Error::Marionette(ref err) => write!(fmt, "{}: {}", err.kind, err.message),
41         }
42     }
43 }
44 
45 impl error::Error for Error {
description(&self) -> &str46     fn description(&self) -> &str {
47         match self {
48             Error::Marionette(_) => self.kind().as_str(),
49         }
50     }
51 }
52 
53 #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
54 pub struct MarionetteError {
55     #[serde(rename = "error")]
56     pub kind: ErrorKind,
57     #[serde(default = "empty_string")]
58     pub message: String,
59     #[serde(rename = "stacktrace", default = "empty_string")]
60     pub stack: String,
61 }
62 
empty_string() -> String63 fn empty_string() -> String {
64     "".to_owned()
65 }
66 
67 impl From<MarionetteError> for Error {
from(error: MarionetteError) -> Error68     fn from(error: MarionetteError) -> Error {
69         Error::Marionette(error)
70     }
71 }
72 
73 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
74 pub enum ErrorKind {
75     #[serde(rename = "element click intercepted")]
76     ElementClickIntercepted,
77     #[serde(rename = "element not accessible")]
78     ElementNotAccessible,
79     #[serde(rename = "element not interactable")]
80     ElementNotInteractable,
81     #[serde(rename = "insecure certificate")]
82     InsecureCertificate,
83     #[serde(rename = "invalid argument")]
84     InvalidArgument,
85     #[serde(rename = "invalid cookie")]
86     InvalidCookieDomain,
87     #[serde(rename = "invalid element state")]
88     InvalidElementState,
89     #[serde(rename = "invalid selector")]
90     InvalidSelector,
91     #[serde(rename = "invalid session id")]
92     InvalidSessionId,
93     #[serde(rename = "javascript error")]
94     JavaScript,
95     #[serde(rename = "move target out of bounds")]
96     MoveTargetOutOfBounds,
97     #[serde(rename = "no such alert")]
98     NoSuchAlert,
99     #[serde(rename = "no such element")]
100     NoSuchElement,
101     #[serde(rename = "no such frame")]
102     NoSuchFrame,
103     #[serde(rename = "no such window")]
104     NoSuchWindow,
105     #[serde(rename = "script timeout")]
106     ScriptTimeout,
107     #[serde(rename = "session not created")]
108     SessionNotCreated,
109     #[serde(rename = "stale element reference")]
110     StaleElementReference,
111     #[serde(rename = "timeout")]
112     Timeout,
113     #[serde(rename = "unable to set cookie")]
114     UnableToSetCookie,
115     #[serde(rename = "unexpected alert open")]
116     UnexpectedAlertOpen,
117     #[serde(rename = "unknown command")]
118     UnknownCommand,
119     #[serde(rename = "unknown error")]
120     Unknown,
121     #[serde(rename = "unsupported operation")]
122     UnsupportedOperation,
123     #[serde(rename = "webdriver error")]
124     WebDriver,
125 }
126 
127 impl ErrorKind {
as_str(self) -> &'static str128     pub(crate) fn as_str(self) -> &'static str {
129         use ErrorKind::*;
130         match self {
131             ElementClickIntercepted => "element click intercepted",
132             ElementNotAccessible => "element not accessible",
133             ElementNotInteractable => "element not interactable",
134             InsecureCertificate => "insecure certificate",
135             InvalidArgument => "invalid argument",
136             InvalidCookieDomain => "invalid cookie",
137             InvalidElementState => "invalid element state",
138             InvalidSelector => "invalid selector",
139             InvalidSessionId => "invalid session id",
140             JavaScript => "javascript error",
141             MoveTargetOutOfBounds => "move target out of bounds",
142             NoSuchAlert => "no such alert",
143             NoSuchElement => "no such element",
144             NoSuchFrame => "no such frame",
145             NoSuchWindow => "no such window",
146             ScriptTimeout => "script timeout",
147             SessionNotCreated => "session not created",
148             StaleElementReference => "stale eelement referencee",
149             Timeout => "timeout",
150             UnableToSetCookie => "unable to set cookie",
151             UnexpectedAlertOpen => "unexpected alert open",
152             UnknownCommand => "unknown command",
153             Unknown => "unknown error",
154             UnsupportedOperation => "unsupported operation",
155             WebDriver => "webdriver error",
156         }
157     }
158 }
159 
160 impl fmt::Display for ErrorKind {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result161     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
162         write!(fmt, "{}", self.as_str())
163     }
164 }
165 
166 #[cfg(test)]
167 mod tests {
168     use super::*;
169     use crate::test::assert_ser_de;
170     use serde_json::json;
171 
172     #[test]
test_json_error()173     fn test_json_error() {
174         let err = MarionetteError {
175             kind: ErrorKind::Timeout,
176             message: "".into(),
177             stack: "".into(),
178         };
179         assert_ser_de(
180             &err,
181             json!({"error": "timeout", "message": "", "stacktrace": ""}),
182         );
183     }
184 }
185