def setUp(self): super(CommentsEmailTests, self).setUp() self.user = UserFactory() self.user_2 = UserFactory() self.user_3 = UserFactory() self.site = Site.objects.get(pk=settings.SITE_ID) self.organization_extension = factories.OrganizationExtensionFactory() self.user.groups.add(self.organization_extension.group) self.user_2.groups.add(self.organization_extension.group) self.user_3.groups.add(self.organization_extension.group) self.seat = factories.SeatFactory() self.course_run = self.seat.course_run self.course = self.course_run.course self.course.organizations.add(self.organization_extension.organization) assign_perm(Course.VIEW_PERMISSION, self.organization_extension.group, self.course) # NOTE: We intentionally do NOT create an attribute for user_2. # By default this user WILL receive email notifications. UserAttributeFactory(user=self.user, enable_email_notification=True) UserAttributeFactory(user=self.user_3, enable_email_notification=False) toggle_switch('enable_publisher_email_notifications', True)
def setUp(self): super(CommentsEmailTests, self).setUp() self.user = UserFactory() self.user_2 = UserFactory() self.user_3 = UserFactory() self.site = Site.objects.get(pk=settings.SITE_ID) self.group = factories.GroupFactory(name='abc') self.user.groups.add(self.group) self.user_2.groups.add(self.group) self.user_3.groups.add(self.group) self.seat = factories.SeatFactory() self.course_run = self.seat.course_run self.course = self.course_run.course assign_perm(Course.VIEW_PERMISSION, self.group, self.course) # NOTE: We intentionally do NOT create an attribute for user_2. # By default this user WILL receive email notifications. UserAttributeFactory(user=self.user, enable_email_notification=True) UserAttributeFactory(user=self.user_3, enable_email_notification=False) toggle_switch('enable_publisher_email_notifications', True)
def setUpClass(cls): super(StateChangeEmailTests, cls).setUpClass() cls.user = UserFactory() cls.user_2 = UserFactory() cls.user_3 = UserFactory() cls.site = Site.objects.get(pk=settings.SITE_ID) cls.organization_extension = factories.OrganizationExtensionFactory() cls.group = cls.organization_extension.group cls.user.groups.add(cls.group) cls.user_2.groups.add(cls.group) cls.user_3.groups.add(cls.group) cls.seat = factories.SeatFactory() cls.course_run = cls.seat.course_run cls.course = cls.course_run.course assign_perm(Course.VIEW_PERMISSION, cls.group, cls.course) # NOTE: We intentionally do NOT create an attribute for user_2. # By default this user WILL receive email notifications. UserAttributeFactory(user=cls.user, enable_email_notification=True) UserAttributeFactory(user=cls.user_3, enable_email_notification=False) toggle_switch('enable_publisher_email_notifications', True)
def test_publication_disabled(self): """ Verify that the publisher is not initialized when publication is disabled. """ toggle_switch('publish_course_runs_to_marketing_site', active=False) with mock.patch.object(CourseRunMarketingSitePublisher, '__init__') as mock_init: self.course_run.save() self.course_run.delete() assert mock_init.call_count == 0 toggle_switch('publish_course_runs_to_marketing_site') with mock.patch.object(CourseRunMarketingSitePublisher, '__init__') as mock_init: # Make sure if the save comes from refresh_course_metadata, we don't actually publish self.course_run.save(suppress_publication=True) assert mock_init.call_count == 0 self.course_run.course.partner.marketing_site_url_root = '' self.course_run.course.partner.save() with mock.patch.object(CourseRunMarketingSitePublisher, '__init__') as mock_init: self.course_run.save() self.course_run.delete() assert mock_init.call_count == 0
def test_create_without_waffle_switch(self): """ Verify endpoint shows error message if waffle switch is disabled. """ toggle_switch('publish_person_to_marketing_site', False) response = self.client.post(self.people_list_url, self._person_data(), format='json') self.assertEqual(response.status_code, 400)
def setUp(self): super(CourseRunStateSerializerTests, self).setUp() self.run_state = CourseRunStateFactory( name=CourseRunStateChoices.Draft) self.course_run = self.run_state.course_run self.request = RequestFactory() self.user = UserFactory() self.request.user = self.user CourseStateFactory(name=CourseStateChoices.Approved, course=self.course_run.course) SeatFactory(course_run=self.course_run, type=Seat.AUDIT) language_tag = LanguageTag(code='te-st', name='Test Language') language_tag.save() self.course_run.transcript_languages.add(language_tag) self.course_run.language = language_tag organization = OrganizationFactory() self.course_run.course.organizations.add(organization) self.course_run.save() self.course_run.staff.add(PersonFactory()) toggle_switch('enable_publisher_email_notifications', True) CourseUserRoleFactory(course=self.course_run.course, role=PublisherUserRole.CourseTeam, user=self.user) CourseUserRoleFactory(course=self.course_run.course, role=PublisherUserRole.ProjectCoordinator, user=UserFactory())
def setUp(self): super(ChangeCourseRunStateViewTests, self).setUp() self.seat = factories.SeatFactory(type=Seat.VERIFIED, price=2) self.course_run = self.seat.course_run self.run_state = factories.CourseRunStateFactory(name=CourseRunStateChoices.Draft, course_run=self.course_run) self.course_state = factories.CourseStateFactory( name=CourseStateChoices.Approved, course=self.course_run.course ) self.user = UserFactory() self.user.groups.add(Group.objects.get(name=INTERNAL_USER_GROUP_NAME)) self.change_state_url = reverse('publisher:api:change_course_run_state', kwargs={'pk': self.run_state.id}) self.client.login(username=self.user.username, password=USER_PASSWORD) language_tag = LanguageTag(code='te-st', name='Test Language') language_tag.save() self.course_run.transcript_languages.add(language_tag) self.course_run.language = language_tag self.course_run.lms_course_id = 'course-v1:edX+DemoX+Demo_Course' self.course_run.course.organizations.add(OrganizationFactory()) self.course_run.save() self.course_run.staff.add(PersonFactory()) toggle_switch('enable_publisher_email_notifications', True)
def test_refresh_course_metadata_parallel(self, mock_set_api_timestamp, mock_receiver): for name in ['threaded_metadata_write', 'parallel_refresh_pipeline']: toggle_switch(name) with responses.RequestsMock() as rsps: self.mock_access_token_api(rsps) self.mock_apis() with mock.patch('concurrent.futures.ProcessPoolExecutor.submit' ) as mock_executor: call_command('refresh_course_metadata') # Set up expected calls expected_calls = [ mock.call(execute_parallel_loader, loader_class, self.partner, api_url, ACCESS_TOKEN, 'JWT', max_workers or 7, True, **self.kwargs) for loader_class, api_url, max_workers in self.pipeline ] mock_executor.assert_has_calls(expected_calls, any_order=True) # Verify that the API cache is invalidated once, and that it isn't # being done by the signal receiver. assert mock_set_api_timestamp.call_count == 1 assert not mock_receiver.called
def setUp(self): super(CourseRunMarkAsReviewedEmailTests, self).setUp() self.user = UserFactory() self.user_2 = UserFactory() self.user_3 = UserFactory() self.seat = factories.SeatFactory() self.course_run = self.seat.course_run self.course = self.course_run.course self.course.organizations.add(OrganizationFactory()) # add user in course-user-role table factories.CourseUserRoleFactory(course=self.course, role=PublisherUserRole.CourseTeam, user=self.user_2) factories.CourseUserRoleFactory(course=self.course, role=PublisherUserRole.Publisher, user=self.user_3) self.course_run_state = factories.CourseRunStateFactory( course_run=self.course_run) self.course_run.lms_course_id = 'course-v1:edX+DemoX+Demo_Course' self.course_run.save() toggle_switch('enable_publisher_email_notifications', True)
def setUpClass(cls): super(StateChangeEmailTests, cls).setUpClass() cls.user = UserFactory() cls.user_2 = UserFactory() cls.user_3 = UserFactory() cls.site = Site.objects.get(pk=settings.SITE_ID) cls.group = factories.GroupFactory() cls.user.groups.add(cls.group) cls.user_2.groups.add(cls.group) cls.user_3.groups.add(cls.group) cls.seat = factories.SeatFactory() cls.course_run = cls.seat.course_run cls.course = cls.course_run.course assign_perm(Course.VIEW_PERMISSION, cls.group, cls.course) # NOTE: We intentionally do NOT create an attribute for user_2. # By default this user WILL receive email notifications. UserAttributeFactory(user=cls.user, enable_email_notification=True) UserAttributeFactory(user=cls.user_3, enable_email_notification=False) toggle_switch('enable_publisher_email_notifications', True)
def test_update_without_waffle_switch(self): """ Verify update endpoint shows error message if waffle switch is disabled. """ url = reverse('api:v1:person-detail', kwargs={'uuid': self.person.uuid}) toggle_switch('publish_person_to_marketing_site', False) response = self.client.patch(url, self._update_person_data(), format='json') self.assertEqual(response.status_code, 400)
def test_create_without_waffle_switch(self): """ Verify endpoint proceeds if waffle switch is disabled. """ toggle_switch('publish_person_to_marketing_site', False) data = self._person_data() with mock.patch.object(MarketingSitePeople, 'update_or_publish_person') as cm: response = self.client.post(self.people_list_url, data, format='json') self.assertEqual(cm.call_count, 0) self.assertEqual(response.status_code, 201) self.assertTrue(self.person_exists(data))
def test_update_without_waffle_switch(self): """ Verify update endpoint proceeds if waffle switch is disabled. """ url = reverse('api:v1:person-detail', kwargs={'uuid': self.person.uuid}) toggle_switch('publish_person_to_marketing_site', False) data = self._update_person_data() with mock.patch.object(MarketingSitePeople, 'update_or_publish_person') as cm: response = self.client.patch(url, data, format='json') self.assertEqual(cm.call_count, 0) self.assertEqual(response.status_code, 200) self.assertTrue(self.person_exists(data))
def test_publish_obj_create_successful( self, mock_update_node_alias, mock_create_node, *args ): # pylint: disable=unused-argument toggle_switch('auto_course_about_page_creation', True) self.publisher.publish_obj(self.obj) mock_create_node.assert_called_with({'data': 'test', 'field_course_uuid': str(self.obj.uuid)}) mock_update_node_alias.assert_called_with(self.obj, 'node_id', None)
def test_publish_obj_create_if_exists_on_discovery(self, mock_update_node_alias, mock_create_node, mock_serialize_obj, mock_node_id, *args): # pylint: disable=unused-argument toggle_switch('auto_course_about_page_creation', True) self.publisher.publish_obj(self.obj, previous_obj=self.obj) mock_node_id.assert_called_with(self.obj) mock_serialize_obj.assert_called_with(self.obj) mock_create_node.assert_called_with('data') mock_update_node_alias.assert_called_with(self.obj, 'node1', self.obj)
def test_delete_and_publish_success(self): self.program.partner.marketing_site_url_root = self.api_root self.program.partner.marketing_site_api_username = self.username self.program.partner.marketing_site_api_password = self.password self.program.type = ProgramType.objects.get(name='MicroMasters') self.mock_api_client(200) self.mock_node_retrieval(self.program.uuid) self.mock_node_delete(204) toggle_switch('publish_program_to_marketing_site', True) self.program.delete() self.assert_responses_call_count(6)
def test_delete_and_publish_success(self): self.program.partner.marketing_site_url_root = self.api_root self.program.partner.marketing_site_api_username = self.username self.program.partner.marketing_site_api_password = self.password self.program.type = ProgramType.objects.get(name='MicroMasters') self.mock_api_client(200) self.mock_node_retrieval(self.program.uuid) self.mock_node_delete(204) toggle_switch('publish_program_to_marketing_site', True) self.program.delete() self.assert_responses_call_count(5)
def test_xseries_program_save(self): """ Make sure if the Program instance is of type XSeries, we do not publish to Marketing Site """ self.program.partner.marketing_site_url_root = self.api_root self.program.partner.marketing_site_api_username = self.username self.program.partner.marketing_site_api_password = self.password self.program.type = ProgramType.objects.get(name='XSeries') toggle_switch('publish_program_to_marketing_site', True) self.program.title = FuzzyText().fuzz() self.program.save() self.assert_responses_call_count(0)
def setUp(self): super(StudioInstanceCreatedEmailTests, self).setUp() self.user = UserFactory() self.group = factories.GroupFactory() self.user.groups.add(self.group) self.course_run = factories.CourseRunFactory() assign_perm(Course.VIEW_PERMISSION, self.group, self.course_run.course) UserAttributeFactory(user=self.user, enable_email_notification=True) toggle_switch('enable_publisher_email_notifications', True)
def setUp(self): super(CourseChangeRoleAssignmentEmailTests, self).setUp() self.user = UserFactory() self.marketing_role = factories.CourseUserRoleFactory( role=PublisherUserRole.MarketingReviewer, user=self.user) self.course = self.marketing_role.course factories.CourseUserRoleFactory(course=self.course, role=PublisherUserRole.Publisher) factories.CourseUserRoleFactory( course=self.course, role=PublisherUserRole.ProjectCoordinator) factories.CourseUserRoleFactory(course=self.course, role=PublisherUserRole.CourseTeam) toggle_switch('enable_publisher_email_notifications', True)
def test_search(self): """ Verify the method returns a filtered queryset of courses. """ toggle_switch('log_course_search_queries', active=True) title = 'Some random title' courses = factories.CourseFactory.create_batch(3, title=title) # Sort lowercase keys to prevent different sort orders due to casing. # For example, sorted(['a', 'Z']) gives ['Z', 'a'], but an ordered # queryset containing the same values may give ['a', 'Z'] depending # on the database backend in use. courses = sorted(courses, key=lambda course: course.key.lower()) query = 'title:' + title # Use Lower() to force a case-insensitive sort. actual = list(Course.search(query).order_by(Lower('key'))) self.assertEqual(actual, courses)
def setUp(self): super(CourseRunPublishedEmailTests, self).setUp() self.user = UserFactory() self.run_state = factories.CourseRunStateFactory() self.course_run = self.run_state.course_run self.course = self.course_run.course factories.CourseUserRoleFactory(course=self.course, role=PublisherUserRole.CourseTeam, user=self.user) factories.CourseUserRoleFactory(course=self.course, role=PublisherUserRole.Publisher, user=UserFactory()) toggle_switch('enable_publisher_email_notifications', True)
def setUp(self): super(PersonViewSetTests, self).setUp() self.user = UserFactory(is_staff=True, is_superuser=True) self.user.groups.add(Group.objects.get(name=INTERNAL_USER_GROUP_NAME)) self.client.force_authenticate(self.user) self.person = PersonFactory(partner=self.partner) self.organization = OrganizationFactory(partner=self.partner) PositionFactory(person=self.person, organization=self.organization) toggle_switch('publish_person_to_marketing_site', True) self.expected_node = { 'resource': 'node', '' 'id': '28691', 'uuid': '18d5542f-fa80-418e-b416-455cfdeb4d4e', 'uri': 'https://stage.edx.org/node/28691' }
def test_publication_enabled(self): """ Verify that the publisher is called when publication is enabled. """ toggle_switch('publish_program_to_marketing_site') with mock.patch.object(ProgramMarketingSitePublisher, 'publish_obj', return_value=None) as mock_publish_obj: self.program.save() assert mock_publish_obj.called with mock.patch.object(ProgramMarketingSitePublisher, 'delete_obj', return_value=None) as mock_delete_obj: self.program.delete() assert mock_delete_obj.called
def setUp(self): super(CourseCreatedEmailTests, self).setUp() self.user = UserFactory() self.course_run = factories.CourseRunFactory() # add user in course-user-role table factories.CourseUserRoleFactory( course=self.course_run.course, role=PublisherUserRole.ProjectCoordinator, user=self.user ) self.course_team = UserFactory() factories.CourseUserRoleFactory( course=self.course_run.course, role=PublisherUserRole.CourseTeam, user=self.course_team ) UserAttributeFactory(user=self.user, enable_email_notification=True) toggle_switch('enable_publisher_email_notifications', True)
def test_publication_enabled(self): """ Verify that the publisher is called when publication is enabled. """ toggle_switch('publish_course_runs_to_marketing_site') with mock.patch.object(CourseRunMarketingSitePublisher, 'publish_obj', return_value=None) as mock_publish_obj: self.course_run.save() assert mock_publish_obj.called with mock.patch.object(CourseRunMarketingSitePublisher, 'delete_obj', return_value=None) as mock_delete_obj: self.course_run.delete() # We don't want to delete course run nodes when CourseRuns are deleted. assert not mock_delete_obj.called
def setUp(self): super(ChangeCourseStateViewTests, self).setUp() self.course_state = factories.CourseStateFactory(name=CourseStateChoices.Draft) self.user = UserFactory() self.user.groups.add(Group.objects.get(name=INTERNAL_USER_GROUP_NAME)) self.course = self.course_state.course self.course.image = make_image_file('test_banner.jpg') self.course.save() self.organization_extension = factories.OrganizationExtensionFactory() self.course.organizations.add(self.organization_extension.organization) factories.UserAttributeFactory(user=self.user, enable_email_notification=True) toggle_switch('enable_publisher_email_notifications', True) self.change_state_url = reverse('publisher:api:change_course_state', kwargs={'pk': self.course_state.id}) self.client.login(username=self.user.username, password=USER_PASSWORD)
def setUp(self): super(CourseRunPreviewEmailTests, self).setUp() self.user = UserFactory() self.run_state = factories.CourseRunStateFactory() self.course = self.run_state.course_run.course # add users in CourseUserRole table factories.CourseUserRoleFactory( course=self.course, role=PublisherUserRole.CourseTeam, user=self.user ) factories.CourseUserRoleFactory( course=self.course, role=PublisherUserRole.Publisher, user=UserFactory() ) factories.CourseUserRoleFactory( course=self.course, role=PublisherUserRole.ProjectCoordinator, user=UserFactory() ) toggle_switch('enable_publisher_email_notifications', True)
def setUp(self): super(CommentsTests, self).setUp() self.user = UserFactory(is_staff=True, is_superuser=True) self.group = factories.GroupFactory() self.user.groups.add(self.group) self.client.login(username=self.user.username, password=USER_PASSWORD) self.site = Site.objects.get(pk=settings.SITE_ID) self.course_edit_page = 'publisher:publisher_courses_edit' self.course_run_edit_page = 'publisher:publisher_course_runs_edit' self.seat_edit_page = 'publisher:publisher_seats_edit' self.edit_comment_page = 'publisher_comments:comment_edit' self.seat = factories.SeatFactory(type=Seat.PROFESSIONAL, credit_hours=0) self.course_run = self.seat.course_run self.course = self.course_run.course self.course.assign_permission_by_group(self.group) toggle_switch('enable_publisher_email_notifications', True)
def test_transaction_roll_back_with_error_on_email(self): """ Verify that transaction is roll backed if error occurred during email sending. """ toggle_switch('enable_publisher_email_notifications', True) serializer = self.serializer_class(self.course_run) self.assertEqual(self.course_run.course_run_state.owner_role, PublisherUserRole.Publisher) with self.assertRaises(Exception): serializer.update( self.course_run, {'preview_url': 'https://example.com/abc/course'}) self.course_run = CourseRun.objects.get(id=self.course_run.id) self.assertFalse(self.course_run.preview_url) # Verify that owner role not changed. self.assertEqual(self.course_run.course_run_state.owner_role, PublisherUserRole.Publisher)
def setUp(self): super(PersonViewSetTests, self).setUp() self.user = UserFactory(is_staff=True, is_superuser=True) self.client.force_authenticate(self.user) self.person = PersonFactory() PositionFactory(person=self.person) self.organization = OrganizationFactory() # DEFAULT_PARTNER_ID is used explicitly here to avoid issues with differences in # auto-incrementing behavior across databases. Otherwise, it's not safe to assume # that the partner created here will always have id=DEFAULT_PARTNER_ID. self.partner = PartnerFactory(id=settings.DEFAULT_PARTNER_ID) toggle_switch('publish_person_to_marketing_site', True) self.expected_node = { 'resource': 'node', '' 'id': '28691', 'uuid': '18d5542f-fa80-418e-b416-455cfdeb4d4e', 'uri': 'https://stage.edx.org/node/28691' }
def setUp(self): super(CourseRunMarkAsReviewedEmailTests, self).setUp() self.user = UserFactory() self.user_2 = UserFactory() self.user_3 = UserFactory() self.seat = factories.SeatFactory() self.course_run = self.seat.course_run self.course = self.course_run.course # add user in course-user-role table factories.CourseUserRoleFactory( course=self.course, role=PublisherUserRole.CourseTeam, user=self.user_2 ) factories.CourseUserRoleFactory( course=self.course, role=PublisherUserRole.Publisher, user=self.user_3 ) self.course_run_state = factories.CourseRunStateFactory(course_run=self.course_run) toggle_switch('enable_publisher_email_notifications', True)
def setUp(self): super(PersonViewSetTests, self).setUp() self.user = UserFactory() self.target_permissions = Permission.objects.filter( codename__in=['add_person', 'change_person', 'delete_person']) internal_test_group = Group.objects.create(name='internal-test') internal_test_group.permissions.add(*self.target_permissions) self.user.groups.add(internal_test_group) self.client.login(username=self.user.username, password=USER_PASSWORD) self.person = PersonFactory(partner=self.partner) self.organization = OrganizationFactory(partner=self.partner) PositionFactory(person=self.person, organization=self.organization) toggle_switch('publish_person_to_marketing_site', True) self.expected_node = { 'resource': 'node', '' 'id': '28691', 'uuid': '18d5542f-fa80-418e-b416-455cfdeb4d4e', 'uri': 'https://stage.edx.org/node/28691' }
def test_refresh_course_metadata_parallel(self): for name in ['threaded_metadata_write', 'parallel_refresh_pipeline']: toggle_switch(name) with responses.RequestsMock() as rsps: self.mock_access_token_api(rsps) self.mock_apis() # Courses must exist for the command to use multiple threads. If there are no # courses, the command won't risk race conditions between threads trying to # create the same course. CourseFactory(partner=self.partner) with mock.patch('concurrent.futures.ProcessPoolExecutor.submit') as mock_executor: call_command('refresh_course_metadata') # Set up expected calls expected_calls = [mock.call(execute_parallel_loader, loader_class, self.partner, api_url, ACCESS_TOKEN, 'JWT', max_workers_override or 7, True, **self.kwargs) for loader_class, api_url, max_workers_override in self.pipeline] mock_executor.assert_has_calls(expected_calls, any_order=True)
def setUp(self): super(CommentsTests, self).setUp() self.user = UserFactory(is_staff=True, is_superuser=True) self.organization_extension = factories.OrganizationExtensionFactory() self.user.groups.add(self.organization_extension.group) self.client.login(username=self.user.username, password=USER_PASSWORD) self.site = Site.objects.get(pk=settings.SITE_ID) self.course_edit_page = 'publisher:publisher_courses_edit' self.course_run_edit_page = 'publisher:publisher_course_runs_edit' self.seat_edit_page = 'publisher:publisher_seats_edit' self.edit_comment_page = 'publisher_comments:comment_edit' self.seat = factories.SeatFactory(type=Seat.PROFESSIONAL, credit_hours=0) self.course_run = self.seat.course_run self.course = self.course_run.course self.course.organizations.add(self.organization_extension.organization) self.course.assign_permission_by_group(self.organization_extension.group) toggle_switch('enable_publisher_email_notifications', True)
def test_delete_program_signal_no_publish(self, delete_program_mock): toggle_switch('publish_program_to_marketing_site', False) self.program.delete() self.assertFalse(delete_program_mock.called)
def test_delete_program_signal_with_publish(self, delete_program_mock): toggle_switch('publish_program_to_marketing_site', True) self.program.delete() delete_program_mock.assert_called_once_with(self.program)
def test_email_with_waffle_switch_disabled(self, send_email_for_change_state): """ Verify that send_email_for_state not called with disable waffle switch.. """ toggle_switch('enable_publisher_email_notifications', False) self.course_run.change_state(target=State.DRAFT) send_email_for_change_state.assert_not_called()
def test_delete_and_no_marketing_site(self): self.program.partner.marketing_site_url_root = None toggle_switch('publish_program_to_marketing_site', True) self.program.delete() self.assert_responses_call_count(0)
def test_email_with_disable_waffle_switch(self, send_email_for_comment): """ Verify that send_email_for_comment not called with disable waffle switch.. """ toggle_switch('enable_publisher_email_notifications', False) self.create_comment(content_object=self.course) send_email_for_comment.assert_not_called()
def test_save_and_no_marketing_site(self): self.program.partner.marketing_site_url_root = None toggle_switch('publish_program_to_marketing_site', True) self.program.title = FuzzyText().fuzz() self.program.save() self.assert_responses_call_count(0)