tests: Add tests for plugin.meta_payroll_type.

This commit is contained in:
Brett Smith 2021-01-29 11:28:29 -05:00
parent fb9aa9eae1
commit 250b14954f

View file

@ -0,0 +1,152 @@
"""test_meta_payroll_type.py - Unit tests for payroll-type validation hook"""
# Copyright © 2021 Brett Smith
# License: AGPLv3-or-later WITH Beancount-Plugin-Additional-Permission-1.0
#
# Full copyright and licensing details can be found at toplevel file
# LICENSE.txt in the repository.
import typing
import pytest
from . import testutil
from conservancy_beancount.plugin import meta_payroll_type
class HookData(typing.NamedTuple):
account: str
hook_type: typing.Type
valid_values: typing.Set[str]
invalid_values: typing.Set[str]
@classmethod
def from_hook(cls, hook, *valid_values):
return cls(hook.ACCOUNT, hook, set(valid_values), set())
@classmethod
def set_invalid_values(cls, datas):
all_values = frozenset(v for d in datas for v in d.valid_values)
for data in datas:
data.invalid_values.update(all_values.difference(data.valid_values))
TEST_KEY = 'payroll-type'
HOOK_DATA = [
HookData.from_hook(meta_payroll_type.HealthInsuranceHook,
'US:HRA:Fees', 'US:HRA:Usage', 'US:Premium:Main'),
HookData.from_hook(meta_payroll_type.OtherBenefitsHook,
'US:403b:Fees', 'US:Education', 'US:ProfessionalMembership'),
HookData.from_hook(
meta_payroll_type.SalaryHook,
'CA:Tax:EI',
'US:NY:Tax:NYC',
'US:Taxes:Medicare',
'CA:General',
'US:403b:Match',
'US:PTO',
),
HookData.from_hook(meta_payroll_type.TaxHook,
'CA:PP', 'US:IL:Unemployment', 'US:SocialSecurity'),
]
HookData.set_invalid_values(HOOK_DATA)
@pytest.fixture(scope='module')
def config():
return testutil.TestConfig()
def norm_value(value):
return value.replace(':Taxes:', ':Tax:', 1)
@pytest.mark.parametrize('hook_type,account,value', (
(data.hook_type, data.account, value)
for data in HOOK_DATA
for value in data.valid_values
))
def test_valid_value_on_post(config, hook_type, account, value):
txn = testutil.Transaction(postings=[
(account, 55, {TEST_KEY: value}),
('Assets:Checking', -55),
])
errors = list(hook_type(config).run(txn))
assert not errors
testutil.check_post_meta(txn, {TEST_KEY: norm_value(value)}, None)
@pytest.mark.parametrize('hook_type,account,value', (
(data.hook_type, data.account, value)
for data in HOOK_DATA
for value in data.valid_values
))
def test_valid_value_on_txn(config, hook_type, account, value):
txn = testutil.Transaction(**{TEST_KEY: value}, postings=[
(account, 80, {TEST_KEY: value}),
('Assets:Checking', -80),
])
errors = list(hook_type(config).run(txn))
assert not errors
testutil.check_post_meta(txn, {TEST_KEY: norm_value(value)}, None)
@pytest.mark.parametrize('hook_type,account,value', (
(data.hook_type, data.account, value)
for data in HOOK_DATA
for value in data.invalid_values
))
def test_invalid_value_on_post(config, hook_type, account, value):
txn = testutil.Transaction(flag='!', postings=[
(account, 90, {TEST_KEY: value}),
('Assets:Checking', -90),
])
errors = list(hook_type(config).run(txn))
assert errors
testutil.check_post_meta(txn, {TEST_KEY: value}, None)
@pytest.mark.parametrize('hook_type,account,value', (
(data.hook_type, data.account, value)
for data in HOOK_DATA
for value in data.invalid_values
))
def test_invalid_value_on_txn(config, hook_type, account, value):
txn = testutil.Transaction(flag='!', **{TEST_KEY: value}, postings=[
(account, 105),
('Assets:Checking', -105),
])
errors = list(hook_type(config).run(txn))
assert errors
testutil.check_post_meta(txn, None, None)
@pytest.mark.parametrize('hook_type,account', (
(data.hook_type, data.account)
for data in HOOK_DATA
))
def test_missing_value(config, hook_type, account):
txn = testutil.Transaction(flag='!', postings=[
(account, 115),
('Assets:Checking', -115),
])
errors = list(hook_type(config).run(txn))
assert errors
@pytest.mark.parametrize('hook_type,account', (
(hook_data.hook_type, other_data.account)
for hook_data in HOOK_DATA
for other_data in HOOK_DATA
if other_data is not hook_data
))
def test_no_overlapping_account_checks(config, hook_type, account):
txn = testutil.Transaction(postings=[
(account, 120, {TEST_KEY: 'Test:Overlap'}),
('Assets:Checking', -120),
])
errors = list(hook_type(config).run(txn))
assert not errors
@pytest.mark.parametrize('hook_data,value', testutil.combine_values(
HOOK_DATA,
testutil.FIXME_VALUES,
))
def test_flagged_fixme_ok(config, hook_data, value):
txn = testutil.Transaction(flag='!', postings=[
(hook_data.account, 120, {TEST_KEY: value}),
('Assets:Checking', -120),
])
errors = list(hook_data.hook_type(config).run(txn))
assert not errors
testutil.check_post_meta(txn, {TEST_KEY: value}, None)