tests: Add tests for plugin.meta_payroll_type.
This commit is contained in:
parent
fb9aa9eae1
commit
250b14954f
1 changed files with 152 additions and 0 deletions
152
tests/test_meta_payroll_type.py
Normal file
152
tests/test_meta_payroll_type.py
Normal 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)
|
Loading…
Reference in a new issue