[tests] Added tests and updated storage.ledgercli
- [ledgercli] Log info messages for operations such as add, delete, update transactions
This commit is contained in:
parent
0108548b4b
commit
3620d97f9d
3 changed files with 284 additions and 0 deletions
|
@ -211,6 +211,8 @@ class Ledger(Storage):
|
||||||
with open(self.ledger_file, 'ab') as f:
|
with open(self.ledger_file, 'ab') as f:
|
||||||
f.write(output)
|
f.write(output)
|
||||||
|
|
||||||
|
_log.info('Added transaction %s', transaction.id)
|
||||||
|
|
||||||
_log.debug('written to file: %s', output)
|
_log.debug('written to file: %s', output)
|
||||||
|
|
||||||
return transaction.id
|
return transaction.id
|
||||||
|
@ -419,6 +421,11 @@ class Ledger(Storage):
|
||||||
# Delete the preceding line to make the file
|
# Delete the preceding line to make the file
|
||||||
del_start -= 1
|
del_start -= 1
|
||||||
|
|
||||||
|
_log.info('Removing transaction with ID: %s (lines %d-%d)',
|
||||||
|
transaction_id,
|
||||||
|
del_start,
|
||||||
|
semantic_lines['next_transaction_or_eof'])
|
||||||
|
|
||||||
del lines[del_start:semantic_lines['next_transaction_or_eof']]
|
del lines[del_start:semantic_lines['next_transaction_or_eof']]
|
||||||
|
|
||||||
with open(self.ledger_file, 'w') as f:
|
with open(self.ledger_file, 'w') as f:
|
||||||
|
@ -444,6 +451,7 @@ class Ledger(Storage):
|
||||||
|
|
||||||
self.add_transaction(transaction)
|
self.add_transaction(transaction)
|
||||||
|
|
||||||
|
_log.info('Updated transaction %s', transaction.id)
|
||||||
_log.debug('Updated transaction from: %s to: %s', old_transaction,
|
_log.debug('Updated transaction from: %s to: %s', old_transaction,
|
||||||
transaction)
|
transaction)
|
||||||
|
|
||||||
|
|
0
accounting/tests/__init__.py
Normal file
0
accounting/tests/__init__.py
Normal file
276
accounting/tests/test_transactions.py
Normal file
276
accounting/tests/test_transactions.py
Normal file
|
@ -0,0 +1,276 @@
|
||||||
|
'''
|
||||||
|
Tests for accounting-api
|
||||||
|
'''
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
import tempfile
|
||||||
|
import logging
|
||||||
|
import copy
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from flask import json
|
||||||
|
|
||||||
|
from accounting.web import app, init_ledger
|
||||||
|
|
||||||
|
from accounting.transport import AccountingEncoder, AccountingDecoder
|
||||||
|
from accounting.models import Transaction, Posting, Amount
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionTestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.app = app.test_client()
|
||||||
|
self.fd, app.config['LEDGER_FILE'] = tempfile.mkstemp()
|
||||||
|
init_ledger()
|
||||||
|
self.simple_transaction = Transaction(
|
||||||
|
date=datetime.today(),
|
||||||
|
payee='Joar',
|
||||||
|
postings=[
|
||||||
|
Posting('Assets:Checking', Amount('-133.7', 'USD')),
|
||||||
|
Posting('Expenses:Foo', Amount('133.7', 'USD'))
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
os.close(self.fd)
|
||||||
|
os.unlink(app.config['LEDGER_FILE'])
|
||||||
|
|
||||||
|
def test_get_transactions(self):
|
||||||
|
open(app.config['LEDGER_FILE'], 'w').write(
|
||||||
|
'1400-12-21 Old stuff\n'
|
||||||
|
' ;Id: foo\n'
|
||||||
|
' Assets:Checking -100 USD\n'
|
||||||
|
' Expenses:Tax 100 USD\n')
|
||||||
|
rv = self.app.get('/transaction')
|
||||||
|
|
||||||
|
json_transaction = (
|
||||||
|
b'{\n'
|
||||||
|
b' "transactions": [\n'
|
||||||
|
b' {\n'
|
||||||
|
b' "__type__": "Transaction", \n'
|
||||||
|
b' "date": "1400-12-21", \n'
|
||||||
|
b' "id": "foo", \n'
|
||||||
|
b' "metadata": {}, \n'
|
||||||
|
b' "payee": "Old stuff", \n'
|
||||||
|
b' "postings": [\n'
|
||||||
|
b' {\n'
|
||||||
|
b' "__type__": "Posting", \n'
|
||||||
|
b' "account": "Assets:Checking", \n'
|
||||||
|
b' "amount": {\n'
|
||||||
|
b' "__type__": "Amount", \n'
|
||||||
|
b' "amount": "-100", \n'
|
||||||
|
b' "symbol": "USD"\n'
|
||||||
|
b' }, \n'
|
||||||
|
b' "metadata": {}\n'
|
||||||
|
b' }, \n'
|
||||||
|
b' {\n'
|
||||||
|
b' "__type__": "Posting", \n'
|
||||||
|
b' "account": "Expenses:Tax", \n'
|
||||||
|
b' "amount": {\n'
|
||||||
|
b' "__type__": "Amount", \n'
|
||||||
|
b' "amount": "100", \n'
|
||||||
|
b' "symbol": "USD"\n'
|
||||||
|
b' }, \n'
|
||||||
|
b' "metadata": {}\n'
|
||||||
|
b' }\n'
|
||||||
|
b' ]\n'
|
||||||
|
b' }\n'
|
||||||
|
b' ]\n'
|
||||||
|
b'}')
|
||||||
|
|
||||||
|
self.assertEqual(rv.get_data(), json_transaction)
|
||||||
|
|
||||||
|
def _post_json(self, path, data, expect=200, **kw):
|
||||||
|
response = self.app.post(
|
||||||
|
path,
|
||||||
|
content_type='application/json',
|
||||||
|
data=json.dumps(data, cls=AccountingEncoder),
|
||||||
|
**kw
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, expect)
|
||||||
|
|
||||||
|
return self._decode_response(response)
|
||||||
|
|
||||||
|
def _decode_response(self, response):
|
||||||
|
return json.loads(response.data, cls=AccountingDecoder)
|
||||||
|
|
||||||
|
def _get_json(self, path, expect=200, **kw):
|
||||||
|
response = self.app.get(path, **kw)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, expect)
|
||||||
|
|
||||||
|
return self._decode_response(response)
|
||||||
|
|
||||||
|
def _open_json(self, method, path, expect=200, **kw):
|
||||||
|
response = self.app.open(
|
||||||
|
path,
|
||||||
|
method=method.upper(),
|
||||||
|
**kw
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, expect)
|
||||||
|
|
||||||
|
return self._decode_response(response)
|
||||||
|
|
||||||
|
def _add_simple_transaction(self, transaction_id=None):
|
||||||
|
if transaction_id is None:
|
||||||
|
transaction_id = str(uuid.uuid4())
|
||||||
|
|
||||||
|
transaction = copy.deepcopy(self.simple_transaction)
|
||||||
|
transaction.id = transaction_id
|
||||||
|
|
||||||
|
response = self._post_json('/transaction', transaction)
|
||||||
|
|
||||||
|
self.assertEqual(len(response['transaction_ids']), 1)
|
||||||
|
self.assertEqual(response['status'], 'OK')
|
||||||
|
|
||||||
|
response = self._get_json('/transaction/' + transaction.id)
|
||||||
|
|
||||||
|
self.assertEqual(transaction_id, response['transaction'].id)
|
||||||
|
|
||||||
|
self.assertEqual(response['transaction'], transaction)
|
||||||
|
|
||||||
|
return transaction
|
||||||
|
|
||||||
|
def test_post_transaction_without_id(self):
|
||||||
|
transaction = copy.deepcopy(self.simple_transaction)
|
||||||
|
|
||||||
|
response = self._post_json('/transaction', transaction)
|
||||||
|
|
||||||
|
self.assertEqual(len(response['transaction_ids']), 1)
|
||||||
|
self.assertEqual(response['status'], 'OK')
|
||||||
|
|
||||||
|
transaction.id = response['transaction_ids'][0]
|
||||||
|
|
||||||
|
response = self._get_json('/transaction/' + transaction.id)
|
||||||
|
|
||||||
|
self.assertEqual(response['transaction'], transaction)
|
||||||
|
|
||||||
|
def test_delete_transaction(self):
|
||||||
|
transaction = copy.deepcopy(self.simple_transaction)
|
||||||
|
|
||||||
|
response = self._post_json('/transaction', transaction)
|
||||||
|
|
||||||
|
transaction_id = response['transaction_ids'][0]
|
||||||
|
|
||||||
|
self.assertIsNotNone(transaction_id)
|
||||||
|
|
||||||
|
response = self._open_json('DELETE',
|
||||||
|
'/transaction/' + transaction_id)
|
||||||
|
|
||||||
|
self.assertEqual(response['status'], 'OK')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
# ValueError thrown because the response does not contain any JSON
|
||||||
|
response = self._get_json('/transaction/' + transaction_id, 404)
|
||||||
|
|
||||||
|
def test_post_multiple_transactions(self):
|
||||||
|
transactions = [
|
||||||
|
Transaction(
|
||||||
|
date=datetime.today(),
|
||||||
|
payee='Rent',
|
||||||
|
postings=[
|
||||||
|
Posting(
|
||||||
|
account='Assets:Checking',
|
||||||
|
amount=Amount(amount='-4600.00', symbol='SEK')
|
||||||
|
),
|
||||||
|
Posting(
|
||||||
|
account='Expenses:Rent',
|
||||||
|
amount=Amount(amount='4600.00', symbol='SEK')
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
Transaction(
|
||||||
|
date=datetime.today(),
|
||||||
|
payee='Hosting',
|
||||||
|
postings=[
|
||||||
|
Posting(
|
||||||
|
account='Assets:Checking',
|
||||||
|
amount=Amount(amount='-700.00', symbol='SEK')
|
||||||
|
),
|
||||||
|
Posting(
|
||||||
|
account='Expenses:Hosting',
|
||||||
|
amount=Amount(amount='700.00', symbol='SEK')
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
response = self._post_json('/transaction',
|
||||||
|
{'transactions': transactions})
|
||||||
|
|
||||||
|
self.assertEqual(len(response['transaction_ids']), 2)
|
||||||
|
|
||||||
|
transactions[0].id = response['transaction_ids'][0]
|
||||||
|
transactions[1].id = response['transaction_ids'][1]
|
||||||
|
|
||||||
|
response = self._get_json('/transaction/' + transactions[0].id)
|
||||||
|
|
||||||
|
self.assertEqual(transactions[0], response['transaction'])
|
||||||
|
|
||||||
|
response = self._get_json('/transaction/' + transactions[1].id)
|
||||||
|
|
||||||
|
self.assertEqual(transactions[1], response['transaction'])
|
||||||
|
|
||||||
|
def test_update_transaction_payee(self):
|
||||||
|
transaction = self._add_simple_transaction()
|
||||||
|
|
||||||
|
transaction.payee = 'not Joar'
|
||||||
|
|
||||||
|
response = self._post_json('/transaction/' + transaction.id,
|
||||||
|
{'transaction': transaction})
|
||||||
|
|
||||||
|
self.assertEqual(response['status'], 'OK')
|
||||||
|
|
||||||
|
response = self._get_json('/transaction/'+ transaction.id)
|
||||||
|
|
||||||
|
self.assertEqual(response['transaction'], transaction)
|
||||||
|
|
||||||
|
def test_update_transaction_postings(self):
|
||||||
|
transaction = self._add_simple_transaction()
|
||||||
|
|
||||||
|
postings = [
|
||||||
|
Posting(account='Assets:Checking',
|
||||||
|
amount=Amount(amount='-733.10', symbol='SEK')),
|
||||||
|
Posting(account='Expenses:Bar',
|
||||||
|
amount=Amount(amount='733.10', symbol='SEK'))
|
||||||
|
]
|
||||||
|
|
||||||
|
transaction.postings = postings
|
||||||
|
|
||||||
|
response = self._post_json('/transaction/' + transaction.id,
|
||||||
|
{'transaction': transaction})
|
||||||
|
|
||||||
|
self.assertEqual(response['status'], 'OK')
|
||||||
|
|
||||||
|
response = self._get_json('/transaction/' + transaction.id)
|
||||||
|
|
||||||
|
self.assertEqual(response['transaction'], transaction)
|
||||||
|
|
||||||
|
def test_post_unbalanced_transaction(self):
|
||||||
|
transaction = Transaction(
|
||||||
|
date=datetime.today(),
|
||||||
|
payee='Unbalanced Transaction',
|
||||||
|
postings=[
|
||||||
|
Posting(account='Assets:Checking',
|
||||||
|
amount=Amount(amount='100.00', symbol='USD')),
|
||||||
|
Posting(account='Income:Foo',
|
||||||
|
amount=Amount(amount='-100.01', symbol='USD'))
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
self._post_json('/transaction', transaction)
|
||||||
|
|
||||||
|
response = self._get_json('/transaction')
|
||||||
|
|
||||||
|
import pdb; pdb.set_trace()
|
||||||
|
|
||||||
|
def test_update_transaction_amounts(self): pass
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Loading…
Reference in a new issue