Skip to content

Commit

Permalink
Merge pull request #223 from olinlibrary/osteele/test-events
Browse files Browse the repository at this point in the history
Test /events and /labels, especially auth
  • Loading branch information
osteele authored May 5, 2018
2 parents 2f5355f + 5eebfda commit d765131
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 31 deletions.
12 changes: 6 additions & 6 deletions abe/resource_models/label_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class LabelApi(Resource):
def get(self, label_name=None):
"""Retrieve labels"""
if label_name: # use label name/object id if present
logging.debug('Label requested: ' + label_name)
logging.debug('Label requested: %s', label_name)
search_fields = ['name', 'id']
result = multi_search(db.Label, label_name, search_fields)
if not result:
Expand All @@ -52,12 +52,12 @@ def get(self, label_name=None):
def post(self):
"""Create new label with parameters passed in through args or form"""
received_data = request_to_dict(request)
logging.debug("Received POST data: {}".format(received_data))
logging.debug("Received POST data: %s", received_data)
try:
new_label = db.Label(**received_data)
new_label.save()
except ValidationError as error:
logging.warning("POST request rejected: {}".format(str(error)))
logging.debug("POST request rejected: %s", error)
return {'error_type': 'validation',
'validation_errors': [str(err) for err in error.errors],
'error_message': error.message}, 400
Expand All @@ -69,7 +69,7 @@ def post(self):
def put(self, label_name):
"""Modify individual label"""
received_data = request_to_dict(request)
logging.debug("Received PUT data: {}".format(received_data))
logging.debug("Received PUT data: %s", received_data)
search_fields = ['name', 'id']
result = multi_search(db.Label, label_name, search_fields)
if not result:
Expand All @@ -88,14 +88,14 @@ def put(self, label_name):
@edit_auth_required
def delete(self, label_name):
"""Delete individual label"""
logging.debug('Label requested: ' + label_name)
logging.debug('Label requested: %s', label_name)
search_fields = ['name', 'id']
result = multi_search(db.Label, label_name, search_fields)
if not result:
return "Label not found with identifier '{}'".format(label_name), 404

received_data = request_to_dict(request)
logging.debug("Received DELETE data: {}".format(received_data))
logging.debug("Received DELETE data: %s", received_data)
result.delete()
return mongo_to_dict(result)

Expand Down
2 changes: 1 addition & 1 deletion tests/context.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
"""Provide context for imports of ABE.
Referenced from The Hitchhiker's Guide to Python.
http://docs.python-guide.org/en/latest/writing/structure/#test-suite
Expand All @@ -10,6 +9,7 @@

MONGODB_TEST_DB_NAME = "abe-unittest"
os.environ["DB_NAME"] = MONGODB_TEST_DB_NAME
os.environ["INTRANET_IPS"] = "127.0.0.1/24"
os.environ["MONGO_URI"] = ""

os.environ['ABE_EMAIL_USERNAME'] = 'email-test-user'
Expand Down
26 changes: 2 additions & 24 deletions tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def test_add_sample_events(self):
data=flask.json.dumps(event), # use flask.json for datetimes
content_type='application/json'
)
self.assertEqual(response._status_code, 201) # check only status code
self.assertEqual(response.status_code, 201) # check only status code

def test_add_sample_labels(self):
"""Adds the sample labels to the database"""
Expand All @@ -44,26 +44,4 @@ def test_add_sample_labels(self):
data=flask.json.dumps(event),
content_type='application/json'
)
self.assertEqual(response._status_code, 201)

def test_date_range(self):
from abe import database as db
sample_data.load_data(db)

with self.subTest("a six-month query returns some events"):
response = self.app.get('/events/?start=2017-01-01&end=2017-07-01')
self.assertEqual(response._status_code, 200)
self.assertEqual(len(flask.json.loads(response.data)), 25)

with self.subTest("a one-year query returns all events"):
response = self.app.get('/events/?start=2017-01-01&end=2018-01-01')
self.assertEqual(response._status_code, 200)
self.assertEqual(len(flask.json.loads(response.data)), 69)

with self.subTest("a two-year query is too long"):
response = self.app.get('/events/?start=2017-01-01&end=2019-01-01')
self.assertEqual(response._status_code, 404)

with self.subTest("a one-year query works for leap years"):
response = self.app.get('/events/?start=2020-01-01&end=2021-01-01')
self.assertEqual(response._status_code, 200)
self.assertEqual(response.status_code, 201)
103 changes: 103 additions & 0 deletions tests/test_events.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from unittest import skip

import flask
import isodate

from . import abe_unittest
from .context import abe # noqa: F401

# These imports have to happen after .context sets the environment variables
import abe.app # isort:skip
from abe import sample_data # isort:skip


class EventsTestCase(abe_unittest.TestCase):

def setUp(self):
super().setUp()
self.app = abe.app.app.test_client()
sample_data.load_data(self.db)

def test_get_events(self):
with self.subTest("a six-month query returns some events"):
response = self.app.get('/events/?start=2017-01-01&end=2017-07-01')
self.assertEqual(response.status_code, 200)
self.assertEqual(len(flask.json.loads(response.data)), 25)

with self.subTest("a one-year query returns all events"):
response = self.app.get('/events/?start=2017-01-01&end=2018-01-01')
self.assertEqual(response.status_code, 200)
self.assertEqual(len(flask.json.loads(response.data)), 69)

with self.subTest("a two-year query is too long"):
response = self.app.get('/events/?start=2017-01-01&end=2019-01-01')
self.assertEqual(response.status_code, 404)

with self.subTest("a one-year query works for leap years"):
response = self.app.get('/events/?start=2020-01-01&end=2021-01-01')
self.assertEqual(response.status_code, 200)

with self.subTest("an unauthenticated sender retrieves only public events"):
event_response = self.app.get('/events/?start=2017-01-01&end=2017-07-01')
# TODO: change the following when #75 is implemented
self.assertEqual(len(flask.json.loads(event_response.data)), 25)

def test_post(self):
event = {
'title': 'test_post',
'start': isodate.parse_datetime('2018-05-04T09:00:00')
}

with self.subTest("succeeds when required fields are present"):
response = self.app.post(
'/events/',
data=flask.json.dumps(event),
content_type='application/json'
)
self.assertEqual(response.status_code, 201)

with self.subTest("fails when fields are missing"):
evt = event.copy()
del evt['title']
response = self.app.post(
'/events/',
data=flask.json.dumps(evt),
content_type='application/json'
)
self.assertEqual(response.status_code, 400)
self.assertRegex(flask.json.loads(response.data)['error_message'], r"^ValidationError.*'title'")

evt = event.copy()
del evt['start']
response = self.app.post(
'/events/',
data=flask.json.dumps(evt),
content_type='application/json'
)
self.assertEqual(response.status_code, 400)
self.assertRegex(flask.json.loads(response.data)['error_message'], r"^ValidationError.*'start'")

with self.subTest("fails when the client is not authorized"):
response = self.app.post(
'/events/',
data=flask.json.dumps(event),
content_type='application/json',
headers={'X-Forwarded-For': '192.168.1.1'}
)
self.assertEqual(response.status_code, 401)

@skip("Unimplemented test")
def test_put(self):
# TODO: test success
# TODO: test invalid id
# TODO: test invalid data
# TODO: test unauthorized user
pass

@skip("Unimplemented test")
def test_delete(self):
# TODO: test success
# TODO: test invalid id
# TODO: test invalid data
# TODO: test unauthorized user
pass
94 changes: 94 additions & 0 deletions tests/test_labels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import flask

from . import abe_unittest
from .context import abe # noqa: F401

# These imports have to happen after .context sets the environment variables
import abe.app # isort:skip
from abe import sample_data # isort:skip


class LabelsTestCase(abe_unittest.TestCase):

def setUp(self):
super().setUp()
self.app = abe.app.app.test_client()
sample_data.load_data(self.db)

def test_get(self):
response = self.app.get('/labels/')
self.assertEqual(response.status_code, 200)
labels = flask.json.loads(response.data)
self.assertEqual(len(labels), 15)
label = next((l for l in labels if l['name'] == 'library'), None)
self.assertIsNotNone(label)
self.assertEqual(label['name'], 'library')
self.assertEqual(label['color'], '#26AAA5')
self.assertRegex(label['description'], r'relating to the Olin Library')
self.assertEqual(label['url'], 'http://library.olin.edu/')

def test_post(self):
label1 = {
'name': 'label-test',
}
with self.subTest("succeeds when required fields are present"):
response = self.app.post(
'/labels/',
data=flask.json.dumps(label1),
content_type='application/json'
)
self.assertEqual(response.status_code, 201)

# FIXME:
# with self.subTest("fails on a duplicate label name"):
# response = self.app.post(
# '/labels/',
# data=flask.json.dumps(label1),
# content_type='application/json'
# )
# self.assertEqual(response.status_code, 400)

with self.subTest("fails when fields are missing"):
response = self.app.post(
'/labels/',
data=flask.json.dumps({}),
content_type='application/json'
)
self.assertEqual(response.status_code, 400)
self.assertRegex(flask.json.loads(response.data)['error_message'], r"^ValidationError.*'name'")

with self.subTest("fails when the client is not authorized"):
label = {
'name': 'label-test-2',
}
response = self.app.post(
'/labels/',
data=flask.json.dumps(label),
content_type='application/json',
headers={'X-Forwarded-For': '192.168.1.1'}
)
self.assertEqual(response.status_code, 401)

def test_put(self):
# TODO: test success
# TODO: test invalid id
# TODO: test invalid data
with self.subTest("fails when the client is not authorized"):
response = self.app.put(
'/labels/library',
data=flask.json.dumps({'description': 'new description'}),
content_type='application/json',
headers={'X-Forwarded-For': '192.168.1.1'}
)
self.assertEqual(response.status_code, 401)

def test_delete(self):
# TODO: test success
# TODO: test invalid id
# TODO: test invalid data
with self.subTest("fails when the client is not authorized"):
response = self.app.delete(
'/labels/library',
headers={'X-Forwarded-For': '192.168.1.1'}
)
self.assertEqual(response.status_code, 401)

0 comments on commit d765131

Please sign in to comment.