1"""
2Tests for cmptest base test class.
3"""
4__copyright__ = "Copyright (C) 2014-2016  Martin Blais"
5__license__ = "GNU GPLv2"
6
7import datetime
8import re
9import textwrap
10import unittest
11
12from beancount.core import amount
13from beancount.core import data
14from beancount.core import position
15from beancount.core.number import MISSING
16from beancount.parser import booking
17from beancount.parser import cmptest
18from beancount.parser import parser
19
20
21class TestCompareTestFunctions(unittest.TestCase):
22
23    def test_read_string_or_entries(self):
24        with self.assertRaises(cmptest.TestError) as assctxt:
25            cmptest.read_string_or_entries("""
26
27              2014-01-27 * "UNION MARKET"
28                Liabilities:US:Amex:BlueCash    -22.02 USD
29                Expenses:Food:Grocery
30
31            """)
32        self.assertRegex(str(assctxt.exception), "may not use interpolation")
33
34    def test_local_booking(self):
35        fileloc = data.new_metadata('<local>', 0)
36        date = datetime.date.today()
37        txn = data.Transaction(
38            fileloc, date, '*', None, "Narration", data.EMPTY_SET, data.EMPTY_SET, [
39                data.Posting(
40                    'Assets:Something',
41                    MISSING,
42                    position.CostSpec(MISSING, None, MISSING, MISSING, MISSING, MISSING),
43                    MISSING, None, None)])
44        expected_txn = data.Transaction(
45            fileloc, date, '*', None, "Narration", data.EMPTY_SET, data.EMPTY_SET, [
46                data.Posting(
47                    'Assets:Something', None,
48                    position.Cost(None, None, None, None),
49                    None, None, None)])
50        actual_txn = cmptest._local_booking(txn)
51        self.assertEqual(actual_txn, expected_txn)
52
53        txn = data.Transaction(
54            fileloc, date, '*', None, "Narration", data.EMPTY_SET, data.EMPTY_SET, [
55                data.Posting(
56                    'Assets:Something',
57                    amount.Amount(MISSING, MISSING),
58                    position.CostSpec(MISSING, None, MISSING, MISSING, MISSING, MISSING),
59                    amount.Amount(MISSING, MISSING), None, None)])
60        expected_txn = data.Transaction(
61            fileloc, date, '*', None, "Narration", data.EMPTY_SET, data.EMPTY_SET, [
62                data.Posting(
63                    'Assets:Something',
64                    amount.Amount(None, None),
65                    position.Cost(None, None, None, None),
66                    amount.Amount(None, None), None, None)])
67        actual_txn = cmptest._local_booking(txn)
68        self.assertEqual(actual_txn, expected_txn)
69
70
71class TestTestCase(cmptest.TestCase):
72
73    ledger_text = textwrap.dedent("""
74
75      2014-01-27 * "UNION MARKET -  HOUSNEW YORK / 131129      GROCERY STORE"
76        Liabilities:US:Amex:BlueCash                                           -22.02 USD
77        Expenses:Food:Grocery                                                   22.02 USD
78
79      2014-01-30 * "T-MOBILE RECURNG PMTT-MOBILE / 1093555839 828422957        98006"
80        Liabilities:US:Amex:BlueCash                                           -73.64 USD
81        Expenses:Communications:Phone:TMobile                                   73.64 USD
82
83      2014-01-30 * "AMAZON SERVICES-KIND866-216-107 / PRYETZFD58N DIGITAL"
84        Liabilities:US:Amex:BlueCash                                           -12.74 USD
85        Expenses:Books                                                          12.74 USD
86
87      2014-02-01 * "LAFAYETTE STREET PARNEW YORK / 5869184     RESTAURANT" "Drinks w/ Jo"
88        Liabilities:US:Amex:BlueCash                                           -34.40 USD
89        Expenses:Food:Alcohol                                                   34.40 USD
90
91      2014-02-01 * "SPOTIFY USA         31630876101 / 2714214519  WWW.SPOTIFY.COM"
92        Liabilities:US:Amex:BlueCash                                            -9.99 USD
93        Expenses:Fun:Music                                                       9.99 USD
94
95      2014-02-01 * "BALABOOSTA          214 MULBERR / 2129667366"
96        Liabilities:US:Amex:BlueCash                                           -45.65 USD
97        Expenses:Food:Restaurant                                                45.65 USD
98
99    """)
100
101    def setUp(self):
102        entries, parse_errors, options_map = parser.parse_string(self.ledger_text)
103        self.entries, booking_errors = booking.book(entries, options_map)
104        self.assertFalse(parse_errors)
105        self.assertFalse(booking_errors)
106
107    def test_assertEqualEntries(self):
108        entries = self.entries
109        self.assertEqualEntries(entries, self.ledger_text)
110        self.assertEqualEntries(self.ledger_text, entries)
111
112        # Try out various modifications and ensure comparison fails.
113        mod_ledger_text, _ = re.subn(r' \* ', ' ! ', self.ledger_text, 1)
114        with self.assertRaises(AssertionError):
115            self.assertEqualEntries(entries, mod_ledger_text)
116
117        mod_ledger_text, _ = re.subn(
118            r'UNION MARKET', 'WHOLE FOODS MARKET', self.ledger_text, 1)
119        with self.assertRaises(AssertionError):
120            self.assertEqualEntries(entries, mod_ledger_text)
121
122        mod_ledger_text, _ = re.subn(r'2014-01-27', '2014-01-28', self.ledger_text, 1)
123        with self.assertRaises(AssertionError):
124            self.assertEqualEntries(entries, mod_ledger_text)
125
126        mod_ledger_text, _ = re.subn(r'73.64 USD', '73.65 USD', self.ledger_text, 1)
127        with self.assertRaises(AssertionError):
128            self.assertEqualEntries(entries, mod_ledger_text)
129
130        mod_ledger_text, _ = re.subn(r'73.64 USD', '73.64 CAD', self.ledger_text, 1)
131        with self.assertRaises(AssertionError):
132            self.assertEqualEntries(entries, mod_ledger_text)
133
134        mod_ledger_text, _ = re.subn(
135            r'Expenses:Food:Grocery', 'Expenses:Food:Groceries', self.ledger_text, 1)
136        with self.assertRaises(AssertionError):
137            self.assertEqualEntries(entries, mod_ledger_text)
138
139    def test_assertIncludesEntries(self):
140        entries = self.entries
141
142        # Check that non-strict inclusion succeeds.
143        self.assertIncludesEntries(entries, self.ledger_text)
144        self.assertIncludesEntries(self.ledger_text, entries)
145
146        first_two = '\n'.join(self.ledger_text.splitlines()[0:10])
147        self.assertIncludesEntries(first_two, entries)
148
149        last_three = '\n'.join(self.ledger_text.splitlines()[-13:])
150        self.assertIncludesEntries(last_three, entries)
151
152        with self.assertRaises(AssertionError):
153            self.assertIncludesEntries("""
154
155              2014-02-01 * "PLAY"
156                Liabilities:US:Amex:BlueCash     -9.99 USD
157                Expenses:Fun:Music                9.99 USD
158
159            """, entries)
160
161        self.assertIncludesEntries("""
162
163          2014-01-30 * "AMAZON SERVICES-KIND866-216-107 / PRYETZFD58N DIGITAL"
164            Liabilities:US:Amex:BlueCash        -12.74 USD
165            Expenses:Books                       12.74 USD
166
167        """, entries)
168
169
170    def test_assertExcludesEntries(self):
171        entries = self.entries
172
173        # Check that exclusion of all entries fails.
174        with self.assertRaises(AssertionError):
175            self.assertExcludesEntries(entries, self.ledger_text)
176        with self.assertRaises(AssertionError):
177            self.assertExcludesEntries(self.ledger_text, entries)
178
179        # Check that partial exclusion of all entries fails.
180        first_two = '\n'.join(self.ledger_text.splitlines()[0:10])
181        with self.assertRaises(AssertionError):
182            self.assertExcludesEntries(first_two, entries)
183
184        self.assertExcludesEntries("""
185
186          2014-02-01 * "PLAY"
187            Liabilities:US:Amex:BlueCash     -9.99 USD
188            Expenses:Fun:Music                9.99 USD
189
190        """, entries)
191
192        with self.assertRaises(AssertionError):
193            self.assertExcludesEntries("""
194
195              2014-01-30 * "AMAZON SERVICES-KIND866-216-107 / PRYETZFD58N DIGITAL"
196                Liabilities:US:Amex:BlueCash             -12.74 USD
197                Expenses:Books                            12.74 USD
198
199            """, entries)
200
201
202if __name__ == '__main__':
203    unittest.main()
204