Skip to content

Commit

Permalink
Merge branch 'master' into umar/replace-jwkest-with-pyjwt
Browse files Browse the repository at this point in the history
  • Loading branch information
mumarkhan999 committed May 26, 2023
2 parents 19b983d + 38a69d1 commit 1a8f1a3
Show file tree
Hide file tree
Showing 172 changed files with 2,962 additions and 1,075 deletions.
2 changes: 2 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ updates:
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "openedx/arbi-bom"
10 changes: 9 additions & 1 deletion cms/djangoapps/contentstore/exams.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,20 @@ def register_exams(course_key):
timed_exam.is_practice_exam,
timed_exam.is_onboarding_exam
)

exams_list.append({
'course_id': str(course_key),
'content_id': str(timed_exam.location),
'exam_name': timed_exam.display_name,
'time_limit_mins': timed_exam.default_time_limit_minutes,
'due_date': timed_exam.due.isoformat() if timed_exam.due and not course.self_paced else None,
# If the subsection has no due date, then infer a due date from the course end date. This behavior is a
# departure from the legacy register_exams function used by the edx-proctoring plugin because
# edx-proctoring makes a direct call to edx-when API when computing an exam's due date.
# By sending the course end date when registering exams, we can avoid calling to the platform from the
# exam service. Also note that we no longer consider the pacing type of the course - this applies to both
# self-paced and indstructor-paced courses. Therefore, this effectively opts out exams powered by edx-exams
# from personalized learner schedules/relative dates.
'due_date': timed_exam.due.isoformat() if timed_exam.due else course.end.isoformat(),
'exam_type': exam_type,
'is_active': True,
'hide_after_due': timed_exam.hide_after_due,
Expand Down
47 changes: 38 additions & 9 deletions cms/djangoapps/contentstore/tests/test_exams.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Test the exams service integration into Studio
"""
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from unittest.mock import patch, Mock

import ddt
Expand Down Expand Up @@ -147,8 +147,15 @@ def test_feature_flag_off(self, mock_patch_course_exams):
listen_for_course_publish(self, self.course.id)
mock_patch_course_exams.assert_not_called()

def test_self_paced_no_due_dates(self, mock_patch_course_exams):
self.course.self_paced = True
@ddt.data(True, False)
def test_no_due_dates(self, is_self_paced, mock_patch_course_exams):
"""
Test that the coures end date is registered as the due date when the subsection does not have a due date for
both self-paced and instructor-paced exams.
"""
self.course.self_paced = is_self_paced
end_date = datetime(2035, 1, 1, 0, 0, tzinfo=timezone.utc)
self.course.end = end_date
self.course = self.update_course(self.course, 1)
BlockFactory.create(
parent=self.chapter,
Expand All @@ -159,18 +166,40 @@ def test_self_paced_no_due_dates(self, mock_patch_course_exams):
default_time_limit_minutes=60,
is_proctored_enabled=False,
is_practice_exam=False,
due=datetime.now(UTC) + timedelta(minutes=60),
due=None,
hide_after_due=True,
is_onboarding_exam=False,
)

listen_for_course_publish(self, self.course.id)
called_exams, called_course = mock_patch_course_exams.call_args[0]
assert called_exams[0]['due_date'] is None
assert called_exams[0]['due_date'] == end_date.isoformat()

# now switch to instructor paced
# the exam will be updated with a due date
self.course.self_paced = False
@ddt.data(True, False)
def test_subsection_due_date_prioritized(self, is_self_paced, mock_patch_course_exams):
"""
Test that the subsection due date is registered as the due date when both the subsection has a due date and the
course has an end date for both self-paced and instructor-paced exams.
"""
self.course.self_paced = is_self_paced
self.course.end = datetime(2035, 1, 1, 0, 0)
self.course = self.update_course(self.course, 1)

sequential_due_date = datetime.now(UTC) + timedelta(minutes=60)
BlockFactory.create(
parent=self.chapter,
category='sequential',
display_name='Test Proctored Exam',
graded=True,
is_time_limited=True,
default_time_limit_minutes=60,
is_proctored_enabled=False,
is_practice_exam=False,
due=sequential_due_date,
hide_after_due=True,
is_onboarding_exam=False,
)

listen_for_course_publish(self, self.course.id)
called_exams, called_course = mock_patch_course_exams.call_args[0]
assert called_exams[0]['due_date'] is not None
assert called_exams[0]['due_date'] == sequential_due_date.isoformat()
8 changes: 4 additions & 4 deletions cms/djangoapps/contentstore/tests/test_libraries.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
from xmodule.x_module import STUDIO_VIEW

from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient, parse_json
from cms.djangoapps.contentstore.utils import reverse_library_url, reverse_url, reverse_usage_url
from cms.djangoapps.contentstore.views.block import _duplicate_block
from cms.djangoapps.contentstore.utils import reverse_library_url, reverse_url, \
reverse_usage_url, duplicate_block
from cms.djangoapps.contentstore.views.preview import _load_preview_block
from cms.djangoapps.contentstore.views.tests.test_library import LIBRARY_REST_URL
from cms.djangoapps.course_creators.views import add_user_with_status_granted
Expand Down Expand Up @@ -947,7 +947,7 @@ def test_persistent_overrides(self, duplicate):
if duplicate:
# Check that this also works when the RCB is duplicated.
self.lc_block = modulestore().get_item(
_duplicate_block(self.course.location, self.lc_block.location, self.user)
duplicate_block(self.course.location, self.lc_block.location, self.user)
)
self.problem_in_course = modulestore().get_item(self.lc_block.children[0])
else:
Expand Down Expand Up @@ -1006,7 +1006,7 @@ def test_duplicated_version(self):

# Duplicate self.lc_block:
duplicate = store.get_item(
_duplicate_block(self.course.location, self.lc_block.location, self.user)
duplicate_block(self.course.location, self.lc_block.location, self.user)
)
# The duplicate should have identical children to the original:
self.assertEqual(len(duplicate.children), 1)
Expand Down
20 changes: 20 additions & 0 deletions cms/djangoapps/contentstore/toggles.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,23 @@ def use_new_unit_page(course_key):
Returns a boolean if new studio course outline mfe is enabled
"""
return ENABLE_NEW_STUDIO_UNIT_PAGE.is_enabled(course_key)


# .. toggle_name: new_studio_mfe.use_new_course_team_page
# .. toggle_implementation: CourseWaffleFlag
# .. toggle_default: False
# .. toggle_description: This flag enables the use of the new studio course team page mfe
# .. toggle_use_cases: temporary
# .. toggle_creation_date: 2023-5-15
# .. toggle_target_removal_date: 2023-8-31
# .. toggle_tickets: TNL-10619
# .. toggle_warning:
ENABLE_NEW_STUDIO_COURSE_TEAM_PAGE = CourseWaffleFlag(
f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_course_team_page', __name__)


def use_new_course_team_page(course_key):
"""
Returns a boolean if new studio course team mfe is enabled
"""
return ENABLE_NEW_STUDIO_COURSE_TEAM_PAGE.is_enabled(course_key)
Loading

0 comments on commit 1a8f1a3

Please sign in to comment.