1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE ScopedTypeVariables #-}
6 import Control.Applicative (Applicative(..), (<*))
7 import Control.Arrow (right)
8 import Control.Monad.IO.Class (MonadIO(..))
10 import Data.Char (Char)
11 import qualified Data.Char as Char
13 import Data.Decimal (DecimalRaw(..))
14 import Data.Either (either, rights)
15 import qualified Data.Foldable as Foldable
16 import Data.Function (($), (.), id, const, flip)
17 import Data.Functor ((<$>))
18 import Data.Functor.Identity (Identity(..))
19 import qualified Data.List as List
20 import qualified Data.List.NonEmpty as NonEmpty
21 import qualified Data.Map.Strict as Map
22 import Data.Maybe (Maybe(..))
23 import Data.Monoid (Monoid(..), (<>))
24 import qualified Data.NonNull as NonNull
25 import qualified Data.TreeMap.Strict as TreeMap
26 import Data.Ord (Ord(..))
27 import Data.String (String)
28 import Data.Text (Text)
29 import qualified Data.Text as Text
30 import qualified Data.Time.Calendar as Time
31 import qualified Data.Time.LocalTime as Time
32 import Data.Tuple (snd)
33 import Prelude (error)
35 import Test.Tasty.HUnit
36 import qualified Text.Parsec as R hiding
49 import qualified Text.Parsec.Combinator.CorrectSourcePosWithTab as R
50 import qualified Text.Parsec.Error.Custom as R
51 import qualified Hcompta.LCC.Lib.Parsec as R
52 import qualified Text.Parsec.Pos as R
53 import Text.Show (Show(..))
55 import qualified Hcompta as H
56 import qualified Hcompta.LCC as LCC
58 test :: String -> Assertion -> TestTree
59 test = testCase . elide . Foldable.foldMap escapeChar
61 escapeChar :: Char -> String
62 escapeChar c | Char.isPrint c = [c]
63 escapeChar c = Char.showLitChar c ""
65 elide :: String -> String
66 elide s | List.length s > 42 = List.take 42 s List.++ ['…']
69 account :: [Text] -> LCC.Account
70 account = LCC.Account . NonNull.impureNonNull . (LCC.Name <$>)
72 tag :: [Text] -> Text -> LCC.Tag
74 (LCC.Tag_Path $ NonNull.impureNonNull (LCC.Name <$> p))
77 tags :: [([Text], Text)] -> LCC.Tags
80 Map.fromListWith (flip mappend) $
82 (LCC.Tag_Path $ NonNull.impureNonNull (LCC.Name <$> p), [LCC.Tag_Value v])
84 amounts :: [(Text, LCC.Quantity)] -> LCC.Amounts
91 postings :: [LCC.Posting] -> LCC.Postings
94 Map.fromListWith (flip mappend) $
96 (LCC.posting_account p, [p])
98 comments :: [Text] -> [LCC.Comment]
99 comments = (LCC.Comment <$>)
102 tests = testGroup "Read"
103 [ {-testGroup "read_date" $
104 (let (==>) (txt::Text) =
105 test (Text.unpack txt) .
106 (@?=) (rights [R.runParserWithError
107 (LCC.read_date id Nothing <* R.eof) () "" txt]) in
109 [ Time.zonedTimeToUTC $
112 (Time.fromGregorian 2000 01 01)
113 (Time.TimeOfDay 0 0 0))
115 , "2000/01/01" ==> []
116 , "2000-01-01_12:34" ==>
117 [ Time.zonedTimeToUTC $
120 (Time.fromGregorian 2000 01 01)
121 (Time.TimeOfDay 12 34 0))
123 , "2000-01-01_12:34:56" ==>
124 [ Time.zonedTimeToUTC $
127 (Time.fromGregorian 2000 01 01)
128 (Time.TimeOfDay 12 34 56))
130 , "2000-01-01_12:34_CET" ==>
131 [ Time.zonedTimeToUTC $
134 (Time.fromGregorian 2000 01 01)
135 (Time.TimeOfDay 12 34 0))
136 (Time.TimeZone 60 True "CET") ]
137 , "2000-01-01_12:34+01:30" ==>
138 [ Time.zonedTimeToUTC $
141 (Time.fromGregorian 2000 01 01)
142 (Time.TimeOfDay 12 34 0))
143 (Time.TimeZone 90 False "+01:30") ]
144 , "2000-01-01_12:34:56_CET" ==>
145 [ Time.zonedTimeToUTC $
148 (Time.fromGregorian 2000 01 01)
149 (Time.TimeOfDay 12 34 56))
150 (Time.TimeZone 60 True "CET") ]
151 , "2001-02-29" ==> []
153 (let (==>) (txt::Text, def) =
154 test (Text.unpack txt) .
155 (@?=) (rights [R.runParserWithError
156 (LCC.read_date id (Just def) <* R.eof) () "" txt]) in
157 [ ("01-01", 2000) ==>
158 [ Time.zonedTimeToUTC $
161 (Time.fromGregorian 2000 01 01)
162 (Time.TimeOfDay 0 0 0))
165 , testGroup "read_account_section" $
166 let (==>) (txt::Text) b =
167 test (Text.unpack txt) $
168 (@?=) (rights [R.runParser
169 (LCC.read_account_section <* R.eof) () "" txt])
170 [LCC.Name txt | b] in
196 (LCC.read_account_section)
201 , testGroup "read_account" $
202 let (==>) (txt::Text) expected =
203 test (Text.unpack txt) $
204 (@?=) (rights [R.runParser
205 (LCC.read_account <* R.eof) () "" txt])
206 (account <$> expected)
214 , "/A/B" ==> [ ["A", "B"] ]
215 , "/A/B/C" ==> [ ["A", "B","C"] ]
216 , "/Aa/Bbb/Cccc" ==> [ ["Aa", "Bbb", "Cccc"] ]
217 , "/A a / B b b / C c c c" ==> []
220 , "/A/B/(C)" ==> [ ["A", "B", "(C)"] ]
222 , testGroup "read_amount" $
223 let (==>) (txt::Text) =
224 test (Text.unpack txt) .
225 (@?=) (rights [R.runParser
226 (LCC.read_amount <* R.eof) () "" txt]) in
230 , LCC.amount { LCC.amount_quantity = Decimal 0 0 } )]
233 , LCC.amount { LCC.amount_quantity = Decimal 0 0 } )]
235 [( mempty { LCC.amount_style_fractioning = Just '.' }
236 , LCC.amount { LCC.amount_quantity = Decimal 0 0 } )]
238 [( mempty { LCC.amount_style_fractioning = Just '.' }
239 , LCC.amount { LCC.amount_quantity = Decimal 1 0 } )]
241 [( mempty { LCC.amount_style_fractioning = Just ',' }
242 , LCC.amount { LCC.amount_quantity = Decimal 0 0 } )]
244 [( mempty { LCC.amount_style_fractioning = Just ',' }
245 , LCC.amount { LCC.amount_quantity = Decimal 1 0 } )]
249 [( mempty { LCC.amount_style_fractioning = Just '.' }
250 , LCC.amount { LCC.amount_quantity = Decimal 1 0 } )]
252 [( mempty { LCC.amount_style_fractioning = Just '.' }
253 , LCC.amount { LCC.amount_quantity = Decimal 2 0 } )]
255 [( mempty { LCC.amount_style_fractioning = Just ',' }
256 , LCC.amount { LCC.amount_quantity = Decimal 1 0 } )]
258 [( mempty { LCC.amount_style_fractioning = Just ',' }
259 , LCC.amount { LCC.amount_quantity = Decimal 2 0 } )]
261 [( mempty { LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '_' [1] }
262 , LCC.amount { LCC.amount_quantity = Decimal 0 0 } )]
264 [( mempty { LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '_' [2] }
265 , LCC.amount { LCC.amount_quantity = Decimal 0 0 } )]
268 { LCC.amount_style_fractioning = Just '.'
269 , LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping ',' [3] }
270 , LCC.amount { LCC.amount_quantity = Decimal 2 0 } )]
273 { LCC.amount_style_fractioning = Just ','
274 , LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '.' [3] }
275 , LCC.amount { LCC.amount_quantity = Decimal 2 0 } )]
278 { LCC.amount_style_fractioning = Just '.'
279 , LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping ',' [3] }
280 , LCC.amount { LCC.amount_quantity = Decimal 2 100000 } )]
283 { LCC.amount_style_fractioning = Just ','
284 , LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '.' [3] }
285 , LCC.amount { LCC.amount_quantity = Decimal 2 100000 } )]
291 , LCC.amount { LCC.amount_quantity = Decimal 0 123 } )]
293 [( mempty { LCC.amount_style_fractioning = Just '.' }
294 , LCC.amount { LCC.amount_quantity = Decimal 1 12 } )]
296 [( mempty { LCC.amount_style_fractioning = Just ',' }
297 , LCC.amount { LCC.amount_quantity = Decimal 1 12 } )]
299 [( mempty { LCC.amount_style_fractioning = Just '.' }
300 , LCC.amount { LCC.amount_quantity = Decimal 2 1234 } )]
302 [( mempty { LCC.amount_style_fractioning = Just ',' }
303 , LCC.amount { LCC.amount_quantity = Decimal 2 1234 } )]
305 [( mempty { LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '_' [1] }
306 , LCC.amount { LCC.amount_quantity = Decimal 0 12 } )]
308 [( mempty { LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '_' [2] }
309 , LCC.amount { LCC.amount_quantity = Decimal 0 123 } )]
311 [( mempty { LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '_' [3, 2] }
312 , LCC.amount { LCC.amount_quantity = Decimal 0 123456 } )]
313 , "1_23_456,7890_12345_678901" ==>
315 { LCC.amount_style_fractioning = Just ','
316 , LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '_' [3, 2]
317 , LCC.amount_style_grouping_fractional = Just $ LCC.Amount_Style_Grouping '_' [4, 5, 6] }
318 , LCC.amount { LCC.amount_quantity = Decimal 15 123456789012345678901 } )]
319 , "1_23_456.7890_12345_678901" ==>
321 { LCC.amount_style_fractioning = Just '.'
322 , LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '_' [3, 2]
323 , LCC.amount_style_grouping_fractional = Just $ LCC.Amount_Style_Grouping '_' [4, 5, 6] }
324 , LCC.amount { LCC.amount_quantity = Decimal 15 123456789012345678901 } )]
325 , "1,23,456.7890_12345_678901" ==>
327 { LCC.amount_style_fractioning = Just '.'
328 , LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping ',' [3, 2]
329 , LCC.amount_style_grouping_fractional = Just $ LCC.Amount_Style_Grouping '_' [4, 5, 6] }
330 , LCC.amount { LCC.amount_quantity = Decimal 15 123456789012345678901 } )]
331 , "1.23.456,7890_12345_678901" ==>
333 { LCC.amount_style_fractioning = Just ','
334 , LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '.' [3, 2]
335 , LCC.amount_style_grouping_fractional = Just $ LCC.Amount_Style_Grouping '_' [4, 5, 6] }
336 , LCC.amount { LCC.amount_quantity = Decimal 15 123456789012345678901 } )]
337 , "123456_78901_2345.678_90_1" ==>
339 { LCC.amount_style_fractioning = Just '.'
340 , LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '_' [4, 5, 6]
341 , LCC.amount_style_grouping_fractional = Just $ LCC.Amount_Style_Grouping '_' [3, 2] }
342 , LCC.amount { LCC.amount_quantity = Decimal 6 123456789012345678901 } )]
345 { LCC.amount_style_unit_side = Just LCC.Amount_Style_Side_Left
346 , LCC.amount_style_unit_spaced = Just False }
348 { LCC.amount_quantity = Decimal 0 1
349 , LCC.amount_unit = "$" } )]
352 { LCC.amount_style_unit_side = Just LCC.Amount_Style_Side_Right
353 , LCC.amount_style_unit_spaced = Just False }
355 { LCC.amount_quantity = Decimal 0 1
356 , LCC.amount_unit = "$" } )]
359 { LCC.amount_style_unit_side = Just LCC.Amount_Style_Side_Left
360 , LCC.amount_style_unit_spaced = Just True }
362 { LCC.amount_quantity = Decimal 0 1
363 , LCC.amount_unit = "$" } )]
366 { LCC.amount_style_unit_side = Just LCC.Amount_Style_Side_Right
367 , LCC.amount_style_unit_spaced = Just True }
369 { LCC.amount_quantity = Decimal 0 1
370 , LCC.amount_unit = "$" } )]
373 { LCC.amount_style_unit_side = Just LCC.Amount_Style_Side_Left
374 , LCC.amount_style_unit_spaced = Just False }
376 { LCC.amount_quantity = Decimal 0 (-1)
377 , LCC.amount_unit = "$" } )]
380 { LCC.amount_style_unit_side = Just LCC.Amount_Style_Side_Left
381 , LCC.amount_style_unit_spaced = Just False }
383 { LCC.amount_quantity = Decimal 0 1
384 , LCC.amount_unit = "4 2" } )]
387 { LCC.amount_style_unit_side = Just LCC.Amount_Style_Side_Right
388 , LCC.amount_style_unit_spaced = Just False }
390 { LCC.amount_quantity = Decimal 0 1
391 , LCC.amount_unit = "4 2" } )]
394 { LCC.amount_style_fractioning = Just ','
395 , LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '.' [3]
396 , LCC.amount_style_unit_side = Just LCC.Amount_Style_Side_Left
397 , LCC.amount_style_unit_spaced = Just False }
399 { LCC.amount_quantity = Decimal 2 100000
400 , LCC.amount_unit = "$" } )]
403 { LCC.amount_style_fractioning = Just ','
404 , LCC.amount_style_grouping_integral = Just $ LCC.Amount_Style_Grouping '.' [3]
405 , LCC.amount_style_unit_side = Just LCC.Amount_Style_Side_Right
406 , LCC.amount_style_unit_spaced = Just False }
408 { LCC.amount_quantity = Decimal 2 100000
409 , LCC.amount_unit = "$" } )]
411 , testGroup "read_comment" $
412 let (==>) (txt::Text, end) expected =
413 test (Text.unpack txt) $
414 (@?=) (rights [R.runParser
415 (LCC.read_comment <* end) () "" txt])
416 (LCC.Comment <$> expected) in
417 [ ("; some comment", R.eof) ==> ["some comment"]
418 , ("; some comment \n", R.string " \n" <* R.eof) ==> [ "some comment" ]
419 , ("; some comment \r\n", R.string " \r\n" <* R.eof) ==> [ "some comment" ]
421 , testGroup "read_comments" $
422 let (==>) (txt::Text, end) expected =
423 test (Text.unpack txt) $
424 (@?=) (rights [R.runParser
425 (LCC.read_comments <* end) () "" txt])
426 ((LCC.Comment <$>) <$> expected) in
427 [ ("; some comment\n ; some other comment", R.eof) ==> [ ["some comment", "some other comment"] ]
428 , ("; some comment \n", R.string " \n" <* R.eof) ==> [ ["some comment"] ]
430 , testGroup "read_transaction_tag" $
431 let (==>) (txt::Text, end) =
432 test (Text.unpack txt) .
433 (@?=) ((\(LCC.Transaction_Tag t) -> t) <$>
435 (LCC.read_transaction_tag <* end) () "" txt]) in
436 [ ("#Name" , R.eof) ==> [ tag ["Name"] "" ]
437 , ("#Name:" , R.eof) ==> []
438 , ("#Name:name" , R.eof) ==> [ tag ["Name", "name"] "" ]
439 , ("#Name=Value" , R.eof) ==> [ tag ["Name"] "Value" ]
440 , ("#Name = Value" , R.eof) ==> [ tag ["Name"] "Value" ]
441 , ("#Name=Value\n" , R.string "\n" <* R.eof) ==> [ tag ["Name"] "Value" ]
442 , ("#Name=Val ue" , R.eof) ==> [ tag ["Name"] "Val ue" ]
443 , ("#Name=," , R.eof) ==> [ tag ["Name"] "," ]
444 , ("#Name=Val,ue" , R.eof) ==> [ tag ["Name"] "Val,ue" ]
445 , ("#Name=Val,ue:" , R.eof) ==> [ tag ["Name"] "Val,ue:" ]
446 , ("#Name=Val,ue :", R.eof) ==> [ tag ["Name"] "Val,ue :" ]
448 , testGroup "read_posting" $
449 let (==>) (txt::Text) =
451 ( LCC.context_read (const ()) LCC.journal
452 ::LCC.Context_Read () ()) in
453 test (Text.unpack txt) .
456 (const []) -- (error . show)
459 (LCC.read_posting <* R.eof) context_read "" txt) .
460 ((\p -> p { LCC.posting_sourcepos = R.newPos "" 1 1 }) <$>) in
461 [ "/A/B/C" ==> [LCC.posting (account ["A", "B", "C"])]
462 , "/A/B/C $1" ==> [(LCC.posting (account ["A", "B", "C"]))
463 { LCC.posting_amounts = amounts [("$", 1)] }]
464 , "/A/B/C $1" ==> [(LCC.posting (account ["A", "B", "C"]))
465 { LCC.posting_amounts = amounts [("$", 1)] }]
466 , "/A/B/C 1€" ==> [(LCC.posting (account ["A", "B", "C"]))
467 { LCC.posting_amounts = amounts [("€", 1)] }]
468 , "/A/B/C $1; some comment" ==> [(LCC.posting (account ["A", "B", "C"]))
469 { LCC.posting_amounts = amounts [("$", 1)]
470 , LCC.posting_comments = comments ["some comment"] }]
471 , "/A/B/C; not a comment" ==> []
472 , "/A/B/C ; some comment" ==> [(LCC.posting (account ["A", "B", "C"]))
473 { LCC.posting_amounts = amounts []
474 , LCC.posting_comments = comments ["some comment"] }]
475 , "/A/B/C ; some comment\n ; some other comment" ==>
476 [(LCC.posting (account ["A", "B", "C"]))
477 { LCC.posting_amounts = amounts []
478 , LCC.posting_comments = comments ["some comment", "some other comment"] }]
479 , "/A/B/C $1 ; some comment" ==>
480 [(LCC.posting (account ["A", "B", "C"]))
481 { LCC.posting_amounts = amounts [("$", 1)]
482 , LCC.posting_comments = comments ["some comment"] }]
484 [(LCC.posting (account ["A", "B", "C"]))
485 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "V") ] }]
486 , "/A/B/C #N:O=V" ==>
487 [(LCC.posting (account ["A", "B", "C"]))
488 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N", "O"], "V") ] }]
489 , "/A/B/C #N=Val;ue" ==>
490 [(LCC.posting (account ["A", "B", "C"]))
491 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "Val;ue") ] }]
492 , "/A/B/C #N=Val#ue" ==>
493 [(LCC.posting (account ["A", "B", "C"]))
494 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "Val#ue") ] }]
495 , "/A/B/C #N=V ; not a comment" ==>
496 [(LCC.posting (account ["A", "B", "C"]))
497 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "V ; not a comment") ] }]
498 , "/A/B/C #N=V #O" ==>
499 [(LCC.posting (account ["A", "B", "C"]))
500 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "V #O") ] }]
501 , "/A/B/C #N#O" ==> []
502 , "/A/B/C #N; #O" ==>
503 [(LCC.posting (account ["A", "B", "C"]))
504 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N;"], ""), (["O"], "") ] }]
506 [(LCC.posting (account ["A", "B", "C"]))
507 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], ""), (["O"], "") ] }]
508 , "/A/B/C \n #N=V" ==>
509 [(LCC.posting (account ["A", "B", "C"]))
510 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "V") ] }]
511 , "/A/B/C ; some comment\n #N=V" ==>
512 [(LCC.posting (account ["A", "B", "C"]))
513 { LCC.posting_comments = comments ["some comment"]
514 , LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "V") ] }]
515 , "/A/B/C ; some comment\n #N=V v\n #N2=V2 v2" ==>
516 [(LCC.posting (account ["A", "B", "C"]))
517 { LCC.posting_comments = comments ["some comment"]
518 , LCC.posting_tags = LCC.Posting_Tags $ tags
520 , (["N2"], "V2 v2") ] }]
521 , "/A/B/C\n #N=V\n #N=V2" ==>
522 [(LCC.posting (account ["A", "B", "C"]))
523 { LCC.posting_tags = LCC.Posting_Tags $ tags
527 , "/A/B/C\n #N=V\n #N2=V" ==>
528 [(LCC.posting (account ["A", "B", "C"]))
529 { LCC.posting_tags = LCC.Posting_Tags $ tags
534 , testGroup "read_transaction" $
535 let (==>) (txt::Text) =
537 ( LCC.context_read (const ()) LCC.journal
538 ::LCC.Context_Read () ()) in
539 test (Text.unpack txt) .
541 either (error . show) pure $
543 (LCC.read_transaction <* R.newline <* R.eof) context_read "" txt) .
544 ((\t -> t { LCC.transaction_sourcepos = R.newPos "" 1 1 }) <$>) in
546 [ "2000-01-01 some wording"
551 { LCC.transaction_dates=
552 (`NonNull.ncons` []) $
553 Time.zonedTimeToUTC $
556 (Time.fromGregorian 2000 01 01)
557 (Time.TimeOfDay 0 0 0))
559 , LCC.transaction_wording="some wording"
560 , LCC.transaction_postings = postings
561 [ (LCC.posting (account ["A", "B", "C"]))
562 { LCC.posting_amounts = amounts [ ("$", 1) ]
563 , LCC.posting_sourcepos = R.newPos "" 2 2 }
564 , (LCC.posting (account ["a", "b", "c"]))
565 { LCC.posting_amounts = amounts [ ("$", -1) ]
566 , LCC.posting_sourcepos = R.newPos "" 3 2 }
570 [ "2000-01-01 some wording ; not a comment"
571 , "; some other;comment"
572 , " ; some last comment"
577 { LCC.transaction_comments = comments
578 [ "some other;comment"
579 , "some last comment"
581 , LCC.transaction_dates=
582 (`NonNull.ncons` []) $
583 Time.zonedTimeToUTC $
586 (Time.fromGregorian 2000 01 01)
587 (Time.TimeOfDay 0 0 0))
589 , LCC.transaction_wording="some wording ; not a comment"
590 , LCC.transaction_postings = postings
591 [ (LCC.posting (account ["A", "B", "C"]))
592 { LCC.posting_amounts = amounts [ ("$", 1) ]
593 , LCC.posting_sourcepos = R.newPos "" 4 2 }
594 , (LCC.posting (account ["a", "b", "c"]))
595 { LCC.posting_amounts = amounts [ ("$", -1) ]
596 , LCC.posting_sourcepos = R.newPos "" 5 2 } ] }]
598 , testGroup "read_journal" $
599 let (==>) (lines::[Text]) e =
600 let txt = Text.unlines lines in
601 test (Text.unpack txt) $ do
604 right (\j -> j{LCC.journal_last_read_time=H.date_epoch}) <$>
605 R.runParserTWithError
606 (LCC.read_journal "" <* R.eof)
607 ( LCC.context_read id LCC.journal
608 ::LCC.Context_Read (LCC.Charted LCC.Transaction)
609 [LCC.Charted LCC.Transaction])
611 (@?=) (rights [res]) e in
612 [ [ "2000-01-01 1° wording"
617 { LCC.journal_content =
618 (LCC.Charted mempty <$>) $
620 { LCC.transaction_dates =
621 (`NonNull.ncons` []) $
622 Time.zonedTimeToUTC $
625 (Time.fromGregorian 2000 01 01)
626 (Time.TimeOfDay 0 0 0))
628 , LCC.transaction_wording="1° wording"
629 , LCC.transaction_postings = postings
630 [ (LCC.posting (account ["A", "B", "C"]))
631 { LCC.posting_amounts = amounts [ ("$", 1) ]
632 , LCC.posting_sourcepos = R.newPos "" 2 2
634 , (LCC.posting (account ["a", "b", "c"]))
635 { LCC.posting_amounts = amounts [ ("$", -1) ]
636 , LCC.posting_sourcepos = R.newPos "" 3 2
639 , LCC.transaction_sourcepos = R.newPos "" 1 1
642 , LCC.journal_files = [""]
643 , LCC.journal_amount_styles = LCC.Amount_Styles $ Map.fromList
646 { LCC.amount_style_unit_side = Just LCC.Amount_Style_Side_Left
647 , LCC.amount_style_unit_spaced = Just False }
652 , [ "2000-01-01 1° wording"
655 , "2000-01-02 2° wording"
660 { LCC.journal_content =
661 (LCC.Charted mempty <$>) $
663 { LCC.transaction_dates =
664 (`NonNull.ncons` []) $
665 Time.zonedTimeToUTC $
668 (Time.fromGregorian 2000 01 02)
669 (Time.TimeOfDay 0 0 0))
671 , LCC.transaction_wording = "2° wording"
672 , LCC.transaction_postings = postings
673 [ (LCC.posting (account ["A", "B", "C"]))
674 { LCC.posting_amounts = amounts [ ("$", 1) ]
675 , LCC.posting_sourcepos = R.newPos "" 5 2
677 , (LCC.posting (account ["x", "y", "z"]))
678 { LCC.posting_amounts = amounts [ ("$", -1) ]
679 , LCC.posting_sourcepos = R.newPos "" 6 2
682 , LCC.transaction_sourcepos = R.newPos "" 4 1
685 { LCC.transaction_dates =
686 (`NonNull.ncons` []) $
687 Time.zonedTimeToUTC $
690 (Time.fromGregorian 2000 01 01)
691 (Time.TimeOfDay 0 0 0))
693 , LCC.transaction_wording="1° wording"
694 , LCC.transaction_postings = postings
695 [ (LCC.posting (account ["A", "B", "C"]))
696 { LCC.posting_amounts = amounts [ ("$", 1) ]
697 , LCC.posting_sourcepos = R.newPos "" 2 2
699 , (LCC.posting (account ["a", "b", "c"]))
700 { LCC.posting_amounts = amounts [ ("$", -1) ]
701 , LCC.posting_sourcepos = R.newPos "" 3 2
704 , LCC.transaction_sourcepos = R.newPos "" 1 1
707 , LCC.journal_files = [""]
708 , LCC.journal_amount_styles = LCC.Amount_Styles $ Map.fromList
711 { LCC.amount_style_unit_side = Just LCC.Amount_Style_Side_Left
712 , LCC.amount_style_unit_spaced = Just False }
718 ,-} testGroup "read_chart" $
719 let (==>) (lines::[Text]) expected =
720 let txt = Text.unlines lines in
721 let context_read :: LCC.Context_Read () () =
722 LCC.context_read (const ()) LCC.journal in
723 test (Text.unpack txt) $
724 let res = runIdentity $
725 ((LCC.journal_chart . LCC.context_read_journal . snd <$>) <$>) $
726 R.runParserTWithError
727 (R.and_state (LCC.read_chart <* R.eof))
728 context_read "" txt in
729 rights [res] @?= expected in
730 -- show res @?= show expected in
731 let acct_path = NonEmpty.fromList . (LCC.Name <$>) in
732 let acct_tags = LCC.Account_Tags . tags in
737 { LCC.chart_accounts = TreeMap.from_List mappend
738 [ (acct_path ["A", "B", "C"], acct_tags [])
739 , (acct_path ["a", "b", "c"], acct_tags [])
741 , LCC.chart_anchors = Map.empty
751 { LCC.chart_accounts = TreeMap.from_List mappend
752 [ (acct_path ["A", "B", "C"], acct_tags [(["N0", "N1"], "")])
753 , (acct_path ["a", "b", "c"], acct_tags
754 [ (["N0", "N1"], "V0")
755 , (["N0", "N1"], "V1") ])
757 , LCC.chart_anchors = Map.empty