""" test views """ import datetime import json import re import pytz import ddt import urlparse from mock import patch, MagicMock from nose.plugins.attrib import attr from capa.tests.response_xml_factory import StringResponseXMLFactory from courseware.courses import get_course_by_id from courseware.tests.factories import StudentModuleFactory from courseware.tests.helpers import LoginEnrollmentTestCase from courseware.tabs import get_course_tab_list from courseware.testutils import FieldOverrideTestMixin from instructor.access import ( allow_access, list_with_level, ) from django.conf import settings from django.core.urlresolvers import reverse, resolve from django.utils.translation import ugettext as _ from django.utils.timezone import UTC from django.test.utils import override_settings from django.test import RequestFactory from edxmako.shortcuts import render_to_response from request_cache.middleware import RequestCache from opaque_keys.edx.keys import CourseKey from student.roles import ( CourseCcxCoachRole, CourseInstructorRole, CourseStaffRole, ) from student.models import ( CourseEnrollment, CourseEnrollmentAllowed, ) from student.tests.factories import ( AdminFactory, CourseEnrollmentFactory, UserFactory, ) from xmodule.x_module import XModuleMixin from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.tests.django_utils import ( ModuleStoreTestCase, SharedModuleStoreTestCase, TEST_DATA_SPLIT_MODULESTORE) from xmodule.modulestore.tests.factories import ( CourseFactory, ItemFactory, SampleCourseFactory, ) from ccx_keys.locator import CCXLocator from lms.djangoapps.ccx.models import CustomCourseForEdX from lms.djangoapps.ccx.overrides import get_override_for_ccx, override_field_for_ccx from lms.djangoapps.ccx.views import ccx_course from lms.djangoapps.ccx.tests.factories import CcxFactory from lms.djangoapps.ccx.tests.utils import ( CcxTestCase, flatten, ) from lms.djangoapps.ccx.utils import is_email from lms.djangoapps.ccx.views import get_date from xmodule.modulestore.django import modulestore def intercept_renderer(path, context): """ Intercept calls to `render_to_response` and attach the context dict to the response for examination in unit tests. """ # I think Django already does this for you in their TestClient, except # we're bypassing that by using edxmako. Probably edxmako should be # integrated better with Django's rendering and event system. response = render_to_response(path, context) response.mako_context = context response.mako_template = path return response def ccx_dummy_request(): """ Returns dummy request object for CCX coach tab test """ factory = RequestFactory() request = factory.get('ccx_coach_dashboard') request.user = MagicMock() return request def setup_students_and_grades(context): """ Create students and set their grades. :param context: class reference """ if context.course: context.student = student = UserFactory.create() CourseEnrollmentFactory.create(user=student, course_id=context.course.id) context.student2 = student2 = UserFactory.create() CourseEnrollmentFactory.create(user=student2, course_id=context.course.id) # create grades for self.student as if they'd submitted the ccx for chapter in context.course.get_children(): for i, section in enumerate(chapter.get_children()): for j, problem in enumerate(section.get_children()): # if not problem.visible_to_staff_only: StudentModuleFactory.create( grade=1 if i < j else 0, max_grade=1, student=context.student, course_id=context.course.id, module_state_key=problem.location ) StudentModuleFactory.create( grade=1 if i > j else 0, max_grade=1, student=context.student2, course_id=context.course.id, module_state_key=problem.location ) class TestAdminAccessCoachDashboard(CcxTestCase, LoginEnrollmentTestCase): """ Tests for Custom Courses views. """ MODULESTORE = TEST_DATA_SPLIT_MODULESTORE def test_staff_access_coach_dashboard(self): """ User is staff, should access coach dashboard. """ staff = self.make_staff() self.client.login(username=staff.username, password="test") self.make_coach() ccx = self.make_ccx() url = reverse( 'ccx_coach_dashboard', kwargs={'course_id': CCXLocator.from_course_locator(self.course.id, ccx.id)}) response = self.client.get(url) self.assertEqual(response.status_code, 200) def test_instructor_access_coach_dashboard(self): """ User is instructor, should access coach dashboard. """ instructor = self.make_instructor() self.client.login(username=instructor.username, password="test") self.make_coach() ccx = self.make_ccx() url = reverse( 'ccx_coach_dashboard', kwargs={'course_id': CCXLocator.from_course_locator(self.course.id, ccx.id)}) response = self.client.get(url) self.assertEqual(response.status_code, 200) def test_forbidden_user_access_coach_dashboard(self): """ Assert user with no access must not see dashboard. """ user = UserFactory.create(password="test") self.client.login(username=user.username, password="test") self.make_coach() ccx = self.make_ccx() url = reverse( 'ccx_coach_dashboard', kwargs={'course_id': CCXLocator.from_course_locator(self.course.id, ccx.id)}) response = self.client.get(url) self.assertEqual(response.status_code, 403) @attr('shard_1') @ddt.ddt class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase): """ Tests for Custom Courses views. """ def setUp(self): """ Set up tests """ super(TestCoachDashboard, self).setUp() # Login with the instructor account self.client.login(username=self.coach.username, password="test") # adding staff to master course. staff = UserFactory() allow_access(self.course, staff, 'staff') self.assertTrue(CourseStaffRole(self.course.id).has_user(staff)) # adding instructor to master course. instructor = UserFactory() allow_access(self.course, instructor, 'instructor') self.assertTrue(CourseInstructorRole(self.course.id).has_user(instructor)) def test_not_a_coach(self): """ User is not a coach, should get Forbidden response. """ self.make_coach() ccx = self.make_ccx() # create session of non-coach user user = UserFactory.create(password="test") self.client.login(username=user.username, password="test") url = reverse( 'ccx_coach_dashboard', kwargs={'course_id': CCXLocator.from_course_locator(self.course.id, ccx.id)}) response = self.client.get(url) self.assertEqual(response.status_code, 403) def test_no_ccx_created(self): """ No CCX is created, coach should see form to add a CCX. """ self.make_coach() url = reverse( 'ccx_coach_dashboard', kwargs={'course_id': unicode(self.course.id)}) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertTrue(re.search( '