123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- package Selenium::Remote::ErrorHandler;
- use strict;
- use warnings;
- # ABSTRACT: Error handler for Selenium::Remote::Driver
- use Moo;
- use Carp qw(croak);
- # We're going to handle only codes that are errors.
- # http://code.google.com/p/selenium/wiki/JsonWireProtocol
- has STATUS_CODE => (
- is => 'lazy',
- builder => sub {
- return {
- 7 => {
- 'code' => 'NO_SUCH_ELEMENT',
- 'msg' =>
- 'An element could not be located on the page using the given search parameters.',
- },
- 8 => {
- 'code' => 'NO_SUCH_FRAME',
- 'msg' =>
- 'A request to switch to a frame could not be satisfied because the frame could not be found.',
- },
- 9 => {
- 'code' => 'UNKNOWN_COMMAND',
- 'msg' =>
- 'The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource.',
- },
- 10 => {
- 'code' => 'STALE_ELEMENT_REFERENCE',
- 'msg' =>
- 'An element command failed because the referenced element is no longer attached to the DOM.',
- },
- 11 => {
- 'code' => 'ELEMENT_NOT_VISIBLE',
- 'msg' =>
- 'An element command could not be completed because the element is not visible on the page.',
- },
- 12 => {
- 'code' => 'INVALID_ELEMENT_STATE',
- 'msg' =>
- 'An element command could not be completed because the element is in an invalid state (e.g. attempting to click a disabled element).',
- },
- 13 => {
- 'code' => 'UNKNOWN_ERROR',
- 'msg' =>
- 'An unknown server-side error occurred while processing the command.',
- },
- 15 => {
- 'code' => 'ELEMENT_IS_NOT_SELECTABLE',
- 'msg' =>
- 'An attempt was made to select an element that cannot be selected.',
- },
- 19 => {
- 'code' => 'XPATH_LOOKUP_ERROR',
- 'msg' =>
- 'An error occurred while searching for an element by XPath.',
- },
- 21 => {
- 'code' => 'Timeout',
- 'msg' =>
- 'An operation did not complete before its timeout expired.',
- },
- 23 => {
- 'code' => 'NO_SUCH_WINDOW',
- 'msg' =>
- 'A request to switch to a different window could not be satisfied because the window could not be found.',
- },
- 24 => {
- 'code' => 'INVALID_COOKIE_DOMAIN',
- 'msg' =>
- 'An illegal attempt was made to set a cookie under a different domain than the current page.',
- },
- 25 => {
- 'code' => 'UNABLE_TO_SET_COOKIE',
- 'msg' =>
- 'A request to set a cookie\'s value could not be satisfied.',
- },
- 26 => {
- 'code' => 'UNEXPECTED_ALERT_OPEN',
- 'msg' => 'A modal dialog was open, blocking this operation',
- },
- 27 => {
- 'code' => 'NO_ALERT_OPEN_ERROR',
- 'msg' =>
- 'An attempt was made to operate on a modal dialog when one was not open.',
- },
- 28 => {
- 'code' => 'SCRIPT_TIMEOUT',
- 'msg' =>
- 'A script did not complete before its timeout expired.',
- },
- 29 => {
- 'code' => 'INVALID_ELEMENT_COORDINATES',
- 'msg' =>
- 'The coordinates provided to an interactions operation are invalid.',
- },
- 30 => {
- 'code' => 'IME_NOT_AVAILABLE',
- 'msg' => 'IME was not available.',
- },
- 31 => {
- 'code' => 'IME_ENGINE_ACTIVATION_FAILED',
- 'msg' => 'An IME engine could not be started.',
- },
- 32 => {
- 'code' => 'INVALID_SELECTOR',
- 'msg' => 'Argument was an invalid selector (e.g. XPath/CSS).',
- },
- };
- }
- );
- =head1 SUBROUTINES
- =head2 process_error (Selenium::Remote::Driver $driver, HTTP::Response $response)
- Instead of just returning the end user a server returned error code, this returns a more human readable & usable error message.
- Used internally in Selenium::Remote::Driver, but overriding this might be useful in some situations.
- You could additionally alter the STATUS_CODE parameter of this module to add extra handlers if the situation warrants it.
- =cut
- sub process_error {
- my ( $self, $resp ) = @_;
- # TODO: Handle screen if it sent back with the response. Either we could
- # let the end user handle it or we can save it an image file at a temp
- # location & return the path.
- # handle stacktrace-only responses by assuming unknown error
- my $is_stacktrace = !$resp->{status};
- $resp->{status} = 13 unless $resp->{status};
- my $ret;
- #XXX capitalization is inconsistent among geckodriver versions
- $ret->{'stackTrace'} = $resp->{'value'}->{'stacktrace'}
- // $resp->{'value'}->{'stackTrace'};
- $ret->{'error'} =
- $is_stacktrace
- ? $resp->{value}->{error}
- : $self->STATUS_CODE->{ $resp->{'status'} };
- $ret->{'message'} = $resp->{'value'}->{'message'};
- return $ret;
- }
- 1;
- __END__
|