Merge pull request #6720 from edx/renzo/remove-split-verification-session-flag
Remove old payment and verification flow
This commit is contained in:
@@ -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")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -252,12 +252,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(
|
||||
@@ -277,7 +277,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
|
||||
@@ -303,7 +303,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
|
||||
@@ -314,7 +314,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
|
||||
@@ -326,7 +326,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
|
||||
@@ -337,7 +337,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
|
||||
@@ -356,7 +356,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
|
||||
|
||||
Reference in New Issue
Block a user