492 lines
20 KiB
Python
492 lines
20 KiB
Python
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 django_comment_client.tests.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):
|
|
d = {'cats': 'meow', 'dogs': 'woof'}
|
|
k = ['cats', 'dogs', 'hamsters']
|
|
expected = {'cats': 'meow', 'dogs': 'woof', 'hamsters': None}
|
|
self.assertEqual(utils.extract(d, k), expected)
|
|
|
|
def test_strip_none(self):
|
|
d = {'cats': 'meow', 'dogs': 'woof', 'hamsters': None}
|
|
expected = {'cats': 'meow', 'dogs': 'woof'}
|
|
self.assertEqual(utils.strip_none(d), expected)
|
|
|
|
def test_strip_blank(self):
|
|
d = {'cats': 'meow', 'dogs': 'woof', 'hamsters': ' ', 'yetis': ''}
|
|
expected = {'cats': 'meow', 'dogs': 'woof'}
|
|
self.assertEqual(utils.strip_blank(d), expected)
|
|
|
|
def test_merge_dict(self):
|
|
d1 = {'cats': 'meow', 'dogs': 'woof'}
|
|
d2 = {'lions': 'roar', 'ducks': 'quack'}
|
|
expected = {'cats': 'meow', 'dogs': 'woof', 'lions': 'roar', 'ducks': 'quack'}
|
|
self.assertEqual(utils.merge_dict(d1, d2), expected)
|
|
|
|
|
|
class AccessUtilsTestCase(TestCase):
|
|
def setUp(self):
|
|
self.course_id = 'edX/toy/2012_Fall'
|
|
self.student_role = RoleFactory(name='Student', course_id=self.course_id)
|
|
self.moderator_role = RoleFactory(name='Moderator', course_id=self.course_id)
|
|
self.community_ta_role = RoleFactory(name='Community TA', course_id=self.course_id)
|
|
self.student1 = UserFactory(username='student', email='student@edx.org')
|
|
self.student1_enrollment = CourseEnrollmentFactory(user=self.student1)
|
|
self.student_role.users.add(self.student1)
|
|
self.student2 = UserFactory(username='student2', email='student2@edx.org')
|
|
self.student2_enrollment = CourseEnrollmentFactory(user=self.student2)
|
|
self.moderator = UserFactory(username='moderator', email='staff@edx.org', is_staff=True)
|
|
self.moderator_enrollment = CourseEnrollmentFactory(user=self.moderator)
|
|
self.moderator_role.users.add(self.moderator)
|
|
self.community_ta1 = UserFactory(username='community_ta1', email='community_ta1@edx.org')
|
|
self.community_ta_role.users.add(self.community_ta1)
|
|
self.community_ta2 = UserFactory(username='community_ta2', email='community_ta2@edx.org')
|
|
self.community_ta_role.users.add(self.community_ta2)
|
|
|
|
def test_get_role_ids(self):
|
|
ret = utils.get_role_ids(self.course_id)
|
|
expected = {u'Moderator': [3], u'Community TA': [4, 5]}
|
|
self.assertEqual(ret, expected)
|
|
|
|
def test_has_forum_access(self):
|
|
ret = utils.has_forum_access('student', self.course_id, 'Student')
|
|
self.assertTrue(ret)
|
|
|
|
ret = utils.has_forum_access('not_a_student', self.course_id, 'Student')
|
|
self.assertFalse(ret)
|
|
|
|
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_empty(self):
|
|
utils.add_courseware_context([], self.course)
|
|
|
|
def test_missing_commentable_id(self):
|
|
orig = {"commentable_id": "non-inline"}
|
|
modified = dict(orig)
|
|
utils.add_courseware_context([modified], self.course)
|
|
self.assertEqual(modified, orig)
|
|
|
|
def test_basic(self):
|
|
threads = [
|
|
{"commentable_id": self.discussion1.discussion_id},
|
|
{"commentable_id": self.discussion2.discussion_id}
|
|
]
|
|
utils.add_courseware_context(threads, self.course)
|
|
|
|
def assertThreadCorrect(thread, discussion, expected_title): #pylint: disable=C0103
|
|
self.assertEqual(
|
|
set(thread.keys()),
|
|
set(["commentable_id", "courseware_url", "courseware_title"])
|
|
)
|
|
self.assertEqual(
|
|
thread.get("courseware_url"),
|
|
reverse(
|
|
"jump_to",
|
|
kwargs={
|
|
"course_id": self.course.location.course_id,
|
|
"location": discussion.location
|
|
}
|
|
)
|
|
)
|
|
self.assertEqual(thread.get("courseware_title"), expected_title)
|
|
|
|
assertThreadCorrect(threads[0], self.discussion1, "Chapter / Discussion 1")
|
|
assertThreadCorrect(threads[1], 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"]
|
|
}
|
|
)
|