def test_list(self): """ Verify the endpoint returns a list of all programs. """ url = reverse('api:v1:program-list') ProgramFactory.create_batch(3) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertEqual(response.data['results'], ProgramSerializer(Program.objects.all(), many=True).data)
def test_filter_by_marketable(self, status, is_marketable, expected_query_count): """ Verify the endpoint filters programs to those that are marketable. """ url = self.list_path + '?marketable=1' ProgramFactory(marketing_slug='') programs = ProgramFactory.create_batch(3, status=status) programs.reverse() expected = programs if is_marketable else [] self.assertEqual(list(Program.objects.marketable()), expected) self.assert_list_results(url, expected, expected_query_count)
def test_filter_by_uuids(self): """ Verify that the endpoint filters programs to those matching the provided UUIDs. """ expected = ProgramFactory.create_batch(2) expected.reverse() uuids = [str(p.uuid) for p in expected] url = self.list_path + '?uuids=' + ','.join(uuids) # Create a third program, which should be filtered out. ProgramFactory() self.assert_list_results(url, expected, 8)
def test_data(self): program = ProgramFactory() organization = OrganizationFactory() program.organizations.add(organization) program.save() # NOTE: This serializer expects SearchQuerySet results, so we run a search on the newly-created object # to generate such a result. result = SearchQuerySet().models(Program).filter(uuid=program.uuid)[0] serializer = ProgramSearchSerializer(result) expected = { 'uuid': str(program.uuid), 'name': program.name, 'subtitle': program.subtitle, 'category': program.category, 'marketing_url': program.marketing_url, 'organizations': [OrganizationsMixin.format_organization(organization)], } self.assertDictEqual(serializer.data, expected)
def setUp(self): super(MarketingSitePublisherTests, self).setUp() self.program = ProgramFactory() 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.program.save() # pylint: disable=no-member self.api_client = MarketingSiteAPIClient( self.username, self.password, self.api_root )
def test_get_include_unpublished_programs(self): """ Verify the endpoint returns associated unpublished programs with the 'include_unpublished_programs' flag set to True """ ProgramFactory(courses=[self.course_run.course], status=ProgramStatus.Unpublished) url = reverse('api:v1:course_run-detail', kwargs={'key': self.course_run.key}) url += '?include_unpublished_programs=1' with self.assertNumQueries(17): response = self.client.get(url) assert response.status_code == 200 assert response.data == \ self.serialize_course_run(self.course_run, extra_context={'include_unpublished_programs': True})
def test_partial_term_search(self): """ Test typeahead response with partial term search. """ title = "Learn Data Science" course_run = CourseRunFactory(title=title, course__partner=self.partner) program = ProgramFactory(title=title, status=ProgramStatus.Active, partner=self.partner) query = "Data Sci" response = self.get_response({'q': query}) self.assertEqual(response.status_code, 200) response_data = response.json() expected_response_data = { 'course_runs': [self.serialize_course_run_search(course_run)], 'programs': [self.serialize_program_search(program)] } self.assertDictEqual(response_data, expected_response_data)
def test_typeahead_multiple_authoring_organizations(self): """ Test typeahead response with multiple authoring organizations. """ title = "Design" authoring_organizations = OrganizationFactory.create_batch(3) course_run = CourseRunFactory( title=title, authoring_organizations=authoring_organizations, course__partner=self.partner ) program = ProgramFactory( title=title, authoring_organizations=authoring_organizations, status=ProgramStatus.Active, partner=self.partner ) response = self.get_response({'q': title}) self.assertEqual(response.status_code, 200) response_data = response.json() self.assertDictEqual(response_data, {'course_runs': [self.serialize_course_run_search(course_run)], 'programs': [self.serialize_program_search(program)]})
def test_empty_query(self): """ Verify, when the query (q) parameter is empty, the endpoint behaves as if the parameter was not provided. """ course_run = CourseRunFactory(course__partner=self.partner, status=CourseRunStatus.Published) program = ProgramFactory(partner=self.partner, status=ProgramStatus.Active) response = self.get_response({ 'q': '', 'content_type': ['courserun', 'program'] }) self.assertEqual(response.status_code, 200) response_data = json.loads(response.content.decode('utf-8')) self.assertListEqual(response_data['objects']['results'], [ self.serialize_program(program), self.serialize_course_run(course_run) ])
def create_program(self, orgs): program = ProgramFactory(authoring_organizations=orgs, type=self.program_type) curr = CurriculumFactory(program=program) course1_draft = CourseFactory(draft=True) course1 = CourseFactory(draft_version=course1_draft) _run1a = CourseRunFactory(course=course1) _run1b = CourseRunFactory(course=course1) course2 = CourseFactory() _run2a = CourseRunFactory(course=course2) run2b = CourseRunFactory(course=course2) _mem1 = CurriculumCourseMembershipFactory(curriculum=curr, course=course1) mem2 = CurriculumCourseMembershipFactory(curriculum=curr, course=course2) _ex = CurriculumCourseRunExclusionFactory(course_membership=mem2, course_run=run2b) return program
def test_to_representation(self): request = make_request() program = ProgramFactory(banner_image=make_image_file('test.jpg')) field = StdImageSerializerField() field._context = {'request': request} # pylint: disable=protected-access expected = { size_key: { 'url': '{}{}'.format('http://testserver', getattr(program.banner_image, size_key).url), 'width': program.banner_image.field.variations[size_key]['width'], 'height': program.banner_image.field.variations[size_key]['height'] } for size_key in program.banner_image.field.variations } assert field.to_representation(program.banner_image) == expected
def test_typeahead_authoring_organizations_partial_search(self): """ Test typeahead response with partial organization matching. """ authoring_organizations = OrganizationFactory.create_batch(3) course_run = CourseRunFactory( authoring_organizations=authoring_organizations, course__partner=self.partner) program = ProgramFactory( authoring_organizations=authoring_organizations, partner=self.partner) partial_key = authoring_organizations[0].key[0:5] response = self.get_response({'q': partial_key}) self.assertEqual(response.status_code, 200) expected = { 'course_runs': [self.serialize_course_run(course_run)], 'programs': [self.serialize_program(program)] } self.assertDictEqual(response.data, expected)
def test_results_include_aggregation_key(self): """ Verify the search results only include the aggregation_key for each document. """ course_run = CourseRunFactory(course__partner=self.partner, status=CourseRunStatus.Published) program = ProgramFactory(partner=self.partner, status=ProgramStatus.Active) response = self.get_response() assert response.status_code == 200 response_data = response.json() expected = sorted( [f'courserun:{course_run.course.key}', f'program:{program.uuid}']) actual = sorted([ obj.get('aggregation_key') for obj in response_data['objects']['results'] ]) assert expected == actual
def test_course_ordering(self): """ Verify that courses in a program are ordered by ascending run start date, with ties broken by earliest run enrollment start date. """ request = make_request() course_list = CourseFactory.create_batch(3) # Create a course run with arbitrary start and empty enrollment_start. CourseRunFactory( course=course_list[2], enrollment_start=None, start=datetime(2014, 2, 1), ) # Create a second run with matching start, but later enrollment_start. CourseRunFactory( course=course_list[1], enrollment_start=datetime(2014, 1, 2), start=datetime(2014, 2, 1), ) # Create a third run with later start and enrollment_start. CourseRunFactory( course=course_list[0], enrollment_start=datetime(2014, 2, 1), start=datetime(2014, 3, 1), ) program = ProgramFactory(courses=course_list) serializer = self.serializer_class(program, context={'request': request}) expected = MinimalProgramCourseSerializer( # The expected ordering is the reverse of course_list. course_list[::-1], many=True, context={ 'request': request, 'program': program, 'course_runs': list(program.course_runs) }).data self.assertEqual(serializer.data['courses'], expected)
def create_program(self): organizations = [OrganizationFactory()] person = PersonFactory() course = CourseFactory() CourseRunFactory(course=course, staff=[person]) program = ProgramFactory( courses=[course], authoring_organizations=organizations, credit_backing_organizations=organizations, corporate_endorsements=CorporateEndorsementFactory.create_batch(1), individual_endorsements=EndorsementFactory.create_batch(1), expected_learning_items=ExpectedLearningItemFactory.create_batch( 1), job_outlook_items=JobOutlookItemFactory.create_batch(1), banner_image=make_image_file('test_banner.jpg'), video=VideoFactory()) return program
def test_results_include_aggregation_key(self): """ Verify the search results only include the aggregation_key for each document. """ course_run = CourseRunFactory(course__partner=self.partner, status=CourseRunStatus.Published) program = ProgramFactory(partner=self.partner, status=ProgramStatus.Active) response = self.get_response() assert response.status_code == 200 response_data = json.loads(response.content.decode('utf-8')) expected = sorted([ 'courserun:{}'.format(course_run.course.key), 'program:{}'.format(program.uuid) ]) actual = sorted([ obj.get('aggregation_key') for obj in response_data['objects']['results'] ]) assert expected == actual
def test_program_autocomplete(self, admin_client): """ Verify Program autocomplete returns the data. """ programs = ProgramFactory.create_batch(3) path = reverse('admin_metadata:program-autocomplete') response = admin_client.get(path) data = json.loads(response.content.decode('utf-8')) assert response.status_code == 200 assert len(data['results']) == 3 # Search for substrings of program titles program = programs[0] self.assert_valid_query_result(admin_client, path, program.title[5:], program) program = programs[1] self.assert_valid_query_result(admin_client, path, program.title[5:], program) admin_client.logout() response = admin_client.get(path) data = json.loads(response.content.decode('utf-8')) assert response.status_code == 200 assert len(data['results']) == 0
def create_test_program(self, partner): program = Program.objects.filter(title='test-program') if program: program.first().delete() logger.info('Creating test-program') course = CourseFactory(partner=partner) excluded_course_run = CourseRunFactory(course=course) ProgramFactory( title='test-program', partner=partner, courses=[course], excluded_course_runs=[excluded_course_run], authoring_organizations=[OrganizationFactory(partner=partner)], credit_backing_organizations=[OrganizationFactory(partner=partner)], corporate_endorsements=[CorporateEndorsementFactory()], individual_endorsements=[EndorsementFactory(endorser__partner=partner)], expected_learning_items=[ExpectedLearningItemFactory()], faq=[FAQFactory()], job_outlook_items=[JobOutlookItemFactory()], instructor_ordering=[PersonFactory()], )
def test_affiliate_with_approved_programs(self): """Verify that only the expected Program types are returned, No Masters programs""" response = self.client.get(self.affiliate_url) assert response.status_code == status.HTTP_200_OK root = ET.fromstring(response.content) # Assert that there is only on Program in the returned data even though 2 # are created in setup assert len(root.findall('product')) == 1 print(root.findall('product/[pid="{}"]'.format(self.program.uuid))) self._assert_product_xml( root.findall('product/[pid="{}"]'.format(self.program.uuid))[0], self.program) # Add a new program of approved type and verify it is available mm_program_type = ProgramType.objects.get( slug=ProgramType.MICROMASTERS) mm_program = ProgramFactory(type=mm_program_type, courses=[self.course], banner_image=self.test_image) response = self.client.get(self.affiliate_url) assert response.status_code == status.HTTP_200_OK root = ET.fromstring(response.content) # Assert that there is only on Program in the returned data even though 2 # are created in setup assert len(root.findall('product')) == 2 print(root.findall('product/[pid="{}"]'.format(self.program.uuid))) self._assert_product_xml( root.findall('product/[pid="{}"]'.format(self.program.uuid))[0], self.program) self._assert_product_xml( root.findall('product/[pid="{}"]'.format(mm_program.uuid))[0], mm_program) # Verify that the Masters program is not in the data assert not root.findall('product/[pid="{}"]'.format( self.ms_program.uuid))
def test_to_representation(self): request = make_request() # TODO Create test-only model to avoid unnecessary dependency on Program model. program = ProgramFactory(banner_image=make_image_file('test.jpg')) field = StdImageSerializerField() field._context = {'request': request} # pylint: disable=protected-access expected = { size_key: { 'url': '{}{}'.format('http://testserver', getattr(program.banner_image, size_key).url), 'width': program.banner_image.field.variations[size_key]['width'], 'height': program.banner_image.field.variations[size_key]['height'] } for size_key in program.banner_image.field.variations } self.assertDictEqual(field.to_representation(program.banner_image), expected)
def create_program(self, courses=None): organizations = [OrganizationFactory(partner=self.partner)] person = PersonFactory() if courses is None: courses = [CourseFactory(partner=self.partner)] CourseRunFactory(course=courses[0], staff=[person]) program = ProgramFactory( courses=courses, authoring_organizations=organizations, credit_backing_organizations=organizations, corporate_endorsements=CorporateEndorsementFactory.create_batch(1), individual_endorsements=EndorsementFactory.create_batch(1), expected_learning_items=ExpectedLearningItemFactory.create_batch( 1), job_outlook_items=JobOutlookItemFactory.create_batch(1), instructor_ordering=PersonFactory.create_batch(1), banner_image=make_image_file('test_banner.jpg'), video=VideoFactory(), partner=self.partner) return program
def test_excluded_course_run(self, course_runs): course_list = [] course_run_list = [] excluded_course_run_list = [] non_excluded_course_run_list = [] for run in course_runs: course_run = CourseRunFactory(course__partner=self.partner, course__title=run['title'], status=CourseRunStatus.Published) course_list.append(course_run.course) course_run_list.append(course_run) if run['excluded']: excluded_course_run_list.append(course_run) else: non_excluded_course_run_list.append(course_run) program = ProgramFactory( courses=course_list, status=ProgramStatus.Active, excluded_course_runs=excluded_course_run_list ) self.reindex_courses(program) with self.assertNumQueries(5): response = self.get_response('software', path=self.list_path) assert response.status_code == 200 response_data = response.json() assert response_data['count'] == len(course_run_list) for result in response_data['results']: for course_run in excluded_course_run_list: if result.get('title') == course_run.title: assert result.get('program_types') == [] for course_run in non_excluded_course_run_list: if result.get('title') == course_run.title: assert result.get('program_types') == course_run.program_types
def test_query_count_exclude_expired_course_run(self, exclude_expired, expected_queries): """ Verify that there is no query explosion when excluding expired course runs. """ program = ProgramFactory(partner=self.partner, status=ProgramStatus.Active) course_run = CourseRunFactory(course__partner=self.partner, status=CourseRunStatus.Published) course_run2 = CourseRunFactory(course=course_run.course, status=CourseRunStatus.Published) course_run3 = CourseRunFactory(course=course_run.course, status=CourseRunStatus.Published) course_run4 = CourseRunFactory(course=course_run.course, status=CourseRunStatus.Published) self.reindex_courses(program) query = {'partner': self.partner.short_code} if exclude_expired: query['exclude_expired_course_run'] = 'True' # Filter results by partner with self.assertNumQueries(expected_queries): response = self.get_response(query, endpoint='api:v1:search-all-list') assert response.status_code == 200 response_data = response.json() expected = [ self.serialize_course_run_search(run) for run in (course_run, course_run2, course_run3, course_run4) ] + [ self.serialize_program_search(program), # We need to render the json, and then parse it again, to get all of the formatted # data the same as the data coming out of search. json.loads(JSONRenderer().render( self.serialize_course_search( course_run.course)).decode('utf-8')), ] self.assertCountEqual(response_data['results'], expected)
def create_program(self): organizations = OrganizationFactory.create_batch(2) person = PersonFactory() courses = CourseFactory.create_batch(3) for course in courses: CourseRunFactory.create_batch(2, course=course, staff=[person], start=datetime.now()) return ProgramFactory( courses=courses, authoring_organizations=organizations, credit_backing_organizations=organizations, corporate_endorsements=CorporateEndorsementFactory.create_batch(1), individual_endorsements=EndorsementFactory.create_batch(1), expected_learning_items=ExpectedLearningItemFactory.create_batch( 1), job_outlook_items=JobOutlookItemFactory.create_batch(1), banner_image=make_image_file('test_banner.jpg'), video=VideoFactory(), order_courses_by_start_date=False, )
def test_excluded_course_run(self, course_runs): course_list = [] course_run_list = [] excluded_course_run_list = [] non_excluded_course_run_list = [] for run in course_runs: course_run = CourseRunFactory(course__partner=self.partner, course__title=run['title'], status=CourseRunStatus.Published) course_list.append(course_run.course) course_run_list.append(course_run) if run['excluded']: excluded_course_run_list.append(course_run) else: non_excluded_course_run_list.append(course_run) ProgramFactory(courses=course_list, status=ProgramStatus.Active, excluded_course_runs=excluded_course_run_list) with self.assertNumQueries(4): response = self.get_response('software', faceted=False) self.assertEqual(response.status_code, 200) response_data = response.json() self.assertEqual(response_data['count'], len(course_run_list)) for result in response_data['results']: for course_run in excluded_course_run_list: if result.get('title') == course_run.title: self.assertEqual(result.get('program_types'), []) for course_run in non_excluded_course_run_list: if result.get('title') == course_run.title: self.assertEqual(result.get('program_types'), course_run.program_types)
def test_typeahead_partner_filter(self): """ Ensure that a partner param limits results to that partner. """ course_runs = [] programs = [] for partner in ['edx', 'other']: title = 'Belongs to partner ' + partner partner = PartnerFactory(short_code=partner) course_runs.append( CourseRunFactory(title=title, course=CourseFactory(partner=partner))) programs.append( ProgramFactory(title=title, partner=partner, status=ProgramStatus.Active)) response = self.get_response({'q': 'partner'}, 'edx') self.assertEqual(response.status_code, 200) edx_course_run = course_runs[0] edx_program = programs[0] self.assertDictEqual( response.data, { 'course_runs': [self.serialize_course_run(edx_course_run)], 'programs': [self.serialize_program(edx_program)] })
def test_typeahead_authoring_organizations_partial_search(self): """ Test typeahead response with partial organization matching. """ authoring_organizations = OrganizationFactory.create_batch(3) course_run = CourseRunFactory.create(course__partner=self.partner) program = ProgramFactory.create(partner=self.partner) for authoring_organization in authoring_organizations: course_run.authoring_organizations.add(authoring_organization) program.authoring_organizations.add(authoring_organization) course_run.save() program.save() partial_key = authoring_organizations[0].key[0:5] response = self.get_response({'q': partial_key}) self.assertEqual(response.status_code, 200) # This call is flaky in Travis. It is reliable locally, but occasionally in our CI environment, # this call won't contain the data for course_runs and programs. Instead of relying on the factories # we now explicitly add the authoring organizations to a course_run and program and call .save() # in order to update the search indexes. expected = { 'course_runs': [self.serialize_course_run_search(course_run)], 'programs': [self.serialize_program_search(program)] } self.assertDictEqual(response.data, expected)
def test_special_character_synonyms(self): """ Test that synonyms work with special characters (non ascii) """ ProgramFactory(title='spanish', partner=self.partner) response1 = self.process_response({'q': 'spanish'}) response2 = self.process_response({'q': 'español'}) self.assertDictEqual(response1, response2)
def setUp(self): super(UploadToFieldNamePathTests, self).setUp() self.program = ProgramFactory()
def test_to_representation(self): """ Should be using provided serializer, rather than the slug """ program = ProgramFactory() serializer = SlugRelatedFieldWithReadSerializer(slug_field='uuid', queryset=Program.objects.all(), read_serializer=ProgramSerializer()) self.assertIsInstance(serializer.to_representation(program), dict)
def test_update_node_alias(self): """ Verify that the publisher attempts to create a new alias when necessary and deletes an old alias, if one existed, and that appropriate exceptions are raised for non-200 status codes. """ # No previous object is provided. Create a new node and make sure # title alias created, by default, based on the title is deleted # and a new alias based on marketing slug is created. self.mock_api_client() self.mock_get_alias_form() self.mock_get_delete_form(self.obj.title) self.mock_delete_alias() self.mock_get_delete_form(self.obj.marketing_slug) self.mock_add_alias() self.publisher.update_node_alias(self.obj, self.node_id, None) assert responses.calls[-1].request.url == '{}/add'.format( self.publisher.alias_api_base) responses.reset() # Same scenario, but this time a non-200 status code is returned during # alias creation. An exception should be raised. self.mock_api_client() self.mock_get_alias_form() self.mock_get_delete_form(self.obj.title) self.mock_delete_alias() self.mock_get_delete_form(self.obj.marketing_slug) self.mock_add_alias(status=500) with pytest.raises(AliasCreateError): self.publisher.update_node_alias(self.obj, self.node_id, None) responses.reset() # A previous object is provided, but the marketing slug hasn't changed. # Neither alias creation nor alias deletion should occur. self.mock_api_client() self.mock_get_delete_form(self.obj.marketing_slug) self.publisher.update_node_alias(self.obj, self.node_id, self.obj) responses.reset() # A previous object is provided, and the marketing slug has changed. # Both alias creation and alias deletion should occur. previous_obj = ProgramFactory() self.mock_api_client() self.mock_get_delete_form(self.obj.marketing_slug) self.mock_get_delete_form(previous_obj.marketing_slug) self.mock_delete_alias_form() self.mock_delete_alias() self.mock_get_alias_form() self.mock_get_delete_form(self.obj.marketing_slug) self.mock_add_alias() self.publisher.update_node_alias(self.obj, self.node_id, previous_obj) assert any('/add' in call.request.url for call in responses.calls) assert any( '/list/{}'.format(previous_obj.marketing_slug) in call.request.url for call in responses.calls) responses.reset() # Same scenario, but this time a non-200 status code is returned during # alias deletion. An exception should be raised. self.mock_api_client() self.mock_get_delete_form(self.obj.marketing_slug) self.mock_get_delete_form(previous_obj.marketing_slug) self.mock_delete_alias_form() self.mock_delete_alias(status=500) with pytest.raises(AliasDeleteError): self.publisher.update_node_alias(self.obj, self.node_id, previous_obj)
def test_marketable_exclusions(self): """ Verify the method excludes Programs without a marketing slug. """ ProgramFactory(marketing_slug='') assert Program.objects.marketable().count() == 0
def test_marketable(self, status, is_marketable): """ Verify the method filters Programs to those which are active and have marketing slugs. """ program = ProgramFactory(status=status) expected = [program] if is_marketable else [] assert list(Program.objects.marketable()) == expected
def test_create_command_overwrite(self): # Verify that the program can be overwritten ProgramFactory(title='test-program', subtitle='test') call_command('create_test_program', *self.command_args) test_program = Program.objects.get(title='test-program') assert test_program.subtitle != 'test'
def build_program(self, **kwargs): """ Build a Program that will be visible in search results.""" kwargs.update({'status': ProgramStatus.Active}) return ProgramFactory(**kwargs)
class MarketingSitePublisherTests(MarketingSitePublisherTestMixin): """ Unit test cases for the MarketingSitePublisher """ def setUp(self): super(MarketingSitePublisherTests, self).setUp() self.program = ProgramFactory() 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.program.save() # pylint: disable=no-member self.api_client = MarketingSiteAPIClient( self.username, self.password, self.api_root ) def test_get_node_data(self): publisher = MarketingSitePublisher() publish_data = publisher._get_node_data(self.program, self.user_id) # pylint: disable=protected-access expected = { 'type': str(self.program.type).lower(), 'title': self.program.title, 'field_uuid': str(self.program.uuid), 'uuid': str(self.program.uuid), 'author': { 'id': self.user_id, }, 'status': 1 if self.program.status == ProgramStatus.Active else 0 } self.assertDictEqual(publish_data, expected) @responses.activate def test_get_node_id(self): self.mock_api_client(200) self.mock_node_retrieval(self.program.uuid) publisher = MarketingSitePublisher() node_id = publisher._get_node_id(self.api_client, self.program.uuid) # pylint: disable=protected-access self.assert_responses_call_count(4) self.assertEqual(node_id, self.nid) @responses.activate def test_get_non_existent_node_id(self): self.mock_api_client(200) self.mock_node_retrieval(self.program.uuid, exists=False) publisher = MarketingSitePublisher() node_id = publisher._get_node_id(self.api_client, self.program.uuid) # pylint: disable=protected-access self.assertIsNone(node_id) @responses.activate def test_edit_node(self): self.mock_api_client(200) self.mock_node_edit(200) publisher = MarketingSitePublisher() publish_data = publisher._get_node_data(self.program, self.user_id) # pylint: disable=protected-access publisher._edit_node(self.api_client, self.nid, publish_data) # pylint: disable=protected-access self.assert_responses_call_count(4) @responses.activate def test_edit_node_failed(self): self.mock_api_client(200) self.mock_node_edit(500) publisher = MarketingSitePublisher() publish_data = publisher._get_node_data(self.program, self.user_id) # pylint: disable=protected-access with self.assertRaises(ProgramPublisherException): publisher._edit_node(self.api_client, self.nid, publish_data) # pylint: disable=protected-access @responses.activate def test_create_node(self): self.mock_api_client(200) expected = { 'list': [{ 'nid': self.nid }] } self.mock_node_create(expected, 201) publisher = MarketingSitePublisher() publish_data = publisher._get_node_data(self.program, self.user_id) # pylint: disable=protected-access data = publisher._create_node(self.api_client, publish_data) # pylint: disable=protected-access self.assertEqual(data, expected) @responses.activate def test_create_node_failed(self): self.mock_api_client(200) self.mock_node_create({}, 500) publisher = MarketingSitePublisher() publish_data = publisher._get_node_data(self.program, self.user_id) # pylint: disable=protected-access with self.assertRaises(ProgramPublisherException): publisher._create_node(self.api_client, publish_data) # pylint: disable=protected-access @responses.activate def test_publish_program_create(self): self.mock_api_client(200) expected = { 'list': [{ 'nid': self.nid }] } self.mock_node_retrieval(self.program.uuid, exists=False) self.mock_node_create(expected, 201) publisher = MarketingSitePublisher() publisher.publish_program(self.program) self.assert_responses_call_count(6) @responses.activate def test_publish_program_edit(self): self.mock_api_client(200) self.mock_node_retrieval(self.program.uuid) self.mock_node_edit(200) publisher = MarketingSitePublisher() publisher.publish_program(self.program) self.assert_responses_call_count(6) @responses.activate def test_publish_modified_program(self): self.mock_api_client(200) self.mock_node_retrieval(self.program.uuid) self.mock_node_edit(200) program_before = ProgramFactory() publisher = MarketingSitePublisher(program_before) publisher.publish_program(self.program) self.assert_responses_call_count(6) @responses.activate def test_publish_unmodified_program(self): self.mock_api_client(200) publisher = MarketingSitePublisher(self.program) publisher.publish_program(self.program) self.assert_responses_call_count(0) @responses.activate def test_publish_xseries_program(self): self.program.type = ProgramType.objects.get(name='XSeries') publisher = MarketingSitePublisher() publisher.publish_program(self.program) self.assert_responses_call_count(0) @responses.activate def test_publish_program_no_credential(self): self.program.partner.marketing_site_api_password = None self.program.partner.marketing_site_api_username = None publisher = MarketingSitePublisher() with self.assertRaises(ProgramPublisherException): publisher.publish_program(self.program) self.assert_responses_call_count(0) @responses.activate def test_publish_delete_program(self): self.mock_api_client(200) self.mock_node_retrieval(self.program.uuid) self.mock_node_delete(204) publisher = MarketingSitePublisher() publisher.delete_program(self.program) self.assert_responses_call_count(5) @responses.activate def test_publish_delete_non_existent_program(self): self.mock_api_client(200) self.mock_node_retrieval(self.program.uuid, exists=False) publisher = MarketingSitePublisher() publisher.delete_program(self.program) self.assert_responses_call_count(4)