Disallow free verified course modes

The verification workflow assumes that all verified courses will have a
price. Free verified course modes cause a 404 when the user attempts to
enroll or upgrade.
This commit is contained in:
Omar Khan
2016-01-29 11:47:51 +07:00
committed by Braden MacDonald
parent a2c686cf6f
commit 6fc4b38ea0
19 changed files with 122 additions and 70 deletions

View File

@@ -17,6 +17,7 @@ import pytz
from course_modes.helpers import enrollment_mode_display
from course_modes.models import CourseMode, Mode
from course_modes.tests.factories import CourseModeFactory
@ddt.ddt
@@ -74,9 +75,9 @@ class CourseModeModelTest(TestCase):
Find the modes for a course with only one mode
"""
self.create_mode('verified', 'Verified Certificate')
self.create_mode('verified', 'Verified Certificate', 10)
modes = CourseMode.modes_for_course(self.course_key)
mode = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', None, None, None)
mode = Mode(u'verified', u'Verified Certificate', 10, '', 'usd', None, None, None)
self.assertEqual([mode], modes)
modes_dict = CourseMode.modes_for_course_dict(self.course_key)
@@ -89,7 +90,7 @@ class CourseModeModelTest(TestCase):
Finding the modes when there's multiple modes
"""
mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None)
mode2 = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', None, None, None)
mode2 = Mode(u'verified', u'Verified Certificate', 10, '', 'usd', None, None, None)
set_modes = [mode1, mode2]
for mode in set_modes:
self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices)
@@ -119,7 +120,7 @@ class CourseModeModelTest(TestCase):
self.assertEqual(80, CourseMode.min_course_price_for_currency(self.course_key, 'cny'))
def test_modes_for_course_expired(self):
expired_mode, _status = self.create_mode('verified', 'Verified Certificate')
expired_mode, _status = self.create_mode('verified', 'Verified Certificate', 10)
expired_mode.expiration_datetime = datetime.now(pytz.UTC) + timedelta(days=-1)
expired_mode.save()
modes = CourseMode.modes_for_course(self.course_key)
@@ -133,7 +134,7 @@ class CourseModeModelTest(TestCase):
expiration_datetime = datetime.now(pytz.UTC) + timedelta(days=1)
expired_mode.expiration_datetime = expiration_datetime
expired_mode.save()
expired_mode_value = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', expiration_datetime, None, None)
expired_mode_value = Mode(u'verified', u'Verified Certificate', 10, '', 'usd', expiration_datetime, None, None)
modes = CourseMode.modes_for_course(self.course_key)
self.assertEqual([expired_mode_value, mode1], modes)
@@ -141,14 +142,14 @@ class CourseModeModelTest(TestCase):
self.assertEqual([CourseMode.DEFAULT_MODE], modes)
def test_verified_mode_for_course(self):
self.create_mode('verified', 'Verified Certificate')
self.create_mode('verified', 'Verified Certificate', 10)
mode = CourseMode.verified_mode_for_course(self.course_key)
self.assertEqual(mode.slug, 'verified')
# verify that the professional mode is preferred
self.create_mode('professional', 'Professional Education Verified Certificate')
self.create_mode('professional', 'Professional Education Verified Certificate', 10)
mode = CourseMode.verified_mode_for_course(self.course_key)
@@ -163,9 +164,8 @@ class CourseModeModelTest(TestCase):
verified, _ = self.create_mode('verified', 'Verified', min_price=5)
self.assertTrue(CourseMode.has_payment_options(self.course_key))
# Unset verified's minimum price.
verified.min_price = 0
verified.save()
# Remove the verified option.
verified.delete()
self.assertFalse(CourseMode.has_payment_options(self.course_key))
# Finally, give the honor mode payment options
@@ -215,7 +215,7 @@ class CourseModeModelTest(TestCase):
past = now - timedelta(days=1)
# Unexpired, no expiration date
CourseMode.objects.create(
CourseModeFactory.create(
course_id=self.course_key,
mode_display_name="Honor No Expiration",
mode_slug="honor_no_expiration",
@@ -223,7 +223,7 @@ class CourseModeModelTest(TestCase):
)
# Unexpired, expiration date in future
CourseMode.objects.create(
CourseModeFactory.create(
course_id=self.course_key,
mode_display_name="Honor Not Expired",
mode_slug="honor_not_expired",
@@ -231,7 +231,7 @@ class CourseModeModelTest(TestCase):
)
# Expired
CourseMode.objects.create(
CourseModeFactory.create(
course_id=self.course_key,
mode_display_name="Verified Expired",
mode_slug="verified_expired",
@@ -306,9 +306,9 @@ class CourseModeModelTest(TestCase):
def test_invalid_mode_expiration(self, mode_slug, exp_dt):
is_error_expected = CourseMode.is_professional_slug(mode_slug) and exp_dt is not None
try:
self.create_mode(mode_slug=mode_slug, mode_name=mode_slug.title(), expiration_datetime=exp_dt)
self.create_mode(mode_slug=mode_slug, mode_name=mode_slug.title(), expiration_datetime=exp_dt, min_price=10)
self.assertFalse(is_error_expected, "Expected a ValidationError to be thrown.")
except ValidationError, exc:
except ValidationError as exc:
self.assertTrue(is_error_expected, "Did not expect a ValidationError to be thrown.")
self.assertEqual(
exc.messages,
@@ -367,7 +367,7 @@ class CourseModeModelTest(TestCase):
def test_hide_credit_modes(self, available_modes, expected_selectable_modes):
# Create the course modes
for mode in available_modes:
CourseMode.objects.create(
CourseModeFactory.create(
course_id=self.course_key,
mode_display_name=mode,
mode_slug=mode,
@@ -406,7 +406,7 @@ class CourseModeModelTest(TestCase):
def test_expiration_datetime_explicitly_set(self):
""" Verify that setting the expiration_date property sets the explicit flag. """
verified_mode, __ = self.create_mode('verified', 'Verified Certificate')
verified_mode, __ = self.create_mode('verified', 'Verified Certificate', 10)
now = datetime.now()
verified_mode.expiration_datetime = now
@@ -415,7 +415,7 @@ class CourseModeModelTest(TestCase):
def test_expiration_datetime_not_explicitly_set(self):
""" Verify that setting the _expiration_date property does not set the explicit flag. """
verified_mode, __ = self.create_mode('verified', 'Verified Certificate')
verified_mode, __ = self.create_mode('verified', 'Verified Certificate', 10)
now = datetime.now()
verified_mode._expiration_datetime = now # pylint: disable=protected-access
@@ -424,7 +424,7 @@ class CourseModeModelTest(TestCase):
def test_expiration_datetime_explicitly_set_to_none(self):
""" Verify that setting the _expiration_date property does not set the explicit flag. """
verified_mode, __ = self.create_mode('verified', 'Verified Certificate')
verified_mode, __ = self.create_mode('verified', 'Verified Certificate', 10)
self.assertFalse(verified_mode.expiration_datetime_is_explicit)
verified_mode.expiration_datetime = None
@@ -443,3 +443,21 @@ class CourseModeModelTest(TestCase):
def test_eligible_for_cert(self, mode_slug, expected_eligibility):
"""Verify that non-audit modes are eligible for a cert."""
self.assertEqual(CourseMode.is_eligible_for_certificate(mode_slug), expected_eligibility)
@ddt.data(
(CourseMode.AUDIT, False),
(CourseMode.HONOR, False),
(CourseMode.VERIFIED, True),
(CourseMode.CREDIT_MODE, False),
(CourseMode.PROFESSIONAL, True),
(CourseMode.NO_ID_PROFESSIONAL_MODE, False),
)
@ddt.unpack
def test_verified_min_price(self, mode_slug, is_error_expected):
"""Verify that verified modes have a price."""
try:
self.create_mode(mode_slug=mode_slug, mode_name=mode_slug.title(), min_price=0)
except ValidationError:
self.assertTrue(is_error_expected, "Did not expect a ValidationError to be thrown.")
else:
self.assertFalse(is_error_expected, "Expected a ValidationError to be thrown.")