{-# OPTIONS_HADDOCK hide #-} module WebDriverPreCore.Error ( WebDriverErrorType(..), ErrorClassification(..), errorDescription, errorCodeToErrorType, errorTypeToErrorCode, parseWebDriverError, parseWebDriverErrorType ) where import Data.Aeson (Value, withObject) import Data.Aeson.Types ((.:), parseMaybe) import Data.Text (Text) import Data.Eq (Eq) import GHC.Show (Show) import Data.Ord (Ord) import Data.Maybe (Maybe (..)) import WebDriverPreCore.HttpResponse (HttpResponse (..)) import GHC.Enum ( Bounded, Enum ) import Data.Either (Either (..)) import Control.Monad ((>>=)) import Data.Function (($)) {- Error Code HTTP Status JSON Error Code Description element click intercepted 400 element click intercepted The Element Click command could not be completed because the element receiving the events is obscuring the element that was requested clicked. element not interactable 400 element not interactable A command could not be completed because the element is not pointer- or keyboard interactable. insecure certificate 400 insecure certificate Navigation caused the user agent to hit a certificate warning, which is usually the result of an expired or invalid TLS certificate. invalid argument 400 invalid argument The arguments passed to a command are either invalid or malformed. invalid cookie domain 400 invalid cookie domain An illegal attempt was made to set a cookie under a different domain than the current page. invalid element state 400 invalid element state A command could not be completed because the element is in an invalid state, e.g. attempting to clear an element that isn't both editable and resettable. invalid selector 400 invalid selector Argument was an invalid selector. invalid session id 404 invalid session id Occurs if the given session id is not in the list of active sessions, meaning the session either does not exist or that it's not active. javascript error 500 javascript error An error occurred while executing JavaScript supplied by the user. move target out of bounds 500 move target out of bounds The target for mouse interaction is not in the browser's viewport and cannot be brought into that viewport. no such alert 404 no such alert An attempt was made to operate on a modal dialog when one was not open. no such cookie 404 no such cookie No cookie matching the given path name was found amongst the associated cookies of session's current browsing context's active document. no such element 404 no such element An element could not be located on the page using the given search parameters. no such frame 404 no such frame A command to switch to a frame could not be satisfied because the frame could not be found. no such window 404 no such window A command to switch to a window could not be satisfied because the window could not be found. no such shadow root 404 no such shadow root The element does not have a shadow root. script timeout error 500 script timeout A script did not complete before its timeout expired. session not created 500 session not created A new session could not be created. stale element reference 404 stale element reference A command failed because the referenced element is no longer attached to the DOM. detached shadow root 404 detached shadow root A command failed because the referenced shadow root is no longer attached to the DOM. timeout 500 timeout An operation did not complete before its timeout expired. unable to set cookie 500 unable to set cookie A command to set a cookie's value could not be satisfied. unable to capture screen 500 unable to capture screen A screen capture was made impossible. unexpected alert open 500 unexpected alert open A modal dialog was open, blocking this operation. unknown command 404 unknown command A command could not be executed because the remote end is not aware of it. unknown error 500 unknown error An unknown error occurred in the remote end while processing the command. unknown method 405 unknown method The requested command matched a known URL but did not match any method for that URL. unsupported operation 500 unsupported operation Indicates that a command that should have executed properly cannot be supported for some reason. -} -- | Known WevDriver error types: [spec](https://www.w3.org/TR/2025/WD-webdriver2-20250210/#errors) data WebDriverErrorType = ElementClickIntercepted | ElementNotInteractable | InsecureCertificate | InvalidArgument | InvalidCookieDomain | InvalidElementState | InvalidSelector | InvalidSessionId | JavascriptError | MoveTargetOutOfBounds | NoSuchAlert | NoSuchCookie | NoSuchElement | NoSuchFrame | NoSuchWindow | NoSuchShadowRoot | ScriptTimeoutError | SessionNotCreated | StaleElementReference | DetachedShadowRoot | Timeout | UnableToSetCookie | UnableToCaptureScreen | UnexpectedAlertOpen | UnknownCommand | UnknownError | UnknownMethod | UnsupportedOperation deriving (Eq, Show, Ord, Bounded, Enum) getError :: Value -> Maybe Text getError = parseMaybe $ withObject "root" $ \o -> o .: "value" >>= withObject "inner" (.: "error") errorCodeToErrorType :: Text -> Either Text WebDriverErrorType errorCodeToErrorType errCode = case errCode of "element click intercepted" -> r ElementClickIntercepted "element not interactable" -> r ElementNotInteractable "insecure certificate" -> r InsecureCertificate "invalid argument" -> r InvalidArgument "invalid cookie domain" -> r InvalidCookieDomain "invalid element state" -> r InvalidElementState "invalid selector" -> r InvalidSelector "invalid session id" -> r InvalidSessionId "javascript error" -> r JavascriptError "move target out of bounds" -> r MoveTargetOutOfBounds "no such alert" -> r NoSuchAlert "no such cookie" -> r NoSuchCookie "no such element" -> r NoSuchElement "no such frame" -> r NoSuchFrame "no such window" -> r NoSuchWindow "no such shadow root" -> r NoSuchShadowRoot "script timeout" -> r ScriptTimeoutError "session not created" -> r SessionNotCreated "stale element reference" -> r StaleElementReference "detached shadow root" -> r DetachedShadowRoot "timeout" -> r Timeout "unable to set cookie" -> r UnableToSetCookie "unable to capture screen" -> r UnableToCaptureScreen "unexpected alert open" -> r UnexpectedAlertOpen "unknown command" -> r UnknownCommand "unknown error" -> r UnknownError "unknown method" -> r UnknownMethod "unsupported operation" -> r UnsupportedOperation er -> Left er where r = Right errorTypeToErrorCode :: WebDriverErrorType -> Text errorTypeToErrorCode = \case ElementClickIntercepted -> "element click intercepted" ElementNotInteractable -> "element not interactable" InsecureCertificate -> "insecure certificate" InvalidArgument -> "invalid argument" InvalidCookieDomain -> "invalid cookie domain" InvalidElementState -> "invalid element state" InvalidSelector -> "invalid selector" InvalidSessionId -> "invalid session id" JavascriptError -> "javascript error" MoveTargetOutOfBounds -> "move target out of bounds" NoSuchAlert -> "no such alert" NoSuchCookie -> "no such cookie" NoSuchElement -> "no such element" NoSuchFrame -> "no such frame" NoSuchWindow -> "no such window" NoSuchShadowRoot -> "no such shadow root" ScriptTimeoutError -> "script timeout" SessionNotCreated -> "session not created" StaleElementReference -> "stale element reference" DetachedShadowRoot -> "detached shadow root" Timeout -> "timeout" UnableToSetCookie -> "unable to set cookie" UnableToCaptureScreen -> "unable to capture screen" UnexpectedAlertOpen -> "unexpected alert open" UnknownCommand -> "unknown command" UnknownError -> "unknown error" UnknownMethod -> "unknown method" UnsupportedOperation -> "unsupported operation" errorDescription :: WebDriverErrorType -> Text errorDescription = \case ElementClickIntercepted -> "The Element Click command could not be completed because the element receiving the events is obscuring the element that was requested clicked" ElementNotInteractable -> "A command could not be completed because the element is not pointer- or keyboard interactable" InsecureCertificate -> "Navigation caused the user agent to hit a certificate warning, which is usually the result of an expired or invalid TLS certificate" InvalidArgument -> "The arguments passed to a command are either invalid or malformed" InvalidCookieDomain -> "An illegal attempt was made to set a cookie under a different domain than the current page" InvalidElementState -> "A command could not be completed because the element is in an invalid state, e.g. attempting to clear an element that isn't both editable and resettable" InvalidSelector -> "Argument was an invalid selector" InvalidSessionId -> "Occurs if the given session id is not in the list of active sessions, meaning the session either does not exist or that it's not active" JavascriptError -> "An error occurred while executing JavaScript supplied by the user" MoveTargetOutOfBounds -> "The target for mouse interaction is not in the browser's viewport and cannot be brought into that viewport" NoSuchAlert -> "An attempt was made to operate on a modal dialog when one was not open" NoSuchCookie -> "No cookie matching the given path name was found amongst the associated cookies of session's current browsing context's active document" NoSuchElement -> "An element could not be located on the page using the given search parameters" NoSuchFrame -> "A command to switch to a frame could not be satisfied because the frame could not be found" NoSuchWindow -> "A command to switch to a window could not be satisfied because the window could not be found" NoSuchShadowRoot -> "The element does not have a shadow root" ScriptTimeoutError -> "A script did not complete before its timeout expired" SessionNotCreated -> "A new session could not be created" StaleElementReference -> "A command failed because the referenced element is no longer attached to the DOM" DetachedShadowRoot -> "A command failed because the referenced shadow root is no longer attached to the DOM" Timeout -> "An operation did not complete before its timeout expired" UnableToSetCookie -> "A command to set a cookie's value could not be satisfied" UnableToCaptureScreen -> "A screen capture was made impossible" UnexpectedAlertOpen -> "A modal dialog was open, blocking this operation" UnknownCommand -> "A command could not be executed because the remote end is not aware of it" UnknownError -> "An unknown error occurred in the remote end while processing the command" UnknownMethod -> "The requested command matched a known URL but did not match any method for that URL" UnsupportedOperation -> "Indicates that a command that should have executed properly cannot be supported for some reason" data ErrorClassification = NotAnError {httpResponse :: HttpResponse} | UnrecognisedError {httpResponse :: HttpResponse} | WebDriverError { error :: WebDriverErrorType, description :: Text, httpResponse :: HttpResponse -- todo find stacktrace -- stacktrace :: Maybe Text } deriving (Eq, Show, Ord) parseWebDriverError :: HttpResponse -> ErrorClassification parseWebDriverError resp = case getError resp.body of Nothing -> NotAnError resp Just err -> case errorCodeToErrorType err of Right et -> WebDriverError et (errorDescription et) resp Left _ -> UnrecognisedError resp parseWebDriverErrorType :: HttpResponse -> Maybe WebDriverErrorType parseWebDriverErrorType resp = case parseWebDriverError resp of WebDriverError {error} -> Just error NotAnError {} -> Nothing UnrecognisedError {} -> Nothing