def setUp(self): """ Sets up user for testing with time zone utils. """ super().setUp() self.user = UserFactory.build() self.user.save()
def setUp(self): """ Sets up user for testing with time zone utils. """ super(TestTimeZoneUtils, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments self.user = UserFactory.build() self.user.save()
def setUp(self): super(TestPreferenceAPI, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments self.user = UserFactory.create(password=self.password) self.different_user = UserFactory.create(password=self.password) self.staff_user = UserFactory.create(is_staff=True, password=self.password) self.no_such_user = UserFactory.build(password=self.password, username="******") self.test_preference_key = "test_key" self.test_preference_value = "test_value" set_user_preference(self.user, self.test_preference_key, self.test_preference_value)
def setUp(self): super(UserReadOnlySerializerTest, self).setUp() request_factory = RequestFactory() self.request = request_factory.get('/api/user/v1/accounts/') self.user = UserFactory.build(username='******', email='*****@*****.**') self.user.save() self.config = { "default_visibility": "public", "public_fields": ['email', 'name', 'username'], }
def setUp(self): super(DarkLangMiddlewareTests, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments self.user = UserFactory.build(username='******', email='*****@*****.**', password='******') self.user.save() self.client = Client() self.client.login(username=self.user.username, password='******') DarkLangConfig( released_languages='rel', changed_by=self.user, enabled=True ).save()
def setUp(self): super().setUp() self.user = UserFactory.create(password=self.password) self.different_user = UserFactory.create(password=self.password) self.staff_user = UserFactory.create(is_staff=True, password=self.password) self.no_such_user = UserFactory.build(password=self.password, username="******") self.test_preference_key = "test_key" self.test_preference_value = "test_value" set_user_preference(self.user, self.test_preference_key, self.test_preference_value)
def setUp(self): super().setUp() self.user = UserFactory.build(username='******', email='*****@*****.**', password='******') self.user.save() self.client = Client() self.client.login(username=self.user.username, password='******') DarkLangConfig(released_languages='rel', changed_by=self.user, enabled=True).save()
def test_single_session_with_no_user_profile(self): """ Assert that user login with cas (Central Authentication Service) is redirect to dashboard in case of lms or upload_transcripts in case of cms """ user = UserFactory.build(username='******', email='*****@*****.**') user.set_password(self.password) user.save() # Assert that no profile is created. assert not hasattr(user, 'profile') creds = {'email': '*****@*****.**', 'password': self.password} client1 = Client() client2 = Client() response = client1.post(self.url, creds) self._assert_response(response, success=True) # Reload the user from the database user = User.objects.get(pk=user.pk) # Assert that profile is created. assert hasattr(user, 'profile') # second login should log out the first response = client2.post(self.url, creds) self._assert_response(response, success=True) try: # this test can be run with either lms or studio settings # since studio does not have a dashboard url, we should # look for another url that is login_required, in that case url = reverse('dashboard') except NoReverseMatch: url = reverse('upload_transcripts') response = client1.get(url) # client1 will be logged out assert response.status_code == 302
def _create_user(self, username, user_email): user = UserFactory.build(username=username, email=user_email) user.set_password(self.password) user.save() return user
class SequenceBlockTestCase(XModuleXmlImportTest): """ Base class for tests of Sequence Module. """ def setUp(self): super(SequenceBlockTestCase, self).setUp() course_xml = self._set_up_course_xml() self.course = self.process_xml(course_xml) self._set_up_module_system(self.course) for chapter_index in range(len(self.course.get_children())): chapter = self._set_up_block(self.course, chapter_index) setattr(self, 'chapter_{}'.format(chapter_index + 1), chapter) for sequence_index in range(len(chapter.get_children())): sequence = self._set_up_block(chapter, sequence_index) setattr( self, 'sequence_{}_{}'.format(chapter_index + 1, sequence_index + 1), sequence) @staticmethod def _set_up_course_xml(): """ Sets up and returns XML course structure. """ course = xml.CourseFactory.build(end=str(COURSE_END_DATE)) chapter_1 = xml.ChapterFactory.build( parent=course) # has 2 child sequences xml.ChapterFactory.build(parent=course) # has 0 child sequences chapter_3 = xml.ChapterFactory.build( parent=course) # has 1 child sequence chapter_4 = xml.ChapterFactory.build( parent=course) # has 1 child sequence, with hide_after_due chapter_5 = xml.ChapterFactory.build( parent=course) # has 1 child sequence, with a time limit xml.SequenceFactory.build(parent=chapter_1) xml.SequenceFactory.build(parent=chapter_1) sequence_3_1 = xml.SequenceFactory.build( parent=chapter_3) # has 3 verticals xml.SequenceFactory.build( # sequence_4_1 parent=chapter_4, hide_after_due=str(True), due=str(DUE_DATE), ) for _ in range(3): xml.VerticalFactory.build(parent=sequence_3_1) sequence_5_1 = xml.SequenceFactory.build(parent=chapter_5, is_time_limited=str(True)) vertical_5_1 = xml.VerticalFactory.build(parent=sequence_5_1) xml.ProblemFactory.build(parent=vertical_5_1) return course def _set_up_block(self, parent, index_in_parent): """ Sets up the stub sequence module for testing. """ block = parent.get_children()[index_in_parent] self._set_up_module_system(block) block.xmodule_runtime._services['bookmarks'] = Mock() # pylint: disable=protected-access block.xmodule_runtime._services['completion'] = Mock( # pylint: disable=protected-access return_value=Mock(vertical_is_complete=Mock(return_value=True))) block.xmodule_runtime._services['user'] = StubUserService() # pylint: disable=protected-access block.xmodule_runtime.xmodule_instance = getattr( block, '_xmodule', None) block.parent = parent.location return block def _set_up_module_system(self, block): """ Sets up the test module system for the given block. """ module_system = get_test_system() module_system.descriptor_runtime = block._runtime # pylint: disable=protected-access block.xmodule_runtime = module_system def _get_rendered_view(self, sequence, requested_child=None, extra_context=None, self_paced=False, view=STUDENT_VIEW): """ Returns the rendered student view for the given sequence and the requested_child parameter. """ context = {'requested_child': requested_child} if extra_context: context.update(extra_context) # The render operation will ask modulestore for the current course to get some data. As these tests were # originally not written to be compatible with a real modulestore, we've mocked out the relevant return values. with patch.object(SequenceModule, '_get_course') as mock_course: self.course.self_paced = self_paced mock_course.return_value = self.course return sequence.xmodule_runtime.render(sequence, view, context).content def _assert_view_at_position(self, rendered_html, expected_position): """ Verifies that the rendered view contains the expected position. """ self.assertIn("'position': {}".format(expected_position), rendered_html) def test_student_view_init(self): seq_module = SequenceModule(runtime=Mock(position=2), descriptor=Mock(), scope_ids=Mock()) self.assertEqual(seq_module.position, 2) # matches position set in the runtime @ddt.unpack @ddt.data( {'view': STUDENT_VIEW}, {'view': PUBLIC_VIEW}, ) def test_render_student_view(self, view): html = self._get_rendered_view(self.sequence_3_1, extra_context=dict( next_url='NextSequential', prev_url='PrevSequential'), view=view) self._assert_view_at_position(html, expected_position=1) self.assertIn(six.text_type(self.sequence_3_1.location), html) self.assertIn("'gated': False", html) self.assertIn("'next_url': 'NextSequential'", html) self.assertIn("'prev_url': 'PrevSequential'", html) self.assertNotIn("fa fa-check-circle check-circle is-hidden", html) @patch('xmodule.seq_module.User.objects.get', return_value=UserFactory.build()) def test_timed_exam_gating_waffle_flag(self, mocked_user): """ Verify the code inside the waffle flag is not executed with the flag off Verify the code inside the waffle flag is executed with the flag on """ # the order of the overrides is important since the `assert_not_called` does # not appear to be limited to just the override_waffle_flag = False scope with override_waffle_flag(TIMED_EXAM_GATING_WAFFLE_FLAG, active=False): self._get_rendered_view(self.sequence_5_1, extra_context=dict( next_url='NextSequential', prev_url='PrevSequential'), view=STUDENT_VIEW) mocked_user.assert_not_called() with override_waffle_flag(TIMED_EXAM_GATING_WAFFLE_FLAG, active=True): self._get_rendered_view(self.sequence_5_1, extra_context=dict( next_url='NextSequential', prev_url='PrevSequential'), view=STUDENT_VIEW) mocked_user.assert_called_once() @override_waffle_flag(TIMED_EXAM_GATING_WAFFLE_FLAG, active=True) @patch('xmodule.seq_module.User.objects.get', return_value=UserFactory.build()) def test_that_timed_sequence_gating_respects_access_configurations( self, mocked_user): # pylint: disable=unused-argument """ Verify that if a time limited sequence contains content type gated problems, we gate the sequence Verify that if a time limited sequence does not contain content type gated problems, we do not gate the sequence """ # the one problem in this sequence needs to have graded set to true in order to test content type gating self.sequence_5_1.get_children()[0].get_children()[0].graded = True gated_fragment = Fragment('i_am_gated') # When a time limited sequence contains content type gated problems, the sequence itself is gated self.sequence_5_1.runtime._services['content_type_gating'] = Mock( return_value=Mock( # pylint: disable=protected-access enabled_for_enrollment=Mock(return_value=True), content_type_gate_for_block=Mock(return_value=gated_fragment))) view = self._get_rendered_view(self.sequence_5_1, extra_context=dict( next_url='NextSequential', prev_url='PrevSequential'), view=STUDENT_VIEW) self.assertIn('i_am_gated', view) # check a few elements to ensure the correct page was loaded self.assertIn("seq_module.html", view) self.assertIn('NextSequential', view) self.assertIn('PrevSequential', view) # When enabled_for_enrollment is false, the sequence itself is not gated self.sequence_5_1.runtime._services['content_type_gating'] = Mock( return_value=Mock( # pylint: disable=protected-access enabled_for_enrollment=Mock(return_value=False), content_type_gate_for_block=Mock(return_value=gated_fragment))) view = self._get_rendered_view(self.sequence_5_1, extra_context=dict( next_url='NextSequential', prev_url='PrevSequential'), view=STUDENT_VIEW) self.assertNotIn('i_am_gated', view) # check a few elements to ensure the correct page was loaded self.assertIn("seq_module.html", view) self.assertIn('NextSequential', view) self.assertIn('PrevSequential', view) # When content_type_gate_for_block returns None, the sequence itself is not gated self.sequence_5_1.runtime._services['content_type_gating'] = Mock( return_value=Mock( # pylint: disable=protected-access enabled_for_enrollment=Mock(return_value=True), content_type_gate_for_block=Mock(return_value=None))) view = self._get_rendered_view(self.sequence_5_1, extra_context=dict( next_url='NextSequential', prev_url='PrevSequential'), view=STUDENT_VIEW) self.assertNotIn('i_am_gated', view) # check a few elements to ensure the correct page was loaded self.assertIn("seq_module.html", view) self.assertIn('NextSequential', view) self.assertIn('PrevSequential', view) @ddt.unpack @ddt.data( {'view': STUDENT_VIEW}, {'view': PUBLIC_VIEW}, ) def test_student_view_first_child(self, view): html = self._get_rendered_view(self.sequence_3_1, requested_child='first', view=view) self._assert_view_at_position(html, expected_position=1) @ddt.unpack @ddt.data( {'view': STUDENT_VIEW}, {'view': PUBLIC_VIEW}, ) def test_student_view_last_child(self, view): html = self._get_rendered_view(self.sequence_3_1, requested_child='last', view=view) self._assert_view_at_position(html, expected_position=3) def test_tooltip(self): html = self._get_rendered_view(self.sequence_3_1, requested_child=None) for child in self.sequence_3_1.children: self.assertIn("'page_title': '{}'".format(child.block_id), html) def test_hidden_content_before_due(self): html = self._get_rendered_view(self.sequence_4_1) self.assertIn("seq_module.html", html) self.assertIn("'banner_text': None", html) def test_hidden_content_past_due(self): with freeze_time(COURSE_END_DATE): progress_url = 'http://test_progress_link' html = self._get_rendered_view( self.sequence_4_1, extra_context=dict(progress_url=progress_url), ) self.assertIn("hidden_content.html", html) self.assertIn(progress_url, html) def test_masquerade_hidden_content_past_due(self): with freeze_time(COURSE_END_DATE): html = self._get_rendered_view( self.sequence_4_1, extra_context=dict(specific_masquerade=True), ) self.assertIn("seq_module.html", html) html = self.get_context_dict_from_string(html) self.assertEqual( 'Because the due date has passed, this assignment is hidden from the learner.', html['banner_text']) def test_hidden_content_self_paced_past_due_before_end(self): with freeze_time(PAST_DUE_BEFORE_END_DATE): html = self._get_rendered_view(self.sequence_4_1, self_paced=True) self.assertIn("seq_module.html", html) self.assertIn("'banner_text': None", html) def test_hidden_content_self_paced_past_end(self): with freeze_time(COURSE_END_DATE + timedelta(days=7)): progress_url = 'http://test_progress_link' html = self._get_rendered_view( self.sequence_4_1, extra_context=dict(progress_url=progress_url), self_paced=True, ) self.assertIn("hidden_content.html", html) self.assertIn(progress_url, html) def _assert_gated(self, html, sequence): """ Assert sequence content is gated """ self.assertIn("seq_module.html", html) html = self.get_context_dict_from_string(html) self.assertIsNone(html['banner_text']) self.assertEqual([], html['items']) self.assertTrue(html['gated_content']['gated']) self.assertEqual('PrereqUrl', html['gated_content']['prereq_url']) self.assertEqual('PrereqSectionName', html['gated_content']['prereq_section_name']) self.assertIn(six.text_type(sequence.display_name), html['gated_content']['gated_section_name']) self.assertEqual('NextSequential', html['next_url']) self.assertEqual('PrevSequential', html['prev_url']) def _assert_prereq(self, html, sequence): """ Assert sequence is a prerequisite with unfulfilled gates """ self.assertIn("seq_module.html", html) html = self.get_context_dict_from_string(html) self.assertEqual( "This section is a prerequisite. You must complete this section in order to unlock additional content.", html['banner_text']) self.assertFalse(html['gated_content']['gated']) self.assertEqual(six.text_type(sequence.location), html['item_id']) self.assertIsNone(html['gated_content']['prereq_url']) self.assertIsNone(html['gated_content']['prereq_section_name']) self.assertEqual('NextSequential', html['next_url']) self.assertEqual('PrevSequential', html['prev_url']) def _assert_ungated(self, html, sequence): """ Assert sequence is not gated """ self.assertIn("seq_module.html", html) self.assertIn("'banner_text': None", html) self.assertIn("'gated': False", html) self.assertIn(six.text_type(sequence.location), html) self.assertIn("'prereq_url': None", html) self.assertIn("'prereq_section_name': None", html) self.assertIn("'next_url': 'NextSequential'", html) self.assertIn("'prev_url': 'PrevSequential'", html) def test_gated_content(self): """ Test when sequence is both a prerequisite for a sequence and gated on another prerequisite sequence """ # setup seq_1_2 as a gate and gated gating_mock_1_2 = Mock() gating_mock_1_2.return_value.is_gate_fulfilled.return_value = False gating_mock_1_2.return_value.required_prereq.return_value = True gating_mock_1_2.return_value.compute_is_prereq_met.return_value = [ False, { 'url': 'PrereqUrl', 'display_name': 'PrereqSectionName', 'id': 'mockId' } ] self.sequence_1_2.xmodule_runtime._services['gating'] = gating_mock_1_2 # pylint: disable=protected-access self.sequence_1_2.display_name = 'sequence_1_2' html = self._get_rendered_view( self.sequence_1_2, extra_context=dict(next_url='NextSequential', prev_url='PrevSequential'), ) # expect content to be gated, with no banner self._assert_gated(html, self.sequence_1_2) # change seq_1_2 to be ungated, but still a gate (prequiste) gating_mock_1_2.return_value.is_gate_fulfilled.return_value = False gating_mock_1_2.return_value.required_prereq.return_value = True gating_mock_1_2.return_value.compute_is_prereq_met.return_value = [ True, {} ] html = self._get_rendered_view( self.sequence_1_2, extra_context=dict(next_url='NextSequential', prev_url='PrevSequential'), ) # assert that content and preq banner is shown self._assert_prereq(html, self.sequence_1_2) # change seq_1_2 to have no unfulfilled gates gating_mock_1_2.return_value.is_gate_fulfilled.return_value = True gating_mock_1_2.return_value.required_prereq.return_value = True gating_mock_1_2.return_value.compute_is_prereq_met.return_value = [ True, {} ] html = self._get_rendered_view( self.sequence_1_2, extra_context=dict(next_url='NextSequential', prev_url='PrevSequential'), ) # assert content shown as normal self._assert_ungated(html, self.sequence_1_2) def test_handle_ajax_get_completion_success(self): """ Test that the completion data is returned successfully on targeted vertical through ajax call """ for child in self.sequence_3_1.get_children(): usage_key = six.text_type(child.location) completion_return = json.loads( self.sequence_3_1.handle_ajax('get_completion', {'usage_key': usage_key})) self.assertIsNot(completion_return, None) self.assertTrue('complete' in completion_return) self.assertEqual(completion_return['complete'], True) def test_handle_ajax_get_completion_return_none(self): """ Test that the completion data is returned successfully None when usage key is None through ajax call """ usage_key = None completion_return = self.sequence_3_1.handle_ajax( 'get_completion', {'usage_key': usage_key}) self.assertIs(completion_return, None) def test_handle_ajax_metadata(self): """ Test that the sequence metadata is returned from the metadata ajax handler. """ # rather than dealing with json serialization of the Mock object, # let's just disable the bookmarks service self.sequence_3_1.xmodule_runtime._services['bookmarks'] = None metadata = json.loads(self.sequence_3_1.handle_ajax('metadata', {})) self.assertEqual(len(metadata['items']), 3) self.assertEqual(metadata['tag'], 'sequential') self.assertEqual(metadata['display_name'], self.sequence_3_1.display_name_with_default) def get_context_dict_from_string(self, data): """ Retrieve dictionary from string. """ # Replace tuple and un-necessary info from inside string and get the dictionary. cleaned_data = data.replace("(('seq_module.html',\n", '').replace("),\n {})", '').strip() return ast.literal_eval(cleaned_data)
class TestContentTypeGatingService(ModuleStoreTestCase): """ The ContentTypeGatingService was originally created as a helper class for timed exams to check whether a sequence contains content type gated blocks The content_type_gate_for_block can be used to return the content type gate for a given block """ def setUp(self): super().setUp() self.user = UserFactory.create() self.request_factory = RequestFactory() ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime( 2018, 1, 1)) def _create_course(self): course = CourseFactory.create(run='test', display_name='test') CourseModeFactory.create(course_id=course.id, mode_slug='audit') CourseModeFactory.create(course_id=course.id, mode_slug='verified') blocks_dict = {} with self.store.bulk_operations(course.id): blocks_dict['chapter'] = ItemFactory.create(parent=course, category='chapter', display_name='Week 1') blocks_dict['sequential'] = ItemFactory.create( parent=blocks_dict['chapter'], category='sequential', display_name='Lesson 1') blocks_dict['vertical'] = ItemFactory.create( parent=blocks_dict['sequential'], category='vertical', display_name='Lesson 1 Vertical - Unit 1') return { 'course': course, 'blocks': blocks_dict, } def test_content_type_gate_for_block(self): ''' Verify that the method returns a content type gate when appropriate ''' course = self._create_course() blocks_dict = course['blocks'] CourseEnrollmentFactory.create(user=self.user, course_id=course['course'].id, mode='audit') blocks_dict['graded_1'] = ItemFactory.create( parent=blocks_dict['vertical'], category='problem', graded=True, metadata=METADATA, ) blocks_dict['not_graded_1'] = ItemFactory.create( parent=blocks_dict['vertical'], category='problem', graded=False, metadata=METADATA, ) # The method returns a content type gate for blocks that should be gated assert 'content-paywall' in ContentTypeGatingService( )._content_type_gate_for_block(self.user, blocks_dict['graded_1'], course['course'].id).content # The method returns None for blocks that should not be gated assert ContentTypeGatingService()._content_type_gate_for_block( self.user, blocks_dict['not_graded_1'], course['course'].id) is None @patch.object(ContentTypeGatingService, '_get_user', return_value=UserFactory.build()) def test_check_children_for_content_type_gating_paywall(self, mocked_user): # pylint: disable=unused-argument ''' Verify that the method returns a content type gate when appropriate ''' course = self._create_course() blocks_dict = course['blocks'] CourseEnrollmentFactory.create(user=self.user, course_id=course['course'].id, mode='audit') blocks_dict['not_graded_1'] = ItemFactory.create( parent=blocks_dict['vertical'], category='problem', graded=False, metadata=METADATA, ) # The method returns a content type gate for blocks that should be gated assert ContentTypeGatingService( ).check_children_for_content_type_gating_paywall( blocks_dict['vertical'], course['course'].id) is None blocks_dict['graded_1'] = ItemFactory.create( parent=blocks_dict['vertical'], category='problem', graded=True, metadata=METADATA, ) # The method returns None for blocks that should not be gated assert 'content-paywall' in ContentTypeGatingService( ).check_children_for_content_type_gating_paywall( blocks_dict['vertical'], course['course'].id)