""" 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='', 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 = '' 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 = ''.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, '')