238 lines
7.7 KiB
Python
238 lines
7.7 KiB
Python
"""
|
|
Python tests for the Survey workflows
|
|
"""
|
|
|
|
|
|
from collections import OrderedDict
|
|
from copy import deepcopy
|
|
|
|
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
|
from django.urls import reverse
|
|
|
|
from common.test.utils import XssTestMixin
|
|
from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase
|
|
from lms.djangoapps.survey.models import SurveyAnswer, SurveyForm
|
|
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
|
from xmodule.modulestore.tests.factories import CourseFactory
|
|
|
|
|
|
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', 'openedx.course_experience.course_home', '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', 'openedx.course_experience.course_home', '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 courseware home with an unanswered survey is not
|
|
redirected to survey and home page renders without server error.
|
|
"""
|
|
self.logout()
|
|
resp = self.client.get(
|
|
reverse(
|
|
'openedx.course_experience.course_home',
|
|
kwargs={'course_id': str(self.course.id)}
|
|
)
|
|
)
|
|
assert resp.status_code == 200
|
|
|
|
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)}
|
|
)
|
|
)
|
|
course_home_path = 'openedx.course_experience.course_home'
|
|
self.assertRedirects(
|
|
resp,
|
|
reverse(course_home_path, kwargs={'course_id': str(self.course_with_bogus_survey.id)})
|
|
)
|
|
|
|
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)}
|
|
)
|
|
)
|
|
course_home_path = 'openedx.course_experience.course_home'
|
|
self.assertRedirects(
|
|
resp,
|
|
reverse(course_home_path, kwargs={'course_id': str(self.course_without_survey.id)})
|
|
)
|
|
|
|
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>')
|