AA-177: Add masquerading for course home MFE

- Looks at masquerading config for dates, outline, metadata, and
  celebration APIs in course_home_api / courseware_api.
- Consolidates and cleans up places we check whether masquerading
  gives us full access to a course.
This commit is contained in:
Michael Terry
2020-06-22 17:40:08 -04:00
parent cf5f9482e3
commit 3030efec78
40 changed files with 318 additions and 447 deletions

View File

@@ -329,6 +329,52 @@ class CourseAccessTestMixin(TestCase):
self.assertFalse(has_access(user, action, CourseOverview.get_from_id(course.id)))
class MasqueradeMixin:
"""
Adds masquerade utilities for your TestCase.
Your test case class must have self.client. And can optionally have self.course if you don't want
to pass in the course parameter below.
"""
def update_masquerade(self, course=None, role='student', group_id=None, username=None, user_partition_id=None):
"""
Installs a masquerade for the specified user and course, to enable
the user to masquerade as belonging to the specific partition/group
combination.
Arguments:
course (object): a course or None for self.course
user_partition_id (int): the integer partition id, referring to partitions already
configured in the course.
group_id (int); the integer group id, within the specified partition.
username (str): user to masquerade as
role (str): role to masquerade as
Returns: the response object for the AJAX call to update the user's masquerade.
"""
course = course or self.course
masquerade_url = reverse(
'masquerade_update',
kwargs={
'course_key_string': str(course.id),
}
)
response = self.client.post(
masquerade_url,
json.dumps({
'role': role,
'group_id': group_id,
'user_name': username,
'user_partition_id': user_partition_id,
}),
'application/json'
)
self.assertEqual(response.status_code, 200)
self.assertTrue(response.json()['success'], response.json().get('error'))
return response
def masquerade_as_group_member(user, course, partition_id, group_id):
"""
Installs a masquerade for the specified user and course, to enable

View File

@@ -844,18 +844,18 @@ class CourseOverviewAccessTestCase(ModuleStoreTestCase):
if user_attr_name == 'user_staff' and action == 'see_exists':
# always checks staff role, and if the course has started, check the duration configuration
if course_attr_name == 'course_started':
num_queries = 3
num_queries = 2
else:
num_queries = 1
elif user_attr_name == 'user_normal' and action == 'see_exists':
if course_attr_name == 'course_started':
num_queries = 6
num_queries = 4
else:
# checks staff role and enrollment data
num_queries = 2
elif user_attr_name == 'user_anonymous' and action == 'see_exists':
if course_attr_name == 'course_started':
num_queries = 3
num_queries = 1
else:
num_queries = 0
else:

View File

@@ -431,8 +431,8 @@ class SelfPacedCourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest
def test_num_queries_instructor_paced(self):
# TODO: decrease query count as part of REVO-28
self.fetch_course_info_with_queries(self.instructor_paced_course, 44, 3)
self.fetch_course_info_with_queries(self.instructor_paced_course, 42, 3)
def test_num_queries_self_paced(self):
# TODO: decrease query count as part of REVO-28
self.fetch_course_info_with_queries(self.self_paced_course, 44, 3)
self.fetch_course_info_with_queries(self.self_paced_course, 42, 3)

View File

@@ -22,7 +22,7 @@ from lms.djangoapps.courseware.masquerade import (
CourseMasquerade, MasqueradingKeyValueStore, get_masquerading_user_group,
)
from lms.djangoapps.courseware.tests.factories import StaffFactory
from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase, masquerade_as_group_member
from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase, MasqueradeMixin, masquerade_as_group_member
from lms.djangoapps.courseware.tests.test_submitting_problems import ProblemSubmissionTestMixin
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration
@@ -37,7 +37,7 @@ from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from xmodule.partitions.partitions import Group, UserPartition
class MasqueradeTestCase(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
class MasqueradeTestCase(SharedModuleStoreTestCase, LoginEnrollmentTestCase, MasqueradeMixin):
"""
Base class for masquerade tests that sets up a test course and enrolls a user in the course.
"""
@@ -205,24 +205,6 @@ class StaffMasqueradeTestCase(MasqueradeTestCase):
"""
return StaffFactory(course_key=self.course.id)
def update_masquerade(self, role, group_id=None, user_name=None):
"""
Toggle masquerade state.
"""
masquerade_url = reverse(
'masquerade_update',
kwargs={
'course_key_string': six.text_type(self.course.id),
}
)
response = self.client.post(
masquerade_url,
json.dumps({"role": role, "group_id": group_id, "user_name": user_name}),
"application/json"
)
self.assertEqual(response.status_code, 200)
return response
class TestStaffMasqueradeAsStudent(StaffMasqueradeTestCase):
"""
@@ -334,7 +316,7 @@ class TestStaffMasqueradeAsSpecificStudent(StaffMasqueradeTestCase, ProblemSubmi
# Masquerade as the student,enable the self paced configuration, and check we can see the info page.
SelfPacedConfiguration(enable_course_home_improvements=True).save()
self.update_masquerade(role='student', user_name=self.student_user.username)
self.update_masquerade(role='student', username=self.student_user.username)
response = self.get_course_info_page()
self.assertContains(response, "OOGIE BLOOGIE")
@@ -363,7 +345,7 @@ class TestStaffMasqueradeAsSpecificStudent(StaffMasqueradeTestCase, ProblemSubmi
self.assertEqual(self.get_progress_detail(), u'0/2')
# Masquerade as the student, and check we can see the student state.
self.update_masquerade(role='student', user_name=student.username)
self.update_masquerade(role='student', username=student.username)
self.assertEqual(self.get_progress_detail(), u'2/2')
# Temporarily override the student state.
@@ -402,7 +384,7 @@ class TestStaffMasqueradeAsSpecificStudent(StaffMasqueradeTestCase, ProblemSubmi
# Set student language preference and set masquerade to view same page the student.
set_user_preference(self.student_user, preference_key=LANGUAGE_KEY, preference_value='es-419')
self.update_masquerade(role='student', user_name=self.student_user.username)
self.update_masquerade(role='student', username=self.student_user.username)
# Reload the page and check we have expected language preference in system and in cookies.
self.get_courseware_page()
@@ -423,7 +405,7 @@ class TestStaffMasqueradeAsSpecificStudent(StaffMasqueradeTestCase, ProblemSubmi
self.assertIn("OOGIE BLOOGIE", content)
# Masquerade as the student, and check we can see the info page.
self.update_masquerade(role='student', user_name=self.student_user.username)
self.update_masquerade(role='student', username=self.student_user.username)
content = self.get_course_info_page().content.decode('utf-8')
self.assertIn("OOGIE BLOOGIE", content)
@@ -446,7 +428,7 @@ class TestStaffMasqueradeAsSpecificStudent(StaffMasqueradeTestCase, ProblemSubmi
self.assertIn("1 of 2 possible points", staff_progress)
# Should now see the student's scores
self.update_masquerade(role='student', user_name=self.student_user.username)
self.update_masquerade(role='student', username=self.student_user.username)
masquerade_progress = self.get_progress_page().content.decode('utf-8')
self.assertNotIn("1 of 2 possible points", masquerade_progress)
self.assertIn("2 of 2 possible points", masquerade_progress)

View File

@@ -268,8 +268,8 @@ class IndexQueryTestCase(ModuleStoreTestCase):
NUM_PROBLEMS = 20
@ddt.data(
(ModuleStoreEnum.Type.mongo, 10, 167),
(ModuleStoreEnum.Type.split, 4, 165),
(ModuleStoreEnum.Type.mongo, 10, 170),
(ModuleStoreEnum.Type.split, 4, 166),
)
@ddt.unpack
def test_index_query_counts(self, store_type, expected_mongo_query_count, expected_mysql_query_count):
@@ -1434,8 +1434,8 @@ class ProgressPageTests(ProgressPageBaseTests):
self.assertContains(resp, u"Download Your Certificate")
@ddt.data(
(True, 54),
(False, 53),
(True, 52),
(False, 51),
)
@ddt.unpack
def test_progress_queries_paced_courses(self, self_paced, query_count):
@@ -1448,8 +1448,8 @@ class ProgressPageTests(ProgressPageBaseTests):
@patch.dict(settings.FEATURES, {'ASSUME_ZERO_GRADE_IF_ABSENT_FOR_ALL_TESTS': False})
@ddt.data(
(False, 62, 40),
(True, 53, 35)
(False, 60, 41),
(True, 51, 36)
)
@ddt.unpack
def test_progress_queries(self, enable_waffle, initial, subsequent):
@@ -1628,7 +1628,8 @@ class ProgressPageTests(ProgressPageBaseTests):
CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1))
user = UserFactory.create()
self.assertTrue(self.client.login(username=user.username, password='test'))
add_course_mode(self.course, upgrade_deadline_expired=False)
add_course_mode(self.course, mode_slug=CourseMode.AUDIT)
add_course_mode(self.course)
CourseEnrollmentFactory(user=user, course_id=self.course.id, mode=course_mode)
response = self._get_progress_page()
@@ -2807,7 +2808,8 @@ class TestIndexViewWithCourseDurationLimits(ModuleStoreTestCase):
"""
CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1))
self.assertTrue(self.client.login(username=self.user.username, password='test'))
add_course_mode(self.course, upgrade_deadline_expired=False)
add_course_mode(self.course, mode_slug=CourseMode.AUDIT)
add_course_mode(self.course)
response = self.client.get(
reverse(
'courseware_section',