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