def setUp(self): super(PeerReviewDashboardStudentTest, self).setUp() self.base = '/' + self.COURSE_NAME context = actions.simple_add_course( self.COURSE_NAME, '*****@*****.**', 'Peer Back Button Child') self.course = courses.Course(None, context) self.assessment = self.course.add_assessment() self.assessment.title = 'Assessment' self.assessment.html_content = 'assessment content' self.assessment.workflow_yaml = ( '{grader: human,' 'matcher: peer,' 'review_due_date: \'2034-07-01 12:00\',' 'review_min_count: 1,' 'review_window_mins: 20,' 'submission_due_date: \'2034-07-01 12:00\'}') self.assessment.now_available = True self.course.save() actions.login(self.STUDENT_EMAIL) actions.register(self, self.STUDENT_EMAIL) actions.submit_assessment( self, self.assessment.unit_id, {'answers': '', 'score': 0, 'assessment_type': self.assessment.unit_id}, presubmit_checks=False )
def test_registration_closed(self): """Test student registration when course is full.""" email = '*****@*****.**' name = 'Test Registration Closed' # Override course.yaml settings by patching app_context. get_environ_old = sites.ApplicationContext.get_environ def get_environ_new(self): environ = get_environ_old(self) environ['reg_form']['can_register'] = False return environ sites.ApplicationContext.get_environ = get_environ_new # Try to login and register. actions.login(email) try: actions.register(self, name) raise actions.ShouldHaveFailedByNow( 'Expected to fail: new registrations should not be allowed ' 'when registration is closed.') except actions.ShouldHaveFailedByNow as e: raise e except: pass # Clean up app_context. sites.ApplicationContext.get_environ = get_environ_old
def test_student_cannot_see_reviews_prematurely(self): """Test that students cannot see others' reviews prematurely.""" email = '*****@*****.**' name = 'Student 1' submission = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True}, ]) payload = { 'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload) # Student 1 cannot see the reviews for his assignment yet, because he # has not submitted the two required reviews. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('Due date for this assignment', response.body) assert_contains( 'After you have completed the required number of peer reviews', response.body) actions.logout()
def test_multiple_course(self): """Tests when multiple courses are available.""" sites.setup_courses('course:/test::ns_test, course:/:/') name = 'Test completed course' email = 'Student' # Make the course available. get_environ_old = sites.ApplicationContext.get_environ def get_environ_new(self): environ = get_environ_old(self) environ['course']['now_available'] = True return environ sites.ApplicationContext.get_environ = get_environ_new actions.login(email) actions.register(self, name) response = self.get('/explorer/courses') # Assert if 'View course list' text is shown on my course page. assert_contains('View course list', response.body) # Clean up app_context. sites.ApplicationContext.get_environ = get_environ_old sites.reset_courses()
def test_not_enough_assignments_to_allocate(self): """Test for the case when there are too few assignments in the pool.""" email = '*****@*****.**' name = 'Student 1' submission = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True}, ]) payload = { 'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload) # The student goes to the review dashboard and requests an assignment # to review -- but there is nothing to review. response = actions.request_new_review( self, LEGACY_REVIEW_UNIT_ID, expected_status_code=200) assert_does_not_contain('Assignment to review', response.body) assert_contains('Sorry, there are no new submissions ', response.body) assert_contains('disabled="true"', response.body) actions.logout()
def test_attempt_activity_event(self): """Test activity attempt generates event.""" email = '*****@*****.**' name = 'Test Attempt Activity Event' actions.login(email) actions.register(self, name) # Enable event recording. config.Registry.db_overrides[ lessons.CAN_PERSIST_ACTIVITY_EVENTS.name] = True # Prepare event. request = {} request['source'] = 'test-source' request['payload'] = json.dumps({'Alice': 'Bob'}) # Check XSRF token is required. response = self.post('rest/events?%s' % urllib.urlencode( {'request': json.dumps(request)}), {}) assert_equals(response.status_int, 200) assert_contains('"status": 403', response.body) # Check PUT works. request['xsrf_token'] = XsrfTokenManager.create_xsrf_token( 'event-post') response = self.post('rest/events?%s' % urllib.urlencode( {'request': json.dumps(request)}), {}) assert_equals(response.status_int, 200) assert not response.body # Clean up. config.Registry.db_overrides = {}
def test_student_cannot_see_reviews_prematurely(self): """Test that students cannot see others' reviews prematurely.""" email = "*****@*****.**" name = "Student 1" submission = transforms.dumps( [ {"index": 0, "type": "regex", "value": "S1-1", "correct": True}, {"index": 1, "type": "choices", "value": 3, "correct": False}, {"index": 2, "type": "regex", "value": "is-S1", "correct": True}, ] ) payload = {"answers": submission, "assessment_type": LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload) # Student 1 cannot see the reviews for his assignment yet, because he # has not submitted the two required reviews. response = self.get("assessment?name=%s" % LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains("Due date for this assignment", response.body) assert_contains("After you have completed the required number of peer reviews", response.body) actions.logout()
def test_not_enough_assignments_to_allocate(self): """Test for the case when there are too few assignments in the pool.""" email = "*****@*****.**" name = "Student 1" submission = transforms.dumps( [ {"index": 0, "type": "regex", "value": "S1-1", "correct": True}, {"index": 1, "type": "choices", "value": 3, "correct": False}, {"index": 2, "type": "regex", "value": "is-S1", "correct": True}, ] ) payload = {"answers": submission, "assessment_type": LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload) # The student goes to the review dashboard and requests an assignment # to review -- but there is nothing to review. response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID, expected_status_code=200) assert_does_not_contain("Assignment to review", response.body) assert_contains("Sorry, there are no new submissions ", response.body) assert_contains('disabled="true"', response.body) actions.logout()
def test_manage_announcements(self): """Test course author can manage announcements.""" email = '*****@*****.**' name = 'Test Announcements' actions.login(email, True) actions.register(self, name) # add new response = actions.view_announcements(self) add_form = response.forms['gcb-add-announcement'] response = self.submit(add_form) assert_equals(response.status_int, 302) # check added response = actions.view_announcements(self) assert_contains('Sample Announcement (Draft)', response.body) # delete draft response = actions.view_announcements(self) delete_form = response.forms['gcb-delete-announcement-1'] response = self.submit(delete_form) assert_equals(response.status_int, 302) # check deleted assert_does_not_contain('Welcome to the final class!', response.body)
def setUp(self): super(CertificateCriteriaTestCase, self).setUp() self.base = '/' + self.COURSE_NAME context = actions.simple_add_course(self.COURSE_NAME, self.ADMIN_EMAIL, 'Certificate Criteria') self.old_namespace = namespace_manager.get_namespace() namespace_manager.set_namespace('ns_%s' % self.COURSE_NAME) self.course = courses.Course(None, context) self.course.save() actions.login(self.STUDENT_EMAIL) actions.register(self, self.STUDENT_EMAIL) self.student = ( models.StudentProfileDAO.get_enrolled_student_by_email_for( self.STUDENT_EMAIL, context)) # Override course.yaml settings by patching app_context. self.get_environ_old = sites.ApplicationContext.get_environ self.certificate_criteria = [] def get_environ_new(app_context): environ = self.get_environ_old(app_context) environ['certificate_criteria'] = self.certificate_criteria return environ sites.ApplicationContext.get_environ = get_environ_new
def setUp(self): super(CertificateCriteriaTestCase, self).setUp() self.base = '/' + self.COURSE_NAME context = actions.simple_add_course( self.COURSE_NAME, self.ADMIN_EMAIL, 'Certificate Criteria') self.old_namespace = namespace_manager.get_namespace() namespace_manager.set_namespace('ns_%s' % self.COURSE_NAME) self.course = courses.Course(None, context) self.course.save() actions.login(self.STUDENT_EMAIL) actions.register(self, self.STUDENT_EMAIL) self.student = ( models.StudentProfileDAO.get_enrolled_student_by_email_for( self.STUDENT_EMAIL, context)) # Override course.yaml settings by patching app_context. self.get_environ_old = sites.ApplicationContext.get_environ self.certificate_criteria = [] def get_environ_new(app_context): environ = self.get_environ_old(app_context) environ['certificate_criteria'] = self.certificate_criteria return environ sites.ApplicationContext.get_environ = get_environ_new
def test_single_completed_course(self): """Tests when a single completed course is present.""" user = self.make_test_user('*****@*****.**') name = 'Test Assessments' # Register. actions.login(user.email()) actions.register(self, name) response = self.get('/explorer') # Before a course is not completed, # explorer page should not show 'view score' button. assert_does_not_contain('View score', response.body) # Assign a grade to the course enrolled to mark it complete. profile = PersonalProfile.get_by_key_name(user.user_id()) info = {'final_grade': 'A'} course_info_dict = {'': info} profile.course_info = transforms.dumps(course_info_dict) profile.put() # Check if 'View score' text is visible on profile page. response = self.get('/explorer/profile') assert_contains('View score', response.body) # Check if 'Go to course' button is not visible on explorer page. response = self.get('/explorer') assert_does_not_contain('Go to course', response.body) # Check if 'View score' button is visible on explorer page. response = self.get('/explorer') assert_contains('View score', response.body)
def setUp(self): super(PeerReviewDashboardStudentTest, self).setUp() self.base = '/' + self.COURSE_NAME context = actions.simple_add_course(self.COURSE_NAME, '*****@*****.**', 'Peer Back Button Child') self.course = courses.Course(None, context) self.assessment = self.course.add_assessment() self.assessment.title = 'Assessment' self.assessment.html_content = 'assessment content' self.assessment.workflow_yaml = ( '{grader: human,' 'matcher: peer,' 'review_due_date: \'2034-07-01 12:00\',' 'review_min_count: 1,' 'review_window_mins: 20,' 'submission_due_date: \'2034-07-01 12:00\'}') self.assessment.now_available = True self.course.save() actions.login(self.STUDENT_EMAIL) actions.register(self, self.STUDENT_EMAIL) config.Registry.test_overrides[ utils.CAN_PERSIST_ACTIVITY_EVENTS.name] = True actions.submit_assessment( self, self.assessment.unit_id, { 'answers': '', 'score': 0, 'assessment_type': self.assessment.unit_id }, presubmit_checks=False)
def test_single_completed_course(self): """Tests when a single completed course is present.""" email = '*****@*****.**' name = 'Test Assessments' # Register. actions.login(email) actions.register(self, name) response = self.get('/explorer') # Before a course is not completed, # explorer page should not show 'view score' button. assert_does_not_contain('View score', response.body) # Assign a grade to the course enrolled to mark it complete. profile = PersonalProfile.get_by_key_name(email) info = {'final_grade': 'A'} course_info_dict = {'': info} profile.course_info = transforms.dumps(course_info_dict) profile.put() # Check if 'View score' text is visible on profile page. response = self.get('/explorer/profile') assert_contains('View score', response.body) # Check if 'Go to course' button is not visible on explorer page. response = self.get('/explorer') assert_does_not_contain('Go to course', response.body) # Check if 'View score' button is visible on explorer page. response = self.get('/explorer') assert_contains('View score', response.body)
def test_registration_closed(self): """Test student registration when course is full.""" email = '*****@*****.**' name = 'Test Registration Closed' # Override course.yaml settings by patching app_context. get_environ_old = sites.ApplicationContext.get_environ def get_environ_new(self): environ = get_environ_old(self) environ['reg_form']['can_register'] = False return environ sites.ApplicationContext.get_environ = get_environ_new # Try to ogin and register. actions.login(email) try: actions.register(self, name) raise actions.MustFail('Expected to fail.') except actions.MustFail as e: raise e except: pass # Clean up app_context. sites.ApplicationContext.get_environ = get_environ_old
def test_tracked_lessons(self): context = actions.simple_add_course('test', '*****@*****.**', 'Test Course') course = courses.Course(None, context) actions.login('*****@*****.**') actions.register(self, 'Some Admin', 'test') with common_utils.Namespace('ns_test'): foo_id = models.LabelDAO.save(models.LabelDTO( None, {'title': 'Foo', 'descripton': 'foo', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK})) bar_id = models.LabelDAO.save(models.LabelDTO( None, {'title': 'Bar', 'descripton': 'bar', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK})) unit1 = course.add_unit() unit1.now_available = True unit1.labels = str(foo_id) lesson11 = course.add_lesson(unit1) lesson11.objectives = 'common plugh <gcb-youtube videoid="glados">' lesson11.now_available = True lesson11.notes = search_unit_test.VALID_PAGE_URL lesson11.video = 'portal' course.update_unit(unit1) unit2 = course.add_unit() unit2.now_available = True unit1.labels = str(bar_id) lesson21 = course.add_lesson(unit2) lesson21.objectives = 'common plover' lesson21.now_available = True course.update_unit(unit2) course.save() self.index_test_course() # Registered, un-tracked student sees all. response = self.get('/test/search?query=common') self.assertIn('common', response.body) self.assertIn('plugh', response.body) self.assertIn('plover', response.body) response = self.get('/test/search?query=link') # Do see followed links self.assertIn('Partial', response.body) self.assertIn('Absolute', response.body) response = self.get('/test/search?query=lemon') # Do see video refs self.assertIn('v=glados', response.body) # Student with tracks sees filtered view. with common_utils.Namespace('ns_test'): models.Student.set_labels_for_current(str(foo_id)) response = self.get('/test/search?query=common') self.assertIn('common', response.body) self.assertNotIn('plugh', response.body) self.assertIn('plover', response.body) response = self.get('/test/search?query=link') # Links are filtered self.assertNotIn('Partial', response.body) self.assertNotIn('Absolute', response.body) response = self.get('/test/search?query=lemon') # Don't see video refs self.assertNotIn('v=glados', response.body)
def test_student_progress_stats_analytics_displays_on_dashboard(self): """Test analytics page on course dashboard.""" with actions.OverriddenEnvironment( {'course': { analytics.CAN_RECORD_STUDENT_EVENTS: 'true' }}): student1 = '*****@*****.**' name1 = 'Test Student 1' student2 = '*****@*****.**' name2 = 'Test Student 2' # Student 1 completes a unit. actions.login(student1) actions.register(self, name1) actions.view_unit(self) actions.logout() # Student 2 completes a unit. actions.login(student2) actions.register(self, name2) actions.view_unit(self) actions.logout() # Admin logs back in and checks if progress exists. email = '*****@*****.**' actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics_students') assert_contains('Google > Dashboard > Manage > Students', response.body) assert_contains('have not been calculated yet', response.body) response = response.forms['gcb-generate-analytics-data'].submit( ).follow() assert len(self.taskq.GetTasks('default')) == ( ProgressAnalyticsTest.EXPECTED_TASK_COUNT) response = self.get('dashboard?action=analytics_students') assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics_students') assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 2', response.body) assert_contains('total: 2', response.body) assert_contains('Student Progress', response.body) assert_does_not_contain( 'No student progress has been recorded for this course.', response.body) # JSON code for the completion statistics. assert_contains( '\\"u.1.l.1\\": {\\"progress\\": 0, \\"completed\\": 2}', response.body) assert_contains( '\\"u.1\\": {\\"progress\\": 2, \\"completed\\": 0}', response.body)
def test_student_progress_stats_analytics_displays_on_dashboard(self): """Test analytics page on course dashboard.""" self.enable_progress_tracking() student1 = '*****@*****.**' name1 = 'Test Student 1' student2 = '*****@*****.**' name2 = 'Test Student 2' # Student 1 completes a unit. actions.login(student1) actions.register(self, name1) actions.view_unit(self) actions.logout() # Student 2 completes a unit. actions.login(student2) actions.register(self, name2) actions.view_unit(self) actions.logout() # Admin logs back in and checks if progress exists. email = '*****@*****.**' actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics') assert_contains( 'Google ><a href="%s"> Dashboard </a>> Analytics' % self.canonicalize('dashboard'), response.body) assert_contains('have not been calculated yet', response.body) compute_form = response.forms['gcb-compute-student-stats'] response = self.submit(compute_form) assert_equals(response.status_int, 302) assert len(self.taskq.GetTasks('default')) == 5 response = self.get('dashboard?action=analytics') assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics') assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 2', response.body) assert_contains('total: 2', response.body) assert_contains('Student Progress Statistics', response.body) assert_does_not_contain( 'No student progress has been recorded for this course.', response.body) # JSON code for the completion statistics. assert_contains( '\\"u.1.l.1\\": {\\"progress\\": 0, \\"completed\\": 2}', response.body) assert_contains( '\\"u.1\\": {\\"progress\\": 2, \\"completed\\": 0}', response.body)
def test_student_progress_stats_analytics_displays_on_dashboard(self): """Test analytics page on course dashboard.""" with actions.OverriddenEnvironment( {'course': {analytics.CAN_RECORD_STUDENT_EVENTS: 'true'}}): student1 = '*****@*****.**' name1 = 'Test Student 1' student2 = '*****@*****.**' name2 = 'Test Student 2' # Student 1 completes a unit. actions.login(student1) actions.register(self, name1) actions.view_unit(self) actions.logout() # Student 2 completes a unit. actions.login(student2) actions.register(self, name2) actions.view_unit(self) actions.logout() # Admin logs back in and checks if progress exists. email = '*****@*****.**' actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics_students') assert_contains( 'Google > Dashboard > Manage > Students', response.body) assert_contains('have not been calculated yet', response.body) response = response.forms[ 'gcb-generate-analytics-data'].submit().follow() assert len(self.taskq.GetTasks('default')) == ( ProgressAnalyticsTest.EXPECTED_TASK_COUNT) response = self.get('dashboard?action=analytics_students') assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics_students') assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 2', response.body) assert_contains('total: 2', response.body) assert_contains('Student Progress', response.body) assert_does_not_contain( 'No student progress has been recorded for this course.', response.body) # JSON code for the completion statistics. assert_contains( '\\"u.1.l.1\\": {\\"progress\\": 0, \\"completed\\": 2}', response.body) assert_contains( '\\"u.1\\": {\\"progress\\": 2, \\"completed\\": 0}', response.body)
def test_student_progress_stats_analytics_displays_on_dashboard(self): """Test analytics page on course dashboard.""" self.enable_progress_tracking() student1 = '*****@*****.**' name1 = 'Test Student 1' student2 = '*****@*****.**' name2 = 'Test Student 2' # Student 1 completes a unit. actions.login(student1) actions.register(self, name1) actions.view_unit(self) actions.logout() # Student 2 completes a unit. actions.login(student2) actions.register(self, name2) actions.view_unit(self) actions.logout() # Admin logs back in and checks if progress exists. email = '*****@*****.**' actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics') assert_contains( 'Google > Dashboard > Analytics', response.body) assert_contains('have not been calculated yet', response.body) compute_form = response.forms['gcb-compute-student-stats'] response = self.submit(compute_form) assert_equals(response.status_int, 302) assert len(self.taskq.GetTasks('default')) == 4 response = self.get('dashboard?action=analytics') assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics') assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 2', response.body) assert_contains('total: 2', response.body) assert_contains('Student Progress Statistics', response.body) assert_does_not_contain( 'No student progress has been recorded for this course.', response.body) # JSON code for the completion statistics. assert_contains( '\\"u.1.l.1\\": {\\"progress\\": 0, \\"completed\\": 2}', response.body) assert_contains( '\\"u.1\\": {\\"progress\\": 2, \\"completed\\": 0}', response.body)
def test_announcements_rest(self): """Test REST access to announcements.""" email = '*****@*****.**' name = 'Test Announcements Rest' actions.login(email, True) actions.register(self, name) response = actions.view_announcements(self) assert_does_not_contain('My Test Title', response.body) # REST GET existing item items = AnnouncementEntity.all().fetch(1) for item in items: response = self.get('rest/announcements/item?key=%s' % item.key()) json_dict = json.loads(response.body) assert json_dict['status'] == 200 assert 'message' in json_dict assert 'payload' in json_dict payload_dict = json.loads(json_dict['payload']) assert 'title' in payload_dict assert 'date' in payload_dict # REST PUT item payload_dict['title'] = u'My Test Title Мой заголовок теста' payload_dict['date'] = '2012/12/31' payload_dict['is_draft'] = True request = {} request['key'] = str(item.key()) request['payload'] = json.dumps(payload_dict) # Check XSRF is required. response = self.put('rest/announcements/item?%s' % urllib.urlencode( {'request': json.dumps(request)}), {}) assert_equals(response.status_int, 200) assert_contains('"status": 403', response.body) # Check PUT works. request['xsrf_token'] = json_dict['xsrf_token'] response = self.put('rest/announcements/item?%s' % urllib.urlencode( {'request': json.dumps(request)}), {}) assert_equals(response.status_int, 200) assert_contains('"status": 200', response.body) # Confirm change is visible on the page. response = self.get('announcements') assert_contains( u'My Test Title Мой заголовок теста (Draft)', response.body) # REST GET not-existing item response = self.get('rest/announcements/item?key=not_existent_key') json_dict = json.loads(response.body) assert json_dict['status'] == 404
def test_trigger_sample_announcements(self): """Test course author can trigger adding sample announcements.""" email = '*****@*****.**' name = 'Test Announcements' actions.login(email, True) actions.register(self, name) response = actions.view_announcements(self) assert_contains('Example Announcement', response.body) assert_contains('Welcome to the final class!', response.body) assert_does_not_contain('No announcements yet.', response.body)
def test_permissions(self): """Test student permissions, and which pages they can view.""" email = '*****@*****.**' name = 'Test Permissions' actions.login(email) actions.register(self, name) actions.Permissions.assert_enrolled(self) actions.unregister(self) actions.Permissions.assert_unenrolled(self) actions.register(self, name) actions.Permissions.assert_enrolled(self)
def test_xsrf_defence(self): """Test defense against XSRF attack.""" email = '*****@*****.**' name = 'Test Xsrf Defence' actions.login(email) actions.register(self, name) response = self.get('student/home') response.form.set('name', 'My New Name') response.form.set('xsrf_token', 'bad token') response = response.form.submit(expect_errors=True) assert_equals(response.status_int, 403)
def setUp(self): super(CronCleanupTest, self).setUp() admin_email = '*****@*****.**' self.course_one = actions.simple_add_course( COURSE_ONE, admin_email, 'Course One') self.course_two = actions.simple_add_course( COURSE_TWO, admin_email, 'Course Two') actions.login(admin_email, True) actions.register(self, admin_email, COURSE_ONE) actions.register(self, admin_email, COURSE_TWO) self.save_tz = os.environ.get('TZ') os.environ['TZ'] = 'GMT' time.tzset()
def setUp(self): super(CronCleanupTest, self).setUp() admin_email = '*****@*****.**' self.course_one = actions.simple_add_course(COURSE_ONE, admin_email, 'Course One') self.course_two = actions.simple_add_course(COURSE_TWO, admin_email, 'Course Two') actions.login(admin_email, True) actions.register(self, admin_email, COURSE_ONE) actions.register(self, admin_email, COURSE_TWO) self.save_tz = os.environ.get('TZ') os.environ['TZ'] = 'GMT' time.tzset()
def test_course_explorer_disabled(self): """Tests for disabled course explorer page.""" # This call should redirect to course page not explorer page. response = self.get('/') assert_contains('/course', response.location) name = 'Test explorer page off' email = 'student' # Register actions.login(email) actions.register(self, name) response = self.get('/course') # 'My courses' and 'Profile' tab should not be present in tab bar. assert_does_not_contain('My Courses', response.body) assert_does_not_contain('Profile', response.body)
def test_registration(self): """Test student registration.""" email = '*****@*****.**' name1 = 'Test Student' name2 = 'John Smith' name3 = u'Pavel Simakov (тест данные)' actions.login(email) actions.register(self, name1) actions.check_profile(self, name1) actions.change_name(self, name2) actions.unregister(self) actions.register(self, name3) actions.check_profile(self, name3)
def test_registration(self): """Test student registration.""" email = '*****@*****.**' name1 = 'Test Student' name2 = 'John Smith' name3 = 'Pavel Simakov' actions.login(email) actions.register(self, name1) actions.check_profile(self, name1) actions.change_name(self, name2) actions.unregister(self) actions.register(self, name3) actions.check_profile(self, name3)
def test_add_reviewer(self): """Test that admin can add a reviewer, and cannot re-add reviewers.""" email = '*****@*****.**' name = 'Test Add Reviewer' submission = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'First answer to Q1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'First answer to Q3', 'correct': True}, ]) payload = { 'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload) # There is nothing to review on the review dashboard. response = actions.request_new_review( self, LEGACY_REVIEW_UNIT_ID, expected_status_code=200) assert_does_not_contain('Assignment to review', response.body) assert_contains('Sorry, there are no new submissions ', response.body) actions.logout() # The admin assigns the student to review his own work. actions.login(email, is_admin=True) response = actions.add_reviewer( self, LEGACY_REVIEW_UNIT_ID, email, email) assert_equals(response.status_int, 302) response = self.get(response.location) assert_does_not_contain( 'Error 412: The reviewer is already assigned', response.body) assert_contains('First answer to Q1', response.body) assert_contains( 'Review 1 from [email protected]', response.body) # The admin repeats the 'add reviewer' action. This should fail. response = actions.add_reviewer( self, LEGACY_REVIEW_UNIT_ID, email, email) assert_equals(response.status_int, 302) response = self.get(response.location) assert_contains( 'Error 412: The reviewer is already assigned', response.body)
def test_attempt_activity_event(self): """Test activity attempt generates event.""" email = '*****@*****.**' name = 'Test Attempt Activity Event' actions.login(email) actions.register(self, name) # Enable event recording. config.Registry.db_overrides[ lessons.CAN_PERSIST_ACTIVITY_EVENTS.name] = True # Prepare event. request = {} request['source'] = 'test-source' request['payload'] = json.dumps({'Alice': u'Bob (тест данные)'}) # Check XSRF token is required. response = self.post('rest/events?%s' % urllib.urlencode( {'request': json.dumps(request)}), {}) assert_equals(response.status_int, 200) assert_contains('"status": 403', response.body) # Check PUT works. request['xsrf_token'] = XsrfTokenManager.create_xsrf_token( 'event-post') response = self.post('rest/events?%s' % urllib.urlencode( {'request': json.dumps(request)}), {}) assert_equals(response.status_int, 200) assert not response.body # Check event is properly recorded. old_namespace = namespace_manager.get_namespace() namespace_manager.set_namespace(self.namespace) try: events = models.EventEntity.all().fetch(1000) assert 1 == len(events) assert_contains( u'Bob (тест данные)', json.loads(events[0].data)['Alice']) finally: namespace_manager.set_namespace(old_namespace) # Clean up. config.Registry.db_overrides = {}
def test_single_uncompleted_course(self): """Tests for a single available course.""" # This call should redirect to explorer page. response = self.get('/') assert_contains('/explorer', response.location) name = 'Test student courses page' email = 'Student' actions.login(email) # Test the explorer page. response = self.get('/explorer') assert_equals(response.status_int, 200) assert_contains('Register', response.body) # Navbar should not contain profile tab. assert_does_not_contain('<a href="/explorer/profile">Profile</a>', response.body) # Test 'my courses' page when a student is not enrolled in any course. response = self.get('/explorer/courses') assert_equals(response.status_int, 200) assert_contains('You are not currently enrolled in any course', response.body) # Test 'my courses' page when a student is enrolled in all courses. actions.register(self, name) response = self.get('/explorer/courses') assert_equals(response.status_int, 200) assert_contains('Go to course', response.body) assert_does_not_contain('You are not currently enrolled in any course', response.body) # After the student registers for a course, # profile tab should be visible in navbar. assert_contains('<a href="/explorer/profile">Profile</a>', response.body) # Test profile page. response = self.get('/explorer/profile') assert_contains('<td>%s</td>' % email, response.body) assert_contains('<td>%s</td>' % name, response.body) assert_contains('Progress', response.body) assert_does_not_contain('View score', response.body)
def test_single_uncompleted_course(self): """Tests for a single available course.""" # This call should redirect to explorer page. response = self.get('/') assert_contains('/explorer', response.location) name = 'Test student courses page' email = 'Student' actions.login(email) # Test the explorer page. response = self.get('/explorer') assert_equals(response.status_int, 200) assert_contains('Register', response.body) # Navbar should not contain profile tab. assert_does_not_contain( '<a href="/explorer/profile">Profile</a>', response.body) # Test 'my courses' page when a student is not enrolled in any course. response = self.get('/explorer/courses') assert_equals(response.status_int, 200) assert_contains('You are not currently enrolled in any course', response.body) # Test 'my courses' page when a student is enrolled in all courses. actions.register(self, name) response = self.get('/explorer/courses') assert_equals(response.status_int, 200) assert_contains('Go to course', response.body) assert_does_not_contain('You are not currently enrolled in any course', response.body) # After the student registers for a course, # profile tab should be visible in navbar. assert_contains( '<a href="/explorer/profile">Profile</a>', response.body) # Test profile page. response = self.get('/explorer/profile') assert_contains('<td>%s</td>' % email, response.body) assert_contains('<td>%s</td>' % name, response.body) assert_contains('Progress', response.body) assert_does_not_contain('View score', response.body)
def test_lesson_activity_navigation(self): """Test navigation between lesson/activity pages.""" email = '*****@*****.**' name = 'Test Lesson Activity Navigation' actions.login(email) actions.register(self, name) response = self.get('unit?unit=1&lesson=1') assert_does_not_contain('Previous Page', response.body) assert_contains('Next Page', response.body) response = self.get('unit?unit=2&lesson=3') assert_contains('Previous Page', response.body) assert_contains('Next Page', response.body) response = self.get('unit?unit=3&lesson=5') assert_contains('Previous Page', response.body) assert_does_not_contain('Next Page', response.body) assert_contains('End', response.body)
def test_course_pass(self): """Test student passing final exam.""" email = '*****@*****.**' name = 'Test Pass' post = {'assessment_type': 'postcourse', 'score': '100.00'} # Register. actions.login(email) actions.register(self, name) # Submit answer. response = self.submit_assessment('Post', post) assert_equals(response.status_int, 200) assert_contains('Your score is 70%', response.body) assert_contains('you have passed the course', response.body) # Check that the result shows up on the profile page. response = actions.check_profile(self, name) assert_contains('70', response.body) assert_contains('100', response.body)
def test_handling_of_fake_review_step_key(self): """Test that bad keys result in the appropriate responses.""" email = "*****@*****.**" name = "Student 1" submission = transforms.dumps( [ {"index": 0, "type": "regex", "value": "S1-1", "correct": True}, {"index": 1, "type": "choices", "value": 3, "correct": False}, {"index": 2, "type": "regex", "value": "is-S1", "correct": True}, ] ) payload = {"answers": submission, "assessment_type": LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload) actions.view_review(self, LEGACY_REVIEW_UNIT_ID, "Fake key", expected_status_code=404) actions.logout()
def test_handling_of_fake_review_step_key(self): """Test that bad keys result in the appropriate responses.""" email = '*****@*****.**' name = 'Student 1' submission = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True }, ]) payload = { 'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID } actions.login(email) actions.register(self, name) actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload) actions.view_review(self, LEGACY_REVIEW_UNIT_ID, 'Fake key', expected_status_code=404) actions.logout()
def test_handling_of_fake_review_step_key(self): """Test that bad keys result in the appropriate responses.""" email = '*****@*****.**' name = 'Student 1' submission = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True}, ]) payload = { 'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload) actions.view_review( self, LEGACY_REVIEW_UNIT_ID, 'Fake key', expected_status_code=404) actions.logout()
def test_access_to_admin_pages(self): """Test access to admin pages.""" # assert anonymous user has no access response = self.testapp.get('/admin?action=settings') assert_equals(response.status_int, 302) # assert admin user has access email = '*****@*****.**' name = 'Test Access to Admin Pages' actions.login(email, True) actions.register(self, name) response = self.testapp.get('/admin') assert_contains('Power Searching with Google', response.body) assert_contains('All Courses', response.body) response = self.testapp.get('/admin?action=settings') assert_contains('gcb_admin_user_emails', response.body) assert_contains('gcb_config_update_interval_sec', response.body) assert_contains('All Settings', response.body) response = self.testapp.get('/admin?action=perf') assert_contains('gcb-admin-uptime-sec:', response.body) assert_contains('In-process Performance Counters', response.body) response = self.testapp.get('/admin?action=deployment') assert_contains('application_id: testbed-test', response.body) assert_contains('About the Application', response.body) actions.unregister(self) actions.logout() # assert not-admin user has no access actions.login(email) actions.register(self, name) response = self.testapp.get('/admin?action=settings') assert_equals(response.status_int, 302)
def test_add_reviewer(self): """Test that admin can add a reviewer, and cannot re-add reviewers.""" email = "*****@*****.**" name = "Test Add Reviewer" submission = transforms.dumps( [ {"index": 0, "type": "regex", "value": "First answer to Q1", "correct": True}, {"index": 1, "type": "choices", "value": 3, "correct": False}, {"index": 2, "type": "regex", "value": "First answer to Q3", "correct": True}, ] ) payload = {"answers": submission, "assessment_type": LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload) # There is nothing to review on the review dashboard. response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID, expected_status_code=200) assert_does_not_contain("Assignment to review", response.body) assert_contains("Sorry, there are no new submissions ", response.body) actions.logout() # The admin assigns the student to review his own work. actions.login(email, is_admin=True) response = actions.add_reviewer(self, LEGACY_REVIEW_UNIT_ID, email, email) assert_equals(response.status_int, 302) response = self.get(response.location) assert_does_not_contain("Error 412: The reviewer is already assigned", response.body) assert_contains("First answer to Q1", response.body) assert_contains("Review 1 from [email protected]", response.body) # The admin repeats the 'add reviewer' action. This should fail. response = actions.add_reviewer(self, LEGACY_REVIEW_UNIT_ID, email, email) assert_equals(response.status_int, 302) response = self.get(response.location) assert_contains("Error 412: The reviewer is already assigned", response.body)
def test_view_announcements(self): """Test student aspect of announcements.""" email = '*****@*****.**' name = 'Test Announcements' actions.login(email) actions.register(self, name) # Check no announcements yet. response = actions.view_announcements(self) assert_does_not_contain('Example Announcement', response.body) assert_does_not_contain('Welcome to the final class!', response.body) assert_contains('No announcements yet.', response.body) actions.logout() # Login as admin and add announcements. actions.login('*****@*****.**', True) actions.register(self, 'admin') response = actions.view_announcements(self) actions.logout() # Check we can see non-draft announcements. actions.login(email) response = actions.view_announcements(self) assert_contains('Example Announcement', response.body) assert_does_not_contain('Welcome to the final class!', response.body) assert_does_not_contain('No announcements yet.', response.body) # Check no access to access to draft announcements via REST handler. items = AnnouncementEntity.all().fetch(1000) for item in items: response = self.get('rest/announcements/item?key=%s' % item.key()) if item.is_draft: json_dict = json.loads(response.body) assert json_dict['status'] == 401 else: assert_equals(response.status_int, 200)
def test_two_students_dont_see_each_other_pages(self): """Test a user can't see another user pages.""" email1 = '*****@*****.**' name1 = 'User 1' email2 = '*****@*****.**' name2 = 'User 2' # Login as one user and view 'unit' and other pages, which are not # cached. actions.login(email1) actions.register(self, name1) actions.Permissions.assert_enrolled(self) response = actions.view_unit(self) assert_contains(email1, response.body) actions.logout() # Login as another user and check that 'unit' and other pages show # the correct new email. actions.login(email2) actions.register(self, name2) actions.Permissions.assert_enrolled(self) response = actions.view_unit(self) assert_contains(email2, response.body) actions.logout()
def register(): if request.method == "POST": username = request.form.get('username') password = request.form.get('password') try: if act.register(username, password): flash("Welcome {}, to your Personal Finance Assistant!".format( username), category="success") return redirect(url_for('dashboard')) else: flash("User Account already exists", category="danger") return redirect(url_for('index')) except Exception as e: flash("An error occurred: {}".format(str(e)), category="danger") else: flash("Invalid Action", category="danger") return redirect(url_for("index"))
def test_independence_of_draft_reviews(self): """Test that draft reviews do not interfere with each other.""" email1 = '*****@*****.**' name1 = 'Student 1' submission1 = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True }, ]) payload1 = { 'answers': submission1, 'assessment_type': LEGACY_REVIEW_UNIT_ID } email2 = '*****@*****.**' name2 = 'Student 2' submission2 = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S2-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True }, ]) payload2 = { 'answers': submission2, 'assessment_type': LEGACY_REVIEW_UNIT_ID } email3 = '*****@*****.**' name3 = 'Student 3' submission3 = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S3-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True }, ]) payload3 = { 'answers': submission3, 'assessment_type': LEGACY_REVIEW_UNIT_ID } # Student 1 submits the assignment. actions.login(email1) actions.register(self, name1) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload1) actions.logout() # Student 2 logs in and submits the assignment. actions.login(email2) actions.register(self, name2) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload2) actions.logout() # Student 3 logs in and submits the assignment. actions.login(email3) actions.register(self, name3) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload3) actions.logout() # Student 1 logs in and requests two assignments to review. actions.login(email1) response = self.get('/reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('Assignment to review', response.body) assert_contains('not-S1', response.body) review_step_key_1_for_someone = get_review_step_key(response) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('Assignment to review', response.body) assert_contains('not-S1', response.body) review_step_key_1_for_someone_else = get_review_step_key(response) self.assertNotEqual(review_step_key_1_for_someone, review_step_key_1_for_someone_else) # Student 1 submits two draft reviews. response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone, get_review_payload('R1forFirst', is_draft=True)) assert_contains('Your review has been saved.', response.body) response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone_else, get_review_payload('R1forSecond', is_draft=True)) assert_contains('Your review has been saved.', response.body) # The two draft reviews should still be different when subsequently # accessed. response = self.get( 'review?unit=%s&key=%s' % (LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone)) assert_contains('R1forFirst', response.body) response = self.get( 'review?unit=%s&key=%s' % (LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone_else)) assert_contains('R1forSecond', response.body) # Student 1 logs out. actions.logout()
def test_peer_review_analytics(self): """Test analytics page on course dashboard.""" student1 = '*****@*****.**' name1 = 'Test Student 1' student2 = '*****@*****.**' name2 = 'Test Student 2' peer = {'assessment_type': 'ReviewAssessmentExample'} # Student 1 submits a peer review assessment. actions.login(student1) actions.register(self, name1) actions.submit_assessment(self, 'ReviewAssessmentExample', peer) actions.logout() # Student 2 submits the same peer review assessment. actions.login(student2) actions.register(self, name2) actions.submit_assessment(self, 'ReviewAssessmentExample', peer) actions.logout() email = '*****@*****.**' # The admin looks at the analytics page on the dashboard. actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics') assert_contains( 'Google ><a href="%s"> Dashboard </a>> Analytics' % self.canonicalize('dashboard'), response.body) assert_contains('have not been calculated yet', response.body) compute_form = response.forms['gcb-compute-student-stats'] response = self.submit(compute_form) assert_equals(response.status_int, 302) assert len(self.taskq.GetTasks('default')) == 5 response = self.get('dashboard?action=analytics') assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics') assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 2', response.body) assert_contains('total: 2', response.body) assert_contains('Peer Review Statistics', response.body) assert_contains('Sample peer review assignment', response.body) # JSON code for the completion statistics. assert_contains('"[{\\"stats\\": [2]', response.body) actions.logout() # Student2 requests a review. actions.login(student2) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) review_step_key_2_for_1 = get_review_step_key(response) assert_contains('Assignment to review', response.body) # Student2 submits the review. response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, get_review_payload('R2for1')) assert_contains( 'Your review has been submitted successfully', response.body) actions.logout() actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics') assert_contains( 'Google ><a href="%s"> Dashboard </a>> Analytics' % self.canonicalize('dashboard'), response.body) compute_form = response.forms['gcb-compute-student-stats'] response = self.submit(compute_form) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics') assert_contains('Peer Review Statistics', response.body) # JSON code for the completion statistics. assert_contains('"[{\\"stats\\": [1, 1]', response.body) actions.logout()