def test_view_learner(self, status): """ Test that the detail view works correctly for non-ADMINS, and that unpublished and deleted Programs are filtered out. """ filtered_statuses = (ProgramStatus.DELETED, ProgramStatus.UNPUBLISHED) program = ProgramFactory.create(status=status) response = self._make_request(program_id=program.id) self.assertEqual(response.status_code, 404 if status in filtered_statuses else 200) if status not in filtered_statuses: self.assertEqual( response.data, { 'name': program.name, 'subtitle': program.subtitle, 'category': program.category, 'status': status, 'organizations': [], 'course_codes': [], 'id': program.id, 'created': program.created.strftime(DRF_DATE_FORMAT), 'modified': program.modified.strftime(DRF_DATE_FORMAT), 'marketing_slug': program.marketing_slug, 'banner_image_urls': {}, 'uuid': str(program.uuid), } )
def test_view_admin(self, status): """ Test that the detail view works correctly for ADMINS, and that deleted Programs are filtered out. """ program = ProgramFactory.create(status=status) response = self._make_request(program_id=program.id, admin=True) self.assertEqual(response.status_code, 404 if status == ProgramStatus.DELETED else 200) if status != ProgramStatus.DELETED: self.assertEqual( response.data, { u"name": program.name, u"subtitle": program.subtitle, u"category": program.category, u"status": status, u"organizations": [], u"course_codes": [], u"id": program.id, u"created": program.created.strftime(DRF_DATE_FORMAT), u"modified": program.modified.strftime(DRF_DATE_FORMAT), u'marketing_slug': program.marketing_slug, u'banner_image_urls': {} } )
def test_invalid_nested_run_modes(self, invalid_mode): """ Ensure that invalid nested run mode data causes a 400 response. """ org = OrganizationFactory.create() program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) course_code = CourseCodeFactory.create(organization=org) patch_data = { u'course_codes': [ { u'key': course_code.key, u'organization': { u'key': course_code.organization.key, }, u'run_modes': [invalid_mode], }, ], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 400)
def assert_correct_default_banner_image_urls(self, url_prepend='', set_program_banner=False): """ DRY test helper. Ensure that the serializer generates a complete set of absolute URLs for the default banner_image when the banner image on program is not set. If the flag set_program_banner is defined, then make sure the banner image for program is set and returned """ default_program_value = ProgramDefaultFactory.create() default_program_value.banner_image = make_banner_image_file( 'default_test_filename.jpg') default_program_value.save() program = ProgramFactory.create(status=ProgramStatus.ACTIVE) if set_program_banner: program.banner_image = make_banner_image_file('test_filename.jpg') program.save() response = self._make_request(program_id=program.id) self.assertEqual(response.status_code, 200) banner_image_instance = default_program_value.banner_image if set_program_banner: banner_image_instance = program.banner_image expected_urls = { 'w{}h{}'.format(*size): '{}{}__{}x{}.jpg'.format(url_prepend, banner_image_instance.url, *size) for size in banner_image_instance.field.sizes } self.assertEqual(response.data[u'banner_image_urls'], expected_urls)
def test_view_admin(self, status): """ Test that the detail view works correctly for ADMINS, and that deleted Programs are filtered out. """ program = ProgramFactory.create(status=status) response = self._make_request(program_id=program.id, admin=True) self.assertEqual(response.status_code, 404 if status == ProgramStatus.DELETED else 200) if status != ProgramStatus.DELETED: self.assertEqual( response.data, { 'name': program.name, 'subtitle': program.subtitle, 'category': program.category, 'status': status, 'organizations': [], 'course_codes': [], 'id': program.id, 'created': program.created.strftime(DRF_DATE_FORMAT), 'modified': program.modified.strftime(DRF_DATE_FORMAT), 'marketing_slug': program.marketing_slug, 'banner_image_urls': {}, 'uuid': str(program.uuid), })
def assert_correct_default_banner_image_urls(self, url_prepend='', set_program_banner=False): """ DRY test helper. Ensure that the serializer generates a complete set of absolute URLs for the default banner_image when the banner image on program is not set. If the flag set_program_banner is defined, then make sure the banner image for program is set and returned """ default_program_value = ProgramDefaultFactory.create() default_program_value.banner_image = make_banner_image_file('default_test_filename.jpg') default_program_value.save() program = ProgramFactory.create(status=ProgramStatus.ACTIVE) if set_program_banner: program.banner_image = make_banner_image_file('test_filename.jpg') program.save() response = self._make_request(program_id=program.id) self.assertEqual(response.status_code, 200) banner_image_instance = default_program_value.banner_image if set_program_banner: banner_image_instance = program.banner_image expected_urls = { 'w{}h{}'.format(*size): '{}{}__{}x{}.jpg'.format( url_prepend, banner_image_instance.url, *size) for size in banner_image_instance.field.sizes } self.assertEqual(response.data['banner_image_urls'], expected_urls)
def test_view_admin(self, status): """ Test that the detail view works correctly for ADMINS, and that deleted Programs are filtered out. """ program = ProgramFactory.create(status=status) response = self._make_request(program_id=program.id, admin=True) self.assertEqual(response.status_code, 404 if status == ProgramStatus.DELETED else 200) if status != ProgramStatus.DELETED: self.assertEqual( response.data, { 'name': program.name, 'subtitle': program.subtitle, 'category': program.category, 'status': status, 'organizations': [], 'course_codes': [], 'id': program.id, 'created': program.created.strftime(DRF_DATE_FORMAT), 'modified': program.modified.strftime(DRF_DATE_FORMAT), 'marketing_slug': program.marketing_slug, 'banner_image_urls': {}, 'uuid': str(program.uuid), } )
def test_view_learner(self, status): """ Test that the detail view works correctly for non-ADMINS, and that unpublished and deleted Programs are filtered out. """ filtered_statuses = (ProgramStatus.DELETED, ProgramStatus.UNPUBLISHED) program = ProgramFactory.create(status=status) response = self._make_request(program_id=program.id) self.assertEqual(response.status_code, 404 if status in filtered_statuses else 200) if status not in filtered_statuses: self.assertEqual( response.data, { u"name": program.name, u"subtitle": program.subtitle, u"category": program.category, u"status": status, u"organizations": [], u"course_codes": [], u"id": program.id, u"created": program.created.strftime(DRF_DATE_FORMAT), u"modified": program.modified.strftime(DRF_DATE_FORMAT), u'marketing_slug': program.marketing_slug, u'banner_image_urls': {} })
def test_program_completion_filtering(self, status, is_admin): """Verify that program candidates for completion are filtered.""" program = ProgramFactory.create(status=status) org = OrganizationFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) course_code = CourseCodeFactory.create(organization=org) program_course_code = ProgramCourseCodeFactory.create( program=program, course_code=course_code ) course_key = 'org/code/run' ProgramCourseRunModeFactory.create( course_key=course_key, program_course_code=program_course_code, ) complete_run_modes = {'completed_courses': [ {'course_id': course_key, 'mode': 'verified'}, ]} response = self._make_request(method='post', complete=True, data=complete_run_modes, admin=is_admin) self.assertEqual(response.status_code, 200) program_ids = response.data['program_ids'] if status in [ProgramStatus.ACTIVE, ProgramStatus.RETIRED]: self.assertEqual(program_ids, [1]) else: # No one should be able to complete deleted or unpublished programs. self.assertEqual(program_ids, [])
def test_update_run_modes(self): """ Ensure that nested run modes can be updated. """ org = OrganizationFactory.create() program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) course_code = CourseCodeFactory.create(organization=org) program_course_code = ProgramCourseCodeFactory.create( program=program, course_code=course_code) for n in range(2): ProgramCourseRunModeFactory.create( program_course_code=program_course_code, course_key='course-v1:org+course+run-{}'.format(n)) # PATCH the course code's run modes: send one matching an existing record and a second new one patch_data = { u'course_codes': [ { u'key': course_code.key, u'organization': { u'key': course_code.organization.key, }, u'run_modes': [ { u'course_key': u'course-v1:org+course+run-0', u'mode_slug': u'verified', }, { u'course_key': u'course-v1:org+course+run-2', u'mode_slug': u'verified', u'start_date': u'2015-12-09T21:20:26.491639Z', }, ], }, ], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 200) # check response data patched_run_modes = response.data['course_codes'][0]['run_modes'] self.assertEqual( [u'course-v1:org+course+run-0', u'course-v1:org+course+run-2'], sorted([rm[u'course_key'] for rm in patched_run_modes])) # check models (ensure things were saved properly) db_run_modes = ProgramCourseRunMode.objects.filter( program_course_code=program_course_code) self.assertEqual( [u'course-v1:org+course+run-0', u'course-v1:org+course+run-2'], sorted([rm.course_key for rm in db_run_modes]))
def test_patch_non_admin(self): """ Verify that the API only allows admins to issue PATCH requests. """ # Only allow admin to update program program = ProgramFactory.create() data = json.dumps({"name": "dummy-name"}) response = self._make_request(method="patch", program_id=program.id, data=data) self.assertEqual(response.status_code, 403)
def test_create_duplicated_name(self): """ Ensure that it is not allowed to create a Program with a duplicate name """ ProgramFactory(name="duplicated name") # saved directly to db data = self._build_post_data(name="duplicated name") response = self._make_request(method='post', data=data, admin=True) self.assertEqual(response.status_code, 400) self.assertIn("must be unique", response.data["name"][0])
def test_update_run_modes(self): """ Ensure that nested run modes can be updated. """ org = OrganizationFactory.create() program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) course_code = CourseCodeFactory.create(organization=org) program_course_code = ProgramCourseCodeFactory.create(program=program, course_code=course_code) for n in range(2): ProgramCourseRunModeFactory.create( program_course_code=program_course_code, course_key='course-v1:org+course+run-{}'.format(n) ) # PATCH the course code's run modes: send one matching an existing record and a second new one patch_data = { 'course_codes': [ { 'key': course_code.key, 'organization': { 'key': course_code.organization.key, }, 'run_modes': [ { 'course_key': 'course-v1:org+course+run-0', 'mode_slug': 'verified', }, { 'course_key': 'course-v1:org+course+run-2', 'mode_slug': 'verified', 'start_date': '2015-12-09T21:20:26.491639Z', }, ], }, ], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 200) # check response data patched_run_modes = response.data['course_codes'][0]['run_modes'] self.assertEqual( ['course-v1:org+course+run-0', 'course-v1:org+course+run-2'], sorted([rm['course_key'] for rm in patched_run_modes]) ) # check models (ensure things were saved properly) db_run_modes = ProgramCourseRunMode.objects.filter(program_course_code=program_course_code) self.assertEqual( ['course-v1:org+course+run-0', 'course-v1:org+course+run-2'], sorted([rm.course_key for rm in db_run_modes]) )
def test_patch(self, patch_data): """ Verify that the API is able to apply PATCH requests. """ program = ProgramFactory.create() response = self._make_request(method="patch", program_id=program.id, data=patch_data, admin=True) self.assertEqual(response.status_code, 200) program = Program.objects.get(id=program.id) for field, value in patch_data.viewitems(): self.assertEqual(getattr(program, field), value)
def test_update_course_codes(self): """ Ensure that nested program course codes can be updated. """ org = OrganizationFactory.create(key='test-org-key') program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) for n in range(3): course_code = CourseCodeFactory.create( key='test-course-key-{}'.format(n), display_name='test-course-display_name-{}'.format(n), organization=org, ) # associate the first and second course codes, not the third. if n < 2: ProgramCourseCodeFactory.create(program=program, course_code=course_code) # PATCH the course codes: send one already associated, and another not yet associated patch_data = { u'course_codes': [ { u'key': 'test-course-key-0', u'organization': { u'key': 'test-org-key', }, }, { u'key': 'test-course-key-2', u'organization': { u'key': 'test-org-key', }, }, ], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 200) # check response data patched_course_codes = response.data['course_codes'] self.assertEqual([u'test-course-key-0', u'test-course-key-2'], sorted([cc[u'key'] for cc in patched_course_codes])) # check models (ensure things were saved properly) db_course_codes = ProgramCourseCode.objects.filter( program__id=program.id) self.assertEqual([u'test-course-key-0', u'test-course-key-2'], sorted( [pcc.course_code.key for pcc in db_course_codes]))
def test_invalid_nested_course_codes(self, invalid_code): """ Ensure that invalid nested course code data causes a 400 response. """ org = OrganizationFactory.create(key='test-org-key') program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) CourseCodeFactory.create(key='test-course-key', organization=org) patch_data = { 'course_codes': [invalid_code], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 400)
def test_update_course_codes(self): """ Ensure that nested program course codes can be updated. """ org = OrganizationFactory.create(key='test-org-key') program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) for n in range(3): course_code = CourseCodeFactory.create( key='test-course-key-{}'.format(n), display_name='test-course-display_name-{}'.format(n), organization=org, ) # associate the first and second course codes, not the third. if n < 2: ProgramCourseCodeFactory.create(program=program, course_code=course_code) # PATCH the course codes: send one already associated, and another not yet associated patch_data = { 'course_codes': [ { 'key': 'test-course-key-0', 'organization': { 'key': 'test-org-key', }, }, { 'key': 'test-course-key-2', 'organization': { 'key': 'test-org-key', }, }, ], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 200) # check response data patched_course_codes = response.data['course_codes'] self.assertEqual( ['test-course-key-0', 'test-course-key-2'], sorted([cc['key'] for cc in patched_course_codes]) ) # check models (ensure things were saved properly) db_course_codes = ProgramCourseCode.objects.filter(program__id=program.id) self.assertEqual( ['test-course-key-0', 'test-course-key-2'], sorted([pcc.course_code.key for pcc in db_course_codes]) )
def test_list_admin(self): """ Verify the list includes all Programs, except those with DELETED status, for ADMINS. """ # create one Program of each status for status in STATUSES: ProgramFactory(name="{} program".format(status), status=status) response = self._make_request(admin=True) self.assertEqual(response.status_code, 200) results = response.data['results'] self.assertEqual(len(results), 3) self.assertNotIn(ProgramStatus.DELETED, set(obj["status"] for obj in results))
def test_status_list_filter(self, query_status): """ Verify that list results can be filtered by a 'status' query string argument. """ # create one Program of each status for status in STATUSES: ProgramFactory(name="{} program".format(status), status=status) response = self._make_request(admin=True, data={'status': query_status}) self.assertEqual(response.status_code, 200) results = response.data['results'] self.assertEqual(len(results), 1) self.assertEqual(results[0]['status'], query_status)
def test_list_learner(self): """ Verify the list includes only UNPUBLISHED and RETIRED Programs, for LEARNERS. """ # create one Program of each status for status in STATUSES: ProgramFactory(name="{} program".format(status), status=status) response = self._make_request() self.assertEqual(response.status_code, 200) results = response.data['results'] self.assertEqual(len(results), 2) statuses = set(obj["status"] for obj in results) self.assertNotIn(ProgramStatus.DELETED, statuses) self.assertNotIn(ProgramStatus.UNPUBLISHED, statuses)
def test_org_list_filter(self): """ Verify that list results can be filtered by an 'organization' query string argument. """ org_keys = ("org1", "org2") for org_key in org_keys: org = OrganizationFactory.create(key=org_key) program = ProgramFactory.create() ProgramOrganizationFactory.create(organization=org, program=program) for org_key in org_keys: response = self._make_request(admin=True, data={'organization': org_key}) self.assertEqual(response.status_code, 200) results = response.data['results'] self.assertEqual(len(results), 1) self.assertEqual(results[0]['organizations'][0]['key'], org_key)
def assert_correct_banner_image_urls(self, url_prepend=''): """ DRY test helper. Ensure that the serializer generates a complete set of absolute URLs for the banner_image when one is set. """ program = ProgramFactory.create(status=ProgramStatus.ACTIVE) program.banner_image = make_banner_image_file('test_filename.jpg') program.save() response = self._make_request(program_id=program.id) self.assertEqual(response.status_code, 200) expected_urls = { 'w{}h{}'.format(*size): '{}{}__{}x{}.jpg'.format(url_prepend, program.banner_image.url, *size) for size in program.banner_image.field.sizes } self.assertEqual(response.data['banner_image_urls'], expected_urls)
def test_invalid_nested_course_codes(self, invalid_code): """ Ensure that invalid nested course code data causes a 400 response. """ org = OrganizationFactory.create(key='test-org-key') program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) CourseCodeFactory.create(key='test-course-key', organization=org) patch_data = { u'course_codes': [invalid_code], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 400)
def assert_correct_banner_image_urls(self, url_prepend=''): """ DRY test helper. Ensure that the serializer generates a complete set of absolute URLs for the banner_image when one is set. """ program = ProgramFactory.create(status=ProgramStatus.ACTIVE) program.banner_image = make_banner_image_file('test_filename.jpg') program.save() response = self._make_request(program_id=program.id) self.assertEqual(response.status_code, 200) expected_urls = { 'w{}h{}'.format(*size): '{}{}__{}x{}.jpg'.format(url_prepend, program.banner_image.url, *size) for size in program.banner_image.field.sizes } self.assertEqual(response.data[u'banner_image_urls'], expected_urls)
def test_create_course_codes(self): """ Ensure that course codes can be created on the fly from request data when referenced as part of nested program updates. """ org = OrganizationFactory.create(key='test-org-key') program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) patch_data = { 'course_codes': [ { 'key': 'test-course-code-key', 'display_name': 'test-course-code-name', 'organization': { 'key': 'test-org-key', }, }, ], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 200) # check response data response_course_code = response.data['course_codes'][0] self.assertEqual(response_course_code['key'], 'test-course-code-key') self.assertEqual(response_course_code['display_name'], 'test-course-code-name') self.assertEqual(response_course_code['organization']['key'], 'test-org-key') # check models (ensure things were saved properly) db_course_code = CourseCode.objects.get( key='test-course-code-key', display_name='test-course-code-name', organization__key='test-org-key', ) self.assertEqual(db_course_code.programs.count(), 1) self.assertEqual(db_course_code.programs.first(), program)
def test_update_course_code_display_name(self): """ Ensure that course codes' display names can be updated on the fly from request data when referenced as part of nested program updates. """ org = OrganizationFactory.create(key='test-org-key') program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) CourseCodeFactory.create( key='test-course-code-key', display_name='original-display-name', organization=org, ) patch_data = { u'course_codes': [ { u'key': 'test-course-code-key', u'display_name': 'changed-display-name', u'organization': { u'key': 'test-org-key', }, }, ], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 200) # check response data response_course_code = response.data['course_codes'][0] self.assertEqual(response_course_code['display_name'], 'changed-display-name') # check models (ensure things were saved properly) CourseCode.objects.get( key='test-course-code-key', display_name='changed-display-name', organization__key='test-org-key', )
def test_invalid_nested_run_modes(self, invalid_mode): """ Ensure that invalid nested run mode data causes a 400 response. """ org = OrganizationFactory.create() program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) course_code = CourseCodeFactory.create(organization=org) patch_data = { 'course_codes': [ { 'key': course_code.key, 'organization': { 'key': course_code.organization.key, }, 'run_modes': [invalid_mode], }, ], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 400)
def test_program_completion_filtering(self, status, is_admin): """Verify that program candidates for completion are filtered.""" program = ProgramFactory.create(status=status) org = OrganizationFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) course_code = CourseCodeFactory.create(organization=org) program_course_code = ProgramCourseCodeFactory.create( program=program, course_code=course_code) course_key = 'org/code/run' ProgramCourseRunModeFactory.create( course_key=course_key, program_course_code=program_course_code, ) complete_run_modes = { 'completed_courses': [ { 'course_id': course_key, 'mode': 'verified' }, ] } response = self._make_request(method='post', complete=True, data=complete_run_modes, admin=is_admin) self.assertEqual(response.status_code, 200) program_ids = response.data['program_ids'] if status in [ProgramStatus.ACTIVE, ProgramStatus.RETIRED]: self.assertEqual(program_ids, [1]) else: # No one should be able to complete deleted or unpublished programs. self.assertEqual(program_ids, [])
def test_update_course_code_display_name(self): """ Ensure that course codes' display names can be updated on the fly from request data when referenced as part of nested program updates. """ org = OrganizationFactory.create(key='test-org-key') program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) CourseCodeFactory.create( key='test-course-code-key', display_name='original-display-name', organization=org, ) patch_data = { 'course_codes': [ { 'key': 'test-course-code-key', 'display_name': 'changed-display-name', 'organization': { 'key': 'test-org-key', }, }, ], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 200) # check response data response_course_code = response.data['course_codes'][0] self.assertEqual(response_course_code['display_name'], 'changed-display-name') # check models (ensure things were saved properly) CourseCode.objects.get( key='test-course-code-key', display_name='changed-display-name', organization__key='test-org-key', )
def test_create_course_codes(self): """ Ensure that course codes can be created on the fly from request data when referenced as part of nested program updates. """ org = OrganizationFactory.create(key='test-org-key') program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) patch_data = { u'course_codes': [ { u'key': 'test-course-code-key', u'display_name': 'test-course-code-name', u'organization': { u'key': 'test-org-key', }, }, ], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 200) # check response data response_course_code = response.data['course_codes'][0] self.assertEqual(response_course_code['key'], 'test-course-code-key') self.assertEqual(response_course_code['display_name'], 'test-course-code-name') self.assertEqual(response_course_code['organization']['key'], 'test-org-key') # check models (ensure things were saved properly) db_course_code = CourseCode.objects.get( key='test-course-code-key', display_name='test-course-code-name', organization__key='test-org-key', ) self.assertEqual(db_course_code.programs.count(), 1) self.assertEqual(db_course_code.programs.first(), program)
def test_view_admin(self, status): """ Test that the detail view works correctly for ADMINS, and that deleted Programs are filtered out. """ program = ProgramFactory.create(status=status) response = self._make_request(program_id=program.id, admin=True) self.assertEqual(response.status_code, 404 if status == ProgramStatus.DELETED else 200) if status != ProgramStatus.DELETED: self.assertEqual( response.data, { u"name": program.name, u"subtitle": program.subtitle, u"category": program.category, u"status": status, u"organizations": [], u"course_codes": [], u"id": program.id, u"created": program.created.strftime(DRF_DATE_FORMAT), u"modified": program.modified.strftime(DRF_DATE_FORMAT), u'marketing_slug': program.marketing_slug, u'banner_image_urls': {} })
def test_view_with_nested(self): """ Ensure that nested serializers are working in program detail views. """ start_date = datetime.datetime.now(tz=pytz.UTC) course_key = "edX/DemoX/Demo_Course" run_key = "Demo_Course" org = OrganizationFactory.create(key="test-org-key", display_name="test-org-display_name") program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) course_code = CourseCodeFactory.create( key="test-course-key", display_name="test-course-display_name", organization=org, ) program_course_code = ProgramCourseCodeFactory.create(program=program, course_code=course_code) ProgramCourseRunModeFactory.create( course_key=course_key, program_course_code=program_course_code, start_date=start_date ) response = self._make_request(program_id=program.id, admin=True) self.assertEqual(response.status_code, 200) self.assertEqual( response.data, { 'name': program.name, 'subtitle': program.subtitle, 'category': program.category, 'status': ProgramStatus.UNPUBLISHED, 'organizations': [ { 'key': 'test-org-key', 'display_name': 'test-org-display_name', } ], 'course_codes': [ { 'key': 'test-course-key', 'display_name': 'test-course-display_name', 'organization': { 'key': 'test-org-key', 'display_name': 'test-org-display_name', }, 'run_modes': [ { 'course_key': course_key, 'run_key': run_key, 'mode_slug': 'verified', 'sku': '', 'start_date': start_date.strftime(DRF_DATE_FORMAT) } ], } ], 'id': program.id, 'created': program.created.strftime(DRF_DATE_FORMAT), 'modified': program.modified.strftime(DRF_DATE_FORMAT), 'marketing_slug': program.marketing_slug, 'banner_image_urls': {}, 'uuid': unicode(program.uuid), } )
def _build_post_data(**kwargs): """ Build and return a dict representation to use for POST / create. """ instance = ProgramFactory.build(**kwargs) return {k: getattr(instance, k) for k in POST_FIELDS}
def test_create_course_code_with_run_modes(self): """ Ensure that nested program course codes and run modes can be correctly created during updates. """ org = OrganizationFactory.create() program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) course_codes = [ CourseCodeFactory.create(organization=org, key='test-cc-{}'.format(i)) for i in range(2) ] # associate two course codes with two run modes each, in one PATCH request. patch_data = { u'course_codes': [ { u'key': course_codes[0].key, u'organization': { u'key': course_codes[0].organization.key, }, u'run_modes': [ { u'course_key': u'course-v1:org+{}+run-0'.format( course_codes[0].key), u'mode_slug': u'verified', u'start_date': u'2015-12-09T21:20:26.491639Z', }, { u'course_key': u'course-v1:org+{}+run-1'.format( course_codes[0].key), u'mode_slug': u'verified', u'start_date': u'2015-12-09T21:20:26.491639Z', }, ], }, { u'key': course_codes[1].key, u'organization': { u'key': course_codes[1].organization.key, }, u'run_modes': [ { u'course_key': u'course-v1:org+{}+run-0'.format( course_codes[1].key), u'mode_slug': u'verified', u'start_date': u'2015-12-09T21:20:26.491639Z', }, { u'course_key': u'course-v1:org+{}+run-1'.format( course_codes[1].key), u'mode_slug': u'verified', u'start_date': u'2015-12-09T21:20:26.491639Z', }, ], }, ], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 200) # check response data response_course_codes = response.data['course_codes'] response_course_codes = sorted(response_course_codes, key=lambda d: d['key']) for course_code, response_course_code in zip(course_codes, response_course_codes): self.assertEqual(response_course_code['key'], course_code.key) self.assertEqual(response_course_code['organization']['key'], course_code.organization.key) self.assertEqual(len(response_course_code['run_modes']), 2) # check db values. the following call should throw DoesNotExist if things didn't go as expected db_program_course_code = ProgramCourseCode.objects.get( program=program, course_code=course_code) run_modes = sorted(db_program_course_code.run_modes.all(), key=lambda o: o.course_key) for i, run_mode in enumerate(run_modes): self.assertEqual( 'course-v1:org+{}+run-{}'.format(course_code.key, i), run_mode.course_key)
def test_create_course_code_with_run_modes(self): """ Ensure that nested program course codes and run modes can be correctly created during updates. """ org = OrganizationFactory.create() program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) course_codes = [CourseCodeFactory.create(organization=org, key='test-cc-{}'.format(i)) for i in range(2)] # associate two course codes with two run modes each, in one PATCH request. patch_data = { 'course_codes': [ { 'key': course_codes[0].key, 'organization': { 'key': course_codes[0].organization.key, }, 'run_modes': [ { 'course_key': 'course-v1:org+{}+run-0'.format(course_codes[0].key), 'mode_slug': 'verified', 'start_date': '2015-12-09T21:20:26.491639Z', }, { 'course_key': 'course-v1:org+{}+run-1'.format(course_codes[0].key), 'mode_slug': 'verified', 'start_date': '2015-12-09T21:20:26.491639Z', }, ], }, { 'key': course_codes[1].key, 'organization': { 'key': course_codes[1].organization.key, }, 'run_modes': [ { 'course_key': 'course-v1:org+{}+run-0'.format(course_codes[1].key), 'mode_slug': 'verified', 'start_date': '2015-12-09T21:20:26.491639Z', }, { 'course_key': 'course-v1:org+{}+run-1'.format(course_codes[1].key), 'mode_slug': 'verified', 'start_date': '2015-12-09T21:20:26.491639Z', }, ], }, ], } response = self._make_request(program_id=program.id, admin=True, method='patch', data=patch_data) self.assertEqual(response.status_code, 200) # check response data response_course_codes = response.data['course_codes'] response_course_codes = sorted(response_course_codes, key=lambda d: d['key']) for course_code, response_course_code in zip(course_codes, response_course_codes): self.assertEqual(response_course_code['key'], course_code.key) self.assertEqual(response_course_code['organization']['key'], course_code.organization.key) self.assertEqual(len(response_course_code['run_modes']), 2) # check db values. the following call should throw DoesNotExist if things didn't go as expected db_program_course_code = ProgramCourseCode.objects.get(program=program, course_code=course_code) run_modes = sorted(db_program_course_code.run_modes.all(), key=lambda o: o.course_key) for i, run_mode in enumerate(run_modes): self.assertEqual('course-v1:org+{}+run-{}'.format(course_code.key, i), run_mode.course_key)
def test_view_with_nested(self): """ Ensure that nested serializers are working in program detail views. """ start_date = datetime.datetime.now(tz=pytz.UTC) course_key = "edX/DemoX/Demo_Course" run_key = "Demo_Course" org = OrganizationFactory.create(key="test-org-key", display_name="test-org-display_name") program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) course_code = CourseCodeFactory.create( key="test-course-key", display_name="test-course-display_name", organization=org, ) program_course_code = ProgramCourseCodeFactory.create( program=program, course_code=course_code) ProgramCourseRunModeFactory.create( course_key=course_key, program_course_code=program_course_code, start_date=start_date) response = self._make_request(program_id=program.id, admin=True) self.assertEqual(response.status_code, 200) self.assertEqual( response.data, { u"name": program.name, u"subtitle": program.subtitle, u"category": program.category, u"status": ProgramStatus.UNPUBLISHED, u"organizations": [{ u"key": "test-org-key", u"display_name": "test-org-display_name", }], u"course_codes": [{ u"key": "test-course-key", u"display_name": "test-course-display_name", u"organization": { u"key": "test-org-key", u"display_name": "test-org-display_name", }, u"run_modes": [{ u"course_key": course_key, u"run_key": run_key, u"mode_slug": "verified", u"sku": '', u"start_date": start_date.strftime(DRF_DATE_FORMAT) }], }], u"id": program.id, u"created": program.created.strftime(DRF_DATE_FORMAT), u"modified": program.modified.strftime(DRF_DATE_FORMAT), u'marketing_slug': program.marketing_slug, u'banner_image_urls': {} })
def test_view_with_nested(self): """ Ensure that nested serializers are working in program detail views. """ start_date = datetime.datetime.now(tz=pytz.UTC) course_key = "edX/DemoX/Demo_Course" run_key = "Demo_Course" org = OrganizationFactory.create(key="test-org-key", display_name="test-org-display_name") program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) course_code = CourseCodeFactory.create( key="test-course-key", display_name="test-course-display_name", organization=org, ) program_course_code = ProgramCourseCodeFactory.create( program=program, course_code=course_code) ProgramCourseRunModeFactory.create( course_key=course_key, program_course_code=program_course_code, start_date=start_date) response = self._make_request(program_id=program.id, admin=True) self.assertEqual(response.status_code, 200) self.assertEqual( response.data, { 'name': program.name, 'subtitle': program.subtitle, 'category': program.category, 'status': ProgramStatus.UNPUBLISHED, 'organizations': [{ 'key': 'test-org-key', 'display_name': 'test-org-display_name', }], 'course_codes': [{ 'key': 'test-course-key', 'display_name': 'test-course-display_name', 'organization': { 'key': 'test-org-key', 'display_name': 'test-org-display_name', }, 'run_modes': [{ 'course_key': course_key, 'run_key': run_key, 'mode_slug': 'verified', 'sku': '', 'start_date': start_date.strftime(DRF_DATE_FORMAT) }], }], 'id': program.id, 'created': program.created.strftime(DRF_DATE_FORMAT), 'modified': program.modified.strftime(DRF_DATE_FORMAT), 'marketing_slug': program.marketing_slug, 'banner_image_urls': {}, 'uuid': unicode(program.uuid), })
def test_view_with_nested(self): """ Ensure that nested serializers are working in program detail views. """ start_date = datetime.datetime.now(tz=pytz.UTC) course_key = "edX/DemoX/Demo_Course" run_key = "Demo_Course" org = OrganizationFactory.create(key="test-org-key", display_name="test-org-display_name") program = ProgramFactory.create() ProgramOrganizationFactory.create(program=program, organization=org) course_code = CourseCodeFactory.create( key="test-course-key", display_name="test-course-display_name", organization=org, ) program_course_code = ProgramCourseCodeFactory.create(program=program, course_code=course_code) ProgramCourseRunModeFactory.create( course_key=course_key, program_course_code=program_course_code, start_date=start_date ) response = self._make_request(program_id=program.id, admin=True) self.assertEqual(response.status_code, 200) self.assertEqual( response.data, { u"name": program.name, u"subtitle": program.subtitle, u"category": program.category, u"status": ProgramStatus.UNPUBLISHED, u"organizations": [ { u"key": "test-org-key", u"display_name": "test-org-display_name", } ], u"course_codes": [ { u"key": "test-course-key", u"display_name": "test-course-display_name", u"organization": { u"key": "test-org-key", u"display_name": "test-org-display_name", }, u"run_modes": [ { u"course_key": course_key, u"run_key": run_key, u"mode_slug": "verified", u"sku": '', u"start_date": start_date.strftime(DRF_DATE_FORMAT) } ], } ], u"id": program.id, u"created": program.created.strftime(DRF_DATE_FORMAT), u"modified": program.modified.strftime(DRF_DATE_FORMAT), u'marketing_slug': program.marketing_slug, u'banner_image_urls': {} } )