sandwich-webdriver 0.1.2.0 → 0.2.0.0
raw patch · 5 files changed
+68/−32 lines, 5 filesdep +unliftioPVP ok
version bump matches the API change (PVP)
Dependencies added: unliftio
API changes (from Hackage documentation)
- Test.Sandwich.WebDriver.Config: obtainChromeDriver :: (MonadIO m, MonadLogger m, MonadBaseControl IO m) => FilePath -> ChromeDriverToUse -> m (Either Text FilePath)
+ Test.Sandwich.WebDriver.Config: obtainChromeDriver :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadMask m) => FilePath -> ChromeDriverToUse -> m (Either Text FilePath)
- Test.Sandwich.WebDriver.Internal.Binaries: obtainChromeDriver :: (MonadIO m, MonadLogger m, MonadBaseControl IO m) => FilePath -> ChromeDriverToUse -> m (Either Text FilePath)
+ Test.Sandwich.WebDriver.Internal.Binaries: obtainChromeDriver :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadMask m) => FilePath -> ChromeDriverToUse -> m (Either Text FilePath)
Files
- CHANGELOG.md +4/−0
- LICENSE +1/−1
- sandwich-webdriver.cabal +5/−3
- src/Test/Sandwich/WebDriver/Internal/Binaries.hs +40/−19
- test/Spec.hs +18/−9
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Changelog for sandwich-webdriver +# 0.2.0.0++* Fix the obtainChromeDriver function now that the zip files contain multiple files. This added a MonadMask constraint to the function so it's a major version bump.+ # 0.1.2.0 * Be able to control download directory.
LICENSE view
@@ -1,4 +1,4 @@-Copyright Tom McLaughlin (c) 2022+Copyright Tom McLaughlin (c) 2023 All rights reserved.
sandwich-webdriver.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.0.+-- This file has been generated from package.yaml by hpack version 0.35.1. -- -- see: https://github.com/sol/hpack name: sandwich-webdriver-version: 0.1.2.0+version: 0.2.0.0 synopsis: Sandwich integration with Selenium WebDriver description: Please see the <https://codedownio.github.io/sandwich/docs/extensions/sandwich-webdriver documentation>. category: Testing@@ -13,7 +13,7 @@ bug-reports: https://github.com/codedownio/sandwich/issues author: Tom McLaughlin maintainer: tom@codedown.io-copyright: 2022 Tom McLaughlin+copyright: 2023 Tom McLaughlin license: BSD3 license-file: LICENSE build-type: Simple@@ -226,11 +226,13 @@ , safe , safe-exceptions , sandwich >=0.1.0.3+ , sandwich-webdriver , string-interpolate , temporary , text , time , transformers+ , unliftio , unordered-containers , vector , webdriver
src/Test/Sandwich/WebDriver/Internal/Binaries.hs view
@@ -1,5 +1,9 @@ {-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE CPP, QuasiQuotes, ScopedTypeVariables, NamedFieldPuns, Rank2Types #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE Rank2Types #-} module Test.Sandwich.WebDriver.Internal.Binaries ( obtainSelenium@@ -9,7 +13,9 @@ , downloadChromeDriverIfNecessary ) where +import Control.Exception import Control.Monad+import Control.Monad.Catch import Control.Monad.IO.Class import Control.Monad.Logger import Control.Monad.Trans.Control (MonadBaseControl)@@ -19,17 +25,25 @@ import GHC.Stack import System.Directory import System.FilePath+import System.IO.Temp import System.Process import Test.Sandwich.Logging import Test.Sandwich.WebDriver.Internal.Binaries.Util import Test.Sandwich.WebDriver.Internal.Types import Test.Sandwich.WebDriver.Internal.Util -type Constraints m = (HasCallStack, MonadLogger m, MonadIO m, MonadBaseControl IO m) +type Constraints m = (+ HasCallStack+ , MonadLogger m+ , MonadIO m+ , MonadBaseControl IO m+ , MonadMask m+ )+ -- * Obtaining binaries - -- TODO: remove curl dependencies here+-- TODO: remove curl dependencies here -- | Manually obtain a Selenium server JAR file, according to the 'SeleniumToUse' policy, -- storing it under the provided 'FilePath' if necessary and returning the exact path.@@ -46,14 +60,15 @@ unlessM (liftIO $ doesFileExist seleniumPath) $ void $ liftIO $ readCreateProcess (shell [i|curl https://selenium-release.storage.googleapis.com/3.141/selenium-server-standalone-3.141.59.jar -o #{seleniumPath}|]) "" return $ Right seleniumPath-obtainSelenium _ (UseSeleniumAt path) =- (liftIO $ doesFileExist path) >>= \case- False -> return $ Left [i|Path '#{path}' didn't exist|]- True -> return $ Right path+obtainSelenium _ (UseSeleniumAt path) = liftIO (doesFileExist path) >>= \case+ False -> return $ Left [i|Path '#{path}' didn't exist|]+ True -> return $ Right path -- | Manually obtain a chromedriver binary, according to the 'ChromeDriverToUse' policy, -- storing it under the provided 'FilePath' if necessary and returning the exact path.-obtainChromeDriver :: (MonadIO m, MonadLogger m, MonadBaseControl IO m) => FilePath -> ChromeDriverToUse -> m (Either T.Text FilePath)+obtainChromeDriver :: (+ MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadMask m+ ) => FilePath -> ChromeDriverToUse -> m (Either T.Text FilePath) obtainChromeDriver toolsDir (DownloadChromeDriverFrom url) = do let path = [i|#{toolsDir}/#{chromeDriverExecutable}|] liftIO $ createDirectoryIfMissing True (takeDirectory path)@@ -71,10 +86,9 @@ obtainChromeDriver toolsDir (DownloadChromeDriverAutodetect maybeChromePath) = runExceptT $ do version <- ExceptT $ liftIO $ getChromeDriverVersion maybeChromePath ExceptT $ obtainChromeDriver toolsDir (DownloadChromeDriverVersion version)-obtainChromeDriver _ (UseChromeDriverAt path) =- (liftIO $ doesFileExist path) >>= \case- False -> return $ Left [i|Path '#{path}' didn't exist|]- True -> return $ Right path+obtainChromeDriver _ (UseChromeDriverAt path) = liftIO (doesFileExist path) >>= \case+ False -> return $ Left [i|Path '#{path}' didn't exist|]+ True -> return $ Right path -- | Manually obtain a geckodriver binary, according to the 'GeckoDriverToUse' policy, -- storing it under the provided 'FilePath' if necessary and returning the exact path.@@ -96,10 +110,9 @@ obtainGeckoDriver toolsDir (DownloadGeckoDriverAutodetect maybeFirefoxPath) = runExceptT $ do version <- ExceptT $ liftIO $ getGeckoDriverVersion maybeFirefoxPath ExceptT $ obtainGeckoDriver toolsDir (DownloadGeckoDriverVersion version)-obtainGeckoDriver _ (UseGeckoDriverAt path) =- (liftIO $ doesFileExist path) >>= \case- False -> return $ Left [i|Path '#{path}' didn't exist|]- True -> return $ Right path+obtainGeckoDriver _ (UseGeckoDriverAt path) = liftIO (doesFileExist path) >>= \case+ False -> return $ Left [i|Path '#{path}' didn't exist|]+ True -> return $ Right path -- * Lower level helpers @@ -107,7 +120,7 @@ downloadSeleniumIfNecessary :: Constraints m => FilePath -> m (Either T.Text FilePath) downloadSeleniumIfNecessary toolsDir = leftOnException' $ do let seleniumPath = [i|#{toolsDir}/selenium-server.jar|]- (liftIO (doesFileExist seleniumPath) >>= flip unless (downloadSelenium seleniumPath))+ liftIO (doesFileExist seleniumPath) >>= flip unless (downloadSelenium seleniumPath) return seleniumPath downloadSelenium :: Constraints m => FilePath -> m ()@@ -147,11 +160,19 @@ Windows -> "geckodriver.exe" _ -> "geckodriver" -downloadAndUnzipToPath :: (MonadIO m, MonadBaseControl IO m, MonadLogger m) => T.Text -> FilePath -> m (Either T.Text ())+downloadAndUnzipToPath :: (MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadMask m) => T.Text -> FilePath -> m (Either T.Text ()) downloadAndUnzipToPath downloadPath localPath = leftOnException' $ do info [i|Downloading #{downloadPath} to #{localPath}|] liftIO $ createDirectoryIfMissing True (takeDirectory localPath)- liftIO $ void $ readCreateProcess (shell [i|wget -nc -O - #{downloadPath} | gunzip - > #{localPath}|]) ""+ withSystemTempDirectory "sandwich-webdriver-tool-download" $ \dir -> liftIO $ do+ void $ readCreateProcess ((proc "curl" [T.unpack downloadPath, "-o", "temp.zip"]) { cwd = Just dir }) ""+ void $ readCreateProcess ((proc "unzip" ["temp.zip"]) { cwd = Just dir }) ""++ liftIO (listDirectory dir >>= filterM (\f -> executable <$> getPermissions (dir </> f))) >>= \case+ [] -> throwIO $ userError [i|No executable found in file downloaded from #{downloadPath}|]+ [x] -> renameFile (dir </> x) localPath+ xs -> throwIO $ userError [i|Found multiple executable found in file downloaded from #{downloadPath}: #{xs}|]+ liftIO $ void $ readCreateProcess (shell [i|chmod u+x #{localPath}|]) "" downloadAndUntarballToPath :: (MonadIO m, MonadBaseControl IO m, MonadLogger m) => T.Text -> FilePath -> m (Either T.Text ())
test/Spec.hs view
@@ -1,20 +1,29 @@ import Test.Sandwich+import Test.Sandwich.WebDriver.Config+import Data.Text as T+import UnliftIO.Temporary import Data.Time.Clock-import Test.Sandwich.Formatters.Print+import Data.String.Interpolate -data Foo = Foo { fooInt :: Int, fooString :: String, fooBar :: Bar } deriving (Show, Eq)-data Bar = Bar { barInt :: Int, barString :: String } deriving (Show, Eq)-data Baz = Baz Int String Bar deriving (Show, Eq)-data Simple = Simple { simpleInt :: Int } deriving (Show, Eq) +spec :: TopSpec+spec = do+ it "successfully runs obtainChromeDriver" $ do+ withSystemTempDirectory "test-download" $ \dir -> do+ obtainChromeDriver dir (DownloadChromeDriverAutodetect Nothing) >>= \case+ Right x -> info [i|Got chromedriver: #{x}|]+ Left err -> expectationFailure (T.unpack err) -verySimple :: TopSpec-verySimple = do- it "succeeds" (return ())+ it "successfully runs obtainGeckoDriver" $ do+ withSystemTempDirectory "test-download" $ \dir -> do+ obtainGeckoDriver dir (DownloadGeckoDriverAutodetect Nothing) >>= \case+ Right x -> info [i|Got geckoDriver: #{x}|]+ Left err -> expectationFailure (T.unpack err) + main :: IO ()-main = runSandwich options verySimple+main = runSandwich options spec where options = defaultOptions { optionsTestArtifactsDirectory = TestArtifactsGeneratedDirectory "test_runs" (show <$> getCurrentTime)