def test_not_from_cron_and_not_admin(self): config.set_report_allowed(True) actions.logout() response = self.get(usage_reporting.StartReportingJobs.URL, expect_errors=True) self.assertEquals(403, response.status_int) self.assertEquals('Forbidden.', response.body)
def test_lesson_access_title_only(self): actions.logout() self.unit.availability = courses.AVAILABILITY_AVAILABLE self.lesson.availability = courses.AVAILABILITY_UNAVAILABLE self.lesson.shown_when_unavailable = True self.course.save() expected_lesson = {'title': self.lesson.title, 'body': None} # Access single lesson response = self.get_response( '{course(id: "%s") {unit(id: "%s") {' 'lesson(id: "%s") {title body}}}}' % ( self.course_id, self.unit_id, self.lesson_id)) _lesson = response['data']['course']['unit']['lesson'] self.assertEquals(expected_lesson, _lesson) # Access lesson list response = self.get_response( '{course(id: "%s") {unit(id: "%s") {allLessons {edges {node {' ' ... on Lesson{title body}}}}}}}' % ( self.course_id, self.unit_id)) edges = response['data']['course']['unit']['allLessons']['edges'] self.assertEquals(1, len(edges)) self.assertEquals(expected_lesson, edges[0]['node'])
def setUp(self): super(RolesTest, self).setUp() actions.login(COURSE_ADMIN_EMAIL, is_admin=True) payload_dict = { 'name': COURSE_NAME, 'title': 'Roles Test', 'admin_email': COURSE_ADMIN_EMAIL} request = { 'payload': transforms.dumps(payload_dict), 'xsrf_token': crypto.XsrfTokenManager.create_xsrf_token( 'add-course-put')} response = self.testapp.put('/rest/courses/item?%s' % urllib.urlencode( {'request': transforms.dumps(request)}), {}) self.assertEquals(response.status_int, 200) sites.setup_courses('course:/%s::ns_%s, course:/:/' % ( COURSE_NAME, COURSE_NAME)) actions.logout() config.Registry.test_overrides[roles.GCB_ADMIN_LIST.name] = ( '[%s]' % SITE_ADMIN_EMAIL) # pylint: disable-msg=protected-access self.old_registered_permission = roles.Roles._REGISTERED_PERMISSIONS roles.Roles._REGISTERED_PERMISSIONS = {} config.Registry.test_overrides[models.CAN_USE_MEMCACHE.name] = True
def setUp(self): super(StudentLabelsTest, self).setUp() actions.simple_add_course(COURSE_NAME, ADMIN_EMAIL, COURSE_TITLE) with common_utils.Namespace(NAMESPACE): self.foo_id = models.LabelDAO.save(models.LabelDTO( None, {'title': 'Foo', 'descripton': 'foo', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK})) self.bar_id = models.LabelDAO.save(models.LabelDTO( None, {'title': 'Bar', 'descripton': 'bar', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK})) self.baz_id = models.LabelDAO.save(models.LabelDTO( None, {'title': 'Baz', 'descripton': 'baz', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK})) self.quux_id = models.LabelDAO.save(models.LabelDTO( None, {'title': 'Quux', 'descripton': 'quux', 'type': models.LabelDTO.LABEL_TYPE_GENERAL})) actions.login(REGISTERED_STUDENT_EMAIL) actions.register(self, REGISTERED_STUDENT_NAME, COURSE_NAME) actions.logout()
def test_not_logged_in(self): actions.logout() response = self.get(UNIT_PROGRESS_URL + '?key=%s' % self._unit_one.unit_id) self._expect_response( response, 403, 'Bad XSRF token. Please reload the page and try again')
def test_enrollment(self): actions.logout() response = self.get_response( '{course(id: "%s") {enrollment {email enrolled}}}' % ( self.course_id)) enrollment = response['data']['course']['enrollment'] self.assertEquals({'enrolled': False, 'email': None}, enrollment) actions.login(STUDENT_EMAIL) response = self.get_response( '{course(id: "%s") {enrollment {email enrolled}}}' % ( self.course_id)) enrollment = response['data']['course']['enrollment'] self.assertEquals({'enrolled': False, 'email': None}, enrollment) actions.register(self, STUDENT_NAME) response = self.get_response( '{course (id: "%s") { enrollment { email enrolled}}}' % ( self.course_id)) enrollment = response['data']['course']['enrollment'] self.assertEquals( {'enrolled': True, 'email': STUDENT_EMAIL}, enrollment)
def test_guide_enabled_course(self): with actions.OverriddenEnvironment(self.GUIDE_ENABLED_COURSE): actions.logout() self.assert_guide_accesssible("Alpha") self.assert_guide_accesssible("Bravo") self.assert_guide_not_accesssible("Charlie", is_guides_accessible=True) self.assert_guide_not_accesssible("Delta", is_guides_accessible=True) actions.login("*****@*****.**") self.assert_guide_accesssible("Alpha") self.assert_guide_accesssible("Bravo") self.assert_guide_not_accesssible("Charlie", is_guides_accessible=True) self.assert_guide_not_accesssible("Delta", is_guides_accessible=True) self.register("Charlie") self.assert_guide_accesssible("Alpha") self.assert_guide_accesssible("Bravo") self.assert_guide_accesssible("Charlie") self.assert_guide_not_accesssible("Delta", is_guides_accessible=True) actions.login("*****@*****.**", is_admin=True) for name in ["Alpha", "Bravo", "Charlie", "Delta"]: self.assert_guide_accesssible(name) # check course labels as admin sees them response = self.get("/modules/guides") self.assertEquals(200, response.status_int) self.assertIn('category="Power Searching with Google [Alpha]', response.body) self.assertIn('category="Power Searching with Google [Bravo]', response.body) self.assertIn('category="Power Searching with Google [Charlie] ' "(Registration required)", response.body) self.assertIn('category="Power Searching with Google [Delta] (Private)', response.body)
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) actions.assert_does_not_contain('Assignment to review', response.body) actions.assert_contains( 'Sorry, there are no new submissions ', response.body) actions.assert_contains('disabled="true"', response.body) actions.logout()
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) actions.assert_equals(response.status_int, 200) actions.assert_contains('Due date for this assignment', response.body) actions.assert_contains( 'After you have completed the required number of peer reviews', response.body) actions.logout()
def setUp(self): super(StudentTracksTest, self).setUp() # Add a course that will show up. actions.simple_add_course(COURSE_NAME, ADMIN_EMAIL, COURSE_TITLE) # Add labels with common_utils.Namespace(NAMESPACE): self.foo_id = models.LabelDAO.save(models.LabelDTO( None, {'title': 'Foo', 'descripton': 'foo', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK})) self.bar_id = models.LabelDAO.save(models.LabelDTO( None, {'title': 'Bar', 'descripton': 'bar', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK})) self.baz_id = models.LabelDAO.save(models.LabelDTO( None, {'title': 'Baz', 'descripton': 'baz', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK})) self.quux_id = models.LabelDAO.save(models.LabelDTO( None, {'title': 'Quux', 'descripton': 'quux', 'type': models.LabelDTO.LABEL_TYPE_GENERAL})) # Register a student for that course. actions.login(REGISTERED_STUDENT_EMAIL) actions.register(self, REGISTERED_STUDENT_NAME, COURSE_NAME) actions.logout() # Add some units to the course. self._course = courses.Course( None, app_context=sites.get_all_courses()[0]) self._unit_no_labels = self._course.add_unit() self._unit_no_labels.title = 'Unit No Labels' self._unit_no_labels.availability = courses.AVAILABILITY_AVAILABLE self._course.add_lesson(self._unit_no_labels) self._unit_labels_foo = self._course.add_unit() self._unit_labels_foo.title = 'Unit Labels: Foo' self._unit_labels_foo.availability = courses.AVAILABILITY_AVAILABLE self._unit_labels_foo.labels = str(self.foo_id) self._course.add_lesson(self._unit_labels_foo) self._unit_labels_foo_bar = self._course.add_unit() self._unit_labels_foo_bar.title = 'Unit Labels: Bar, Foo' self._unit_labels_foo_bar.availability = courses.AVAILABILITY_AVAILABLE self._unit_labels_foo_bar.labels = '%s %s' % (self.bar_id, self.foo_id) self._course.add_lesson(self._unit_labels_foo_bar) self._unit_labels_quux = self._course.add_unit() self._unit_labels_quux.title = 'Unit Labels: Quux' self._unit_labels_quux.availability = courses.AVAILABILITY_AVAILABLE self._unit_labels_quux.labels = str(self.quux_id) self._course.add_lesson(self._unit_labels_quux) self._unit_labels_foo_quux = self._course.add_unit() self._unit_labels_foo_quux.title = 'Unit Labels: Foo Quux' self._unit_labels_foo_quux.availability = courses.AVAILABILITY_AVAILABLE self._unit_labels_foo_quux.labels = '%s %s' % (str(self.foo_id), str(self.quux_id)) self._course.add_lesson(self._unit_labels_foo_quux) self._course.save()
def test_availability_course(self): course = self._init_course('test') env = self.enabled(availability=courses.AVAILABILITY_COURSE) for availability in [ courses.COURSE_AVAILABILITY_PUBLIC, courses.COURSE_AVAILABILITY_REGISTRATION_OPTIONAL]: course.set_course_availability(availability) with actions.OverriddenEnvironment(env): actions.logout() self.assertPage('/test/foo/index.html', 'Web Server') self.assertPage('/test/foo/markdown.md', 'Web Server') self.assertPage('/test/foo/main.css', 'Web Server') actions.login('*****@*****.**') self.assertPage('/test/foo/index.html', 'Web Server') self.assertPage('/test/foo/markdown.md', 'Web Server') self.assertPage('/test/foo/main.css', 'Web Server') if availability == ( courses.COURSE_AVAILABILITY_REGISTRATION_OPTIONAL): self.register() self.assertPage('/test/foo/index.html', ' Web Server') self.assertPage('/test/foo/markdown.md', ' Web Server') self.assertPage('/test/foo/main.css', ' Web Server') self.unregister() actions.login('*****@*****.**', is_admin=True) self.assertPage('/test/foo/index.html', ' Web Server') self.assertPage('/test/foo/markdown.md', ' Web Server') self.assertPage('/test/foo/main.css', ' Web Server') for availability in [ courses.COURSE_AVAILABILITY_REGISTRATION_REQUIRED, courses.COURSE_AVAILABILITY_PRIVATE]: course.set_course_availability(availability) with actions.OverriddenEnvironment(env): actions.logout() self.assertNoPage('/test/foo/index.html') self.assertNoPage('/test/foo/markdown.md') self.assertNoPage('/test/foo/main.css') actions.login('*****@*****.**') self.assertNoPage('/test/foo/index.html') self.assertNoPage('/test/foo/markdown.md') self.assertNoPage('/test/foo/main.css') if availability == ( courses.COURSE_AVAILABILITY_REGISTRATION_REQUIRED): self.register() self.assertPage('/test/foo/index.html', ' Web Server') self.assertPage('/test/foo/markdown.md', ' Web Server') self.assertPage('/test/foo/main.css', ' Web Server') self.unregister() actions.login('*****@*****.**', is_admin=True) self.assertPage('/test/foo/index.html', ' Web Server') self.assertPage('/test/foo/markdown.md', ' Web Server') self.assertPage('/test/foo/main.css', ' Web Server')
def test_unsubscribe_request_with_no_email_prompts_for_login(self): actions.logout() response = self.get('modules/unsubscribe') self.assertEquals(302, response.status_int) self.assertEquals( 'https://www.google.com/accounts/Login' '?continue=http%3A//localhost/a/modules/unsubscribe', response.headers['Location'])
def test_handler_rejects_non_super_user(self): actions.logout() xsrf_token = crypto.XsrfTokenManager.create_xsrf_token(self.XSRF_TOKEN) response = self.do_post(xsrf_token, False) self.assertEqual(200, response.status_int) response_dict = transforms.loads(response.body) self.assertEqual(401, response_dict['status']) self.assertIn('Access denied.', response_dict['message'])
def test_banner_without_buttons_shown_to_instructor_on_dashboard(self): actions.logout() actions.login(self.NOT_SUPER_EMAIL, is_admin=False) dom = self.parse_html_string(self.get('dashboard').body) banner = dom.find('.//div[@class="consent-banner"]') self.assertIsNotNone(banner) self.assertIn(self.NOT_SUPER_MESSAGE, banner.findall('.//p')[1].text) self.assertEqual(0, len(banner.findall('.//button')))
def test_not_registered(self): actions.logout() actions.login(UNREGISTERED_STUDENT_EMAIL) xsrf_token = crypto.XsrfTokenManager.create_xsrf_token( manual_progress.XSRF_ACTION) response = self.get(UNIT_PROGRESS_URL + '?key=%s' % self._unit_one.unit_id + '&xsrf_token=%s' % xsrf_token) self._expect_response(response, 401, 'Access Denied.')
def test_cancel_import_not_admin(self): actions.logout() response = self.post(self.dashboard_url, { 'action': unit_lesson_editor.UnitLessonEditor.ACTION_POST_CANCEL_IMPORT, 'xsrf_token': crypto.XsrfTokenManager.create_xsrf_token( unit_lesson_editor.UnitLessonEditor.ACTION_POST_CANCEL_IMPORT), }) self.assertEquals(302, response.status_int)
def setUp(self): super(StudentTracksTest, self).setUp() # Add a course that will show up. actions.simple_add_course(COURSE_NAME, ADMIN_EMAIL, COURSE_TITLE) # Add labels with common_utils.Namespace(NAMESPACE): self.foo_id = models.LabelDAO.save( models.LabelDTO( None, {"title": "Foo", "descripton": "foo", "type": models.LabelDTO.LABEL_TYPE_COURSE_TRACK} ) ) self.bar_id = models.LabelDAO.save( models.LabelDTO( None, {"title": "Bar", "descripton": "bar", "type": models.LabelDTO.LABEL_TYPE_COURSE_TRACK} ) ) self.baz_id = models.LabelDAO.save( models.LabelDTO( None, {"title": "Baz", "descripton": "baz", "type": models.LabelDTO.LABEL_TYPE_COURSE_TRACK} ) ) self.quux_id = models.LabelDAO.save( models.LabelDTO( None, {"title": "Quux", "descripton": "quux", "type": models.LabelDTO.LABEL_TYPE_GENERAL} ) ) # Register a student for that course. actions.login(REGISTERED_STUDENT_EMAIL) actions.register(self, REGISTERED_STUDENT_NAME, COURSE_NAME) actions.logout() # Add some units to the course. self._course = courses.Course(None, app_context=sites.get_all_courses()[0]) self._unit_no_labels = self._course.add_unit() self._unit_no_labels.title = "Unit No Labels" self._unit_no_labels.now_available = True self._unit_labels_foo = self._course.add_unit() self._unit_labels_foo.title = "Unit Labels: Foo" self._unit_labels_foo.now_available = True self._unit_labels_foo.labels = str(self.foo_id) self._unit_labels_foo_bar = self._course.add_unit() self._unit_labels_foo_bar.title = "Unit Labels: Bar, Foo" self._unit_labels_foo_bar.now_available = True self._unit_labels_foo_bar.labels = "%s %s" % (self.bar_id, self.foo_id) self._unit_labels_quux = self._course.add_unit() self._unit_labels_quux.title = "Unit Labels: Quux" self._unit_labels_quux.now_available = True self._unit_labels_quux.labels = str(self.quux_id) self._unit_labels_foo_quux = self._course.add_unit() self._unit_labels_foo_quux.title = "Unit Labels: Foo Quux" self._unit_labels_foo_quux.now_available = True self._unit_labels_foo_quux.labels = "%s %s" % (str(self.foo_id), str(self.quux_id)) self._course.save()
def test_unsubscribe_request_with_no_email_prompts_for_login(self): actions.logout() course = courses.Course(None, app_context=sites.get_all_courses()[0]) course.set_course_availability(courses.COURSE_AVAILABILITY_PUBLIC) response = self.get('modules/unsubscribe') self.assertEquals(302, response.status_int) self.assertEquals( 'https://www.google.com/accounts/Login' '?continue=http%3A//localhost/a/modules/unsubscribe', response.headers['Location'])
def test_access_assessment(self): assessment = self.course.add_assessment() assessment.is_draft = True self.course.save() self.assertEquals( self.get('assessment?name=%s' % assessment.unit_id).status_int, 302) actions.login(self.USER_EMAIL, is_admin=False) self.assertEquals( self.get('assessment?name=%s' % assessment.unit_id).status_int, 200) actions.logout()
def test_course_picker(self): actions.login(self.USER_EMAIL, is_admin=False) picker_options = self._get_all_picker_options() self.assertEquals(len(list(picker_options)), 1) actions.logout() actions.login(self.ADMIN_EMAIL, is_admin=True) picker_options = self._get_all_picker_options() # Expect 3 courses, as the default one is also considered for the picker self.assertEquals(len(picker_options), 3) actions.logout()
def test_edit_lesson_buttons_for_each_lesson(self): actions.logout() actions.login(ADMIN_EMAIL) dom = self.parse_html_string( self.get(UNIT_URL_PREFIX + str(self.unit.unit_id)).body) # The Edit Lesson buttons all have a data-lesson-id attribute set buttons = dom.findall('.//*[@data-lesson-id]') self.assertEquals(2, len(buttons)) self.assertEquals( str(self.lesson_one.lesson_id), buttons[0].get('data-lesson-id')) self.assertEquals( str(self.lesson_two.lesson_id), buttons[1].get('data-lesson-id'))
def setUp(self): super(TextFileUploadHandlerTestCase, self).setUp() self.contents = "contents" self.email = "*****@*****.**" self.headers = {"referer": "http://localhost/path?query=value#fragment"} self.unit_id = "1" actions.login(self.email) user = users.get_current_user() actions.logout() self.user_id = user.user_id() self.student = models.Student(is_enrolled=True, key_name=self.email, user_id=self.user_id) self.student.put() # Allow protected access for tests. pylint: disable=protected-access self.xsrf_token = utils.XsrfTokenManager.create_xsrf_token(upload._XSRF_TOKEN_NAME)
def test_access_lesson(self): unit = self.course.add_unit() unit.is_draft = True lesson = self.course.add_lesson(unit) lesson.is_draft = True self.course.save() self.assertEquals( self.get('unit?unit=%s&lesson=%s' % ( unit.unit_id, lesson.lesson_id)).status_int, 302) actions.login(self.USER_EMAIL, is_admin=False) self.assertEquals( self.get('unit?unit=%s&lesson=%s' % ( unit.unit_id, lesson.lesson_id)).status_int, 200) actions.logout()
def test_guide_disabled(self): with actions.OverriddenEnvironment(self.GUIDE_DISABLED): for name in ["Alpha", "Bravo", "Charlie", "Delta"]: actions.logout() self.assert_guide_not_accesssible(name) actions.login("*****@*****.**") self.assert_guide_not_accesssible(name) if name == "Bravo" or name == "Charlie": self.register(name) self.assert_guide_not_accesssible(name) actions.login("*****@*****.**", is_admin=True) self.assert_guide_not_accesssible(name)
def setUp(self): super(TextFileUploadHandlerTestCase, self).setUp() self.contents = 'contents' self.email = '*****@*****.**' self.headers = {'referer': 'http://localhost/path?query=value#fragment'} self.unit_id = '1' actions.login(self.email) user = users.get_current_user() actions.logout() self.user_id = user.user_id() self.student = models.Student( is_enrolled=True, key_name=self.email, user_id=self.user_id) self.student.put() self.xsrf_token = utils.XsrfTokenManager.create_xsrf_token( upload._XSRF_TOKEN_NAME)
def test_dashboard_access_method(self): with utils.Namespace(self.course_with_access.app_context.namespace): self.assertFalse(dashboard.DashboardHandler.current_user_has_access( self.course_with_access.app_context)) with utils.Namespace(self.course_without_access.app_context.namespace): self.assertFalse(dashboard.DashboardHandler.current_user_has_access( self.course_without_access.app_context)) actions.login(self.USER_EMAIL, is_admin=False) with utils.Namespace(self.course_with_access.app_context.namespace): self.assertTrue(dashboard.DashboardHandler.current_user_has_access( self.course_with_access.app_context)) with utils.Namespace(self.course_without_access.app_context.namespace): self.assertFalse(dashboard.DashboardHandler.current_user_has_access( self.course_without_access.app_context)) actions.logout()
def test_content_permissions(self): # as admin, you can access this response = self.get('modules/drive/item/content?key=6') self.assertEqual(response.status_code, 200) # as nobody, you can't actions.logout() response = self.get( 'modules/drive/item/content?key=6', expect_errors=True) self.assertEqual(response.status_code, 404) # unless it's public self.set_availability_for_file('6', 'public') response = self.get( 'modules/drive/item/content?key=6', expect_errors=True) self.assertEqual(response.status_code, 404)
def test_banner_not_shown_when_choices_have_been_made(self): config.set_report_allowed(False) # Check super-user role; global admin dom = self.parse_html_string(self.get('/admin/global').body) self.assertIsNone(dom.find('.//div[@class="consent-banner"]')) # check super-user role; dashboard dom = self.parse_html_string(self.get('dashboard').body) self.assertIsNone(dom.find('.//div[@class="consent-banner"]')) # Check non-super role; dashboadd actions.logout() actions.login(self.NOT_SUPER_EMAIL, is_admin=False) dom = self.parse_html_string(self.get('dashboard').body) self.assertIsNone(dom.find('.//div[@class="consent-banner"]'))
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) actions.assert_does_not_contain('Assignment to review', response.body) actions.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) actions.assert_equals(response.status_int, 302) response = self.get(response.location) actions.assert_does_not_contain( 'Error 412: The reviewer is already assigned', response.body) actions.assert_contains('First answer to Q1', response.body) actions.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) actions.assert_equals(response.status_int, 302) response = self.get(response.location) actions.assert_contains( 'Error 412: The reviewer is already assigned', response.body)
def test_data_extraction(self): # Register a student and save some form values for that student student = self.register() entity = StudentFormEntity.load_or_default(student, 'form-0') entity.value = transforms.dumps({ u'form_data': self.FORM_0_DATA}) entity.put() entity = StudentFormEntity.load_or_default(student, u'form-1') entity.value = transforms.dumps({ u'form_data': self.FORM_1_DATA}) entity.put() entity = StudentFormEntity.load_or_default(student, u'form-2') entity.value = transforms.dumps({ u'form_data': self.FORM_2_DATA}) entity.put() # Log in as admin for the data query actions.logout() actions.login(ADMIN_EMAIL, is_admin=True) xsrf_token = crypto.XsrfTokenManager.create_xsrf_token( data_sources_utils.DATA_SOURCE_ACCESS_XSRF_ACTION) pii_secret = crypto.generate_transform_secret_from_xsrf_token( xsrf_token, data_sources_utils.DATA_SOURCE_ACCESS_XSRF_ACTION) safe_user_id = crypto.hmac_sha_2_256_transform( pii_secret, student.user_id) response = self.get( 'rest/data/questionnaire_responses/items?' 'data_source_token=%s&page_number=0' % xsrf_token) data = transforms.loads(response.body)['data'] self.assertEqual(3, len(data)) for index in range(3): self.assertIn(safe_user_id, data[index]['user_id']) self.assertEqual('form-%s' % index, data[index]['questionnaire_id']) self.assertEqual(self.FORM_0_DATA, data[0]['form_data']) self.assertEqual(self.FORM_1_DATA, data[1]['form_data']) self.assertEqual(self.FORM_2_DATA_OUT, data[2]['form_data'])
def test_unit_access_unavailable(self): actions.logout() self.unit.availability = courses.AVAILABILITY_UNAVAILABLE self.course.save() # Access single unit response = self.get_response( '{course(id: "%s") {unit(id: "%s") {title} }}' % (self.course_id, self.unit_id)) self.assertIsNone(response['data']['course']['unit']) # Access unit list response = self.get_response( '{course(id: "%s") {allUnits {edges {node {id}}}}}' % (self.course_id)) self.assertEquals([], response['data']['course']['allUnits']['edges'])
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) actions.assert_does_not_contain('Assignment to review', response.body) actions.assert_contains('Sorry, there are no new submissions ', response.body) actions.assert_contains('disabled="true"', response.body) actions.logout()
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) actions.assert_equals(response.status_int, 200) actions.assert_contains('Due date for this assignment', response.body) actions.assert_contains( 'After you have completed the required number of peer reviews', response.body) actions.logout()
def setUp(self): super(TextFileUploadHandlerTestCase, self).setUp() self.contents = 'contents' self.email = '*****@*****.**' self.headers = { 'referer': 'http://localhost/path?query=value#fragment' } self.unit_id = '1' actions.login(self.email) user = users.get_current_user() actions.logout() self.user_id = user.user_id() self.student = models.Student(is_enrolled=True, key_name=self.email, user_id=self.user_id) self.student.put() self.xsrf_token = utils.XsrfTokenManager.create_xsrf_token( upload._XSRF_TOKEN_NAME)
def test_data_extraction(self): # Register a student and save some form values for that student student = self.register() entity = StudentFormEntity.load_or_create(student, 'form-0') entity.value = transforms.dumps({u'form_data': self.FORM_0_DATA}) entity.put() entity = StudentFormEntity.load_or_create(student, u'form-1') entity.value = transforms.dumps({u'form_data': self.FORM_1_DATA}) entity.put() entity = StudentFormEntity.load_or_create(student, u'form-2') entity.value = transforms.dumps({u'form_data': self.FORM_2_DATA}) entity.put() # Log in as admin for the data query actions.logout() actions.login(ADMIN_EMAIL, is_admin=True) xsrf_token = crypto.XsrfTokenManager.create_xsrf_token( data_sources_utils.DATA_SOURCE_ACCESS_XSRF_ACTION) pii_secret = crypto.generate_transform_secret_from_xsrf_token( xsrf_token, data_sources_utils.DATA_SOURCE_ACCESS_XSRF_ACTION) safe_user_id = crypto.hmac_sha_2_256_transform(pii_secret, student.user_id) response = self.get('rest/data/questionnaire_responses/items?' 'data_source_token=%s&page_number=0' % xsrf_token) data = transforms.loads(response.body)['data'] self.assertEqual(3, len(data)) for index in range(3): self.assertIn(safe_user_id, data[index]['user_id']) self.assertEqual('form-%s' % index, data[index]['questionnaire_id']) self.assertEqual(self.FORM_0_DATA, data[0]['form_data']) self.assertEqual(self.FORM_1_DATA, data[1]['form_data']) self.assertEqual(self.FORM_2_DATA_OUT, data[2]['form_data'])
def setUp(self): super(DashboardAccessTestCase, self).setUp() actions.login(self.ADMIN_EMAIL, is_admin=True) context = actions.simple_add_course( self.ACCESS_COURSE_NAME, self.ADMIN_EMAIL, 'Course with access') self.course_with_access = courses.Course(None, context) with utils.Namespace(self.course_with_access.app_context.namespace): role_dto = models.RoleDTO(None, { 'name': self.ROLE, 'users': [self.USER_EMAIL], 'permissions': {dashboard.custom_module.name: [self.PERMISSION]} }) models.RoleDAO.save(role_dto) context = actions.simple_add_course( self.NO_ACCESS_COURSE_NAME, self.ADMIN_EMAIL, 'Course with no access' ) self.course_without_access = courses.Course(None, context) def test_content(self): return self.render_page( {'main_content': 'test', 'page_title': 'test'}) # save properties self.old_menu_group = dashboard.DashboardHandler.root_menu_group # pylint: disable=W0212 self.old_get_acitons = dashboard.DashboardHandler._custom_get_actions # pylint: enable=W0212 # put a dummy method in menu_group = menus.MenuGroup('test', 'Test Dashboard') dashboard.DashboardHandler.root_menu_group = menu_group dashboard.DashboardHandler.default_action = self.ACTION dashboard.DashboardHandler.add_nav_mapping(self.ACTION, self.ACTION) dashboard.DashboardHandler.add_sub_nav_mapping(self.ACTION, self.ACTION, self.ACTION, action=self.ACTION, contents=test_content) dashboard.DashboardHandler.map_get_action_to_permission( self.ACTION, dashboard.custom_module, self.PERMISSION) actions.logout()
def test_dashboard_access_method(self): with utils.Namespace(self.course_with_access.app_context.namespace): self.assertFalse( dashboard.DashboardHandler.current_user_has_access( self.course_with_access.app_context)) with utils.Namespace(self.course_without_access.app_context.namespace): self.assertFalse( dashboard.DashboardHandler.current_user_has_access( self.course_without_access.app_context)) actions.login(self.USER_EMAIL, is_admin=False) with utils.Namespace(self.course_with_access.app_context.namespace): self.assertTrue( dashboard.DashboardHandler.current_user_has_access( self.course_with_access.app_context)) with utils.Namespace(self.course_without_access.app_context.namespace): self.assertFalse( dashboard.DashboardHandler.current_user_has_access( self.course_without_access.app_context)) actions.logout()
def test_data_source(self): # Register a student and give some feedback user = self.register_student() student = models.Student.get_enrolled_student_by_user(user) response = self.post_data( rating_int=2, additional_comments='Good lesson') self.assertEquals(200, response['status']) self.assertIn('Thank you for your feedback', response['message']) # Log in as admin for the data query actions.logout() actions.login(ADMIN_EMAIL, is_admin=True) xsrf_token = crypto.XsrfTokenManager.create_xsrf_token( data_sources_utils.DATA_SOURCE_ACCESS_XSRF_ACTION) pii_secret = crypto.generate_transform_secret_from_xsrf_token( xsrf_token, data_sources_utils.DATA_SOURCE_ACCESS_XSRF_ACTION) safe_user_id = crypto.hmac_sha_2_256_transform( pii_secret, student.user_id) response = self.get( 'rest/data/rating_events/items?' 'data_source_token=%s&page_number=0' % xsrf_token) data = transforms.loads(response.body)['data'] self.assertEqual(1, len(data)) record = data[0] self.assertEqual(7, len(record)) self.assertEqual(safe_user_id, record['user_id']) self.assertEqual('2', record['rating']) self.assertEqual('Good lesson', record['additional_comments']) self.assertEqual( '/rating_course/unit?unit=%s&lesson=%s' % ( self.unit.unit_id, self.lesson.lesson_id), record['content_url']) self.assertEqual(str(self.unit.unit_id), record['unit_id']) self.assertEqual(str(self.lesson.lesson_id), record['lesson_id']) self.assertIn('recorded_on', record)
def test_guide_enabled_course(self): with actions.OverriddenEnvironment(self.GUIDE_ENABLED_COURSE): actions.logout() self.assert_guide_accesssible('Alpha') self.assert_guide_accesssible('Bravo') self.assert_guide_not_accesssible('Charlie', is_guides_accessible=True) self.assert_guide_not_accesssible('Delta', is_guides_accessible=True) actions.login('*****@*****.**') self.assert_guide_accesssible('Alpha') self.assert_guide_accesssible('Bravo') self.assert_guide_not_accesssible('Charlie', is_guides_accessible=True) self.assert_guide_not_accesssible('Delta', is_guides_accessible=True) self.register('Charlie') self.assert_guide_accesssible('Alpha') self.assert_guide_accesssible('Bravo') self.assert_guide_accesssible('Charlie') self.assert_guide_not_accesssible('Delta', is_guides_accessible=True) actions.login('*****@*****.**', is_admin=True) for name in ['Alpha', 'Bravo', 'Charlie', 'Delta']: self.assert_guide_accesssible(name) # check course labels as admin sees them response = self.get('/modules/guides') self.assertEquals(200, response.status_int) self.assertIn('category="Power Searching with Google [Alpha]', response.body) self.assertIn('category="Power Searching with Google [Bravo]', response.body) self.assertIn( 'category="Power Searching with Google [Charlie] ' '(Registration required)', response.body) self.assertIn( 'category="Power Searching with Google [Delta] (Private)', response.body)
def test_unit_access_available(self): actions.logout() self.unit.availability = courses.AVAILABILITY_AVAILABLE self.course.save() # Access single unit response = self.get_response( '{course (id: "%s") {unit(id: "%s") { title } }}' % (self.course_id, self.unit_id)) self.assertEquals(self.unit.title, response['data']['course']['unit']['title']) # Access unit list response = self.get_response( '{course(id: "%s") {allUnits {edges {node {' ' ... on Unit {id title}}}}}}' % self.course_id) edges = response['data']['course']['allUnits']['edges'] self.assertEquals(1, len(edges)) self.assertEquals(self.unit.title, edges[0]['node']['title'])
def setUp(self): super(WhitelistTest, self).setUp() config.Registry.test_overrides[ course_explorer.GCB_ENABLE_COURSE_EXPLORER_PAGE.name] = True actions.login(ADMIN_EMAIL, is_admin=True) payload_dict = { 'name': COURSE_NAME, 'title': 'Whitelist Test', 'admin_email': ADMIN_EMAIL} request = { 'payload': transforms.dumps(payload_dict), 'xsrf_token': crypto.XsrfTokenManager.create_xsrf_token( 'add-course-put')} response = self.testapp.put('/rest/courses/item?%s' % urllib.urlencode( {'request': transforms.dumps(request)}), {}) self.assertEquals(response.status_int, 200) sites.setup_courses('course:/%s::ns_%s, course:/:/' % ( COURSE_NAME, COURSE_NAME)) 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_lesson_access_unavailable(self): actions.logout() self.unit.availability = courses.AVAILABILITY_AVAILABLE self.lesson.availability = courses.AVAILABILITY_UNAVAILABLE self.lesson.shown_when_unavailable = False self.course.save() # Access single lesson response = self.get_response( '{course(id: "%s") {unit(id: "%s") {' 'lesson(id: "%s") {title body}}}}' % (self.course_id, self.unit_id, self.lesson_id)) self.assertIsNone(response['data']['course']['unit']['lesson']) # Access lesson list response = self.get_response( '{course(id: "%s") {unit(id: "%s") {allLessons {edges {node {' ' ... on Lesson{title body}}}}}}}' % (self.course_id, self.unit_id)) self.assertEquals( [], response['data']['course']['unit']['allLessons']['edges'])
def setUp(self): super(StudentLabelsTest, self).setUp() actions.simple_add_course(COURSE_NAME, ADMIN_EMAIL, COURSE_TITLE) with common_utils.Namespace(NAMESPACE): self.foo_id = models.LabelDAO.save( models.LabelDTO( None, { 'title': 'Foo', 'descripton': 'foo', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK })) self.bar_id = models.LabelDAO.save( models.LabelDTO( None, { 'title': 'Bar', 'descripton': 'bar', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK })) self.baz_id = models.LabelDAO.save( models.LabelDTO( None, { 'title': 'Baz', 'descripton': 'baz', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK })) self.quux_id = models.LabelDAO.save( models.LabelDTO( None, { 'title': 'Quux', 'descripton': 'quux', 'type': models.LabelDTO.LABEL_TYPE_GENERAL })) actions.login(REGISTERED_STUDENT_EMAIL) actions.register(self, REGISTERED_STUDENT_NAME, COURSE_NAME) actions.logout()
def setUp(self): super(BaseQuestionnaireTests, self).setUp() actions.login(ADMIN_EMAIL, is_admin=True) self.base = '/' + COURSE_NAME test_course = actions.simple_add_course(COURSE_NAME, ADMIN_EMAIL, 'Questionnaire Test Course') self.old_namespace = namespace_manager.get_namespace() namespace_manager.set_namespace('ns_%s' % COURSE_NAME) self.course = courses.Course(None, test_course) test_unit = self.course.add_unit() test_unit.now_available = True test_lesson = self.course.add_lesson(test_unit) test_lesson.now_available = True test_lesson.title = 'This is a lesson that contains a form.' test_lesson.objectives = '%s\n%s' % (TEST_FORM_HTML, QUESTIONNAIRE_TAG) self.unit_id = test_unit.unit_id self.lesson_id = test_lesson.lesson_id self.course.save() actions.logout()
def test_lesson_access_available(self): actions.logout() self.unit.availability = courses.AVAILABILITY_AVAILABLE self.lesson.availability = courses.AVAILABILITY_AVAILABLE self.course.save() expected_lesson = {'title': self.lesson.title, 'body': 'Lesson body'} # Access single lesson response = self.get_response( '{course(id: "%s") {unit(id: "%s") {' 'lesson(id: "%s") {title body}}}}' % (self.course_id, self.unit_id, self.lesson_id)) _lesson = response['data']['course']['unit']['lesson'] self.assertEquals(expected_lesson, _lesson) # Access lesson list response = self.get_response( '{course(id: "%s") {unit(id: "%s") {allLessons {edges {node {' ' ... on Lesson{title body}}}}}}}' % (self.course_id, self.unit_id)) edges = response['data']['course']['unit']['allLessons']['edges'] self.assertEquals(1, len(edges)) self.assertEquals(expected_lesson, edges[0]['node'])
def test_submit_assignment(self): """Test submission of peer-reviewed assignments.""" # 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['course']['browsable'] = False return environ sites.ApplicationContext.get_environ = get_environ_new email = '*****@*****.**' name = 'Test Peer Reviewed Assignment Submission' 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 }, ]) second_submission = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'Second answer to Q1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'Second answer to Q3', 'correct': True }, ]) actions.login(email) actions.register(self, name) # Check that the sample peer-review assignment shows up in the course # page and that it can be visited. response = actions.view_course(self) actions.assert_contains('Sample peer review assignment', response.body) actions.assert_contains('Review peer assignments', response.body) actions.assert_contains( '<a href="assessment?name=%s">' % LEGACY_REVIEW_UNIT_ID, response.body) actions.assert_contains('Review peer assignments </p>', response.body, collapse_whitespace=True) actions.assert_does_not_contain('<a href="reviewdashboard', response.body, collapse_whitespace=True) # Check that the progress circle for this assignment is unfilled. actions.assert_contains( 'progress-notstarted-%s' % LEGACY_REVIEW_UNIT_ID, response.body) actions.assert_does_not_contain( 'progress-completed-%s' % LEGACY_REVIEW_UNIT_ID, response.body) # Try to access an invalid assignment. response = self.get('assessment?name=FakeAssessment', expect_errors=True) actions.assert_equals(response.status_int, 404) # The student should not be able to see others' reviews because he/she # has not submitted an assignment yet. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) actions.assert_does_not_contain('Submitted assignment', response.body) actions.assert_contains('Due date for this assignment', response.body) actions.assert_does_not_contain('Reviews received', response.body) # The student should not be able to access the review dashboard because # he/she has not submitted the assignment yet. response = self.get('reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID, expect_errors=True) actions.assert_contains('You must submit the assignment for', response.body) # The student submits the assignment. response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, { 'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID }) actions.assert_contains('Thank you for completing this assignment', response.body) actions.assert_contains('Review peer assignments', response.body) # The student views the submitted assignment, which has become readonly. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) actions.assert_contains('First answer to Q1', response.body) actions.assert_contains('Submitted assignment', response.body) # The student tries to re-submit the same assignment. This should fail. response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, { 'answers': second_submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID }, presubmit_checks=False) actions.assert_contains('You have already submitted this assignment.', response.body) actions.assert_contains('Review peer assignments', response.body) # The student views the submitted assignment. The new answers have not # been saved. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) actions.assert_contains('First answer to Q1', response.body) actions.assert_does_not_contain('Second answer to Q1', response.body) # The student checks the course page and sees that the progress # circle for this assignment has been filled, and that the 'Review # peer assignments' link is now available. response = actions.view_course(self) actions.assert_contains( 'progress-completed-%s' % LEGACY_REVIEW_UNIT_ID, response.body) actions.assert_does_not_contain( '<span> Review peer assignments </span>', response.body, collapse_whitespace=True) actions.assert_contains('<a href="reviewdashboard?unit=%s">' % LEGACY_REVIEW_UNIT_ID, response.body, collapse_whitespace=True) # The student should also be able to now view the review dashboard. response = self.get('reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) actions.assert_contains('Assignments for your review', response.body) actions.assert_contains('Review a new assignment', response.body) actions.logout() # Clean up app_context. sites.ApplicationContext.get_environ = get_environ_old
def setUp(self): super(StudentTracksTest, self).setUp() # Add a course that will show up. actions.simple_add_course(COURSE_NAME, ADMIN_EMAIL, COURSE_TITLE) # Add labels with common_utils.Namespace(NAMESPACE): self.foo_id = models.LabelDAO.save( models.LabelDTO( None, { 'title': 'Foo', 'descripton': 'foo', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK })) self.bar_id = models.LabelDAO.save( models.LabelDTO( None, { 'title': 'Bar', 'descripton': 'bar', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK })) self.baz_id = models.LabelDAO.save( models.LabelDTO( None, { 'title': 'Baz', 'descripton': 'baz', 'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK })) self.quux_id = models.LabelDAO.save( models.LabelDTO( None, { 'title': 'Quux', 'descripton': 'quux', 'type': models.LabelDTO.LABEL_TYPE_GENERAL })) # Register a student for that course. actions.login(REGISTERED_STUDENT_EMAIL) actions.register(self, REGISTERED_STUDENT_NAME, COURSE_NAME) actions.logout() # Add some units to the course. self._course = courses.Course(None, app_context=sites.get_all_courses()[0]) self._unit_no_labels = self._course.add_unit() self._unit_no_labels.title = 'Unit No Labels' self._unit_no_labels.availability = courses.AVAILABILITY_AVAILABLE self._course.add_lesson(self._unit_no_labels) self._unit_labels_foo = self._course.add_unit() self._unit_labels_foo.title = 'Unit Labels: Foo' self._unit_labels_foo.availability = courses.AVAILABILITY_AVAILABLE self._unit_labels_foo.labels = str(self.foo_id) self._course.add_lesson(self._unit_labels_foo) self._unit_labels_foo_bar = self._course.add_unit() self._unit_labels_foo_bar.title = 'Unit Labels: Bar, Foo' self._unit_labels_foo_bar.availability = courses.AVAILABILITY_AVAILABLE self._unit_labels_foo_bar.labels = '%s %s' % (self.bar_id, self.foo_id) self._course.add_lesson(self._unit_labels_foo_bar) self._unit_labels_quux = self._course.add_unit() self._unit_labels_quux.title = 'Unit Labels: Quux' self._unit_labels_quux.availability = courses.AVAILABILITY_AVAILABLE self._unit_labels_quux.labels = str(self.quux_id) self._course.add_lesson(self._unit_labels_quux) self._unit_labels_foo_quux = self._course.add_unit() self._unit_labels_foo_quux.title = 'Unit Labels: Foo Quux' self._unit_labels_foo_quux.availability = courses.AVAILABILITY_AVAILABLE self._unit_labels_foo_quux.labels = '%s %s' % (str( self.foo_id), str(self.quux_id)) self._course.add_lesson(self._unit_labels_foo_quux) self._course.save()
def test_logged_out_does_not_use_prefs(self): actions.logout() response = self.get(BASE_URL) response = response.click('Unit 1 - The Unit') response = self.get(BASE_URL) self.assertEquals(200, response.status_int)
def test_extra_tabs_on_navbar_visible_to_everyone(self): actions.logout() body = self.get('course').body self.assertIn('FAQ', body) self.assertNotIn('Resources', body)
def test_availability_course(self): course = self._init_course('test') env = self.enabled(availability=courses.AVAILABILITY_COURSE) for availability in [ courses.COURSE_AVAILABILITY_PUBLIC, courses.COURSE_AVAILABILITY_REGISTRATION_OPTIONAL ]: course.set_course_availability(availability) with actions.OverriddenEnvironment(env): actions.logout() self.assertPage('/test/foo/index.html', 'Web Server') self.assertPage('/test/foo/markdown.md', 'Web Server') self.assertPage('/test/foo/main.css', 'Web Server') actions.login('*****@*****.**') self.assertPage('/test/foo/index.html', 'Web Server') self.assertPage('/test/foo/markdown.md', 'Web Server') self.assertPage('/test/foo/main.css', 'Web Server') if availability == ( courses.COURSE_AVAILABILITY_REGISTRATION_OPTIONAL): self.register() self.assertPage('/test/foo/index.html', ' Web Server') self.assertPage('/test/foo/markdown.md', ' Web Server') self.assertPage('/test/foo/main.css', ' Web Server') self.unregister() actions.login('*****@*****.**', is_admin=True) self.assertPage('/test/foo/index.html', ' Web Server') self.assertPage('/test/foo/markdown.md', ' Web Server') self.assertPage('/test/foo/main.css', ' Web Server') for availability in [ courses.COURSE_AVAILABILITY_REGISTRATION_REQUIRED, courses.COURSE_AVAILABILITY_PRIVATE ]: course.set_course_availability(availability) with actions.OverriddenEnvironment(env): actions.logout() self.assertNoPage('/test/foo/index.html') self.assertNoPage('/test/foo/markdown.md') self.assertNoPage('/test/foo/main.css') actions.login('*****@*****.**') self.assertNoPage('/test/foo/index.html') self.assertNoPage('/test/foo/markdown.md') self.assertNoPage('/test/foo/main.css') if availability == ( courses.COURSE_AVAILABILITY_REGISTRATION_REQUIRED): self.register() self.assertPage('/test/foo/index.html', ' Web Server') self.assertPage('/test/foo/markdown.md', ' Web Server') self.assertPage('/test/foo/main.css', ' Web Server') self.unregister() actions.login('*****@*****.**', is_admin=True) self.assertPage('/test/foo/index.html', ' Web Server') self.assertPage('/test/foo/markdown.md', ' Web Server') self.assertPage('/test/foo/main.css', ' Web Server')
def test_draft_review_behaviour(self): """Test correctness of draft review visibility.""" 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) # Student 2 requests a review, and is given Student 1's assignment. response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) review_step_key_2_for_1 = get_review_step_key(response) actions.assert_contains('S1-1', response.body) # Student 2 saves her review as a draft. review_2_for_1_payload = get_review_payload('R2for1', is_draft=True) response = actions.submit_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, review_2_for_1_payload) actions.assert_contains('Your review has been saved.', response.body) response = self.get('reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) actions.assert_equals(response.status_int, 200) actions.assert_contains('(Draft)', response.body) # Student 2's draft is still changeable. response = actions.view_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1) actions.assert_contains('Submit Review', response.body) response = actions.submit_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, review_2_for_1_payload) actions.assert_contains('Your review has been saved.', response.body) # Student 2 logs out. actions.logout() # Student 3 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) actions.assert_contains('Assignment to review', response.body) actions.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) actions.assert_contains('Assignment to review', response.body) actions.assert_contains('not-S1', response.body) review_step_key_1_for_someone_else = get_review_step_key(response) response = self.get('reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) actions.assert_equals(response.status_int, 200) actions.assert_contains('disabled="true"', response.body) # Student 1 submits both reviews, fulfilling his quota. review_1_for_other_payload = get_review_payload('R1for') response = actions.submit_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone, review_1_for_other_payload) actions.assert_contains('Your review has been submitted successfully', response.body) response = actions.submit_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone_else, review_1_for_other_payload) actions.assert_contains('Your review has been submitted successfully', response.body) response = self.get('/reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) actions.assert_contains('(Completed)', response.body) actions.assert_does_not_contain('(Draft)', response.body) # Although Student 1 has submitted 2 reviews, he cannot view Student # 2's review because it is still in Draft status. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) actions.assert_equals(response.status_int, 200) actions.assert_contains('You have not received any peer reviews yet.', response.body) actions.assert_does_not_contain('R2for1', response.body) # Student 1 logs out. actions.logout() # Student 2 submits her review for Student 1's assignment. actions.login(email2) response = self.get('review?unit=%s&key=%s' % (LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1)) actions.assert_does_not_contain('Submitted review', response.body) response = actions.submit_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, get_review_payload('R2for1')) actions.assert_contains('Your review has been submitted successfully', response.body) # Her review is now read-only. response = self.get('review?unit=%s&key=%s' % (LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1)) actions.assert_contains('Submitted review', response.body) actions.assert_contains('R2for1', response.body) # Student 2 logs out. actions.logout() # Now Student 1 can see the review he has received from Student 2. actions.login(email1) response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) actions.assert_equals(response.status_int, 200) actions.assert_contains('R2for1', response.body)
def test_reviewer_cannot_impersonate_another_reviewer(self): """Test that one reviewer cannot use another's review step key.""" 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) # Student 2 requests a review, and is given Student 1's assignment. response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) review_step_key_2_for_1 = get_review_step_key(response) actions.assert_contains('S1-1', response.body) 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) # Student 3 tries to view Student 1's assignment using Student 2's # review step key, but is not allowed to. response = actions.view_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, expected_status_code=404) # Student 3 logs out. actions.logout()
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) actions.assert_equals(response.status_int, 200) actions.assert_contains('Assignment to review', response.body) actions.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) actions.assert_equals(response.status_int, 200) actions.assert_contains('Assignment to review', response.body) actions.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)) actions.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)) actions.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)) actions.assert_contains('R1forFirst', response.body) response = self.get( 'review?unit=%s&key=%s' % (LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone_else)) actions.assert_contains('R1forSecond', response.body) # Student 1 logs out. actions.logout()
def test_end_to_end(self): """Actually enroll and unenroll students; verify reporting counts.""" COURSE_NAME_BASE = 'test' NUM_COURSES = 2 NUM_STUDENTS = 3 THE_TIMESTAMP = 1427245200 for course_num in range(NUM_COURSES): course_name = '%s_%d' % (COURSE_NAME_BASE, course_num) actions.simple_add_course(course_name, ADMIN_EMAIL, course_name) actions.update_course_config(course_name, { 'course': { 'now_available': True, 'browsable': True, }, }) for student_num in range(NUM_STUDENTS): name = '%s_%d_%d' % (COURSE_NAME_BASE, course_num, student_num) actions.login(name + '@foo.com') actions.register(self, name, course_name) if student_num == 0: actions.unregister(self, course_name) actions.logout() # Expect no messages yet; haven't run job. self.assertEquals([], MockSender.get_sent()) # Run all counting jobs. with actions.OverriddenConfig(config.REPORT_ALLOWED.name, True): usage_reporting.StartReportingJobs._for_testing_only_get() self.execute_all_deferred_tasks( models.StudentLifecycleObserver.QUEUE_NAME) self.execute_all_deferred_tasks() # Verify counts. (Ignore dates, these are fickle and subject to # weirdness on hour boundaries. Also ignore course/instance IDs; # they are non-random and thus all the same.) num_enrolled_msgs = 0 num_unenrolled_msgs = 0 num_student_count_msgs = 0 for message in MockSender.get_sent(): if (message[messaging.Message._METRIC] == messaging.Message.METRIC_STUDENT_COUNT): num_student_count_msgs += 1 self.assertEquals(NUM_STUDENTS, message[messaging.Message._VALUE]) elif (message[messaging.Message._METRIC] == messaging.Message.METRIC_ENROLLED): num_enrolled_msgs += 1 self.assertEquals(NUM_STUDENTS, message[messaging.Message._VALUE]) elif (message[messaging.Message._METRIC] == messaging.Message.METRIC_UNENROLLED): num_unenrolled_msgs += 1 self.assertEquals(1, message[messaging.Message._VALUE]) self.assertEquals(NUM_COURSES, num_enrolled_msgs) self.assertEquals(NUM_COURSES, num_unenrolled_msgs) self.assertEquals(NUM_COURSES, num_student_count_msgs) sites.reset_courses()
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=peer_review') actions.assert_contains( 'Google > Dashboard > Manage > Peer review', response.body) actions.assert_contains('have not been calculated yet', response.body) response = response.forms['gcb-generate-analytics-data'].submit( ).follow() assert len(self.taskq.GetTasks('default')) == 1 actions.assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get(response.request.url) actions.assert_contains('were last updated at', response.body) actions.assert_contains('Peer review', response.body) actions.assert_contains('Sample peer review assignment', response.body) # JSON code for the completion statistics. actions.assert_contains('"[{\\"stats\\": [2]', response.body) actions.logout() # Student2 requests a review. actions.login(student2) response = actions.request_new_review( self, controllers_tests.LEGACY_REVIEW_UNIT_ID) review_step_key_2_for_1 = controllers_tests.get_review_step_key( response) actions.assert_contains('Assignment to review', response.body) # Student2 submits the review. response = actions.submit_review( self, controllers_tests.LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, controllers_tests.get_review_payload('R2for1')) actions.assert_contains('Your review has been submitted successfully', response.body) actions.logout() actions.login(email, is_admin=True) response = self.get('dashboard?action=peer_review') actions.assert_contains( 'Google > Dashboard > Manage > Peer review', response.body) response = response.forms['gcb-generate-analytics-data'].submit( ).follow() self.execute_all_deferred_tasks() response = self.get(response.request.url) actions.assert_contains('Peer review', response.body) # JSON code for the completion statistics. actions.assert_contains('"[{\\"stats\\": [1, 1]', response.body) actions.logout()
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) actions.assert_does_not_contain('Assignment to review', response.body) actions.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) actions.assert_equals(response.status_int, 302) response = self.get(response.location) actions.assert_does_not_contain( 'Error 412: The reviewer is already assigned', response.body) actions.assert_contains('First answer to Q1', response.body) actions.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) actions.assert_equals(response.status_int, 302) response = self.get(response.location) actions.assert_contains('Error 412: The reviewer is already assigned', response.body)