Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop courseware legacy view for all but Studio preview mode #30238

Merged
merged 1 commit into from
Apr 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2554,7 +2554,6 @@ paths:
* `"empty"`: no start date is specified
* pacing: Course pacing. Possible values: instructor, self
* user_timezone: User's chosen timezone setting (or null for browser default)
* can_view_legacy_courseware: Indicates whether the user is able to see the legacy courseware view
* user_has_passing_grade: Whether or not the effective user's grade is equal to or above the courses minimum
passing grade
* course_exit_page_is_active: Flag for the learning mfe on whether or not the course exit page should display
Expand Down
10 changes: 2 additions & 8 deletions lms/djangoapps/ccx/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from django.urls import resolve, reverse
from django.utils.translation import gettext as _
from edx_django_utils.cache import RequestCache
from edx_toggles.toggles.testutils import override_waffle_flag
from opaque_keys.edx.keys import CourseKey
from pytz import UTC
from xmodule.modulestore import ModuleStoreEnum
Expand All @@ -41,7 +40,6 @@
from lms.djangoapps.courseware.tests.factories import StudentModuleFactory
from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase
from lms.djangoapps.courseware.testutils import FieldOverrideTestMixin
from lms.djangoapps.courseware.toggles import COURSEWARE_USE_LEGACY_FRONTEND
from lms.djangoapps.discussion.django_comment_client.utils import has_forum_access
from lms.djangoapps.grades.api import task_compute_all_grades_for_course
from lms.djangoapps.instructor.access import allow_access, list_with_level
Expand Down Expand Up @@ -1219,12 +1217,8 @@ def test_load_student_dashboard(self):
assert response.status_code == 200
assert re.search('Test CCX', response.content.decode('utf-8'))

@override_waffle_flag(COURSEWARE_USE_LEGACY_FRONTEND, active=True)
def test_load_courseware(self):
self.client.login(username=self.student.username, password=self.student_password)
response = self.client.get(reverse('courseware_section', kwargs={
'course_id': str(self.ccx_course_key),
'chapter': 'chapter_x',
'section': 'sequential_x1',
}))
sequence_key = self.ccx_course_key.make_usage_key('sequential', 'sequential_x1')
response = self.client.get(reverse('render_xblock', args=[str(sequence_key)]))
assert response.status_code == 200
9 changes: 1 addition & 8 deletions lms/djangoapps/course_home_api/course_metadata/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
from lms.djangoapps.courseware.courses import check_course_access
from lms.djangoapps.courseware.masquerade import setup_masquerade
from lms.djangoapps.courseware.tabs import get_course_tab_list
from lms.djangoapps.courseware.toggles import courseware_mfe_is_visible


class CourseHomeMetadataView(RetrieveAPIView):
Expand Down Expand Up @@ -102,12 +101,6 @@ def get(self, request, *args, **kwargs):
enrollment = CourseEnrollment.get_enrollment(request.user, course_key_string)
user_is_enrolled = bool(enrollment and enrollment.is_active)

can_load_courseware = courseware_mfe_is_visible(
course_key=course_key,
is_global_staff=original_user_is_global_staff,
is_course_staff=original_user_is_staff
)

# User locale settings
user_timezone_locale = user_timezone_locale_prefs(request)
user_timezone = user_timezone_locale['user_timezone']
Expand All @@ -133,7 +126,7 @@ def get(self, request, *args, **kwargs):
'is_self_paced': getattr(course, 'self_paced', False),
'is_enrolled': user_is_enrolled,
'course_access': load_access.to_json(),
'can_load_courseware': can_load_courseware,
'can_load_courseware': True, # can be removed once the MFE no longer references this field
'celebrations': celebrations,
'user_timezone': user_timezone,
'can_view_certificate': certificates_viewable_for_course(course),
Expand Down
12 changes: 11 additions & 1 deletion lms/djangoapps/courseware/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
import json
from collections import OrderedDict
from datetime import timedelta
from unittest.mock import Mock
from unittest.mock import Mock, patch

from django.conf import settings
from django.contrib import messages
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.test import TestCase
Expand All @@ -18,6 +19,7 @@
from xblock.field_data import DictFieldData

from common.djangoapps.edxmako.shortcuts import render_to_string
from lms.djangoapps.courseware import access_utils
from lms.djangoapps.courseware.access import has_access
from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link
from lms.djangoapps.courseware.masquerade import MasqueradeView
Expand Down Expand Up @@ -451,3 +453,11 @@ def get_context_dict_from_string(data):
sorted(json.loads(cleaned_data['metadata']).items(), key=lambda t: t[0])
)
return cleaned_data


def set_preview_mode(preview_mode: bool):
"""
A decorator to force the preview mode on or off.
"""
hostname = settings.FEATURES.get('PREVIEW_LMS_BASE') if preview_mode else None
return patch.object(access_utils, 'get_current_request_hostname', new=lambda: hostname)
221 changes: 2 additions & 219 deletions lms/djangoapps/courseware/tests/test_entrance_exam.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
"""


from unittest.mock import Mock, patch
from unittest.mock import patch
from crum import set_current_request
from django.urls import reverse
from edx_toggles.toggles.testutils import override_waffle_flag
from milestones.tests.utils import MilestonesTestCaseMixin
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
Expand All @@ -21,11 +20,9 @@
from lms.djangoapps.courseware.model_data import FieldDataCache
from lms.djangoapps.courseware.module_render import get_module, handle_xblock_callback, toc_for_course
from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase
from lms.djangoapps.courseware.toggles import COURSEWARE_USE_LEGACY_FRONTEND
from openedx.core.djangolib.testing.utils import get_mock_request
from openedx.features.course_experience import DISABLE_COURSE_OUTLINE_PAGE_FLAG, DISABLE_UNIFIED_COURSE_TAB_FLAG
from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.tests.factories import AnonymousUserFactory, CourseEnrollmentFactory
from common.djangoapps.student.tests.factories import AnonymousUserFactory
from common.djangoapps.student.tests.factories import InstructorFactory
from common.djangoapps.student.tests.factories import RequestFactoryNoCsrf
from common.djangoapps.student.tests.factories import StaffFactory
Expand All @@ -40,7 +37,6 @@
)


@override_waffle_flag(COURSEWARE_USE_LEGACY_FRONTEND, active=True)
@patch.dict('django.conf.settings.FEATURES', {'ENTRANCE_EXAMS': True})
class EntranceExamTestCases(LoginEnrollmentTestCase, ModuleStoreTestCase, MilestonesTestCaseMixin):
"""
Expand Down Expand Up @@ -216,54 +212,6 @@ def setUp(self):
]
)

def test_view_redirect_if_entrance_exam_required(self):
"""
Unit Test: if entrance exam is required. Should return a redirect.
"""
url = reverse('courseware', kwargs={'course_id': str(self.course.id)})
expected_url = reverse('courseware_section',
kwargs={
'course_id': str(self.course.id),
'chapter': self.entrance_exam.location.block_id,
'section': self.exam_1.location.block_id
})
resp = self.client.get(url)
self.assertRedirects(resp, expected_url, status_code=302, target_status_code=200)

@patch.dict('django.conf.settings.FEATURES', {'ENTRANCE_EXAMS': False})
def test_entrance_exam_content_absence(self):
"""
Unit Test: If entrance exam is not enabled then page should be redirected with chapter contents.
"""
url = reverse('courseware', kwargs={'course_id': str(self.course.id)})
expected_url = reverse('courseware_section',
kwargs={
'course_id': str(self.course.id),
'chapter': self.chapter.location.block_id,
'section': self.welcome.location.block_id
})
resp = self.client.get(url)
self.assertRedirects(resp, expected_url, status_code=302, target_status_code=200)
resp = self.client.get(expected_url)
self.assertNotContains(resp, 'Exam Vertical - Unit 1')

def test_entrance_exam_content_presence(self):
"""
Unit Test: If entrance exam is enabled then its content e.g. problems should be loaded and redirection will
occur with entrance exam contents.
"""
url = reverse('courseware', kwargs={'course_id': str(self.course.id)})
expected_url = reverse('courseware_section',
kwargs={
'course_id': str(self.course.id),
'chapter': self.entrance_exam.location.block_id,
'section': self.exam_1.location.block_id
})
resp = self.client.get(url)
self.assertRedirects(resp, expected_url, status_code=302, target_status_code=200)
resp = self.client.get(expected_url)
self.assertContains(resp, 'Exam Vertical - Unit 1')

def test_get_entrance_exam_content(self):
"""
test get entrance exam content method
Expand All @@ -279,95 +227,6 @@ def test_get_entrance_exam_content(self):
assert exam_chapter is None
assert user_has_passed_entrance_exam(self.request.user, self.course)

def test_entrance_exam_requirement_message(self):
"""
Unit Test: entrance exam requirement message should be present in response
"""
url = reverse(
'courseware_section',
kwargs={
'course_id': str(self.course.id),
'chapter': self.entrance_exam.location.block_id,
'section': self.exam_1.location.block_id,
}
)
resp = self.client.get(url)
self.assertContains(resp, 'To access course materials, you must score')

def test_entrance_exam_requirement_message_with_correct_percentage(self):
"""
Unit Test: entrance exam requirement message should be present in response
and percentage of required score should be rounded as expected
"""
minimum_score_pct = 29
self.course.entrance_exam_minimum_score_pct = float(minimum_score_pct) / 100
self.update_course(self.course, self.request.user.id)

# answer the problem so it results in only 20% correct.
answer_entrance_exam_problem(self.course, self.request, self.problem_1, value=1, max_value=5)

url = reverse(
'courseware_section',
kwargs={
'course_id': str(self.course.id),
'chapter': self.entrance_exam.location.block_id,
'section': self.exam_1.location.block_id
}
)
resp = self.client.get(url)
self.assertContains(
resp,
f'To access course materials, you must score {minimum_score_pct}% or higher',
)
assert 'Your current score is 20%.' in resp.content.decode(resp.charset)

def test_entrance_exam_requirement_message_hidden(self):
"""
Unit Test: entrance exam message should not be present outside the context of entrance exam subsection.
"""
# Login as staff to avoid redirect to entrance exam
self.client.logout()
staff_user = StaffFactory(course_key=self.course.id)
self.client.login(username=staff_user.username, password='test')
CourseEnrollment.enroll(staff_user, self.course.id)

url = reverse(
'courseware_section',
kwargs={
'course_id': str(self.course.id),
'chapter': self.chapter.location.block_id,
'section': self.chapter_subsection.location.block_id
}
)
resp = self.client.get(url)
assert resp.status_code == 200
self.assertNotContains(resp, 'To access course materials, you must score')
self.assertNotContains(resp, 'You have passed the entrance exam.')

# TODO: LEARNER-71: Do we need to adjust or remove this test?
@override_waffle_flag(DISABLE_COURSE_OUTLINE_PAGE_FLAG, active=True)
def test_entrance_exam_passed_message_and_course_content(self):
"""
Unit Test: exam passing message and rest of the course section should be present
when user achieves the entrance exam milestone/pass the exam.
"""
url = reverse(
'courseware_section',
kwargs={
'course_id': str(self.course.id),
'chapter': self.entrance_exam.location.block_id,
'section': self.exam_1.location.block_id
}
)

answer_entrance_exam_problem(self.course, self.request, self.problem_1)
answer_entrance_exam_problem(self.course, self.request, self.problem_2)

resp = self.client.get(url)
self.assertNotContains(resp, 'To access course materials, you must score')
self.assertContains(resp, 'Your score is 100%. You have passed the entrance exam.')
self.assertContains(resp, 'Lesson 1')

def test_entrance_exam_gating(self):
"""
Unit Test: test_entrance_exam_gating
Expand Down Expand Up @@ -427,71 +286,6 @@ def test_entrance_exam_gating_for_staff(self):
for toc_section in self.expected_unlocked_toc:
assert toc_section in unlocked_toc

def test_courseware_page_access_without_passing_entrance_exam(self):
"""
Test courseware access page without passing entrance exam
"""
url = reverse(
'courseware_chapter',
kwargs={'course_id': str(self.course.id), 'chapter': self.chapter.url_name}
)
response = self.client.get(url)
expected_url = reverse('courseware_section',
kwargs={
'course_id': str(self.course.id),
'chapter': self.entrance_exam.location.block_id,
'section': self.exam_1.location.block_id
})
self.assertRedirects(response, expected_url, status_code=302, target_status_code=200)

@override_waffle_flag(DISABLE_UNIFIED_COURSE_TAB_FLAG, active=True)
def test_courseinfo_page_access_without_passing_entrance_exam(self):
"""
Test courseware access page without passing entrance exam
"""
url = reverse('info', args=[str(self.course.id)])
response = self.client.get(url)
redirect_url = reverse('courseware', args=[str(self.course.id)])
self.assertRedirects(response, redirect_url, status_code=302, target_status_code=302)
response = self.client.get(redirect_url)
exam_url = response.get('Location')
self.assertRedirects(response, exam_url)

@patch('lms.djangoapps.courseware.entrance_exams.get_entrance_exam_content', Mock(return_value=None))
def test_courseware_page_access_after_passing_entrance_exam(self):
"""
Test courseware access page after passing entrance exam
"""
self._assert_chapter_loaded(self.course, self.chapter)

@patch('common.djangoapps.util.milestones_helpers.get_required_content', Mock(return_value=['a value']))
def test_courseware_page_access_with_staff_user_without_passing_entrance_exam(self):
"""
Test courseware access page without passing entrance exam but with staff user
"""
self.logout()
staff_user = StaffFactory.create(course_key=self.course.id)
self.login(staff_user.email, 'test')
CourseEnrollmentFactory(user=staff_user, course_id=self.course.id)
self._assert_chapter_loaded(self.course, self.chapter)

def test_courseware_page_access_with_staff_user_after_passing_entrance_exam(self):
"""
Test courseware access page after passing entrance exam but with staff user
"""
self.logout()
staff_user = StaffFactory.create(course_key=self.course.id)
self.login(staff_user.email, 'test')
CourseEnrollmentFactory(user=staff_user, course_id=self.course.id)
self._assert_chapter_loaded(self.course, self.chapter)

@patch.dict("django.conf.settings.FEATURES", {'ENTRANCE_EXAMS': False})
def test_courseware_page_access_when_entrance_exams_disabled(self):
"""
Test courseware page access when ENTRANCE_EXAMS feature is disabled
"""
self._assert_chapter_loaded(self.course, self.chapter)

def test_can_skip_entrance_exam_with_anonymous_user(self):
"""
Test can_skip_entrance_exam method with anonymous user
Expand Down Expand Up @@ -540,17 +334,6 @@ def test_entrance_exam_xblock_response(self):
assert response.status_code == 200
self.assertContains(response, 'entrance_exam_passed')

def _assert_chapter_loaded(self, course, chapter):
"""
Asserts courseware chapter load successfully.
"""
url = reverse(
'courseware_chapter',
kwargs={'course_id': str(course.id), 'chapter': chapter.url_name}
)
response = self.client.get(url)
assert response.status_code == 200

def _return_table_of_contents(self):
"""
Returns table of content for the entrance exam specific to this test
Expand Down
Loading