__copyright__ = 'Copyright (c) 2020 Kristóf Marussy <kristof@marussy.com>'
__license__ = 'GNU GPLv2'
import unittest
from beancount.loader import load_doc
from beancount.parser import cmptest
import pytest
class TestClosingBalance(cmptest.TestCase):
@load_doc()
def test_use_template_simple(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-01-01 * "Eating out" #tag ^link
template: "eating-out"
Assets:Checking 25 USD
Expenses:Food -25 USD
2020-03-15 custom "template-use" "eating-out"
2020-04-12 custom "template-use" "eating-out"
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.closing_balance"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-03-15 * "Eating out" #tag ^link ^template_eating-out
template: "eating-out"
Assets:Checking 25 USD
Expenses:Food -25 USD
2020-04-12 * "Eating out" #tag ^link ^template_eating-out
template: "eating-out"
Assets:Checking 25 USD
Expenses:Food -25 USD
''', entries)
@load_doc()
def test_use_template_metadata(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-01-01 * "Eating out" #tag ^link
template: "eating-out"
meta1: "data"
meta2: TRUE
Assets:Checking 25 USD
Expenses:Food -25 USD
2020-03-15 custom "template-use" "eating-out"
meta1: "foo"
meta3: 3.14
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.closing_balance"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-03-15 * "Eating out" #tag ^link ^template_eating-out
template: "eating-out"
meta1: "foo"
meta2: TRUE
meta3: 2.14
Assets:Checking 25 USD
Expenses:Food -25 USD
''', entries)
@load_doc()
def test_use_template_scaled(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-01-01 * "Eating out" #tag ^link
template: "eating-out"
Assets:Checking 1 USD
Expenses:Food -1 USD
2020-03-15 custom "template-use" "eating-out" 25
2020-04-12 custom "template-use" "eating-out" 27
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.closing_balance"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-03-15 * "Eating out" #tag ^link ^template_eating-out
template: "eating-out"
Assets:Checking 25 USD
Expenses:Food -25 USD
2020-04-12 * "Eating out" #tag ^link ^template_eating-out
template: "eating-out"
Assets:Checking 27 USD
Expenses:Food -27 USD
''', entries)
@load_doc()
def test_use_template_overwritten(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-01-01 open Expenses:Tax
2020-04-01 * "Eating out" #tag ^link
template: "eating-out"
Assets:Checking 1.10 USD
Expenses:Food -1 USD
Expenses:Tax -0.10 USD
2020-01-01 * "Eating out" #tag ^link
template: "eating-out"
Assets:Checking 1 USD
Expenses:Food -1 USD
2020-03-15 custom "template-use" "eating-out" 25
2020-04-12 custom "template-use" "eating-out" 27
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.closing_balance"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-01-01 open Expenses:Tax
2020-03-15 * "Eating out" #tag ^link ^template_eating-out
template: "eating-out"
Assets:Checking 25 USD
Expenses:Food -25 USD
2020-04-12 * "Eating out" #tag ^link ^template_eating-out
template: "eating-out"
Assets:Checking 29.70 USD
Expenses:Food -27 USD
Expenses:Tax -2.70 USD
''', entries)
@load_doc(expect_errors=True)
def test_invalid_name(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-01-01 * "Eating out"
template: TRUE
Assets:Checking 25 USD
Expenses:Food -25 USD
'''
self.assertRegex(errors[0].message, "^template must be a string")
@pytest.mark.xfail(reason="Empty custom directive fails in beancount.ops.pad")
@load_doc(expect_errors=True)
def test_use_missing_name(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-01-01 * "Eating out"
template: "eating-out"
Assets:Checking 25 USD
Expenses:Food -25 USD
2020-03-15 custom "template-use"
'''
self.assertRegex(errors[0].message, "^Template name missing")
@load_doc(expect_errors=True)
def test_use_too_many_arguments(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-01-01 * "Eating out"
template: "eating-out"
Assets:Checking 25 USD
Expenses:Food -25 USD
2020-03-15 custom "template-use" "eating-out" 2 "another"
'''
self.assertRegex(errors[0].message, "^Too many template-use arguments")
@load_doc(expect_errors=True)
def test_use_invalid_name(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-03-15 custom "template-use" TRUE
'''
self.assertRegex(errors[0].message, "^Template name must be a string")
@load_doc(expect_errors=True)
def test_use_unknown(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-03-15 custom "template-use" "taxi"
'''
self.assertRegex(errors[0].message, "^Unknown template")
@load_doc(expect_errors=True)
def test_use_invalid_scale_factor(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-01-01 * "Eating out"
template: "eating-out"
Assets:Checking 25 USD
Expenses:Food -25 USD
2020-03-15 custom "template-use" "eating-out" TRUE
'''
self.assertRegex(errors[0].message, "^Invalid scale factor")
@load_doc(expect_errors=True)
def test_use_zero_scale_factor(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-01-01 * "Eating out"
template: "eating-out"
Assets:Checking 25 USD
Expenses:Food -25 USD
2020-03-15 custom "template-use" "eating-out" 0.0
'''
self.assertRegex(errors[0].message, "^Scale factor must not be 0")
@load_doc(expect_errors=True)
def test_template_delete(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-01-01 * "Eating out"
template: "eating-out"
Assets:Checking 25 USD
Expenses:Food -25 USD
2020-03-01 custom "template-delete" "eating-out"
2020-03-15 custom "template-use" "eating-out"
'''
self.assertRegex(errors[0].message, "^Unknown template")
@pytest.mark.xfail(reason="Empty custom directive fails in beancount.ops.pad")
@load_doc(expect_errors=True)
def test_template_delete_too_few_arguments(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-03-01 custom "template-delete"
'''
self.assertRegex(errors[0].message, "^template-delete takes a single argument")
@load_doc(expect_errors=True)
def test_template_delete_too_many_arguments(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-01-01 open Assets:Checking
2020-01-01 open Expenses:Food
2020-01-01 * "Eating out"
template: "eating-out"
Assets:Checking 25 USD
Expenses:Food -25 USD
2020-03-01 custom "template-delete" "eating-out" TRUE
'''
self.assertRegex(errors[0].message, "^template-delete takes a single argument")
@load_doc(expect_errors=True)
def test_template_delete_invalid_argument(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-03-01 custom "template-delete" TRUE
'''
self.assertRegex(errors[0].message, "^Template name must be a string")
@load_doc(expect_errors=True)
def test_template_delete_unknown(self, entries, errors, options_map):
'''
plugin "beancount_extras_kris7t.plugins.templates"
2020-03-01 custom "template-delete" "taxi"
'''
self.assertRegex(errors[0].message, "^Unknown template")
if __name__ == '__main__':
unittest.main()