{-# LANGUAGE OverloadedStrings, RecordWildCards, BangPatterns #-}
module Web.Api.WebDriver.Types (
SessionId
, ElementRef(..)
, ContextId(..)
, Selector
, AttributeName
, PropertyName
, Script
, CookieName
, CssPropertyName
, FrameReference(..)
, Capabilities(..)
, BrowserName(..)
, PlatformName(..)
, emptyCapabilities
, defaultFirefoxCapabilities
, headlessFirefoxCapabilities
, defaultChromeCapabilities
, LogLevel(..)
, FirefoxOptions(..)
, FirefoxLog(..)
, defaultFirefoxOptions
, ChromeOptions(..)
, defaultChromeOptions
, ProxyConfig(..)
, emptyProxyConfig
, ProxyType(..)
, HostAndOptionalPort(..)
, TimeoutConfig(..)
, emptyTimeoutConfig
, InputSource(..)
, PointerSubtype(..)
, InputSourceParameter(..)
, Action(..)
, emptyAction
, ActionType(..)
, ActionItem(..)
, emptyActionItem
, LocationStrategy(..)
, Rect(..)
, emptyRect
, PromptHandler(..)
, Cookie(..)
, emptyCookie
, ResponseErrorCode(..)
) where
import Data.Char
( toLower )
import Data.Maybe
( catMaybes )
import Data.Scientific
( Scientific, scientific )
import Data.String
( IsString(..) )
import Data.HashMap.Strict
( HashMap, toList, fromList )
import Data.Aeson.Types
( ToJSON(..), FromJSON(..), Value(..), KeyValue
, Pair, (.:?), (.:), (.=), object, typeMismatch )
import Data.Text
( Text, pack, unpack )
import Test.QuickCheck
( Arbitrary(..), arbitraryBoundedEnum, Gen )
import Test.QuickCheck.Gen
( listOf, oneof )
import Web.Api.WebDriver.Uri
import Web.Api.WebDriver.Types.Keyboard
unrecognizedValue :: (Monad m) => String -> Text -> m a
unrecognizedValue !name !string = fail $
"Unrecognized value for type " ++ name ++ ": " ++ unpack string
malformedValue :: (Monad m) => String -> String -> m a
malformedValue !name !value = fail $
"Malformed value for type" ++ name ++ ": " ++ value
object_ :: [Maybe Pair] -> Value
object_ = object . filter (\(_, v) -> v /= Null) . catMaybes
(.==) :: (ToJSON v, KeyValue kv) => Text -> v -> Maybe kv
(.==) key value = Just (key .= value)
(.=?) :: (ToJSON v, KeyValue kv) => Text -> Maybe v -> Maybe kv
(.=?) key = fmap (key .=)
type SessionId = String
newtype ElementRef = ElementRef
{ theElementRef :: String
} deriving Eq
instance Show ElementRef where
show (ElementRef str) = str
instance IsString ElementRef where
fromString = ElementRef
newtype ContextId = ContextId
{ theContextId :: String
} deriving Eq
instance Show ContextId where
show (ContextId str) = str
instance IsString ContextId where
fromString = ContextId
type Selector = String
type AttributeName = String
type PropertyName = String
type Script = String
type CookieName = String
type CssPropertyName = String
data FrameReference
= TopLevelFrame
| FrameNumber Int
| FrameContainingElement ElementRef
deriving (Eq, Show)
data ResponseErrorCode
= ElementClickIntercepted
| ElementNotSelectable
| ElementNotInteractable
| InsecureCertificate
| InvalidArgument
| InvalidCookieDomain
| InvalidCoordinates
| InvalidElementState
| InvalidSelector
| InvalidSessionId
| JavaScriptError
| MoveTargetOutOfBounds
| NoSuchAlert
| NoSuchCookie
| NoSuchElement
| NoSuchFrame
| NoSuchWindow
| ScriptTimeout
| SessionNotCreated
| StaleElementReference
| Timeout
| UnableToSetCookie
| UnableToCaptureScreen
| UnexpectedAlertOpen
| UnknownCommand
| UnknownError
| UnknownMethod
| UnsupportedOperation
| UnhandledErrorCode Text
deriving (Eq, Show)
instance FromJSON ResponseErrorCode where
parseJSON (String x) = case x of
"element click intercepted" -> return ElementClickIntercepted
"element not selectable" -> return ElementNotSelectable
"element not interactable" -> return ElementNotInteractable
"insecure certificate" -> return InsecureCertificate
"invalid argument" -> return InvalidArgument
"invalid cookie domain" -> return InvalidCookieDomain
"invalid coordinates" -> return InvalidCoordinates
"invalid element state" -> return InvalidElementState
"invalid selector" -> return InvalidSelector
"invalid session id" -> return InvalidSessionId
"javascript error" -> return JavaScriptError
"move target out of bounds" -> return MoveTargetOutOfBounds
"no such alert" -> return NoSuchAlert
"no such cookie" -> return NoSuchCookie
"no such element" -> return NoSuchElement
"no such frame" -> return NoSuchFrame
"no such window" -> return NoSuchWindow
"script timeout" -> return ScriptTimeout
"session not created" -> return SessionNotCreated
"stale element reference" -> return StaleElementReference
"timeout" -> return Timeout
"unable to set cookie" -> return UnableToSetCookie
"unable to capture screen" -> return UnableToCaptureScreen
"unexpected alert open" -> return UnexpectedAlertOpen
"unknown command" -> return UnknownCommand
"unknown error" -> return UnknownError
"unknown method" -> return UnknownMethod
"unsupported operation" -> return UnsupportedOperation
text -> return $ UnhandledErrorCode text
parseJSON invalid = typeMismatch "ResponseErrorCode" invalid
instance ToJSON ResponseErrorCode where
toJSON x = case x of
ElementClickIntercepted -> String "element click intercepted"
ElementNotSelectable -> String "element not selectable"
ElementNotInteractable -> String "element not interactable"
InsecureCertificate -> String "insecure certificate"
InvalidArgument -> String "invalid argument"
InvalidCookieDomain -> String "invalid cookie domain"
InvalidCoordinates -> String "invalid coordinates"
InvalidElementState -> String "invalid element state"
InvalidSelector -> String "invalid selector"
InvalidSessionId -> String "invalid session id"
JavaScriptError -> String "javascript error"
MoveTargetOutOfBounds -> String "move target out of bounds"
NoSuchAlert -> String "no such alert"
NoSuchCookie -> String "no such cookie"
NoSuchElement -> String "no such element"
NoSuchFrame -> String "no such frame"
NoSuchWindow -> String "no such window"
ScriptTimeout -> String "script timeout"
SessionNotCreated -> String "session not created"
StaleElementReference -> String "stale element reference"
Timeout -> String "timeout"
UnableToSetCookie -> String "unable to set cookie"
UnableToCaptureScreen -> String "unable to capture screen"
UnexpectedAlertOpen -> String "unexpected alert open"
UnknownCommand -> String "unknown command"
UnknownError -> String "unknown error"
UnknownMethod -> String "unknown method"
UnsupportedOperation -> String "unsupported operation"
UnhandledErrorCode msg -> String msg
instance Arbitrary ResponseErrorCode where
arbitrary = oneof $ map return
[ ElementClickIntercepted
, ElementNotSelectable
, ElementNotInteractable
, InsecureCertificate
, InvalidArgument
, InvalidCookieDomain
, InvalidCoordinates
, InvalidElementState
, InvalidSelector
, InvalidSessionId
, JavaScriptError
, MoveTargetOutOfBounds
, NoSuchAlert
, NoSuchCookie
, NoSuchElement
, NoSuchFrame
, NoSuchWindow
, ScriptTimeout
, SessionNotCreated
, StaleElementReference
, Timeout
, UnableToSetCookie
, UnableToCaptureScreen
, UnexpectedAlertOpen
, UnknownCommand
, UnknownError
, UnknownMethod
, UnsupportedOperation
]
data Capabilities = Capabilities
{ _browserName :: Maybe BrowserName
, _browserVersion :: Maybe String
, _platformName :: Maybe PlatformName
, _acceptInsecureCerts :: Maybe Bool
, _pageLoadStrategy :: Maybe String
, _proxy :: Maybe ProxyConfig
, _setWindowRect :: Maybe Bool
, _timeouts :: Maybe TimeoutConfig
, _unhandledPromptBehavior :: Maybe PromptHandler
, _chromeOptions :: Maybe ChromeOptions
, _firefoxOptions :: Maybe FirefoxOptions
} deriving (Eq, Show)
instance FromJSON Capabilities where
parseJSON (Object v) = Capabilities
<$> v .:? "browserName"
<*> v .:? "browserVersion"
<*> v .:? "platformName"
<*> v .:? "acceptInsecureCerts"
<*> v .:? "pageLoadStrategy"
<*> v .:? "proxy"
<*> v .:? "setWindowRect"
<*> v .:? "timeouts"
<*> v .:? "unhandledPromptBehavior"
<*> v .:? "chromeOptions"
<*> v .:? "moz:firefoxOptions"
parseJSON invalid = typeMismatch "Capabilities" invalid
instance ToJSON Capabilities where
toJSON Capabilities{..} = object_
[ "browserName" .=? (toJSON <$> _browserName)
, "browserVersion" .=? (toJSON <$> _browserVersion)
, "platformName" .=? (toJSON <$> _platformName)
, "acceptInsecureCerts" .=? (toJSON <$> _acceptInsecureCerts)
, "pageLoadStrategy" .=? (toJSON <$> _pageLoadStrategy)
, "proxy" .=? (toJSON <$> _proxy)
, "setWindowRect" .=? (toJSON <$> _setWindowRect)
, "timeouts" .=? (toJSON <$> _timeouts)
, "unhandledPromptBehavior" .=? (toJSON <$> _unhandledPromptBehavior)
, "chromeOptions" .=? (toJSON <$> _chromeOptions)
, "moz:firefoxOptions" .=? (toJSON <$> _firefoxOptions)
]
instance Arbitrary Capabilities where
arbitrary = Capabilities
<$> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
emptyCapabilities :: Capabilities
emptyCapabilities = Capabilities
{ _browserName = Nothing
, _browserVersion = Nothing
, _platformName = Nothing
, _acceptInsecureCerts = Nothing
, _pageLoadStrategy = Nothing
, _proxy = Nothing
, _setWindowRect = Nothing
, _timeouts = Nothing
, _unhandledPromptBehavior = Nothing
, _chromeOptions = Nothing
, _firefoxOptions = Nothing
}
defaultFirefoxCapabilities :: Capabilities
defaultFirefoxCapabilities = emptyCapabilities
{ _browserName = Just Firefox
}
headlessFirefoxCapabilities :: Capabilities
headlessFirefoxCapabilities = defaultFirefoxCapabilities
{ _firefoxOptions = Just $ defaultFirefoxOptions
{ _firefoxArgs = Just ["-headless"]
}
}
defaultChromeCapabilities :: Capabilities
defaultChromeCapabilities = emptyCapabilities
{ _browserName = Just Chrome
}
data BrowserName
= Firefox
| Chrome
| Safari
deriving (Eq, Show, Enum, Bounded)
instance FromJSON BrowserName where
parseJSON (String x) = case x of
"firefox" -> return Firefox
"chrome" -> return Chrome
"safari" -> return Safari
_ -> unrecognizedValue "BrowserName" x
parseJSON invalid = typeMismatch "BrowserName" invalid
instance ToJSON BrowserName where
toJSON Firefox = String "firefox"
toJSON Chrome = String "chrome"
toJSON Safari = String "safari"
instance Arbitrary BrowserName where
arbitrary = arbitraryBoundedEnum
data PlatformName
= Mac
deriving (Eq, Show, Enum, Bounded)
instance FromJSON PlatformName where
parseJSON (String x) = case unpack x of
"mac" -> return Mac
_ -> unrecognizedValue "PlaformName" x
parseJSON invalid = typeMismatch "PlatformName" invalid
instance ToJSON PlatformName where
toJSON Mac = String "mac"
instance Arbitrary PlatformName where
arbitrary = arbitraryBoundedEnum
data ChromeOptions = ChromeOptions
{ _chromeBinary :: Maybe FilePath
, _chromeArgs :: Maybe [String]
, _chromePrefs :: Maybe (HashMap Text Value)
} deriving (Eq, Show)
instance FromJSON ChromeOptions where
parseJSON (Object v) = ChromeOptions
<$> v .:? "binary"
<*> v .:? "args"
<*> v .:? "prefs"
parseJSON invalid = typeMismatch "ChromeOptions" invalid
instance ToJSON ChromeOptions where
toJSON ChromeOptions{..} = object_
[ "binary" .=? (toJSON <$> _chromeBinary)
, "args" .=? (toJSON <$> _chromeArgs)
, "prefs" .=? (toJSON <$> _chromePrefs)
]
instance Arbitrary ChromeOptions where
arbitrary = ChromeOptions
<$> arbitrary
<*> arbitrary
<*> arbHashMap
defaultChromeOptions :: ChromeOptions
defaultChromeOptions = ChromeOptions
{ _chromeBinary = Nothing
, _chromeArgs = Nothing
, _chromePrefs = Nothing
}
data FirefoxOptions = FirefoxOptions
{ _firefoxBinary :: Maybe FilePath
, _firefoxArgs :: Maybe [String]
, _firefoxLog :: Maybe FirefoxLog
, _firefoxPrefs :: Maybe (HashMap Text Value)
} deriving (Eq, Show)
instance FromJSON FirefoxOptions where
parseJSON (Object v) = FirefoxOptions
<$> v .:? "binary"
<*> v .:? "args"
<*> v .:? "log"
<*> v .:? "prefs"
parseJSON invalid = typeMismatch "FirefoxOptions" invalid
instance ToJSON FirefoxOptions where
toJSON FirefoxOptions{..} = object_
[ "binary" .=? (toJSON <$> _firefoxBinary)
, "args" .=? (toJSON <$> _firefoxArgs)
, "log" .=? (toJSON <$> _firefoxLog)
, "prefs" .=? (toJSON <$> _firefoxPrefs)
]
instance Arbitrary FirefoxOptions where
arbitrary = FirefoxOptions
<$> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbHashMap
arbHashMap :: Gen (Maybe (HashMap Text Value))
arbHashMap = do
p <- arbitrary
if p
then return Nothing
else do
m <- fromList <$> listOf (mPair arbKey arbPrefVal)
return $ Just m
arbKey :: Gen Text
arbKey = pack <$> ('k':) <$> arbitrary
arbText :: Gen Text
arbText = pack <$> arbitrary
arbPrefVal :: Gen Value
arbPrefVal = do
k <- arbitrary :: Gen Int
case k`mod`3 of
0 -> Bool <$> arbitrary
1 -> String <$> arbText
_ -> Number <$> arbScientific
mPair :: (Monad m) => m a -> m b -> m (a,b)
mPair ga gb = do
a <- ga
b <- gb
return (a,b)
defaultFirefoxOptions :: FirefoxOptions
defaultFirefoxOptions = FirefoxOptions
{ _firefoxBinary = Nothing
, _firefoxArgs = Nothing
, _firefoxLog = Nothing
, _firefoxPrefs = Nothing
}
newtype FirefoxLog = FirefoxLog
{ _firefoxLogLevel :: Maybe LogLevel
} deriving (Eq, Show)
instance FromJSON FirefoxLog where
parseJSON (Object v) = FirefoxLog
<$> v .:? "level"
parseJSON invalid = typeMismatch "FirefoxLog" invalid
instance ToJSON FirefoxLog where
toJSON FirefoxLog{..} = object_
[ "level" .=? (toJSON <$> _firefoxLogLevel)
]
instance Arbitrary FirefoxLog where
arbitrary = FirefoxLog
<$> arbitrary
data LogLevel
= LogTrace
| LogDebug
| LogConfig
| LogInfo
| LogWarn
| LogError
| LogFatal
deriving (Eq, Show, Enum, Bounded)
instance FromJSON LogLevel where
parseJSON (String x) = case x of
"trace" -> return LogTrace
"debug" -> return LogDebug
"config" -> return LogConfig
"info" -> return LogInfo
"warn" -> return LogWarn
"error" -> return LogError
"fatal" -> return LogFatal
_ -> unrecognizedValue "LogLevel" x
parseJSON invalid = typeMismatch "LogLevel" invalid
instance ToJSON LogLevel where
toJSON x = case x of
LogTrace -> String "trace"
LogDebug -> String "debug"
LogConfig -> String "config"
LogInfo -> String "info"
LogWarn -> String "warn"
LogError -> String "error"
LogFatal -> String "fatal"
instance Arbitrary LogLevel where
arbitrary = arbitraryBoundedEnum
data ProxyConfig = ProxyConfig
{ _proxyType :: Maybe ProxyType
, _proxyAutoconfigUrl :: Maybe String
, _ftpProxy :: Maybe HostAndOptionalPort
, _httpProxy :: Maybe HostAndOptionalPort
, _noProxy :: Maybe [String]
, _sslProxy :: Maybe HostAndOptionalPort
, _socksProxy :: Maybe HostAndOptionalPort
, _socksVersion :: Maybe Int
} deriving (Eq, Show)
instance FromJSON ProxyConfig where
parseJSON (Object v) = ProxyConfig
<$> v .:? "proxyType"
<*> v .:? "proxyAutoconfigUrl"
<*> v .:? "ftpProxy"
<*> v .:? "httpProxy"
<*> v .:? "noProxy"
<*> v .:? "sslProxy"
<*> v .:? "socksProxy"
<*> v .:? "socksVersion"
parseJSON invalid = typeMismatch "ProxyConfig" invalid
instance ToJSON ProxyConfig where
toJSON ProxyConfig{..} = object_
[ "proxyType" .=? (toJSON <$> _proxyType)
, "proxyAutoconfigUrl" .=? (toJSON <$> _proxyAutoconfigUrl)
, "ftpProxy" .=? (toJSON <$> _ftpProxy)
, "httpProxy" .=? (toJSON <$> _httpProxy)
, "noProxy" .=? (toJSON <$> _noProxy)
, "sslProxy" .=? (toJSON <$> _sslProxy)
, "socksProxy" .=? (toJSON <$> _socksProxy)
, "socksVersion" .=? (toJSON <$> _socksVersion)
]
instance Arbitrary ProxyConfig where
arbitrary = ProxyConfig
<$> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
emptyProxyConfig :: ProxyConfig
emptyProxyConfig = ProxyConfig
{ _proxyType = Nothing
, _proxyAutoconfigUrl = Nothing
, _ftpProxy = Nothing
, _httpProxy = Nothing
, _noProxy = Nothing
, _sslProxy = Nothing
, _socksProxy = Nothing
, _socksVersion = Nothing
}
data HostAndOptionalPort = HostAndOptionalPort
{ _urlHost :: Host
, _urlPort :: Maybe Port
} deriving (Eq, Show)
instance FromJSON HostAndOptionalPort where
parseJSON (String x) =
let string = unpack x in
case span (/= ':') string of
("",_) -> malformedValue "Host" string
(str,[]) -> case mkHost str of
Nothing -> malformedValue "Host" string
Just h -> return HostAndOptionalPort
{ _urlHost = h
, _urlPort = Nothing
}
(str,":") -> malformedValue "Port" string
(str,':':rest) -> case mkHost str of
Nothing -> malformedValue "Host" string
Just h -> case mkPort rest of
Nothing -> malformedValue "Port" rest
Just p -> return HostAndOptionalPort
{ _urlHost = h
, _urlPort = Just p
}
(str,rest) -> malformedValue "Host" string
parseJSON invalid = typeMismatch "HostAndOptionalPort" invalid
instance ToJSON HostAndOptionalPort where
toJSON HostAndOptionalPort{..} = case _urlPort of
Nothing -> String $ pack $ show _urlHost
Just pt -> String $ pack $ concat [show _urlHost, ":", show pt]
instance Arbitrary HostAndOptionalPort where
arbitrary = HostAndOptionalPort
<$> arbitrary
<*> arbitrary
data ProxyType
= ProxyPac
| ProxyDirect
| ProxyAutodetect
| ProxySystem
| ProxyManual
deriving (Eq, Show, Enum, Bounded)
instance FromJSON ProxyType where
parseJSON (String x) = case x of
"pac" -> return ProxyPac
"direct" -> return ProxyDirect
"autodetect" -> return ProxyAutodetect
"system" -> return ProxySystem
"manual" -> return ProxyManual
_ -> unrecognizedValue "ProxyType" x
parseJSON invalid = typeMismatch "ProxyType" invalid
instance ToJSON ProxyType where
toJSON x = case x of
ProxyPac -> String "pac"
ProxyDirect -> String "direct"
ProxyAutodetect -> String "autodetect"
ProxySystem -> String "system"
ProxyManual -> String "manual"
instance Arbitrary ProxyType where
arbitrary = arbitraryBoundedEnum
data TimeoutConfig = TimeoutConfig
{ _script :: Maybe Int
, _pageLoad :: Maybe Int
, _implicit :: Maybe Int
} deriving (Eq, Show)
instance FromJSON TimeoutConfig where
parseJSON (Object v) = TimeoutConfig
<$> v .:? "script"
<*> v .:? "pageLoad"
<*> v .:? "implicit"
parseJSON invalid = typeMismatch "TimeoutConfig" invalid
instance ToJSON TimeoutConfig where
toJSON TimeoutConfig{..} = object_
[ "script" .== (toJSON <$> _script)
, "pageLoad" .== (toJSON <$> _pageLoad)
, "implicit" .== (toJSON <$> _implicit)
]
instance Arbitrary TimeoutConfig where
arbitrary = TimeoutConfig
<$> arbitrary
<*> arbitrary
<*> arbitrary
emptyTimeoutConfig :: TimeoutConfig
emptyTimeoutConfig = TimeoutConfig
{ _script = Nothing
, _pageLoad = Nothing
, _implicit = Nothing
}
data LocationStrategy
= CssSelector
| LinkTextSelector
| PartialLinkTextSelector
| TagName
| XPathSelector
deriving (Eq, Show, Enum, Bounded)
instance FromJSON LocationStrategy where
parseJSON (String x) = case x of
"css selector" -> return CssSelector
"link text" -> return LinkTextSelector
"partial link text" -> return PartialLinkTextSelector
"tag name" -> return TagName
"xpath" -> return XPathSelector
_ -> unrecognizedValue "LocationStrategy" x
parseJSON invalid = typeMismatch "LocationStrategy" invalid
instance ToJSON LocationStrategy where
toJSON x = case x of
CssSelector -> String "css selector"
LinkTextSelector -> String "link text"
PartialLinkTextSelector -> String "partial link text"
TagName -> String "tag name"
XPathSelector -> String "xpath"
instance Arbitrary LocationStrategy where
arbitrary = arbitraryBoundedEnum
data InputSource
= NullInputSource
| KeyInputSource
| PointerInputSource
deriving (Eq, Show, Enum, Bounded)
instance FromJSON InputSource where
parseJSON (String x) = case x of
"null" -> return NullInputSource
"key" -> return KeyInputSource
"pointer" -> return PointerInputSource
_ -> unrecognizedValue "InputSource" x
parseJSON invalid = typeMismatch "InputSource" invalid
instance ToJSON InputSource where
toJSON x = case x of
NullInputSource -> String "null"
KeyInputSource -> String "key"
PointerInputSource -> String "pointer"
instance Arbitrary InputSource where
arbitrary = arbitraryBoundedEnum
data PointerSubtype
= PointerMouse
| PointerPen
| PointerTouch
deriving (Eq, Show, Enum, Bounded)
instance FromJSON PointerSubtype where
parseJSON (String x) = case x of
"mouse" -> return PointerMouse
"pen" -> return PointerPen
"touch" -> return PointerTouch
_ -> unrecognizedValue "PointerSubtype" x
parseJSON invalid = typeMismatch "PointerSubtype" invalid
instance ToJSON PointerSubtype where
toJSON x = case x of
PointerMouse -> String "mouse"
PointerPen -> String "pen"
PointerTouch -> String "touch"
instance Arbitrary PointerSubtype where
arbitrary = arbitraryBoundedEnum
data Action = Action
{ _inputSourceType :: Maybe InputSource
, _inputSourceId :: Maybe String
, _inputSourceParameters :: Maybe InputSourceParameter
, _actionItems :: [ActionItem]
} deriving (Eq, Show)
instance FromJSON Action where
parseJSON (Object v) = Action
<$> v .:? "type"
<*> v .:? "id"
<*> v .:? "parameters"
<*> v .: "actions"
parseJSON invalid = typeMismatch "Action" invalid
instance ToJSON Action where
toJSON Action{..} = object_
[ "type" .=? (toJSON <$> _inputSourceType)
, "id" .=? (toJSON <$> _inputSourceId)
, "parameters" .=? (toJSON <$> _inputSourceParameters)
, "actions" .== (toJSON <$> _actionItems)
]
instance Arbitrary Action where
arbitrary = Action
<$> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
emptyAction = Action
{ _inputSourceType = Nothing
, _inputSourceId = Nothing
, _inputSourceParameters = Nothing
, _actionItems = []
}
data ActionType
= PauseAction
| KeyUpAction
| KeyDownAction
| PointerDownAction
| PointerUpAction
| PointerMoveAction
| PointerCancelAction
deriving (Eq, Show, Enum, Bounded)
instance FromJSON ActionType where
parseJSON (String x) = case x of
"pause" -> return PauseAction
"keyUp" -> return KeyUpAction
"keyDown" -> return KeyDownAction
"pointerDown" -> return PointerDownAction
"pointerUp" -> return PointerUpAction
"pointerMove" -> return PointerMoveAction
"pointerCancel" -> return PointerCancelAction
_ -> unrecognizedValue "ActionType" x
parseJSON invalid = typeMismatch "ActionType" invalid
instance ToJSON ActionType where
toJSON x = case x of
PauseAction -> String "pause"
KeyUpAction -> String "keyUp"
KeyDownAction -> String "keyDown"
PointerDownAction -> String "pointerDown"
PointerUpAction -> String "pointerUp"
PointerMoveAction -> String "pointerMove"
PointerCancelAction -> String "pointerCancel"
instance Arbitrary ActionType where
arbitrary = arbitraryBoundedEnum
newtype InputSourceParameter = InputSourceParameter
{ _pointerSubtype :: Maybe PointerSubtype
} deriving (Eq, Show)
instance FromJSON InputSourceParameter where
parseJSON (Object v) = InputSourceParameter
<$> v .:? "subtype"
parseJSON invalid = typeMismatch "InputSourceParameter" invalid
instance ToJSON InputSourceParameter where
toJSON InputSourceParameter{..} = object_
[ "subtype" .=? (toJSON <$> _pointerSubtype)
]
instance Arbitrary InputSourceParameter where
arbitrary = InputSourceParameter
<$> arbitrary
data ActionItem = ActionItem
{ _actionType :: Maybe ActionType
, _actionDuration :: Maybe Int
, _actionOrigin :: Maybe String
, _actionValue :: Maybe String
, _actionButton :: Maybe Int
, _actionX :: Maybe Int
, _actionY :: Maybe Int
} deriving (Eq, Show)
instance FromJSON ActionItem where
parseJSON (Object v) = ActionItem
<$> v .:? "type"
<*> v .:? "duration"
<*> v .:? "origin"
<*> v .:? "value"
<*> v .:? "button"
<*> v .:? "x"
<*> v .:? "y"
parseJSON invalid = typeMismatch "ActionItem" invalid
instance ToJSON ActionItem where
toJSON ActionItem{..} = object_
[ "type" .=? (toJSON <$> _actionType)
, "duration" .=? (toJSON <$> _actionDuration)
, "origin" .=? (toJSON <$> _actionOrigin)
, "value" .=? (toJSON <$> _actionValue)
, "button" .=? (toJSON <$> _actionButton)
, "x" .=? (toJSON <$> _actionX)
, "y" .=? (toJSON <$> _actionY)
]
instance Arbitrary ActionItem where
arbitrary = ActionItem
<$> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
emptyActionItem :: ActionItem
emptyActionItem = ActionItem
{ _actionType = Nothing
, _actionDuration = Nothing
, _actionOrigin = Nothing
, _actionValue = Nothing
, _actionButton = Nothing
, _actionX = Nothing
, _actionY = Nothing
}
data Rect = Rect
{ _rectX :: Scientific
, _rectY :: Scientific
, _rectWidth :: Scientific
, _rectHeight :: Scientific
} deriving (Eq, Show)
instance ToJSON Rect where
toJSON Rect{..} = object
[ "x" .= toJSON _rectX
, "y" .= toJSON _rectY
, "width" .= toJSON _rectWidth
, "height" .= toJSON _rectHeight
]
instance FromJSON Rect where
parseJSON (Object v) = Rect
<$> v .: "x"
<*> v .: "y"
<*> v .: "width"
<*> v .: "height"
parseJSON invalid = typeMismatch "Rect" invalid
arbScientific :: Gen Scientific
arbScientific = scientific <$> arbitrary <*> arbitrary
instance Arbitrary Rect where
arbitrary = Rect
<$> arbScientific
<*> arbScientific
<*> arbScientific
<*> arbScientific
emptyRect :: Rect
emptyRect = Rect
{ _rectX = 0
, _rectY = 0
, _rectWidth = 0
, _rectHeight = 0
}
data PromptHandler
= DismissPrompts
| AcceptPrompts
| DismissPromptsAndNotify
| AcceptPromptsAndNotify
| IgnorePrompts
deriving (Eq, Show, Enum, Bounded)
instance FromJSON PromptHandler where
parseJSON (String x) = case x of
"dismiss" -> return DismissPrompts
"accept" -> return AcceptPrompts
"dismiss and notify" -> return DismissPromptsAndNotify
"accept and notify" -> return AcceptPromptsAndNotify
"ignore" -> return IgnorePrompts
_ -> unrecognizedValue "PromptHandler" x
parseJSON invalid = typeMismatch "PromptHandler" invalid
instance ToJSON PromptHandler where
toJSON x = case x of
DismissPrompts -> String "dismiss"
AcceptPrompts -> String "accept"
DismissPromptsAndNotify -> String "dismiss and notify"
AcceptPromptsAndNotify -> String "accept and notify"
IgnorePrompts -> String "ignore"
instance Arbitrary PromptHandler where
arbitrary = arbitraryBoundedEnum
data Cookie = Cookie
{ _cookieName :: Maybe String
, _cookieValue :: Maybe String
, _cookiePath :: Maybe String
, _cookieDomain :: Maybe String
, _cookieSecure :: Maybe Bool
, _cookieHttpOnly :: Maybe Bool
, _cookieExpiryTime :: Maybe String
} deriving (Eq, Show)
instance ToJSON Cookie where
toJSON Cookie{..} = object_
[ "name" .=? (toJSON <$> _cookieName)
, "value" .=? (toJSON <$> _cookieValue)
, "path" .=? (toJSON <$> _cookiePath)
, "domain" .=? (toJSON <$> _cookieDomain)
, "secure" .=? (toJSON <$> _cookieSecure)
, "httpOnly" .=? (toJSON <$> _cookieHttpOnly)
, "expiryTime" .=? (toJSON <$> _cookieExpiryTime)
]
instance FromJSON Cookie where
parseJSON (Object v) = Cookie
<$> v .:? "name"
<*> v .:? "value"
<*> v .:? "path"
<*> v .:? "domain"
<*> v .:? "secure"
<*> v .:? "httpOnly"
<*> v .:? "expiryTime"
parseJSON invalid = typeMismatch "Cookie" invalid
instance Arbitrary Cookie where
arbitrary = Cookie
<$> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
emptyCookie :: Cookie
emptyCookie = Cookie
{ _cookieName = Nothing
, _cookieValue = Nothing
, _cookiePath = Nothing
, _cookieDomain = Nothing
, _cookieSecure = Nothing
, _cookieHttpOnly = Nothing
, _cookieExpiryTime = Nothing
}
cookie
:: String
-> String
-> Cookie
cookie name value = emptyCookie
{ _cookieName = Just name
, _cookieValue = Just value
}