{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedLists #-} module CSVImport.Integration (tests) where import Test.HUnit import Turtle import Prelude hiding (FilePath) import qualified Data.Map.Strict as Map import qualified Control.Foldl as Fold import qualified Data.Text as T import qualified Data.List as List (sort) import TestHelpers import Hledger.MakeItSo.Import.Types import Hledger.MakeItSo.Common import Control.Concurrent.STM testHiddenFiles = TestCase ( sh ( do tmpdir <- using (mktempdir "." "makeitso") let tmpJournals = map (tmpdir ) journalFiles :: [FilePath] let tmpExtras = map (tmpdir ) extraFiles :: [FilePath] let tmpHidden = map (tmpdir ) hiddenFiles :: [FilePath] let onDisk = List.sort $ tmpJournals ++ tmpExtras ++ tmpHidden touchAll onDisk filtered <- (fmap List.sort) $ shellToList $ onlyFiles $ select onDisk let expected = List.sort $ tmpExtras ++ tmpJournals liftIO $ assertEqual "Hidden files should be excluded" expected filtered ) ) testDirOrPwd = TestCase ( sh ( do currentDir <- fmap (\p -> directory (p "t")) pwd tmpdir <- using (mktempdir "." "makeitso") let fooDir = collapse $ currentDir tmpdir "foo/" let barDir = collapse $ currentDir tmpdir "bar/" mkdir fooDir mkdir barDir d1 <- liftIO $ dirOrPwd Nothing liftIO $ assertEqual "dirOrPwd returns pwd as a fallback" currentDir d1 liftIO $ assertEqual "dirOrPwd assumes the fallback is a directory" (directory d1) d1 d2 <- liftIO $ dirOrPwd $ Just $ tmpdir "foo" liftIO $ assertEqual "dirOrPwd returns the supplied dir - no trailing slash supplied" fooDir d2 liftIO $ assertEqual "dirOrPwd assumes the supplied dir is a directory - no trailing slash supplied" (directory d2) d2 d3 <- liftIO $ dirOrPwd $ Just $ tmpdir "bar/" liftIO $ assertEqual "dirOrPwd returns the supplied dir - trailing slash supplied" barDir d3 liftIO $ assertEqual "dirOrPwd assumes the supplied dir is a directory - trailing slash supplied" (directory d3) d3 ) ) testFilterPaths = TestCase ( sh ( do tmpdir <- using (mktempdir "." "makeitso") let tmpJournals = map (tmpdir ) journalFiles :: [FilePath] let tmpExtras = map (tmpdir ) extraFiles :: [FilePath] let tmpHidden = map (tmpdir ) hiddenFiles :: [FilePath] let onDisk = List.sort $ tmpJournals ++ tmpExtras ++ tmpHidden touchAll onDisk let nonExistant = map (tmpdir ) ["where", "is", "my", "mind"] let toFilter = nonExistant ++ onDisk filtered <- single $ filterPaths testfile toFilter let actual = List.sort filtered liftIO $ assertEqual "The filtered paths should exclude files not actually on disk" onDisk actual ) ) testExtraIncludesForFile = TestCase ( sh ( do tmpdir <- using (mktempdir "." "makeitso") let importedJournals = map (tmpdir ) journalFiles :: [FilePath] let accountDir = "import/john/bogartbank/savings" let opening = tmpdir accountDir "2017-opening.journal" let closing = tmpdir accountDir "2017-closing.journal" let hidden = map (tmpdir ) hiddenFiles :: [FilePath] touchAll $ importedJournals ++ hidden let accountInclude = tmpdir accountDir "2017-include.journal" let expectedEmpty = [(accountInclude, [])] ch <- liftIO newTChanIO extraOpening1 <- extraIncludesForFile (defaultOpts tmpdir) ch accountInclude ["opening.journal"] [] liftIO $ assertEqual "The opening journal should not be included when it is not on disk" expectedEmpty extraOpening1 extraClosing1 <- extraIncludesForFile (defaultOpts tmpdir) ch accountInclude ["closing.journal"] [] liftIO $ assertEqual "The closing journal should not be included when it is not on disk" expectedEmpty extraClosing1 touchAll [opening, closing] extraOpening2 <- extraIncludesForFile (defaultOpts tmpdir) ch accountInclude ["opening.journal"] [] liftIO $ assertEqual "The opening journal should be included when it is on disk" [(accountInclude, [opening])] extraOpening2 extraClosing2 <- extraIncludesForFile (defaultOpts tmpdir) ch accountInclude ["closing.journal"] [] liftIO $ assertEqual "The closing journal should be included when it is on disk" [(accountInclude, [closing])] extraClosing2 )) testIncludesPrePost = TestCase ( sh ( do tmpdir <- using (mktempdir "." "makeitso") let ownerDir = tmpdir "import/john" let includeFile = ownerDir "2019-include.journal" let pre = ownerDir "_manual_" "2019" "pre-import.journal" let post = ownerDir "_manual_" "2019" "post-import.journal" touchAll [pre, post] let includeMap = Map.singleton includeFile [ownerDir "bank1" "2019-include.journal", ownerDir "bank2" "2019-include.journal"] ch <- liftIO newTChanIO fileMap <- toIncludeFiles (defaultOpts tmpdir) ch includeMap let expectedText = includePreamble <> "\n" <> "!include _manual_/2019/pre-import.journal\n" <> "!include bank1/2019-include.journal\n" <> "!include bank2/2019-include.journal\n" <> "!include _manual_/2019/post-import.journal\n" let expectedMap = Map.singleton includeFile expectedText liftIO $ assertEqual "All pre/post files on disk should be included" expectedMap fileMap )) testIncludesOpeningClosing = TestCase ( sh ( do tmpdir <- using (mktempdir "." "makeitso") let ownerDir = tmpdir "import/john" let accountDir = ownerDir "bank1" "savings" let includeFile = accountDir "2019-include.journal" let opening = accountDir "2019-opening.journal" let closing = accountDir "2019-closing.journal" touchAll [opening, closing] let includeMap = Map.singleton includeFile [accountDir "3-journal" "2019" "2019-01-30.journal"] ch <- liftIO newTChanIO fileMap <- toIncludeFiles (defaultOpts tmpdir) ch includeMap let expectedText = includePreamble <> "\n" <> "!include 2019-opening.journal\n" <> "!include 3-journal/2019/2019-01-30.journal\n" <> "!include 2019-closing.journal\n" let expectedMap = Map.singleton includeFile expectedText liftIO $ assertEqual "All pre/post files on disk should be included" expectedMap fileMap )) testWriteIncludeFiles = TestCase ( sh ( do tmpdir <- using (mktempdir "." "makeitso") let importedJournals = map (tmpdir ) journalFiles :: [FilePath] let extras = map (tmpdir ) extraFiles :: [FilePath] let hidden = map (tmpdir ) hiddenFiles :: [FilePath] touchAll $ importedJournals ++ extras ++ hidden let jane1 = tmpdir "import/jane/bogartbank/checking/2018-include.journal" let jane2 = tmpdir "import/jane/bogartbank/checking/2019-include.journal" let jane3 = tmpdir "import/jane/bogartbank/savings/2017-include.journal" let jane4 = tmpdir "import/jane/bogartbank/savings/2018-include.journal" let jane5 = tmpdir "import/jane/otherbank/creditcard/2017-include.journal" let jane6 = tmpdir "import/jane/otherbank/creditcard/2018-include.journal" let jane7 = tmpdir "import/jane/otherbank/investments/2018-include.journal" let jane8 = tmpdir "import/jane/otherbank/investments/2019-include.journal" let john1 = tmpdir "import/john/bogartbank/checking/2018-include.journal" let john2 = tmpdir "import/john/bogartbank/checking/2019-include.journal" let john3 = tmpdir "import/john/bogartbank/savings/2017-include.journal" let john4 = tmpdir "import/john/bogartbank/savings/2018-include.journal" let john5 = tmpdir "import/john/otherbank/creditcard/2017-include.journal" let john6 = tmpdir "import/john/otherbank/creditcard/2018-include.journal" let john7 = tmpdir "import/john/otherbank/investments/2018-include.journal" let john8 = tmpdir "import/john/otherbank/investments/2019-include.journal" let expectedIncludes = [jane1, jane2, jane3, jane4, jane5, jane6, jane7, jane8, john1, john2, john3, john4, john5, john6, john7, john8] ch <- liftIO newTChanIO reportedAsWritten <- single $ groupAndWriteIncludeFiles (defaultOpts tmpdir) ch importedJournals liftIO $ assertEqual "groupAndWriteIncludeFiles should return which files it wrote" expectedIncludes reportedAsWritten let allYears = [tmpdir "import/jane/bogartbank/checking/all-years.journal", tmpdir "import/jane/bogartbank/savings/all-years.journal", tmpdir "import/jane/otherbank/creditcard/all-years.journal", tmpdir "import/jane/otherbank/investments/all-years.journal", tmpdir "import/john/bogartbank/checking/all-years.journal", tmpdir "import/john/bogartbank/savings/all-years.journal", tmpdir "import/john/otherbank/creditcard/all-years.journal", tmpdir "import/john/otherbank/investments/all-years.journal"] let expectedOnDisk = List.sort $ reportedAsWritten ++ extras ++ importedJournals ++ allYears allFilesOnDisk <- single $ sort $ onlyFiles $ lstree tmpdir liftIO $ assertEqual "The actual files on disk should match what groupAndWriteIncludeFiles reported" expectedOnDisk allFilesOnDisk let expectedJohn1Contents = includePreamble <> "\n" <> "!include 3-journal/2018/2018-10-30.journal\n" <> "!include 3-journal/2018/2018-11-30.journal\n" <> "!include 3-journal/2018/2018-12-30.journal\n" actualJohn1Contents <- liftIO $ readTextFile john1 liftIO $ assertEqual "John1: The include file contents should be the journal files" expectedJohn1Contents actualJohn1Contents let expectedJohn2Contents = includePreamble <> "\n" <> "!include 3-journal/2019/2019-01-30.journal\n" <> "!include 3-journal/2019/2019-02-30.journal\n" actualJohn2Contents <- liftIO $ readTextFile john2 liftIO $ assertEqual "John2: The include file contents should be the journal files" expectedJohn2Contents actualJohn2Contents let expectedJohn3Contents = includePreamble <> "\n" <> "!include 2017-opening.journal\n" <> "!include 3-journal/2017/2017-11-30.journal\n" <> "!include 3-journal/2017/2017-12-30.journal\n" actualJohn3Contents <- liftIO $ readTextFile john3 liftIO $ assertEqual "John3: The include file contents should be the journal files" expectedJohn3Contents actualJohn3Contents let expectedJohn4Contents = includePreamble <> "\n" <> "!include 3-journal/2018/2018-01-30.journal\n" <> "!include 3-journal/2018/2018-02-30.journal\n" actualJohn4Contents <- liftIO $ readTextFile john4 liftIO $ assertEqual "John4: The include file contents should be the journal files" expectedJohn4Contents actualJohn4Contents let expectedJane7Contents = includePreamble <> "\n" <> "!include 3-journal/2018/2018-12-30.journal\n" actualJane7Contents <- liftIO $ readTextFile jane7 liftIO $ assertEqual "Jane7: The include file contents should be the journal files" expectedJane7Contents actualJane7Contents ) ) tests = TestList [testDirOrPwd, testExtraIncludesForFile, testIncludesPrePost, testIncludesOpeningClosing, testHiddenFiles, testFilterPaths, testWriteIncludeFiles]