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…
	
	Add table
		
		Reference in a new issue