Files
edx-platform/lms/djangoapps/courseware/tests/test_course_survey.py
Michael Terry ce5f1bb343 feat!: drop legacy course home view and related code
This was the "outline tab" view of the course. Preceded by the
course info view, succeeded by the MFE outline tab.

In addition to the course home view itself, this drops related
features:
- Legacy version of Course Goals (MFE has a newer implementation)
- Course home in-course search (MFE has no search)

The old course info view and course about views survive for now.

This also drops a few now-unused feature toggles:
- course_experience.latest_update
- course_experience.show_upgrade_msg_on_course_home
- course_experience.upgrade_deadline_message
- course_home.course_home_use_legacy_frontend

With this change, just the progress and courseware tabs are still
supported in legacy form, if you opt-in with waffle flags. The
outline and dates tabs are offered only by the MFE.

AA-798

(This is identical to previous commit be5c1a6, just reintroduced
now that the e2e tests have been fixed)
2022-04-14 15:18:31 -04:00

243 lines
7.6 KiB
Python

"""
Python tests for the Survey workflows
"""
from collections import OrderedDict
from copy import deepcopy
from urllib.parse import quote
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.urls import reverse
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from common.test.utils import XssTestMixin
from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase
from lms.djangoapps.survey.models import SurveyAnswer, SurveyForm
from openedx.features.course_experience import course_home_url
class SurveyViewsTests(LoginEnrollmentTestCase, SharedModuleStoreTestCase, XssTestMixin):
"""
All tests for the views.py file
"""
STUDENT_INFO = [('view@test.com', 'foo')]
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.test_survey_name = 'TestSurvey'
cls.course = CourseFactory.create(
display_name='<script>alert("XSS")</script>',
course_survey_required=True,
course_survey_name=cls.test_survey_name
)
cls.course_with_bogus_survey = CourseFactory.create(
course_survey_required=True,
course_survey_name="DoesNotExist"
)
cls.course_without_survey = CourseFactory.create()
def setUp(self):
"""
Set up the test data used in the specific tests
"""
super().setUp()
self.test_form = '<input name="field1"></input>'
self.survey = SurveyForm.create(self.test_survey_name, self.test_form)
self.student_answers = OrderedDict({
'field1': 'value1',
'field2': 'value2',
})
# Create student accounts and activate them.
for i in range(len(self.STUDENT_INFO)):
email, password = self.STUDENT_INFO[i]
username = f'u{i}'
self.create_account(username, email, password)
self.activate_user(email)
email, password = self.STUDENT_INFO[0]
self.login(email, password)
self.enroll(self.course, True)
self.enroll(self.course_without_survey, True)
self.enroll(self.course_with_bogus_survey, True)
self.user = User.objects.get(email=email)
self.view_url = reverse('view_survey', args=[self.test_survey_name])
self.postback_url = reverse('submit_answers', args=[self.test_survey_name])
def _assert_survey_redirect(self, course):
"""
Helper method to assert that all known redirect points do redirect as expected
"""
for view_name in ['courseware', 'progress']:
resp = self.client.get(
reverse(
view_name,
kwargs={'course_id': str(course.id)}
)
)
self.assertRedirects(
resp,
reverse('course_survey', kwargs={'course_id': str(course.id)})
)
def _assert_no_redirect(self, course):
"""
Helper method to asswer that all known conditionally redirect points do
not redirect as expected
"""
for view_name in ['courseware', 'progress']:
resp = self.client.get(
reverse(
view_name,
kwargs={'course_id': str(course.id)}
)
)
assert resp.status_code == 200
def test_visiting_course_without_survey(self):
"""
Verifies that going to the courseware which does not have a survey does
not redirect to a survey
"""
self._assert_no_redirect(self.course_without_survey)
def test_visiting_course_with_survey_redirects(self):
"""
Verifies that going to the courseware with an unanswered survey, redirects to the survey
"""
self._assert_survey_redirect(self.course)
def test_anonymous_user_visiting_course_with_survey(self):
"""
Verifies that anonymous user going to the course with an unanswered survey is not
redirected to survey.
"""
self.logout()
resp = self.client.get(
reverse(
'courseware',
kwargs={'course_id': str(self.course.id)}
)
)
self.assertRedirects(
resp,
f'/login?next=/courses/{quote(str(self.course.id))}/courseware'
)
def test_visiting_course_with_existing_answers(self):
"""
Verifies that going to the courseware with an answered survey, there is no redirect
"""
resp = self.client.post(
self.postback_url,
self.student_answers
)
assert resp.status_code == 200
self._assert_no_redirect(self.course)
def test_course_id_field(self):
"""
Assert that the course_id will be in the form fields, if available
"""
resp = self.client.get(
reverse(
'course_survey',
kwargs={'course_id': str(self.course.id)}
)
)
assert resp.status_code == 200
expected = '<input type="hidden" name="course_id" value="{course_id}" />'.format(
course_id=str(self.course.id)
)
self.assertContains(resp, expected)
def test_course_id_persists(self):
"""
Assert that a posted back course_id is stored in the database
"""
answers = deepcopy(self.student_answers)
answers.update({
'course_id': str(self.course.id)
})
resp = self.client.post(
self.postback_url,
answers
)
assert resp.status_code == 200
self._assert_no_redirect(self.course)
# however we want to make sure we persist the course_id
answer_objs = SurveyAnswer.objects.filter(
user=self.user,
form=self.survey
)
for answer_obj in answer_objs:
assert answer_obj.course_key == self.course.id
def test_visiting_course_with_bogus_survey(self):
"""
Verifies that going to the courseware with a required, but non-existing survey, does not redirect
"""
self._assert_no_redirect(self.course_with_bogus_survey)
def test_visiting_survey_with_bogus_survey_name(self):
"""
Verifies that going to the courseware with a required, but non-existing survey, does not redirect
"""
resp = self.client.get(
reverse(
'course_survey',
kwargs={'course_id': str(self.course_with_bogus_survey.id)}
)
)
self.assertRedirects(
resp,
course_home_url(self.course_with_bogus_survey.id),
fetch_redirect_response=False,
)
def test_visiting_survey_with_no_course_survey(self):
"""
Verifies that going to the courseware with a required, but non-existing survey, does not redirect
"""
resp = self.client.get(
reverse(
'course_survey',
kwargs={'course_id': str(self.course_without_survey.id)}
)
)
self.assertRedirects(
resp,
course_home_url(self.course_without_survey.id),
fetch_redirect_response=False,
)
def test_survey_xss(self):
"""Test that course display names are correctly HTML-escaped."""
response = self.client.get(
reverse(
'course_survey',
kwargs={'course_id': str(self.course.id)}
)
)
self.assert_no_xss(response, '<script>alert("XSS")</script>')