{-# LANGUAGE ConstraintKinds #-}
module Test.Sandwich.WebDriver.Internal.Binaries.Selenium (
obtainSelenium
, downloadSeleniumIfNecessary
, SeleniumToUse(..)
) where
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.IO.Unlift
import Control.Monad.Logger
import Control.Monad.Reader
import qualified Data.List as L
import Data.String.Interpolate
import qualified Data.Text as T
import GHC.Stack
import Test.Sandwich
import Test.Sandwich.Contexts.Files
import Test.Sandwich.Contexts.Nix
import Test.Sandwich.WebDriver.Internal.Binaries.Common
import Test.Sandwich.WebDriver.Internal.Binaries.Selenium.Types
import Test.Sandwich.WebDriver.Internal.Util
import UnliftIO.Directory
type Constraints m = (
HasCallStack
, MonadLogger m
, MonadUnliftIO m
)
defaultSeleniumJarUrl :: String
defaultSeleniumJarUrl :: String
defaultSeleniumJarUrl = String
"https://selenium-release.storage.googleapis.com/3.141/selenium-server-standalone-3.141.59.jar"
obtainSelenium :: (
MonadReader context m, HasBaseContext context
, MonadUnliftIO m, MonadLogger m
)
=> SeleniumToUse
-> m FilePath
obtainSelenium :: forall context (m :: * -> *).
(MonadReader context m, HasBaseContext context, MonadUnliftIO m,
MonadLogger m) =>
SeleniumToUse -> m String
obtainSelenium (DownloadSeleniumFrom String
toolsDir String
url) = do
let path :: String
path = [i|#{toolsDir}/selenium-server-standalone.jar|]
String -> m Bool
forall (m :: * -> *). MonadIO m => String -> m Bool
doesFileExist String
path m Bool -> (Bool -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
True -> do
Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
debug [i|Selenium already existed at #{path}|]
Bool
False -> do
Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
debug [i|Downloading Selenium from #{url} to #{path}|]
String -> String -> m ()
forall (m :: * -> *).
(MonadUnliftIO m, MonadLogger m) =>
String -> String -> m ()
curlDownloadToPath String
url String
path
String -> m String
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return String
path
obtainSelenium (DownloadSeleniumDefault String
toolsDir) = do
let path :: String
path = [i|#{toolsDir}/selenium-server-standalone-3.141.59.jar|]
String -> m Bool
forall (m :: * -> *). MonadIO m => String -> m Bool
doesFileExist String
path m Bool -> (Bool -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
True -> do
Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
debug [i|Selenium already existed at #{path}|]
Bool
False -> do
Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
debug [i|Downloading Selenium from #{defaultSeleniumJarUrl} to #{path}|]
String -> String -> m ()
forall (m :: * -> *).
(MonadUnliftIO m, MonadLogger m) =>
String -> String -> m ()
curlDownloadToPath String
defaultSeleniumJarUrl String
path
String -> m String
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return String
path
obtainSelenium (UseSeleniumAt String
path) = IO Bool -> m Bool
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO Bool
forall (m :: * -> *). MonadIO m => String -> m Bool
doesFileExist String
path) m Bool -> (Bool -> m String) -> m String
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
False -> String -> m String
forall (m :: * -> *) a. (HasCallStack, MonadIO m) => String -> m a
expectationFailure [i|Path '#{path}' didn't exist|]
Bool
True -> do
Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
debug [i|Found Selenium at #{path}|]
String -> m String
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return String
path
obtainSelenium (UseSeleniumFromNixpkgs NixContext
nc) = do
Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
debug [i|Building selenium-server-standalone with Nix...|]
ret <- NixContext -> [Text] -> m String
forall context (m :: * -> *).
(HasBaseContextMonad context m, MonadUnliftIO m, MonadLogger m) =>
NixContext -> [Text] -> m String
buildNixSymlinkJoin' NixContext
nc [Text
"selenium-server-standalone"] m String -> (String -> m String) -> m String
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
IO String -> m String
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO String -> m String)
-> (String -> IO String) -> String -> m String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> IO Bool) -> String -> IO String
findFirstFile (Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> (String -> Bool) -> String -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
".jar" String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`L.isSuffixOf`))
debug [i|Got Selenium: #{ret}|]
return ret
downloadSeleniumIfNecessary :: Constraints m => FilePath -> m (Either T.Text FilePath)
downloadSeleniumIfNecessary :: forall (m :: * -> *).
Constraints m =>
String -> m (Either Text String)
downloadSeleniumIfNecessary String
toolsDir = m String -> m (Either Text String)
forall (m :: * -> *) a. MonadUnliftIO m => m a -> m (Either Text a)
leftOnException' (m String -> m (Either Text String))
-> m String -> m (Either Text String)
forall a b. (a -> b) -> a -> b
$ do
let seleniumPath :: String
seleniumPath = [i|#{toolsDir}/selenium-server.jar|]
IO Bool -> m Bool
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO Bool
forall (m :: * -> *). MonadIO m => String -> m Bool
doesFileExist String
seleniumPath) m Bool -> (Bool -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Bool -> m () -> m ()) -> m () -> Bool -> m ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (String -> m ()
forall (m :: * -> *). Constraints m => String -> m ()
downloadSelenium String
seleniumPath)
String -> m String
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return String
seleniumPath
where
downloadSelenium :: Constraints m => FilePath -> m ()
downloadSelenium :: forall (m :: * -> *). Constraints m => String -> m ()
downloadSelenium String
seleniumPath = m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
info [i|Downloading selenium-server.jar to #{seleniumPath}|]
String -> String -> m ()
forall (m :: * -> *).
(MonadUnliftIO m, MonadLogger m) =>
String -> String -> m ()
curlDownloadToPath String
defaultSeleniumJarUrl String
seleniumPath