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