replaced unittest assertions pytest assertions (#26568)
This commit is contained in:
@@ -58,12 +58,12 @@ class CountryMiddlewareTests(TestCase):
|
||||
request.user = self.authenticated_user
|
||||
self.session_middleware.process_request(request)
|
||||
# No country code exists before request.
|
||||
self.assertNotIn('country_code', request.session)
|
||||
self.assertNotIn('ip_address', request.session)
|
||||
assert 'country_code' not in request.session
|
||||
assert 'ip_address' not in request.session
|
||||
self.country_middleware.process_request(request)
|
||||
# Country code added to session.
|
||||
self.assertEqual('CN', request.session.get('country_code'))
|
||||
self.assertEqual('117.79.83.1', request.session.get('ip_address'))
|
||||
assert 'CN' == request.session.get('country_code')
|
||||
assert '117.79.83.1' == request.session.get('ip_address')
|
||||
|
||||
def test_ip_address_changed(self):
|
||||
request = self.request_factory.get(
|
||||
@@ -76,8 +76,8 @@ class CountryMiddlewareTests(TestCase):
|
||||
request.session['ip_address'] = '117.79.83.1'
|
||||
self.country_middleware.process_request(request)
|
||||
# Country code is changed.
|
||||
self.assertEqual('SD', request.session.get('country_code'))
|
||||
self.assertEqual('4.0.0.0', request.session.get('ip_address'))
|
||||
assert 'SD' == request.session.get('country_code')
|
||||
assert '4.0.0.0' == request.session.get('ip_address')
|
||||
|
||||
def test_ip_address_is_not_changed(self):
|
||||
request = self.request_factory.get(
|
||||
@@ -90,8 +90,8 @@ class CountryMiddlewareTests(TestCase):
|
||||
request.session['ip_address'] = '117.79.83.1'
|
||||
self.country_middleware.process_request(request)
|
||||
# Country code is not changed.
|
||||
self.assertEqual('CN', request.session.get('country_code'))
|
||||
self.assertEqual('117.79.83.1', request.session.get('ip_address'))
|
||||
assert 'CN' == request.session.get('country_code')
|
||||
assert '117.79.83.1' == request.session.get('ip_address')
|
||||
|
||||
def test_same_country_different_ip(self):
|
||||
request = self.request_factory.get(
|
||||
@@ -104,8 +104,8 @@ class CountryMiddlewareTests(TestCase):
|
||||
request.session['ip_address'] = '117.79.83.1'
|
||||
self.country_middleware.process_request(request)
|
||||
# Country code is not changed.
|
||||
self.assertEqual('CN', request.session.get('country_code'))
|
||||
self.assertEqual('117.79.83.100', request.session.get('ip_address'))
|
||||
assert 'CN' == request.session.get('country_code')
|
||||
assert '117.79.83.100' == request.session.get('ip_address')
|
||||
|
||||
def test_ip_address_is_none(self):
|
||||
# IP address is not defined in request.
|
||||
@@ -118,8 +118,8 @@ class CountryMiddlewareTests(TestCase):
|
||||
request.session['ip_address'] = '117.79.83.1'
|
||||
self.country_middleware.process_request(request)
|
||||
# No country code exists after request processing.
|
||||
self.assertNotIn('country_code', request.session)
|
||||
self.assertNotIn('ip_address', request.session)
|
||||
assert 'country_code' not in request.session
|
||||
assert 'ip_address' not in request.session
|
||||
|
||||
def test_ip_address_is_ipv6(self):
|
||||
request = self.request_factory.get(
|
||||
@@ -129,10 +129,9 @@ class CountryMiddlewareTests(TestCase):
|
||||
request.user = self.authenticated_user
|
||||
self.session_middleware.process_request(request)
|
||||
# No country code exists before request.
|
||||
self.assertNotIn('country_code', request.session)
|
||||
self.assertNotIn('ip_address', request.session)
|
||||
assert 'country_code' not in request.session
|
||||
assert 'ip_address' not in request.session
|
||||
self.country_middleware.process_request(request)
|
||||
# Country code added to session.
|
||||
self.assertEqual('CN', request.session.get('country_code'))
|
||||
self.assertEqual(
|
||||
'2001:da8:20f:1502:edcf:550b:4a9c:207d', request.session.get('ip_address'))
|
||||
assert 'CN' == request.session.get('country_code')
|
||||
assert '2001:da8:20f:1502:edcf:550b:4a9c:207d' == request.session.get('ip_address')
|
||||
|
||||
@@ -20,7 +20,7 @@ class TestRemoveHeaders(TestCase):
|
||||
wrapper = remove_headers('Vary', 'Accept-Encoding')
|
||||
wrapped_view = wrapper(fake_view)
|
||||
response = wrapped_view(request)
|
||||
self.assertEqual(len(response.remove_headers), 2)
|
||||
assert len(response.remove_headers) == 2
|
||||
|
||||
|
||||
class TestForceHeader(TestCase):
|
||||
@@ -31,5 +31,5 @@ class TestForceHeader(TestCase):
|
||||
wrapper = force_header('Vary', 'Origin')
|
||||
wrapped_view = wrapper(fake_view)
|
||||
response = wrapped_view(request)
|
||||
self.assertEqual(len(response.force_headers), 1)
|
||||
self.assertEqual(response.force_headers['Vary'], 'Origin')
|
||||
assert len(response.force_headers) == 1
|
||||
assert response.force_headers['Vary'] == 'Origin'
|
||||
|
||||
@@ -22,8 +22,8 @@ class TestHeaderControlMiddlewareProcessResponse(TestCase):
|
||||
fake_response['Accept-Encoding'] = 'gzip'
|
||||
|
||||
result = self.middleware.process_response(fake_request, fake_response)
|
||||
self.assertEqual('Cookie', result['Vary'])
|
||||
self.assertEqual('gzip', result['Accept-Encoding'])
|
||||
assert 'Cookie' == result['Vary']
|
||||
assert 'gzip' == result['Accept-Encoding']
|
||||
|
||||
def test_doesnt_barf_removing_nonexistent_headers(self):
|
||||
fake_request = HttpRequest()
|
||||
@@ -34,8 +34,8 @@ class TestHeaderControlMiddlewareProcessResponse(TestCase):
|
||||
remove_headers_from_response(fake_response, 'Vary', 'FakeHeaderWeeee')
|
||||
|
||||
result = self.middleware.process_response(fake_request, fake_response)
|
||||
self.assertNotIn('Vary', result)
|
||||
self.assertEqual('gzip', result['Accept-Encoding'])
|
||||
assert 'Vary' not in result
|
||||
assert 'gzip' == result['Accept-Encoding']
|
||||
|
||||
def test_removes_intended_headers(self):
|
||||
fake_request = HttpRequest()
|
||||
@@ -46,8 +46,8 @@ class TestHeaderControlMiddlewareProcessResponse(TestCase):
|
||||
remove_headers_from_response(fake_response, 'Vary')
|
||||
|
||||
result = self.middleware.process_response(fake_request, fake_response)
|
||||
self.assertNotIn('Vary', result)
|
||||
self.assertEqual('gzip', result['Accept-Encoding'])
|
||||
assert 'Vary' not in result
|
||||
assert 'gzip' == result['Accept-Encoding']
|
||||
|
||||
def test_forces_intended_header(self):
|
||||
fake_request = HttpRequest()
|
||||
@@ -58,8 +58,8 @@ class TestHeaderControlMiddlewareProcessResponse(TestCase):
|
||||
force_header_for_response(fake_response, 'Vary', 'Origin')
|
||||
|
||||
result = self.middleware.process_response(fake_request, fake_response)
|
||||
self.assertEqual('Origin', result['Vary'])
|
||||
self.assertEqual('gzip', result['Accept-Encoding'])
|
||||
assert 'Origin' == result['Vary']
|
||||
assert 'gzip' == result['Accept-Encoding']
|
||||
|
||||
def test_does_not_mangle_undecorated_response(self):
|
||||
fake_request = HttpRequest()
|
||||
@@ -69,5 +69,5 @@ class TestHeaderControlMiddlewareProcessResponse(TestCase):
|
||||
fake_response['Accept-Encoding'] = 'gzip'
|
||||
|
||||
result = self.middleware.process_response(fake_request, fake_response)
|
||||
self.assertEqual('Cookie', result['Vary'])
|
||||
self.assertEqual('gzip', result['Accept-Encoding'])
|
||||
assert 'Cookie' == result['Vary']
|
||||
assert 'gzip' == result['Accept-Encoding']
|
||||
|
||||
@@ -28,18 +28,18 @@ class HeartbeatTestCase(ModuleStoreTestCase):
|
||||
response = self.client.get(self.heartbeat_url + '?extended')
|
||||
print(response)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_sql_fail(self):
|
||||
with patch('openedx.core.djangoapps.heartbeat.default_checks.connection') as mock_connection:
|
||||
mock_connection.cursor.return_value.execute.side_effect = DatabaseError
|
||||
response = self.client.get(self.heartbeat_url)
|
||||
self.assertEqual(response.status_code, 503)
|
||||
assert response.status_code == 503
|
||||
response_dict = json.loads(response.content.decode('utf-8'))
|
||||
self.assertIn('sql', response_dict)
|
||||
assert 'sql' in response_dict
|
||||
|
||||
def test_modulestore_fail(self):
|
||||
with patch('openedx.core.djangoapps.heartbeat.default_checks.modulestore') as mock_modulestore:
|
||||
mock_modulestore.return_value.heartbeat.side_effect = HeartbeatFailure('msg', 'service')
|
||||
response = self.client.get(self.heartbeat_url)
|
||||
self.assertEqual(response.status_code, 503)
|
||||
assert response.status_code == 503
|
||||
|
||||
@@ -42,7 +42,7 @@ class LanguageApiTest(CacheIsolationTestCase):
|
||||
"""
|
||||
with patch.dict('django.conf.settings.FEATURES', base_config):
|
||||
with with_site_configuration_context(configuration=site_config):
|
||||
self.assertEqual(language_api.header_language_selector_is_enabled(), expected)
|
||||
assert language_api.header_language_selector_is_enabled() == expected
|
||||
|
||||
@ddt.data(
|
||||
# Should return the base config value
|
||||
@@ -59,7 +59,7 @@ class LanguageApiTest(CacheIsolationTestCase):
|
||||
"""
|
||||
with patch.dict('django.conf.settings.FEATURES', base_config):
|
||||
with with_site_configuration_context(configuration=site_config):
|
||||
self.assertEqual(language_api.footer_language_selector_is_enabled(), expected)
|
||||
assert language_api.footer_language_selector_is_enabled() == expected
|
||||
|
||||
@ddt.data(*[
|
||||
('en', [], [], []),
|
||||
@@ -83,7 +83,7 @@ class LanguageApiTest(CacheIsolationTestCase):
|
||||
enabled=True
|
||||
).save()
|
||||
released_languages = language_api.released_languages()
|
||||
self.assertEqual(released_languages, expected_languages)
|
||||
assert released_languages == expected_languages
|
||||
|
||||
@override_settings(ALL_LANGUAGES=[[u"cs", u"Czech"], [u"nl", u"Dutch"]])
|
||||
def test_all_languages(self):
|
||||
@@ -93,12 +93,12 @@ class LanguageApiTest(CacheIsolationTestCase):
|
||||
with translation.override('fr'):
|
||||
all_languages = language_api.all_languages()
|
||||
|
||||
self.assertEqual(2, len(all_languages))
|
||||
self.assertLess(all_languages[0][1], all_languages[1][1])
|
||||
self.assertEqual("nl", all_languages[0][0])
|
||||
self.assertEqual("cs", all_languages[1][0])
|
||||
self.assertEqual(u"Hollandais", all_languages[0][1])
|
||||
self.assertEqual(u"Tchèque", all_languages[1][1])
|
||||
assert 2 == len(all_languages)
|
||||
assert all_languages[0][1] < all_languages[1][1]
|
||||
assert 'nl' == all_languages[0][0]
|
||||
assert 'cs' == all_languages[1][0]
|
||||
assert u'Hollandais' == all_languages[0][1]
|
||||
assert u'Tchèque' == all_languages[1][1]
|
||||
|
||||
def test_beta_languages(self):
|
||||
"""
|
||||
@@ -117,4 +117,4 @@ class LanguageApiTest(CacheIsolationTestCase):
|
||||
|
||||
released_languages = language_api.released_languages()
|
||||
expected_languages = [EN, ES_419, LT_LT]
|
||||
self.assertEqual(released_languages, expected_languages)
|
||||
assert released_languages == expected_languages
|
||||
|
||||
@@ -83,7 +83,7 @@ class TestUserPreferenceMiddleware(CacheIsolationTestCase):
|
||||
domain=settings.SESSION_COOKIE_DOMAIN,
|
||||
)
|
||||
|
||||
self.assertNotIn(LANGUAGE_SESSION_KEY, self.request.session)
|
||||
assert LANGUAGE_SESSION_KEY not in self.request.session
|
||||
|
||||
@ddt.data(*itertools.product(
|
||||
(None, 'eo', 'es'), # LANGUAGE_COOKIE
|
||||
@@ -102,7 +102,7 @@ class TestUserPreferenceMiddleware(CacheIsolationTestCase):
|
||||
self.middleware.process_request(self.request)
|
||||
|
||||
if lang_cookie is None:
|
||||
self.assertEqual(mock_set_user_preference.mock_calls, [])
|
||||
assert mock_set_user_preference.mock_calls == []
|
||||
else:
|
||||
mock_set_user_preference.assert_called_with(self.user, LANGUAGE_KEY, lang_cookie)
|
||||
|
||||
@@ -153,9 +153,9 @@ class TestUserPreferenceMiddleware(CacheIsolationTestCase):
|
||||
if accept_lang_out and accept_lang_result:
|
||||
six.assertCountEqual(self, accept_lang_result, accept_lang_out)
|
||||
else:
|
||||
self.assertEqual(accept_lang_result, accept_lang_out)
|
||||
assert accept_lang_result == accept_lang_out
|
||||
|
||||
self.assertEqual(self.request.session.get(LANGUAGE_SESSION_KEY), lang_session_out)
|
||||
assert self.request.session.get(LANGUAGE_SESSION_KEY) == lang_session_out
|
||||
|
||||
@ddt.data(None, 'es', 'en')
|
||||
def test_logout_preserves_cookie(self, lang_cookie):
|
||||
@@ -167,12 +167,9 @@ class TestUserPreferenceMiddleware(CacheIsolationTestCase):
|
||||
# explicitly clears all cookies
|
||||
self.client.get(reverse('logout'))
|
||||
if lang_cookie:
|
||||
self.assertEqual(
|
||||
self.client.cookies[settings.LANGUAGE_COOKIE].value,
|
||||
lang_cookie
|
||||
)
|
||||
assert self.client.cookies[settings.LANGUAGE_COOKIE].value == lang_cookie
|
||||
else:
|
||||
self.assertNotIn(settings.LANGUAGE_COOKIE, self.client.cookies)
|
||||
assert settings.LANGUAGE_COOKIE not in self.client.cookies
|
||||
|
||||
@ddt.data(
|
||||
(None, None),
|
||||
@@ -198,19 +195,16 @@ class TestUserPreferenceMiddleware(CacheIsolationTestCase):
|
||||
}
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
|
||||
if lang_cookie:
|
||||
self.assertEqual(response['Content-Language'], expected_lang)
|
||||
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), lang_cookie)
|
||||
self.assertEqual(
|
||||
self.client.cookies[settings.LANGUAGE_COOKIE].value,
|
||||
lang_cookie
|
||||
)
|
||||
assert response['Content-Language'] == expected_lang
|
||||
assert get_user_preference(self.user, LANGUAGE_KEY) == lang_cookie
|
||||
assert self.client.cookies[settings.LANGUAGE_COOKIE].value == lang_cookie
|
||||
else:
|
||||
self.assertEqual(response['Content-Language'], 'en')
|
||||
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), None)
|
||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE].value, '')
|
||||
assert response['Content-Language'] == 'en'
|
||||
assert get_user_preference(self.user, LANGUAGE_KEY) is None
|
||||
assert self.client.cookies[settings.LANGUAGE_COOKIE].value == ''
|
||||
|
||||
def test_process_response_no_user_noop(self):
|
||||
del self.request.user
|
||||
@@ -218,17 +212,17 @@ class TestUserPreferenceMiddleware(CacheIsolationTestCase):
|
||||
|
||||
result = self.middleware.process_response(self.request, response)
|
||||
|
||||
self.assertIs(result, response)
|
||||
self.assertEqual(response.mock_calls, [])
|
||||
assert result is response
|
||||
assert response.mock_calls == []
|
||||
|
||||
def test_preference_update_noop(self):
|
||||
self.request.COOKIES[settings.LANGUAGE_COOKIE] = 'es'
|
||||
|
||||
# No preference yet, should write to the database
|
||||
|
||||
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), None)
|
||||
assert get_user_preference(self.user, LANGUAGE_KEY) is None
|
||||
self.middleware.process_request(self.request)
|
||||
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'es')
|
||||
assert get_user_preference(self.user, LANGUAGE_KEY) == 'es'
|
||||
|
||||
response = mock.Mock(spec=HttpResponse)
|
||||
|
||||
@@ -240,7 +234,7 @@ class TestUserPreferenceMiddleware(CacheIsolationTestCase):
|
||||
with self.assertNumQueries(3):
|
||||
self.middleware.process_request(self.request)
|
||||
|
||||
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'es')
|
||||
assert get_user_preference(self.user, LANGUAGE_KEY) == 'es'
|
||||
|
||||
response = mock.Mock(spec=HttpResponse)
|
||||
|
||||
@@ -251,7 +245,7 @@ class TestUserPreferenceMiddleware(CacheIsolationTestCase):
|
||||
|
||||
self.request.COOKIES[settings.LANGUAGE_COOKIE] = 'en'
|
||||
self.middleware.process_request(self.request)
|
||||
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'en')
|
||||
assert get_user_preference(self.user, LANGUAGE_KEY) == 'en'
|
||||
|
||||
with self.assertNumQueries(1):
|
||||
self.middleware.process_response(self.request, response)
|
||||
|
||||
@@ -30,11 +30,11 @@ class TestLangPrefView(TestCase):
|
||||
# test language session updating correctly.
|
||||
self.request.session[LANGUAGE_SESSION_KEY] = 'ar'
|
||||
response = self.client.patch(reverse("session_language"), json.dumps({'pref-lang': 'eo'}))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
self.client.get('/')
|
||||
self.assertEqual(get_language(), 'eo')
|
||||
assert get_language() == 'eo'
|
||||
|
||||
response = self.client.patch(reverse("session_language"), json.dumps({'pref-lang': 'en'}))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
self.client.get('/')
|
||||
self.assertEqual(get_language(), 'en')
|
||||
assert get_language() == 'en'
|
||||
|
||||
@@ -4,7 +4,7 @@ Tests for CourseDetails
|
||||
|
||||
|
||||
import datetime
|
||||
|
||||
import pytest
|
||||
import ddt
|
||||
from pytz import UTC
|
||||
|
||||
@@ -26,109 +26,74 @@ class CourseDetailsTestCase(ModuleStoreTestCase):
|
||||
|
||||
def test_virgin_fetch(self):
|
||||
details = CourseDetails.fetch(self.course.id)
|
||||
self.assertEqual(details.org, self.course.location.org, "Org not copied into")
|
||||
self.assertEqual(details.course_id, self.course.location.course, "Course_id not copied into")
|
||||
self.assertEqual(details.run, self.course.location.block_id, "Course name not copied into")
|
||||
self.assertEqual(details.course_image_name, self.course.course_image)
|
||||
self.assertIsNotNone(details.start_date.tzinfo)
|
||||
self.assertIsNone(details.end_date, "end date somehow initialized " + str(details.end_date))
|
||||
self.assertIsNone(
|
||||
details.enrollment_start, "enrollment_start date somehow initialized " + str(details.enrollment_start)
|
||||
)
|
||||
self.assertIsNone(
|
||||
details.enrollment_end, "enrollment_end date somehow initialized " + str(details.enrollment_end)
|
||||
)
|
||||
self.assertIsNone(
|
||||
details.certificate_available_date,
|
||||
"certificate_available_date date somehow initialized " + str(details.certificate_available_date)
|
||||
)
|
||||
self.assertIsNone(details.syllabus, "syllabus somehow initialized" + str(details.syllabus))
|
||||
self.assertIsNone(details.intro_video, "intro_video somehow initialized" + str(details.intro_video))
|
||||
self.assertIsNone(details.effort, "effort somehow initialized" + str(details.effort))
|
||||
self.assertIsNone(details.language, "language somehow initialized" + str(details.language))
|
||||
self.assertFalse(details.self_paced)
|
||||
assert details.org == self.course.location.org, 'Org not copied into'
|
||||
assert details.course_id == self.course.location.course, 'Course_id not copied into'
|
||||
assert details.run == self.course.location.block_id, 'Course name not copied into'
|
||||
assert details.course_image_name == self.course.course_image
|
||||
assert details.start_date.tzinfo is not None
|
||||
assert details.end_date is None, ('end date somehow initialized ' + str(details.end_date))
|
||||
assert details.enrollment_start is None,\
|
||||
('enrollment_start date somehow initialized ' + str(details.enrollment_start))
|
||||
assert details.enrollment_end is None,\
|
||||
('enrollment_end date somehow initialized ' + str(details.enrollment_end))
|
||||
assert details.certificate_available_date is None,\
|
||||
('certificate_available_date date somehow initialized ' + str(details.certificate_available_date))
|
||||
assert details.syllabus is None, ('syllabus somehow initialized' + str(details.syllabus))
|
||||
assert details.intro_video is None, ('intro_video somehow initialized' + str(details.intro_video))
|
||||
assert details.effort is None, ('effort somehow initialized' + str(details.effort))
|
||||
assert details.language is None, ('language somehow initialized' + str(details.language))
|
||||
assert not details.self_paced
|
||||
|
||||
def test_update_and_fetch(self):
|
||||
jsondetails = CourseDetails.fetch(self.course.id)
|
||||
jsondetails.syllabus = "<a href='foo'>bar</a>"
|
||||
# encode - decode to convert date fields and other data which changes form
|
||||
with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.course.id):
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).syllabus,
|
||||
jsondetails.syllabus, "After set syllabus"
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).syllabus ==\
|
||||
jsondetails.syllabus, 'After set syllabus'
|
||||
jsondetails.short_description = "Short Description"
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).short_description,
|
||||
jsondetails.short_description, "After set short_description"
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).short_description ==\
|
||||
jsondetails.short_description, 'After set short_description'
|
||||
jsondetails.overview = "Overview"
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).overview,
|
||||
jsondetails.overview, "After set overview"
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).overview ==\
|
||||
jsondetails.overview, 'After set overview'
|
||||
jsondetails.intro_video = "intro_video"
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).intro_video,
|
||||
jsondetails.intro_video, "After set intro_video"
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).intro_video ==\
|
||||
jsondetails.intro_video, 'After set intro_video'
|
||||
jsondetails.about_sidebar_html = "About Sidebar HTML"
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).about_sidebar_html,
|
||||
jsondetails.about_sidebar_html, "After set about_sidebar_html"
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user)\
|
||||
.about_sidebar_html == jsondetails.about_sidebar_html, 'After set about_sidebar_html'
|
||||
jsondetails.effort = "effort"
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).effort,
|
||||
jsondetails.effort, "After set effort"
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).effort ==\
|
||||
jsondetails.effort, 'After set effort'
|
||||
jsondetails.self_paced = True
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).self_paced,
|
||||
jsondetails.self_paced
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).self_paced ==\
|
||||
jsondetails.self_paced
|
||||
jsondetails.start_date = datetime.datetime(2010, 10, 1, 0, tzinfo=UTC)
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).start_date,
|
||||
jsondetails.start_date
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).start_date ==\
|
||||
jsondetails.start_date
|
||||
jsondetails.end_date = datetime.datetime(2011, 10, 1, 0, tzinfo=UTC)
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).end_date,
|
||||
jsondetails.end_date
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).end_date ==\
|
||||
jsondetails.end_date
|
||||
jsondetails.certificate_available_date = datetime.datetime(2010, 10, 1, 0, tzinfo=UTC)
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(
|
||||
self.course.id, jsondetails.__dict__, self.user
|
||||
).certificate_available_date,
|
||||
jsondetails.certificate_available_date
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user)\
|
||||
.certificate_available_date == jsondetails.certificate_available_date
|
||||
jsondetails.course_image_name = "an_image.jpg"
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).course_image_name,
|
||||
jsondetails.course_image_name
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).course_image_name ==\
|
||||
jsondetails.course_image_name
|
||||
jsondetails.banner_image_name = "an_image.jpg"
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).banner_image_name,
|
||||
jsondetails.banner_image_name
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).banner_image_name ==\
|
||||
jsondetails.banner_image_name
|
||||
jsondetails.video_thumbnail_image_name = "an_image.jpg"
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).video_thumbnail_image_name, # lint-amnesty, pylint: disable=line-too-long
|
||||
jsondetails.video_thumbnail_image_name
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user)\
|
||||
.video_thumbnail_image_name == jsondetails.video_thumbnail_image_name
|
||||
jsondetails.language = "hr"
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).language,
|
||||
jsondetails.language
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).language ==\
|
||||
jsondetails.language
|
||||
jsondetails.learning_info = ["test", "test"]
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).learning_info,
|
||||
jsondetails.learning_info
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).learning_info ==\
|
||||
jsondetails.learning_info
|
||||
|
||||
jsondetails.instructor_info = {
|
||||
"instructors": [
|
||||
{
|
||||
@@ -140,10 +105,8 @@ class CourseDetailsTestCase(ModuleStoreTestCase):
|
||||
}
|
||||
]
|
||||
}
|
||||
self.assertEqual(
|
||||
CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).instructor_info,
|
||||
jsondetails.instructor_info
|
||||
)
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).instructor_info ==\
|
||||
jsondetails.instructor_info
|
||||
|
||||
def test_toggle_pacing_during_course_run(self):
|
||||
self.course.start = datetime.datetime.now()
|
||||
@@ -156,26 +119,26 @@ class CourseDetailsTestCase(ModuleStoreTestCase):
|
||||
dict(details.__dict__, self_paced=True),
|
||||
self.user
|
||||
)
|
||||
self.assertFalse(updated_details.self_paced)
|
||||
assert not updated_details.self_paced
|
||||
|
||||
@ddt.data(*ABOUT_ATTRIBUTES)
|
||||
def test_fetch_about_attribute(self, attribute_name):
|
||||
attribute_value = 'test_value'
|
||||
with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.course.id):
|
||||
CourseDetails.update_about_item(self.course, attribute_name, attribute_value, self.user.id)
|
||||
self.assertEqual(CourseDetails.fetch_about_attribute(self.course.id, attribute_name), attribute_value)
|
||||
assert CourseDetails.fetch_about_attribute(self.course.id, attribute_name) == attribute_value
|
||||
|
||||
def test_fetch_about_attribute_error(self):
|
||||
attribute_name = 'not_an_about_attribute'
|
||||
with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.course.id):
|
||||
CourseDetails.update_about_item(self.course, attribute_name, 'test_value', self.user.id)
|
||||
with self.assertRaises(ValueError):
|
||||
with pytest.raises(ValueError):
|
||||
CourseDetails.fetch_about_attribute(self.course.id, attribute_name)
|
||||
|
||||
def test_fetch_video(self):
|
||||
video_value = 'test_video_id'
|
||||
with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.course.id):
|
||||
CourseDetails.update_about_video(self.course, video_value, self.user.id)
|
||||
self.assertEqual(CourseDetails.fetch_youtube_video_id(self.course.id), video_value)
|
||||
assert CourseDetails.fetch_youtube_video_id(self.course.id) == video_value
|
||||
video_url = CourseDetails.fetch_video_url(self.course.id)
|
||||
self.assertRegex(video_url, r'http://.*{}'.format(video_value))
|
||||
|
||||
@@ -46,4 +46,4 @@ class TestAdapters(unittest.TestCase):
|
||||
</problem>
|
||||
"""
|
||||
olx_out = adapters.rewrite_absolute_static_urls(olx_in, course_id)
|
||||
self.assertEqual(olx_out, olx_expected)
|
||||
assert olx_out == olx_expected
|
||||
|
||||
@@ -50,7 +50,7 @@ class OlxRestApiTestCase(SharedModuleStoreTestCase):
|
||||
xml_str = re.sub(r'(\s)\s+', r'\1', xml_str)
|
||||
xml_bytes = xml_str.encode('utf8')
|
||||
return minidom.parseString(xml_bytes).toprettyxml()
|
||||
self.assertEqual(clean(xml_str_a), clean(xml_str_b))
|
||||
assert clean(xml_str_a) == clean(xml_str_b)
|
||||
|
||||
def get_olx_response_for_block(self, block_id):
|
||||
return self.client.get('/api/olx-export/v1/xblock/{}/'.format(block_id))
|
||||
@@ -63,11 +63,9 @@ class OlxRestApiTestCase(SharedModuleStoreTestCase):
|
||||
team) should not be able to use the API.
|
||||
"""
|
||||
response = self.get_olx_response_for_block(self.unit_key)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertEqual(
|
||||
response.json()['detail'],
|
||||
'You must be a member of the course team in Studio to export OLX using this API.'
|
||||
)
|
||||
assert response.status_code == 403
|
||||
assert response.json()['detail'] ==\
|
||||
'You must be a member of the course team in Studio to export OLX using this API.'
|
||||
|
||||
def test_export(self):
|
||||
"""
|
||||
@@ -77,11 +75,8 @@ class OlxRestApiTestCase(SharedModuleStoreTestCase):
|
||||
CourseStaffRole(self.course.id).add_users(self.user)
|
||||
|
||||
response = self.get_olx_response_for_block(self.unit_key)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(
|
||||
response.json()['root_block_id'],
|
||||
str(self.unit_key),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json()['root_block_id'] == str(self.unit_key)
|
||||
blocks = response.json()['blocks']
|
||||
# Check the OLX of the root block:
|
||||
self.assertXmlEqual(
|
||||
@@ -110,8 +105,8 @@ class OlxRestApiTestCase(SharedModuleStoreTestCase):
|
||||
|
||||
block_id = str(self.course.id.make_usage_key('html', 'just_img'))
|
||||
response = self.get_olx_response_for_block(block_id)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.json()['root_block_id'], block_id)
|
||||
assert response.status_code == 200
|
||||
assert response.json()['root_block_id'] == block_id
|
||||
block_data = response.json()['blocks'][block_id]
|
||||
self.assertXmlEqual(
|
||||
block_data['olx'],
|
||||
@@ -121,7 +116,7 @@ class OlxRestApiTestCase(SharedModuleStoreTestCase):
|
||||
]]></html>
|
||||
'''
|
||||
)
|
||||
self.assertIn('static_files', block_data)
|
||||
self.assertIn('foo_bar.jpg', block_data['static_files'])
|
||||
assert 'static_files' in block_data
|
||||
assert 'foo_bar.jpg' in block_data['static_files']
|
||||
url = block_data['static_files']['foo_bar.jpg']['url']
|
||||
self.assertEqual(url, 'http://testserver/asset-v1:edX+toy+2012_Fall+type@asset+block@foo_bar.jpg')
|
||||
assert url == 'http://testserver/asset-v1:edX+toy+2012_Fall+type@asset+block@foo_bar.jpg'
|
||||
|
||||
@@ -31,8 +31,8 @@ class TestApps(TestCase):
|
||||
app.ready()
|
||||
config = settings.PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG
|
||||
|
||||
self.assertEqual(mock_log.exception.call_count, 1)
|
||||
self.assertIsNone(config['STAFF_USER_COMPLIANCE_DEADLINE'])
|
||||
assert mock_log.exception.call_count == 1
|
||||
assert config['STAFF_USER_COMPLIANCE_DEADLINE'] is None
|
||||
|
||||
self.assertIsInstance(config['GENERAL_USER_COMPLIANCE_DEADLINE'], datetime.datetime)
|
||||
self.assertEqual(config['GENERAL_USER_COMPLIANCE_DEADLINE'], parse_date('2018-01-01 00:00:00+00:00'))
|
||||
assert isinstance(config['GENERAL_USER_COMPLIANCE_DEADLINE'], datetime.datetime)
|
||||
assert config['GENERAL_USER_COMPLIANCE_DEADLINE'] == parse_date('2018-01-01 00:00:00+00:00')
|
||||
|
||||
@@ -4,6 +4,7 @@ Test password policy utilities
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytest
|
||||
import pytz
|
||||
from dateutil.parser import parse as parse_date
|
||||
from django.test import TestCase, override_settings
|
||||
@@ -36,7 +37,7 @@ class TestCompliance(TestCase):
|
||||
Test that if the config is disabled or nonexistent nothing is returned
|
||||
"""
|
||||
# Parameters don't matter for this method as it only tests the config
|
||||
self.assertTrue(should_enforce_compliance_on_login())
|
||||
assert should_enforce_compliance_on_login()
|
||||
|
||||
def test_enforce_compliance_on_login(self):
|
||||
"""
|
||||
@@ -57,7 +58,7 @@ class TestCompliance(TestCase):
|
||||
with patch('openedx.core.djangoapps.password_policy.compliance._check_user_compliance') as \
|
||||
mock_check_user_compliance:
|
||||
mock_check_user_compliance.return_value = True
|
||||
self.assertIsNone(enforce_compliance_on_login(user, password))
|
||||
assert enforce_compliance_on_login(user, password) is None
|
||||
|
||||
# Test no deadline is set
|
||||
with patch('openedx.core.djangoapps.password_policy.compliance._check_user_compliance') as \
|
||||
@@ -66,7 +67,7 @@ class TestCompliance(TestCase):
|
||||
with patch('openedx.core.djangoapps.password_policy.compliance._get_compliance_deadline_for_user') as \
|
||||
mock_get_compliance_deadline_for_user:
|
||||
mock_get_compliance_deadline_for_user.return_value = None
|
||||
self.assertIsNone(enforce_compliance_on_login(user, password))
|
||||
assert enforce_compliance_on_login(user, password) is None
|
||||
|
||||
# Test deadline is in the past
|
||||
with patch('openedx.core.djangoapps.password_policy.compliance._check_user_compliance') as \
|
||||
@@ -75,7 +76,7 @@ class TestCompliance(TestCase):
|
||||
with patch('openedx.core.djangoapps.password_policy.compliance._get_compliance_deadline_for_user') as \
|
||||
mock_get_compliance_deadline_for_user:
|
||||
mock_get_compliance_deadline_for_user.return_value = datetime.now(pytz.UTC) - timedelta(1)
|
||||
self.assertRaises(NonCompliantPasswordException, enforce_compliance_on_login, user, password)
|
||||
pytest.raises(NonCompliantPasswordException, enforce_compliance_on_login, user, password)
|
||||
|
||||
# Test deadline is in the future
|
||||
with patch('openedx.core.djangoapps.password_policy.compliance._check_user_compliance') as \
|
||||
@@ -84,7 +85,7 @@ class TestCompliance(TestCase):
|
||||
with patch('openedx.core.djangoapps.password_policy.compliance._get_compliance_deadline_for_user') as \
|
||||
mock_get_compliance_deadline_for_user:
|
||||
mock_get_compliance_deadline_for_user.return_value = datetime.now(pytz.UTC) + timedelta(1)
|
||||
self.assertRaises(NonCompliantPasswordWarning, enforce_compliance_on_login, user, password)
|
||||
assert pytest.raises(NonCompliantPasswordWarning, enforce_compliance_on_login, user, password)
|
||||
|
||||
def test_check_user_compliance(self):
|
||||
"""
|
||||
@@ -99,7 +100,8 @@ class TestCompliance(TestCase):
|
||||
user = UserFactory()
|
||||
# Mock validate_password to return True without checking the password
|
||||
mock_validate_password.return_value = True
|
||||
self.assertTrue(_check_user_compliance(user, None)) # Don't need a password here
|
||||
assert _check_user_compliance(user, None)
|
||||
# Don't need a password here
|
||||
|
||||
# Test that a user that does not pass validate_password returns False
|
||||
with patch('openedx.core.djangoapps.password_policy.compliance.validate_password') as \
|
||||
@@ -107,7 +109,8 @@ class TestCompliance(TestCase):
|
||||
user = UserFactory()
|
||||
# Mock validate_password to throw a ValidationError without checking the password
|
||||
mock_validate_password.side_effect = ValidationError('Some validation error')
|
||||
self.assertFalse(_check_user_compliance(user, None)) # Don't need a password here
|
||||
assert not _check_user_compliance(user, None)
|
||||
# Don't need a password here
|
||||
|
||||
@override_settings(PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG={
|
||||
'STAFF_USER_COMPLIANCE_DEADLINE': date1,
|
||||
@@ -123,15 +126,15 @@ class TestCompliance(TestCase):
|
||||
"""
|
||||
# Staff user returned the STAFF_USER_COMPLIANCE_DEADLINE
|
||||
user = UserFactory(is_staff=True)
|
||||
self.assertEqual(date1, _get_compliance_deadline_for_user(user))
|
||||
assert date1 == _get_compliance_deadline_for_user(user)
|
||||
|
||||
# User with CourseAccessRole returns the ELEVATED_PRIVILEGE_USER_COMPLIANCE_DEADLINE
|
||||
user = UserFactory()
|
||||
CourseAccessRoleFactory.create(user=user)
|
||||
self.assertEqual(date2, _get_compliance_deadline_for_user(user))
|
||||
assert date2 == _get_compliance_deadline_for_user(user)
|
||||
|
||||
user = UserFactory()
|
||||
self.assertEqual(date3, _get_compliance_deadline_for_user(user))
|
||||
assert date3 == _get_compliance_deadline_for_user(user)
|
||||
|
||||
def test_get_compliance_deadline_for_user_fallbacks(self):
|
||||
"""
|
||||
@@ -148,43 +151,43 @@ class TestCompliance(TestCase):
|
||||
'GENERAL_USER_COMPLIANCE_DEADLINE': date3
|
||||
}
|
||||
with self.settings(PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG=only_general):
|
||||
self.assertEqual(date3, _get_compliance_deadline_for_user(staff))
|
||||
self.assertEqual(date3, _get_compliance_deadline_for_user(privileged))
|
||||
self.assertEqual(date3, _get_compliance_deadline_for_user(both))
|
||||
assert date3 == _get_compliance_deadline_for_user(staff)
|
||||
assert date3 == _get_compliance_deadline_for_user(privileged)
|
||||
assert date3 == _get_compliance_deadline_for_user(both)
|
||||
|
||||
no_staff = {
|
||||
'ELEVATED_PRIVILEGE_USER_COMPLIANCE_DEADLINE': date2,
|
||||
'GENERAL_USER_COMPLIANCE_DEADLINE': date3
|
||||
}
|
||||
with self.settings(PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG=no_staff):
|
||||
self.assertEqual(date2, _get_compliance_deadline_for_user(both))
|
||||
self.assertEqual(date2, _get_compliance_deadline_for_user(staff))
|
||||
assert date2 == _get_compliance_deadline_for_user(both)
|
||||
assert date2 == _get_compliance_deadline_for_user(staff)
|
||||
|
||||
no_privileged = {
|
||||
'STAFF_USER_COMPLIANCE_DEADLINE': date1,
|
||||
'GENERAL_USER_COMPLIANCE_DEADLINE': date3
|
||||
}
|
||||
with self.settings(PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG=no_privileged):
|
||||
self.assertEqual(date1, _get_compliance_deadline_for_user(both))
|
||||
self.assertEqual(date3, _get_compliance_deadline_for_user(privileged))
|
||||
assert date1 == _get_compliance_deadline_for_user(both)
|
||||
assert date3 == _get_compliance_deadline_for_user(privileged)
|
||||
|
||||
only_privileged = {
|
||||
'ELEVATED_PRIVILEGE_USER_COMPLIANCE_DEADLINE': date2,
|
||||
}
|
||||
with self.settings(PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG=only_privileged):
|
||||
self.assertEqual(date2, _get_compliance_deadline_for_user(both))
|
||||
self.assertEqual(date2, _get_compliance_deadline_for_user(staff))
|
||||
self.assertIsNone(_get_compliance_deadline_for_user(user))
|
||||
assert date2 == _get_compliance_deadline_for_user(both)
|
||||
assert date2 == _get_compliance_deadline_for_user(staff)
|
||||
assert _get_compliance_deadline_for_user(user) is None
|
||||
|
||||
early_elevated = {
|
||||
'STAFF_USER_COMPLIANCE_DEADLINE': date2,
|
||||
'ELEVATED_PRIVILEGE_USER_COMPLIANCE_DEADLINE': date1,
|
||||
}
|
||||
with self.settings(PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG=early_elevated):
|
||||
self.assertEqual(date1, _get_compliance_deadline_for_user(both))
|
||||
self.assertEqual(date2, _get_compliance_deadline_for_user(staff))
|
||||
self.assertEqual(date1, _get_compliance_deadline_for_user(privileged))
|
||||
self.assertIsNone(_get_compliance_deadline_for_user(user))
|
||||
assert date1 == _get_compliance_deadline_for_user(both)
|
||||
assert date2 == _get_compliance_deadline_for_user(staff)
|
||||
assert date1 == _get_compliance_deadline_for_user(privileged)
|
||||
assert _get_compliance_deadline_for_user(user) is None
|
||||
|
||||
early_general = {
|
||||
'STAFF_USER_COMPLIANCE_DEADLINE': date3,
|
||||
@@ -192,7 +195,7 @@ class TestCompliance(TestCase):
|
||||
'GENERAL_USER_COMPLIANCE_DEADLINE': date1,
|
||||
}
|
||||
with self.settings(PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG=early_general):
|
||||
self.assertEqual(date1, _get_compliance_deadline_for_user(both))
|
||||
self.assertEqual(date1, _get_compliance_deadline_for_user(staff))
|
||||
self.assertEqual(date1, _get_compliance_deadline_for_user(privileged))
|
||||
self.assertEqual(date1, _get_compliance_deadline_for_user(user))
|
||||
assert date1 == _get_compliance_deadline_for_user(both)
|
||||
assert date1 == _get_compliance_deadline_for_user(staff)
|
||||
assert date1 == _get_compliance_deadline_for_user(privileged)
|
||||
assert date1 == _get_compliance_deadline_for_user(user)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Test password policy forms
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import mock
|
||||
|
||||
from django.forms import ValidationError
|
||||
@@ -34,8 +34,8 @@ class PasswordPolicyAwareAdminAuthFormTests(TestCase):
|
||||
Verify that the username and password are returned when compliance is disabled
|
||||
"""
|
||||
cleaned_data = self.auth_form.clean()
|
||||
self.assertEqual(cleaned_data.get('username'), 'test_user')
|
||||
self.assertTrue(cleaned_data.get('password'), 'test_password')
|
||||
assert cleaned_data.get('username') == 'test_user'
|
||||
assert cleaned_data.get('password'), 'test_password'
|
||||
|
||||
@override_settings(PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG={'ENFORCE_COMPLIANCE_ON_LOGIN': True})
|
||||
def test_auth_form_policy_enabled(self):
|
||||
@@ -47,8 +47,8 @@ class PasswordPolicyAwareAdminAuthFormTests(TestCase):
|
||||
) as mock_enforce_compliance_on_login:
|
||||
mock_enforce_compliance_on_login.return_value = True
|
||||
cleaned_data = self.auth_form.clean()
|
||||
self.assertEqual(cleaned_data.get('username'), self.user.username)
|
||||
self.assertTrue(cleaned_data.get('password'), self.user.password)
|
||||
assert cleaned_data.get('username') == self.user.username
|
||||
assert cleaned_data.get('password'), self.user.password
|
||||
|
||||
@override_settings(PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG={'ENFORCE_COMPLIANCE_ON_LOGIN': True})
|
||||
def test_auth_form_policy_enabled_with_warning(self):
|
||||
@@ -64,8 +64,8 @@ class PasswordPolicyAwareAdminAuthFormTests(TestCase):
|
||||
) as mock_enforce_compliance_on_login:
|
||||
mock_enforce_compliance_on_login.side_effect = NonCompliantPasswordWarning('Test warning')
|
||||
cleaned_data = self.auth_form.clean()
|
||||
self.assertEqual(cleaned_data.get('username'), self.user.username)
|
||||
self.assertTrue(cleaned_data.get('password'))
|
||||
assert cleaned_data.get('username') == self.user.username
|
||||
assert cleaned_data.get('password')
|
||||
|
||||
@override_settings(PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG={'ENFORCE_COMPLIANCE_ON_LOGIN': True})
|
||||
def test_auth_form_policy_enabled_with_exception(self):
|
||||
@@ -76,4 +76,4 @@ class PasswordPolicyAwareAdminAuthFormTests(TestCase):
|
||||
'openedx.core.djangoapps.password_policy.forms.password_policy_compliance.enforce_compliance_on_login'
|
||||
) as mock_enforce_compliance_on_login:
|
||||
mock_enforce_compliance_on_login.side_effect = NonCompliantPasswordException('Test exception')
|
||||
self.assertRaises(ValidationError, self.auth_form.clean)
|
||||
pytest.raises(ValidationError, self.auth_form.clean)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Test cases for image processing functions in the profile image package.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from contextlib import closing
|
||||
from itertools import product
|
||||
import os
|
||||
@@ -46,12 +47,12 @@ class TestValidateUploadedImage(TestCase):
|
||||
Internal DRY helper.
|
||||
"""
|
||||
if expected_failure_message is not None:
|
||||
with self.assertRaises(ImageValidationError) as ctx:
|
||||
with pytest.raises(ImageValidationError) as ctx:
|
||||
validate_uploaded_image(uploaded_file)
|
||||
self.assertEqual(text_type(ctx.exception), expected_failure_message)
|
||||
assert text_type(ctx.value) == expected_failure_message
|
||||
else:
|
||||
validate_uploaded_image(uploaded_file)
|
||||
self.assertEqual(uploaded_file.tell(), 0)
|
||||
assert uploaded_file.tell() == 0
|
||||
|
||||
@ddt.data(
|
||||
(99, u"The file must be at least 100 bytes in size."),
|
||||
@@ -105,9 +106,9 @@ class TestValidateUploadedImage(TestCase):
|
||||
content_type="image/jpeg",
|
||||
size=os.path.getsize(fake_jpeg_file.name)
|
||||
)
|
||||
with self.assertRaises(ImageValidationError) as ctx:
|
||||
with pytest.raises(ImageValidationError) as ctx:
|
||||
validate_uploaded_image(uploaded_file)
|
||||
self.assertEqual(text_type(ctx.exception), file_upload_bad_ext)
|
||||
assert text_type(ctx.value) == file_upload_bad_ext
|
||||
|
||||
def test_content_type(self):
|
||||
"""
|
||||
@@ -119,9 +120,9 @@ class TestValidateUploadedImage(TestCase):
|
||||
u'the file data. The file may be corrupted.'
|
||||
)
|
||||
with make_uploaded_file(extension=".jpeg", content_type="image/gif") as uploaded_file:
|
||||
with self.assertRaises(ImageValidationError) as ctx:
|
||||
with pytest.raises(ImageValidationError) as ctx:
|
||||
validate_uploaded_image(uploaded_file)
|
||||
self.assertEqual(text_type(ctx.exception), file_upload_bad_mimetype)
|
||||
assert text_type(ctx.value) == file_upload_bad_mimetype
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -135,12 +136,12 @@ class TestGenerateProfileImages(TestCase):
|
||||
"""
|
||||
Check that the created object is a JPEG and that it has the expected
|
||||
"""
|
||||
self.assertEqual(image.format, 'JPEG')
|
||||
assert image.format == 'JPEG'
|
||||
if expected_orientation is not None:
|
||||
self.assertIn('exif', image.info)
|
||||
self.assertEqual(_get_exif_orientation(image.info['exif']), expected_orientation)
|
||||
assert 'exif' in image.info
|
||||
assert _get_exif_orientation(image.info['exif']) == expected_orientation
|
||||
else:
|
||||
self.assertIsNone(_get_exif_orientation(image.info.get('exif', piexif.dump({}))))
|
||||
assert _get_exif_orientation(image.info.get('exif', piexif.dump({}))) is None
|
||||
|
||||
@ddt.data(
|
||||
*product(
|
||||
@@ -168,9 +169,9 @@ class TestGenerateProfileImages(TestCase):
|
||||
for name, image_obj in names_and_images:
|
||||
# get the size of the image file and ensure it's square jpeg
|
||||
width, height = image_obj.size
|
||||
self.assertEqual(width, height)
|
||||
assert width == height
|
||||
actual_sizes[width] = name
|
||||
self.assertEqual(requested_sizes, actual_sizes)
|
||||
assert requested_sizes == actual_sizes
|
||||
|
||||
def test_jpeg_with_exif_orientation(self):
|
||||
requested_images = {10: "ten.jpg", 100: "hunnert.jpg"}
|
||||
@@ -194,10 +195,7 @@ class TestGenerateProfileImages(TestCase):
|
||||
for _, image in self._create_mocked_profile_images(imfile, requested_images):
|
||||
self.check_exif_orientation(image, None)
|
||||
exif = image.info.get('exif', piexif.dump({}))
|
||||
self.assertEqual(
|
||||
_update_exif_orientation(exif, None),
|
||||
image.info.get('exif', piexif.dump({}))
|
||||
)
|
||||
assert _update_exif_orientation(exif, None) == image.info.get('exif', piexif.dump({}))
|
||||
|
||||
def _create_mocked_profile_images(self, image_file, requested_images):
|
||||
"""
|
||||
@@ -215,7 +213,7 @@ class TestGenerateProfileImages(TestCase):
|
||||
):
|
||||
create_profile_images(image_file, requested_images)
|
||||
names_and_files = [v[0] for v in mock_storage.save.call_args_list]
|
||||
self.assertEqual(len(names_and_files), len(requested_images))
|
||||
assert len(names_and_files) == len(requested_images)
|
||||
for name, file_ in names_and_files:
|
||||
with closing(Image.open(file_)) as image:
|
||||
yield name, image
|
||||
@@ -244,5 +242,5 @@ class TestRemoveProfileImages(TestCase):
|
||||
):
|
||||
remove_profile_images(requested_sizes)
|
||||
deleted_names = [v[0][0] for v in mock_storage.delete.call_args_list]
|
||||
self.assertEqual(list(requested_sizes.values()), deleted_names)
|
||||
assert list(requested_sizes.values()) == deleted_names
|
||||
mock_storage.save.reset_mock()
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Test cases for the HTTP endpoints of the profile image api.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from contextlib import closing
|
||||
import datetime
|
||||
from pytz import UTC
|
||||
@@ -54,7 +55,7 @@ class ProfileImageEndpointMixin(UserSettingsEventTestMixin):
|
||||
self.table = 'auth_userprofile'
|
||||
# this assertion is made here as a sanity check because all tests
|
||||
# assume user.profile.has_profile_image is False by default
|
||||
self.assertFalse(self.user.profile.has_profile_image)
|
||||
assert not self.user.profile.has_profile_image
|
||||
|
||||
# Reset the mock event tracker so that we're not considering the
|
||||
# initial profile creation events.
|
||||
@@ -74,26 +75,26 @@ class ProfileImageEndpointMixin(UserSettingsEventTestMixin):
|
||||
"""
|
||||
for size, name in get_profile_image_names(self.user.username).items():
|
||||
if exist:
|
||||
self.assertTrue(self.storage.exists(name))
|
||||
assert self.storage.exists(name)
|
||||
with closing(Image.open(self.storage.path(name))) as img:
|
||||
self.assertEqual(img.size, (size, size))
|
||||
self.assertEqual(img.format, 'JPEG')
|
||||
assert img.size == (size, size)
|
||||
assert img.format == 'JPEG'
|
||||
else:
|
||||
self.assertFalse(self.storage.exists(name))
|
||||
assert not self.storage.exists(name)
|
||||
|
||||
def check_response(self, response, expected_code, expected_developer_message=None, expected_user_message=None):
|
||||
"""
|
||||
Make sure the response has the expected code, and if that isn't 204,
|
||||
optionally check the correctness of a developer-facing message.
|
||||
"""
|
||||
self.assertEqual(expected_code, response.status_code)
|
||||
assert expected_code == response.status_code
|
||||
if expected_code == 204:
|
||||
self.assertIsNone(response.data)
|
||||
assert response.data is None
|
||||
else:
|
||||
if expected_developer_message is not None:
|
||||
self.assertEqual(response.data.get('developer_message'), expected_developer_message)
|
||||
assert response.data.get('developer_message') == expected_developer_message
|
||||
if expected_user_message is not None:
|
||||
self.assertEqual(response.data.get('user_message'), expected_user_message)
|
||||
assert response.data.get('user_message') == expected_user_message
|
||||
|
||||
def check_has_profile_image(self, has_profile_image=True):
|
||||
"""
|
||||
@@ -103,7 +104,7 @@ class ProfileImageEndpointMixin(UserSettingsEventTestMixin):
|
||||
# it's necessary to reload this model from the database since save()
|
||||
# would have been called on another instance.
|
||||
profile = self.user.profile.__class__.objects.get(user=self.user)
|
||||
self.assertEqual(profile.has_profile_image, has_profile_image)
|
||||
assert profile.has_profile_image == has_profile_image
|
||||
|
||||
def check_anonymous_request_rejected(self, method):
|
||||
"""
|
||||
@@ -128,10 +129,10 @@ class ProfileImageViewGeneralTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
"""
|
||||
Test that GET, PUT, and PATCH are not supported.
|
||||
"""
|
||||
self.assertEqual(405, self.client.get(self.url).status_code)
|
||||
self.assertEqual(405, self.client.put(self.url).status_code)
|
||||
self.assertEqual(405, self.client.patch(self.url).status_code)
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert 405 == self.client.get(self.url).status_code
|
||||
assert 405 == self.client.put(self.url).status_code
|
||||
assert 405 == self.client.patch(self.url).status_code
|
||||
assert not mock_log.info.called
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
|
||||
@@ -161,7 +162,7 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
Test that an anonymous client (not logged in) cannot call POST.
|
||||
"""
|
||||
self.check_anonymous_request_rejected('post')
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
|
||||
@ddt.data('.jpg', '.jpeg', '.jpg', '.jpeg', '.png', '.gif', '.GIF')
|
||||
@patch(
|
||||
@@ -238,7 +239,7 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
self.check_response(response, 415)
|
||||
self.check_images(False)
|
||||
self.check_has_profile_image(False)
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
def test_upload_nonexistent_user(self, mock_log):
|
||||
@@ -251,7 +252,7 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
with make_image_file() as image_file:
|
||||
response = self.client.post(nonexistent_user_url, {'file': image_file}, format='multipart')
|
||||
self.check_response(response, 403)
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
|
||||
def test_upload_other(self, mock_log):
|
||||
"""
|
||||
@@ -268,7 +269,7 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
self.check_response(response, 403)
|
||||
self.check_images(False)
|
||||
self.check_has_profile_image(False)
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
def test_upload_staff(self, mock_log):
|
||||
@@ -286,7 +287,7 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
self.check_response(response, 403)
|
||||
self.check_images(False)
|
||||
self.check_has_profile_image(False)
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
def test_upload_missing_file(self, mock_log):
|
||||
@@ -301,7 +302,7 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
)
|
||||
self.check_images(False)
|
||||
self.check_has_profile_image(False)
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
def test_upload_not_a_file(self, mock_log):
|
||||
@@ -317,7 +318,7 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
)
|
||||
self.check_images(False)
|
||||
self.check_has_profile_image(False)
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
def test_upload_validation(self, mock_log):
|
||||
@@ -338,7 +339,7 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
)
|
||||
self.check_images(False)
|
||||
self.check_has_profile_image(False)
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
@patch('PIL.Image.open')
|
||||
@@ -349,11 +350,11 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
"""
|
||||
image_open.side_effect = [Exception(u"whoops"), None]
|
||||
with make_image_file() as image_file:
|
||||
with self.assertRaises(Exception):
|
||||
with pytest.raises(Exception):
|
||||
self.client.post(self.url, {'file': image_file}, format='multipart')
|
||||
self.check_images(False)
|
||||
self.check_has_profile_image(False)
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
|
||||
@@ -388,7 +389,7 @@ class ProfileImageViewDeleteTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
Test that an anonymous client (not logged in) cannot call DELETE.
|
||||
"""
|
||||
self.check_anonymous_request_rejected('delete')
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
|
||||
def test_remove_self(self, mock_log):
|
||||
"""
|
||||
@@ -419,7 +420,7 @@ class ProfileImageViewDeleteTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
self.check_response(response, 403)
|
||||
self.check_images(True) # thumbnails should remain intact.
|
||||
self.check_has_profile_image(True)
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
def test_remove_staff(self, mock_log):
|
||||
@@ -447,11 +448,11 @@ class ProfileImageViewDeleteTestCase(ProfileImageEndpointMixin, APITestCase):
|
||||
messages are returned.
|
||||
"""
|
||||
user_profile_save.side_effect = [Exception(u"whoops"), None]
|
||||
with self.assertRaises(Exception):
|
||||
with pytest.raises(Exception):
|
||||
self.client.delete(self.url)
|
||||
self.check_images(True) # thumbnails should remain intact.
|
||||
self.check_has_profile_image(True)
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
|
||||
@@ -468,11 +469,11 @@ class DeprecatedProfileImageTestMixin(ProfileImageEndpointMixin):
|
||||
"""
|
||||
Test that GET, PUT, PATCH, and DELETE are not supported.
|
||||
"""
|
||||
self.assertEqual(405, self.client.get(self.url).status_code)
|
||||
self.assertEqual(405, self.client.put(self.url).status_code)
|
||||
self.assertEqual(405, self.client.patch(self.url).status_code)
|
||||
self.assertEqual(405, self.client.delete(self.url).status_code)
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert 405 == self.client.get(self.url).status_code
|
||||
assert 405 == self.client.put(self.url).status_code
|
||||
assert 405 == self.client.patch(self.url).status_code
|
||||
assert 405 == self.client.delete(self.url).status_code
|
||||
assert not mock_log.info.called
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
def test_post_calls_replacement_view_method(self, mock_log):
|
||||
@@ -483,7 +484,7 @@ class DeprecatedProfileImageTestMixin(ProfileImageEndpointMixin):
|
||||
mock_method.return_value = HttpResponse()
|
||||
self.client.post(self.url)
|
||||
assert mock_method.called
|
||||
self.assertFalse(mock_log.info.called)
|
||||
assert not mock_log.info.called
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
|
||||
|
||||
@@ -289,8 +289,8 @@ class BackpopulateProgramCredentialsTests(CatalogIntegrationMixin, CredentialsAp
|
||||
passing_status = CertificateStatuses.downloadable
|
||||
failing_status = CertificateStatuses.notpassing
|
||||
|
||||
self.assertIn(passing_status, CertificateStatuses.PASSED_STATUSES)
|
||||
self.assertNotIn(failing_status, CertificateStatuses.PASSED_STATUSES)
|
||||
assert passing_status in CertificateStatuses.PASSED_STATUSES
|
||||
assert failing_status not in CertificateStatuses.PASSED_STATUSES
|
||||
|
||||
GeneratedCertificateFactory(
|
||||
user=self.alice,
|
||||
@@ -382,7 +382,7 @@ class BackpopulateProgramCredentialsTests(CatalogIntegrationMixin, CredentialsAp
|
||||
|
||||
call_command('backpopulate_program_credentials', commit=True)
|
||||
|
||||
self.assertTrue(mock_log.called)
|
||||
assert mock_log.called
|
||||
|
||||
calls = [
|
||||
mock.call(self.alice.username),
|
||||
|
||||
@@ -62,7 +62,7 @@ class CertAwardedReceiverTest(TestCase):
|
||||
known to take place inside the function.
|
||||
"""
|
||||
COURSE_CERT_AWARDED.send(**self.signal_kwargs)
|
||||
self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1)
|
||||
assert mock_is_learner_issuance_enabled.call_count == 1
|
||||
|
||||
def test_programs_disabled(self, mock_is_learner_issuance_enabled, mock_task):
|
||||
"""
|
||||
@@ -70,8 +70,8 @@ class CertAwardedReceiverTest(TestCase):
|
||||
configuration is not enabled.
|
||||
"""
|
||||
handle_course_cert_awarded(**self.signal_kwargs)
|
||||
self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1)
|
||||
self.assertEqual(mock_task.call_count, 0)
|
||||
assert mock_is_learner_issuance_enabled.call_count == 1
|
||||
assert mock_task.call_count == 0
|
||||
|
||||
def test_programs_enabled(self, mock_is_learner_issuance_enabled, mock_task):
|
||||
"""
|
||||
@@ -82,9 +82,9 @@ class CertAwardedReceiverTest(TestCase):
|
||||
|
||||
handle_course_cert_awarded(**self.signal_kwargs)
|
||||
|
||||
self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1)
|
||||
self.assertEqual(mock_task.call_count, 1)
|
||||
self.assertEqual(mock_task.call_args[0], (TEST_USERNAME,))
|
||||
assert mock_is_learner_issuance_enabled.call_count == 1
|
||||
assert mock_task.call_count == 1
|
||||
assert mock_task.call_args[0] == (TEST_USERNAME,)
|
||||
|
||||
|
||||
# The credentials app isn't installed for the CMS.
|
||||
@@ -127,7 +127,7 @@ class CertChangedReceiverTest(TestCase):
|
||||
known to take place inside the function.
|
||||
"""
|
||||
COURSE_CERT_CHANGED.send(**self.signal_kwargs)
|
||||
self.assertEqual(mock_is_learner_issuance_enabled.call_count, 2)
|
||||
assert mock_is_learner_issuance_enabled.call_count == 2
|
||||
|
||||
def test_credentials_disabled(self, mock_is_learner_issuance_enabled, mock_task):
|
||||
"""
|
||||
@@ -135,8 +135,8 @@ class CertChangedReceiverTest(TestCase):
|
||||
configuration is not enabled.
|
||||
"""
|
||||
handle_course_cert_changed(**self.signal_kwargs)
|
||||
self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1)
|
||||
self.assertEqual(mock_task.call_count, 0)
|
||||
assert mock_is_learner_issuance_enabled.call_count == 1
|
||||
assert mock_task.call_count == 0
|
||||
|
||||
def test_credentials_enabled(self, mock_is_learner_issuance_enabled, mock_task):
|
||||
"""
|
||||
@@ -147,9 +147,9 @@ class CertChangedReceiverTest(TestCase):
|
||||
|
||||
handle_course_cert_changed(**self.signal_kwargs)
|
||||
|
||||
self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1)
|
||||
self.assertEqual(mock_task.call_count, 1)
|
||||
self.assertEqual(mock_task.call_args[0], (TEST_USERNAME, str(TEST_COURSE_KEY)))
|
||||
assert mock_is_learner_issuance_enabled.call_count == 1
|
||||
assert mock_task.call_count == 1
|
||||
assert mock_task.call_args[0] == (TEST_USERNAME, str(TEST_COURSE_KEY))
|
||||
|
||||
def test_records_enabled(self, mock_is_learner_issuance_enabled, mock_task):
|
||||
mock_is_learner_issuance_enabled.return_value = True
|
||||
@@ -160,14 +160,14 @@ class CertChangedReceiverTest(TestCase):
|
||||
|
||||
# Correctly sent
|
||||
handle_course_cert_changed(**self.signal_kwargs)
|
||||
self.assertTrue(mock_task.called)
|
||||
assert mock_task.called
|
||||
mock_task.reset_mock()
|
||||
|
||||
# Correctly not sent
|
||||
site_config.site_values['ENABLE_LEARNER_RECORDS'] = False
|
||||
site_config.save()
|
||||
handle_course_cert_changed(**self.signal_kwargs)
|
||||
self.assertFalse(mock_task.called)
|
||||
assert not mock_task.called
|
||||
|
||||
|
||||
# The credentials app isn't installed for the CMS.
|
||||
@@ -206,7 +206,7 @@ class CertRevokedReceiverTest(TestCase):
|
||||
known to take place inside the function.
|
||||
"""
|
||||
COURSE_CERT_REVOKED.send(**self.signal_kwargs)
|
||||
self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1)
|
||||
assert mock_is_learner_issuance_enabled.call_count == 1
|
||||
|
||||
def test_programs_disabled(self, mock_is_learner_issuance_enabled, mock_task):
|
||||
"""
|
||||
@@ -214,8 +214,8 @@ class CertRevokedReceiverTest(TestCase):
|
||||
configuration is not enabled.
|
||||
"""
|
||||
handle_course_cert_revoked(**self.signal_kwargs)
|
||||
self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1)
|
||||
self.assertEqual(mock_task.call_count, 0)
|
||||
assert mock_is_learner_issuance_enabled.call_count == 1
|
||||
assert mock_task.call_count == 0
|
||||
|
||||
def test_programs_enabled(self, mock_is_learner_issuance_enabled, mock_task):
|
||||
"""
|
||||
@@ -226,9 +226,9 @@ class CertRevokedReceiverTest(TestCase):
|
||||
|
||||
handle_course_cert_revoked(**self.signal_kwargs)
|
||||
|
||||
self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1)
|
||||
self.assertEqual(mock_task.call_count, 1)
|
||||
self.assertEqual(mock_task.call_args[0], (TEST_USERNAME, TEST_COURSE_KEY))
|
||||
assert mock_is_learner_issuance_enabled.call_count == 1
|
||||
assert mock_task.call_count == 1
|
||||
assert mock_task.call_args[0] == (TEST_USERNAME, TEST_COURSE_KEY)
|
||||
|
||||
|
||||
@skip_unless_lms
|
||||
@@ -263,7 +263,7 @@ class CourseCertAvailableDateChangedReceiverTest(TestCase):
|
||||
known to take place inside the function.
|
||||
"""
|
||||
COURSE_CERT_DATE_CHANGE.send(**self.signal_kwargs)
|
||||
self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1)
|
||||
assert mock_is_learner_issuance_enabled.call_count == 1
|
||||
|
||||
def test_programs_disabled(self, mock_is_learner_issuance_enabled, mock_task):
|
||||
"""
|
||||
@@ -271,8 +271,8 @@ class CourseCertAvailableDateChangedReceiverTest(TestCase):
|
||||
configuration is not enabled.
|
||||
"""
|
||||
handle_course_cert_date_change(**self.signal_kwargs)
|
||||
self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1)
|
||||
self.assertEqual(mock_task.call_count, 0)
|
||||
assert mock_is_learner_issuance_enabled.call_count == 1
|
||||
assert mock_task.call_count == 0
|
||||
|
||||
def test_programs_enabled(self, mock_is_learner_issuance_enabled, mock_task):
|
||||
"""
|
||||
@@ -283,5 +283,5 @@ class CourseCertAvailableDateChangedReceiverTest(TestCase):
|
||||
|
||||
handle_course_cert_date_change(**self.signal_kwargs)
|
||||
|
||||
self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1)
|
||||
self.assertEqual(mock_task.call_count, 1)
|
||||
assert mock_is_learner_issuance_enabled.call_count == 1
|
||||
assert mock_task.call_count == 1
|
||||
|
||||
@@ -6,7 +6,7 @@ Tests for programs celery tasks.
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytest
|
||||
import ddt
|
||||
import httpretty
|
||||
import mock
|
||||
@@ -70,9 +70,9 @@ class GetAwardedCertificateProgramsTestCase(TestCase):
|
||||
]
|
||||
|
||||
result = tasks.get_certified_programs(student)
|
||||
self.assertEqual(mock_get_credentials.call_args[0], (student,))
|
||||
self.assertEqual(mock_get_credentials.call_args[1], {'credential_type': 'program'})
|
||||
self.assertEqual(result, [1])
|
||||
assert mock_get_credentials.call_args[0] == (student,)
|
||||
assert mock_get_credentials.call_args[1] == {'credential_type': 'program'}
|
||||
assert result == [1]
|
||||
|
||||
|
||||
@skip_unless_lms
|
||||
@@ -110,7 +110,7 @@ class AwardProgramCertificateTestCase(TestCase):
|
||||
]
|
||||
}
|
||||
last_request_body = httpretty.last_request().body.decode('utf-8')
|
||||
self.assertEqual(json.loads(last_request_body), expected_body)
|
||||
assert json.loads(last_request_body) == expected_body
|
||||
|
||||
|
||||
@skip_unless_lms
|
||||
@@ -171,10 +171,11 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
tasks.award_program_certificates.delay(self.student.username).get()
|
||||
|
||||
actual_program_uuids = [call[0][2] for call in mock_award_program_certificate.call_args_list]
|
||||
self.assertEqual(actual_program_uuids, expected_awarded_program_uuids)
|
||||
assert actual_program_uuids == expected_awarded_program_uuids
|
||||
|
||||
actual_visible_dates = [call[0][3] for call in mock_award_program_certificate.call_args_list]
|
||||
self.assertEqual(actual_visible_dates, expected_awarded_program_uuids) # program uuids are same as mock dates
|
||||
assert actual_visible_dates == expected_awarded_program_uuids
|
||||
# program uuids are same as mock dates
|
||||
|
||||
@mock.patch('openedx.core.djangoapps.site_configuration.helpers.get_current_site_configuration')
|
||||
def test_awarding_certs_with_skip_program_certificate(
|
||||
@@ -208,9 +209,10 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
|
||||
tasks.award_program_certificates.delay(self.student.username).get()
|
||||
actual_program_uuids = [call[0][2] for call in mock_award_program_certificate.call_args_list]
|
||||
self.assertEqual(actual_program_uuids, expected_awarded_program_uuids)
|
||||
assert actual_program_uuids == expected_awarded_program_uuids
|
||||
actual_visible_dates = [call[0][3] for call in mock_award_program_certificate.call_args_list]
|
||||
self.assertEqual(actual_visible_dates, expected_awarded_program_uuids) # program uuids are same as mock dates
|
||||
assert actual_visible_dates == expected_awarded_program_uuids
|
||||
# program uuids are same as mock dates
|
||||
|
||||
@ddt.data(
|
||||
('credentials', 'enable_learner_issuance'),
|
||||
@@ -228,11 +230,11 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
"""
|
||||
getattr(self, 'create_{}_config'.format(disabled_config_type))(**{disabled_config_attribute: False})
|
||||
with mock.patch(TASKS_MODULE + '.LOGGER.warning') as mock_warning:
|
||||
with self.assertRaises(MaxRetriesExceededError):
|
||||
with pytest.raises(MaxRetriesExceededError):
|
||||
tasks.award_program_certificates.delay(self.student.username).get()
|
||||
self.assertTrue(mock_warning.called)
|
||||
assert mock_warning.called
|
||||
for mock_helper in mock_helpers:
|
||||
self.assertFalse(mock_helper.called)
|
||||
assert not mock_helper.called
|
||||
|
||||
def test_abort_if_invalid_username(self, *mock_helpers):
|
||||
"""
|
||||
@@ -241,9 +243,9 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
"""
|
||||
with mock.patch(TASKS_MODULE + '.LOGGER.exception') as mock_exception:
|
||||
tasks.award_program_certificates.delay('nonexistent-username').get()
|
||||
self.assertTrue(mock_exception.called)
|
||||
assert mock_exception.called
|
||||
for mock_helper in mock_helpers:
|
||||
self.assertFalse(mock_helper.called)
|
||||
assert not mock_helper.called
|
||||
|
||||
def test_abort_if_no_completed_programs(
|
||||
self,
|
||||
@@ -257,9 +259,9 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
"""
|
||||
mock_get_completed_programs.return_value = {}
|
||||
tasks.award_program_certificates.delay(self.student.username).get()
|
||||
self.assertTrue(mock_get_completed_programs.called)
|
||||
self.assertFalse(mock_get_certified_programs.called)
|
||||
self.assertFalse(mock_award_program_certificate.called)
|
||||
assert mock_get_completed_programs.called
|
||||
assert not mock_get_certified_programs.called
|
||||
assert not mock_award_program_certificate.called
|
||||
|
||||
@mock.patch('openedx.core.djangoapps.site_configuration.helpers.get_value')
|
||||
def test_programs_without_certificates(
|
||||
@@ -276,9 +278,9 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
mock_get_value.return_value = ["ALL"]
|
||||
mock_get_completed_programs.return_value = {1: 1, 2: 2}
|
||||
tasks.award_program_certificates.delay(self.student.username).get()
|
||||
self.assertFalse(mock_get_completed_programs.called)
|
||||
self.assertFalse(mock_get_certified_programs.called)
|
||||
self.assertFalse(mock_award_program_certificate.called)
|
||||
assert not mock_get_completed_programs.called
|
||||
assert not mock_get_certified_programs.called
|
||||
assert not mock_award_program_certificate.called
|
||||
|
||||
@mock.patch(TASKS_MODULE + '.get_credentials_api_client')
|
||||
def test_failure_to_create_api_client_retries(
|
||||
@@ -296,12 +298,12 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
mock_get_certified_programs.return_value = [2]
|
||||
|
||||
with mock.patch(TASKS_MODULE + '.LOGGER.exception') as mock_exception:
|
||||
with self.assertRaises(MaxRetriesExceededError):
|
||||
with pytest.raises(MaxRetriesExceededError):
|
||||
tasks.award_program_certificates.delay(self.student.username).get()
|
||||
|
||||
self.assertTrue(mock_exception.called)
|
||||
self.assertEqual(mock_get_api_client.call_count, tasks.MAX_RETRIES + 1)
|
||||
self.assertFalse(mock_award_program_certificate.called)
|
||||
assert mock_exception.called
|
||||
assert mock_get_api_client.call_count == (tasks.MAX_RETRIES + 1)
|
||||
assert not mock_award_program_certificate.called
|
||||
|
||||
def _make_side_effect(self, side_effects):
|
||||
"""
|
||||
@@ -344,7 +346,7 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
mock.patch(TASKS_MODULE + '.LOGGER.warning') as mock_warning:
|
||||
tasks.award_program_certificates.delay(self.student.username).get()
|
||||
|
||||
self.assertEqual(mock_award_program_certificate.call_count, 3)
|
||||
assert mock_award_program_certificate.call_count == 3
|
||||
mock_warning.assert_called_once_with(
|
||||
u'Failed to award certificate for program {uuid} to user {username}.'.format(
|
||||
uuid=1,
|
||||
@@ -366,7 +368,7 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
"""
|
||||
mock_get_completed_programs.side_effect = self._make_side_effect([Exception('boom'), None])
|
||||
tasks.award_program_certificates.delay(self.student.username).get()
|
||||
self.assertEqual(mock_get_completed_programs.call_count, 3)
|
||||
assert mock_get_completed_programs.call_count == 3
|
||||
|
||||
def test_retry_on_credentials_api_errors(
|
||||
self,
|
||||
@@ -384,8 +386,8 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
mock_get_certified_programs.return_value = [1]
|
||||
mock_get_certified_programs.side_effect = self._make_side_effect([Exception('boom'), None])
|
||||
tasks.award_program_certificates.delay(self.student.username).get()
|
||||
self.assertEqual(mock_get_certified_programs.call_count, 2)
|
||||
self.assertEqual(mock_award_program_certificate.call_count, 1)
|
||||
assert mock_get_certified_programs.call_count == 2
|
||||
assert mock_award_program_certificate.call_count == 1
|
||||
|
||||
def test_retry_on_credentials_api_429_error(
|
||||
self,
|
||||
@@ -405,7 +407,7 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
|
||||
tasks.award_program_certificates.delay(self.student.username).get()
|
||||
|
||||
self.assertEqual(mock_award_program_certificate.call_count, 3)
|
||||
assert mock_award_program_certificate.call_count == 3
|
||||
|
||||
def test_no_retry_on_credentials_api_404_error(
|
||||
self,
|
||||
@@ -425,7 +427,7 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
|
||||
tasks.award_program_certificates.delay(self.student.username).get()
|
||||
|
||||
self.assertEqual(mock_award_program_certificate.call_count, 2)
|
||||
assert mock_award_program_certificate.call_count == 2
|
||||
|
||||
def test_no_retry_on_credentials_api_4XX_error(
|
||||
self,
|
||||
@@ -445,7 +447,7 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
|
||||
tasks.award_program_certificates.delay(self.student.username).get()
|
||||
|
||||
self.assertEqual(mock_award_program_certificate.call_count, 2)
|
||||
assert mock_award_program_certificate.call_count == 2
|
||||
|
||||
|
||||
@skip_unless_lms
|
||||
@@ -496,7 +498,7 @@ class PostCourseCertificateTestCase(TestCase):
|
||||
}]
|
||||
}
|
||||
last_request_body = httpretty.last_request().body.decode('utf-8')
|
||||
self.assertEqual(json.loads(last_request_body), expected_body)
|
||||
assert json.loads(last_request_body) == expected_body
|
||||
|
||||
|
||||
@skip_unless_lms
|
||||
@@ -544,9 +546,9 @@ class AwardCourseCertificatesTestCase(CredentialsApiConfigMixin, TestCase):
|
||||
self.certificate.save()
|
||||
tasks.award_course_certificate.delay(self.student.username, str(self.course.id)).get()
|
||||
call_args, _ = mock_post_course_certificate.call_args
|
||||
self.assertEqual(call_args[1], self.student.username)
|
||||
self.assertEqual(call_args[2], self.certificate)
|
||||
self.assertEqual(call_args[3], self.certificate.modified_date)
|
||||
assert call_args[1] == self.student.username
|
||||
assert call_args[2] == self.certificate
|
||||
assert call_args[3] == self.certificate.modified_date
|
||||
|
||||
def test_award_course_certificates_available_date(self, mock_post_course_certificate):
|
||||
"""
|
||||
@@ -556,9 +558,9 @@ class AwardCourseCertificatesTestCase(CredentialsApiConfigMixin, TestCase):
|
||||
self.course.save()
|
||||
tasks.award_course_certificate.delay(self.student.username, str(self.course.id)).get()
|
||||
call_args, _ = mock_post_course_certificate.call_args
|
||||
self.assertEqual(call_args[1], self.student.username)
|
||||
self.assertEqual(call_args[2], self.certificate)
|
||||
self.assertEqual(call_args[3], self.available_date)
|
||||
assert call_args[1] == self.student.username
|
||||
assert call_args[2] == self.certificate
|
||||
assert call_args[3] == self.available_date
|
||||
|
||||
def test_award_course_cert_not_called_if_disabled(self, mock_post_course_certificate):
|
||||
"""
|
||||
@@ -566,10 +568,10 @@ class AwardCourseCertificatesTestCase(CredentialsApiConfigMixin, TestCase):
|
||||
"""
|
||||
self.create_credentials_config(enabled=False)
|
||||
with mock.patch(TASKS_MODULE + '.LOGGER.warning') as mock_warning:
|
||||
with self.assertRaises(MaxRetriesExceededError):
|
||||
with pytest.raises(MaxRetriesExceededError):
|
||||
tasks.award_course_certificate.delay(self.student.username, str(self.course.id)).get()
|
||||
self.assertTrue(mock_warning.called)
|
||||
self.assertFalse(mock_post_course_certificate.called)
|
||||
assert mock_warning.called
|
||||
assert not mock_post_course_certificate.called
|
||||
|
||||
def test_award_course_cert_not_called_if_user_not_found(self, mock_post_course_certificate):
|
||||
"""
|
||||
@@ -578,8 +580,8 @@ class AwardCourseCertificatesTestCase(CredentialsApiConfigMixin, TestCase):
|
||||
with mock.patch(TASKS_MODULE + '.LOGGER.exception') as mock_exception:
|
||||
# Use a random username here since this user won't be found in the DB
|
||||
tasks.award_course_certificate.delay('random_username', str(self.course.id)).get()
|
||||
self.assertTrue(mock_exception.called)
|
||||
self.assertFalse(mock_post_course_certificate.called)
|
||||
assert mock_exception.called
|
||||
assert not mock_post_course_certificate.called
|
||||
|
||||
def test_award_course_cert_not_called_if_certificate_not_found(self, mock_post_course_certificate):
|
||||
"""
|
||||
@@ -588,8 +590,8 @@ class AwardCourseCertificatesTestCase(CredentialsApiConfigMixin, TestCase):
|
||||
self.certificate.delete()
|
||||
with mock.patch(TASKS_MODULE + '.LOGGER.exception') as mock_exception:
|
||||
tasks.award_course_certificate.delay(self.student.username, str(self.course.id)).get()
|
||||
self.assertTrue(mock_exception.called)
|
||||
self.assertFalse(mock_post_course_certificate.called)
|
||||
assert mock_exception.called
|
||||
assert not mock_post_course_certificate.called
|
||||
|
||||
def test_award_course_cert_not_called_if_course_overview_not_found(self, mock_post_course_certificate):
|
||||
"""
|
||||
@@ -599,8 +601,8 @@ class AwardCourseCertificatesTestCase(CredentialsApiConfigMixin, TestCase):
|
||||
with mock.patch(TASKS_MODULE + '.LOGGER.exception') as mock_exception:
|
||||
# Use the certificate course id here since the course will be deleted
|
||||
tasks.award_course_certificate.delay(self.student.username, str(self.certificate.course_id)).get()
|
||||
self.assertTrue(mock_exception.called)
|
||||
self.assertFalse(mock_post_course_certificate.called)
|
||||
assert mock_exception.called
|
||||
assert not mock_post_course_certificate.called
|
||||
|
||||
def test_award_course_cert_not_called_if_certificated_not_verified_mode(self, mock_post_course_certificate):
|
||||
"""
|
||||
@@ -613,7 +615,7 @@ class AwardCourseCertificatesTestCase(CredentialsApiConfigMixin, TestCase):
|
||||
self.create_credentials_config()
|
||||
|
||||
tasks.award_course_certificate.delay(self.student.username, str(self.certificate.course_id)).get()
|
||||
self.assertFalse(mock_post_course_certificate.called)
|
||||
assert not mock_post_course_certificate.called
|
||||
|
||||
|
||||
@skip_unless_lms
|
||||
@@ -646,7 +648,7 @@ class RevokeProgramCertificateTestCase(TestCase):
|
||||
}
|
||||
}
|
||||
last_request_body = httpretty.last_request().body.decode('utf-8')
|
||||
self.assertEqual(json.loads(last_request_body), expected_body)
|
||||
assert json.loads(last_request_body) == expected_body
|
||||
|
||||
|
||||
@skip_unless_lms
|
||||
@@ -705,8 +707,8 @@ class RevokeProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiC
|
||||
tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get()
|
||||
|
||||
call_args, _ = mock_revoke_program_certificate.call_args
|
||||
self.assertEqual(call_args[1], self.student.username)
|
||||
self.assertEqual(call_args[2], expected_program_uuid)
|
||||
assert call_args[1] == self.student.username
|
||||
assert call_args[2] == expected_program_uuid
|
||||
|
||||
@ddt.data(
|
||||
('credentials', 'enable_learner_issuance'),
|
||||
@@ -724,11 +726,11 @@ class RevokeProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiC
|
||||
"""
|
||||
getattr(self, 'create_{}_config'.format(disabled_config_type))(**{disabled_config_attribute: False})
|
||||
with mock.patch(TASKS_MODULE + '.LOGGER.warning') as mock_warning:
|
||||
with self.assertRaises(MaxRetriesExceededError):
|
||||
with pytest.raises(MaxRetriesExceededError):
|
||||
tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get()
|
||||
self.assertTrue(mock_warning.called)
|
||||
assert mock_warning.called
|
||||
for mock_helper in mock_helpers:
|
||||
self.assertFalse(mock_helper.called)
|
||||
assert not mock_helper.called
|
||||
|
||||
def test_abort_if_invalid_username(self, *mock_helpers):
|
||||
"""
|
||||
@@ -737,9 +739,9 @@ class RevokeProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiC
|
||||
"""
|
||||
with mock.patch(TASKS_MODULE + '.LOGGER.exception') as mock_exception:
|
||||
tasks.revoke_program_certificates.delay('nonexistent-username', self.course_key).get()
|
||||
self.assertTrue(mock_exception.called)
|
||||
assert mock_exception.called
|
||||
for mock_helper in mock_helpers:
|
||||
self.assertFalse(mock_helper.called)
|
||||
assert not mock_helper.called
|
||||
|
||||
def test_abort_if_no_program(
|
||||
self,
|
||||
@@ -753,9 +755,9 @@ class RevokeProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiC
|
||||
"""
|
||||
mock_get_inverted_programs.return_value = {}
|
||||
tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get()
|
||||
self.assertTrue(mock_get_inverted_programs.called)
|
||||
self.assertFalse(mock_get_certified_programs.called)
|
||||
self.assertFalse(mock_revoke_program_certificate.called)
|
||||
assert mock_get_inverted_programs.called
|
||||
assert not mock_get_certified_programs.called
|
||||
assert not mock_revoke_program_certificate.called
|
||||
|
||||
def _make_side_effect(self, side_effects):
|
||||
"""
|
||||
@@ -798,7 +800,7 @@ class RevokeProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiC
|
||||
mock.patch(TASKS_MODULE + '.LOGGER.warning') as mock_warning:
|
||||
tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get()
|
||||
|
||||
self.assertEqual(mock_revoke_program_certificate.call_count, 3)
|
||||
assert mock_revoke_program_certificate.call_count == 3
|
||||
mock_warning.assert_called_once_with(
|
||||
u'Failed to revoke certificate for program {uuid} of user {username}.'.format(
|
||||
uuid=1,
|
||||
@@ -823,8 +825,8 @@ class RevokeProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiC
|
||||
mock_get_certified_programs.return_value = [1]
|
||||
mock_get_certified_programs.side_effect = self._make_side_effect([Exception('boom'), None])
|
||||
tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get()
|
||||
self.assertEqual(mock_get_certified_programs.call_count, 2)
|
||||
self.assertEqual(mock_revoke_program_certificate.call_count, 1)
|
||||
assert mock_get_certified_programs.call_count == 2
|
||||
assert mock_revoke_program_certificate.call_count == 1
|
||||
|
||||
def test_retry_on_credentials_api_429_error(
|
||||
self,
|
||||
@@ -845,7 +847,7 @@ class RevokeProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiC
|
||||
|
||||
tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get()
|
||||
|
||||
self.assertEqual(mock_revoke_program_certificate.call_count, 3)
|
||||
assert mock_revoke_program_certificate.call_count == 3
|
||||
|
||||
def test_no_retry_on_credentials_api_404_error(
|
||||
self,
|
||||
@@ -866,7 +868,7 @@ class RevokeProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiC
|
||||
|
||||
tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get()
|
||||
|
||||
self.assertEqual(mock_revoke_program_certificate.call_count, 2)
|
||||
assert mock_revoke_program_certificate.call_count == 2
|
||||
|
||||
def test_no_retry_on_credentials_api_4XX_error(
|
||||
self,
|
||||
@@ -887,7 +889,7 @@ class RevokeProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiC
|
||||
|
||||
tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get()
|
||||
|
||||
self.assertEqual(mock_revoke_program_certificate.call_count, 2)
|
||||
assert mock_revoke_program_certificate.call_count == 2
|
||||
|
||||
def test_get_api_client_failure_retries(
|
||||
self,
|
||||
@@ -907,8 +909,8 @@ class RevokeProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiC
|
||||
TASKS_MODULE + '.LOGGER.exception'
|
||||
) as mock_exception:
|
||||
mock_get_api_client.side_effect = Exception("boom")
|
||||
with self.assertRaises(MaxRetriesExceededError):
|
||||
with pytest.raises(MaxRetriesExceededError):
|
||||
tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get()
|
||||
self.assertTrue(mock_exception.called)
|
||||
self.assertEqual(mock_get_api_client.call_count, tasks.MAX_RETRIES + 1)
|
||||
self.assertFalse(mock_revoke_program_certificate.called)
|
||||
assert mock_exception.called
|
||||
assert mock_get_api_client.call_count == (tasks.MAX_RETRIES + 1)
|
||||
assert not mock_revoke_program_certificate.called
|
||||
|
||||
@@ -91,7 +91,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
|
||||
def _assert_progress(self, meter, *progresses):
|
||||
"""Variadic helper used to verify progress calculations."""
|
||||
self.assertEqual(meter.progress(), list(progresses))
|
||||
assert meter.progress() == list(progresses)
|
||||
|
||||
def _attach_detail_url(self, programs):
|
||||
"""Add expected detail URLs to a list of program dicts."""
|
||||
@@ -105,9 +105,9 @@ class TestProgramProgressMeter(TestCase):
|
||||
|
||||
meter = ProgramProgressMeter(self.site, self.user)
|
||||
|
||||
self.assertEqual(meter.engaged_programs, [])
|
||||
assert meter.engaged_programs == []
|
||||
self._assert_progress(meter)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == []
|
||||
|
||||
def test_enrollments_but_no_programs(self, mock_get_programs):
|
||||
"""Verify behavior when enrollments exist, but no matching programs do."""
|
||||
@@ -117,9 +117,9 @@ class TestProgramProgressMeter(TestCase):
|
||||
self._create_enrollments(course_run_id)
|
||||
meter = ProgramProgressMeter(self.site, self.user)
|
||||
|
||||
self.assertEqual(meter.engaged_programs, [])
|
||||
assert meter.engaged_programs == []
|
||||
self._assert_progress(meter)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == []
|
||||
|
||||
def test_entitlements_but_no_programs(self, mock_get_programs):
|
||||
""" Verify engaged_programs is empty when entitlements exist, but no matching programs do. """
|
||||
@@ -128,7 +128,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
self._create_entitlements(uuid.uuid4())
|
||||
meter = ProgramProgressMeter(self.site, self.user)
|
||||
|
||||
self.assertEqual(meter.engaged_programs, [])
|
||||
assert meter.engaged_programs == []
|
||||
|
||||
def test_single_program_enrollment(self, mock_get_programs):
|
||||
"""
|
||||
@@ -153,12 +153,12 @@ class TestProgramProgressMeter(TestCase):
|
||||
|
||||
self._attach_detail_url(data)
|
||||
program = data[0]
|
||||
self.assertEqual(meter.engaged_programs, [program])
|
||||
assert meter.engaged_programs == [program]
|
||||
self._assert_progress(
|
||||
meter,
|
||||
ProgressFactory(uuid=program['uuid'], in_progress=1)
|
||||
)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == []
|
||||
|
||||
def test_single_program_entitlement(self, mock_get_programs):
|
||||
"""
|
||||
@@ -177,7 +177,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
|
||||
self._attach_detail_url(data)
|
||||
program = data[0]
|
||||
self.assertEqual(meter.engaged_programs, [program])
|
||||
assert meter.engaged_programs == [program]
|
||||
|
||||
def test_single_program_multiple_entitlements(self, mock_get_programs):
|
||||
"""
|
||||
@@ -221,11 +221,11 @@ class TestProgramProgressMeter(TestCase):
|
||||
|
||||
meter = ProgramProgressMeter(self.site, self.user)
|
||||
self._attach_detail_url(data)
|
||||
self.assertEqual(len(meter.entitlements), 1)
|
||||
assert len(meter.entitlements) == 1
|
||||
|
||||
entitlement = meter.entitlements[0]
|
||||
self.assertIsNone(entitlement.expired_at)
|
||||
self.assertEqual(entitlement.enrollment_course_run.course_id, enrollment2.course_id)
|
||||
assert entitlement.expired_at is None
|
||||
assert entitlement.enrollment_course_run.course_id == enrollment2.course_id
|
||||
|
||||
def test_course_progress(self, mock_get_programs):
|
||||
"""
|
||||
@@ -258,7 +258,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
)
|
||||
]
|
||||
|
||||
self.assertEqual(meter.progress(count_only=False), expected)
|
||||
assert meter.progress(count_only=False) == expected
|
||||
|
||||
def test_no_id_professional_in_progress(self, mock_get_programs):
|
||||
"""
|
||||
@@ -294,7 +294,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
)
|
||||
]
|
||||
|
||||
self.assertEqual(meter.progress(count_only=False), expected)
|
||||
assert meter.progress(count_only=False) == expected
|
||||
|
||||
@ddt.data(None, 1, -1)
|
||||
def test_in_progress_course_upgrade_deadline_check(self, offset, mock_get_programs):
|
||||
@@ -335,7 +335,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
)
|
||||
]
|
||||
|
||||
self.assertEqual(meter.progress(count_only=True), expected)
|
||||
assert meter.progress(count_only=True) == expected
|
||||
|
||||
def test_multiple_program_enrollment(self, mock_get_programs):
|
||||
"""
|
||||
@@ -369,13 +369,13 @@ class TestProgramProgressMeter(TestCase):
|
||||
|
||||
self._attach_detail_url(data)
|
||||
programs = data[:2]
|
||||
self.assertEqual(meter.engaged_programs, programs)
|
||||
assert meter.engaged_programs == programs
|
||||
|
||||
self._assert_progress(
|
||||
meter,
|
||||
*(ProgressFactory(uuid=program['uuid'], in_progress=1) for program in programs)
|
||||
)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == []
|
||||
|
||||
def test_multiple_program_entitlement(self, mock_get_programs):
|
||||
"""
|
||||
@@ -397,7 +397,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
|
||||
self._attach_detail_url(data)
|
||||
programs = data[:2]
|
||||
self.assertEqual(meter.engaged_programs, programs)
|
||||
assert meter.engaged_programs == programs
|
||||
|
||||
def test_shared_enrollment_engagement(self, mock_get_programs):
|
||||
"""
|
||||
@@ -437,13 +437,13 @@ class TestProgramProgressMeter(TestCase):
|
||||
|
||||
self._attach_detail_url(data)
|
||||
programs = data[:3]
|
||||
self.assertEqual(meter.engaged_programs, programs)
|
||||
assert meter.engaged_programs == programs
|
||||
|
||||
self._assert_progress(
|
||||
meter,
|
||||
*(ProgressFactory(uuid=program['uuid'], in_progress=1) for program in programs)
|
||||
)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == []
|
||||
|
||||
def test_shared_entitlement_engagement(self, mock_get_programs):
|
||||
"""
|
||||
@@ -471,7 +471,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
|
||||
self._attach_detail_url(data)
|
||||
programs = data[:3]
|
||||
self.assertEqual(meter.engaged_programs, programs)
|
||||
assert meter.engaged_programs == programs
|
||||
|
||||
def test_simulate_progress(self, mock_get_programs):
|
||||
"""Simulate the entirety of a user's progress through a program."""
|
||||
@@ -494,7 +494,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
# No enrollments, no programs in progress.
|
||||
meter = ProgramProgressMeter(self.site, self.user)
|
||||
self._assert_progress(meter)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == []
|
||||
|
||||
# One enrollment, one program in progress.
|
||||
self._create_enrollments(first_course_run_key)
|
||||
@@ -504,7 +504,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
meter,
|
||||
ProgressFactory(uuid=program_uuid, in_progress=1, not_started=1)
|
||||
)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == []
|
||||
|
||||
# Two enrollments, all courses in progress.
|
||||
self._create_enrollments(second_course_run_key)
|
||||
@@ -516,7 +516,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
in_progress=2,
|
||||
)
|
||||
)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == []
|
||||
|
||||
# One valid certificate earned, one course complete.
|
||||
self._create_certificates(first_course_run_key, mode=MODES.verified)
|
||||
@@ -529,7 +529,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
in_progress=1,
|
||||
)
|
||||
)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == []
|
||||
|
||||
# Invalid certificate earned, still one course to complete. (invalid because mode doesn't match the course)
|
||||
second_cert = self._create_certificates(second_course_run_key, mode=MODES.honor)[0]
|
||||
@@ -543,7 +543,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
in_progress=1,
|
||||
)
|
||||
)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == []
|
||||
|
||||
# Second valid certificate obtained, all courses complete.
|
||||
second_cert.mode = MODES.verified
|
||||
@@ -556,7 +556,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
completed=2,
|
||||
)
|
||||
)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [program_uuid])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == [program_uuid]
|
||||
|
||||
def test_nonverified_course_run_completion(self, mock_get_programs):
|
||||
"""
|
||||
@@ -586,7 +586,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
meter,
|
||||
ProgressFactory(uuid=program_uuid, completed=1)
|
||||
)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [program_uuid])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == [program_uuid]
|
||||
|
||||
@mock.patch(UTILS_MODULE + '.available_date_for_certificate')
|
||||
def test_completed_programs_with_available_dates(self, mock_available_date_for_certificate, mock_get_programs):
|
||||
@@ -674,7 +674,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
|
||||
# Verify that the test program is not complete.
|
||||
meter = ProgramProgressMeter(self.site, self.user)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == []
|
||||
|
||||
# Grant a 'no-id-professional' certificate for one of the course runs,
|
||||
# thereby completing the program.
|
||||
@@ -683,7 +683,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
|
||||
# Verify that the program is complete.
|
||||
meter = ProgramProgressMeter(self.site, self.user)
|
||||
self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [program['uuid']])
|
||||
assert list(meter.completed_programs_with_available_dates.keys()) == [program['uuid']]
|
||||
|
||||
@mock.patch(UTILS_MODULE + '.ProgramProgressMeter.completed_course_runs', new_callable=mock.PropertyMock)
|
||||
def test_credit_course_counted_complete_for_verified(self, mock_completed_course_runs, mock_get_programs):
|
||||
@@ -700,7 +700,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
self._create_enrollments(course_run_key)
|
||||
meter = ProgramProgressMeter(self.site, self.user)
|
||||
mock_completed_course_runs.return_value = [{'course_run_id': course_run_key, 'type': CourseMode.VERIFIED}]
|
||||
self.assertEqual(meter._is_course_complete(course), True) # lint-amnesty, pylint: disable=protected-access
|
||||
assert meter._is_course_complete(course) is True # lint-amnesty, pylint: disable=protected-access
|
||||
|
||||
def test_detail_url_for_mobile_only(self, mock_get_programs):
|
||||
"""
|
||||
@@ -727,7 +727,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
path_id = detail_fragment_url.replace('/dashboard/', '')
|
||||
expected_url = 'edxapp://enrolled_program_info?path_id={}'.format(path_id)
|
||||
|
||||
self.assertEqual(program_data['detail_url'], expected_url)
|
||||
assert program_data['detail_url'] == expected_url
|
||||
|
||||
|
||||
def _create_course(self, course_price, course_run_count=1, make_entitlement=False):
|
||||
@@ -812,7 +812,7 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
course['course_runs'] = [course_run]
|
||||
program['courses'] = [course]
|
||||
|
||||
self.assertEqual(actual, program)
|
||||
assert actual == program
|
||||
|
||||
@ddt.data(-1, 0, 1)
|
||||
def test_is_enrollment_open(self, days_offset):
|
||||
@@ -960,7 +960,7 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
|
||||
data = ProgramDataExtender(self.program, self.user).extend()
|
||||
|
||||
self.assertEqual(may_certify, data['courses'][0]['course_runs'][0]['may_certify'])
|
||||
assert may_certify == data['courses'][0]['course_runs'][0]['may_certify']
|
||||
|
||||
self._assert_supplemented(data)
|
||||
|
||||
@@ -971,7 +971,7 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
- There are courses remaining that have not been purchased and enrolled in.
|
||||
"""
|
||||
data = ProgramDataExtender(self.program, self.user).extend()
|
||||
self.assertFalse(data['is_learner_eligible_for_one_click_purchase'])
|
||||
assert not data['is_learner_eligible_for_one_click_purchase']
|
||||
|
||||
courses = [_create_course(self, self.course_price)]
|
||||
|
||||
@@ -980,7 +980,7 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
is_program_eligible_for_one_click_purchase=False
|
||||
)
|
||||
data = ProgramDataExtender(program, self.user).extend()
|
||||
self.assertFalse(data['is_learner_eligible_for_one_click_purchase'])
|
||||
assert not data['is_learner_eligible_for_one_click_purchase']
|
||||
|
||||
course1 = _create_course(self, self.course_price)
|
||||
course2 = _create_course(self, self.course_price)
|
||||
@@ -992,7 +992,7 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
applicable_seat_types=[CourseMode.VERIFIED],
|
||||
)
|
||||
data = ProgramDataExtender(program2, self.user).extend()
|
||||
self.assertTrue(data['is_learner_eligible_for_one_click_purchase'])
|
||||
assert data['is_learner_eligible_for_one_click_purchase']
|
||||
|
||||
def test_learner_eligibility_for_one_click_purchase_with_unpublished(self):
|
||||
"""
|
||||
@@ -1010,8 +1010,8 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
applicable_seat_types=[CourseMode.VERIFIED],
|
||||
)
|
||||
data = ProgramDataExtender(program2, self.user).extend()
|
||||
self.assertEqual(len(data['skus']), 1)
|
||||
self.assertTrue(data['is_learner_eligible_for_one_click_purchase'])
|
||||
assert len(data['skus']) == 1
|
||||
assert data['is_learner_eligible_for_one_click_purchase']
|
||||
|
||||
def test_learner_eligibility_for_one_click_purchase_professional_no_id(self):
|
||||
"""
|
||||
@@ -1029,7 +1029,7 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
applicable_seat_types=[CourseMode.PROFESSIONAL]
|
||||
)
|
||||
data = ProgramDataExtender(program2, self.user).extend()
|
||||
self.assertFalse(data['is_learner_eligible_for_one_click_purchase'])
|
||||
assert not data['is_learner_eligible_for_one_click_purchase']
|
||||
|
||||
def test_multiple_published_course_runs(self):
|
||||
"""
|
||||
@@ -1066,12 +1066,12 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
)
|
||||
data = ProgramDataExtender(program, self.user).extend()
|
||||
|
||||
self.assertFalse(data['is_learner_eligible_for_one_click_purchase'])
|
||||
assert not data['is_learner_eligible_for_one_click_purchase']
|
||||
|
||||
course_run_2['status'] = 'unpublished'
|
||||
data = ProgramDataExtender(program, self.user).extend()
|
||||
|
||||
self.assertTrue(data['is_learner_eligible_for_one_click_purchase'])
|
||||
assert data['is_learner_eligible_for_one_click_purchase']
|
||||
|
||||
def test_learner_eligibility_for_one_click_purchase_entitlement_products(self):
|
||||
"""
|
||||
@@ -1088,8 +1088,8 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
applicable_seat_types=[CourseMode.VERIFIED],
|
||||
)
|
||||
data = ProgramDataExtender(program, self.user).extend()
|
||||
self.assertTrue(data['is_learner_eligible_for_one_click_purchase'])
|
||||
self.assertEqual(set(data['skus']), expected_skus)
|
||||
assert data['is_learner_eligible_for_one_click_purchase']
|
||||
assert set(data['skus']) == expected_skus
|
||||
|
||||
def test_learner_eligibility_for_one_click_purchase_ineligible_program(self):
|
||||
"""
|
||||
@@ -1103,8 +1103,8 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
applicable_seat_types=[CourseMode.VERIFIED],
|
||||
)
|
||||
data = ProgramDataExtender(program, self.user).extend()
|
||||
self.assertFalse(data['is_learner_eligible_for_one_click_purchase'])
|
||||
self.assertEqual(data['skus'], [])
|
||||
assert not data['is_learner_eligible_for_one_click_purchase']
|
||||
assert data['skus'] == []
|
||||
|
||||
def test_learner_eligibility_for_one_click_purchase_user_entitlements(self):
|
||||
"""
|
||||
@@ -1121,8 +1121,8 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
applicable_seat_types=[CourseMode.VERIFIED],
|
||||
)
|
||||
data = ProgramDataExtender(program, self.user).extend()
|
||||
self.assertTrue(data['is_learner_eligible_for_one_click_purchase'])
|
||||
self.assertEqual(set(data['skus']), expected_skus)
|
||||
assert data['is_learner_eligible_for_one_click_purchase']
|
||||
assert set(data['skus']) == expected_skus
|
||||
|
||||
def test_all_courses_owned(self):
|
||||
"""
|
||||
@@ -1139,8 +1139,8 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
)
|
||||
data = ProgramDataExtender(program, self.user).extend()
|
||||
|
||||
self.assertFalse(data['is_learner_eligible_for_one_click_purchase'])
|
||||
self.assertEqual(data['skus'], [])
|
||||
assert not data['is_learner_eligible_for_one_click_purchase']
|
||||
assert data['skus'] == []
|
||||
|
||||
def test_old_course_runs(self):
|
||||
"""
|
||||
@@ -1172,8 +1172,8 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
applicable_seat_types=[CourseMode.VERIFIED],
|
||||
)
|
||||
data = ProgramDataExtender(program, self.user).extend()
|
||||
self.assertFalse(data['is_learner_eligible_for_one_click_purchase'])
|
||||
self.assertEqual(data['skus'], [])
|
||||
assert not data['is_learner_eligible_for_one_click_purchase']
|
||||
assert data['skus'] == []
|
||||
|
||||
def test_second_entitlement_product_wrong_mode(self):
|
||||
"""
|
||||
@@ -1192,8 +1192,8 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
applicable_seat_types=[CourseMode.VERIFIED],
|
||||
)
|
||||
data = ProgramDataExtender(program, self.user).extend()
|
||||
self.assertTrue(data['is_learner_eligible_for_one_click_purchase'])
|
||||
self.assertEqual(set(data['skus']), expected_skus)
|
||||
assert data['is_learner_eligible_for_one_click_purchase']
|
||||
assert set(data['skus']) == expected_skus
|
||||
|
||||
def test_entitlement_product_and_user_enrollment(self):
|
||||
"""
|
||||
@@ -1210,8 +1210,8 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
applicable_seat_types=[CourseMode.VERIFIED],
|
||||
)
|
||||
data = ProgramDataExtender(program, self.user).extend()
|
||||
self.assertTrue(data['is_learner_eligible_for_one_click_purchase'])
|
||||
self.assertEqual(set(data['skus']), expected_skus)
|
||||
assert data['is_learner_eligible_for_one_click_purchase']
|
||||
assert set(data['skus']) == expected_skus
|
||||
|
||||
def test_user_enrollment_with_other_course_entitlement_product(self):
|
||||
"""
|
||||
@@ -1228,8 +1228,8 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
applicable_seat_types=[CourseMode.VERIFIED, CourseMode.PROFESSIONAL],
|
||||
)
|
||||
data = ProgramDataExtender(program, self.user).extend()
|
||||
self.assertTrue(data['is_learner_eligible_for_one_click_purchase'])
|
||||
self.assertEqual(set(data['skus']), expected_skus)
|
||||
assert data['is_learner_eligible_for_one_click_purchase']
|
||||
assert set(data['skus']) == expected_skus
|
||||
|
||||
def test_course_url_with_mobile_only(self):
|
||||
"""
|
||||
@@ -1293,7 +1293,7 @@ class TestGetCertificates(TestCase):
|
||||
}]
|
||||
|
||||
certificates = get_certificates(self.user, self.program)
|
||||
self.assertEqual(certificates, expected)
|
||||
assert certificates == expected
|
||||
|
||||
def test_course_run_certificates_missing(self, mock_get_credentials):
|
||||
"""
|
||||
@@ -1317,8 +1317,8 @@ class TestGetCertificates(TestCase):
|
||||
mock_get_credentials.return_value = [{'certificate_url': self.program_certificate_url}]
|
||||
|
||||
certificates = get_certificates(self.user, self.program)
|
||||
self.assertTrue(mock_get_credentials.called)
|
||||
self.assertEqual(certificates, expected)
|
||||
assert mock_get_credentials.called
|
||||
assert certificates == expected
|
||||
|
||||
def test_program_certificate_missing(self, mock_get_credentials):
|
||||
"""
|
||||
@@ -1335,7 +1335,7 @@ class TestGetCertificates(TestCase):
|
||||
mock_get_credentials.return_value = []
|
||||
|
||||
certificates = get_certificates(self.user, self.program)
|
||||
self.assertEqual(certificates, expected)
|
||||
assert certificates == expected
|
||||
|
||||
def test_get_program_certificate_url(self, mock_get_credentials): # pylint: disable=unused-argument
|
||||
"""
|
||||
@@ -1343,7 +1343,7 @@ class TestGetCertificates(TestCase):
|
||||
"""
|
||||
expected = 'http://fake-credentials.edx.org/login/?next=/credentials/fake-uuid/'
|
||||
actual = get_logged_in_program_certificate_url(self.program_certificate_url)
|
||||
self.assertEqual(expected, actual)
|
||||
assert expected == actual
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -1408,15 +1408,15 @@ class TestProgramMarketingDataExtender(ModuleStoreTestCase):
|
||||
data = ProgramMarketingDataExtender(self.program, self.user).extend()
|
||||
|
||||
self.program.update(self.instructors['instructors']) # lint-amnesty, pylint: disable=no-member
|
||||
self.assertEqual(data, self.program)
|
||||
assert data == self.program
|
||||
|
||||
def test_course_pricing(self):
|
||||
data = ProgramMarketingDataExtender(self.program, self.user).extend()
|
||||
|
||||
program_full_price = self.course_price * self.number_of_courses
|
||||
self.assertEqual(data['number_of_courses'], self.number_of_courses)
|
||||
self.assertEqual(data['full_program_price'], program_full_price)
|
||||
self.assertEqual(data['avg_price_per_course'], program_full_price / self.number_of_courses)
|
||||
assert data['number_of_courses'] == self.number_of_courses
|
||||
assert data['full_program_price'] == program_full_price
|
||||
assert data['avg_price_per_course'] == (program_full_price / self.number_of_courses)
|
||||
|
||||
def test_course_pricing_when_all_course_runs_have_no_seats(self):
|
||||
# Create three seatless course runs and add them to the program
|
||||
@@ -1429,9 +1429,9 @@ class TestProgramMarketingDataExtender(ModuleStoreTestCase):
|
||||
|
||||
data = ProgramMarketingDataExtender(program, self.user).extend()
|
||||
|
||||
self.assertEqual(data['number_of_courses'], len(program['courses']))
|
||||
self.assertEqual(data['full_program_price'], 0.0)
|
||||
self.assertEqual(data['avg_price_per_course'], 0.0)
|
||||
assert data['number_of_courses'] == len(program['courses'])
|
||||
assert data['full_program_price'] == 0.0
|
||||
assert data['avg_price_per_course'] == 0.0
|
||||
|
||||
@ddt.data(True, False)
|
||||
@mock.patch('django.contrib.auth.models.PermissionsMixin.has_perm')
|
||||
@@ -1443,7 +1443,7 @@ class TestProgramMarketingDataExtender(ModuleStoreTestCase):
|
||||
|
||||
data = ProgramMarketingDataExtender(self.program, self.user).extend()
|
||||
|
||||
self.assertEqual(data['courses'][0]['course_runs'][0]['can_enroll'], can_enroll)
|
||||
assert data['courses'][0]['course_runs'][0]['can_enroll'] == can_enroll
|
||||
|
||||
@httpretty.activate
|
||||
def test_fetching_program_discounted_price(self):
|
||||
@@ -1468,12 +1468,9 @@ class TestProgramMarketingDataExtender(ModuleStoreTestCase):
|
||||
data = ProgramMarketingDataExtender(self.program, self.user).extend()
|
||||
self._update_discount_data(mock_discount_data)
|
||||
|
||||
self.assertEqual(httpretty.last_request().querystring.get('username')[0], self.user.username) # lint-amnesty, pylint: disable=no-member
|
||||
self.assertEqual(
|
||||
data['skus'],
|
||||
[course['course_runs'][0]['seats'][0]['sku'] for course in self.program['courses']]
|
||||
)
|
||||
self.assertEqual(data['discount_data'], mock_discount_data)
|
||||
assert httpretty.last_request().querystring.get('username')[0] == self.user.username # lint-amnesty, pylint: disable=no-member, line-too-long
|
||||
assert data['skus'] == [course['course_runs'][0]['seats'][0]['sku'] for course in self.program['courses']]
|
||||
assert data['discount_data'] == mock_discount_data
|
||||
|
||||
@httpretty.activate
|
||||
@override_switch(ALWAYS_CALCULATE_PROGRAM_PRICE_AS_ANONYMOUS_USER.name, active=True)
|
||||
@@ -1495,7 +1492,7 @@ class TestProgramMarketingDataExtender(ModuleStoreTestCase):
|
||||
content_type='application/json'
|
||||
)
|
||||
ProgramMarketingDataExtender(self.program, self.user).extend()
|
||||
self.assertEqual(httpretty.last_request().querystring.get('is_anonymous')[0], u'True') # lint-amnesty, pylint: disable=no-member
|
||||
assert httpretty.last_request().querystring.get('is_anonymous')[0] == u'True' # lint-amnesty, pylint: disable=no-member, line-too-long
|
||||
|
||||
@httpretty.activate
|
||||
def test_fetching_program_discounted_price_as_anonymous_user(self):
|
||||
@@ -1520,12 +1517,9 @@ class TestProgramMarketingDataExtender(ModuleStoreTestCase):
|
||||
data = ProgramMarketingDataExtender(self.program, user).extend()
|
||||
self._update_discount_data(mock_discount_data)
|
||||
|
||||
self.assertIsNotNone(httpretty.last_request().querystring.get('is_anonymous', None)) # lint-amnesty, pylint: disable=no-member
|
||||
self.assertEqual(
|
||||
data['skus'],
|
||||
[course['course_runs'][0]['seats'][0]['sku'] for course in self.program['courses']]
|
||||
)
|
||||
self.assertEqual(data['discount_data'], mock_discount_data)
|
||||
assert httpretty.last_request().querystring.get('is_anonymous', None) is not None # lint-amnesty, pylint: disable=no-member, line-too-long
|
||||
assert data['skus'] == [course['course_runs'][0]['seats'][0]['sku'] for course in self.program['courses']]
|
||||
assert data['discount_data'] == mock_discount_data
|
||||
|
||||
def test_fetching_program_discounted_price_no_applicable_seats(self):
|
||||
"""
|
||||
@@ -1534,7 +1528,7 @@ class TestProgramMarketingDataExtender(ModuleStoreTestCase):
|
||||
self.program['applicable_seat_types'] = []
|
||||
data = ProgramMarketingDataExtender(self.program, self.user).extend()
|
||||
|
||||
self.assertEqual(len(data['skus']), 0)
|
||||
assert len(data['skus']) == 0
|
||||
|
||||
@httpretty.activate
|
||||
def test_fetching_program_discounted_price_api_exception_caught(self):
|
||||
@@ -1552,10 +1546,7 @@ class TestProgramMarketingDataExtender(ModuleStoreTestCase):
|
||||
|
||||
data = ProgramMarketingDataExtender(self.program, self.user).extend()
|
||||
|
||||
self.assertEqual(
|
||||
data['skus'],
|
||||
[course['course_runs'][0]['seats'][0]['sku'] for course in self.program['courses']]
|
||||
)
|
||||
assert data['skus'] == [course['course_runs'][0]['seats'][0]['sku'] for course in self.program['courses']]
|
||||
|
||||
|
||||
@skip_unless_lms
|
||||
@@ -1587,28 +1578,29 @@ class TestProgramEnrollment(SharedModuleStoreTestCase):
|
||||
|
||||
def test_user_not_in_program(self, mock_get_programs_by_type):
|
||||
mock_get_programs_by_type.return_value = [self.program]
|
||||
self.assertFalse(is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS))
|
||||
assert not is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS)
|
||||
|
||||
def test_user_enrolled_in_mb_program(self, mock_get_programs_by_type):
|
||||
CourseEnrollmentFactory.create(user=self.user, course_id=self.course_run.id, mode=CourseMode.VERIFIED)
|
||||
mock_get_programs_by_type.return_value = [self.program]
|
||||
self.assertTrue(is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS))
|
||||
assert is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS)
|
||||
|
||||
def test_user_enrolled_unpaid_in_program(self, mock_get_programs_by_type):
|
||||
CourseEnrollmentFactory.create(user=self.user, course_id=self.course_run.id, mode=CourseMode.AUDIT)
|
||||
mock_get_programs_by_type.return_value = [self.program]
|
||||
self.assertTrue(is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS))
|
||||
assert is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS)
|
||||
|
||||
def test_user_enrolled_unpaid_in_program_paid_only_request(self, mock_get_programs_by_type):
|
||||
CourseEnrollmentFactory.create(user=self.user, course_id=self.course_run.id, mode=CourseMode.AUDIT)
|
||||
mock_get_programs_by_type.return_value = [self.program]
|
||||
self.assertFalse(
|
||||
is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS, paid_modes_only=True) # lint-amnesty, pylint: disable=line-too-long
|
||||
)
|
||||
assert not is_user_enrolled_in_program_type(user=self.user,
|
||||
program_type_slug=self.MICROBACHELORS,
|
||||
paid_modes_only=True)
|
||||
|
||||
# NEW CODE HERE
|
||||
@mock.patch('openedx.core.djangoapps.programs.utils.get_paid_modes_for_course')
|
||||
def test_user_enrolled_in_paid_only_with_no_matching_paid_course_modes(self, mock_get_paid_modes_for_course, mock_get_programs_by_type): # lint-amnesty, pylint: disable=line-too-long
|
||||
def test_user_enrolled_in_paid_only_with_no_matching_paid_course_modes(self, mock_get_paid_modes_for_course,
|
||||
mock_get_programs_by_type):
|
||||
second_program = ProgramFactory(type=self.MICROBACHELORS)
|
||||
second_catalog_course_run = second_program['courses'][0]['course_runs'][0]
|
||||
second_course_key = CourseKey.from_string(second_catalog_course_run['key'])
|
||||
@@ -1628,16 +1620,12 @@ class TestProgramEnrollment(SharedModuleStoreTestCase):
|
||||
# we should return False
|
||||
mock_get_paid_modes_for_course.return_value = []
|
||||
# raise Exception((mock_get_programs_by_type, mock_get_paid_modes_for_course))
|
||||
self.assertFalse(
|
||||
is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS, paid_modes_only=True) # lint-amnesty, pylint: disable=line-too-long
|
||||
)
|
||||
assert not is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS, paid_modes_only=True)
|
||||
|
||||
# We should continue to return false even if they do contain paid modes
|
||||
Mode = namedtuple('Mode', ['slug']) # lint-amnesty, pylint: disable=unused-variable
|
||||
# mock_get_paid_modes_for_course.return_value = [Mode(CourseMode.VERIFIED)]
|
||||
self.assertFalse(
|
||||
is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS, paid_modes_only=True) # lint-amnesty, pylint: disable=line-too-long
|
||||
)
|
||||
assert not is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS, paid_modes_only=True)
|
||||
|
||||
def test_user_with_entitlement_no_enrollment(self, mock_get_programs_by_type):
|
||||
CourseEntitlementFactory.create(
|
||||
@@ -1646,4 +1634,4 @@ class TestProgramEnrollment(SharedModuleStoreTestCase):
|
||||
course_uuid=self.program['courses'][0]['uuid']
|
||||
)
|
||||
mock_get_programs_by_type.return_value = [self.program]
|
||||
self.assertTrue(is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS))
|
||||
assert is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS)
|
||||
|
||||
@@ -47,32 +47,29 @@ class TestSafeSessionProcessRequest(TestSafeSessionsLogMixin, TestCase):
|
||||
self.request.COOKIES[settings.SESSION_COOKIE_NAME] = six.text_type(safe_cookie_data)
|
||||
response = SafeSessionMiddleware().process_request(self.request)
|
||||
if success:
|
||||
self.assertIsNone(response)
|
||||
self.assertIsNone(getattr(self.request, 'need_to_delete_cookie', None))
|
||||
assert response is None
|
||||
assert getattr(self.request, 'need_to_delete_cookie', None) is None
|
||||
else:
|
||||
self.assertEqual(response.status_code, HttpResponseRedirect.status_code)
|
||||
self.assertTrue(self.request.need_to_delete_cookie)
|
||||
assert response.status_code == HttpResponseRedirect.status_code
|
||||
assert self.request.need_to_delete_cookie
|
||||
|
||||
def assert_no_session(self):
|
||||
"""
|
||||
Asserts that a session object is *not* set on the request.
|
||||
"""
|
||||
self.assertIsNone(getattr(self.request, 'session', None))
|
||||
assert getattr(self.request, 'session', None) is None
|
||||
|
||||
def assert_no_user_in_session(self):
|
||||
"""
|
||||
Asserts that a user object is *not* set on the request's session.
|
||||
"""
|
||||
self.assertIsNone(self.request.session.get(SESSION_KEY))
|
||||
assert self.request.session.get(SESSION_KEY) is None
|
||||
|
||||
def assert_user_in_session(self):
|
||||
"""
|
||||
Asserts that a user object *is* set on the request's session.
|
||||
"""
|
||||
self.assertEqual(
|
||||
SafeSessionMiddleware.get_user_id_from_session(self.request),
|
||||
self.user.id
|
||||
)
|
||||
assert SafeSessionMiddleware.get_user_id_from_session(self.request) == self.user.id
|
||||
|
||||
def test_success(self):
|
||||
self.client.login(username=self.user.username, password='test')
|
||||
@@ -80,21 +77,21 @@ class TestSafeSessionProcessRequest(TestSafeSessionsLogMixin, TestCase):
|
||||
safe_cookie_data = SafeCookieData.create(session_id, self.user.id)
|
||||
|
||||
# pre-verify steps 3, 4, 5
|
||||
self.assertIsNone(getattr(self.request, 'session', None))
|
||||
self.assertIsNone(getattr(self.request, 'safe_cookie_verified_user_id', None))
|
||||
assert getattr(self.request, 'session', None) is None
|
||||
assert getattr(self.request, 'safe_cookie_verified_user_id', None) is None
|
||||
|
||||
# verify step 1: safe cookie data is parsed
|
||||
self.assert_response(safe_cookie_data)
|
||||
self.assert_user_in_session()
|
||||
|
||||
# verify step 2: cookie value is replaced with parsed session_id
|
||||
self.assertEqual(self.request.COOKIES[settings.SESSION_COOKIE_NAME], session_id)
|
||||
assert self.request.COOKIES[settings.SESSION_COOKIE_NAME] == session_id
|
||||
|
||||
# verify step 3: session set in request
|
||||
self.assertIsNotNone(self.request.session)
|
||||
assert self.request.session is not None
|
||||
|
||||
# verify steps 4, 5: user_id stored for later verification
|
||||
self.assertEqual(self.request.safe_cookie_verified_user_id, self.user.id)
|
||||
assert self.request.safe_cookie_verified_user_id == self.user.id
|
||||
|
||||
def test_success_no_cookies(self):
|
||||
self.assert_response()
|
||||
@@ -156,7 +153,7 @@ class TestSafeSessionProcessResponse(TestSafeSessionsLogMixin, TestCase):
|
||||
self.client.response.cookies[settings.SESSION_COOKIE_NAME] = "some_session_id"
|
||||
|
||||
response = SafeSessionMiddleware().process_response(self.request, self.client.response)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
|
||||
def assert_response_with_delete_cookie(
|
||||
self,
|
||||
@@ -174,7 +171,7 @@ class TestSafeSessionProcessResponse(TestSafeSessionsLogMixin, TestCase):
|
||||
"""
|
||||
with patch('django.http.HttpResponse.set_cookie') as mock_delete_cookie:
|
||||
self.assert_response(set_request_user=set_request_user, set_session_cookie=set_session_cookie)
|
||||
self.assertEqual(mock_delete_cookie.called, expect_delete_called)
|
||||
assert mock_delete_cookie.called == expect_delete_called
|
||||
|
||||
def test_success(self):
|
||||
with self.assert_not_logged():
|
||||
@@ -207,9 +204,9 @@ class TestSafeSessionProcessResponse(TestSafeSessionsLogMixin, TestCase):
|
||||
|
||||
serialized_cookie_data = self.client.response.cookies[settings.SESSION_COOKIE_NAME].value
|
||||
safe_cookie_data = SafeCookieData.parse(serialized_cookie_data)
|
||||
self.assertEqual(safe_cookie_data.version, SafeCookieData.CURRENT_VERSION)
|
||||
self.assertEqual(safe_cookie_data.session_id, "some_session_id")
|
||||
self.assertTrue(safe_cookie_data.verify(self.user.id))
|
||||
assert safe_cookie_data.version == SafeCookieData.CURRENT_VERSION
|
||||
assert safe_cookie_data.session_id == 'some_session_id'
|
||||
assert safe_cookie_data.verify(self.user.id)
|
||||
|
||||
def test_cant_update_cookie_at_step_3_error(self):
|
||||
self.client.response.cookies[settings.SESSION_COOKIE_NAME] = None
|
||||
@@ -265,14 +262,14 @@ class TestSafeSessionMiddleware(TestSafeSessionsLogMixin, TestCase):
|
||||
|
||||
with self.assert_not_logged():
|
||||
response = SafeSessionMiddleware().process_request(self.request)
|
||||
self.assertIsNone(response)
|
||||
assert response is None
|
||||
|
||||
self.assertEqual(self.request.safe_cookie_verified_user_id, self.user.id)
|
||||
assert self.request.safe_cookie_verified_user_id == self.user.id
|
||||
self.cookies_from_request_to_response()
|
||||
|
||||
with self.assert_not_logged():
|
||||
response = SafeSessionMiddleware().process_response(self.request, self.client.response)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_success(self):
|
||||
self.verify_success()
|
||||
@@ -294,14 +291,14 @@ class TestSafeSessionMiddleware(TestSafeSessionsLogMixin, TestCase):
|
||||
|
||||
with self.assert_parse_error():
|
||||
request_response = SafeSessionMiddleware().process_request(self.request)
|
||||
self.assertEqual(request_response.status_code, expected_response_status)
|
||||
assert request_response.status_code == expected_response_status
|
||||
|
||||
self.assertTrue(self.request.need_to_delete_cookie)
|
||||
assert self.request.need_to_delete_cookie
|
||||
self.cookies_from_request_to_response()
|
||||
|
||||
with patch('django.http.HttpResponse.set_cookie') as mock_delete_cookie:
|
||||
SafeSessionMiddleware().process_response(self.request, self.client.response)
|
||||
self.assertTrue(mock_delete_cookie.called)
|
||||
assert mock_delete_cookie.called
|
||||
|
||||
def test_error(self):
|
||||
self.verify_error(302)
|
||||
|
||||
@@ -6,7 +6,7 @@ Unit tests for SafeCookieData
|
||||
|
||||
import itertools
|
||||
from time import time
|
||||
|
||||
import pytest
|
||||
import ddt
|
||||
import six
|
||||
from django.test import TestCase
|
||||
@@ -48,25 +48,25 @@ class TestSafeCookieData(TestSafeSessionsLogMixin, TestCase):
|
||||
def test_success(self, session_id, user_id):
|
||||
# create and verify
|
||||
safe_cookie_data_1 = SafeCookieData.create(session_id, user_id)
|
||||
self.assertTrue(safe_cookie_data_1.verify(user_id))
|
||||
assert safe_cookie_data_1.verify(user_id)
|
||||
|
||||
# serialize
|
||||
serialized_value = six.text_type(safe_cookie_data_1)
|
||||
|
||||
# parse and verify
|
||||
safe_cookie_data_2 = SafeCookieData.parse(serialized_value)
|
||||
self.assertTrue(safe_cookie_data_2.verify(user_id))
|
||||
assert safe_cookie_data_2.verify(user_id)
|
||||
|
||||
# compare
|
||||
self.assert_cookie_data_equal(safe_cookie_data_1, safe_cookie_data_2)
|
||||
|
||||
def test_version(self):
|
||||
self.assertEqual(self.safe_cookie_data.version, SafeCookieData.CURRENT_VERSION)
|
||||
assert self.safe_cookie_data.version == SafeCookieData.CURRENT_VERSION
|
||||
|
||||
def test_serialize(self):
|
||||
serialized_value = six.text_type(self.safe_cookie_data)
|
||||
for field_value in six.itervalues(self.safe_cookie_data.__dict__):
|
||||
self.assertIn(six.text_type(field_value), serialized_value)
|
||||
assert six.text_type(field_value) in serialized_value
|
||||
|
||||
#---- Test Parse ----#
|
||||
|
||||
@@ -87,14 +87,14 @@ class TestSafeCookieData(TestSafeSessionsLogMixin, TestCase):
|
||||
@ddt.data('1', '1|s', '1|s|k', '1|s|k|sig|extra', '73453', 's90sfs')
|
||||
def test_parse_error(self, serialized_value):
|
||||
with self.assert_parse_error():
|
||||
with self.assertRaises(SafeCookieError):
|
||||
with pytest.raises(SafeCookieError):
|
||||
SafeCookieData.parse(serialized_value)
|
||||
|
||||
@ddt.data(0, 2, -1, 'invalid_version')
|
||||
def test_parse_invalid_version(self, version):
|
||||
serialized_value = '{}|session_id|key_salt|signature'.format(version)
|
||||
with self.assert_logged(r"SafeCookieData version .* is not supported."):
|
||||
with self.assertRaises(SafeCookieError):
|
||||
with pytest.raises(SafeCookieError):
|
||||
SafeCookieData.parse(serialized_value)
|
||||
|
||||
#---- Test Create ----#
|
||||
@@ -102,19 +102,19 @@ class TestSafeCookieData(TestSafeSessionsLogMixin, TestCase):
|
||||
@ddt.data(None, '')
|
||||
def test_create_invalid_session_id(self, session_id):
|
||||
with self.assert_invalid_session_id():
|
||||
with self.assertRaises(SafeCookieError):
|
||||
with pytest.raises(SafeCookieError):
|
||||
SafeCookieData.create(session_id, self.user_id)
|
||||
|
||||
@ddt.data(None, '')
|
||||
def test_create_no_user_id(self, user_id):
|
||||
with self.assert_logged('SafeCookieData received empty user_id', 'debug'):
|
||||
safe_cookie_data = SafeCookieData.create(self.session_id, user_id)
|
||||
self.assertTrue(safe_cookie_data.verify(user_id))
|
||||
assert safe_cookie_data.verify(user_id)
|
||||
|
||||
#---- Test Verify ----#
|
||||
|
||||
def test_verify_success(self):
|
||||
self.assertTrue(self.safe_cookie_data.verify(self.user_id))
|
||||
assert self.safe_cookie_data.verify(self.user_id)
|
||||
|
||||
#- Test verify: expiration -#
|
||||
|
||||
@@ -122,20 +122,20 @@ class TestSafeCookieData(TestSafeSessionsLogMixin, TestCase):
|
||||
three_weeks_from_now = time() + 60 * 60 * 24 * 7 * 3
|
||||
with patch('time.time', return_value=three_weeks_from_now):
|
||||
with self.assert_signature_error_logged('Signature age'):
|
||||
self.assertFalse(self.safe_cookie_data.verify(self.user_id))
|
||||
assert not self.safe_cookie_data.verify(self.user_id)
|
||||
|
||||
#- Test verify: incorrect user -#
|
||||
|
||||
@ddt.data(None, 'invalid_user_id', -1)
|
||||
def test_verify_incorrect_user_id(self, user_id):
|
||||
with self.assert_incorrect_user_logged():
|
||||
self.assertFalse(self.safe_cookie_data.verify(user_id))
|
||||
assert not self.safe_cookie_data.verify(user_id)
|
||||
|
||||
@ddt.data('version', 'session_id')
|
||||
def test_verify_incorrect_field_value(self, field_name):
|
||||
setattr(self.safe_cookie_data, field_name, 'incorrect_cookie_value')
|
||||
with self.assert_incorrect_user_logged():
|
||||
self.assertFalse(self.safe_cookie_data.verify(self.user_id))
|
||||
assert not self.safe_cookie_data.verify(self.user_id)
|
||||
|
||||
#- Test verify: incorrect signature -#
|
||||
|
||||
@@ -143,12 +143,12 @@ class TestSafeCookieData(TestSafeSessionsLogMixin, TestCase):
|
||||
another_cookie_data = SafeCookieData.create(self.session_id, self.user_id) # different key_salt and expiration
|
||||
self.safe_cookie_data.signature = another_cookie_data.signature
|
||||
with self.assert_incorrect_signature_logged():
|
||||
self.assertFalse(self.safe_cookie_data.verify(self.user_id))
|
||||
assert not self.safe_cookie_data.verify(self.user_id)
|
||||
|
||||
def test_verify_incorrect_key_salt(self):
|
||||
self.safe_cookie_data.key_salt = 'incorrect_cookie_value'
|
||||
with self.assert_incorrect_signature_logged():
|
||||
self.assertFalse(self.safe_cookie_data.verify(self.user_id))
|
||||
assert not self.safe_cookie_data.verify(self.user_id)
|
||||
|
||||
@ddt.data(
|
||||
*itertools.product(
|
||||
@@ -170,30 +170,26 @@ class TestSafeCookieData(TestSafeSessionsLogMixin, TestCase):
|
||||
self.safe_cookie_data.signature, start, start + length
|
||||
)
|
||||
with self.assert_incorrect_signature_logged():
|
||||
self.assertFalse(self.safe_cookie_data.verify(self.user_id))
|
||||
assert not self.safe_cookie_data.verify(self.user_id)
|
||||
|
||||
#- Test verify: corrupt signature -#
|
||||
|
||||
def test_verify_corrupt_signature(self):
|
||||
self.safe_cookie_data.signature = 'corrupt_signature'
|
||||
with self.assert_signature_error_logged('No .* found in value'):
|
||||
self.assertFalse(self.safe_cookie_data.verify(self.user_id))
|
||||
assert not self.safe_cookie_data.verify(self.user_id)
|
||||
|
||||
#---- Test Digest ----#
|
||||
|
||||
def test_digest_success(self):
|
||||
# Should return the same digest twice.
|
||||
self.assertEqual(
|
||||
self.safe_cookie_data._compute_digest(self.user_id),
|
||||
self.safe_cookie_data._compute_digest(self.user_id),
|
||||
)
|
||||
assert self.safe_cookie_data._compute_digest(self.user_id) == \
|
||||
self.safe_cookie_data._compute_digest(self.user_id)
|
||||
|
||||
@ddt.data('another_user', 0, None)
|
||||
def test_digest_incorrect_user(self, incorrect_user):
|
||||
self.assertNotEqual(
|
||||
self.safe_cookie_data._compute_digest(self.user_id),
|
||||
self.safe_cookie_data._compute_digest(incorrect_user)
|
||||
)
|
||||
assert self.safe_cookie_data._compute_digest(self.user_id) !=\
|
||||
self.safe_cookie_data._compute_digest(incorrect_user)
|
||||
|
||||
@ddt.data(
|
||||
*itertools.product(
|
||||
@@ -205,7 +201,4 @@ class TestSafeCookieData(TestSafeSessionsLogMixin, TestCase):
|
||||
def test_digest_incorrect_field_value(self, field_name, incorrect_field_value):
|
||||
digest = self.safe_cookie_data._compute_digest(self.user_id)
|
||||
setattr(self.safe_cookie_data, field_name, incorrect_field_value)
|
||||
self.assertNotEqual(
|
||||
digest,
|
||||
self.safe_cookie_data._compute_digest(self.user_id)
|
||||
)
|
||||
assert digest != self.safe_cookie_data._compute_digest(self.user_id)
|
||||
|
||||
@@ -21,7 +21,7 @@ class TestSafeSessionsLogMixin(object):
|
||||
"""
|
||||
with patch('openedx.core.djangoapps.safe_sessions.middleware.log.' + log_level) as mock_log:
|
||||
yield
|
||||
self.assertTrue(mock_log.called)
|
||||
assert mock_log.called
|
||||
self.assertRegex(mock_log.call_args_list[0][0][0], log_string)
|
||||
|
||||
@contextmanager
|
||||
@@ -51,7 +51,7 @@ class TestSafeSessionsLogMixin(object):
|
||||
"""
|
||||
with patch('openedx.core.djangoapps.safe_sessions.middleware.log.warning') as mock_log:
|
||||
yield
|
||||
self.assertFalse(mock_log.called)
|
||||
assert not mock_log.called
|
||||
|
||||
@contextmanager
|
||||
def assert_no_error_logged(self):
|
||||
@@ -60,7 +60,7 @@ class TestSafeSessionsLogMixin(object):
|
||||
"""
|
||||
with patch('openedx.core.djangoapps.safe_sessions.middleware.log.error') as mock_log:
|
||||
yield
|
||||
self.assertFalse(mock_log.called)
|
||||
assert not mock_log.called
|
||||
|
||||
@contextmanager
|
||||
def assert_signature_error_logged(self, sig_error_string):
|
||||
|
||||
Reference in New Issue
Block a user