def create_staff_and_instructor(self): """ Creates one instructor and several course staff for self.course. Assigns them to self.instructor (single user) and self.staff (list of users), respectively. """ self.instructor = InstructorFactory(course_key=self.course.id) self.staff = [ StaffFactory(course_key=self.course.id) for __ in xrange(STAFF_COUNT) ]
def test_not_authorized(self): user = StaffFactory(course_key=self.course.id) access_token = AccessTokenFactory.create(user=user, client=self.oauth_client).token auth_header = 'Bearer ' + access_token # Access should be granted if the proper access token is supplied. response = self.http_get_for_course(HTTP_AUTHORIZATION=auth_header) self.assertEqual(response.status_code, 200) # Access should be denied if the user is not course staff. response = self.http_get_for_course(course_id=unicode(self.empty_course.id), HTTP_AUTHORIZATION=auth_header) self.assertEqual(response.status_code, 404)
def setUp(self): super(AccessTestCase, self).setUp() self.course = CourseFactory.create(org='edX', course='toy', run='test_run') self.anonymous_user = AnonymousUserFactory() self.beta_user = BetaTesterFactory(course_key=self.course.id) self.student = UserFactory() self.global_staff = UserFactory(is_staff=True) self.course_staff = StaffFactory(course_key=self.course.id) self.course_instructor = InstructorFactory(course_key=self.course.id) self.staff = GlobalStaffFactory()
def test_course_tabs_list_for_staff_members(self): """ Tests tab list is not limited if user is member of staff and has not passed entrance exam. """ # Login as member of staff self.client.logout() staff_user = StaffFactory(course_key=self.course.id) self.client.login(username=staff_user.username, password='******') request = get_mock_request(staff_user) course_tab_list = get_course_tab_list(request, self.course) self.assertEqual(len(course_tab_list), 4)
def setUp(self): super(AccessTestCase, self).setUp() course_key = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall') self.course = course_key.make_usage_key('course', course_key.run) self.anonymous_user = AnonymousUserFactory() self.beta_user = BetaTesterFactory(course_key=self.course.course_key) self.student = UserFactory() self.global_staff = UserFactory(is_staff=True) self.course_staff = StaffFactory(course_key=self.course.course_key) self.course_instructor = InstructorFactory( course_key=self.course.course_key) self.staff = GlobalStaffFactory()
def setUp(self): super(TestWikiAccess, self).setUp() self.course_310b = CourseFactory.create(org='org', number='310b', display_name='Course') self.course_310b_staff = [ InstructorFactory(course=self.course_310b.location), StaffFactory(course=self.course_310b.location) ] self.course_310b_ = CourseFactory.create(org='org', number='310b_', display_name='Course') self.course_310b__staff = [ InstructorFactory(course=self.course_310b_.location), StaffFactory(course=self.course_310b_.location) ] self.wiki_310b = self.create_urlpath( self.wiki, course_wiki_slug(self.course_310b)) self.wiki_310b_ = self.create_urlpath( self.wiki, course_wiki_slug(self.course_310b_))
def setUp(self): # Clear out the modulestores, causing them to reload clear_existing_modulestores() self.graded_course = modulestore().get_course( SlashSeparatedCourseKey("edX", "graded", "2012_Fall")) # Create staff account self.staff = StaffFactory(course_key=self.graded_course.id) self.logout() # self.staff.password is the sha hash but login takes the plain text self.login(self.staff.email, 'test') self.enroll(self.graded_course)
def setUp(self): super(TestViewAuth, self).setUp() self.course = CourseFactory.create(number='999', display_name='Robot_Super_Course') self.courseware_chapter = ItemFactory.create(display_name='courseware') self.overview_chapter = ItemFactory.create( parent_location=self.course.location, display_name='Super Overview' ) self.welcome_section = ItemFactory.create( parent_location=self.overview_chapter.location, display_name='Super Welcome' ) self.welcome_unit = ItemFactory.create( parent_location=self.welcome_section.location, display_name='Super Unit' ) self.course = modulestore().get_course(self.course.id) self.test_course = CourseFactory.create(org=self.course.id.org) self.other_org_course = CourseFactory.create(org='Other_Org_Course') self.sub_courseware_chapter = ItemFactory.create( parent_location=self.test_course.location, display_name='courseware' ) self.sub_overview_chapter = ItemFactory.create( parent_location=self.sub_courseware_chapter.location, display_name='Overview' ) self.sub_welcome_section = ItemFactory.create( parent_location=self.sub_overview_chapter.location, display_name='Welcome' ) self.sub_welcome_unit = ItemFactory.create( parent_location=self.sub_welcome_section.location, display_name='New Unit' ) self.test_course = modulestore().get_course(self.test_course.id) self.global_staff_user = GlobalStaffFactory() self.unenrolled_user = UserFactory(last_name="Unenrolled") self.enrolled_user = UserFactory(last_name="Enrolled") CourseEnrollmentFactory(user=self.enrolled_user, course_id=self.course.id) CourseEnrollmentFactory(user=self.enrolled_user, course_id=self.test_course.id) self.staff_user = StaffFactory(course_key=self.course.id) self.instructor_user = InstructorFactory(course_key=self.course.id) self.org_staff_user = OrgStaffFactory(course_key=self.course.id) self.org_instructor_user = OrgInstructorFactory(course_key=self.course.id)
def test_entrance_exam_gating_for_staff(self): """ Tests gating is disabled if user is member of staff. """ # Login as member of staff self.client.logout() staff_user = StaffFactory(course_key=self.course.id) staff_user.is_staff = True self.client.login(username=staff_user.username, password='******') # assert staff has access to all toc self.request.user = staff_user unlocked_toc = self._return_table_of_contents() for toc_section in self.expected_unlocked_toc: self.assertIn(toc_section, unlocked_toc)
def setUp(self): super(TestWikiAccessForNumericalCourseNumber, self).setUp() self.course_200 = CourseFactory.create(org='org', number='200', display_name='Course') self.course_200_staff = [ InstructorFactory(course=self.course_200.location), StaffFactory(course=self.course_200.location) ] wiki_200 = self.create_urlpath(self.wiki, course_wiki_slug(self.course_200)) wiki_200_page = self.create_urlpath(wiki_200, 'Child') wiki_200_page_page = self.create_urlpath(wiki_200_page, 'Grandchild') self.wiki_200_pages = [wiki_200, wiki_200_page, wiki_200_page_page]
def test_student_admin_staff_instructor(self): """ Verify that staff users are not able to see course-wide options, while still seeing individual learner options. """ # Original (instructor) user can see both specific grades, and course-wide grade adjustment tools response = self.client.get(self.url) self.assertIn('<h4 class="hd hd-4">Adjust all enrolled learners', response.content) self.assertIn('<h4 class="hd hd-4">View a specific learner's grades and progress', response.content) # But staff user can only see specific grades staff = StaffFactory(course_key=self.course.id) self.client.login(username=staff.username, password="******") response = self.client.get(self.url) self.assertNotIn('<h4 class="hd hd-4">Adjust all enrolled learners', response.content) self.assertIn('<h4 class="hd hd-4">View a specific learner's grades and progress', response.content)
def test_save_completion_staff_ended(self, store): """ Save a CourseModuleCompletion with the feature flag on a course that has not yet started but Staff should be able to write """ self._create_course(store=store, end=datetime(1999, 1, 1, tzinfo=UTC())) self.user = StaffFactory(course_key=self.course.id) module = self.get_module_for_user(self.user, self.course, self.problem4) module.system.publish(module, 'progress', {}) with self.assertRaises(CourseModuleCompletion.DoesNotExist): CourseModuleCompletion.objects.get( user=self.user.id, course_id=self.course.id, content_id=self.problem4.location )
def test_save_completion_staff_not_started(self): """ Save a CourseModuleCompletion with the feature flag on a course that has not yet started but Staff should be able to write """ self._create_course(start=datetime(3000, 1, 1, tzinfo=UTC())) self.user = StaffFactory(course_key=self.course.id) module = self.get_module_for_user(self.user, self.course, self.problem4) module.system.publish(module, 'progress', {}) completion_fetch = CourseModuleCompletion.objects.get( user=self.user.id, course_id=self.course.id, content_id=self.problem4.location ) self.assertIsNotNone(completion_fetch)
def test_instructor_tab(self): """ Verify that the instructor tab appears for staff only. """ def has_instructor_tab(user, course): """Returns true if the "Instructor" tab is shown.""" request = RequestFactory().request() request.user = user tabs = get_course_tab_list(request, course) return len([tab for tab in tabs if tab.name == 'Instructor']) == 1 self.assertTrue(has_instructor_tab(self.instructor, self.course)) staff = StaffFactory(course_key=self.course.id) self.assertTrue(has_instructor_tab(staff, self.course)) student = UserFactory.create() self.assertFalse(has_instructor_tab(student, self.course))
def i_am_staff_or_instructor(step, role): # pylint: disable=unused-argument ## In summary: makes a test course, makes a new Staff or Instructor user ## (depending on `role`), and logs that user in to the course # Store the role assert_in(role, ['instructor', 'staff']) # Clear existing courses to avoid conflicts world.clear_courses() # Create a new course course = world.CourseFactory.create( org='edx', number='999', display_name='Test Course' ) world.course_key = course.id world.role = 'instructor' # Log in as the an instructor or staff for the course if role == 'instructor': # Make & register an instructor for the course world.instructor = InstructorFactory(course_key=world.course_key) world.enroll_user(world.instructor, world.course_key) world.log_in( username=world.instructor.username, password='******', email=world.instructor.email, name=world.instructor.profile.name ) else: world.role = 'staff' # Make & register a staff member world.staff = StaffFactory(course_key=world.course_key) world.enroll_user(world.staff, world.course_key) world.log_in( username=world.staff.username, password='******', email=world.staff.email, name=world.staff.profile.name )
def create_user_for_course(self, course, user_type=CourseUserType.ENROLLED): """ Create a test user for a course. """ if user_type is CourseUserType.ANONYMOUS: return AnonymousUser() is_enrolled = user_type is CourseUserType.ENROLLED is_unenrolled_staff = user_type is CourseUserType.UNENROLLED_STAFF # Set up the test user if is_unenrolled_staff: user = StaffFactory(course_key=course.id, password=self.TEST_PASSWORD) else: user = UserFactory(password=self.TEST_PASSWORD) self.client.login(username=user.username, password=self.TEST_PASSWORD) if is_enrolled: CourseEnrollment.enroll(user, course.id) return user
def make_populated_course(step): # pylint: disable=unused-argument ## This is different than the function defined in common.py because it enrolls ## a staff, instructor, and student member regardless of what `role` is, then ## logs `role` in. This is to ensure we have 3 class participants to email. # Clear existing courses to avoid conflicts world.clear_courses() # Create a new course course = world.CourseFactory.create(org='edx', number='888', display_name='Bulk Email Test Course') world.bulk_email_course_key = course.id try: # See if we've defined the instructor & staff user yet world.bulk_email_instructor except AttributeError: # Make & register an instructor for the course world.bulk_email_instructor = InstructorFactory( course_key=world.bulk_email_course_key) world.enroll_user(world.bulk_email_instructor, world.bulk_email_course_key) # Make & register a staff member world.bulk_email_staff = StaffFactory(course_key=course.id) world.enroll_user(world.bulk_email_staff, world.bulk_email_course_key) # Make & register a student world.register_by_course_key(course.id, username='******', password='******', is_staff=False) # Store the expected recipients # given each "send to" option staff_emails = [ world.bulk_email_staff.email, world.bulk_email_instructor.email ] world.expected_addresses = { 'course staff': staff_emails, 'students, staff, and instructors': staff_emails + ['*****@*****.**'] }
def test_preview(self): """ Verify the behavior of preview for the course outline. """ course = CourseFactory.create(start=datetime.datetime.now() - datetime.timedelta(days=30)) staff_user = StaffFactory(course_key=course.id, password=TEST_PASSWORD) CourseEnrollment.enroll(staff_user, course.id) future_date = datetime.datetime.now() + datetime.timedelta(days=30) with self.store.bulk_operations(course.id): chapter = ItemFactory.create( category='chapter', parent_location=course.location, display_name='First Chapter', ) sequential = ItemFactory.create(category='sequential', parent_location=chapter.location) ItemFactory.create(category='vertical', parent_location=sequential.location) chapter = ItemFactory.create( category='chapter', parent_location=course.location, display_name='Future Chapter', start=future_date, ) sequential = ItemFactory.create(category='sequential', parent_location=chapter.location) ItemFactory.create(category='vertical', parent_location=sequential.location) # Verify that a staff user sees a chapter with a due date in the future self.client.login(username=staff_user.username, password='******') url = course_home_url(course) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertContains(response, 'Future Chapter') # Verify that staff masquerading as a learner does not see the future chapter. self.update_masquerade(course, role='student') response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertNotContains(response, 'Future Chapter')
def setUp(self): super(TestInlineAnalytics, self).setUp() self.user = UserFactory.create() self.request = RequestFactory().get('/') self.request.user = self.user self.request.session = {} self.course = CourseFactory.create( org='A', number='B', display_name='C', ) self.staff = StaffFactory(course_key=self.course.id) self.instructor = InstructorFactory(course_key=self.course.id) self.problem_xml = OptionResponseXMLFactory().build_xml( question_text='The correct answer is Correct', num_inputs=2, weight=2, options=['Correct', 'Incorrect'], correct_option='Correct', ) self.descriptor = ItemFactory.create( category='problem', data=self.problem_xml, display_name='Option Response Problem', rerandomize='never', ) self.location = self.descriptor.location self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents( self.course.id, self.user, self.descriptor, ) self.field_data_cache_staff = FieldDataCache.cache_for_descriptor_descendents( self.course.id, self.staff, self.descriptor, ) self.field_data_cache_instructor = FieldDataCache.cache_for_descriptor_descendents( self.course.id, self.instructor, self.descriptor, )
def setUp(self): self.wiki = get_or_create_root() self.course_math101 = CourseFactory.create(org='org', number='math101', display_name='Course') self.course_math101_staff = [ InstructorFactory(course=self.course_math101.location), StaffFactory(course=self.course_math101.location) ] wiki_math101 = self.create_urlpath( self.wiki, course_wiki_slug(self.course_math101)) wiki_math101_page = self.create_urlpath(wiki_math101, 'Child') wiki_math101_page_page = self.create_urlpath(wiki_math101_page, 'Grandchild') self.wiki_math101_pages = [ wiki_math101, wiki_math101_page, wiki_math101_page_page ]
def setUp(self): super(TestWikiAccessForOldFormatCourseStaffGroups, self).setUp() self.course_math101c = CourseFactory.create(org='org', number='math101c', display_name='Course') Group.objects.get_or_create(name='instructor_math101c') self.course_math101c_staff = [ InstructorFactory(course=self.course_math101c.location), StaffFactory(course=self.course_math101c.location) ] wiki_math101c = self.create_urlpath( self.wiki, course_wiki_slug(self.course_math101c)) wiki_math101c_page = self.create_urlpath(wiki_math101c, 'Child') wiki_math101c_page_page = self.create_urlpath(wiki_math101c_page, 'Grandchild') self.wiki_math101c_pages = [ wiki_math101c, wiki_math101c_page, wiki_math101c_page_page ]
def setUp(self): super(EmailSendFromDashboardTestCase, self).setUp() course_title = u"ẗëṡẗ title イ乇丂イ ᄊ乇丂丂ムg乇 キo尺 ムレレ тэѕт мэѕѕаБэ" self.course = CourseFactory.create(display_name=course_title) self.instructor = InstructorFactory(course_key=self.course.id) # Create staff self.staff = [ StaffFactory(course_key=self.course.id) for _ in xrange(STAFF_COUNT) ] # Create students self.students = [UserFactory() for _ in xrange(STUDENT_COUNT)] for student in self.students: CourseEnrollmentFactory.create(user=student, course_id=self.course.id) # load initial content (since we don't run migrations as part of tests): call_command("loaddata", "course_email_template.json") self.client.login(username=self.instructor.username, password="******") # Pull up email view on instructor dashboard self.url = reverse( 'instructor_dashboard', kwargs={'course_id': self.course.id.to_deprecated_string()}) # Response loads the whole instructor dashboard, so no need to explicitly # navigate to a particular email section response = self.client.get(self.url) email_section = '<div class="vert-left send-email" id="section-send-email">' # If this fails, it is likely because ENABLE_INSTRUCTOR_EMAIL is set to False self.assertTrue(email_section in response.content) self.send_mail_url = reverse( 'send_email', kwargs={'course_id': self.course.id.to_deprecated_string()}) self.success_content = { 'course_id': self.course.id.to_deprecated_string(), 'success': True, }
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='******') CourseEnrollment.enroll(staff_user, self.course.id) url = reverse('courseware_section', kwargs={ 'course_id': unicode(self.course.id), 'chapter': self.chapter.location.name, 'section': self.chapter_subsection.location.name }) resp = self.client.get(url) self.assertEqual(resp.status_code, 200) self.assertNotIn('To access course materials, you must score', resp.content) self.assertNotIn('You have passed the entrance exam.', resp.content)
def setUp(self): course_title = u"ẗëṡẗ title イ乇丂イ ᄊ乇丂丂ムg乇 キo尺 ムレレ тэѕт мэѕѕаБэ" self.course = CourseFactory.create(display_name=course_title) self.instructor = InstructorFactory(course=self.course.location) # Create staff self.staff = [ StaffFactory(course=self.course.location) for _ in xrange(STAFF_COUNT) ] # Create students self.students = [UserFactory() for _ in xrange(STUDENT_COUNT)] for student in self.students: CourseEnrollmentFactory.create(user=student, course_id=self.course.id) # load initial content (since we don't run migrations as part of tests): call_command("loaddata", "course_email_template.json") self.client.login(username=self.instructor.username, password="******") # Pull up email view on instructor dashboard self.url = reverse('instructor_dashboard', kwargs={'course_id': self.course.id}) response = self.client.get(self.url) email_link = '<a href="#" onclick="goto(\'Email\')" class="None">Email</a>' # If this fails, it is likely because ENABLE_INSTRUCTOR_EMAIL is set to False self.assertTrue(email_link in response.content) # Select the Email view of the instructor dash session = self.client.session session['idash_mode'] = 'Email' session.save() response = self.client.get(self.url) selected_email_link = '<a href="#" onclick="goto(\'Email\')" class="selectedmode">Email</a>' self.assertTrue(selected_email_link in response.content)
def test_closed_course_staff(self): """ Users marked as course staff should be able to submit grade events to a closed course """ course = self.setup_course_with_grading( start=datetime(2010, 1, 1, tzinfo=UTC()), end=datetime(2011, 1, 1, tzinfo=UTC()), ) self.user = StaffFactory(course_key=course.id) module = self.get_module_for_user(self.user, course, course.homework_assignment) grade_dict = {'value': 0.5, 'max_value': 1, 'user_id': self.user.id} module.system.publish(module, 'grade', grade_dict) with self.assertRaises(StudentGradebook.DoesNotExist): __ = StudentGradebook.objects.get(user=self.user, course_id=course.id) gradebook = StudentGradebook.objects.all() self.assertEqual(len(gradebook), 0) history = StudentGradebookHistory.objects.all() self.assertEqual(len(history), 0)
def setUp(self): super(InlineAnalyticsAnswerDistributionWithOverrides, self).setUp() self.user = UserFactory.create() self.factory = RequestFactory() self.course = CourseFactory.create( org='A', number='B', display_name='C', ) self.staff = StaffFactory(course_key=self.course.id) self.instructor = InstructorFactory(course_key=self.course.id) analytics_data = { 'module_id': '123', 'question_types_by_part': 'radio', 'num_options_by_part': 6, 'course_id': 'A/B/C', } json_analytics_data = json.dumps(analytics_data) self.data = json_analytics_data self.zendesk_response = ( 'A problem has occurred retrieving the data, to report the problem click ' '<a href="{ZENDESK_URL}/hc/en-us/requests/new">here</a>').format( ZENDESK_URL=ZENDESK_URL)
def test_not_authorized(self): """ Unauthorized users should get an empty list. """ user = StaffFactory(course_key=self.course.id) access_token = AccessTokenFactory.create( user=user, client=self.oauth_client).token auth_header = 'Bearer ' + access_token # If debug mode is enabled, the view should always return data. with override_settings(DEBUG=True): response = self.http_get(reverse(self.view), HTTP_AUTHORIZATION=auth_header) self.assertEqual(response.status_code, 200) # Data should be returned if the user is authorized. response = self.http_get(reverse(self.view), HTTP_AUTHORIZATION=auth_header) self.assertEqual(response.status_code, 200) url = "{}?course_id={}".format(reverse(self.view), self.course_id) response = self.http_get(url, HTTP_AUTHORIZATION=auth_header) self.assertEqual(response.status_code, 200) data = response.data['results'] self.assertEqual(len(data), 1) self.assertEqual(data[0]['name'], self.course.display_name) # The view should return an empty list if the user cannot access any courses. url = "{}?course_id={}".format(reverse(self.view), unicode(self.empty_course.id)) response = self.http_get(url, HTTP_AUTHORIZATION=auth_header) self.assertEqual(response.status_code, 200) self.assertDictContainsSubset({ 'count': 0, u'results': [] }, response.data)
def test_not_authorized(self): user = StaffFactory(course_key=self.course.id) access_token = AccessTokenFactory.create( user=user, client=self.oauth_client).token auth_header = 'Bearer ' + access_token # If debug mode is enabled, the view should always return data. with override_settings(DEBUG=True): response = self.http_get(reverse( self.view, kwargs={'course_id': self.course_id}), HTTP_AUTHORIZATION=auth_header) self.assertEqual(response.status_code, 200) # Access should be granted if the proper access token is supplied. response = self.http_get(reverse(self.view, kwargs={'course_id': self.course_id}), HTTP_AUTHORIZATION=auth_header) self.assertEqual(response.status_code, 200) # Access should be denied if the user is not course staff. response = self.http_get(reverse( self.view, kwargs={'course_id': unicode(self.empty_course.id)}), HTTP_AUTHORIZATION=auth_header) self.assertEqual(response.status_code, 403)
def setUpTestData(cls): """Set up and enroll our fake user in the course.""" cls.staff_user = StaffFactory(course_key=cls.course.id, password=TEST_PASSWORD) cls.user = UserFactory(password=TEST_PASSWORD) CourseEnrollment.enroll(cls.user, cls.course.id)
def create_user(self): """ Creates a staff user. """ return StaffFactory(course_key=self.course.id)