packages feed

hledger-flow-0.18.0: test/CSVImport/ImportHelperTurtleTests.hs

{-# LANGUAGE OverloadedStrings #-}

module CSVImport.ImportHelperTurtleTests where

import Control.Concurrent.STM (newTChanIO)
import Data.Either (lefts)
import qualified Data.Map.Strict as Map
import qualified Data.Text as T
import Hledger.Flow.Common (includeYears')
import Hledger.Flow.Import.ImportHelpersTurtle (includePreamble, toIncludeFiles, toIncludeLine, yearsIncludeMap)
import qualified Path
import System.FilePath ((</>))
import Test.HUnit
import TestHelpers (defaultOpts, withTestDir)

testIncludeYears :: Test
testIncludeYears =
  TestCase
    ( do
        let txterr = "Some text without years"
        let expectederr = ["Unable to extract years from the following text:", txterr, "Errors:"]
        let actualerr = case lefts [includeYears' txterr] of
              (errTxt : _) -> (init . T.lines) errTxt
              [] -> []
        assertEqual "Get a list of years from an include file - error case" expectederr actualerr

        let txt1 =
              "### Generated by hledger-flow - DO NOT EDIT ###\n\n"
                <> "include import/2014-include.journal\n"
                <> "include import/2015-include.journal\n"
                <> "include import/2016-include.journal\n"
                <> "include import/2017-include.journal\n"
                <> "include import/2018-include.journal\n"
                <> "include import/2019-include.journal"

        let expected1 = Right [2014 .. 2019]
        let actual1 = includeYears' txt1
        assertEqual "Get a list of years from an include file - success case 1" expected1 actual1

        let txt2 = "include 2019-include.journal"

        let expected2 = Right [2019]
        let actual2 = includeYears' txt2
        assertEqual "Get a list of years from an include file - success case 2" expected2 actual2
    )

testToIncludeLine :: Test
testToIncludeLine =
  TestCase
    ( do
        let expected = "include file1.journal"
        let relativeWithTrailingSlash = toIncludeLine "./base/dir/" "./base/dir/file1.journal"
        assertEqual "Include line - relative base dir with trailing slash" expected relativeWithTrailingSlash

        let relativeNoTrailingSlash = toIncludeLine "./base/dir" "./base/dir/file1.journal"
        assertEqual "Include line - relative base dir without a trailing slash" expected relativeNoTrailingSlash

        let absoluteWithTrailingSlash = toIncludeLine "/base/dir/" "/base/dir/file1.journal"
        assertEqual "Include line - absolute base dir with trailing slash" expected absoluteWithTrailingSlash

        let absoluteNoTrailingSlash = toIncludeLine "/base/dir" "/base/dir/file1.journal"
        assertEqual "Include line - absolute base dir without a trailing slash" expected absoluteNoTrailingSlash
    )

testIncludeRendering :: Test
testIncludeRendering = TestCase $ withTestDir $ \base -> do
  let account = Path.toFilePath base </> "import/john/bank/checking"
      year2019 = account </> "2019-include.journal"
      year2020 = account </> "2020-include.journal"
      first = account </> "3-journal/2019/first.journal"
      lastJournal = account </> "3-journal/2019/last.journal"
  assertEqual "years share their account index"
    (Map.singleton (account </> "all-years.journal") [year2019, year2020])
    (yearsIncludeMap [year2019, year2020])
  ch <- newTChanIO
  rendered <- toIncludeFiles (defaultOpts base) ch
    (Map.singleton year2019 [lastJournal, first, lastJournal])
  assertEqual "sort and deduplicate relative include lines"
    (Map.singleton year2019 (includePreamble <> "\ninclude 3-journal/2019/first.journal\ninclude 3-journal/2019/last.journal\n")) rendered

tests :: Test
tests = TestList [testIncludeYears, testToIncludeLine, testIncludeRendering]