Login/Registration page can skip track selection.
Add querystring param "course_mode" to the login/registration page so the user can skip track selection. This supports upcoming changes to the course details page that allow the user to choose the track when clicking "enroll", which will replace the functionality of the track selection page.
This commit is contained in:
@@ -246,12 +246,25 @@ class StudentAccountLoginAndRegistrationTest(UrlResetMixin, ModuleStoreTestCase)
|
||||
'course_id': 'edX/DemoX/Demo_Course'
|
||||
}
|
||||
|
||||
# The response should have a "Sign In" button with the URL
|
||||
# that preserves the querystring params
|
||||
with mock.patch.dict(settings.FEATURES, {'IS_EDX_DOMAIN': is_edx_domain}):
|
||||
response = self.client.get(reverse(url_name), params)
|
||||
self.assertContains(response, "login?course_id=edX%2FDemoX%2FDemo_Course&enrollment_action=enroll")
|
||||
|
||||
# Add an additional "course mode" parameter
|
||||
params['course_mode'] = 'honor'
|
||||
|
||||
# Verify that this parameter is also preserved
|
||||
with mock.patch.dict(settings.FEATURES, {'IS_EDX_DOMAIN': is_edx_domain}):
|
||||
response = self.client.get(reverse(url_name), params)
|
||||
|
||||
# The response should have a "Sign In" button with the URL
|
||||
# that preserves the querystring params
|
||||
self.assertContains(response, "login?course_id=edX%2FDemoX%2FDemo_Course&enrollment_action=enroll")
|
||||
expected_url = (
|
||||
"login?course_id=edX%2FDemoX%2FDemo_Course"
|
||||
"&enrollment_action=enroll"
|
||||
"&course_mode=honor"
|
||||
)
|
||||
self.assertContains(response, expected_url)
|
||||
|
||||
@mock.patch.dict(settings.FEATURES, {"ENABLE_THIRD_PARTY_AUTH": False})
|
||||
@ddt.data("account_login", "account_register")
|
||||
|
||||
@@ -91,7 +91,8 @@ def login_and_registration_form(request, initial_mode="login"):
|
||||
# We need to pass these parameters so that the header's
|
||||
# "Sign In" button preserves the querystring params.
|
||||
'enrollment_action': request.GET.get('enrollment_action'),
|
||||
'course_id': request.GET.get('course_id')
|
||||
'course_id': request.GET.get('course_id'),
|
||||
'course_mode': request.GET.get('course_mode'),
|
||||
}
|
||||
|
||||
return render_to_response('student_account/login_and_register.html', context)
|
||||
|
||||
@@ -166,7 +166,52 @@ define([
|
||||
view.subview.login.trigger('auth-complete');
|
||||
|
||||
// Expect that the view tried to enroll the student
|
||||
expect( EnrollmentInterface.enroll ).toHaveBeenCalledWith( COURSE_KEY );
|
||||
expect( EnrollmentInterface.enroll ).toHaveBeenCalledWith(
|
||||
COURSE_KEY,
|
||||
'/course_modes/choose/' + COURSE_KEY + '/'
|
||||
);
|
||||
});
|
||||
|
||||
it('sends the user to the payment flow when the course mode is not honor', function() {
|
||||
ajaxSpyAndInitialize(this, 'login');
|
||||
|
||||
// Simulate providing enrollment query string params
|
||||
// AND specifying a course mode.
|
||||
setFakeQueryParams({
|
||||
'?enrollment_action': 'enroll',
|
||||
'?course_id': COURSE_KEY,
|
||||
'?course_mode': 'verified'
|
||||
});
|
||||
|
||||
// Trigger auth complete on the login view
|
||||
view.subview.login.trigger('auth-complete');
|
||||
|
||||
// Expect that the view tried to auto-enroll the student
|
||||
// with a redirect into the payment flow.
|
||||
expect( EnrollmentInterface.enroll ).toHaveBeenCalledWith(
|
||||
COURSE_KEY,
|
||||
'/verify_student/start-flow/' + COURSE_KEY + '/'
|
||||
);
|
||||
});
|
||||
|
||||
it('sends the user to the student dashboard when the course mode is honor', function() {
|
||||
ajaxSpyAndInitialize(this, 'login');
|
||||
|
||||
// Simulate providing enrollment query string params
|
||||
// AND specifying a course mode.
|
||||
setFakeQueryParams({
|
||||
'?enrollment_action': 'enroll',
|
||||
'?course_id': COURSE_KEY,
|
||||
'?course_mode': 'honor'
|
||||
});
|
||||
|
||||
// Trigger auth complete on the login view
|
||||
view.subview.login.trigger('auth-complete');
|
||||
|
||||
// Expect that the view tried auto-enrolled the student
|
||||
// and sent the student to the dashboard
|
||||
// (skipping the payment flow).
|
||||
expect( EnrollmentInterface.enroll ).toHaveBeenCalledWith(COURSE_KEY, '/dashboard');
|
||||
});
|
||||
|
||||
it('adds a white-label course to the shopping cart on auth complete', function() {
|
||||
|
||||
@@ -19,7 +19,7 @@ define(['js/common_helpers/ajax_helpers', 'js/student_account/enrollment'],
|
||||
var requests = AjaxHelpers.requests( this );
|
||||
|
||||
// Attempt to enroll the user
|
||||
EnrollmentInterface.enroll( COURSE_KEY );
|
||||
EnrollmentInterface.enroll( COURSE_KEY, FORWARD_URL );
|
||||
|
||||
// Expect that the correct request was made to the server
|
||||
AjaxHelpers.expectRequest(
|
||||
@@ -41,7 +41,7 @@ define(['js/common_helpers/ajax_helpers', 'js/student_account/enrollment'],
|
||||
var requests = AjaxHelpers.requests( this );
|
||||
|
||||
// Attempt to enroll the user
|
||||
EnrollmentInterface.enroll( COURSE_KEY );
|
||||
EnrollmentInterface.enroll( COURSE_KEY, FORWARD_URL );
|
||||
|
||||
// Simulate an error response from the server
|
||||
AjaxHelpers.respondWithError(requests);
|
||||
@@ -55,7 +55,7 @@ define(['js/common_helpers/ajax_helpers', 'js/student_account/enrollment'],
|
||||
var requests = AjaxHelpers.requests( this );
|
||||
|
||||
// Attempt to enroll the user
|
||||
EnrollmentInterface.enroll( COURSE_KEY );
|
||||
EnrollmentInterface.enroll( COURSE_KEY, FORWARD_URL );
|
||||
|
||||
// Simulate an error response (403) from the server
|
||||
// with a "user_message_url" parameter for the redirect.
|
||||
|
||||
@@ -10,7 +10,6 @@ var edx = edx || {};
|
||||
|
||||
urls: {
|
||||
orders: '/commerce/orders/',
|
||||
trackSelection: '/course_modes/choose/'
|
||||
},
|
||||
|
||||
headers: {
|
||||
@@ -18,11 +17,11 @@ var edx = edx || {};
|
||||
},
|
||||
|
||||
/**
|
||||
* Enroll a user in a course, then redirect the user
|
||||
* to the track selection page.
|
||||
* Enroll a user in a course, then redirect the user.
|
||||
* @param {string} courseKey Slash-separated course key.
|
||||
* @param {string} redirectUrl The URL to redirect to once enrollment completes.
|
||||
*/
|
||||
enroll: function( courseKey ) {
|
||||
enroll: function( courseKey, redirectUrl ) {
|
||||
var data_obj = {course_id: courseKey},
|
||||
data = JSON.stringify(data_obj);
|
||||
|
||||
@@ -42,30 +41,22 @@ var edx = edx || {};
|
||||
// If so, redirect to a page explaining to the user
|
||||
// why they were blocked.
|
||||
this.redirect( responseData.user_message_url );
|
||||
}
|
||||
else {
|
||||
// Otherwise, go to the track selection page as usual.
|
||||
// This can occur, for example, when a course does not
|
||||
// have a free enrollment mode, so we can't auto-enroll.
|
||||
this.redirect( this.trackSelectionUrl( courseKey ) );
|
||||
} else {
|
||||
// Otherwise, redirect the user to the next page.
|
||||
if ( redirectUrl ) {
|
||||
this.redirect( redirectUrl );
|
||||
}
|
||||
}
|
||||
})
|
||||
.done(function() {
|
||||
// If we successfully enrolled, go to the track selection
|
||||
// page to allow the user to choose a paid enrollment mode.
|
||||
this.redirect( this.trackSelectionUrl( courseKey ) );
|
||||
// If we successfully enrolled, redirect the user
|
||||
// to the next page (usually the student dashboard or payment flow)
|
||||
if ( redirectUrl ) {
|
||||
this.redirect( redirectUrl );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Construct the URL to the track selection page for a course.
|
||||
* @param {string} courseKey Slash-separated course key.
|
||||
* @return {string} The URL to the track selection page.
|
||||
*/
|
||||
trackSelectionUrl: function( courseKey ) {
|
||||
return this.urls.trackSelection + courseKey + '/';
|
||||
},
|
||||
|
||||
/**
|
||||
* Redirect to a URL. Mainly useful for mocking out in tests.
|
||||
* @param {string} url The URL to redirect to.
|
||||
|
||||
@@ -29,6 +29,12 @@ var edx = edx || {};
|
||||
passwordHelp: {}
|
||||
},
|
||||
|
||||
urls: {
|
||||
dashboard: '/dashboard',
|
||||
payment: '/verify_student/start-flow/',
|
||||
trackSelection: '/course_modes/choose/'
|
||||
},
|
||||
|
||||
// The form currently loaded
|
||||
activeForm: '',
|
||||
|
||||
@@ -243,15 +249,37 @@ var edx = edx || {};
|
||||
enrollment: function() {
|
||||
var enrollment = edx.student.account.EnrollmentInterface,
|
||||
shoppingcart = edx.student.account.ShoppingCartInterface,
|
||||
redirectUrl = '/dashboard',
|
||||
redirectUrl = this.urls.dashboard,
|
||||
queryParams = this.queryParams();
|
||||
|
||||
if ( queryParams.enrollmentAction === 'enroll' && queryParams.courseId) {
|
||||
/*
|
||||
If we need to enroll in a course, mark as enrolled.
|
||||
The enrollment interface will redirect the student once enrollment completes.
|
||||
*/
|
||||
enrollment.enroll( decodeURIComponent( queryParams.courseId ) );
|
||||
if ( queryParams.enrollmentAction === 'enroll' && queryParams.courseId ) {
|
||||
var courseId = decodeURIComponent( queryParams.courseId );
|
||||
|
||||
// Determine where to redirect the user after auto-enrollment.
|
||||
if ( !queryParams.courseMode ) {
|
||||
/* Backwards compatibility with the original course details page.
|
||||
The old implementation did not specify the course mode for enrollment,
|
||||
so we'd always send the user to the "track selection" page.
|
||||
The track selection page would allow the user to select the course mode
|
||||
("verified", "honor", etc.) -- or, if the only course mode was "honor",
|
||||
it would redirect the user to the dashboard. */
|
||||
redirectUrl = this.urls.trackSelection + courseId + '/';
|
||||
} else if ( queryParams.courseMode === 'honor' || queryParams.courseMode === 'audit' ) {
|
||||
/* The newer version of the course details page allows the user
|
||||
to specify which course mode to enroll as. If the student has
|
||||
chosen "honor", we send them immediately to the dashboard
|
||||
rather than the payment flow. The user may decide to upgrade
|
||||
from the dashboard later. */
|
||||
redirectUrl = this.urls.dashboard;
|
||||
} else {
|
||||
/* If the user selected any other kind of course mode, send them
|
||||
to the payment/verification flow. */
|
||||
redirectUrl = this.urls.payment + courseId + '/';
|
||||
}
|
||||
|
||||
/* Attempt to auto-enroll the user in a free mode of the course,
|
||||
then redirect to the next location. */
|
||||
enrollment.enroll( courseId, redirectUrl );
|
||||
} else if ( queryParams.enrollmentAction === 'add_to_cart' && queryParams.courseId) {
|
||||
/*
|
||||
If this is a paid course, add it to the shopping cart and redirect
|
||||
@@ -298,6 +326,7 @@ var edx = edx || {};
|
||||
next: $.url( '?next' ),
|
||||
enrollmentAction: $.url( '?enrollment_action' ),
|
||||
courseId: $.url( '?course_id' ),
|
||||
courseMode: $.url( '?course_mode' ),
|
||||
emailOptIn: $.url( '?email_opt_in')
|
||||
};
|
||||
},
|
||||
|
||||
@@ -173,9 +173,13 @@
|
||||
</html>
|
||||
|
||||
<%def name="login_query()">${
|
||||
u"?course_id={0}&enrollment_action={1}{email_opt_in}".format(
|
||||
u"?course_id={0}&enrollment_action={1}{course_mode}{email_opt_in}".format(
|
||||
urlquote_plus(course_id),
|
||||
urlquote_plus(enrollment_action),
|
||||
course_mode=(
|
||||
u"&course_mode=" + urlquote_plus(course_mode)
|
||||
if course_mode else ""
|
||||
),
|
||||
email_opt_in=(
|
||||
u"&email_opt_in=" + urlquote_plus(email_opt_in)
|
||||
if email_opt_in else ""
|
||||
|
||||
Reference in New Issue
Block a user