[tests] Check transactions for errors before being added

- Added support for Exception-specific HTTP response codes for
  AccountinExceptions.
This commit is contained in:
Joar Wandborg 2013-12-26 21:48:45 +01:00
parent ef12c232ad
commit 8abbe3462f
5 changed files with 52 additions and 10 deletions

View file

@ -19,7 +19,11 @@ def jsonify_exceptions(func):
try: try:
return func(*args, **kw) return func(*args, **kw)
except AccountingException as exc: except AccountingException as exc:
return jsonify(error=exc) response = jsonify(error=exc)
response.status_code = exc.http_code
return response
return wrapper return wrapper

View file

@ -7,6 +7,7 @@ class AccountingException(Exception):
Used as a base for exceptions that are returned to the caller via the Used as a base for exceptions that are returned to the caller via the
jsonify_exceptions decorator jsonify_exceptions decorator
''' '''
http_code = 500
def __init__(self, message, **kw): def __init__(self, message, **kw):
self.message = message self.message = message
for key, value in kw.items(): for key, value in kw.items():
@ -14,12 +15,12 @@ class AccountingException(Exception):
class TransactionNotFound(AccountingException): class TransactionNotFound(AccountingException):
pass http_code = 404
class LedgerNotBalanced(AccountingException): class LedgerNotBalanced(AccountingException):
pass http_code = 400
class TransactionIDCollision(AccountingException): class TransactionIDCollision(AccountingException):
pass http_code = 400

View file

@ -173,6 +173,18 @@ 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)
# Check to see that no errors were introduced
try:
self.get_transactions()
except AccountingException as exc:
# TODO: Do a hard reset on the repository using Repository.reset,
# this is on hold because of
# https://github.com/libgit2/pygit2/issues/271.
# This solution will work in the meantime
self.delete_transaction(transaction.id)
setattr(exc, 'transaction', transaction)
raise exc
self.commit_changes('Added transaction %s' % transaction.id) self.commit_changes('Added transaction %s' % transaction.id)
_log.info('Added transaction %s', transaction.id) _log.info('Added transaction %s', transaction.id)

View file

@ -9,6 +9,7 @@ import copy
import uuid import uuid
from datetime import datetime from datetime import datetime
from decimal import Decimal
from flask import json from flask import json
@ -17,7 +18,7 @@ from accounting.web import app, init_ledger
from accounting.transport import AccountingEncoder, AccountingDecoder from accounting.transport import AccountingEncoder, AccountingDecoder
from accounting.models import Transaction, Posting, Amount from accounting.models import Transaction, Posting, Amount
logging.basicConfig(level=logging.DEBUG) #logging.basicConfig(level=logging.DEBUG)
class TransactionTestCase(unittest.TestCase): class TransactionTestCase(unittest.TestCase):
@ -263,13 +264,36 @@ class TransactionTestCase(unittest.TestCase):
] ]
) )
self._post_json('/transaction', transaction) response = self._post_json('/transaction', transaction, expect=400)
response = self._get_json('/transaction') self.assertEqual(response['error']['type'], 'LedgerNotBalanced')
import pdb; pdb.set_trace() def test_update_transaction_amounts(self):
transaction = self._add_simple_transaction()
response = self._get_json(
'/transaction/' + transaction.id)
def test_update_transaction_amounts(self): pass transaction = response['transaction']
for posting in transaction.postings:
posting.amount.amount *= Decimal(1.50)
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_delete_nonexistent_transaction(self):
response = self._open_json('DELETE', '/transaction/I-do-not-exist',
expect=404)
self.assertEqual(response['error']['type'], 'TransactionNotFound')
def test_post_transaction_with_metadata(self): pass
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -44,7 +44,8 @@ class AccountingEncoder(json.JSONEncoder):
elif isinstance(o, AccountingException): elif isinstance(o, AccountingException):
return dict( return dict(
type=o.__class__.__name__, type=o.__class__.__name__,
message=o.message message=o.message,
transaction=getattr(o, 'transaction', None)
) )
return json.JSONEncoder.default(self, o) return json.JSONEncoder.default(self, o)