Files @ 76f2707aacf7
Branch filter:

Location: NPO-Accounting/import2ledger/tests/test_hooks.py

Brett Smith
hooks.ledger_entry: New hook to output Ledger entries.

This is roughly the smallest diff necessary to move output to a hook.
There's a lot of code reorganization that should still happen to bring it
better in line with this new structure.
import argparse
import datetime
import itertools

import pytest

from import2ledger import hooks
from import2ledger.hooks import add_entity, default_date, filter_by_date, ledger_entry

def test_load_all():
    all_hooks = list(hooks.load_all())
    positions = {hook: index for index, hook in enumerate(all_hooks)}
    expected_order = [
        default_date.DefaultDateHook,
        add_entity.AddEntityHook,
        filter_by_date.FilterByDateHook,
        ledger_entry.LedgerEntryHook,
    ]
    actual_order = list(sorted(expected_order, key=positions.__getitem__))
    assert actual_order == expected_order

@pytest.mark.parametrize('in_key,payee,out_key,expected', [
    ('payee', 'Alex Smith', 'entity', 'Smith-Alex'),
    ('payee', 'Dakota D.  Doe', 'entity', 'Doe-Dakota-D'),
    ('payee', 'Björk', 'entity', 'Bjork'),
    ('payee', 'Fran Doe-Smith', 'entity', 'Doe-Smith-Fran'),
    ('payee', 'Alex(Nickname) Smith', 'entity', 'Smith-Alex'),
    ('payee', '稲荷', 'entity', '稲荷'),
    ('payee', '稲(Jan)荷', 'entity', '稲荷'),
    ('payee', 'Pøweł', 'entity', 'Powel'),
    ('payee', 'Elyse Jan Smith', 'entity', 'Smith-Elyse-Jan'),
    ('payee', 'Jan van Smith', 'entity', 'van-Smith-Jan'),
    ('payee', 'Francis da Silva', 'entity', 'da-Silva-Francis'),
    ('payee', 'A van der B', 'entity', 'van-der-B-A'),
    ('payee', 'A de B de la C', 'entity', 'de-la-C-A-de-B'),
    ('corporation', 'Company A', 'corp_entity', 'Company-A'),
    ('corporation', 'Company A 99', 'corp_entity', 'Company-A-99'),
    ('corporation', 'DX Co.', 'corp_entity', 'DX'),
    ('corporation', 'DX Company', 'corp_entity', 'DX'),
    ('corporation', 'DX Company Inc.', 'corp_entity', 'DX'),
    ('corporation', 'DX Corp', 'corp_entity', 'DX'),
    ('corporation', 'DX Corp LLC', 'corp_entity', 'DX'),
    ('corporation', 'DX Corporation', 'corp_entity', 'DX'),
    ('corporation', 'DX, Inc.', 'corp_entity', 'DX'),
    ('corporation', 'DX Incorporated', 'corp_entity', 'DX'),
    ('payee', 'Poe Inc', 'entity', 'Inc-Poe'),
    ('corporation', 'Silly Van', 'corp_entity', 'Silly-Van'),
])
def test_add_entity(in_key, payee, out_key, expected):
    data = {in_key: payee}
    hook = add_entity.AddEntityHook(argparse.Namespace())
    hook.run(data)
    assert data[out_key] == expected


class DateRangeConfig:
    def __init__(self, start_date=None, end_date=None):
        self.start_date = start_date
        self.end_date = end_date

    def date_in_want_range(self, date):
        return (
            ((self.start_date is None) or (date >= self.start_date))
            and ((self.end_date is None) or (date <= self.end_date))
        )


@pytest.mark.parametrize('entry_date,start_date,end_date,allowed', [
    (datetime.date(2016, 5, 10), datetime.date(2016, 1, 1), datetime.date(2016, 12, 31), True),
    (datetime.date(2016, 1, 1), datetime.date(2016, 1, 1), datetime.date(2016, 12, 31), True),
    (datetime.date(2016, 12, 31), datetime.date(2016, 1, 1), datetime.date(2016, 12, 31), True),
    (datetime.date(2016, 1, 1), datetime.date(2016, 1, 1), None, True),
    (datetime.date(2016, 12, 31), None, datetime.date(2016, 12, 31), True),
    (datetime.date(1999, 1, 2), None, None, True),
    (datetime.date(2016, 1, 25), datetime.date(2016, 2, 1), datetime.date(2016, 12, 31), False),
    (datetime.date(2016, 12, 26), datetime.date(2016, 1, 1), datetime.date(2016, 11, 30), False),
    (datetime.date(2016, 1, 31), datetime.date(2016, 2, 1), None, False),
    (datetime.date(2016, 12, 1), None, datetime.date(2016, 11, 30), False),
])
def test_filter_by_date(entry_date, start_date, end_date, allowed):
    entry_data = {'date': entry_date}
    hook = filter_by_date.FilterByDateHook(DateRangeConfig(start_date, end_date))
    assert hook.run(entry_data) is (None if allowed else False)

class DefaultDateConfig:
    ONE_DAY = datetime.timedelta(days=1)

    def __init__(self, start_date=None):
        if start_date is None:
            start_date = datetime.date(2016, 3, 5)
        self.date = start_date - self.ONE_DAY

    def get_default_date(self, section_name=None):
        self.date += self.ONE_DAY
        return self.date


class TestDefaultDate:
    def test_simple_case(self):
        expect_date = datetime.date(2016, 2, 4)
        config = DefaultDateConfig(expect_date)
        data = {}
        hook = default_date.DefaultDateHook(config)
        hook.run(data)
        assert data['date'] == expect_date

    def test_no_caching(self):
        config = DefaultDateConfig()
        hook = default_date.DefaultDateHook(config)
        d1 = {}
        d2 = {}
        hook.run(d1)
        hook.run(d2)
        assert d1['date'] != d2['date']

    def test_no_override(self):
        expect_date = datetime.date(2016, 2, 6)
        config = DefaultDateConfig(expect_date + datetime.timedelta(days=300))
        hook = default_date.DefaultDateHook(config)
        data = {'date': expect_date}
        hook.run(data)
        assert data['date'] is expect_date