Changeset - 51db04dc200c
[Not reviewed]
0 1 0
Brett Smith - 4 years ago 2020-05-15 20:46:20
brettcsmith@brettcsmith.org
test_meta_receipt: Prepare for multiple fallback meta keys.
1 file changed with 66 insertions and 65 deletions:
0 comments (0 inline, 0 general)
tests/test_meta_receipt.py
Show inline comments
...
 
@@ -38,14 +38,15 @@ class PostType(enum.IntFlag):
 
class AccountForTesting(typing.NamedTuple):
 
    name: str
 
    required_types: PostType
 
    fallback_meta: typing.Optional[str]
 
    fallback_meta: typing.Sequence[str] = ()
 

	
 
    def missing_message(self, include_fallback=True):
 
        if self.fallback_meta is None or not include_fallback:
 
            rest = ""
 
        else:
 
            rest = f"/{self.fallback_meta}"
 
        return f"{self.name} missing {TEST_KEY}{rest}"
 
        return "{} missing {}{}{}".format(
 
            self.name,
 
            TEST_KEY,
 
            '/' if self.fallback_meta else '',
 
            '/'.join(self.fallback_meta),
 
        )
 

	
 
    def wrong_type_message(self, wrong_value, key=TEST_KEY):
 
        expect_type = 'Decimal' if key == 'check-id' else 'str'
...
 
@@ -58,22 +59,25 @@ class AccountForTesting(typing.NamedTuple):
 

	
 

	
 
ACCOUNTS = [AccountForTesting._make(t) for t in [
 
    ('Assets:Bank:CheckCard', PostType.CREDIT, 'check'),
 
    ('Assets:Bank:CheckCard', PostType.DEBIT, 'check-id'),
 
    ('Assets:Cash', PostType.BOTH, None),
 
    ('Assets:Checking', PostType.CREDIT, 'check'),
 
    ('Assets:Checking', PostType.DEBIT, 'check-id'),
 
    ('Assets:Savings', PostType.BOTH, None),
 
    ('Liabilities:CreditCard', PostType.CREDIT, None),
 
    ('Liabilities:CreditCard', PostType.DEBIT, 'invoice'),
 
    ('Assets:Bank:CheckCard', PostType.CREDIT, ('check',)),
 
    ('Assets:Bank:CheckCard', PostType.DEBIT, ('check-id',)),
 
    ('Assets:Cash', PostType.BOTH, ()),
 
    ('Assets:Checking', PostType.CREDIT, ('check',)),
 
    ('Assets:Checking', PostType.DEBIT, ('check-id',)),
 
    ('Assets:Savings', PostType.BOTH, ()),
 
    ('Liabilities:CreditCard', PostType.CREDIT, ()),
 
    ('Liabilities:CreditCard', PostType.DEBIT, ('invoice',)),
 
]]
 

	
 
ACCOUNTS_WITH_LINK_FALLBACK = [acct for acct in ACCOUNTS
 
                               if acct.fallback_meta and acct.fallback_meta != 'check-id']
 
ACCOUNTS_WITH_CHECK_ID_FALLBACK = [acct for acct in ACCOUNTS
 
                                   if acct.fallback_meta == 'check-id']
 
ACCOUNTS_WITHOUT_FALLBACKS = [acct for acct in ACCOUNTS if not acct.fallback_meta]
 
KNOWN_FALLBACKS = {acct.fallback_meta for acct in ACCOUNTS if acct.fallback_meta}
 
ACCOUNTS_WITH_LINK_FALLBACK = [
 
    (acct, fallback_key)
 
    for acct in ACCOUNTS
 
    for fallback_key in acct.fallback_meta
 
    if fallback_key != 'check-id'
 
]
 
ACCOUNTS_WITH_CHECK_ID_FALLBACK = [
 
    acct for acct in ACCOUNTS if 'check-id' in acct.fallback_meta
 
]
 

	
 
# These are mostly fill-in values.
 
# We don't need to run every test on every value for these, just enough to
...
 
@@ -181,67 +185,69 @@ def test_bad_type_receipt_on_txn(hook, test_acct, other_acct, value):
 
    check(hook, test_acct, other_acct, test_acct.wrong_type_message(value),
 
          txn_meta={TEST_KEY: value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
@pytest.mark.parametrize('test_pair,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_LINK_FALLBACK,
 
    NOT_REQUIRED_ACCOUNTS,
 
    testutil.LINK_METADATA_STRINGS,
 
))
 
def test_valid_fallback_on_post(hook, test_acct, other_acct, value):
 
    check(hook, test_acct, other_acct, None,
 
          post_meta={test_acct.fallback_meta: value})
 
def test_valid_fallback_on_post(hook, test_pair, other_acct, value):
 
    test_acct, meta_key = test_pair
 
    check(hook, test_acct, other_acct, None, post_meta={meta_key: value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
@pytest.mark.parametrize('test_pair,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_LINK_FALLBACK,
 
    NOT_REQUIRED_ACCOUNTS,
 
    testutil.NON_LINK_METADATA_STRINGS,
 
))
 
def test_invalid_fallback_on_post(hook, test_acct, other_acct, value):
 
def test_invalid_fallback_on_post(hook, test_pair, other_acct, value):
 
    test_acct, meta_key = test_pair
 
    check(hook, test_acct, other_acct, {test_acct.missing_message()},
 
          post_meta={test_acct.fallback_meta: value})
 
          post_meta={meta_key: value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
@pytest.mark.parametrize('test_pair,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_LINK_FALLBACK,
 
    NOT_REQUIRED_ACCOUNTS,
 
    testutil.NON_STRING_METADATA_VALUES,
 
))
 
def test_bad_type_fallback_on_post(hook, test_acct, other_acct, value):
 
def test_bad_type_fallback_on_post(hook, test_pair, other_acct, value):
 
    test_acct, meta_key = test_pair
 
    expected = {
 
        test_acct.missing_message(),
 
        test_acct.wrong_type_message(value, test_acct.fallback_meta),
 
        test_acct.wrong_type_message(value, meta_key),
 
    }
 
    check(hook, test_acct, other_acct, expected,
 
          post_meta={test_acct.fallback_meta: value})
 
    check(hook, test_acct, other_acct, expected, post_meta={meta_key: value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
@pytest.mark.parametrize('test_pair,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_LINK_FALLBACK,
 
    NOT_REQUIRED_ACCOUNTS,
 
    testutil.LINK_METADATA_STRINGS,
 
))
 
def test_valid_fallback_on_txn(hook, test_acct, other_acct, value):
 
    check(hook, test_acct, other_acct, None,
 
          txn_meta={test_acct.fallback_meta: value})
 
def test_valid_fallback_on_txn(hook, test_pair, other_acct, value):
 
    test_acct, meta_key = test_pair
 
    check(hook, test_acct, other_acct, None, txn_meta={meta_key: value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
@pytest.mark.parametrize('test_pair,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_LINK_FALLBACK,
 
    NOT_REQUIRED_ACCOUNTS,
 
    testutil.NON_LINK_METADATA_STRINGS,
 
))
 
def test_invalid_fallback_on_txn(hook, test_acct, other_acct, value):
 
def test_invalid_fallback_on_txn(hook, test_pair, other_acct, value):
 
    test_acct, meta_key = test_pair
 
    check(hook, test_acct, other_acct, {test_acct.missing_message()},
 
          txn_meta={test_acct.fallback_meta: value})
 
          txn_meta={meta_key: value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
@pytest.mark.parametrize('test_pair,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_LINK_FALLBACK,
 
    NOT_REQUIRED_ACCOUNTS,
 
    testutil.NON_STRING_METADATA_VALUES,
 
))
 
def test_bad_type_fallback_on_txn(hook, test_acct, other_acct, value):
 
def test_bad_type_fallback_on_txn(hook, test_pair, other_acct, value):
 
    test_acct, meta_key = test_pair
 
    expected = {
 
        test_acct.missing_message(),
 
        test_acct.wrong_type_message(value, test_acct.fallback_meta),
 
        test_acct.wrong_type_message(value, meta_key),
 
    }
 
    check(hook, test_acct, other_acct, expected,
 
          txn_meta={test_acct.fallback_meta: value})
 
    check(hook, test_acct, other_acct, expected, txn_meta={meta_key: value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_CHECK_ID_FALLBACK,
...
 
@@ -249,8 +255,7 @@ def test_bad_type_fallback_on_txn(hook, test_acct, other_acct, value):
 
    CHECK_IDS,
 
))
 
def test_valid_check_id_on_post(hook, test_acct, other_acct, value):
 
    check(hook, test_acct, other_acct, None,
 
          post_meta={test_acct.fallback_meta: value})
 
    check(hook, test_acct, other_acct, None, post_meta={'check-id': value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_CHECK_ID_FALLBACK,
...
 
@@ -260,10 +265,9 @@ def test_valid_check_id_on_post(hook, test_acct, other_acct, value):
 
def test_invalid_check_id_on_post(hook, test_acct, other_acct, value):
 
    expected = {
 
        test_acct.missing_message(),
 
        f"{test_acct.name} has invalid {test_acct.fallback_meta}: {value}",
 
        f"{test_acct.name} has invalid check-id: {value}",
 
    }
 
    check(hook, test_acct, other_acct, expected,
 
          post_meta={test_acct.fallback_meta: value})
 
    check(hook, test_acct, other_acct, expected, post_meta={'check-id': value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_CHECK_ID_FALLBACK,
...
 
@@ -275,10 +279,9 @@ def test_bad_type_check_id_on_post(hook, test_acct, other_acct, value):
 
        value = ''
 
    expected = {
 
        test_acct.missing_message(),
 
        test_acct.wrong_type_message(value, test_acct.fallback_meta),
 
        test_acct.wrong_type_message(value, 'check-id'),
 
    }
 
    check(hook, test_acct, other_acct, expected,
 
          post_meta={test_acct.fallback_meta: value})
 
    check(hook, test_acct, other_acct, expected, post_meta={'check-id': value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_CHECK_ID_FALLBACK,
...
 
@@ -286,8 +289,7 @@ def test_bad_type_check_id_on_post(hook, test_acct, other_acct, value):
 
    CHECK_IDS,
 
))
 
def test_valid_check_id_on_txn(hook, test_acct, other_acct, value):
 
    check(hook, test_acct, other_acct, None,
 
          txn_meta={test_acct.fallback_meta: value})
 
    check(hook, test_acct, other_acct, None, txn_meta={'check-id': value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_CHECK_ID_FALLBACK,
...
 
@@ -297,10 +299,9 @@ def test_valid_check_id_on_txn(hook, test_acct, other_acct, value):
 
def test_invalid_check_id_on_txn(hook, test_acct, other_acct, value):
 
    expected = {
 
        test_acct.missing_message(),
 
        f"{test_acct.name} has invalid {test_acct.fallback_meta}: {value}",
 
        f"{test_acct.name} has invalid check-id: {value}",
 
    }
 
    check(hook, test_acct, other_acct, expected,
 
          txn_meta={test_acct.fallback_meta: value})
 
    check(hook, test_acct, other_acct, expected, txn_meta={'check-id': value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_CHECK_ID_FALLBACK,
...
 
@@ -312,34 +313,34 @@ def test_bad_type_check_id_on_txn(hook, test_acct, other_acct, value):
 
        value = ''
 
    expected = {
 
        test_acct.missing_message(),
 
        test_acct.wrong_type_message(value, test_acct.fallback_meta),
 
        test_acct.wrong_type_message(value, 'check-id'),
 
    }
 
    check(hook, test_acct, other_acct, expected,
 
          txn_meta={test_acct.fallback_meta: value})
 
    check(hook, test_acct, other_acct, expected, txn_meta={'check-id': value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,key,value', testutil.combine_values(
 
    ACCOUNTS_WITHOUT_FALLBACKS,
 
    [acct for acct in ACCOUNTS if not acct.fallback_meta],
 
    NOT_REQUIRED_ACCOUNTS,
 
    KNOWN_FALLBACKS,
 
    {key for acct in ACCOUNTS for key in acct.fallback_meta},
 
    testutil.LINK_METADATA_STRINGS,
 
))
 
def test_fallback_not_accepted_on_other_accounts(hook, test_acct, other_acct, key, value):
 
    check(hook, test_acct, other_acct, {test_acct.missing_message()},
 
          post_meta={key: value})
 

	
 
@pytest.mark.parametrize('test_acct,other_acct,value', testutil.combine_values(
 
@pytest.mark.parametrize('test_pair,other_acct,value', testutil.combine_values(
 
    ACCOUNTS_WITH_LINK_FALLBACK,
 
    NOT_REQUIRED_ACCOUNTS,
 
    testutil.LINK_METADATA_STRINGS,
 
))
 
def test_fallback_on_zero_amount_postings(hook, test_acct, other_acct, value):
 
def test_fallback_on_zero_amount_postings(hook, test_pair, other_acct, value):
 
    # Unfortunately it does happen that we get donations that go 100% to
 
    # banking fees, and our importer writes a zero-amount posting to the
 
    # Assets account.
 
    test_acct, meta_key = test_pair
 
    txn = testutil.Transaction(postings=[
 
        ('Income:Donations', '-.1'),
 
        ('Expenses:BankingFees', '.1'),
 
        (test_acct.name, 0, {test_acct.fallback_meta: value}),
 
        (test_acct.name, 0, {meta_key: value}),
 
    ])
 
    assert not list(hook.run(txn))
 

	
0 comments (0 inline, 0 general)