Merge pull request #26264 from edx/ddumesnil/reset-deadlines-event-aa-492
AA-492: Adds research tracking event for reset deadlines
This commit is contained in:
@@ -10,6 +10,7 @@ from mock import patch
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.util.testing import EventTestMixin
|
||||
from lms.djangoapps.courseware.tests.helpers import MasqueradeMixin
|
||||
from lms.djangoapps.course_home_api.tests.utils import BaseCourseHomeTests
|
||||
from openedx.core.djangoapps.schedules.models import Schedule
|
||||
@@ -18,28 +19,30 @@ from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ResetCourseDeadlinesViewTests(BaseCourseHomeTests, MasqueradeMixin):
|
||||
class ResetCourseDeadlinesViewTests(EventTestMixin, BaseCourseHomeTests, MasqueradeMixin):
|
||||
"""
|
||||
Tests for reset deadlines endpoint.
|
||||
"""
|
||||
def setUp(self):
|
||||
# Need to supply tracker name for the EventTestMixin. Also, EventTestMixin needs to come
|
||||
# first in class inheritance so the setUp call here appropriately works
|
||||
super().setUp('openedx.features.course_experience.api.v1.views.tracker')
|
||||
|
||||
def test_reset_deadlines(self):
|
||||
CourseEnrollment.enroll(self.user, self.course.id, CourseMode.VERIFIED)
|
||||
# Test correct post body
|
||||
response = self.client.post(reverse('course-experience-reset-course-deadlines'), {'course_key': self.course.id})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# Test body with incorrect body param
|
||||
# Test body with incorrect body param (course_key is required)
|
||||
response = self.client.post(reverse('course-experience-reset-course-deadlines'), {'course': self.course.id})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
# Test body with additional incorrect body param
|
||||
response = self.client.post(
|
||||
reverse('course-experience-reset-course-deadlines'), {'course_key': self.course.id, 'invalid': 'value'}
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
def test_reset_deadlines_with_masquerade(self):
|
||||
""" Staff users should be able to masquerade as a learner and reset the learner's schedule """
|
||||
course = CourseFactory.create(self_paced=True)
|
||||
student_username = self.user.username
|
||||
student_user_id = self.user.id
|
||||
student_enrollment = CourseEnrollment.enroll(self.user, course.id)
|
||||
student_schedule = ScheduleFactory.create(
|
||||
start_date=timezone.now() - datetime.timedelta(days=100),
|
||||
@@ -61,6 +64,14 @@ class ResetCourseDeadlinesViewTests(BaseCourseHomeTests, MasqueradeMixin):
|
||||
self.assertEqual(updated_schedule.start_date.date(), datetime.datetime.today().date())
|
||||
updated_staff_schedule = Schedule.objects.get(id=staff_schedule.id)
|
||||
self.assertEqual(updated_staff_schedule.start_date, staff_schedule.start_date)
|
||||
self.assert_event_emitted(
|
||||
'edx.ui.lms.reset_deadlines.clicked',
|
||||
courserun_key=str(course.id),
|
||||
is_masquerading=True,
|
||||
is_staff=False,
|
||||
org_key=course.org,
|
||||
user_id=student_user_id,
|
||||
)
|
||||
|
||||
def test_post_unauthenticated_user(self):
|
||||
self.client.logout()
|
||||
|
||||
@@ -7,6 +7,7 @@ from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from django.utils.html import format_html
|
||||
from django.utils.translation import ugettext as _
|
||||
from eventtracking import tracker
|
||||
|
||||
from rest_framework.decorators import api_view, authentication_classes, permission_classes
|
||||
from rest_framework.exceptions import APIException, ParseError
|
||||
@@ -18,11 +19,12 @@ from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthenticat
|
||||
from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
from lms.djangoapps.course_api.api import course_detail
|
||||
from lms.djangoapps.course_home_api.toggles import course_home_mfe_dates_tab_is_active
|
||||
from lms.djangoapps.course_home_api.utils import get_microfrontend_url
|
||||
from lms.djangoapps.courseware.access import has_access
|
||||
from lms.djangoapps.courseware.courses import get_course_with_access
|
||||
from lms.djangoapps.courseware.masquerade import setup_masquerade
|
||||
from lms.djangoapps.courseware.masquerade import is_masquerading, setup_masquerade
|
||||
|
||||
from openedx.core.djangoapps.schedules.utils import reset_self_paced_schedule
|
||||
from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser
|
||||
@@ -48,22 +50,24 @@ def reset_course_deadlines(request):
|
||||
Set the start_date of a schedule to today, which in turn will adjust due dates for
|
||||
sequentials belonging to a self paced course
|
||||
|
||||
Request Parameters:
|
||||
course_key: course key
|
||||
research_event_data: any data that should be included in the research tracking event
|
||||
Example: sending the location of where the reset deadlines banner (i.e. outline-tab)
|
||||
|
||||
IMPORTANT NOTE: If updates are happening to the logic here, ALSO UPDATE the `reset_course_deadlines`
|
||||
function in common/djangoapps/util/views.py as well.
|
||||
"""
|
||||
course_key = request.data.get('course_key', None)
|
||||
research_event_data = request.data.get('research_event_data', {})
|
||||
|
||||
# If body doesnt contain 'course_key', return 400 to client.
|
||||
if not course_key:
|
||||
raise ParseError(_("'course_key' is required."))
|
||||
|
||||
# If body contains params other than 'course_key', return 400 to client.
|
||||
if len(request.data) > 1:
|
||||
raise ParseError(_("Only 'course_key' is expected."))
|
||||
|
||||
try:
|
||||
course_key = CourseKey.from_string(course_key)
|
||||
_course_masquerade, user = setup_masquerade(
|
||||
course_masquerade, user = setup_masquerade(
|
||||
request,
|
||||
course_key,
|
||||
has_access(request.user, 'staff', course_key)
|
||||
@@ -73,6 +77,19 @@ def reset_course_deadlines(request):
|
||||
if missed_deadlines and not missed_gated_content:
|
||||
reset_self_paced_schedule(user, course_key)
|
||||
|
||||
course_overview = course_detail(request, user.username, course_key)
|
||||
# For context here, research_event_data should already contain `location` indicating
|
||||
# the page/location dates were reset from and could also contain `block_id` if reset
|
||||
# within courseware.
|
||||
research_event_data.update({
|
||||
'courserun_key': str(course_key),
|
||||
'is_masquerading': is_masquerading(user, course_key, course_masquerade),
|
||||
'is_staff': has_access(user, 'staff', course_key).has_access,
|
||||
'org_key': course_overview.display_org_with_default,
|
||||
'user_id': user.id,
|
||||
})
|
||||
tracker.emit('edx.ui.lms.reset_deadlines.clicked', research_event_data)
|
||||
|
||||
if course_home_mfe_dates_tab_is_active(course_key):
|
||||
body_link = get_microfrontend_url(course_key=str(course_key), view_name='dates')
|
||||
else:
|
||||
|
||||
@@ -200,9 +200,8 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase, MasqueradeMixin):
|
||||
@ddt.data(
|
||||
([CourseMode.AUDIT, CourseMode.VERIFIED], CourseMode.AUDIT, False, True),
|
||||
([CourseMode.AUDIT, CourseMode.VERIFIED], CourseMode.VERIFIED, False, True),
|
||||
([CourseMode.AUDIT, CourseMode.VERIFIED, CourseMode.MASTERS], CourseMode.MASTERS, False, True),
|
||||
([CourseMode.PROFESSIONAL], CourseMode.PROFESSIONAL, False, True),
|
||||
([CourseMode.AUDIT, CourseMode.VERIFIED], CourseMode.VERIFIED, True, False),
|
||||
([CourseMode.MASTERS], CourseMode.MASTERS, False, True),
|
||||
([CourseMode.PROFESSIONAL], CourseMode.PROFESSIONAL, True, True), # staff accounts should also see the banner
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_reset_course_deadlines_banner_shows_for_self_paced_course(
|
||||
|
||||
@@ -293,13 +293,6 @@ def dates_banner_should_display(course_key, user):
|
||||
if not CourseEnrollment.is_enrolled(user, course_key):
|
||||
return False, False
|
||||
|
||||
# Don't display the banner for course staff
|
||||
is_course_staff = bool(
|
||||
user and course_overview and has_access(user, 'staff', course_overview, course_overview.id)
|
||||
)
|
||||
if is_course_staff:
|
||||
return False, False
|
||||
|
||||
# Don't display the banner if the course has ended
|
||||
if course_end_date and course_end_date < timezone.now():
|
||||
return False, False
|
||||
|
||||
@@ -151,6 +151,10 @@ class PersonalizedLearnerScheduleCallToAction:
|
||||
},
|
||||
'url': '{}{}'.format(settings.LMS_ROOT_URL, reverse('course-experience-reset-course-deadlines')),
|
||||
},
|
||||
'research_event_data': {
|
||||
'block_id': str(xblock.location),
|
||||
'location': '{category}-view'.format(category=xblock.category),
|
||||
},
|
||||
}
|
||||
|
||||
return cta_data
|
||||
|
||||
Reference in New Issue
Block a user