module Test.WebDriver.Commands.Angular (
waitForAngular
, NgException(..)
, NgSelector(..)
, findNg
, findNgs
, findNgFrom
, findNgsFrom
, NgRepeater(..)
, findRepeater
, findRepeaters
, findRepeaterFrom
, findRepeatersFrom
, ngEvaluate
, getLocationAbsUrl
) where
import Control.Monad.IO.Class (liftIO, MonadIO)
import Control.Exception (throwIO, Exception)
import Control.Applicative ((<$>))
import Data.Typeable (Typeable)
import Test.WebDriver.Classes
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 => T.Text -> [JSArg] -> wd [Element]
execElems script arg = do
x <- execCS script arg
case (x, A.fromJSON x) of
(A.Null, _) -> return []
(A.Array _, A.Success [A.Null]) -> return []
_ -> fromJSON' x
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 :: WebDriver wd => T.Text
-> wd Bool
waitForAngular sel = do
a <- asyncCS "waitForAngular" [JSArg sel] :: WebDriver wd => wd (Maybe ())
return $ maybe False (const True) 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
| ByInput T.Text
| ByTextarea T.Text
| BySelect 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" [e, JSArg name]
findNg' e (ByInput name) = execElems "findInputs" [e, JSArg name]
findNg' e (ByTextarea name) = execElems "findTextareas" [e, JSArg name]
findNg' e (BySelect name) = execElems "findSelects" [e, JSArg name]
findNg' e (BySelectedOption name) = execElems "findSelectedOptions" [e, JSArg name]
findNg' e (ByModel name) = concat <$> sequence [ findNg' e $ ByInput name
, findNg' e $ ByTextarea name
, findNg' e $ BySelect name
]
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" [e, JSArg rep]
findRepeater' e (ByRow rep idx) = execElems "findRepeaterRows" [e, JSArg rep, JSArg idx]
findRepeater' e (ByColumn rep idx) = execElems "findRepeaterColumn" [e, JSArg rep, JSArg idx]
findRepeater' e (ByRowAndCol rep row col) = execElems "findRepeaterElement" [e, JSArg rep, JSArg row, JSArg col]
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]