{-# LANGUAGE OverloadedStrings #-} import Data.List (intercalate) import GHC.IO (bracket) import Hasql.Connection (settings) import Lib (getFileNames, getSqlFiles, runMigrations, withConnection) import System.Directory (createDirectory, removeDirectoryRecursive) import System.FilePath () import Test.Hspec (around_, describe, hspec, it, shouldBe) import Test.QuickCheck ( Gen, choose, generate, listOf1, vectorOf, ) import Test.QuickCheck.Gen (elements) main :: IO () main = hspec $ do describe "Lib" $ do around_ withTempDirectory $ do it "should return a list of file names" $ do fileNames <- generate $ vectorOf 5 genFlywayFilename mapM_ (\filename -> writeFile ("testdir/" <> filename) "test\n") fileNames names <- getFileNames "testdir" length names `shouldBe` 5 around_ withTempDirectory $ do it "should return only files that pass all filters [startsWith V/U/R, endsWith .sql]" $ do fileNamesSql <- generate $ vectorOf 5 genFlywayFilename fileNames <- generate $ vectorOf 5 genRandomFilename mapM_ (\filename -> writeFile ("testdir/" <> filename) "test\n") $ fileNames ++ fileNamesSql names <- getSqlFiles "testdir" length names `shouldBe` 5 it "Runs migrations" $ do let set = settings "localhost" 5432 "postgres" "postgres" "postgres" withConnection set (runMigrations "./test/good_migrations") withTempDirectory :: IO () -> IO () withTempDirectory action = bracket (createDirectory "testdir") (\_ -> removeDirectoryRecursive "testdir") (const action) -- Generate a valid Flyway migration filename genFlywayFilename :: Gen String genFlywayFilename = do version <- genVersion description <- listOf1 $ elements ['a' .. 'z'] let filename = "V" ++ version ++ "__" ++ description ++ ".sql" return filename where genVersion = do parts <- listOf1 $ choose (1, 9) :: Gen [Int] return $ intercalate "." (map show parts) -- Generate a random filename genRandomFilename :: Gen String genRandomFilename = do name <- listOf1 $ elements (['a' .. 'z'] ++ ['A' .. 'Z'] ++ ['0' .. '9']) let filename = name ++ ".sql" return filename