{-# LANGUAGE OverloadedStrings, BangPatterns #-}
module Web.Api.WebDriver.Endpoints (
runIsolated
, newSession
, newSession'
, deleteSession
, sessionStatus
, getTimeouts
, setTimeouts
, navigateTo
, navigateToStealth
, getCurrentUrl
, goBack
, goForward
, pageRefresh
, getTitle
, getWindowHandle
, closeWindow
, switchToWindow
, getWindowHandles
, switchToFrame
, switchToParentFrame
, getWindowRect
, setWindowRect
, maximizeWindow
, minimizeWindow
, fullscreenWindow
, findElement
, findElements
, findElementFromElement
, findElementsFromElement
, getActiveElement
, isElementSelected
, getElementAttribute
, getElementProperty
, getElementCssValue
, getElementText
, getElementTagName
, getElementRect
, isElementEnabled
, elementClick
, elementClear
, elementSendKeys
, getPageSource
, getPageSourceStealth
, executeScript
, executeAsyncScript
, getAllCookies
, getNamedCookie
, addCookie
, deleteCookie
, deleteAllCookies
, performActions
, performActionsStealth
, releaseActions
, dismissAlert
, acceptAlert
, getAlertText
, sendAlertText
, takeScreenshot
, takeElementScreenshot
, _WEB_ELEMENT_ID
, _WEB_WINDOW_ID
, _WEB_FRAME_ID
) where
import Control.Monad.Trans.Class
( MonadTrans(..) )
import Data.Aeson
( Value(..), encode, object, (.=), toJSON )
import Data.Text
( Text, unpack, pack )
import Data.Text.Encoding
( encodeUtf8 )
import qualified Data.ByteString as SB
import qualified Data.ByteString.Base64 as B64
import qualified Network.URI.Encode as E
import Web.Api.WebDriver.Types
import Web.Api.WebDriver.Classes
import Web.Api.WebDriver.Monad
_WEB_ELEMENT_ID :: Text
_WEB_ELEMENT_ID = "element-6066-11e4-a52e-4f735466cecf"
_WEB_WINDOW_ID :: Text
_WEB_WINDOW_ID = "window-fcc6-11e5-b4f8-330a88ab9d7f"
_WEB_FRAME_ID :: Text
_WEB_FRAME_ID = "frame-075b-4da1-b6ba-e579c2d3230a"
theRemoteUrl
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff String
theRemoteUrl = do
host <- fromEnv (_remoteHostname . _env)
port <- fromEnv (_remotePort . _env)
path <- fromEnv (_remotePath . _env)
return $ concat [ "http://", host, ":", show port, path]
theRemoteUrlWithSession :: (Monad eff, Monad (t eff), MonadTrans t) => WebDriverTT t eff String
theRemoteUrlWithSession = do
st <- fromState (_sessionId . _userState)
case st of
Nothing -> throwError NoSession
Just session_id -> do
baseUrl <- theRemoteUrl
return $ concat [ baseUrl, "/session/", session_id ]
setSessionId
:: Maybe String
-> S WDState
-> S WDState
setSessionId x st = st { _userState = (_userState st) { _sessionId = x } }
cleanupOnError
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff a
-> WebDriverTT t eff a
cleanupOnError x = catchAnyError x
(\e -> deleteSession >> throwError e)
(\e -> deleteSession >> throwHttpException e)
(\e -> deleteSession >> throwIOException e)
(\e -> deleteSession >> throwJsonError e)
runIsolated
:: (Monad eff, Monad (t eff), MonadTrans t)
=> Capabilities
-> WebDriverTT t eff a
-> WebDriverTT t eff ()
runIsolated caps theSession = cleanupOnError $ do
session_id <- newSession caps
modifyState $ setSessionId (Just session_id)
theSession
deleteSession
modifyState $ setSessionId Nothing
newSession
:: (Monad eff, Monad (t eff), MonadTrans t)
=> Capabilities
-> WebDriverTT t eff SessionId
newSession = newSession' id
newSession'
:: (Monad eff, Monad (t eff), MonadTrans t)
=> (Value -> Value)
-> Capabilities
-> WebDriverTT t eff SessionId
newSession' f caps = do
baseUrl <- theRemoteUrl
format <- fromEnv (_responseFormat . _env)
let
!payload = encode $ f $ object
[ "capabilities" .= object
[ "alwaysMatch" .= toJSON caps ]
, "desiredCapabilities" .= toJSON caps
]
httpPost (baseUrl ++ "/session") payload
>>= (return . _responseBody)
>>= parseJson
>>= case format of
SpecFormat -> lookupKeyJson "value"
ChromeFormat -> return
>>= lookupKeyJson "sessionId"
>>= constructFromJson
>>= (return . unpack)
deleteSession
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff ()
deleteSession = do
(baseUrl, format) <- theRequestContext
httpDelete baseUrl
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
sessionStatus
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff (Bool, String)
sessionStatus = do
baseUrl <- theRemoteUrl
format <- fromEnv (_responseFormat . _env)
r <- httpGet (baseUrl ++ "/status")
>>= (return . _responseBody)
>>= parseJson
ready <- case format of
SpecFormat ->
lookupKeyJson "value" r
>>= lookupKeyJson "ready"
>>= constructFromJson
ChromeFormat -> return True
msg <- case format of
SpecFormat ->
lookupKeyJson "value" r
>>= lookupKeyJson "message"
>>= constructFromJson
>>= (return . unpack)
ChromeFormat -> return "chromedriver is not spec compliant :)"
return (ready, msg)
getTimeouts
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff TimeoutConfig
getTimeouts = do
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/timeouts")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
setTimeouts
:: (Monad eff, Monad (t eff), MonadTrans t)
=> TimeoutConfig
-> WebDriverTT t eff ()
setTimeouts timeouts = do
baseUrl <- theRemoteUrlWithSession
let !payload = encode timeouts
httpPost (baseUrl ++ "/timeouts") payload
return ()
navigateTo
:: (Monad eff, Monad (t eff), MonadTrans t)
=> Url
-> WebDriverTT t eff ()
navigateTo url = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object [ "url" .= url ]
httpPost (baseUrl ++ "/url") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
navigateToStealth
:: (Monad eff, Monad (t eff), MonadTrans t)
=> Url
-> WebDriverTT t eff ()
navigateToStealth url = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object [ "url" .= url ]
httpSilentPost (baseUrl ++ "/url") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
getCurrentUrl
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff Url
getCurrentUrl = do
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/url")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
>>= (return . unpack)
goBack
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff ()
goBack = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object []
httpPost (baseUrl ++ "/back") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
goForward
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff ()
goForward = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object []
httpPost (baseUrl ++ "/forward") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
pageRefresh
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff ()
pageRefresh = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object []
httpPost (baseUrl ++ "/refresh") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
getTitle
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff String
getTitle = do
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/title")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
>>= (return . unpack)
getWindowHandle
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff ContextId
getWindowHandle = do
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/window")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
>>= (return . ContextId . unpack)
closeWindow
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff [ContextId]
closeWindow = do
baseUrl <- theRemoteUrlWithSession
httpDelete (baseUrl ++ "/window")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
>>= (sequence . map constructFromJson)
>>= (return . map (ContextId . unpack))
switchToWindow
:: (Monad eff, Monad (t eff), MonadTrans t, HasContextId a)
=> a
-> WebDriverTT t eff ()
switchToWindow t = do
let contextId = contextIdOf t
baseUrl <- theRemoteUrlWithSession
let !payload = encode $ object [ "handle" .= show contextId ]
httpPost (baseUrl ++ "/window") payload
return ()
getWindowHandles
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff [ContextId]
getWindowHandles = do
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/window/handles")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
>>= (sequence . map constructFromJson)
>>= (return . map (ContextId . unpack))
switchToFrame
:: (Monad eff, Monad (t eff), MonadTrans t)
=> FrameReference
-> WebDriverTT t eff ()
switchToFrame ref = do
(baseUrl, format) <- theRequestContext
let
!frame = case ref of
TopLevelFrame -> Null
FrameNumber k -> Number $ fromIntegral k
FrameContainingElement element_id -> String $ pack $ show element_id
!payload = encode $ object
[ "id" .= toJSON frame ]
httpPost (baseUrl ++ "/frame") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
switchToParentFrame
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff ()
switchToParentFrame = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object []
httpPost (baseUrl ++ "/frame/parent") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
getWindowRect
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff Rect
getWindowRect = do
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/window/rect")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
setWindowRect
:: (Monad eff, Monad (t eff), MonadTrans t)
=> Rect
-> WebDriverTT t eff Rect
setWindowRect rect = do
baseUrl <- theRemoteUrlWithSession
let !payload = encode rect
httpPost (baseUrl ++ "/window/rect") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
maximizeWindow
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff Rect
maximizeWindow = do
baseUrl <- theRemoteUrlWithSession
let !payload = encode $ object []
httpPost (baseUrl ++ "/window/maximize") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
minimizeWindow
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff Rect
minimizeWindow = do
baseUrl <- theRemoteUrlWithSession
let !payload = encode $ object []
httpPost (baseUrl ++ "/window/minimize") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
fullscreenWindow
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff Rect
fullscreenWindow = do
baseUrl <- theRemoteUrlWithSession
let !payload = encode $ object []
httpPost (baseUrl ++ "/window/fullscreen") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
findElement
:: (Monad eff, Monad (t eff), MonadTrans t)
=> LocationStrategy
-> Selector
-> WebDriverTT t eff ElementRef
findElement strategy selector = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object [ "value" .= selector, "using" .= toJSON strategy ]
httpPost (baseUrl ++ "/element") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= case format of
SpecFormat -> lookupKeyJson _WEB_ELEMENT_ID
ChromeFormat -> lookupKeyJson "ELEMENT"
>>= constructFromJson
>>= (return . ElementRef . unpack)
findElements
:: (Monad eff, Monad (t eff), MonadTrans t)
=> LocationStrategy
-> Selector
-> WebDriverTT t eff [ElementRef]
findElements strategy selector = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object [ "value" .= selector, "using" .= toJSON strategy ]
httpPost (baseUrl ++ "/elements") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
>>= case format of
SpecFormat -> mapM (lookupKeyJson _WEB_ELEMENT_ID)
ChromeFormat -> mapM (lookupKeyJson "ELEMENT")
>>= mapM constructFromJson
>>= (return . map (ElementRef . unpack))
findElementFromElement
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> LocationStrategy
-> Selector
-> a
-> WebDriverTT t eff ElementRef
findElementFromElement strategy selector root = do
(baseUrl, format) <- theRequestContext
let root_id = elementRefOf root
let !payload = encode $ object [ "value" .= selector, "using" .= toJSON strategy ]
httpPost (baseUrl ++ "/element/" ++ show root_id ++ "/element") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= case format of
SpecFormat -> lookupKeyJson _WEB_ELEMENT_ID
ChromeFormat -> lookupKeyJson "ELEMENT"
>>= constructFromJson
>>= (return . ElementRef . unpack)
findElementsFromElement
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> LocationStrategy
-> Selector
-> a
-> WebDriverTT t eff [ElementRef]
findElementsFromElement strategy selector root = do
(baseUrl, format) <- theRequestContext
let root_id = elementRefOf root
let !payload = encode $ object [ "value" .= selector, "using" .= toJSON strategy ]
httpPost (baseUrl ++ "/element/" ++ show root_id ++ "/elements") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
>>= case format of
SpecFormat -> mapM (lookupKeyJson _WEB_ELEMENT_ID)
ChromeFormat -> mapM (lookupKeyJson "ELEMENT")
>>= mapM constructFromJson
>>= (return . map (ElementRef . unpack))
getActiveElement
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff ElementRef
getActiveElement = do
(baseUrl, format) <- theRequestContext
httpGet (baseUrl ++ "/element/active")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= case format of
SpecFormat -> lookupKeyJson _WEB_ELEMENT_ID
ChromeFormat -> lookupKeyJson "ELEMENT"
>>= constructFromJson
>>= (return . ElementRef . unpack)
isElementSelected
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> a
-> WebDriverTT t eff Bool
isElementSelected element = do
let elementRef = show $ elementRefOf element
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/element/" ++ elementRef ++ "/selected")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
getElementAttribute
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> AttributeName
-> a
-> WebDriverTT t eff (Either Bool String)
getElementAttribute name element = do
let elementRef = show $ elementRefOf element
baseUrl <- theRemoteUrlWithSession
x <- httpGet (baseUrl ++ "/element/" ++ elementRef ++ "/attribute/" ++ E.encode name)
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
case x of
Null -> return (Left False)
String "true" -> return (Left True)
String attr -> return (Right $ unpack attr)
_ -> throwJsonError $ JsonError "Invalid element attribute response"
getElementProperty
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> PropertyName
-> a
-> WebDriverTT t eff Value
getElementProperty name element = do
let elementRef = show $ elementRefOf element
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/element/" ++ elementRef ++ "/property/" ++ E.encode name)
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
getElementCssValue
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> CssPropertyName
-> a
-> WebDriverTT t eff String
getElementCssValue name element = do
let elementRef = show $ elementRefOf element
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/element/" ++ elementRef ++ "/css/" ++ name)
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
getElementText
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> a
-> WebDriverTT t eff String
getElementText element = do
let elementRef = show $ elementRefOf element
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/element/" ++ elementRef ++ "/text")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
getElementTagName
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> a
-> WebDriverTT t eff String
getElementTagName element = do
let elementRef = show $ elementRefOf element
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/element/" ++ elementRef ++ "/name")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
getElementRect
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> a
-> WebDriverTT t eff Rect
getElementRect element = do
let elementRef = show $ elementRefOf element
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/element/" ++ elementRef ++ "/rect")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
isElementEnabled
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> a
-> WebDriverTT t eff Bool
isElementEnabled element = do
let elementRef = show $ elementRefOf element
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/element/" ++ elementRef ++ "/enabled")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
elementClick
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> a
-> WebDriverTT t eff ()
elementClick element = do
(baseUrl, format) <- theRequestContext
let elementRef = show $ elementRefOf element
let !payload = encode $ object []
httpPost (baseUrl ++ "/element/" ++ elementRef ++ "/click") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
elementClear
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> a
-> WebDriverTT t eff ()
elementClear element = do
(baseUrl, format) <- theRequestContext
let elementRef = show $ elementRefOf element
let !payload = encode $ object []
httpPost (baseUrl ++ "/element/" ++ elementRef ++ "/clear") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
elementSendKeys
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> String
-> a
-> WebDriverTT t eff ()
elementSendKeys text element = do
let elementRef = show $ elementRefOf element
(baseUrl, format) <- theRequestContext
let !payload = encode $ object [ "text" .= text ]
httpPost (baseUrl ++ "/element/" ++ elementRef ++ "/value") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
getPageSource
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff String
getPageSource = do
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/source")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
>>= (return . unpack)
getPageSourceStealth
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff String
getPageSourceStealth = do
baseUrl <- theRemoteUrlWithSession
httpSilentGet (baseUrl ++ "/source")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
>>= (return . unpack)
executeScript
:: (Monad eff, Monad (t eff), MonadTrans t)
=> Script
-> [Value]
-> WebDriverTT t eff Value
executeScript script args = do
baseUrl <- theRemoteUrlWithSession
let !payload = encode $ object [ "script" .= script, "args" .= toJSON args ]
httpPost (baseUrl ++ "/execute/sync") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
executeAsyncScript
:: (Monad eff, Monad (t eff), MonadTrans t)
=> Script
-> [Value]
-> WebDriverTT t eff Value
executeAsyncScript script args = do
baseUrl <- theRemoteUrlWithSession
let !payload = encode $ object [ "script" .= script, "args" .= toJSON args ]
httpPost (baseUrl ++ "/execute/async") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
getAllCookies
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff [Cookie]
getAllCookies = do
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/cookie")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
>>= mapM constructFromJson
getNamedCookie
:: (Monad eff, Monad (t eff), MonadTrans t)
=> CookieName
-> WebDriverTT t eff Cookie
getNamedCookie name = do
baseUrl <- theRemoteUrlWithSession
httpGet (baseUrl ++ "/cookie/" ++ E.encode name)
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
addCookie
:: (Monad eff, Monad (t eff), MonadTrans t)
=> Cookie
-> WebDriverTT t eff ()
addCookie cookie = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object [ "cookie" .= cookie ]
httpSilentPost (baseUrl ++ "/cookie") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
deleteCookie
:: (Monad eff, Monad (t eff), MonadTrans t)
=> CookieName
-> WebDriverTT t eff ()
deleteCookie name = do
(baseUrl, format) <- theRequestContext
httpDelete (baseUrl ++ "/cookie/" ++ E.encode name)
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
deleteAllCookies
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff ()
deleteAllCookies = do
(baseUrl, format) <- theRequestContext
httpDelete (baseUrl ++ "/cookie")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
performActions
:: (Monad eff, Monad (t eff), MonadTrans t)
=> [Action]
-> WebDriverTT t eff ()
performActions = _performActions False
performActionsStealth
:: (Monad eff, Monad (t eff), MonadTrans t)
=> [Action]
-> WebDriverTT t eff ()
performActionsStealth = _performActions True
_performActions
:: (Monad eff, Monad (t eff), MonadTrans t)
=> Bool
-> [Action]
-> WebDriverTT t eff ()
_performActions stealth action = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object [ "actions" .= toJSON action ]
let httpMethod = if stealth then httpSilentPost else httpPost
httpMethod (baseUrl ++ "/actions") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
releaseActions
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff ()
releaseActions = do
baseUrl <- theRemoteUrlWithSession
httpDelete (baseUrl ++ "/actions")
return ()
dismissAlert
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff ()
dismissAlert = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object []
httpPost (baseUrl ++ "/alert/dismiss") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
acceptAlert
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff ()
acceptAlert = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object []
httpPost (baseUrl ++ "/alert/accept") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
getAlertText
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff (Maybe String)
getAlertText = do
baseUrl <- theRemoteUrlWithSession
msg <- httpGet (baseUrl ++ "/alert/text")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
case msg of
Null -> return Nothing
String text -> return $ Just (unpack text)
_ -> throwJsonError $ JsonError "Invalid alert text response"
sendAlertText
:: (Monad eff, Monad (t eff), MonadTrans t)
=> String
-> WebDriverTT t eff ()
sendAlertText msg = do
(baseUrl, format) <- theRequestContext
let !payload = encode $ object [ "text" .= msg ]
httpPost (baseUrl ++ "/alert/text") payload
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= expectEmptyObject format
return ()
takeScreenshot
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff SB.ByteString
takeScreenshot = do
baseUrl <- theRemoteUrlWithSession
result <- httpGet (baseUrl ++ "/screenshot")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
>>= (return . B64.decode . encodeUtf8)
case result of
Right img -> return img
Left str -> throwError $ ImageDecodeError str
takeElementScreenshot
:: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a)
=> a
-> WebDriverTT t eff SB.ByteString
takeElementScreenshot element = do
let elementRef = show $ elementRefOf element
baseUrl <- theRemoteUrlWithSession
result <- httpGet (baseUrl ++ "/element/" ++ elementRef ++ "/screenshot")
>>= (return . _responseBody)
>>= parseJson
>>= lookupKeyJson "value"
>>= constructFromJson
>>= (return . B64.decode . encodeUtf8)
case result of
Right img -> return img
Left str -> throwError $ ImageDecodeError str
expectEmptyObject
:: (Monad eff, Monad (t eff), MonadTrans t)
=> ResponseFormat
-> Value
-> WebDriverTT t eff Value
expectEmptyObject format value = case format of
SpecFormat -> expectIs (\x -> elem x [Null, object []]) "empty object or null" value
ChromeFormat -> expect Null value
theRequestContext
:: (Monad eff, Monad (t eff), MonadTrans t)
=> WebDriverTT t eff (String, ResponseFormat)
theRequestContext = do
baseUrl <- theRemoteUrlWithSession
format <- fromEnv (_responseFormat . _env)
return (baseUrl, format)