module Test.WebDriver.Commands.Angular (
waitForAngular
, NgException(..)
, NgSelector(..)
, findNg
, findNgs
, findNgFrom
, findNgsFrom
, NgRepeater(..)
, findRepeaters
, findRepeater
, findRepeaterFrom
, findRepeatersFrom
, ngEvaluate
, getLocationAbsUrl
, setNgLocation
) where
import Control.Monad.IO.Class (liftIO, MonadIO)
import Control.Exception (throwIO, Exception)
import Data.Typeable (Typeable)
import Test.WebDriver.Class
import Test.WebDriver.Commands
import Test.WebDriver.JSON (fromJSON')
import Test.WebDriver.Commands.Internal (clientScripts)
import Language.Haskell.TH (runIO, litE, stringL)
import qualified Data.Aeson as A
import qualified Data.HashMap.Lazy as M
import qualified Data.Text as T
cs :: M.HashMap T.Text T.Text
cs = either (\err -> error $ "Error parsing scripts " ++ err) id mhash
where
mhash = clientScripts j
j = $(runIO (readFile "js/angular-clientsidescripts.js") >>= litE . stringL)
execCS :: (WebDriver wd, A.FromJSON a) => T.Text -> [JSArg] -> wd a
execCS script arg = executeJS arg body
where
body = maybe (error $ "Unable to find " ++ T.unpack script) id $ M.lookup script cs
execElems :: (WebDriver wd, A.FromJSON a) => T.Text -> [JSArg] -> wd [a]
execElems script arg = do
mlst <- execCS script arg
case mlst of
Nothing -> return []
Just lst -> mapM fromJSON' $ filter isObject lst
where
isObject (A.Object _) = True
isObject _ = False
asyncCS :: (WebDriver wd, A.FromJSON a) => T.Text -> [JSArg] -> wd (Maybe a)
asyncCS script arg = asyncJS arg body
where
body = maybe (error $ "Unable to find " ++ T.unpack script) id $ M.lookup script cs
waitForAngular :: (MonadIO wd, WebDriver wd)
=> T.Text
-> wd Bool
waitForAngular sel = do
a <- asyncCS "waitForAngular" [JSArg sel]
case a of
Nothing -> return False
Just A.Null -> return True
Just _ -> liftIO $ throwIO $ NgException $ "Error waiting for angular: " ++ show a
data NgException = NgException String
deriving (Show, Eq, Typeable)
instance Exception NgException
checkOne :: (Show s, MonadIO wd, WebDriver wd) => s -> [Element] -> wd Element
checkOne _ [e] = return e
checkOne sel es = liftIO $ throwIO err
where
err = NgException $ "Selector " ++ show sel ++ " returned " ++ show es
data NgSelector =
ByBinding T.Text
| ByModel T.Text
| BySelectedOption T.Text
deriving (Show,Eq)
data NgRepeater =
ByRows T.Text
| ByRow T.Text Int
| ByColumn T.Text T.Text
| ByRowAndCol T.Text Int T.Text
deriving (Show,Eq)
findNg :: (MonadIO wd, WebDriver wd) => NgSelector -> wd Element
findNg s = checkOne s =<< findNg' (JSArg A.Null) s
findNgs :: WebDriver wd => NgSelector -> wd [Element]
findNgs = findNg' $ JSArg A.Null
findNgFrom :: (MonadIO wd, WebDriver wd) => Element -> NgSelector -> wd Element
findNgFrom e s = checkOne s =<< findNg' (JSArg e) s
findNgsFrom :: WebDriver wd => Element -> NgSelector -> wd [Element]
findNgsFrom e = findNg' $ JSArg e
findNg' :: WebDriver wd => JSArg -> NgSelector -> wd [Element]
findNg' e (ByBinding name) = execElems "findBindings" [JSArg name, e]
findNg' e (ByModel name) = execElems "findByModel" [JSArg name, e]
findNg' e (BySelectedOption name) = execElems "findSelectedOptions" [JSArg name, e]
findRepeater :: (MonadIO wd, WebDriver wd) => NgRepeater -> wd Element
findRepeater r = checkOne r =<< findRepeater' (JSArg A.Null) r
findRepeaters :: WebDriver wd => NgRepeater -> wd [Element]
findRepeaters = findRepeater' $ JSArg A.Null
findRepeaterFrom :: (MonadIO wd, WebDriver wd) => Element -> NgRepeater -> wd Element
findRepeaterFrom e r = checkOne r =<< findRepeater' (JSArg e) r
findRepeatersFrom :: WebDriver wd => Element -> NgRepeater -> wd [Element]
findRepeatersFrom e = findRepeater' $ JSArg e
findRepeater' :: WebDriver wd => JSArg -> NgRepeater -> wd [Element]
findRepeater' e (ByRows rep) = execElems "findAllRepeaterRows" [JSArg rep, e]
findRepeater' e (ByRow rep idx) = execElems "findRepeaterRows" [JSArg rep, JSArg idx, e]
findRepeater' e (ByColumn rep idx) = execElems "findRepeaterColumn" [JSArg rep, JSArg idx, e]
findRepeater' e (ByRowAndCol rep row col) = execElems "findRepeaterElement" [JSArg rep, JSArg row, JSArg col, e]
ngEvaluate :: (WebDriver wd, A.FromJSON a)
=> Element
-> T.Text
-> wd a
ngEvaluate e expr = execCS "evaluate" [JSArg e, JSArg expr]
getLocationAbsUrl :: WebDriver wd => T.Text
-> wd T.Text
getLocationAbsUrl sel = execCS "getLocationAbsUrl" [JSArg sel]
setNgLocation :: (MonadIO wd, WebDriver wd)
=> T.Text
-> T.Text
-> wd ()
setNgLocation sel url = do
x <- execCS "setLocation" [JSArg sel, JSArg url]
case x of
A.Null -> return ()
_ -> liftIO $ throwIO $ NgException $ "Error setting location: " ++ show x