Add forum utility code unit test coverage
This is in preparation for significant refactoring of the code in question.
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
from datetime import datetime
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
from student.tests.factories import UserFactory, CourseEnrollmentFactory
|
||||
from django_comment_common.models import Role, Permission
|
||||
from factories import RoleFactory
|
||||
import django_comment_client.utils as utils
|
||||
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE
|
||||
|
||||
class DictionaryTestCase(TestCase):
|
||||
def test_extract(self):
|
||||
@@ -29,128 +34,6 @@ class DictionaryTestCase(TestCase):
|
||||
self.assertEqual(utils.merge_dict(d1, d2), expected)
|
||||
|
||||
|
||||
class CategorySortTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.category_map = {
|
||||
'entries': {
|
||||
u'General': {
|
||||
'sort_key': u'General'
|
||||
}
|
||||
},
|
||||
'subcategories': {
|
||||
u'Tests': {
|
||||
'sort_key': u'Tests',
|
||||
'subcategories': {},
|
||||
'entries': {
|
||||
u'Quizzes': {
|
||||
'sort_key': None
|
||||
}, u'All': {
|
||||
'sort_key': None
|
||||
}, u'Final Exam': {
|
||||
'sort_key': None
|
||||
},
|
||||
}
|
||||
},
|
||||
u'Assignments': {
|
||||
'sort_key': u'Assignments',
|
||||
'subcategories': {},
|
||||
'entries': {
|
||||
u'Homework': {
|
||||
'sort_key': None
|
||||
},
|
||||
u'All': {
|
||||
'sort_key': None
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def test_alpha_sort_true(self):
|
||||
expected_true = {
|
||||
'entries': {
|
||||
u'General': {
|
||||
'sort_key': u'General'
|
||||
}
|
||||
},
|
||||
'children': [u'Assignments', u'General', u'Tests'],
|
||||
'subcategories': {
|
||||
u'Tests': {
|
||||
'sort_key': u'Tests',
|
||||
'subcategories': {},
|
||||
'children': [u'All', u'Final Exam', u'Quizzes'],
|
||||
'entries': {
|
||||
u'All': {
|
||||
'sort_key': 'All'
|
||||
}, u'Final Exam': {
|
||||
'sort_key': 'Final Exam'
|
||||
}, u'Quizzes': {
|
||||
'sort_key': 'Quizzes'
|
||||
}
|
||||
}
|
||||
},
|
||||
u'Assignments': {
|
||||
'sort_key': u'Assignments',
|
||||
'subcategories': {},
|
||||
'children': [u'All', u'Homework'],
|
||||
'entries': {
|
||||
u'Homework': {
|
||||
'sort_key': 'Homework'
|
||||
},
|
||||
u'All': {
|
||||
'sort_key': 'All'
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
utils.sort_map_entries(self.category_map, True)
|
||||
self.assertEqual(self.category_map, expected_true)
|
||||
|
||||
def test_alpha_sort_false(self):
|
||||
expected_false = {
|
||||
'entries': {
|
||||
u'General': {
|
||||
'sort_key': u'General'
|
||||
}
|
||||
},
|
||||
'children': [u'Assignments', u'General', u'Tests'],
|
||||
'subcategories': {
|
||||
u'Tests': {
|
||||
'sort_key': u'Tests',
|
||||
'subcategories': {},
|
||||
'children': [u'Quizzes', u'All', u'Final Exam'],
|
||||
'entries': {
|
||||
u'Quizzes': {
|
||||
'sort_key': None
|
||||
}, u'All': {
|
||||
'sort_key': None
|
||||
}, u'Final Exam': {
|
||||
'sort_key': None
|
||||
},
|
||||
}
|
||||
},
|
||||
u'Assignments': {
|
||||
'sort_key': u'Assignments',
|
||||
'subcategories': {},
|
||||
'children': [u'All', u'Homework'],
|
||||
'entries': {
|
||||
u'Homework': {
|
||||
'sort_key': None
|
||||
},
|
||||
u'All': {
|
||||
'sort_key': None
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
utils.sort_map_entries(self.category_map, False)
|
||||
self.assertEqual(self.category_map, expected_false)
|
||||
|
||||
|
||||
class AccessUtilsTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.course_id = 'edX/toy/2012_Fall'
|
||||
@@ -179,3 +62,416 @@ class AccessUtilsTestCase(TestCase):
|
||||
|
||||
ret = utils.has_forum_access('student', self.course_id, 'NotARole')
|
||||
self.assertFalse(ret)
|
||||
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE)
|
||||
class CoursewareContextTestCase(ModuleStoreTestCase):
|
||||
def setUp(self):
|
||||
self.course = CourseFactory.create(org="TestX", number="101", display_name="Test Course")
|
||||
self.discussion1 = ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
category="discussion",
|
||||
discussion_id="discussion1",
|
||||
discussion_category="Chapter",
|
||||
discussion_target="Discussion 1"
|
||||
)
|
||||
self.discussion2 = ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
category="discussion",
|
||||
discussion_id="discussion2",
|
||||
discussion_category="Chapter / Section / Subsection",
|
||||
discussion_target="Discussion 2"
|
||||
)
|
||||
|
||||
def test_missing_commentable_id(self):
|
||||
thread = {"commentable_id": "non-inline"}
|
||||
self.assertEqual(utils.get_courseware_context(thread, self.course), None)
|
||||
|
||||
def test_basic(self):
|
||||
def test_discussion(discussion, expected_title):
|
||||
thread = {"commentable_id": discussion.discussion_id}
|
||||
courseware_context = utils.get_courseware_context(thread, self.course)
|
||||
self.assertEqual(set(courseware_context.keys()), set(["courseware_url", "courseware_title"]))
|
||||
self.assertEqual(
|
||||
courseware_context["courseware_url"],
|
||||
reverse(
|
||||
"jump_to",
|
||||
kwargs={
|
||||
"course_id": self.course.location.course_id,
|
||||
"location": discussion.location
|
||||
}
|
||||
)
|
||||
)
|
||||
self.assertEqual(
|
||||
courseware_context["courseware_title"],
|
||||
expected_title
|
||||
)
|
||||
|
||||
test_discussion(self.discussion1, "Chapter / Discussion 1")
|
||||
test_discussion(self.discussion2, " Subsection / Discussion 2")
|
||||
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE)
|
||||
class CategoryMapTestCase(ModuleStoreTestCase):
|
||||
def setUp(self):
|
||||
self.course = CourseFactory.create(org="TestX", number="101", display_name="Test Course")
|
||||
# Courses get a default discussion topic on creation, so remove it
|
||||
self.course.discussion_topics = {}
|
||||
self.course.save()
|
||||
self.discussion_num = 0
|
||||
self.maxDiff = None #pylint: disable=C0103
|
||||
|
||||
def create_discussion(self, discussion_category, discussion_target, **kwargs):
|
||||
self.discussion_num += 1
|
||||
ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
category="discussion",
|
||||
discussion_id="discussion{}".format(self.discussion_num),
|
||||
discussion_category=discussion_category,
|
||||
discussion_target=discussion_target,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def assertCategoryMapEquals(self, expected):
|
||||
self.assertEqual(
|
||||
utils.get_discussion_category_map(self.course),
|
||||
expected
|
||||
)
|
||||
|
||||
def test_empty(self):
|
||||
self.assertEqual(
|
||||
utils.get_discussion_category_map(self.course),
|
||||
{"entries": {}, "subcategories": {}, "children": []}
|
||||
)
|
||||
|
||||
def test_configured_topics(self):
|
||||
self.course.discussion_topics = {
|
||||
"Topic A": {"id": "Topic_A"},
|
||||
"Topic B": {"id": "Topic_B"},
|
||||
"Topic C": {"id": "Topic_C"}
|
||||
}
|
||||
self.assertCategoryMapEquals(
|
||||
{
|
||||
"entries": {
|
||||
"Topic A": {"id": "Topic_A", "sort_key": "Topic A"},
|
||||
"Topic B": {"id": "Topic_B", "sort_key": "Topic B"},
|
||||
"Topic C": {"id": "Topic_C", "sort_key": "Topic C"},
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": ["Topic A", "Topic B", "Topic C"]
|
||||
}
|
||||
)
|
||||
|
||||
def test_single_inline(self):
|
||||
self.create_discussion("Chapter", "Discussion")
|
||||
self.assertCategoryMapEquals(
|
||||
{
|
||||
"entries": {},
|
||||
"subcategories": {
|
||||
"Chapter": {
|
||||
"entries": {
|
||||
"Discussion": {
|
||||
"id": "discussion1",
|
||||
"sort_key": None
|
||||
}
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": ["Discussion"]
|
||||
}
|
||||
},
|
||||
"children": ["Chapter"]
|
||||
}
|
||||
)
|
||||
|
||||
def test_tree(self):
|
||||
self.create_discussion("Chapter 1", "Discussion 1")
|
||||
self.create_discussion("Chapter 1", "Discussion 2")
|
||||
self.create_discussion("Chapter 2", "Discussion")
|
||||
self.create_discussion("Chapter 2 / Section 1 / Subsection 1", "Discussion")
|
||||
self.create_discussion("Chapter 2 / Section 1 / Subsection 2", "Discussion")
|
||||
self.create_discussion("Chapter 3 / Section 1", "Discussion")
|
||||
|
||||
self.assertCategoryMapEquals(
|
||||
{
|
||||
"entries": {},
|
||||
"subcategories": {
|
||||
"Chapter 1": {
|
||||
"entries": {
|
||||
"Discussion 1": {
|
||||
"id": "discussion1",
|
||||
"sort_key": None
|
||||
},
|
||||
"Discussion 2": {
|
||||
"id": "discussion2",
|
||||
"sort_key": None
|
||||
}
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": ["Discussion 1", "Discussion 2"]
|
||||
},
|
||||
"Chapter 2": {
|
||||
"entries": {
|
||||
"Discussion": {
|
||||
"id": "discussion3",
|
||||
"sort_key": None
|
||||
}
|
||||
},
|
||||
"subcategories": {
|
||||
"Section 1": {
|
||||
"entries": {},
|
||||
"subcategories": {
|
||||
"Subsection 1": {
|
||||
"entries": {
|
||||
"Discussion": {
|
||||
"id": "discussion4",
|
||||
"sort_key": None
|
||||
}
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": ["Discussion"]
|
||||
},
|
||||
"Subsection 2": {
|
||||
"entries": {
|
||||
"Discussion": {
|
||||
"id": "discussion5",
|
||||
"sort_key": None
|
||||
}
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": ["Discussion"]
|
||||
}
|
||||
},
|
||||
"children": ["Subsection 1", "Subsection 2"]
|
||||
}
|
||||
},
|
||||
"children": ["Discussion", "Section 1"]
|
||||
},
|
||||
"Chapter 3": {
|
||||
"entries": {},
|
||||
"subcategories": {
|
||||
"Section 1": {
|
||||
"entries": {
|
||||
"Discussion": {
|
||||
"id": "discussion6",
|
||||
"sort_key": None
|
||||
}
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": ["Discussion"]
|
||||
}
|
||||
},
|
||||
"children": ["Section 1"]
|
||||
}
|
||||
},
|
||||
"children": ["Chapter 1", "Chapter 2", "Chapter 3"]
|
||||
}
|
||||
)
|
||||
|
||||
def test_start_date_filter(self):
|
||||
now = datetime.now()
|
||||
later = datetime.max
|
||||
self.create_discussion("Chapter 1", "Discussion 1", start=now)
|
||||
self.create_discussion("Chapter 1", "Discussion 2", start=later)
|
||||
self.create_discussion("Chapter 2", "Discussion", start=now)
|
||||
self.create_discussion("Chapter 2 / Section 1 / Subsection 1", "Discussion", start=later)
|
||||
self.create_discussion("Chapter 2 / Section 1 / Subsection 2", "Discussion", start=later)
|
||||
self.create_discussion("Chapter 3 / Section 1", "Discussion", start=later)
|
||||
|
||||
self.assertCategoryMapEquals(
|
||||
{
|
||||
"entries": {},
|
||||
"subcategories": {
|
||||
"Chapter 1": {
|
||||
"entries": {
|
||||
"Discussion 1": {
|
||||
"id": "discussion1",
|
||||
"sort_key": None
|
||||
}
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": ["Discussion 1"]
|
||||
},
|
||||
"Chapter 2": {
|
||||
"entries": {
|
||||
"Discussion": {
|
||||
"id": "discussion3",
|
||||
"sort_key": None
|
||||
}
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": ["Discussion"]
|
||||
}
|
||||
},
|
||||
"children": ["Chapter 1", "Chapter 2"]
|
||||
}
|
||||
)
|
||||
|
||||
def test_sort_inline_explicit(self):
|
||||
self.create_discussion("Chapter", "Discussion 1", sort_key="D")
|
||||
self.create_discussion("Chapter", "Discussion 2", sort_key="A")
|
||||
self.create_discussion("Chapter", "Discussion 3", sort_key="E")
|
||||
self.create_discussion("Chapter", "Discussion 4", sort_key="C")
|
||||
self.create_discussion("Chapter", "Discussion 5", sort_key="B")
|
||||
|
||||
self.assertCategoryMapEquals(
|
||||
{
|
||||
"entries": {},
|
||||
"subcategories": {
|
||||
"Chapter": {
|
||||
"entries": {
|
||||
"Discussion 1": {
|
||||
"id": "discussion1",
|
||||
"sort_key": "D"
|
||||
},
|
||||
"Discussion 2": {
|
||||
"id": "discussion2",
|
||||
"sort_key": "A"
|
||||
},
|
||||
"Discussion 3": {
|
||||
"id": "discussion3",
|
||||
"sort_key": "E"
|
||||
},
|
||||
"Discussion 4": {
|
||||
"id": "discussion4",
|
||||
"sort_key": "C"
|
||||
},
|
||||
"Discussion 5": {
|
||||
"id": "discussion5",
|
||||
"sort_key": "B"
|
||||
}
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": [
|
||||
"Discussion 2",
|
||||
"Discussion 5",
|
||||
"Discussion 4",
|
||||
"Discussion 1",
|
||||
"Discussion 3"
|
||||
]
|
||||
}
|
||||
},
|
||||
"children": ["Chapter"]
|
||||
}
|
||||
)
|
||||
|
||||
def test_sort_configured_topics_explicit(self):
|
||||
self.course.discussion_topics = {
|
||||
"Topic A": {"id": "Topic_A", "sort_key": "B"},
|
||||
"Topic B": {"id": "Topic_B", "sort_key": "C"},
|
||||
"Topic C": {"id": "Topic_C", "sort_key": "A"}
|
||||
}
|
||||
self.assertCategoryMapEquals(
|
||||
{
|
||||
"entries": {
|
||||
"Topic A": {"id": "Topic_A", "sort_key": "B"},
|
||||
"Topic B": {"id": "Topic_B", "sort_key": "C"},
|
||||
"Topic C": {"id": "Topic_C", "sort_key": "A"},
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": ["Topic C", "Topic A", "Topic B"]
|
||||
}
|
||||
)
|
||||
|
||||
def test_sort_alpha(self):
|
||||
self.course.discussion_sort_alpha = True
|
||||
self.course.save()
|
||||
self.create_discussion("Chapter", "Discussion D")
|
||||
self.create_discussion("Chapter", "Discussion A")
|
||||
self.create_discussion("Chapter", "Discussion E")
|
||||
self.create_discussion("Chapter", "Discussion C")
|
||||
self.create_discussion("Chapter", "Discussion B")
|
||||
|
||||
self.assertCategoryMapEquals(
|
||||
{
|
||||
"entries": {},
|
||||
"subcategories": {
|
||||
"Chapter": {
|
||||
"entries": {
|
||||
"Discussion D": {
|
||||
"id": "discussion1",
|
||||
"sort_key": "Discussion D"
|
||||
},
|
||||
"Discussion A": {
|
||||
"id": "discussion2",
|
||||
"sort_key": "Discussion A"
|
||||
},
|
||||
"Discussion E": {
|
||||
"id": "discussion3",
|
||||
"sort_key": "Discussion E"
|
||||
},
|
||||
"Discussion C": {
|
||||
"id": "discussion4",
|
||||
"sort_key": "Discussion C"
|
||||
},
|
||||
"Discussion B": {
|
||||
"id": "discussion5",
|
||||
"sort_key": "Discussion B"
|
||||
}
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": [
|
||||
"Discussion A",
|
||||
"Discussion B",
|
||||
"Discussion C",
|
||||
"Discussion D",
|
||||
"Discussion E"
|
||||
]
|
||||
}
|
||||
},
|
||||
"children": ["Chapter"]
|
||||
}
|
||||
)
|
||||
|
||||
def test_sort_intermediates(self):
|
||||
self.create_discussion("Chapter B", "Discussion 2")
|
||||
self.create_discussion("Chapter C", "Discussion")
|
||||
self.create_discussion("Chapter A", "Discussion 1")
|
||||
self.create_discussion("Chapter B", "Discussion 1")
|
||||
self.create_discussion("Chapter A", "Discussion 2")
|
||||
|
||||
self.assertCategoryMapEquals(
|
||||
{
|
||||
"entries": {},
|
||||
"subcategories": {
|
||||
"Chapter A": {
|
||||
"entries": {
|
||||
"Discussion 1": {
|
||||
"id": "discussion3",
|
||||
"sort_key": None
|
||||
},
|
||||
"Discussion 2": {
|
||||
"id": "discussion5",
|
||||
"sort_key": None
|
||||
}
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": ["Discussion 1", "Discussion 2"]
|
||||
},
|
||||
"Chapter B": {
|
||||
"entries": {
|
||||
"Discussion 1": {
|
||||
"id": "discussion4",
|
||||
"sort_key": None
|
||||
},
|
||||
"Discussion 2": {
|
||||
"id": "discussion1",
|
||||
"sort_key": None
|
||||
}
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": ["Discussion 1", "Discussion 2"]
|
||||
},
|
||||
"Chapter C": {
|
||||
"entries": {
|
||||
"Discussion": {
|
||||
"id": "discussion2",
|
||||
"sort_key": None
|
||||
}
|
||||
},
|
||||
"subcategories": {},
|
||||
"children": ["Discussion"]
|
||||
}
|
||||
},
|
||||
"children": ["Chapter A", "Chapter B", "Chapter C"]
|
||||
}
|
||||
)
|
||||
|
||||
@@ -70,10 +70,10 @@ def get_discussion_id_map(course):
|
||||
|
||||
def get_discussion_category_map(course):
|
||||
initialize_discussion_info(course)
|
||||
return filter_unstarted_categories(_DISCUSSIONINFO[course.id]['category_map'])
|
||||
return _filter_unstarted_categories(_DISCUSSIONINFO[course.id]['category_map'])
|
||||
|
||||
|
||||
def filter_unstarted_categories(category_map):
|
||||
def _filter_unstarted_categories(category_map):
|
||||
|
||||
now = datetime.now(UTC())
|
||||
|
||||
@@ -111,7 +111,7 @@ def filter_unstarted_categories(category_map):
|
||||
return result_map
|
||||
|
||||
|
||||
def sort_map_entries(category_map, sort_alpha):
|
||||
def _sort_map_entries(category_map, sort_alpha):
|
||||
things = []
|
||||
for title, entry in category_map["entries"].items():
|
||||
if entry["sort_key"] == None and sort_alpha:
|
||||
@@ -119,7 +119,7 @@ def sort_map_entries(category_map, sort_alpha):
|
||||
things.append((title, entry))
|
||||
for title, category in category_map["subcategories"].items():
|
||||
things.append((title, category))
|
||||
sort_map_entries(category_map["subcategories"][title], sort_alpha)
|
||||
_sort_map_entries(category_map["subcategories"][title], sort_alpha)
|
||||
category_map["children"] = [x[0] for x in sorted(things, key=lambda x: x[1]["sort_key"])]
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ def initialize_discussion_info(course):
|
||||
"sort_key": entry.get("sort_key", topic),
|
||||
"start_date": datetime.now(UTC())}
|
||||
|
||||
sort_map_entries(category_map, course.discussion_sort_alpha)
|
||||
_sort_map_entries(category_map, course.discussion_sort_alpha)
|
||||
|
||||
_DISCUSSIONINFO[course.id]['id_map'] = discussion_id_map
|
||||
_DISCUSSIONINFO[course.id]['category_map'] = category_map
|
||||
|
||||
Reference in New Issue
Block a user