Remove old payment and verification flow

Removes old payment and verification endpoints, views, templates, and tests, making the new split flow the default. The SEPARATE_VERIFICATION_FROM_PAYMENT feature flag is also removed.
This commit is contained in:
Renzo Lucioni
2015-01-21 15:22:32 -05:00
parent 1ad0e9fdd8
commit 80589eab36
27 changed files with 994 additions and 2669 deletions

View File

@@ -70,18 +70,6 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
else:
self.assertEquals(response.status_code, 200)
def test_upgrade_copy(self):
# Create the course modes
for mode in ('audit', 'honor', 'verified'):
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
url = reverse('course_modes_choose', args=[unicode(self.course.id)])
response = self.client.get(url, {"upgrade": True})
# Verify that the upgrade copy is displayed instead
# of the usual text.
self.assertContains(response, "Upgrade Your Enrollment")
def test_no_enrollment(self):
# Create the course modes
for mode in ('audit', 'honor', 'verified'):
@@ -137,10 +125,10 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
choose_track_url = reverse('course_modes_choose', args=[unicode(self.course.id)])
response = self.client.get(choose_track_url)
# Expect that we're redirected immediately to the "show requirements" page
# (since the only available track is professional ed)
show_reqs_url = reverse('verify_student_show_requirements', args=[unicode(self.course.id)])
self.assertRedirects(response, show_reqs_url)
# Since the only available track is professional ed, expect that
# we're redirected immediately to the start of the payment flow.
start_flow_url = reverse('verify_student_start_flow', args=[unicode(self.course.id)])
self.assertRedirects(response, start_flow_url)
# Now enroll in the course
CourseEnrollmentFactory(
@@ -164,7 +152,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
@ddt.data(
('honor', 'dashboard'),
('verified', 'show_requirements'),
('verified', 'start-flow'),
)
@ddt.unpack
def test_choose_mode_redirect(self, course_mode, expected_redirect):
@@ -179,11 +167,11 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
# Verify the redirect
if expected_redirect == 'dashboard':
redirect_url = reverse('dashboard')
elif expected_redirect == 'show_requirements':
elif expected_redirect == 'start-flow':
redirect_url = reverse(
'verify_student_show_requirements',
'verify_student_start_flow',
kwargs={'course_id': unicode(self.course.id)}
) + "?upgrade=False"
)
else:
self.fail("Must provide a valid redirect URL name")

View File

@@ -52,19 +52,6 @@ class ChooseModeView(View):
"""
course_key = CourseKey.from_string(course_id)
upgrade = request.GET.get('upgrade', False)
request.session['attempting_upgrade'] = upgrade
# TODO (ECOM-188): Once the A/B test of decoupled/verified flows
# completes, we can remove this flag.
# The A/B test framework will reload the page with the ?separate-verified GET param
# set if the user is in the experimental condition. We then store this flag
# in a session variable so downstream views can check it.
if request.GET.get('separate-verified', False):
request.session['separate-verified'] = True
elif request.GET.get('disable-separate-verified', False) and 'separate-verified' in request.session:
del request.session['separate-verified']
enrollment_mode, is_active = CourseEnrollment.enrollment_mode_for_user(request.user, course_key)
modes = CourseMode.modes_for_course_dict(course_key)
@@ -73,22 +60,12 @@ class ChooseModeView(View):
# to the usual "choose your track" page.
has_enrolled_professional = (enrollment_mode == "professional" and is_active)
if "professional" in modes and not has_enrolled_professional:
# TODO (ECOM-188): Once the A/B test of separating verification / payment completes,
# we can remove the check for the session variable.
if settings.FEATURES.get('SEPARATE_VERIFICATION_FROM_PAYMENT') and request.session.get('separate-verified', False):
return redirect(
reverse(
'verify_student_start_flow',
kwargs={'course_id': unicode(course_key)}
)
)
else:
return redirect(
reverse(
'verify_student_show_requirements',
kwargs={'course_id': unicode(course_key)}
)
return redirect(
reverse(
'verify_student_start_flow',
kwargs={'course_id': unicode(course_key)}
)
)
# If there isn't a verified mode available, then there's nothing
# to do on this page. The user has almost certainly been auto-registered
@@ -113,7 +90,6 @@ class ChooseModeView(View):
"course_num": course.display_number_with_default,
"chosen_price": chosen_price,
"error": error,
"upgrade": upgrade,
"can_audit": "audit" in modes,
"responsive": True
}
@@ -156,8 +132,6 @@ class ChooseModeView(View):
error_msg = _("Enrollment is closed")
return self.get(request, course_id, error=error_msg)
upgrade = request.GET.get('upgrade', False)
requested_mode = self._get_requested_mode(request.POST)
allowed_modes = CourseMode.modes_for_course_dict(course_key)
@@ -192,22 +166,12 @@ class ChooseModeView(View):
donation_for_course[unicode(course_key)] = amount_value
request.session["donation_for_course"] = donation_for_course
# TODO (ECOM-188): Once the A/B test of separate verification flow completes,
# we can remove the check for the session variable.
if settings.FEATURES.get('SEPARATE_VERIFICATION_FROM_PAYMENT') and request.session.get('separate-verified', False):
return redirect(
reverse(
'verify_student_start_flow',
kwargs={'course_id': unicode(course_key)}
)
)
else:
return redirect(
reverse(
'verify_student_show_requirements',
kwargs={'course_id': unicode(course_key)}
) + "?upgrade={}".format(upgrade)
return redirect(
reverse(
'verify_student_start_flow',
kwargs={'course_id': unicode(course_key)}
)
)
def _get_requested_mode(self, request_dict):
"""Get the user's requested mode

View File

@@ -28,10 +28,7 @@ MODULESTORE_CONFIG = mixed_store_config(settings.COMMON_TEST_DATA_ROOT, {}, incl
@override_settings(MODULESTORE=MODULESTORE_CONFIG)
@patch.dict(settings.FEATURES, {
'SEPARATE_VERIFICATION_FROM_PAYMENT': True,
'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': True
})
@patch.dict(settings.FEATURES, {'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': True})
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@ddt.ddt
class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase):
@@ -40,7 +37,6 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase):
PAST = datetime.now(UTC) - timedelta(days=5)
FUTURE = datetime.now(UTC) + timedelta(days=5)
@patch.dict(settings.FEATURES, {'SEPARATE_VERIFICATION_FROM_PAYMENT': True})
def setUp(self):
# Invoke UrlResetMixin
super(TestCourseVerificationStatus, self).setUp('verify_student.urls')

View File

@@ -35,6 +35,7 @@ from xmodule.modulestore.tests.django_utils import TEST_DATA_MOCK_MODULESTORE
from bulk_email.models import Optout # pylint: disable=import-error
from certificates.models import CertificateStatuses # pylint: disable=import-error
from certificates.tests.factories import GeneratedCertificateFactory # pylint: disable=import-error
from verify_student.models import SoftwareSecurePhotoVerification
import shoppingcart # pylint: disable=import-error
@@ -192,11 +193,20 @@ class DashboardTest(ModuleStoreTestCase):
self.client = Client()
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
def check_verification_status_on(self, mode, value):
def _check_verification_status_on(self, mode, value):
"""
Check that the css class and the status message are in the dashboard html.
"""
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
CourseEnrollment.enroll(self.user, self.course.location.course_key, mode=mode)
if mode == 'verified':
# Simulate a successful verification attempt
attempt = SoftwareSecurePhotoVerification.objects.create(user=self.user)
attempt.mark_ready()
attempt.submit()
attempt.approve()
response = self.client.get(reverse('dashboard'))
self.assertContains(response, "class=\"course {0}\"".format(mode))
self.assertContains(response, value)
@@ -207,16 +217,25 @@ class DashboardTest(ModuleStoreTestCase):
Test that the certificate verification status for courses is visible on the dashboard.
"""
self.client.login(username="jack", password="test")
self.check_verification_status_on('verified', 'You\'re enrolled as a verified student')
self.check_verification_status_on('honor', 'You\'re enrolled as an honor code student')
self.check_verification_status_on('audit', 'You\'re auditing this course')
self._check_verification_status_on('verified', 'You\'re enrolled as a verified student')
self._check_verification_status_on('honor', 'You\'re enrolled as an honor code student')
self._check_verification_status_on('audit', 'You\'re auditing this course')
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
def check_verification_status_off(self, mode, value):
def _check_verification_status_off(self, mode, value):
"""
Check that the css class and the status message are not in the dashboard html.
"""
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
CourseEnrollment.enroll(self.user, self.course.location.course_key, mode=mode)
if mode == 'verified':
# Simulate a successful verification attempt
attempt = SoftwareSecurePhotoVerification.objects.create(user=self.user)
attempt.mark_ready()
attempt.submit()
attempt.approve()
response = self.client.get(reverse('dashboard'))
self.assertNotContains(response, "class=\"course {0}\"".format(mode))
self.assertNotContains(response, value)
@@ -228,9 +247,9 @@ class DashboardTest(ModuleStoreTestCase):
if the verified certificates setting is off.
"""
self.client.login(username="jack", password="test")
self.check_verification_status_off('verified', 'You\'re enrolled as a verified student')
self.check_verification_status_off('honor', 'You\'re enrolled as an honor code student')
self.check_verification_status_off('audit', 'You\'re auditing this course')
self._check_verification_status_off('verified', 'You\'re enrolled as a verified student')
self._check_verification_status_off('honor', 'You\'re enrolled as an honor code student')
self._check_verification_status_off('audit', 'You\'re auditing this course')
def test_course_mode_info(self):
verified_mode = CourseModeFactory.create(

View File

@@ -573,22 +573,11 @@ def dashboard(request):
#
# If a course is not included in this dictionary,
# there is no verification messaging to display.
#
# TODO (ECOM-188): After the A/B test completes, we can remove the check
# for the GET param and the session var.
# The A/B test framework will set the GET param for users in the experimental
# group; we then set the session var so downstream views can check this.
if settings.FEATURES.get("SEPARATE_VERIFICATION_FROM_PAYMENT") and request.GET.get('separate-verified', False):
request.session['separate-verified'] = True
verify_status_by_course = check_verify_status_by_course(
user,
course_enrollment_pairs,
all_course_modes
)
else:
if request.GET.get('disable-separate-verified', False) and 'separate-verified' in request.session:
del request.session['separate-verified']
verify_status_by_course = {}
verify_status_by_course = check_verify_status_by_course(
user,
course_enrollment_pairs,
all_course_modes
)
cert_statuses = {
course.id: cert_info(request.user, course)

View File

@@ -13,32 +13,15 @@ class DashboardPage(PageObject):
Student dashboard, where the student can view
courses she/he has registered for.
"""
def __init__(self, browser, separate_verified=False):
def __init__(self, browser):
"""Initialize the page.
Arguments:
browser (Browser): The browser instance.
Keyword Arguments:
separate_verified (Boolean): Whether to use the split payment and
verification flow.
"""
super(DashboardPage, self).__init__(browser)
if separate_verified:
self._querystring = "?separate-verified=1"
else:
self._querystring = "?disable-separate-verified=1"
@property
def url(self):
"""Return the URL corresponding to the dashboard."""
url = "{base}/dashboard{querystring}".format(
base=BASE_URL,
querystring=self._querystring
)
return url
url = "{base}/dashboard".format(base=BASE_URL)
def is_browser_on_page(self):
return self.q(css='section.my-courses').present

View File

@@ -12,11 +12,7 @@ from .dashboard import DashboardPage
class PaymentAndVerificationFlow(PageObject):
"""Interact with the split payment and verification flow.
These pages are currently hidden behind the feature flag
`SEPARATE_VERIFICATION_FROM_PAYMENT`, which is enabled in
the Bok Choy settings.
When enabled, the flow can be accessed at the following URLs:
The flow can be accessed at the following URLs:
`/verify_student/start-flow/{course}/`
`/verify_student/upgrade/{course}/`
`/verify_student/verify-now/{course}/`
@@ -121,7 +117,7 @@ class PaymentAndVerificationFlow(PageObject):
else:
raise Exception("The dashboard can only be accessed from the enrollment confirmation.")
DashboardPage(self.browser, separate_verified=True).wait_for_page()
DashboardPage(self.browser).wait_for_page()
class FakePaymentPage(PageObject):

View File

@@ -14,33 +14,22 @@ class TrackSelectionPage(PageObject):
This page can be accessed at `/course_modes/choose/{course_id}/`.
"""
def __init__(self, browser, course_id, separate_verified=False):
def __init__(self, browser, course_id):
"""Initialize the page.
Arguments:
browser (Browser): The browser instance.
course_id (unicode): The course in which the user is enrolling.
Keyword Arguments:
separate_verified (Boolean): Whether to use the split payment and
verification flow when enrolling as verified.
"""
super(TrackSelectionPage, self).__init__(browser)
self._course_id = course_id
self._separate_verified = separate_verified
if self._separate_verified:
self._querystring = "?separate-verified=1"
else:
self._querystring = "?disable-separate-verified=1"
@property
def url(self):
"""Return the URL corresponding to the track selection page."""
url = "{base}/course_modes/choose/{course_id}/{querystring}".format(
url = "{base}/course_modes/choose/{course_id}/".format(
base=BASE_URL,
course_id=self._course_id,
querystring=self._querystring
course_id=self._course_id
)
return url
@@ -61,7 +50,7 @@ class TrackSelectionPage(PageObject):
if mode == "honor":
self.q(css="input[name='honor_mode']").click()
return DashboardPage(self.browser, separate_verified=self._separate_verified).wait_for_page()
return DashboardPage(self.browser).wait_for_page()
elif mode == "verified":
# Check the first contribution option, then click the enroll button
self.q(css=".contribution-option > input").first.click()

View File

@@ -253,12 +253,12 @@ class PayAndVerifyTest(UniqueCourseTest):
"""
super(PayAndVerifyTest, self).setUp()
self.track_selection_page = TrackSelectionPage(self.browser, self.course_id, separate_verified=True)
self.track_selection_page = TrackSelectionPage(self.browser, self.course_id)
self.payment_and_verification_flow = PaymentAndVerificationFlow(self.browser, self.course_id)
self.immediate_verification_page = PaymentAndVerificationFlow(self.browser, self.course_id, entry_point='verify-now')
self.upgrade_page = PaymentAndVerificationFlow(self.browser, self.course_id, entry_point='upgrade')
self.fake_payment_page = FakePaymentPage(self.browser, self.course_id)
self.dashboard_page = DashboardPage(self.browser, separate_verified=True)
self.dashboard_page = DashboardPage(self.browser)
# Create a course
CourseFixture(
@@ -278,7 +278,7 @@ class PayAndVerifyTest(UniqueCourseTest):
# Create a user and log them in
AutoAuthPage(self.browser).visit()
# Navigate to the track selection page with the appropriate GET parameter in the URL
# Navigate to the track selection page
self.track_selection_page.visit()
# Enter the payment and verification flow by choosing to enroll as verified
@@ -304,7 +304,7 @@ class PayAndVerifyTest(UniqueCourseTest):
# Submit photos and proceed to the enrollment confirmation step
self.payment_and_verification_flow.next_verification_step(self.immediate_verification_page)
# Navigate to the dashboard with the appropriate GET parameter in the URL
# Navigate to the dashboard
self.dashboard_page.visit()
# Expect that we're enrolled as verified in the course
@@ -315,7 +315,7 @@ class PayAndVerifyTest(UniqueCourseTest):
# Create a user and log them in
AutoAuthPage(self.browser).visit()
# Navigate to the track selection page with the appropriate GET parameter in the URL
# Navigate to the track selection page
self.track_selection_page.visit()
# Enter the payment and verification flow by choosing to enroll as verified
@@ -327,7 +327,7 @@ class PayAndVerifyTest(UniqueCourseTest):
# Submit payment
self.fake_payment_page.submit_payment()
# Navigate to the dashboard with the appropriate GET parameter in the URL
# Navigate to the dashboard
self.dashboard_page.visit()
# Expect that we're enrolled as verified in the course
@@ -338,7 +338,7 @@ class PayAndVerifyTest(UniqueCourseTest):
# Create a user, log them in, and enroll them in the honor mode
AutoAuthPage(self.browser, course_id=self.course_id).visit()
# Navigate to the dashboard with the appropriate GET parameter in the URL
# Navigate to the dashboard
self.dashboard_page.visit()
# Expect that we're enrolled as honor in the course
@@ -357,7 +357,7 @@ class PayAndVerifyTest(UniqueCourseTest):
# Submit payment
self.fake_payment_page.submit_payment()
# Navigate to the dashboard with the appropriate GET parameter in the URL
# Navigate to the dashboard
self.dashboard_page.visit()
# Expect that we're enrolled as verified in the course