"""Test main plugin""" # 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 . import pytest from . import testutil from conservancy_beancount import beancount_types, plugin HOOK_REGISTRY = plugin.HookRegistry() class TransactionHook: DIRECTIVE = beancount_types.Transaction HOOK_GROUPS = frozenset() def run(self, txn): assert False, "something called base class run method" @HOOK_REGISTRY.add_hook class TransactionError(TransactionHook): HOOK_GROUPS = frozenset(['configured']) def run(self, txn): return ['txn:{}'.format(id(txn))] @HOOK_REGISTRY.add_hook class PostingError(TransactionHook): HOOK_GROUPS = frozenset(['configured', 'posting']) def run(self, txn): return ['post:{}'.format(id(post)) for post in txn.postings] @pytest.fixture def config_map(): return {} @pytest.fixture def easy_entries(): return [ testutil.Transaction(postings=[ ('Income:Donations', -25), ('Assets:Cash', 25), ]), testutil.Transaction(postings=[ ('Expenses:General', 10), ('Liabilites:CreditCard', -10), ]), ] def hook_types(hooks, key): return {type(hook) for hook in hooks[key]} def map_errors(errors): retval = {} for errkey in errors: key, _, errid = errkey.partition(':') retval.setdefault(key, set()).add(errid) return retval def test_registry_all_by_default(): hook_groups = HOOK_REGISTRY.group_by_directive() hooks = hook_types(hook_groups, 'Transaction') assert len(hooks) >= 2 assert TransactionError in hooks assert PostingError in hooks def test_registry_one_exclude(): hook_groups = HOOK_REGISTRY.group_by_directive('-posting') hooks = hook_types(hook_groups, 'Transaction') assert len(hooks) >= 1 assert TransactionError in hooks assert PostingError not in hooks def test_registry_exclude_then_include(): hook_groups = HOOK_REGISTRY.group_by_directive('-configured posting') hooks = hook_types(hook_groups, 'Transaction') assert len(hooks) >= 1 assert TransactionError not in hooks assert PostingError in hooks def test_registry_include_then_exclude(): hook_groups = HOOK_REGISTRY.group_by_directive('configured -posting') hooks = hook_types(hook_groups, 'Transaction') assert len(hooks) >= 1 assert TransactionError in hooks assert PostingError not in hooks def test_registry_unknown_group_name(): with pytest.raises(ValueError): HOOK_REGISTRY.group_by_directive('UnKnownTestGroup') def test_run_with_multiple_hooks(easy_entries, config_map): out_entries, errors = plugin.run(easy_entries, config_map, '', HOOK_REGISTRY) assert len(out_entries) == 2 errmap = map_errors(errors) assert len(errmap.get('txn', '')) == 2 assert len(errmap.get('post', '')) == 4 def test_run_with_one_hook(easy_entries, config_map): out_entries, errors = plugin.run(easy_entries, config_map, 'posting', HOOK_REGISTRY) assert len(out_entries) == 2 errmap = map_errors(errors) assert len(errmap.get('txn', '')) == 0 assert len(errmap.get('post', '')) == 4