eb7f73e644
This is something reporting tools will want a lot. This will make it easier for them to look at just postings without worrying about the parent transaction.
141 lines
5.1 KiB
Python
141 lines
5.1 KiB
Python
"""Test PostingMeta class"""
|
|
# 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 <https://www.gnu.org/licenses/>.
|
|
|
|
import pytest
|
|
|
|
from . import testutil
|
|
|
|
from conservancy_beancount import data
|
|
|
|
@pytest.fixture
|
|
def simple_txn():
|
|
return testutil.Transaction(note='txn note', postings=[
|
|
('Assets:Cash', 5),
|
|
('Income:Donations', -5, {'note': 'donation love', 'extra': 'Extra'}),
|
|
])
|
|
SIMPLE_TXN_METAKEYS = frozenset(['filename', 'lineno', 'note'])
|
|
|
|
@pytest.fixture
|
|
def payee_txn():
|
|
return testutil.Transaction(payee='SampleCo', postings=[
|
|
('Assets:Receivable:Accounts', -100),
|
|
('Assets:Checking', 95),
|
|
('Expenses:BankingFees', 5, {'entity': 'MyBank'}),
|
|
])
|
|
|
|
def test_getitem_transaction(simple_txn):
|
|
assert data.PostingMeta(simple_txn, 0)['note'] == 'txn note'
|
|
|
|
def test_getitem_posting(simple_txn):
|
|
assert data.PostingMeta(simple_txn, 1)['note'] == 'donation love'
|
|
|
|
def test_getitem_keyerror(simple_txn):
|
|
with pytest.raises(KeyError):
|
|
data.PostingMeta(simple_txn, 1)['InvalidMetadata']
|
|
|
|
def test_setitem_overwrite(simple_txn):
|
|
meta = data.PostingMeta(simple_txn, 1)
|
|
meta['note'] = 'overwritten'
|
|
assert meta['note'] == 'overwritten'
|
|
assert data.PostingMeta(simple_txn, 0)['note'] == 'txn note'
|
|
|
|
def test_setitem_over_txn(simple_txn):
|
|
meta = data.PostingMeta(simple_txn, 0)
|
|
meta['note'] = 'overwritten'
|
|
assert meta['note'] == 'overwritten'
|
|
assert simple_txn.meta['note'] == 'txn note'
|
|
assert data.PostingMeta(simple_txn, 1)['note'] == 'donation love'
|
|
|
|
def test_setitem_new_meta(simple_txn):
|
|
meta = data.PostingMeta(simple_txn, 0)
|
|
meta['newkey'] = 'testvalue'
|
|
assert meta['newkey'] == 'testvalue'
|
|
assert 'newkey' not in simple_txn.meta
|
|
assert 'newkey' not in simple_txn.postings[1].meta
|
|
|
|
def test_delitem(simple_txn):
|
|
meta = data.PostingMeta(simple_txn, 1)
|
|
del meta['note']
|
|
assert 'note' not in simple_txn.postings[1].meta
|
|
|
|
def test_delitem_fails_on_txn_meta(simple_txn):
|
|
meta = data.PostingMeta(simple_txn, 0)
|
|
with pytest.raises(KeyError):
|
|
del meta['note']
|
|
|
|
def test_len_with_empty_post_meta(simple_txn):
|
|
assert len(data.PostingMeta(simple_txn, 0)) == len(SIMPLE_TXN_METAKEYS)
|
|
|
|
def test_len_with_post_meta_over_txn(simple_txn):
|
|
assert len(data.PostingMeta(simple_txn, 1)) == len(SIMPLE_TXN_METAKEYS) + 1
|
|
|
|
def test_iter_with_empty_post_meta(simple_txn):
|
|
assert set(data.PostingMeta(simple_txn, 0)) == SIMPLE_TXN_METAKEYS
|
|
|
|
def test_iter_with_post_meta_over_txn(simple_txn):
|
|
assert set(data.PostingMeta(simple_txn, 1)) == SIMPLE_TXN_METAKEYS.union(['extra'])
|
|
|
|
def test_get_links_from_txn(simple_txn):
|
|
meta = data.PostingMeta(simple_txn, 0)
|
|
assert list(meta.get_links('note')) == ['txn', 'note']
|
|
|
|
def test_get_links_from_post_override(simple_txn):
|
|
meta = data.PostingMeta(simple_txn, 1)
|
|
assert list(meta.get_links('note')) == ['donation', 'love']
|
|
|
|
def test_payee_used_as_entity(payee_txn):
|
|
actual = [data.PostingMeta(payee_txn, n, p)['entity']
|
|
for n, p in enumerate(payee_txn.postings)]
|
|
assert actual == ['SampleCo', 'SampleCo', 'MyBank']
|
|
|
|
def test_entity_metadata_has_precedence_over_payee(payee_txn):
|
|
payee_txn.meta['entity'] = 'ExampleCo'
|
|
actual = [data.PostingMeta(payee_txn, n, p)['entity']
|
|
for n, p in enumerate(payee_txn.postings)]
|
|
assert actual == ['ExampleCo', 'ExampleCo', 'MyBank']
|
|
|
|
def test_keyerror_when_no_entity_or_payee(simple_txn):
|
|
meta = data.PostingMeta(simple_txn, 1)
|
|
with pytest.raises(KeyError):
|
|
meta['entity']
|
|
|
|
@pytest.mark.parametrize('date', [
|
|
testutil.FUTURE_DATE,
|
|
testutil.FY_START_DATE,
|
|
testutil.FY_MID_DATE,
|
|
testutil.PAST_DATE,
|
|
])
|
|
def test_date(date):
|
|
txn = testutil.Transaction(date=date, postings=[
|
|
('Income:Donations', -15),
|
|
('Assets:Cash', 15),
|
|
])
|
|
for index, post in enumerate(txn.postings):
|
|
assert data.PostingMeta(txn, index, post).date == date
|
|
|
|
# The .get() tests are arguably testing the stdlib, but they're short and
|
|
# they confirm that we're using the stdlib as we intend.
|
|
def test_get_with_meta_value(simple_txn):
|
|
assert data.PostingMeta(simple_txn, 1).get('note') == 'donation love'
|
|
|
|
def test_get_with_txn_value(simple_txn):
|
|
assert data.PostingMeta(simple_txn, 0).get('note') == 'txn note'
|
|
|
|
def test_get_with_no_value(simple_txn):
|
|
assert data.PostingMeta(simple_txn, 0).get('extra') is None
|
|
|
|
def test_get_with_specified_default(simple_txn):
|
|
assert data.PostingMeta(simple_txn, 0).get('extra', 'blank') == 'blank'
|