Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test /events and /labels, especially auth #223

Merged
merged 4 commits into from
May 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -38,7 +38,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 @@ -48,26 +48,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)