module TestServerAPI
( withTestServer,
authTestUrl,
invalidUrl,
testServerHomeUrl,
malformedResponseUrl,
boringHelloUrl,
boringHelloUrl2,
)
where
import Control.Concurrent (threadDelay)
import Control.Exception (SomeException, catch, throwIO)
import Control.Monad (void, when)
import Data.Text (Text)
import Data.Text qualified as T
import Data.Time (addUTCTime, getCurrentTime)
import IOUtils (findWebDriverRoot)
import Network.HTTP.Req (GET (..), NoReqBody (..), defaultHttpConfig, http, ignoreResponse, port, req, runReq)
import System.Directory (getCurrentDirectory)
import UnliftIO (finally)
import UnliftIO.Process (createProcess, cwd, proc, terminateProcess)
testServerHomeUrl :: Text
testServerHomeUrl = "http://localhost:8000/"
subPage :: Text -> Text
subPage subPath = testServerHomeUrl <> "/" <> subPath
authTestUrl :: Text
authTestUrl = subPage "authtest"
invalidUrl :: Text
invalidUrl = subPage "invalid-page"
boringHelloUrl :: Text
boringHelloUrl = subPage "boringHello"
boringHelloUrl2 :: Text
boringHelloUrl2 = subPage "boringHello2"
malformedResponseUrl :: Text
malformedResponseUrl = subPage "malformed-response"
-- | Ping the test server until it responds with 200 OK
-- Throws an exception if the server doesn't respond within 10 seconds
pingUntilReady :: Text -> IO ()
pingUntilReady url = do
startTime <- getCurrentTime
let plusTenSecs = addUTCTime 10 startTime
tryPing plusTenSecs
where
tryPing expiryTime = do
currentTime <- getCurrentTime
when (currentTime > expiryTime) $
throwIO $
userError $
"Test server at " <> T.unpack url <> " did not become ready within 10 seconds"
catch
( runReq defaultHttpConfig $
void $
req GET (http "localhost") NoReqBody ignoreResponse (port 8000)
)
\(_ :: SomeException) ->
threadDelay 100_000 -- 100ms
>> tryPing expiryTime
-- | Run an IO action with the test server running
withTestServer :: forall a. IO a -> IO a
withTestServer action = do
currentDir <- getCurrentDirectory
case findWebDriverRoot currentDir of
Nothing ->
fail $
"Could not find 'webdriver' root directory from: "
<> currentDir
<> "\n withTestServer expects to be run from the 'webdriver' directory"
Just webdriverRoot -> do
let serverStart = (proc "cabal" ["run", "test-server"]) {cwd = Just webdriverRoot}
(_, _, _, handle) <- createProcess serverStart
pingUntilReady testServerHomeUrl
finally
action
$ terminateProcess handle