validation endpoint implementation #7

Merged
tux merged 19 commits from experiments-cerberus into master 2021-01-05 14:34:02 +01:00
3 changed files with 70 additions and 39 deletions
Showing only changes of commit 7609c08cb4 - Show all commits

12
app.py
View file

@ -35,10 +35,12 @@ class HealthHandler(tornado.web.RequestHandler, metaclass=ABCMeta):
# if not available, try git
if v is None:
try:
v = subprocess.check_output(["git", "describe", "--always", "--dirty"],
v = subprocess.check_output(["git", "describe", "--always",
"--dirty"],
cwd=os.path.dirname(__file__)).strip().decode()
except subprocess.CalledProcessError as e:
print("Checking git version lead to non-null return code ", e.returncode)
print("Checking git version lead to non-null return code ",
e.returncode)
return v
@ -50,7 +52,8 @@ class HealthHandler(tornado.web.RequestHandler, metaclass=ABCMeta):
health['git-version'] = self.git_version
health['timestamp'] = isodate.datetime_isoformat(datetime.now())
health['uptime'] = isodate.duration_isoformat(datetime.now() - startup_timestamp)
health['uptime'] = isodate.duration_isoformat(datetime.now()
- startup_timestamp)
self.set_header("Content-Type", "application/json")
self.write(json.dumps(health, indent=4))
@ -61,7 +64,8 @@ class Oas3Handler(tornado.web.RequestHandler, metaclass=ABCMeta):
def get(self):
self.set_header("Content-Type", "text/plain")
# This is the proposed content type,
# but browsers like Firefox try to download instead of display the content
# but browsers like Firefox try to download instead of
# display the content
# self.set_header("Content-Type", "text/vnd.yml")
with open('OAS3.yml', 'r') as f:
oas3 = f.read()

90
test.py
View file

@ -22,11 +22,16 @@ class TestBaseAPI(tornado.testing.AsyncHTTPTestCase):
health = json.loads(response.body.decode())
self.assertIn('api-version', health, msg="api-version is not provided by health endpoint")
self.assertEqual("v0", health['api-version'], msg="API version should be v0")
self.assertIn('git-version', health, msg="git-version is not provided by health endpoint")
self.assertIn('timestamp', health, msg="timestamp is not provided by health endpoint")
self.assertIn('uptime', health, msg="uptime is not provided by health endpoint")
self.assertIn('api-version', health,
msg="api-version is not provided by health endpoint")
self.assertEqual("v0", health['api-version'],
msg="API version should be v0")
self.assertIn('git-version', health,
msg="git-version is not provided by health endpoint")
self.assertIn('timestamp', health,
msg="timestamp is not provided by health endpoint")
self.assertIn('uptime', health,
msg="uptime is not provided by health endpoint")
def test_oas3(self):
response = self.fetch('/v0/oas3',
@ -35,7 +40,8 @@ class TestBaseAPI(tornado.testing.AsyncHTTPTestCase):
# check contents against local OAS3.yml
with open('OAS3.yml') as oas3f:
self.assertEqual(response.body.decode(), oas3f.read(), "OAS3 content differs from spec file!")
self.assertEqual(response.body.decode(), oas3f.read(),
"OAS3 content differs from spec file!")
class TestValidation(tornado.testing.AsyncHTTPTestCase):
@ -50,74 +56,90 @@ class TestValidation(tornado.testing.AsyncHTTPTestCase):
method='POST',
body=json.dumps(entity))
self.assertEqual(200, response.code, "Validation must always return 200")
self.assertEqual(200, response.code,
"Validation must always return 200")
validation_result = json.loads(response.body.decode())
self.assertIn('valid', validation_result, "Key 'valid' expected in validation result")
self.assertFalse(validation_result['valid'], "Validation result is expected to be valid==false")
self.assertIn('valid', validation_result,
"Key 'valid' expected in validation result")
self.assertFalse(validation_result['valid'],
"Validation result is expected to be valid==false")
def test_valid_entity(self):
with open('test_cases/valid/valid.json','r') af f:
with open('test_cases/valid/valid.json', 'r') af f:
entity_file = json.load(f)
response = self.fetch('/v0/validate',
method='POST',
body=json.dumps(entity_file))
self.assertEqual(200, response.code, "Validation must always return 200")
self.assertEqual(200, response.code,
"Validation must always return 200")
validation_result = json.loads(response.body.decode())
self.assertIn('valid', validation_result, "Key 'valid' expected in validation result")
self.assertTrue(validation_result['valid'], "Validation result is expected to be valid==true")
self.assertIn('valid', validation_result,
"Key 'valid' expected in validation result")
self.assertTrue(validation_result['valid'],
"Validation result is expected to be valid==true")
def test_invalid_iban(self):
with open('test_cases/invalid/invalid_iban.json','r') af f:
with open('test_cases/invalid/invalid_iban.json', 'r') af f:
entity_file = json.load(f)
response = self.fetch('/v0/validate',
method='POST',
body=json.dumps(entity_file))
self.assertEqual(200, response.code, "Validation must always return 200")
self.assertEqual(200, response.code,
"Validation must always return 200")
validation_result = json.loads(response.body.decode())
self.assertIn('valid', validation_result, "Key 'valid' expected in validation result")
self.assertFalse(validation_result['valid'], "Validation result is expected to be valid==false")
self.assertIn('valid', validation_result,
"Key 'valid' expected in validation result")
self.assertFalse(validation_result['valid'],
"Validation result is expected to be valid==false")
def test_missing_id(self):
with open('test_cases/invalid/missing_id.json','r') af f:
with open('test_cases/invalid/missing_id.json', 'r') af f:
entity_file = json.load(f)
response = self.fetch('/v0/validate',
method='POST',
body=json.dumps(entity_file))
self.assertEqual(200, response.code, "Validation must always return 200")
method='POST',
body=json.dumps(entity_file))
self.assertEqual(200, response.code,
"Validation must always return 200")
validation_result = json.loads(response.body.decode())
self.assertIn('valid', validation_result, "Key 'valid' expected in validation result")
self.assertFalse(validation_result['valid'], "Validation result is expected to be valid==false")
self.assertIn('valid', validation_result,
"Key 'valid' expected in validation result")
self.assertFalse(validation_result['valid'],
"Validation result is expected to be valid==false")
self.assertIn('id', validation_result['errors'])
def test_invalid_id(self):
with open('test_cases/invalid/invalid_id.json','r') af f:
with open('test_cases/invalid/invalid_id.json', 'r') af f:
entity_file = json.load(f)
response = self.fetch('/v0/validate',
method='POST',
body=json.dumps(entity_file))
self.assertEqual(200, response.code, "Validation must always return 200")
method='POST',
body=json.dumps(entity_file))
self.assertEqual(200, response.code,
"Validation must always return 200")
validation_result = json.loads(response.body.decode())
self.assertIn('valid', validation_result, "Key 'valid' expected in validation result")
self.assertFalse(validation_result['valid'], "Validation result is expected to be valid==false")
self.assertIn('valid', validation_result,
"Key 'valid' expected in validation result")
self.assertFalse(validation_result['valid'],
"Validation result is expected to be valid==false")
self.assertIn('id', validation_result['errors'])
if __name__ == "__main__":
unittest.main()

View file

@ -2,6 +2,7 @@ from schwifty import IBAN, BIC
import datetime
from validator_collection import validators, errors
def valid_iban(field, value, error):
try:
IBAN(value)
@ -9,6 +10,7 @@ def valid_iban(field, value, error):
except ValueError:
error(field, 'not a valid IBAN')
def valid_bic(field, value, error):
try:
BIC(value)
@ -16,6 +18,7 @@ def valid_bic(field, value, error):
except ValueError:
error(field, 'not a valid BIC')
def iso_date(field, value, error):
try:
datetime.datetime.strptime(value, "%Y-%m-%d")
@ -23,6 +26,7 @@ def iso_date(field, value, error):
except ValueError:
error(field, 'not a valid ISO 8601 date')
def valid_money_amount(field, value, error):
try:
# value is string, check formatting by parsing as float
@ -31,9 +35,10 @@ def valid_money_amount(field, value, error):
except (ValueError, TypeError):
error(field, 'not a valid money value')
def valid_email(field, value, error):
try:
validators.email(value)
return True
except errors.InvalidEmailError:
error(field, 'not a valid email')
error(field, 'not a valid email')