Commit 090d0d44 by David Baumgold

Fix up unit tests

parent a608d8a3
import json
from datetime import datetime
from io import BytesIO
from pytz import UTC
from unittest import TestCase
from .utils import CourseTestCase
from django.core.urlresolvers import reverse
from contentstore.views import assets
class AssetsTestCase(CourseTestCase):
def setUp(self):
super(AssetsTestCase, self).setUp()
self.url = reverse("asset_index", kwargs={
'org': self.course.location.org,
'course': self.course.location.course,
'name': self.course.location.name,
})
def test_basic(self):
resp = self.client.get(self.url)
self.assertEquals(resp.status_code, 200)
def test_json(self):
resp = self.client.get(
self.url,
HTTP_ACCEPT="application/json",
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
)
self.assertEquals(resp.status_code, 200)
content = json.loads(resp.content)
self.assertIsInstance(content, list)
class UploadTestCase(CourseTestCase):
def setUp(self):
super(UploadTestCase, self).setUp()
self.url = reverse("upload_asset", kwargs={
'org': self.course.location.org,
'course': self.course.location.course,
'coursename': self.course.location.name,
})
def test_happy_path(self):
f = BytesIO("sample content")
f.name = "sample.txt"
resp = self.client.post(self.url, {"name": "my-name", "file": f})
self.assert2XX(resp.status_code)
def test_no_file(self):
resp = self.client.post(self.url, {"name": "file.txt"})
self.assert4XX(resp.status_code)
def test_get(self):
resp = self.client.get(self.url)
self.assertEquals(resp.status_code, 405)
class AssetsToJsonTestCase(TestCase):
def test_basic(self):
upload_date = datetime(2013, 6, 1, 10, 30, tzinfo=UTC)
asset = {
"displayname": "foo",
"chunkSize": 512,
"filename": "foo.png",
"length": 100,
"uploadDate": upload_date,
"_id": {
"course": "course",
"org": "org",
"revision": 12,
"category": "category",
"name": "name",
"tag": "tag",
}
}
output = assets.assets_to_json_dict([asset])
self.assertEquals(len(output), 1)
compare = output[0]
self.assertEquals(compare["name"], "foo")
self.assertEquals(compare["path"], "foo.png")
self.assertEquals(compare["uploaded"], upload_date.isoformat())
self.assertEquals(compare["id"], "/tag/org/course/12/category/name")
import json
import mock
from unittest import TestCase
from .utils import CourseTestCase
from django.core.urlresolvers import reverse
from contentstore.utils import get_modulestore
from xmodule.modulestore.inheritance import own_metadata
from contentstore.views.course import (
validate_textbook_json, TextbookValidationError)
validate_textbooks_json, validate_textbook_json, TextbookValidationError)
class TextbookTestCase(CourseTestCase):
class TextbookIndexTestCase(CourseTestCase):
def setUp(self):
super(TextbookTestCase, self).setUp()
super(TextbookIndexTestCase, self).setUp()
self.url = reverse('textbook_index', kwargs={
'org': self.course.location.org,
'course': self.course.location.course,
......@@ -20,7 +20,7 @@ class TextbookTestCase(CourseTestCase):
def test_view_index(self):
resp = self.client.get(self.url)
self.assertEqual(resp.status_code, 200)
self.assert2XX(resp.status_code)
# we don't have resp.context right now,
# due to bugs in our testing harness :(
if resp.context:
......@@ -32,7 +32,7 @@ class TextbookTestCase(CourseTestCase):
HTTP_ACCEPT="application/json",
HTTP_X_REQUESTED_WITH='XMLHttpRequest'
)
self.assertEqual(resp.status_code, 200)
self.assert2XX(resp.status_code)
obj = json.loads(resp.content)
self.assertEqual(self.course.pdf_textbooks, obj)
......@@ -48,13 +48,17 @@ class TextbookTestCase(CourseTestCase):
HTTP_ACCEPT="application/json",
HTTP_X_REQUESTED_WITH='XMLHttpRequest'
)
self.assertEqual(resp.status_code, 204)
self.assertEqual(resp.content, "")
self.assert2XX(resp.status_code)
# reload course
store = get_modulestore(self.course.location)
course = store.get_item(self.course.location)
self.assertEqual(course.pdf_textbooks, textbooks)
# should be the same, except for added ID
no_ids = []
for textbook in course.pdf_textbooks:
del textbook["id"]
no_ids.append(textbook)
self.assertEqual(no_ids, textbooks)
def test_view_index_xhr_post_invalid(self):
resp = self.client.post(
......@@ -64,43 +68,271 @@ class TextbookTestCase(CourseTestCase):
HTTP_ACCEPT="application/json",
HTTP_X_REQUESTED_WITH='XMLHttpRequest'
)
self.assertEqual(resp.status_code, 400)
self.assert4XX(resp.status_code)
obj = json.loads(resp.content)
self.assertIn("error", obj)
class TextbookValidationTestCase(TestCase):
class TextbookCreateTestCase(CourseTestCase):
def setUp(self):
super(TextbookCreateTestCase, self).setUp()
self.url = reverse('create_textbook', kwargs={
'org': self.course.location.org,
'course': self.course.location.course,
'name': self.course.location.name,
})
self.textbook = {
"tab_title": "Economics",
"chapters": {
"title": "Chapter 1",
"url": "/a/b/c/ch1.pdf",
}
}
def test_happy_path(self):
textbooks = [
{
"tab_title": "Hi, mom!",
"url": "/mom.pdf"
},
{
"tab_title": "Textbook 2",
"chapters": [
{
"title": "Chapter 1",
"url": "/ch1.pdf"
}, {
"title": "Chapter 2",
"url": "/ch2.pdf"
}
]
resp = self.client.post(
self.url,
data=json.dumps(self.textbook),
content_type="application/json",
HTTP_ACCEPT="application/json",
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
)
self.assertEqual(resp.status_code, 201)
self.assertIn("Location", resp)
textbook = json.loads(resp.content)
self.assertIn("id", textbook)
del textbook["id"]
self.assertEqual(self.textbook, textbook)
def test_get(self):
resp = self.client.get(
self.url,
HTTP_ACCEPT="application/json",
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
)
self.assertEqual(resp.status_code, 405)
def test_valid_id(self):
self.textbook["id"] = "7x5"
resp = self.client.post(
self.url,
data=json.dumps(self.textbook),
content_type="application/json",
HTTP_ACCEPT="application/json",
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
)
self.assertEqual(resp.status_code, 201)
textbook = json.loads(resp.content)
self.assertEqual(self.textbook, textbook)
def test_invalid_id(self):
self.textbook["id"] = "xxx"
resp = self.client.post(
self.url,
data=json.dumps(self.textbook),
content_type="application/json",
HTTP_ACCEPT="application/json",
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
)
self.assert4XX(resp.status_code)
self.assertNotIn("Location", resp)
class TextbookByIdTestCase(CourseTestCase):
def setUp(self):
super(TextbookByIdTestCase, self).setUp()
self.textbook1 = {
"tab_title": "Economics",
"id": 1,
"chapters": {
"title": "Chapter 1",
"url": "/a/b/c/ch1.pdf",
}
]
}
self.url1 = reverse('textbook_by_id', kwargs={
'org': self.course.location.org,
'course': self.course.location.course,
'name': self.course.location.name,
'tid': 1,
})
self.textbook2 = {
"tab_title": "Algebra",
"id": 2,
"chapters": {
"title": "Chapter 11",
"url": "/a/b/ch11.pdf",
}
}
self.url2 = reverse('textbook_by_id', kwargs={
'org': self.course.location.org,
'course': self.course.location.course,
'name': self.course.location.name,
'tid': 2,
})
self.course.pdf_textbooks = [self.textbook1, self.textbook2]
self.store = get_modulestore(self.course.location)
self.store.update_metadata(self.course.location, own_metadata(self.course))
self.url_nonexist = reverse('textbook_by_id', kwargs={
'org': self.course.location.org,
'course': self.course.location.course,
'name': self.course.location.name,
'tid': 20,
})
def test_get_1(self):
resp = self.client.get(self.url1)
self.assert2XX(resp.status_code)
compare = json.loads(resp.content)
self.assertEqual(compare, self.textbook1)
def test_get_2(self):
resp = self.client.get(self.url2)
self.assert2XX(resp.status_code)
compare = json.loads(resp.content)
self.assertEqual(compare, self.textbook2)
def test_get_nonexistant(self):
resp = self.client.get(self.url_nonexist)
self.assertEqual(resp.status_code, 404)
def test_delete(self):
resp = self.client.delete(self.url1)
self.assert2XX(resp.status_code)
course = self.store.get_item(self.course.location)
self.assertEqual(course.pdf_textbooks, [self.textbook2])
def test_delete_nonexistant(self):
resp = self.client.delete(self.url_nonexist)
self.assertEqual(resp.status_code, 404)
course = self.store.get_item(self.course.location)
self.assertEqual(course.pdf_textbooks, [self.textbook1, self.textbook2])
def test_create_new_by_id(self):
textbook = {
"tab_title": "a new textbook",
"url": "supercool.pdf",
"id": "1supercool",
}
url = reverse("textbook_by_id", kwargs={
'org': self.course.location.org,
'course': self.course.location.course,
'name': self.course.location.name,
'tid': "1supercool",
})
resp = self.client.post(
url,
data=json.dumps(textbook),
content_type="application/json",
)
self.assertEqual(resp.status_code, 201)
resp2 = self.client.get(url)
self.assert2XX(resp2.status_code)
compare = json.loads(resp2.content)
self.assertEqual(compare, textbook)
course = self.store.get_item(self.course.location)
self.assertEqual(
course.pdf_textbooks,
[self.textbook1, self.textbook2, textbook]
)
def test_replace_by_id(self):
replacement = {
"tab_title": "You've been replaced!",
"url": "supercool.pdf",
"id": "2",
}
resp = self.client.post(
self.url2,
data=json.dumps(replacement),
content_type="application/json",
)
self.assertEqual(resp.status_code, 201)
resp2 = self.client.get(self.url2)
self.assert2XX(resp2.status_code)
compare = json.loads(resp2.content)
self.assertEqual(compare, replacement)
course = self.store.get_item(self.course.location)
self.assertEqual(
course.pdf_textbooks,
[self.textbook1, replacement]
)
class TextbookValidationTestCase(TestCase):
def setUp(self):
self.tb1 = {
"tab_title": "Hi, mom!",
"url": "/mom.pdf"
}
self.tb2 = {
"tab_title": "Hi, dad!",
"chapters": [
{
"title": "Baseball",
"url": "baseball.pdf",
}, {
"title": "Basketball",
"url": "crazypants.pdf",
}
]
}
self.textbooks = [self.tb1, self.tb2]
def test_happy_path_plural(self):
result = validate_textbooks_json(json.dumps(self.textbooks))
self.assertEqual(self.textbooks, result)
def test_happy_path_singular_1(self):
result = validate_textbook_json(json.dumps(self.tb1))
self.assertEqual(self.tb1, result)
def test_happy_path_singular_2(self):
result = validate_textbook_json(json.dumps(self.tb2))
self.assertEqual(self.tb2, result)
result = validate_textbook_json(json.dumps(textbooks))
self.assertEqual(textbooks, result)
def test_valid_id(self):
self.tb1["id"] = 1
result = validate_textbook_json(json.dumps(self.tb1))
self.assertEqual(self.tb1, result)
def test_invalid_id(self):
self.tb1["id"] = "abc"
with self.assertRaises(TextbookValidationError):
validate_textbook_json(json.dumps(self.tb1))
def test_invalid_json_plural(self):
with self.assertRaises(TextbookValidationError):
validate_textbooks_json("[{'abc'}]")
def test_invalid_json_singular(self):
with self.assertRaises(TextbookValidationError):
validate_textbook_json("[{1]}")
def test_wrong_json_plural(self):
with self.assertRaises(TextbookValidationError):
validate_textbooks_json('{"tab_title": "Hi, mom!"}')
def test_wrong_json_singular(self):
with self.assertRaises(TextbookValidationError):
validate_textbook_json('[{"tab_title": "Hi, mom!"}, {"tab_title": "Hi, dad!"}]')
def test_invalid_json(self):
def test_no_tab_title_plural(self):
with self.assertRaises(TextbookValidationError):
validate_textbook_json("[{'abc'}]")
validate_textbooks_json('[{"url": "/textbook.pdf"}]')
def test_wrong_json(self):
def test_no_tab_title_singular(self):
with self.assertRaises(TextbookValidationError):
validate_textbook_json('{"tab_title": "Hi, mom!"}')
validate_textbook_json('{"url": "/textbook.pdf"}')
def test_no_tab_title(self):
def test_duplicate_ids(self):
textbooks = [{
"tab_title": "name one",
"url": "one.pdf",
"id": 1,
}, {
"tab_title": "name two",
"url": "two.pdf",
"id": 1,
}]
with self.assertRaises(TextbookValidationError):
validate_textbook_json('[{"url": "/textbook.pdf"}')
validate_textbooks_json(json.dumps(textbooks))
......@@ -13,6 +13,7 @@ from django_future.csrf import ensure_csrf_cookie
from django.core.urlresolvers import reverse
from django.core.servers.basehttp import FileWrapper
from django.core.files.temp import NamedTemporaryFile
from django.views.decorators.http import require_POST
from mitxmako.shortcuts import render_to_response
from cache_toolbox.core import del_cached_content
......@@ -30,6 +31,7 @@ from xmodule.exceptions import NotFoundError
from ..utils import get_url_reverse
from .access import get_location_and_verify_access
from util.json_request import JsonResponse
__all__ = ['asset_index', 'upload_asset', 'import_course', 'generate_export_course', 'export_course']
......@@ -89,7 +91,7 @@ def asset_index(request, org, course, name):
assets = sorted(assets, key=lambda asset: asset['uploadDate'], reverse=True)
if request.META.get('HTTP_ACCEPT', "").startswith("application/json"):
return HttpResponse(json.dumps(assets_to_json_dict(assets)), content_type="application/json")
return JsonResponse(assets_to_json_dict(assets))
asset_display = []
for asset in assets:
......@@ -120,6 +122,7 @@ def asset_index(request, org, course, name):
})
@require_POST
@ensure_csrf_cookie
@login_required
def upload_asset(request, org, course, coursename):
......@@ -127,10 +130,6 @@ def upload_asset(request, org, course, coursename):
This method allows for POST uploading of files into the course asset library, which will
be supported by GridFS in MongoDB.
'''
if request.method != 'POST':
# (cdodge) @todo: Is there a way to do a - say - 'raise Http400'?
return HttpResponseBadRequest()
# construct a location from the passed in path
location = get_location_and_verify_access(request, org, course, coursename)
......
......@@ -8,7 +8,7 @@ import string
from django.contrib.auth.decorators import login_required
from django_future.csrf import ensure_csrf_cookie
from django.conf import settings
from django.views.decorators.http import require_http_methods
from django.views.decorators.http import require_http_methods, require_POST
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseBadRequest
......@@ -521,9 +521,9 @@ def textbook_index(request, org, course, name):
})
@require_POST
@login_required
@ensure_csrf_cookie
@require_http_methods(("POST",))
def create_textbook(request, org, course, name):
location = get_location_and_verify_access(request, org, course, name)
store = get_modulestore(location)
......@@ -531,7 +531,7 @@ def create_textbook(request, org, course, name):
try:
textbook = validate_textbook_json(request.body)
except TextbookValidationError:
except TextbookValidationError as e:
return JsonResponse({"error": e.message}, status=400)
if not textbook.get("id"):
tids = set(t["id"] for t in course_module.pdf_textbooks if "id" in t)
......@@ -555,7 +555,8 @@ def textbook_by_id(request, org, course, name, tid):
location = get_location_and_verify_access(request, org, course, name)
store = get_modulestore(location)
course_module = store.get_item(location, depth=3)
matching_id = [tb for tb in course_module.pdf_textbooks if tb.get("id") == tid]
matching_id = [tb for tb in course_module.pdf_textbooks
if str(tb.get("id")) == str(tid)]
if matching_id:
textbook = matching_id[0]
else:
......@@ -589,4 +590,4 @@ def textbook_by_id(request, org, course, name, tid):
new_textbooks.extend(course_module.pdf_textbooks[i+1:])
course_module.pdf_textbooks = new_textbooks
store.update_metadata(course_module.location, own_metadata(course_module))
return JsonResponse(new_textbook)
return JsonResponse()
from django.http import HttpResponse
from util.json_request import JsonResponse
import json
import unittest
class JsonResponseTestCase(unittest.TestCase):
def test_empty(self):
resp = JsonResponse()
self.assertIsInstance(resp, HttpResponse)
self.assertEqual(resp.content, "")
self.assertEqual(resp.status_code, 204)
self.assertEqual(resp["content-type"], "application/json")
def test_empty_string(self):
resp = JsonResponse("")
self.assertIsInstance(resp, HttpResponse)
self.assertEqual(resp.content, "")
self.assertEqual(resp.status_code, 204)
self.assertEqual(resp["content-type"], "application/json")
def test_string(self):
resp = JsonResponse("foo")
self.assertEqual(resp.content, '"foo"')
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp["content-type"], "application/json")
def test_dict(self):
obj = {"foo": "bar"}
resp = JsonResponse(obj)
compare = json.loads(resp.content)
self.assertEqual(obj, compare)
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp["content-type"], "application/json")
def test_set_status(self):
obj = {"error": "resource not found"}
resp = JsonResponse(obj, status=404)
compare = json.loads(resp.content)
self.assertEqual(obj, compare)
self.assertEqual(resp.status_code, 404)
self.assertEqual(resp["content-type"], "application/json")
......@@ -6,6 +6,7 @@ from django.test import TestCase
from django.conf import settings
import xmodule.modulestore.django
from xmodule.templates import update_templates
from unittest.util import safe_repr
def mongo_store_config(data_dir):
......@@ -183,3 +184,23 @@ class ModuleStoreTestCase(TestCase):
# Call superclass implementation
super(ModuleStoreTestCase, self)._post_teardown()
def assert2XX(self, status_code, msg=None):
if not 200 <= status_code < 300:
msg = self._formatMessage(msg, "%s is not a success status" % safe_repr(status_code))
raise self.failureExecption(msg)
def assert3XX(self, status_code, msg=None):
if not 300 <= status_code < 400:
msg = self._formatMessage(msg, "%s is not a redirection status" % safe_repr(status_code))
raise self.failureExecption(msg)
def assert4XX(self, status_code, msg=None):
if not 400 <= status_code < 500:
msg = self._formatMessage(msg, "%s is not a client error status" % safe_repr(status_code))
raise self.failureExecption(msg)
def assert5XX(self, status_code, msg=None):
if not 500 <= status_code < 600:
msg = self._formatMessage(msg, "%s is not a server error status" % safe_repr(status_code))
raise self.failureExecption(msg)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment