File diff 0d370c445b9e → 1500d2d9d836
tests/test_meta_project.py
Show inline comments
 
new file 100644
 
"""Test handling of project metadata"""
 
# Copyright © 2020  Brett Smith
 
#
 
# This program is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU Affero General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU Affero General Public License for more details.
 
#
 
# You should have received a copy of the GNU Affero General Public License
 
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
 

	
 
from pathlib import Path
 

	
 
import pytest
 

	
 
from . import testutil
 

	
 
from conservancy_beancount import errors as errormod
 
from conservancy_beancount.plugin import meta_project
 

	
 
VALID_VALUES = {
 
    'Conservancy': 'Conservancy',
 
    'Alpha': 'Alpha',
 
    'Bravo': 'Bravo',
 
    'Charles': 'Charlie',
 
    'Chuck': 'Charlie',
 
}
 

	
 
INVALID_VALUES = {
 
    'Alhpa',
 
    'Yankee',
 
    '',
 
}
 

	
 
TEST_KEY = 'project'
 
DEFAULT_VALUE = 'Conservancy'
 

	
 
@pytest.fixture(scope='module')
 
def hook():
 
    config = testutil.TestConfig(repo_path='repository')
 
    return meta_project.MetaProject(config)
 

	
 
@pytest.mark.parametrize('src_value,set_value', VALID_VALUES.items())
 
def test_valid_values_on_postings(hook, src_value, set_value):
 
    txn = testutil.Transaction(postings=[
 
        ('Assets:Cash', -25),
 
        ('Expenses:General', 25, {TEST_KEY: src_value}),
 
    ])
 
    errors = list(hook.run(txn))
 
    assert not errors
 
    testutil.check_post_meta(txn, None, {TEST_KEY: set_value})
 

	
 
@pytest.mark.parametrize('src_value', INVALID_VALUES)
 
def test_invalid_values_on_postings(hook, src_value):
 
    txn = testutil.Transaction(postings=[
 
        ('Assets:Cash', -25),
 
        ('Expenses:General', 25, {TEST_KEY: src_value}),
 
    ])
 
    errors = list(hook.run(txn))
 
    assert errors
 
    testutil.check_post_meta(txn, None, {TEST_KEY: src_value})
 

	
 
@pytest.mark.parametrize('src_value,set_value', VALID_VALUES.items())
 
def test_valid_values_on_transactions(hook, src_value, set_value):
 
    txn = testutil.Transaction(**{TEST_KEY: src_value}, postings=[
 
        ('Assets:Cash', -25),
 
        ('Expenses:General', 25),
 
    ])
 
    errors = list(hook.run(txn))
 
    assert not errors
 
    testutil.check_post_meta(txn, None, {TEST_KEY: set_value})
 

	
 
@pytest.mark.parametrize('src_value', INVALID_VALUES)
 
def test_invalid_values_on_transactions(hook, src_value):
 
    txn = testutil.Transaction(**{TEST_KEY: src_value}, postings=[
 
        ('Assets:Cash', -25),
 
        ('Expenses:General', 25),
 
    ])
 
    errors = list(hook.run(txn))
 
    assert errors
 
    testutil.check_post_meta(txn, None, None)
 

	
 
@pytest.mark.parametrize('account,required', [
 
    ('Accrued:AccountsReceivable', True),
 
    ('Assets:Cash', False),
 
    ('Expenses:General', True),
 
    ('Income:Donations', True),
 
    ('Liabilities:CreditCard', False),
 
    ('UnearnedIncome:Donations', True),
 
])
 
def test_which_accounts_required_on(hook, account, required):
 
    txn = testutil.Transaction(postings=[
 
        ('Assets:Checking', 25),
 
        (account, 25),
 
    ])
 
    errors = list(hook.run(txn))
 
    assert required == any(errors)
 

	
 
@pytest.mark.parametrize('account', [
 
    'Accrued:VacationPayable',
 
    'Expenses:Payroll:Salary',
 
    'Expenses:Payroll:Tax',
 
])
 
def test_default_values(hook, account):
 
    txn = testutil.Transaction(postings=[
 
        ('Assets:Checking', -25),
 
        (account, 25),
 
    ])
 
    errors = list(hook.run(txn))
 
    assert not errors
 
    testutil.check_post_meta(txn, None, {TEST_KEY: DEFAULT_VALUE})
 

	
 
@pytest.mark.parametrize('date,required', [
 
    (testutil.EXTREME_FUTURE_DATE, False),
 
    (testutil.FUTURE_DATE, True),
 
    (testutil.FY_START_DATE, True),
 
    (testutil.FY_MID_DATE, True),
 
    (testutil.PAST_DATE, None),
 
])
 
def test_default_value_set_in_date_range(hook, date, required):
 
    txn = testutil.Transaction(date=date, postings=[
 
        ('Expenses:Payroll:Benefits', 25),
 
        ('Accrued:VacationPayable', -25),
 
    ])
 
    errors = list(hook.run(txn))
 
    assert not errors
 
    expect_meta = {TEST_KEY: DEFAULT_VALUE} if required else None
 
    testutil.check_post_meta(txn, expect_meta, expect_meta)
 

	
 
@pytest.mark.parametrize('repo_path', [
 
    None,
 
    '..',
 
])
 
def test_missing_project_data(repo_path):
 
    config = testutil.TestConfig(repo_path=repo_path)
 
    with pytest.raises(errormod.ConfigurationError):
 
        meta_project.MetaProject(config)
 

	
 
@pytest.mark.parametrize('repo_path_s,data_path_s', [
 
    ('repository', 'Projects/project-list.yml'),
 
    ('..', 'LICENSE.txt'),
 
])
 
def test_invalid_project_data(repo_path_s, data_path_s):
 
    config = testutil.TestConfig(repo_path=repo_path_s)
 
    with pytest.raises(errormod.ConfigurationError):
 
        meta_project.MetaProject(config, Path(data_path_s))