def test_create(self): """ Ensure the API supports creation of Programs with a valid organization. """ # Create a valid organization OrganizationFactory.create(key="test-org-key", display_name="test-org-display_name") data = self._build_post_data() # Add the valid organization in POST data while creating a Program data["organizations"] = [{"key": "test-org-key"}] response = self._make_request(method='post', data=data, admin=True) self.assertEqual(response.status_code, 201) program = Program.objects.all().last() self.assertEqual( response.data, { 'name': data['name'], 'subtitle': data['subtitle'], 'category': data['category'], 'status': data['status'], 'organizations': [{'key': 'test-org-key', 'display_name': 'test-org-display_name'}], 'course_codes': [], 'id': ANY, 'created': ANY, 'modified': ANY, 'marketing_slug': '', 'banner_image_urls': {}, 'uuid': str(program.uuid), } )
def test_missing_fields(self, field): """ Ensure that missing fields cause validation errors if required, and create with correct defaults otherwise. """ defaults = { 'subtitle': '', 'status': ProgramStatus.UNPUBLISHED, } # Create a valid organization OrganizationFactory.create(key='test-org-key', display_name='test-org-display_name') data = self._build_post_data() # Add the valid organization in POST data while creating a Program data['organizations'] = [{'key': 'test-org-key'}] del data[field] if field in defaults: expected_status = 201 else: expected_status = 400 response = self._make_request(method='post', data=data, admin=True) self.assertEqual(response.status_code, expected_status) if expected_status == 201: self.assertEqual(response.data[field], defaults[field]) else: self.assertIn('field is required', response.data[field][0])
def test_create(self): """ Ensure the API supports creation of Programs with a valid organization. """ # Create a valid organization OrganizationFactory.create(key="test-org-key", display_name="test-org-display_name") data = self._build_post_data() # Add the valid organization in POST data while creating a Program data["organizations"] = [{"key": "test-org-key"}] response = self._make_request(method='post', data=data, admin=True) self.assertEqual(response.status_code, 201) self.assertEqual( response.data, { u"name": data["name"], u"subtitle": data["subtitle"], u"category": data["category"], u"status": data["status"], u"organizations": [{"key": "test-org-key", "display_name": "test-org-display_name"}], u"course_codes": [], u"id": ANY, u"created": ANY, u"modified": ANY, u'marketing_slug': '', u'banner_image_urls': {} } )
def test_list_unauthorized(self): """ Ensure the API prevents unauthorized users from listing organizations. """ for _ in range(3): OrganizationFactory.create() client = self.get_authenticated_client(Role.LEARNERS) response = client.get(reverse("api:v1:organizations-list")) self.assertEqual(response.status_code, 403)
def test_list(self): """ Ensure the API supports listing of Organizations by admins. """ for _ in range(3): OrganizationFactory.create() client = self.get_authenticated_client(Role.ADMINS) response = client.get(reverse("api:v1:organizations-list")) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data['results']), 3) # pylint: disable=no-member
def test_create_with_invalid_org_data(self): """ Ensure the create Programs API fails if provided organization is invalid or there are multiple organizations. """ # validate without providing parameter 'organization' in request data data = self._build_post_data() error_msg = u'This field is required.' self._validate_org_data_errors(request_data=data, validation_error=error_msg) # validate with empty list as value for the parameter 'organization' in # request data error_msg = u'Provide exactly one valid/existing Organization while creating a Program.' self._validate_org_data_errors(request_data=data, validation_error=error_msg, organizations_data=[]) # validate with non existing organization key as value for the parameter # 'organization' in request data org_key = "non-existing-org-key" error_msg = u"Provided Organization with key '{org_key}' doesn't exist.".format( org_key=org_key) self._validate_org_data_errors(request_data=data, validation_error=error_msg, organizations_data=[{ "key": org_key }]) # create two valid organizations OrganizationFactory.create(key="test-org-key-1", display_name="test-org-display_name-1") OrganizationFactory.create(key="test-org-key-2", display_name="test-org-display_name-2") # now add these multiple valid organizations in POST data while creating # a Program and test that the user get validation error for providing # multiple organizations error_msg = u'Provide exactly one valid/existing Organization while creating a Program.' self._validate_org_data_errors(request_data=data, validation_error=error_msg, organizations_data=[ { "key": "test-org-key-2" }, { "key": "test-org-key-2" }, ])
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 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_create(self): """ Ensure the API supports creation of Programs with a valid organization. """ # Create a valid organization OrganizationFactory.create(key="test-org-key", display_name="test-org-display_name") data = self._build_post_data() # Add the valid organization in POST data while creating a Program data["organizations"] = [{"key": "test-org-key"}] response = self._make_request(method='post', data=data, admin=True) self.assertEqual(response.status_code, 201) program = Program.objects.all().last() self.assertEqual( response.data, { 'name': data['name'], 'subtitle': data['subtitle'], 'category': data['category'], 'status': data['status'], 'organizations': [{ 'key': 'test-org-key', 'display_name': 'test-org-display_name' }], 'course_codes': [], 'id': ANY, 'created': ANY, 'modified': ANY, 'marketing_slug': '', 'banner_image_urls': {}, 'uuid': str(program.uuid), })
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_create_with_invalid_org_data(self): """ Ensure the create Programs API fails if provided organization is invalid or there are multiple organizations. """ # validate without providing parameter 'organization' in request data data = self._build_post_data() error_msg = 'This field is required.' self._validate_org_data_errors(request_data=data, validation_error=error_msg) # validate with empty list as value for the parameter 'organization' in # request data error_msg = 'Provide exactly one valid/existing Organization while creating a Program.' self._validate_org_data_errors( request_data=data, validation_error=error_msg, organizations_data=[] ) # validate with non existing organization key as value for the parameter # 'organization' in request data org_key = "non-existing-org-key" error_msg = "Provided Organization with key '{org_key}' doesn't exist.".format(org_key=org_key) self._validate_org_data_errors( request_data=data, validation_error=error_msg, organizations_data=[{"key": org_key}] ) # create two valid organizations OrganizationFactory.create(key="test-org-key-1", display_name="test-org-display_name-1") OrganizationFactory.create(key="test-org-key-2", display_name="test-org-display_name-2") # now add these multiple valid organizations in POST data while creating # a Program and test that the user get validation error for providing # multiple organizations error_msg = 'Provide exactly one valid/existing Organization while creating a Program.' self._validate_org_data_errors( request_data=data, validation_error=error_msg, organizations_data=[ {"key": "test-org-key-2"}, {"key": "test-org-key-2"}, ] )
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_create(self): """ Ensure the API supports creation of Programs with a valid organization. """ # Create a valid organization OrganizationFactory.create(key="test-org-key", display_name="test-org-display_name") data = self._build_post_data() # Add the valid organization in POST data while creating a Program data["organizations"] = [{"key": "test-org-key"}] response = self._make_request(method='post', data=data, admin=True) self.assertEqual(response.status_code, 201) self.assertEqual( response.data, { u"name": data["name"], u"subtitle": data["subtitle"], u"category": data["category"], u"status": data["status"], u"organizations": [{ "key": "test-org-key", "display_name": "test-org-display_name" }], u"course_codes": [], u"id": ANY, u"created": ANY, u"modified": ANY, u'marketing_slug': '', u'banner_image_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 = { '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_org_list_filter(self): """ """ org_keys = ('org1', 'org2') for org_key in org_keys: org = OrganizationFactory.create(key=org_key) CourseCodeFactory.create(organization=org) client = self.get_authenticated_client(Role.ADMINS) for org_key in org_keys: response = client.get(reverse("api:v1:course_codes-list"), {"organization": org_key}) self.assertEqual(response.status_code, 200) results = response.data['results'] # pylint: disable=no-member self.assertEqual(len(results), 1) self.assertEqual(results[0]['organization']['key'], org_key)
def test_org_list_filter(self): """ """ org_keys = (u'org1', u'org2') for org_key in org_keys: org = OrganizationFactory.create(key=org_key) CourseCodeFactory.create(organization=org) client = self.get_authenticated_client(Role.ADMINS) for org_key in org_keys: response = client.get(reverse("api:v1:course_codes-list"), {"organization": org_key}) self.assertEqual(response.status_code, 200) results = response.data['results'] # pylint: disable=no-member self.assertEqual(len(results), 1) self.assertEqual(results[0]['organization']['key'], org_key)
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 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 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_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_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_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_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_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_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_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_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, { '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': {} })