hledger-flow-0.16.1: test/BaseDir/Integration.hs
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
module BaseDir.Integration (tests) where
import Control.Exception (try)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Hledger.Flow.BaseDir (determineBaseDir)
import Hledger.Flow.Common
import Hledger.Flow.PathHelpers
import Hledger.Flow.Types (BaseDir, RunDir)
import Path
import Path.IO
import Test.HUnit
import qualified Turtle
import Prelude hiding (readFile, writeFile)
assertSubDirsForDetermineBaseDir :: AbsDir -> BaseDir -> [Path.Path b Dir] -> IO ()
assertSubDirsForDetermineBaseDir initialPwd expectedBaseDir importDirs = do
sequence_ $ map (assertDetermineBaseDir initialPwd expectedBaseDir) importDirs
assertDetermineBaseDir :: AbsDir -> BaseDir -> Path.Path b Dir -> IO ()
assertDetermineBaseDir initialPwd expectedBaseDir subDir = do
setCurrentDir initialPwd
(bd1, runDir1) <- determineBaseDir $ Just $ pathToTurtle subDir
assertFindTestFileUsingRundir bd1 runDir1
setCurrentDir subDir
(bd2, runDir2) <- determineBaseDir Nothing
assertFindTestFileUsingRundir bd2 runDir2
(bd3, runDir3) <- determineBaseDir $ Just "."
assertFindTestFileUsingRundir bd3 runDir3
(bd4, runDir4) <- determineBaseDir $ Just "./"
assertFindTestFileUsingRundir bd4 runDir4
setCurrentDir initialPwd
let msg dir = "determineBaseDir searches from pwd upwards until it finds a dir containing 'import' - " ++ show dir
sequence_ $ map (\dir -> assertEqual (msg dir) expectedBaseDir dir) [bd1, bd2, bd3, bd4]
assertFindTestFileUsingRundir :: BaseDir -> RunDir -> IO ()
assertFindTestFileUsingRundir baseDir runDir = do
let absRunDir = baseDir </> runDir
found <- Turtle.single $ fmap head $ shellToList $ Turtle.find (Turtle.has "test-file.txt") $ pathToTurtle absRunDir
fileContents <- T.readFile found
assertEqual "We should find our test file by searching from the returned runDir" (T.pack $ "The expected base dir is " ++ show baseDir) fileContents
assertCurrentDirVariations :: AbsDir -> RelDir -> IO ()
assertCurrentDirVariations absoluteTempDir bdRelativeToTempDir = do
let absBaseDir = absoluteTempDir </> bdRelativeToTempDir
setCurrentDir absBaseDir
(bd1, runDir1) <- determineBaseDir Nothing
(bd2, runDir2) <- determineBaseDir $ Just "."
(bd3, runDir3) <- determineBaseDir $ Just "./"
(bd4, runDir4) <- determineBaseDir $ Just $ pathToTurtle absBaseDir
let msg label dir = "When pwd is the base dir, determineBaseDir returns the same " ++ label ++ ", regardless of the input variation. " ++ show dir
sequence_ $ map (\dir -> assertEqual (msg "baseDir" dir) absBaseDir dir) [bd1, bd2, bd3, bd4]
sequence_ $ map (\dir -> assertEqual (msg "runDir" dir) [reldir|.|] dir) [runDir1, runDir2, runDir3, runDir4]
testBaseDirWithTempDir :: AbsDir -> AbsDir -> IO ()
testBaseDirWithTempDir initialPwd absoluteTempDir = do
error1 <- try $ determineBaseDir $ Just "/path/to/dir"
assertEqual "determineBaseDir produces an error message when given a non-existant dir" (Left $ InvalidTurtleDir "/path/to/dir") error1
let unrelatedDir = absoluteTempDir </> [reldir|unrelated|]
createDir unrelatedDir
bdUnrelated <- try $ determineBaseDir $ Just (pathToTurtle unrelatedDir)
assertEqual "determineBaseDir produces an error message when it cannot find a baseDir" (Left $ MissingBaseDir unrelatedDir) bdUnrelated
let baseDir = [reldir|bd1|]
let importDir = baseDir </> [reldir|import|]
let ownerDir = importDir </> [reldir|john|]
let bankDir = ownerDir </> [reldir|mybank|]
let accDir = bankDir </> [reldir|myacc|]
let inDir = accDir </> [reldir|1-in|]
let yearDir = inDir </> [reldir|2019|]
let subDirs = [yearDir, inDir, accDir, bankDir, ownerDir, importDir, baseDir] :: [RelDir]
createDirIfMissing True $ absoluteTempDir </> yearDir
let fictionalDir = absoluteTempDir </> ownerDir </> [reldir|fictionalDir|]
errorSub <- try $ determineBaseDir $ Just $ pathToTurtle fictionalDir
assertEqual "determineBaseDir produces an error message when given a non-existant subdir of a valid basedir" (Left $ InvalidTurtleDir $ pathToTurtle fictionalDir) errorSub
assertCurrentDirVariations absoluteTempDir baseDir
relativeTempDir <- makeRelative initialPwd absoluteTempDir
let subDirsRelativeToTop = map (relativeTempDir </>) subDirs
let absoluteSubDirs = map (absoluteTempDir </>) subDirs
let absoluteBaseDir = absoluteTempDir </> baseDir
T.writeFile (pathToTurtle $ absoluteTempDir </> yearDir </> [relfile|test-file.txt|]) (T.pack $ "The expected base dir is " ++ show absoluteBaseDir)
assertSubDirsForDetermineBaseDir absoluteTempDir absoluteBaseDir subDirs
assertSubDirsForDetermineBaseDir absoluteTempDir absoluteBaseDir absoluteSubDirs
assertSubDirsForDetermineBaseDir initialPwd absoluteBaseDir subDirsRelativeToTop
return ()
assertRunDirs :: RelDir -> [RelDir] -> [RelDir] -> IO ()
assertRunDirs accDir businessAsUsualRundirs specialTreatmentRundirs = do
sequence_ $ map (assertRunDir id "Normal rundirs should not be modified") businessAsUsualRundirs
sequence_ $ map (assertRunDir (\_ -> accDir) "Rundirs deeper than account-level should return the account dir instead") specialTreatmentRundirs
assertRunDir :: (RelDir -> RelDir) -> String -> RelDir -> IO ()
assertRunDir expectedRunDir msg subDir = do
(_, runDir) <- determineBaseDir $ Just $ pathToTurtle subDir
assertEqual msg (expectedRunDir subDir) runDir
testRunDirsWithTempDir :: AbsDir -> IO ()
testRunDirsWithTempDir absoluteTempDir = do
let baseDir = absoluteTempDir </> [reldir|bd1|]
let importDir = [reldir|import|]
let ownerDir = importDir </> [reldir|john|]
let bankDir = ownerDir </> [reldir|mybank|]
let accDir = bankDir </> [reldir|myacc|]
let inDir = accDir </> [reldir|1-in|]
let yearDir = inDir </> [reldir|2019|]
createDirIfMissing True $ baseDir </> yearDir
withCurrentDir baseDir $ assertRunDirs accDir [accDir, bankDir, ownerDir, importDir] [yearDir, inDir]
testRunDirs :: Test
testRunDirs =
TestCase
( do
initialPwd <- getCurrentDir
let tmpbase = initialPwd </> [reldir|test|] </> [reldir|tmp|]
withTempDir tmpbase "hlflowtest" testRunDirsWithTempDir
)
testDetermineBaseDir :: Test
testDetermineBaseDir =
TestCase
( do
initialPwd <- getCurrentDir
let tmpbase = initialPwd </> [reldir|test|] </> [reldir|tmp|]
createDirIfMissing True tmpbase
withTempDir tmpbase "hlflowtest" $ testBaseDirWithTempDir initialPwd
)
tests :: Test
tests = TestList [testDetermineBaseDir, testRunDirs]