Commit 164d3244 by Amir Qayyum Khan

Refactor tests

parent 25d8085b
......@@ -54,6 +54,7 @@ from student.tests.factories import AdminFactory
USER_PASSWORD = 'test'
AUTH_ATTRS = ('auth', 'auth_header_oauth2_provider')
class CcxRestApiTest(CcxTestCase, APITestCase):
......@@ -183,7 +184,8 @@ class CcxListTest(CcxRestApiTest):
'?master_course_id={0}'.format(urllib.quote_plus(self.master_course_key_str))
)
def test_authorization(self):
@ddt.data(*AUTH_ATTRS)
def test_authorization(self, auth_attr):
"""
Test that only the right token is authorized
"""
......@@ -199,12 +201,9 @@ class CcxListTest(CcxRestApiTest):
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=auth)
self.assertEqual(resp.status_code, status.HTTP_401_UNAUTHORIZED)
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=self.auth)
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_200_OK)
# test for oauth2_provider
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
def test_authorization_no_oauth_staff(self):
"""
......@@ -281,7 +280,8 @@ class CcxListTest(CcxRestApiTest):
resp = self.client.post(self.list_url, data, format='json')
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
def test_get_list_wrong_master_course(self):
@ddt.data(*AUTH_ATTRS)
def test_get_list_wrong_master_course(self, auth_attr):
"""
Test for various get requests with wrong master course string
"""
......@@ -290,51 +290,31 @@ class CcxListTest(CcxRestApiTest):
with mock.patch(mock_class_str, autospec=True) as mocked_perm_class:
mocked_perm_class.return_value = True
# case with no master_course_id provided
resp = self.client.get(self.list_url, {}, HTTP_AUTHORIZATION=self.auth)
self.expect_error(status.HTTP_400_BAD_REQUEST, 'master_course_id_not_provided', resp)
# test for oauth2_provider
resp = self.client.get(self.list_url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = self.client.get(self.list_url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_400_BAD_REQUEST, 'master_course_id_not_provided', resp)
base_url = urlparse.urljoin(self.list_url, '?master_course_id=')
# case with empty master_course_id
resp = self.client.get(base_url, {}, HTTP_AUTHORIZATION=self.auth)
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_id_not_valid', resp)
# test for oauth2_provider
resp = self.client.get(base_url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = self.client.get(base_url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_id_not_valid', resp)
# case with invalid master_course_id
url = '{0}invalid_master_course_str'.format(base_url)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth)
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_id_not_valid', resp)
# test for oauth2_provider
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_id_not_valid', resp)
# case with inexistent master_course_id
url = '{0}course-v1%3Aorg_foo.0%2Bcourse_bar_0%2BRun_0'.format(base_url)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth)
self.expect_error(status.HTTP_404_NOT_FOUND, 'course_id_does_not_exist', resp)
# test for oauth2_provider
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_404_NOT_FOUND, 'course_id_does_not_exist', resp)
def test_get_list(self):
@ddt.data(*AUTH_ATTRS)
def test_get_list(self, auth_attr):
"""
Tests the API to get a list of CCX Courses
"""
# there are no CCX courses
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=self.auth)
self.assertIn('count', resp.data) # pylint: disable=no-member
self.assertEqual(resp.data['count'], 0) # pylint: disable=no-member
# test for oauth2_provider
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertIn('count', resp.data) # pylint: disable=no-member
self.assertEqual(resp.data['count'], 0) # pylint: disable=no-member
......@@ -342,22 +322,15 @@ class CcxListTest(CcxRestApiTest):
num_ccx = 10
for _ in xrange(num_ccx):
self.make_ccx()
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=self.auth)
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertIn('count', resp.data) # pylint: disable=no-member
self.assertEqual(resp.data['count'], num_ccx) # pylint: disable=no-member
self.assertIn('results', resp.data) # pylint: disable=no-member
self.assertEqual(len(resp.data['results']), num_ccx) # pylint: disable=no-member
# test for oauth2_provider
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertIn('count', resp.data) # pylint: disable=no-member
self.assertEqual(resp.data['count'], num_ccx) # pylint: disable=no-member
self.assertIn('results', resp.data) # pylint: disable=no-member
self.assertEqual(len(resp.data['results']), num_ccx) # pylint: disable=no-member
def test_get_sorted_list(self):
@ddt.data(*AUTH_ATTRS)
def test_get_sorted_list(self, auth_attr):
"""
Tests the API to get a sorted list of CCX Courses
"""
......@@ -376,15 +349,7 @@ class CcxListTest(CcxRestApiTest):
# sort by display name
url = '{0}&order_by=display_name'.format(self.list_url_master_course)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(len(resp.data['results']), num_ccx) # pylint: disable=no-member
# the display_name should be sorted as "Title CCX x", "Title CCX y", "Title CCX z"
for num, ccx in enumerate(resp.data['results']): # pylint: disable=no-member
self.assertEqual(title_str.format(string.ascii_lowercase[-(num_ccx - num)]), ccx['display_name'])
# test for oauth2_provider
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(len(resp.data['results']), num_ccx) # pylint: disable=no-member
# the display_name should be sorted as "Title CCX x", "Title CCX y", "Title CCX z"
......@@ -393,20 +358,14 @@ class CcxListTest(CcxRestApiTest):
# add sort order desc
url = '{0}&order_by=display_name&sort_order=desc'.format(self.list_url_master_course)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
# the only thing I can check is that the display name is in alphabetically reversed order
# in the same way when the field has been updated above, so with the id asc
for num, ccx in enumerate(resp.data['results']): # pylint: disable=no-member
self.assertEqual(title_str.format(string.ascii_lowercase[-(num + 1)]), ccx['display_name'])
# test for oauth2_provider
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
# the only thing I can check is that the display name is in alphabetically reversed order
# in the same way when the field has been updated above, so with the id asc
for num, ccx in enumerate(resp.data['results']): # pylint: disable=no-member
self.assertEqual(title_str.format(string.ascii_lowercase[-(num + 1)]), ccx['display_name'])
def test_get_paginated_list(self):
@ddt.data(*AUTH_ATTRS)
def test_get_paginated_list(self, auth_attr):
"""
Tests the API to get a paginated list of CCX Courses
"""
......@@ -417,17 +376,7 @@ class CcxListTest(CcxRestApiTest):
page_size = settings.REST_FRAMEWORK.get('PAGE_SIZE', 10)
num_pages = int(math.ceil(num_ccx / float(page_size)))
# get first page
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(resp.data['count'], num_ccx) # pylint: disable=no-member
self.assertEqual(resp.data['num_pages'], num_pages) # pylint: disable=no-member
self.assertEqual(resp.data['current_page'], 1) # pylint: disable=no-member
self.assertEqual(resp.data['start'], 0) # pylint: disable=no-member
self.assertIsNotNone(resp.data['next']) # pylint: disable=no-member
self.assertIsNone(resp.data['previous']) # pylint: disable=no-member
# test for oauth2_provider
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = self.client.get(self.list_url_master_course, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(resp.data['count'], num_ccx) # pylint: disable=no-member
self.assertEqual(resp.data['num_pages'], num_pages) # pylint: disable=no-member
......@@ -438,17 +387,7 @@ class CcxListTest(CcxRestApiTest):
# get a page in the middle
url = '{0}&page=24'.format(self.list_url_master_course)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(resp.data['count'], num_ccx) # pylint: disable=no-member
self.assertEqual(resp.data['num_pages'], num_pages) # pylint: disable=no-member
self.assertEqual(resp.data['current_page'], 24) # pylint: disable=no-member
self.assertEqual(resp.data['start'], (resp.data['current_page'] - 1) * page_size) # pylint: disable=no-member
self.assertIsNotNone(resp.data['next']) # pylint: disable=no-member
self.assertIsNotNone(resp.data['previous']) # pylint: disable=no-member
# test for oauth2_provider
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(resp.data['count'], num_ccx) # pylint: disable=no-member
self.assertEqual(resp.data['num_pages'], num_pages) # pylint: disable=no-member
......@@ -459,17 +398,7 @@ class CcxListTest(CcxRestApiTest):
# get last page
url = '{0}&page={1}'.format(self.list_url_master_course, num_pages)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(resp.data['count'], num_ccx) # pylint: disable=no-member
self.assertEqual(resp.data['num_pages'], num_pages) # pylint: disable=no-member
self.assertEqual(resp.data['current_page'], num_pages) # pylint: disable=no-member
self.assertEqual(resp.data['start'], (resp.data['current_page'] - 1) * page_size) # pylint: disable=no-member
self.assertIsNone(resp.data['next']) # pylint: disable=no-member
self.assertIsNotNone(resp.data['previous']) # pylint: disable=no-member
# test for oauth2_provider
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(resp.data['count'], num_ccx) # pylint: disable=no-member
self.assertEqual(resp.data['num_pages'], num_pages) # pylint: disable=no-member
......@@ -480,42 +409,73 @@ class CcxListTest(CcxRestApiTest):
# last page + 1
url = '{0}&page={1}'.format(self.list_url_master_course, num_pages + 1)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND)
# test for oauth2_provider
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = self.client.get(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND)
@ddt.data(
(
{},
status.HTTP_400_BAD_REQUEST,
'master_course_id_not_provided'
'master_course_id_not_provided',
'auth_header_oauth2_provider'
),
(
{},
status.HTTP_400_BAD_REQUEST,
'master_course_id_not_provided',
'auth'
),
(
{'master_course_id': None},
status.HTTP_400_BAD_REQUEST,
'master_course_id_not_provided'
'master_course_id_not_provided',
'auth_header_oauth2_provider'
),
(
{'master_course_id': None},
status.HTTP_400_BAD_REQUEST,
'master_course_id_not_provided',
'auth'
),
(
{'master_course_id': ''},
status.HTTP_400_BAD_REQUEST,
'course_id_not_valid'
'course_id_not_valid',
'auth_header_oauth2_provider'
),
(
{'master_course_id': ''},
status.HTTP_400_BAD_REQUEST,
'course_id_not_valid',
'auth'
),
(
{'master_course_id': 'invalid_master_course_str'},
status.HTTP_400_BAD_REQUEST,
'course_id_not_valid',
'auth'
),
(
{'master_course_id': 'invalid_master_course_str'},
status.HTTP_400_BAD_REQUEST,
'course_id_not_valid'
'course_id_not_valid',
'auth_header_oauth2_provider'
),
(
{'master_course_id': 'course-v1:org_foo.0+course_bar_0+Run_0'},
status.HTTP_404_NOT_FOUND,
'course_id_does_not_exist',
'auth'
),
(
{'master_course_id': 'course-v1:org_foo.0+course_bar_0+Run_0'},
status.HTTP_404_NOT_FOUND,
'course_id_does_not_exist'
'course_id_does_not_exist',
'auth_header_oauth2_provider'
),
)
@ddt.unpack
def test_post_list_wrong_master_course(self, data, expected_http_error, expected_error_string):
def test_post_list_wrong_master_course(self, data, expected_http_error, expected_error_string, auth_attr):
"""
Test for various post requests with wrong master course string
"""
......@@ -524,19 +484,11 @@ class CcxListTest(CcxRestApiTest):
with mock.patch(mock_class_str, autospec=True) as mocked_perm_class:
mocked_perm_class.return_value = True
# case with no master_course_id provided
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
self.expect_error(expected_http_error, expected_error_string, resp)
# test for oauth2_provider
resp = self.client.post(
self.list_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(expected_http_error, expected_error_string, resp)
def test_post_list_wrong_master_course_special_cases(self):
@ddt.data(*AUTH_ATTRS)
def test_post_list_wrong_master_course_special_cases(self, auth_attr):
"""
Same as test_post_list_wrong_master_course,
but different ways to test the wrong master_course_id
......@@ -546,7 +498,7 @@ class CcxListTest(CcxRestApiTest):
self.mstore.update_item(self.course, self.coach.id)
data = {'master_course_id': self.master_course_key_str}
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_403_FORBIDDEN, 'ccx_not_enabled_for_master_course', resp)
self.course.enable_ccx = True
self.mstore.update_item(self.course, self.coach.id)
......@@ -554,36 +506,10 @@ class CcxListTest(CcxRestApiTest):
# case with deprecated master_course_id
with mock.patch('courseware.courses.get_course_by_id', autospec=True) as mocked:
mocked.return_value.id.deprecated = True
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_400_BAD_REQUEST, 'deprecated_master_course_id', resp)
# test for oauth2_provider
self.course.enable_ccx = False
self.mstore.update_item(self.course, self.coach.id)
data = {'master_course_id': self.master_course_key_str}
resp_header_oauth2_provider = self.client.post(
self.list_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
self.expect_error(status.HTTP_403_FORBIDDEN, 'ccx_not_enabled_for_master_course', resp_header_oauth2_provider)
self.course.enable_ccx = True
self.mstore.update_item(self.course, self.coach.id)
# case with deprecated master_course_id
with mock.patch('courseware.courses.get_course_by_id', autospec=True) as mocked:
mocked.return_value.id.deprecated = True
resp_header_oauth2_provider = self.client.post(
self.list_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
self.expect_error(status.HTTP_400_BAD_REQUEST, 'deprecated_master_course_id', resp_header_oauth2_provider)
@ddt.data(
(
{},
......@@ -591,7 +517,27 @@ class CcxListTest(CcxRestApiTest):
'max_students_allowed': 'missing_field_max_students_allowed',
'display_name': 'missing_field_display_name',
'coach_email': 'missing_field_coach_email'
}
},
'auth'
),
(
{},
{
'max_students_allowed': 'missing_field_max_students_allowed',
'display_name': 'missing_field_display_name',
'coach_email': 'missing_field_coach_email'
},
'auth_header_oauth2_provider'
),
(
{
'max_students_allowed': 10,
'display_name': 'CCX Title'
},
{
'coach_email': 'missing_field_coach_email'
},
'auth'
),
(
{
......@@ -600,7 +546,8 @@ class CcxListTest(CcxRestApiTest):
},
{
'coach_email': 'missing_field_coach_email'
}
},
'auth_header_oauth2_provider'
),
(
{
......@@ -612,7 +559,30 @@ class CcxListTest(CcxRestApiTest):
'max_students_allowed': 'null_field_max_students_allowed',
'display_name': 'null_field_display_name',
'coach_email': 'null_field_coach_email'
}
},
'auth'
),
(
{
'max_students_allowed': None,
'display_name': None,
'coach_email': None
},
{
'max_students_allowed': 'null_field_max_students_allowed',
'display_name': 'null_field_display_name',
'coach_email': 'null_field_coach_email'
},
'auth_header_oauth2_provider'
),
(
{
'max_students_allowed': 10,
'display_name': 'CCX Title',
'coach_email': 'this is not an email@test.com'
},
{'coach_email': 'invalid_coach_email'},
'auth'
),
(
{
......@@ -620,7 +590,8 @@ class CcxListTest(CcxRestApiTest):
'display_name': 'CCX Title',
'coach_email': 'this is not an email@test.com'
},
{'coach_email': 'invalid_coach_email'}
{'coach_email': 'invalid_coach_email'},
'auth_header_oauth2_provider'
),
(
{
......@@ -628,7 +599,17 @@ class CcxListTest(CcxRestApiTest):
'display_name': '',
'coach_email': 'email@test.com'
},
{'display_name': 'invalid_display_name'}
{'display_name': 'invalid_display_name'},
'auth'
),
(
{
'max_students_allowed': 10,
'display_name': '',
'coach_email': 'email@test.com'
},
{'display_name': 'invalid_display_name'},
'auth_header_oauth2_provider'
),
(
{
......@@ -636,7 +617,27 @@ class CcxListTest(CcxRestApiTest):
'display_name': 'CCX Title',
'coach_email': 'email@test.com'
},
{'max_students_allowed': 'invalid_max_students_allowed'}
{'max_students_allowed': 'invalid_max_students_allowed'},
'auth'
),
(
{
'max_students_allowed': 'a',
'display_name': 'CCX Title',
'coach_email': 'email@test.com'
},
{'max_students_allowed': 'invalid_max_students_allowed'},
'auth_header_oauth2_provider'
),
(
{
'max_students_allowed': 10,
'display_name': 'CCX Title',
'coach_email': 'email@test.com',
'course_modules': {'foo': 'bar'}
},
{'course_modules': 'invalid_course_module_list'},
'auth'
),
(
{
......@@ -645,7 +646,8 @@ class CcxListTest(CcxRestApiTest):
'coach_email': 'email@test.com',
'course_modules': {'foo': 'bar'}
},
{'course_modules': 'invalid_course_module_list'}
{'course_modules': 'invalid_course_module_list'},
'auth_header_oauth2_provider'
),
(
{
......@@ -654,7 +656,28 @@ class CcxListTest(CcxRestApiTest):
'coach_email': 'email@test.com',
'course_modules': 'block-v1:org.0+course_0+Run_0+type@chapter+block@chapter_1'
},
{'course_modules': 'invalid_course_module_list'}
{'course_modules': 'invalid_course_module_list'},
'auth'
),
(
{
'max_students_allowed': 10,
'display_name': 'CCX Title',
'coach_email': 'email@test.com',
'course_modules': 'block-v1:org.0+course_0+Run_0+type@chapter+block@chapter_1'
},
{'course_modules': 'invalid_course_module_list'},
'auth_header_oauth2_provider'
),
(
{
'max_students_allowed': 10,
'display_name': 'CCX Title',
'coach_email': 'email@test.com',
'course_modules': ['foo', 'bar']
},
{'course_modules': 'invalid_course_module_keys'},
'auth'
),
(
{
......@@ -663,29 +686,22 @@ class CcxListTest(CcxRestApiTest):
'coach_email': 'email@test.com',
'course_modules': ['foo', 'bar']
},
{'course_modules': 'invalid_course_module_keys'}
{'course_modules': 'invalid_course_module_keys'},
'auth_header_oauth2_provider'
),
)
@ddt.unpack
def test_post_list_wrong_input_data(self, data, expected_errors):
def test_post_list_wrong_input_data(self, data, expected_errors, auth_attr):
"""
Test for various post requests with wrong input data
"""
# add the master_course_key_str to the request data
data['master_course_id'] = self.master_course_key_str
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
self.expect_error_fields(expected_errors, resp)
# test for oauth2_provider
resp = self.client.post(
self.list_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error_fields(expected_errors, resp)
def test_post_list_coach_does_not_exist(self):
@ddt.data(*AUTH_ATTRS)
def test_post_list_coach_does_not_exist(self, auth_attr):
"""
Specific test for the case when the input data is valid but the coach does not exist.
"""
......@@ -695,19 +711,11 @@ class CcxListTest(CcxRestApiTest):
'display_name': 'CCX Title',
'coach_email': 'inexisting_email@test.com'
}
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
self.expect_error(status.HTTP_404_NOT_FOUND, 'coach_user_does_not_exist', resp)
# test for oauth2_provider
resp = self.client.post(
self.list_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_404_NOT_FOUND, 'coach_user_does_not_exist', resp)
def test_post_list_wrong_modules(self):
@ddt.data(*AUTH_ATTRS)
def test_post_list_wrong_modules(self, auth_attr):
"""
Specific test for the case when the input data is valid but the
course modules do not belong to the master course
......@@ -722,19 +730,11 @@ class CcxListTest(CcxRestApiTest):
'block-v1:org.0+course_0+Run_0+type@chapter+block@chapter_bar'
]
}
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_module_list_not_belonging_to_master_course', resp)
# test for oauth2_provider
resp = self.client.post(
self.list_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_module_list_not_belonging_to_master_course', resp)
def test_post_list_mixed_wrong_and_valid_modules(self):
@ddt.data(*AUTH_ATTRS)
def test_post_list_mixed_wrong_and_valid_modules(self, auth_attr):
"""
Specific test for the case when the input data is valid but some of
the course modules do not belong to the master course
......@@ -747,19 +747,11 @@ class CcxListTest(CcxRestApiTest):
'coach_email': self.coach.email,
'course_modules': modules
}
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_module_list_not_belonging_to_master_course', resp)
# test for oauth2_provider
resp = self.client.post(
self.list_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_module_list_not_belonging_to_master_course', resp)
def test_post_list(self):
@ddt.data(*AUTH_ATTRS)
def test_post_list(self, auth_attr):
"""
Test the creation of a CCX
"""
......@@ -771,7 +763,7 @@ class CcxListTest(CcxRestApiTest):
'coach_email': self.coach.email,
'course_modules': self.master_course_chapters[0:1]
}
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
# check if the response has at least the same data of the request
for key, val in data.iteritems():
......@@ -796,38 +788,8 @@ class CcxListTest(CcxRestApiTest):
self.assertEqual(len(outbox), 1)
self.assertIn(self.coach.email, outbox[0].recipients()) # pylint: disable=no-member
# test for oauth2_provider
resp = self.client.post(
self.list_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
# check if the response has at least the same data of the request
for key, val in data.iteritems():
self.assertEqual(resp.data.get(key), val) # pylint: disable=no-member
self.assertIn('ccx_course_id', resp.data) # pylint: disable=no-member
# check that the new CCX actually exists
course_key = CourseKey.from_string(resp.data.get('ccx_course_id')) # pylint: disable=no-member
ccx_course = CustomCourseForEdX.objects.get(pk=course_key.ccx)
self.assertEqual(
unicode(CCXLocator.from_course_locator(ccx_course.course.id, ccx_course.id)),
resp.data.get('ccx_course_id') # pylint: disable=no-member
)
# check that the coach user has coach role on the master course
coach_role_on_master_course = CourseCcxCoachRole(self.master_course_key)
self.assertTrue(coach_role_on_master_course.has_user(self.coach))
# check that the coach has been enrolled in the ccx
ccx_course_object = courses.get_course_by_id(course_key)
self.assertTrue(
CourseEnrollment.objects.filter(course_id=ccx_course_object.id, user=self.coach).exists()
)
# check that an email has been sent to the coach
self.assertEqual(len(outbox), 2)
self.assertIn(self.coach.email, outbox[0].recipients()) # pylint: disable=no-member
def test_post_list_duplicated_modules(self):
@ddt.data(*AUTH_ATTRS)
def test_post_list_duplicated_modules(self, auth_attr):
"""
Test the creation of a CCX, but with duplicated modules
"""
......@@ -840,21 +802,12 @@ class CcxListTest(CcxRestApiTest):
'coach_email': self.coach.email,
'course_modules': duplicated_chapters
}
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
self.assertEqual(resp.data.get('course_modules'), chapters) # pylint: disable=no-member
# test for oauth2_provider
resp = self.client.post(
self.list_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
self.assertEqual(resp.data.get('course_modules'), chapters) # pylint: disable=no-member
def test_post_list_staff_master_course_in_ccx(self):
@ddt.data(*AUTH_ATTRS)
def test_post_list_staff_master_course_in_ccx(self, auth_attr):
"""
Specific test to check that the staff and instructor of the master
course are assigned to the CCX.
......@@ -866,7 +819,7 @@ class CcxListTest(CcxRestApiTest):
'display_name': 'CCX Test Title',
'coach_email': self.coach.email
}
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
# check that only one email has been sent and it is to to the coach
self.assertEqual(len(outbox), 1)
......@@ -891,32 +844,6 @@ class CcxListTest(CcxRestApiTest):
for course_user, ccx_user in izip(sorted(list_instructor_master_course), sorted(list_instructor_ccx_course)):
self.assertEqual(course_user, ccx_user)
# test for oauth2_provider
resp = self.client.post(
self.list_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
# check that only one email has been sent and it is to to the coach
self.assertEqual(len(outbox), 2)
self.assertIn(self.coach.email, outbox[0].recipients()) # pylint: disable=no-member
list_staff_master_course = list_with_level(self.course, 'staff')
list_instructor_master_course = list_with_level(self.course, 'instructor')
course_key = CourseKey.from_string(resp.data.get('ccx_course_id')) # pylint: disable=no-member
with ccx_course_cm(course_key) as course_ccx:
list_staff_ccx_course = list_with_level(course_ccx, 'staff')
list_instructor_ccx_course = list_with_level(course_ccx, 'instructor')
self.assertEqual(len(list_staff_master_course), len(list_staff_ccx_course))
for course_user, ccx_user in izip(sorted(list_staff_master_course), sorted(list_staff_ccx_course)):
self.assertEqual(course_user, ccx_user)
self.assertEqual(len(list_instructor_master_course), len(list_instructor_ccx_course))
for course_user, ccx_user in izip(sorted(list_instructor_master_course), sorted(list_instructor_ccx_course)):
self.assertEqual(course_user, ccx_user)
@attr(shard=1)
@ddt.ddt
......@@ -974,7 +901,8 @@ class CcxDetailTest(CcxRestApiTest):
)
return ccx
def test_authorization(self):
@ddt.data(*AUTH_ATTRS)
def test_authorization(self, auth_attr):
"""
Test that only the right token is authorized
"""
......@@ -990,11 +918,7 @@ class CcxDetailTest(CcxRestApiTest):
resp = self.client.get(self.detail_url, {}, HTTP_AUTHORIZATION=auth)
self.assertEqual(resp.status_code, status.HTTP_401_UNAUTHORIZED)
resp = self.client.get(self.detail_url, {}, HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
# test for oauth2_provider
resp = self.client.get(self.detail_url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = self.client.get(self.detail_url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_200_OK)
def test_authorization_no_oauth_staff(self):
......@@ -1084,9 +1008,16 @@ class CcxDetailTest(CcxRestApiTest):
self.assertEqual(views.CCXDetailView.__name__, resolver.func.__name__)
self.assertEqual(views.CCXDetailView.__module__, resolver.func.__module__)
@ddt.data(('get',), ('delete',), ('patch',))
@ddt.data(
('get', AUTH_ATTRS[0]),
('get', AUTH_ATTRS[1]),
('delete', AUTH_ATTRS[0]),
('delete', AUTH_ATTRS[1]),
('patch', AUTH_ATTRS[0]),
('patch', AUTH_ATTRS[1])
)
@ddt.unpack
def test_detail_wrong_ccx(self, http_method):
def test_detail_wrong_ccx(self, http_method, auth_attr):
"""
Test for different methods for detail of a ccx course.
All check the validity of the ccx course id
......@@ -1097,81 +1028,46 @@ class CcxDetailTest(CcxRestApiTest):
url = reverse('ccx_api:v0:ccx:detail', kwargs={'ccx_course_id': self.master_course_key_str})
# the permission class will give a 403 error because will not find the CCX
resp = client_request(url, {}, HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
# test for oauth2_provider
resp = client_request(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = client_request(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
# bypassing the permission class we get another kind of error
with mock.patch(mock_class_str, autospec=True) as mocked_perm_class:
mocked_perm_class.return_value = True
resp = client_request(url, {}, HTTP_AUTHORIZATION=self.auth)
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_id_not_valid_ccx_id', resp)
# test for oauth2_provider
resp = client_request(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = client_request(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_id_not_valid_ccx_id', resp)
# use an non existing ccx id
url = reverse('ccx_api:v0:ccx:detail', kwargs={'ccx_course_id': 'ccx-v1:foo.0+course_bar_0+Run_0+ccx@1'})
# the permission class will give a 403 error because will not find the CCX
resp = client_request(url, {}, HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
# test for oauth2_provider
resp = client_request(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = client_request(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
# bypassing the permission class we get another kind of error
with mock.patch(mock_class_str, autospec=True) as mocked_perm_class:
mocked_perm_class.return_value = True
resp = client_request(url, {}, HTTP_AUTHORIZATION=self.auth)
self.expect_error(status.HTTP_404_NOT_FOUND, 'ccx_course_id_does_not_exist', resp)
# test for oauth2_provider
resp = client_request(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = client_request(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_404_NOT_FOUND, 'ccx_course_id_does_not_exist', resp)
# get a valid ccx key and add few 0s to get a non existing ccx for a valid course
ccx_key_str = '{0}000000'.format(self.ccx_key_str)
url = reverse('ccx_api:v0:ccx:detail', kwargs={'ccx_course_id': ccx_key_str})
# the permission class will give a 403 error because will not find the CCX
resp = client_request(url, {}, HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
# test for oauth2_provider
resp = client_request(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = client_request(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
# bypassing the permission class we get another kind of error
with mock.patch(mock_class_str, autospec=True) as mocked_perm_class:
mocked_perm_class.return_value = True
resp = client_request(url, {}, HTTP_AUTHORIZATION=self.auth)
resp = client_request(url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_404_NOT_FOUND, 'ccx_course_id_does_not_exist', resp)
# test for oauth2_provider
resp = client_request(url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
self.expect_error(status.HTTP_404_NOT_FOUND, 'ccx_course_id_does_not_exist', resp)
def test_get_detail(self):
@ddt.data(*AUTH_ATTRS)
def test_get_detail(self, auth_attr):
"""
Test for getting detail of a ccx course
"""
resp = self.client.get(self.detail_url, {}, HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(resp.data.get('ccx_course_id'), self.ccx_key_str) # pylint: disable=no-member
self.assertEqual(resp.data.get('display_name'), self.ccx.display_name) # pylint: disable=no-member
self.assertEqual(
resp.data.get('max_students_allowed'), # pylint: disable=no-member
self.ccx.max_student_enrollments_allowed # pylint: disable=no-member
)
self.assertEqual(resp.data.get('coach_email'), self.ccx.coach.email) # pylint: disable=no-member
self.assertEqual(resp.data.get('master_course_id'), unicode(self.ccx.course_id)) # pylint: disable=no-member
self.assertItemsEqual(resp.data.get('course_modules'), self.master_course_chapters) # pylint: disable=no-member
# test for oauth2_provider
resp = self.client.get(self.detail_url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
resp = self.client.get(self.detail_url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(resp.data.get('ccx_course_id'), self.ccx_key_str) # pylint: disable=no-member
self.assertEqual(resp.data.get('display_name'), self.ccx.display_name) # pylint: disable=no-member
......@@ -1183,14 +1079,15 @@ class CcxDetailTest(CcxRestApiTest):
self.assertEqual(resp.data.get('master_course_id'), unicode(self.ccx.course_id)) # pylint: disable=no-member
self.assertItemsEqual(resp.data.get('course_modules'), self.master_course_chapters) # pylint: disable=no-member
def test_delete_detail(self):
@ddt.data(*AUTH_ATTRS)
def test_delete_detail(self, auth_attr):
"""
Test for deleting a ccx course
"""
# check that there are overrides
self.assertGreater(CcxFieldOverride.objects.filter(ccx=self.ccx).count(), 0)
self.assertGreater(CourseEnrollment.objects.filter(course_id=self.ccx_key).count(), 0)
resp = self.client.delete(self.detail_url, {}, HTTP_AUTHORIZATION=self.auth)
resp = self.client.delete(self.detail_url, {}, HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
self.assertIsNone(resp.data) # pylint: disable=no-member
# the CCX does not exist any more
......@@ -1200,40 +1097,15 @@ class CcxDetailTest(CcxRestApiTest):
self.assertEqual(CcxFieldOverride.objects.filter(ccx=self.ccx).count(), 0)
self.assertEqual(CourseEnrollment.objects.filter(course_id=self.ccx_key).count(), 0)
def test_delete_detail_oauth2_provider(self):
"""
Test for deleting a ccx course with oauth2_provider header
"""
# check that there are overrides
self.assertGreater(CcxFieldOverride.objects.filter(ccx=self.ccx).count(), 0)
self.assertGreater(CourseEnrollment.objects.filter(course_id=self.ccx_key).count(), 0)
resp = self.client.delete(self.detail_url, {}, HTTP_AUTHORIZATION=self.auth_header_oauth2_provider)
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
self.assertIsNone(resp.data) # pylint: disable=no-member
# the CCX does not exist any more
with self.assertRaises(CustomCourseForEdX.DoesNotExist):
CustomCourseForEdX.objects.get(id=self.ccx.id)
# check that there are no overrides
self.assertEqual(CcxFieldOverride.objects.filter(ccx=self.ccx).count(), 0)
self.assertEqual(CourseEnrollment.objects.filter(course_id=self.ccx_key).count(), 0)
def test_patch_detail_change_master_course(self):
@ddt.data(*AUTH_ATTRS)
def test_patch_detail_change_master_course(self, auth_attr):
"""
Test to patch a ccx course to change a master course
"""
data = {
'master_course_id': 'changed_course_id'
}
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
self.expect_error(status.HTTP_403_FORBIDDEN, 'master_course_id_change_not_allowed', resp)
# test for oauth2_provider
resp = self.client.patch(
self.detail_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_403_FORBIDDEN, 'master_course_id_change_not_allowed', resp)
@ddt.data(
......@@ -1247,51 +1119,95 @@ class CcxDetailTest(CcxRestApiTest):
'max_students_allowed': 'null_field_max_students_allowed',
'display_name': 'null_field_display_name',
'coach_email': 'null_field_coach_email'
}
},
AUTH_ATTRS[0]
),
(
{
'max_students_allowed': None,
'display_name': None,
'coach_email': None
},
{
'max_students_allowed': 'null_field_max_students_allowed',
'display_name': 'null_field_display_name',
'coach_email': 'null_field_coach_email'
},
AUTH_ATTRS[1]
),
(
{'coach_email': 'this is not an email@test.com'},
{'coach_email': 'invalid_coach_email'},
AUTH_ATTRS[0]
),
(
{'coach_email': 'this is not an email@test.com'},
{'coach_email': 'invalid_coach_email'}
{'coach_email': 'invalid_coach_email'},
AUTH_ATTRS[1]
),
(
{'display_name': ''},
{'display_name': 'invalid_display_name'}
{'display_name': 'invalid_display_name'},
AUTH_ATTRS[0]
),
(
{'display_name': ''},
{'display_name': 'invalid_display_name'},
AUTH_ATTRS[1]
),
(
{'max_students_allowed': 'a'},
{'max_students_allowed': 'invalid_max_students_allowed'},
AUTH_ATTRS[0]
),
(
{'max_students_allowed': 'a'},
{'max_students_allowed': 'invalid_max_students_allowed'}
{'max_students_allowed': 'invalid_max_students_allowed'},
AUTH_ATTRS[1]
),
(
{'course_modules': {'foo': 'bar'}},
{'course_modules': 'invalid_course_module_list'}
{'course_modules': 'invalid_course_module_list'},
AUTH_ATTRS[0]
),
(
{'course_modules': {'foo': 'bar'}},
{'course_modules': 'invalid_course_module_list'},
AUTH_ATTRS[1]
),
(
{'course_modules': 'block-v1:org.0+course_0+Run_0+type@chapter+block@chapter_1'},
{'course_modules': 'invalid_course_module_list'},
AUTH_ATTRS[0]
),
(
{'course_modules': 'block-v1:org.0+course_0+Run_0+type@chapter+block@chapter_1'},
{'course_modules': 'invalid_course_module_list'}
{'course_modules': 'invalid_course_module_list'},
AUTH_ATTRS[1]
),
(
{'course_modules': ['foo', 'bar']},
{'course_modules': 'invalid_course_module_keys'},
AUTH_ATTRS[0]
),
(
{'course_modules': ['foo', 'bar']},
{'course_modules': 'invalid_course_module_keys'}
{'course_modules': 'invalid_course_module_keys'},
AUTH_ATTRS[1]
),
)
@ddt.unpack
def test_patch_detail_wrong_input_data(self, data, expected_errors):
def test_patch_detail_wrong_input_data(self, data, expected_errors, auth_attr):
"""
Test for different wrong inputs for the patch method
"""
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
self.expect_error_fields(expected_errors, resp)
# test for oauth2_provider
resp = self.client.patch(
self.detail_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error_fields(expected_errors, resp)
def test_empty_patch(self):
@ddt.data(*AUTH_ATTRS)
def test_empty_patch(self, auth_attr):
"""
An empty patch does not modify anything
"""
......@@ -1299,7 +1215,7 @@ class CcxDetailTest(CcxRestApiTest):
max_students_allowed = self.ccx.max_student_enrollments_allowed # pylint: disable=no-member
coach_email = self.ccx.coach.email # pylint: disable=no-member
ccx_structure = self.ccx.structure # pylint: disable=no-member
resp = self.client.patch(self.detail_url, {}, format='json', HTTP_AUTHORIZATION=self.auth)
resp = self.client.patch(self.detail_url, {}, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertEqual(display_name, ccx.display_name)
......@@ -1307,21 +1223,8 @@ class CcxDetailTest(CcxRestApiTest):
self.assertEqual(coach_email, ccx.coach.email)
self.assertEqual(ccx_structure, ccx.structure)
# test for oauth2_provider
resp = self.client.patch(
self.detail_url,
{},
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertEqual(display_name, ccx.display_name)
self.assertEqual(max_students_allowed, ccx.max_student_enrollments_allowed)
self.assertEqual(coach_email, ccx.coach.email)
self.assertEqual(ccx_structure, ccx.structure)
def test_patch_detail_coach_does_not_exist(self):
@ddt.data(*AUTH_ATTRS)
def test_patch_detail_coach_does_not_exist(self, auth_attr):
"""
Specific test for the case when the input data is valid but the coach does not exist.
"""
......@@ -1330,19 +1233,11 @@ class CcxDetailTest(CcxRestApiTest):
'display_name': 'CCX Title',
'coach_email': 'inexisting_email@test.com'
}
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_404_NOT_FOUND, 'coach_user_does_not_exist', resp)
# test for oauth2_provider
resp = self.client.patch(
self.detail_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
self.expect_error(status.HTTP_404_NOT_FOUND, 'coach_user_does_not_exist', resp)
def test_patch_detail_wrong_modules(self):
@ddt.data(*AUTH_ATTRS)
def test_patch_detail_wrong_modules(self, auth_attr):
"""
Specific test for the case when the input data is valid but the
course modules do not belong to the master course
......@@ -1353,19 +1248,11 @@ class CcxDetailTest(CcxRestApiTest):
'block-v1:org.0+course_0+Run_0+type@chapter+block@chapter_bar'
]
}
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_module_list_not_belonging_to_master_course', resp)
# test for oauth2_provider
resp = self.client.patch(
self.detail_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_module_list_not_belonging_to_master_course', resp)
def test_patch_detail_mixed_wrong_and_valid_modules(self):
@ddt.data(*AUTH_ATTRS)
def test_patch_detail_mixed_wrong_and_valid_modules(self, auth_attr):
"""
Specific test for the case when the input data is valid but some of
the course modules do not belong to the master course
......@@ -1374,19 +1261,11 @@ class CcxDetailTest(CcxRestApiTest):
data = {
'course_modules': modules
}
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_module_list_not_belonging_to_master_course', resp)
# test for oauth2_provider
resp = self.client.patch(
self.detail_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
self.expect_error(status.HTTP_400_BAD_REQUEST, 'course_module_list_not_belonging_to_master_course', resp)
def test_patch_detail(self):
@ddt.data(*AUTH_ATTRS)
def test_patch_detail(self, auth_attr):
"""
Test for successful patch
"""
......@@ -1398,7 +1277,7 @@ class CcxDetailTest(CcxRestApiTest):
'display_name': 'CCX Title',
'coach_email': new_coach.email
}
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx_from_db = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertEqual(ccx_from_db.max_student_enrollments_allowed, data['max_students_allowed'])
......@@ -1416,116 +1295,38 @@ class CcxDetailTest(CcxRestApiTest):
self.assertEqual(len(outbox), 1)
self.assertIn(new_coach.email, outbox[0].recipients()) # pylint: disable=no-member
# test for oauth2_provider
resp = self.client.patch(
self.detail_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx_from_db = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertEqual(ccx_from_db.max_student_enrollments_allowed, data['max_students_allowed'])
self.assertEqual(ccx_from_db.display_name, data['display_name'])
self.assertEqual(ccx_from_db.coach.email, data['coach_email'])
# check that the coach user has coach role on the master course
coach_role_on_master_course = CourseCcxCoachRole(self.master_course_key)
self.assertTrue(coach_role_on_master_course.has_user(new_coach))
# check that the coach has been enrolled in the ccx
ccx_course_object = courses.get_course_by_id(self.ccx_key)
self.assertTrue(
CourseEnrollment.objects.filter(course_id=ccx_course_object.id, user=new_coach).exists()
)
# check that an email has been sent to the coach
self.assertEqual(len(outbox), 1)
self.assertIn(new_coach.email, outbox[0].recipients()) # pylint: disable=no-member
def test_patch_detail_modules(self):
@ddt.data(*AUTH_ATTRS)
def test_patch_detail_modules(self, auth_attr):
"""
Specific test for successful patch of the course modules
"""
data = {'course_modules': self.master_course_chapters[0:1]}
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx_from_db = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertItemsEqual(ccx_from_db.structure, data['course_modules'])
# test for oauth2_provider
resp = self.client.patch(
self.detail_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx_from_db = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertItemsEqual(ccx_from_db.structure, data['course_modules'])
data = {'course_modules': []}
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx_from_db = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertItemsEqual(ccx_from_db.structure, [])
# test for oauth2_provider
resp = self.client.patch(
self.detail_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx_from_db = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertItemsEqual(ccx_from_db.structure, [])
data = {'course_modules': self.master_course_chapters}
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx_from_db = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertItemsEqual(ccx_from_db.structure, self.master_course_chapters)
# test for oauth2_provider
resp = self.client.patch(
self.detail_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx_from_db = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertItemsEqual(ccx_from_db.structure, self.master_course_chapters)
data = {'course_modules': None}
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx_from_db = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertEqual(ccx_from_db.structure, None)
# test for oauth2_provider
resp = self.client.patch(
self.detail_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx_from_db = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertEqual(ccx_from_db.structure, None)
chapters = self.master_course_chapters[0:1]
data = {'course_modules': chapters * 3}
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx_from_db = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertItemsEqual(ccx_from_db.structure, chapters)
# test for oauth2_provider
resp = self.client.patch(
self.detail_url,
data,
format='json',
HTTP_AUTHORIZATION=self.auth_header_oauth2_provider
)
resp = self.client.patch(self.detail_url, data, format='json', HTTP_AUTHORIZATION=getattr(self, auth_attr))
self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
ccx_from_db = CustomCourseForEdX.objects.get(id=self.ccx.id)
self.assertItemsEqual(ccx_from_db.structure, chapters)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment