Skip to content

Commit d75a86d

Browse files
committed
fixing the error codes situation... but having to do so with exposing a deprecated method on WebDriverException which i don't like one bit. Better ideas appreciated :)
1 parent cf9f18e commit d75a86d

File tree

4 files changed

+70
-13
lines changed

4 files changed

+70
-13
lines changed

java/client/src/org/openqa/selenium/WebDriverException.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class WebDriverException extends RuntimeException {
2929
public static final String SESSION_ID = "Session ID";
3030
public static final String DRIVER_INFO = "Driver info";
3131
protected static final String BASE_SUPPORT_URL = "http://seleniumhq.org/exceptions/";
32+
protected Integer statusCode;
3233

3334
private Map<String, String> extraInfo = new HashMap<>();
3435

@@ -48,6 +49,23 @@ public WebDriverException(String message, Throwable cause) {
4849
super(message, cause);
4950
}
5051

52+
public WebDriverException(String message, Throwable cause, Integer statusCode) {
53+
super(message, cause);
54+
this.statusCode = statusCode;
55+
}
56+
57+
/**
58+
* DO NOT USE -
59+
* This is to help the standalone server map exceptions from remote ends back to clients without
60+
* losing the original status code provide (if one is). This will be going away in 4.0 when status
61+
* codes are only string messages
62+
* @return status code from the response of the remote end driver.
63+
*/
64+
@Deprecated
65+
public Integer getStatusCode() {
66+
return statusCode;
67+
}
68+
5169
@Override
5270
public String getMessage() {
5371
return createMessage(super.getMessage());

java/client/src/org/openqa/selenium/remote/ErrorCodes.java

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import java.util.Set;
5959
import java.util.logging.Logger;
6060
import java.util.stream.Collectors;
61+
import java.util.stream.Stream;
6162

6263
/**
6364
* Defines common error codes for the wire protocol.
@@ -97,6 +98,9 @@ public class ErrorCodes {
9798
// json wire protocol doesn't have analogous status codes for
9899
// these new W3C status repsonse 'codes', so making some up!
99100
public static final int ELEMENT_NOT_INTERACTABLE = 60;
101+
public static final int INVALID_ARGUMENT = 61;
102+
public static final int NO_SUCH_COOKIE = 62;
103+
public static final int UNABLE_TO_CAPTURE_SCREEN = 63;
100104

101105
// The following error codes are derived straight from HTTP return codes.
102106
public static final int METHOD_NOT_ALLOWED = 405;
@@ -113,9 +117,9 @@ public class ErrorCodes {
113117
.put(400,
114118
ImmutableSortedSet.<StatusTuple>naturalOrder()
115119
.add(new StatusTuple("element not selectable", ELEMENT_NOT_SELECTABLE, ElementNotSelectableException.class))
116-
.add(new StatusTuple("element not interactable", ELEMENT_NOT_INTERACTABLE, ElementNotInteractableException.class))
120+
.add(new StatusTuple("element not interactable", ELEMENT_NOT_INTERACTABLE, ElementNotInteractableException.class, UNHANDLED_ERROR))
117121
.add(new StatusTuple("element not visible", ELEMENT_NOT_VISIBLE, ElementNotVisibleException.class))
118-
.add(new StatusTuple("invalid argument", UNHANDLED_ERROR, InvalidArgumentException.class))
122+
.add(new StatusTuple("invalid argument", INVALID_ARGUMENT, InvalidArgumentException.class, UNHANDLED_ERROR))
119123
.add(new StatusTuple("invalid cookie domain", INVALID_COOKIE_DOMAIN, InvalidCookieDomainException.class))
120124
.add(new StatusTuple("invalid element coordinates", INVALID_ELEMENT_COORDINATES, InvalidCoordinatesException.class))
121125
.add(new StatusTuple("invalid element state", INVALID_ELEMENT_STATE, InvalidElementStateException.class))
@@ -131,9 +135,9 @@ public class ErrorCodes {
131135
.put(404,
132136
ImmutableSortedSet.<StatusTuple>naturalOrder()
133137
.add(new StatusTuple("invalid session id", NO_SUCH_SESSION, NoSuchSessionException.class))
134-
.add(new StatusTuple("no such cookie", UNHANDLED_ERROR, NoSuchCookieException.class))
138+
.add(new StatusTuple("no such cookie", NO_SUCH_COOKIE, NoSuchCookieException.class, UNHANDLED_ERROR))
135139
.add(new StatusTuple("no such element", NO_SUCH_ELEMENT, NoSuchElementException.class))
136-
.add(new StatusTuple("unknown command", UNKNOWN_COMMAND, UnsupportedCommandException.class, UNHANDLED_ERROR))
140+
.add(new StatusTuple("unknown command", UNKNOWN_COMMAND, UnsupportedCommandException.class))
137141
.build())
138142
.put(405,
139143
ImmutableSortedSet.<StatusTuple>naturalOrder()
@@ -146,13 +150,13 @@ public class ErrorCodes {
146150
.build())
147151
.put(500,
148152
ImmutableSortedSet.<StatusTuple>naturalOrder()
149-
.add(new StatusTuple("javascript error", JAVASCRIPT_ERROR, WebDriverException.class, UNHANDLED_ERROR))
153+
.add(new StatusTuple("javascript error", JAVASCRIPT_ERROR, WebDriverException.class))
150154
.add(new StatusTuple("move target out of bounds", MOVE_TARGET_OUT_OF_BOUNDS, MoveTargetOutOfBoundsException.class))
151155
.add(new StatusTuple("session not created", SESSION_NOT_CREATED, SessionNotCreatedException.class))
152156
.add(new StatusTuple("unable to set cookie", UNABLE_TO_SET_COOKIE, UnableToSetCookieException.class))
153-
.add(new StatusTuple("unable to capture screen", UNHANDLED_ERROR, ScreenshotException.class))
157+
.add(new StatusTuple("unable to capture screen", UNABLE_TO_CAPTURE_SCREEN, ScreenshotException.class, UNHANDLED_ERROR))
154158
.add(new StatusTuple("unexpected alert open", UNEXPECTED_ALERT_PRESENT, UnhandledAlertException.class))
155-
.add(new StatusTuple("unknown error", UNHANDLED_ERROR, WebDriverException.class, UNHANDLED_ERROR))
159+
.add(new StatusTuple("unknown error", UNHANDLED_ERROR, WebDriverException.class))
156160
.add(new StatusTuple("unsupported operation", METHOD_NOT_ALLOWED, UnsupportedCommandException.class, UNHANDLED_ERROR))
157161
.add(new StatusTuple("unsupported operation", IME_NOT_AVAILABLE, ImeNotAvailableException.class))
158162
.add(new StatusTuple("unsupported operation", IME_ENGINE_ACTIVATION_FAILED, ImeActivationFailedException.class))
@@ -165,6 +169,11 @@ public class ErrorCodes {
165169
.flatMap(Collection::stream)
166170
.collect(Collectors.toMap(StatusTuple::asStatus, StatusTuple::asState, (key1, key2) -> key1));
167171

172+
private static final Map<Integer, Class> JSON_TO_EXCEPTION = ALL_CODES.values().stream()
173+
.flatMap(Collection::stream)
174+
.filter(tuple -> tuple.getException() != null)
175+
.collect(Collectors.toMap(StatusTuple::asStatus, StatusTuple::getException, (key1, key2) -> key1));
176+
168177
private static final Map<String, Integer> W3C_TO_JSON = ALL_CODES.values().stream()
169178
.flatMap(Collection::stream)
170179
.collect(Collectors.toMap(StatusTuple::asState, StatusTuple::asStatus, (key1, key2) -> key1));
@@ -221,7 +230,7 @@ public int toStatus(String webdriverState, Optional<Integer> httpStatus) {
221230
* {@code statusCode == 0}.
222231
*/
223232
public Class<? extends WebDriverException> getExceptionType(int statusCode) {
224-
return getExceptionType(toState(statusCode));
233+
return JSON_TO_EXCEPTION.getOrDefault(statusCode, WebDriverException.class);
225234
}
226235

227236
public Class<? extends WebDriverException> getExceptionType(String webdriverState) {
@@ -242,13 +251,34 @@ public int toStatusCode(Throwable e) {
242251
}
243252

244253
// And then handle the other cases
245-
Set<Integer> possibleMatches = ALL_CODES.values().stream()
254+
Stream<StatusTuple> allCodesStream = ALL_CODES.values().stream()
246255
.flatMap(Collection::stream)
247256
.filter(tuple -> tuple.getException() != null)
248-
.filter(tuple -> tuple.associatedException.isAssignableFrom(e.getClass()))
257+
.filter(tuple -> tuple.associatedException.isAssignableFrom(e.getClass()));
258+
259+
if (e instanceof WebDriverException && ((WebDriverException)e).getStatusCode() != null) {
260+
allCodesStream = allCodesStream.filter(tuple -> ((WebDriverException)e).getStatusCode() == tuple.jsonStatus );
261+
}
262+
263+
Set<Integer> possibleMatches = allCodesStream
249264
.map(StatusTuple::getStatusFromException)
250265
.collect(Collectors.toSet());
251266

267+
if (possibleMatches.size() > 1) {
268+
// if there's multiple matches, let's try filtering on the exact exception class to see if we
269+
// can reduce the possibilities
270+
Set<Integer> reducedPossibleMatches = ALL_CODES.values().stream()
271+
.flatMap(Collection::stream)
272+
.filter(tuple -> tuple.getException() != null)
273+
.filter(tuple -> tuple.associatedException.equals(e.getClass()))
274+
.map(StatusTuple::getStatusFromException)
275+
.collect(Collectors.toSet());
276+
277+
if (reducedPossibleMatches.size() > 0) {
278+
possibleMatches = reducedPossibleMatches;
279+
}
280+
}
281+
252282
return Preconditions.checkNotNull(Iterables.getFirst(possibleMatches, UNHANDLED_ERROR));
253283
}
254284

java/client/src/org/openqa/selenium/remote/ErrorHandler.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ public Response throwIfResponseFailed(Response response, long duration) throws R
159159
toThrow = createUnhandledAlertException(value);
160160
}
161161

162+
if (toThrow == null) {
163+
toThrow = createThrowable(outerErrorType,
164+
new Class<?>[] {String.class, Throwable.class, Integer.class},
165+
new Object[] {message, cause, response.getStatus()});
166+
}
167+
162168
if (toThrow == null) {
163169
toThrow = createThrowable(outerErrorType,
164170
new Class<?>[] {String.class, Throwable.class},

java/client/test/org/openqa/selenium/remote/ErrorHandlerTest.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,12 @@
5353
import org.openqa.selenium.UnableToSetCookieException;
5454
import org.openqa.selenium.UnhandledAlertException;
5555
import org.openqa.selenium.UnsupportedCommandException;
56-
import org.openqa.selenium.WebDriver;
5756
import org.openqa.selenium.WebDriverException;
5857
import org.openqa.selenium.interactions.InvalidCoordinatesException;
5958
import org.openqa.selenium.interactions.MoveTargetOutOfBoundsException;
6059

6160
import javafx.util.Pair;
6261

63-
import java.util.ArrayList;
6462
import java.util.Arrays;
6563
import java.util.List;
6664
import java.util.Map;
@@ -473,7 +471,12 @@ public void testStatusCodesRaisedBackToStatusMatches() {
473471
fail("Should have thrown an Exception");
474472
} catch (Exception e) {
475473
assertEquals("Checking status code: " + exception.getKey(), exception.getValue().getSimpleName(), e.getClass().getSimpleName());
476-
assertEquals(e.getClass().getSimpleName() + " ErrorCodes.toStatusCode", exception.getKey().intValue(), new ErrorCodes().toStatusCode(e));
474+
int expected = exception.getKey();
475+
if (e instanceof InvalidSelectorException) {
476+
// all of the special invalid selector exceptions are just mapped to the generic invalid selector
477+
expected = 32;
478+
}
479+
assertEquals(e.getClass().getSimpleName() + " ErrorCodes.toStatusCode", expected, new ErrorCodes().toStatusCode(e));
477480
}
478481
}
479482
}

0 commit comments

Comments
 (0)