Merge pull request #12064 from open-craft/omar/no-free-verified-coursemodes
Disallow free verified course modes (second attempt)
This commit is contained in:
@@ -488,7 +488,8 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase):
|
||||
verified_mode = CourseMode(
|
||||
course_id=unicode(self.course.id),
|
||||
mode_slug=CourseMode.VERIFIED,
|
||||
mode_display_name=CourseMode.VERIFIED
|
||||
mode_display_name=CourseMode.VERIFIED,
|
||||
min_price=1
|
||||
)
|
||||
verified_mode.save()
|
||||
self.reindex_course(store)
|
||||
|
||||
@@ -137,6 +137,8 @@ class CourseMode(models.Model):
|
||||
raise ValidationError(
|
||||
_(u"Professional education modes are not allowed to have expiration_datetime set.")
|
||||
)
|
||||
if self.is_verified_slug(self.mode_slug) and self.min_price <= 0:
|
||||
raise ValidationError(_(u"Verified modes cannot be free."))
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None):
|
||||
# Ensure currency is always lowercase.
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
"""
|
||||
Factories for course mode models.
|
||||
"""
|
||||
import random
|
||||
|
||||
from course_modes.models import CourseMode
|
||||
from factory.django import DjangoModelFactory
|
||||
from factory import lazy_attribute
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
|
||||
|
||||
@@ -11,8 +17,16 @@ class CourseModeFactory(DjangoModelFactory):
|
||||
|
||||
course_id = SlashSeparatedCourseKey('MITx', '999', 'Robot_Super_Course')
|
||||
mode_slug = 'audit'
|
||||
mode_display_name = 'audit course'
|
||||
min_price = 0
|
||||
currency = 'usd'
|
||||
expiration_datetime = None
|
||||
suggested_prices = ''
|
||||
|
||||
@lazy_attribute
|
||||
def min_price(self):
|
||||
if CourseMode.is_verified_slug(self.mode_slug):
|
||||
return random.randint(1, 100)
|
||||
return 0
|
||||
|
||||
@lazy_attribute
|
||||
def mode_display_name(self):
|
||||
return '{0} course'.format(self.mode_slug)
|
||||
|
||||
@@ -16,6 +16,7 @@ from xmodule.modulestore.tests.factories import CourseFactory
|
||||
from student.tests.factories import UserFactory
|
||||
from course_modes.models import CourseMode
|
||||
from course_modes.admin import CourseModeForm
|
||||
from course_modes.tests.factories import CourseModeFactory
|
||||
|
||||
# Technically, we shouldn't be importing verify_student, since it's
|
||||
# defined in the LMS and course_modes is in common. However, the benefits
|
||||
@@ -178,7 +179,7 @@ class AdminCourseModeFormTest(ModuleStoreTestCase):
|
||||
|
||||
def _configure(self, mode, upgrade_deadline=None, verification_deadline=None):
|
||||
"""Configure course modes and deadlines. """
|
||||
course_mode = CourseMode.objects.create(
|
||||
course_mode = CourseModeFactory.create(
|
||||
mode_slug=mode,
|
||||
mode_display_name=mode,
|
||||
)
|
||||
@@ -193,7 +194,7 @@ class AdminCourseModeFormTest(ModuleStoreTestCase):
|
||||
|
||||
def _admin_form(self, mode, upgrade_deadline=None):
|
||||
"""Load the course mode admin form. """
|
||||
course_mode = CourseMode.objects.create(
|
||||
course_mode = CourseModeFactory.create(
|
||||
course_id=self.course.id,
|
||||
mode_slug=mode,
|
||||
)
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -60,7 +60,7 @@ class CourseModeSignalTest(ModuleStoreTestCase):
|
||||
@ddt.data(1, 14, 30)
|
||||
def test_verified_mode(self, verification_window):
|
||||
""" Verify signal updates expiration to configured time period before course end for verified mode. """
|
||||
course_mode, __ = self.create_mode('verified', 'verified')
|
||||
course_mode, __ = self.create_mode('verified', 'verified', 10)
|
||||
self.assertIsNone(course_mode.expiration_datetime)
|
||||
|
||||
with patch('course_modes.models.CourseModeExpirationConfig.current') as config:
|
||||
@@ -75,7 +75,7 @@ class CourseModeSignalTest(ModuleStoreTestCase):
|
||||
@ddt.data(1, 14, 30)
|
||||
def test_verified_mode_explicitly_set(self, verification_window):
|
||||
""" Verify signal does not update expiration for verified mode with explicitly set expiration. """
|
||||
course_mode, __ = self.create_mode('verified', 'verified')
|
||||
course_mode, __ = self.create_mode('verified', 'verified', 10)
|
||||
course_mode.expiration_datetime_is_explicit = True
|
||||
self.assertIsNone(course_mode.expiration_datetime)
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
|
||||
def test_redirect_to_dashboard(self, is_active, enrollment_mode, redirect):
|
||||
# Create the course modes
|
||||
for mode in ('audit', 'honor', 'verified'):
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id)
|
||||
|
||||
# Enroll the user in the test course
|
||||
if enrollment_mode is not None:
|
||||
@@ -73,7 +73,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
|
||||
|
||||
def test_no_id_redirect(self):
|
||||
# Create the course modes
|
||||
CourseModeFactory(mode_slug=CourseMode.NO_ID_PROFESSIONAL_MODE, course_id=self.course.id, min_price=100)
|
||||
CourseModeFactory.create(mode_slug=CourseMode.NO_ID_PROFESSIONAL_MODE, course_id=self.course.id, min_price=100)
|
||||
|
||||
# Enroll the user in the test course
|
||||
CourseEnrollmentFactory(
|
||||
@@ -112,7 +112,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
|
||||
def test_no_enrollment(self):
|
||||
# Create the course modes
|
||||
for mode in ('audit', 'honor', 'verified'):
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id)
|
||||
|
||||
# User visits the track selection page directly without ever enrolling
|
||||
url = reverse('course_modes_choose', args=[unicode(self.course.id)])
|
||||
@@ -130,9 +130,9 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
|
||||
|
||||
# Create the course modes
|
||||
for mode in ('audit', 'honor'):
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id)
|
||||
|
||||
CourseModeFactory(
|
||||
CourseModeFactory.create(
|
||||
mode_slug='verified',
|
||||
course_id=self.course.id,
|
||||
suggested_prices=price_list
|
||||
@@ -164,7 +164,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
|
||||
def test_credit_upsell_message(self, available_modes, show_upsell):
|
||||
# Create the course modes
|
||||
for mode in available_modes:
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id)
|
||||
|
||||
# Check whether credit upsell is shown on the page
|
||||
# This should *only* be shown when a credit mode is available
|
||||
@@ -179,7 +179,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
|
||||
@ddt.data('professional', 'no-id-professional')
|
||||
def test_professional_enrollment(self, mode):
|
||||
# The only course mode is professional ed
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id, min_price=1)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id, min_price=1)
|
||||
|
||||
# Go to the "choose your track" page
|
||||
choose_track_url = reverse('course_modes_choose', args=[unicode(self.course.id)])
|
||||
@@ -219,8 +219,8 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
|
||||
def test_choose_mode_redirect(self, course_mode, expected_redirect):
|
||||
# Create the course modes
|
||||
for mode in ('audit', 'honor', 'verified'):
|
||||
min_price = 0 if course_mode in ["honor", "audit"] else 1
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id, min_price=min_price)
|
||||
min_price = 0 if mode in ["honor", "audit"] else 1
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id, min_price=min_price)
|
||||
|
||||
# Choose the mode (POST request)
|
||||
choose_track_url = reverse('course_modes_choose', args=[unicode(self.course.id)])
|
||||
@@ -241,8 +241,8 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
|
||||
|
||||
def test_remember_donation_for_course(self):
|
||||
# Create the course modes
|
||||
for mode in ('honor', 'verified'):
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
|
||||
CourseModeFactory.create(mode_slug='honor', course_id=self.course.id)
|
||||
CourseModeFactory.create(mode_slug='verified', course_id=self.course.id, min_price=1)
|
||||
|
||||
# Choose the mode (POST request)
|
||||
choose_track_url = reverse('course_modes_choose', args=[unicode(self.course.id)])
|
||||
@@ -259,7 +259,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
|
||||
def test_successful_default_enrollment(self):
|
||||
# Create the course modes
|
||||
for mode in (CourseMode.DEFAULT_MODE_SLUG, 'verified'):
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id)
|
||||
|
||||
# Enroll the user in the default mode (honor) to emulate
|
||||
# automatic enrollment
|
||||
@@ -281,7 +281,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
|
||||
def test_unsupported_enrollment_mode_failure(self):
|
||||
# Create the supported course modes
|
||||
for mode in ('honor', 'verified'):
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id)
|
||||
|
||||
# Choose an unsupported mode (POST request)
|
||||
choose_track_url = reverse('course_modes_choose', args=[unicode(self.course.id)])
|
||||
@@ -356,7 +356,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
|
||||
def test_hide_nav(self):
|
||||
# Create the course modes
|
||||
for mode in ["honor", "verified"]:
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id)
|
||||
|
||||
# Load the track selection page
|
||||
url = reverse('course_modes_choose', args=[unicode(self.course.id)])
|
||||
@@ -393,8 +393,8 @@ class TrackSelectionEmbargoTest(UrlResetMixin, ModuleStoreTestCase):
|
||||
|
||||
# Create a course and course modes
|
||||
self.course = CourseFactory.create()
|
||||
CourseModeFactory(mode_slug='honor', course_id=self.course.id)
|
||||
CourseModeFactory(mode_slug='verified', course_id=self.course.id, min_price=10)
|
||||
CourseModeFactory.create(mode_slug='honor', course_id=self.course.id)
|
||||
CourseModeFactory.create(mode_slug='verified', course_id=self.course.id, min_price=10)
|
||||
|
||||
# Create a user and log in
|
||||
self.user = UserFactory.create(username="Bob", email="bob@example.com", password="edx")
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
"""Provides factories for student models."""
|
||||
import random
|
||||
|
||||
from student.models import (User, UserProfile, Registration,
|
||||
CourseEnrollmentAllowed, CourseEnrollment,
|
||||
PendingEmailChange, UserStanding,
|
||||
@@ -7,6 +9,7 @@ from course_modes.models import CourseMode
|
||||
from django.contrib.auth.models import Group, AnonymousUser
|
||||
from datetime import datetime
|
||||
import factory
|
||||
from factory import lazy_attribute
|
||||
from factory.django import DjangoModelFactory
|
||||
from uuid import uuid4
|
||||
from pytz import UTC
|
||||
@@ -54,11 +57,16 @@ class CourseModeFactory(DjangoModelFactory):
|
||||
course_id = None
|
||||
mode_display_name = CourseMode.DEFAULT_MODE.name
|
||||
mode_slug = CourseMode.DEFAULT_MODE_SLUG
|
||||
min_price = 0
|
||||
suggested_prices = ''
|
||||
currency = 'usd'
|
||||
expiration_datetime = None
|
||||
|
||||
@lazy_attribute
|
||||
def min_price(self):
|
||||
if CourseMode.is_verified_slug(self.mode_slug):
|
||||
return random.randint(1, 100)
|
||||
return 0
|
||||
|
||||
|
||||
class RegistrationFactory(DjangoModelFactory):
|
||||
class Meta(object):
|
||||
|
||||
@@ -182,7 +182,7 @@ class TestRecentEnrollments(ModuleStoreTestCase, XssTestMixin):
|
||||
|
||||
# Create the course mode(s)
|
||||
for mode, min_price in course_modes:
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id, min_price=min_price)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id, min_price=min_price)
|
||||
|
||||
self.enrollment.mode = enrollment_mode
|
||||
self.enrollment.save()
|
||||
@@ -203,7 +203,7 @@ class TestRecentEnrollments(ModuleStoreTestCase, XssTestMixin):
|
||||
|
||||
# Create a white-label course mode
|
||||
# (honor mode with a price set)
|
||||
CourseModeFactory(mode_slug="honor", course_id=self.course.id, min_price=100)
|
||||
CourseModeFactory.create(mode_slug="honor", course_id=self.course.id, min_price=100)
|
||||
|
||||
# Check that the donate button is NOT displayed
|
||||
self.client.login(username=self.student.username, password=self.PASSWORD)
|
||||
|
||||
@@ -245,7 +245,7 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase):
|
||||
# Adding another verification with different course.
|
||||
# Its created_at is greater than course deadline.
|
||||
course2 = CourseFactory.create()
|
||||
CourseModeFactory(
|
||||
CourseModeFactory.create(
|
||||
course_id=course2.id,
|
||||
mode_slug="verified",
|
||||
expiration_datetime=self.PAST
|
||||
@@ -277,7 +277,7 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase):
|
||||
enrollment_mode (str): The mode of the enrollment.
|
||||
|
||||
"""
|
||||
CourseModeFactory(
|
||||
CourseModeFactory.create(
|
||||
course_id=self.course.id,
|
||||
mode_slug="verified",
|
||||
expiration_datetime=deadline
|
||||
|
||||
@@ -226,7 +226,7 @@ class DashboardTest(ModuleStoreTestCase):
|
||||
"""
|
||||
Check that the css class and the status message are in the dashboard html.
|
||||
"""
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id)
|
||||
CourseEnrollment.enroll(self.user, self.course.location.course_key, mode=mode)
|
||||
|
||||
if mode == 'verified':
|
||||
@@ -263,7 +263,7 @@ class DashboardTest(ModuleStoreTestCase):
|
||||
"""
|
||||
Check that the css class and the status message are not in the dashboard html.
|
||||
"""
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id)
|
||||
CourseEnrollment.enroll(self.user, self.course.location.course_key, mode=mode)
|
||||
|
||||
if mode == 'verified':
|
||||
|
||||
@@ -369,8 +369,8 @@ class GenerateExampleCertificatesTest(TestCase):
|
||||
|
||||
def test_generate_example_certs_with_verified_mode(self):
|
||||
# Create verified and honor modes for the course
|
||||
CourseModeFactory(course_id=self.COURSE_KEY, mode_slug='honor')
|
||||
CourseModeFactory(course_id=self.COURSE_KEY, mode_slug='verified')
|
||||
CourseModeFactory.create(course_id=self.COURSE_KEY, mode_slug='honor')
|
||||
CourseModeFactory.create(course_id=self.COURSE_KEY, mode_slug='verified')
|
||||
|
||||
# Generate certificates for the course
|
||||
with self._mock_xqueue() as mock_queue:
|
||||
|
||||
@@ -649,9 +649,13 @@ class ViewsTestCase(ModuleStoreTestCase):
|
||||
(verified_course_deadline_passed, CourseMode.AUDIT, datetime.now(UTC) - timedelta(days=1))
|
||||
)
|
||||
for course, mode, expiration in enrollments:
|
||||
CourseModeFactory(mode_slug=CourseMode.AUDIT, course_id=course)
|
||||
CourseModeFactory.create(mode_slug=CourseMode.AUDIT, course_id=course)
|
||||
if course != non_verified_course:
|
||||
CourseModeFactory(mode_slug=CourseMode.VERIFIED, course_id=course, expiration_datetime=expiration)
|
||||
CourseModeFactory.create(
|
||||
mode_slug=CourseMode.VERIFIED,
|
||||
course_id=course,
|
||||
expiration_datetime=expiration
|
||||
)
|
||||
CourseEnrollmentFactory(course_id=course, user=self.user, mode=mode)
|
||||
|
||||
self.client.login(username=self.user.username, password=self.password)
|
||||
|
||||
@@ -403,7 +403,7 @@ class TestInstructorAPIBulkAccountCreationAndEnrollment(SharedModuleStoreTestCas
|
||||
|
||||
# Create a course with mode 'audit'
|
||||
cls.audit_course = CourseFactory.create()
|
||||
CourseModeFactory(course_id=cls.audit_course.id, mode_slug=CourseMode.AUDIT)
|
||||
CourseModeFactory.create(course_id=cls.audit_course.id, mode_slug=CourseMode.AUDIT)
|
||||
|
||||
cls.url = reverse(
|
||||
'register_and_enroll_students', kwargs={'course_id': unicode(cls.course.id)}
|
||||
@@ -417,7 +417,7 @@ class TestInstructorAPIBulkAccountCreationAndEnrollment(SharedModuleStoreTestCas
|
||||
|
||||
# Create a course with mode 'honor' and with price
|
||||
self.white_label_course = CourseFactory.create()
|
||||
self.white_label_course_mode = CourseModeFactory(
|
||||
self.white_label_course_mode = CourseModeFactory.create(
|
||||
course_id=self.white_label_course.id,
|
||||
mode_slug=CourseMode.HONOR,
|
||||
min_price=10,
|
||||
|
||||
@@ -29,7 +29,7 @@ class UserCartContextProcessorUnitTest(ModuleStoreTestCase):
|
||||
Adds content to self.user's cart
|
||||
"""
|
||||
course = CourseFactory.create(org='MITx', number='999', display_name='Robot Super Course')
|
||||
CourseModeFactory(course_id=course.id)
|
||||
CourseModeFactory.create(course_id=course.id)
|
||||
cart = Order.get_cart_for_user(self.user)
|
||||
PaidCourseRegistration.add_to_order(cart, course.id)
|
||||
|
||||
|
||||
@@ -44,7 +44,11 @@ class RefundTests(ModuleStoreTestCase):
|
||||
username='student',
|
||||
email='student+refund@edx.org'
|
||||
)
|
||||
self.course_mode = CourseMode.objects.get_or_create(course_id=self.course_id, mode_slug='verified')[0]
|
||||
self.course_mode = CourseMode.objects.get_or_create(
|
||||
course_id=self.course_id,
|
||||
mode_slug='verified',
|
||||
min_price=1
|
||||
)[0]
|
||||
|
||||
self.order = None
|
||||
self.form_pars = {'course_id': str(self.course_id), 'user': self.student.email}
|
||||
|
||||
@@ -26,7 +26,7 @@ class TestProfEdVerification(ModuleStoreTestCase):
|
||||
self.client.login(username="rusty", password="test")
|
||||
course = CourseFactory.create(org='Robot', number='999', display_name='Test Course')
|
||||
self.course_key = course.id
|
||||
CourseModeFactory(
|
||||
CourseModeFactory.create(
|
||||
mode_slug="professional",
|
||||
course_id=self.course_key,
|
||||
min_price=self.MIN_PRICE,
|
||||
|
||||
@@ -31,7 +31,7 @@ class TestReverificationService(ModuleStoreTestCase):
|
||||
self.user = UserFactory.create(username="rusty", password="test")
|
||||
self.course = CourseFactory.create(org='Robot', number='999', display_name='Test Course')
|
||||
self.course_id = self.course.id
|
||||
CourseModeFactory(
|
||||
CourseModeFactory.create(
|
||||
mode_slug="verified",
|
||||
course_id=self.course_id,
|
||||
min_price=100,
|
||||
|
||||
@@ -822,7 +822,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
|
||||
|
||||
for course_mode in course_modes:
|
||||
min_price = (0 if course_mode in ["honor", "audit"] else self.MIN_PRICE)
|
||||
CourseModeFactory(
|
||||
CourseModeFactory.create(
|
||||
course_id=course.id,
|
||||
mode_slug=course_mode,
|
||||
mode_display_name=course_mode,
|
||||
@@ -1012,7 +1012,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
|
||||
course = CourseFactory.create(display_name=mode_display_name)
|
||||
for course_mode in [CourseMode.DEFAULT_MODE_SLUG, "verified"]:
|
||||
min_price = (self.MIN_PRICE if course_mode != CourseMode.DEFAULT_MODE_SLUG else 0)
|
||||
CourseModeFactory(
|
||||
CourseModeFactory.create(
|
||||
course_id=course.id,
|
||||
mode_slug=course_mode,
|
||||
mode_display_name=mode_display_name,
|
||||
@@ -1074,7 +1074,7 @@ class CheckoutTestMixin(object):
|
||||
self.user = UserFactory.create(username="test", password="test")
|
||||
self.course = CourseFactory.create()
|
||||
for mode, min_price in (('audit', 0), ('honor', 0), ('verified', 100)):
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course.id, min_price=min_price, sku=self.make_sku())
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course.id, min_price=min_price, sku=self.make_sku())
|
||||
self.client.login(username="test", password="test")
|
||||
|
||||
def _assert_checked_out(
|
||||
@@ -1119,7 +1119,7 @@ class CheckoutTestMixin(object):
|
||||
def test_create_order_prof_ed(self, patched_create_order):
|
||||
# Create a prof ed course
|
||||
course = CourseFactory.create()
|
||||
CourseModeFactory(mode_slug="professional", course_id=course.id, min_price=10, sku=self.make_sku())
|
||||
CourseModeFactory.create(mode_slug="professional", course_id=course.id, min_price=10, sku=self.make_sku())
|
||||
# Create an order for a prof ed course
|
||||
params = {'course_id': unicode(course.id)}
|
||||
self._assert_checked_out(params, patched_create_order, course.id, 'professional')
|
||||
@@ -1127,7 +1127,7 @@ class CheckoutTestMixin(object):
|
||||
def test_create_order_no_id_professional(self, patched_create_order):
|
||||
# Create a no-id-professional ed course
|
||||
course = CourseFactory.create()
|
||||
CourseModeFactory(mode_slug="no-id-professional", course_id=course.id, min_price=10, sku=self.make_sku())
|
||||
CourseModeFactory.create(mode_slug="no-id-professional", course_id=course.id, min_price=10, sku=self.make_sku())
|
||||
# Create an order for a prof ed course
|
||||
params = {'course_id': unicode(course.id)}
|
||||
self._assert_checked_out(params, patched_create_order, course.id, 'no-id-professional')
|
||||
@@ -1135,8 +1135,8 @@ class CheckoutTestMixin(object):
|
||||
def test_create_order_for_multiple_paid_modes(self, patched_create_order):
|
||||
# Create a no-id-professional ed course
|
||||
course = CourseFactory.create()
|
||||
CourseModeFactory(mode_slug="no-id-professional", course_id=course.id, min_price=10, sku=self.make_sku())
|
||||
CourseModeFactory(mode_slug="professional", course_id=course.id, min_price=10, sku=self.make_sku())
|
||||
CourseModeFactory.create(mode_slug="no-id-professional", course_id=course.id, min_price=10, sku=self.make_sku())
|
||||
CourseModeFactory.create(mode_slug="professional", course_id=course.id, min_price=10, sku=self.make_sku())
|
||||
# Create an order for a prof ed course
|
||||
params = {'course_id': unicode(course.id)}
|
||||
# TODO jsa - is this the intended behavior?
|
||||
@@ -1227,7 +1227,7 @@ class TestCheckoutWithEcommerceService(ModuleStoreTestCase):
|
||||
ecommerce api, we correctly call to that api to create a basket.
|
||||
"""
|
||||
user = UserFactory.create(username="test-username")
|
||||
course_mode = CourseModeFactory(sku="test-sku").to_tuple() # pylint: disable=no-member
|
||||
course_mode = CourseModeFactory.create(sku="test-sku").to_tuple() # pylint: disable=no-member
|
||||
expected_payment_data = {'foo': 'bar'}
|
||||
# mock out the payment processors endpoint
|
||||
httpretty.register_uri(
|
||||
@@ -2079,7 +2079,7 @@ class TestInCourseReverifyView(ModuleStoreTestCase):
|
||||
# Create the course modes
|
||||
for mode in ('audit', 'honor', 'verified'):
|
||||
min_price = 0 if mode in ["honor", "audit"] else 1
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course_key, min_price=min_price)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course_key, min_price=min_price)
|
||||
|
||||
# Create the 'edx-reverification-block' in course tree
|
||||
section = ItemFactory.create(parent=self.course, category='chapter', display_name='Test Section')
|
||||
@@ -2280,7 +2280,7 @@ class TestEmailMessageWithCustomICRVBlock(ModuleStoreTestCase):
|
||||
# Create the course modes
|
||||
for mode in ('audit', 'honor', 'verified'):
|
||||
min_price = 0 if mode in ["honor", "audit"] else 1
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course_key, min_price=min_price)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course_key, min_price=min_price)
|
||||
|
||||
# Create the 'edx-reverification-block' in course tree
|
||||
section = ItemFactory.create(parent=self.course, category='chapter', display_name='Test Section')
|
||||
@@ -2483,7 +2483,7 @@ class TestEmailMessageWithDefaultICRVBlock(ModuleStoreTestCase):
|
||||
# Create the course modes
|
||||
for mode in ('audit', 'honor', 'verified'):
|
||||
min_price = 0 if mode in ["honor", "audit"] else 1
|
||||
CourseModeFactory(mode_slug=mode, course_id=self.course_key, min_price=min_price)
|
||||
CourseModeFactory.create(mode_slug=mode, course_id=self.course_key, min_price=min_price)
|
||||
|
||||
# Create the 'edx-reverification-block' in course tree
|
||||
section = ItemFactory.create(parent=self.course, category='chapter', display_name='Test Section')
|
||||
|
||||
Reference in New Issue
Block a user