Commit 2abd023a by Will Daly

Merge pull request #5895 from edx/will/logistration-include-course-in-analytics

Logistration: Include course ID in analytics events for login/registration
parents bb257b6f 95a435ab
......@@ -343,6 +343,20 @@ def shim_student_view(view_func, check_logged_in=False):
if "course_id" in request.POST:
del request.POST["course_id"]
# Include the course ID if it's specified in the analytics info
# so it can be included in analytics events.
if "analytics" in request.POST:
try:
analytics = json.loads(request.POST["analytics"])
if "enroll_course_id" in analytics:
request.POST["course_id"] = analytics.get("enroll_course_id")
except (ValueError, TypeError):
LOGGER.error(
u"Could not parse analytics object sent to user API: {analytics}".format(
analytics=analytics
)
)
# Backwards compatibility: the student view expects both
# terms of service and honor code values. Since we're combining
# these into a single checkbox, the only value we may get
......
......@@ -150,6 +150,17 @@ class StudentViewShimTest(TestCase):
self.assertNotIn("enrollment_action", self.captured_request.POST)
self.assertNotIn("course_id", self.captured_request.POST)
def test_include_analytics_info(self):
view = self._shimmed_view(HttpResponse())
request = HttpRequest()
request.POST["analytics"] = json.dumps({
"enroll_course_id": "edX/DemoX/Fall"
})
view(request)
# Expect that the analytics course ID was passed to the view
self.assertEqual(self.captured_request.POST.get("course_id"), "edX/DemoX/Fall")
def test_third_party_auth_login_failure(self):
view = self._shimmed_view(
HttpResponse(status=403),
......
......@@ -133,6 +133,13 @@ class LoginSessionView(APIView):
def post(self, request):
"""Log in a user.
You must send all required form fields with the request.
You can optionally send an `analytics` param with a JSON-encoded
object with additional info to include in the login analytics event.
Currently, the only supported field is "enroll_course_id" to indicate
that the user logged in while enrolling in a particular course.
Arguments:
request (HttpRequest)
......@@ -148,7 +155,7 @@ class LoginSessionView(APIView):
Example Usage:
POST /user_api/v1/login_session
with POST params `email` and `password`
with POST params `email`, `password`, and `remember`.
200 OK
......@@ -246,6 +253,13 @@ class RegistrationView(APIView):
def post(self, request):
"""Create the user's account.
You must send all required form fields with the request.
You can optionally send an `analytics` param with a JSON-encoded
object with additional info to include in the registration analytics event.
Currently, the only supported field is "enroll_course_id" to indicate
that the user registered while enrolling in a particular course.
Arguments:
request (HTTPRequest)
......
......@@ -6,208 +6,237 @@ define([
'js/student_account/models/LoginModel',
'js/student_account/views/LoginView'
], function($, _, TemplateHelpers, AjaxHelpers, LoginModel, LoginView) {
describe('edx.student.account.LoginView', function() {
'use strict';
var model = null,
view = null,
requests = null,
authComplete = false,
PLATFORM_NAME = 'edX',
USER_DATA = {
email: 'xsy@edx.org',
password: 'xsyisawesome',
remember: true
},
THIRD_PARTY_AUTH = {
currentProvider: null,
providers: [
{
name: 'Google',
iconClass: 'icon-google-plus',
loginUrl: '/auth/login/google-oauth2/?auth_entry=account_login',
registerUrl: '/auth/login/google-oauth2/?auth_entry=account_register'
},
{
name: 'Facebook',
iconClass: 'icon-facebook',
loginUrl: '/auth/login/facebook/?auth_entry=account_login',
registerUrl: '/auth/login/facebook/?auth_entry=account_register'
}
]
},
FORM_DESCRIPTION = {
method: 'post',
submit_url: '/user_api/v1/account/login_session/',
fields: [
{
name: 'email',
label: 'Email',
defaultValue: '',
type: 'email',
required: true,
placeholder: 'place@holder.org',
instructions: 'Enter your email.',
restrictions: {}
},
{
name: 'password',
label: 'Password',
defaultValue: '',
type: 'password',
required: true,
instructions: 'Enter your password.',
restrictions: {}
},
{
name: 'remember',
label: 'Remember me',
defaultValue: '',
type: 'checkbox',
required: true,
instructions: "Agree to the terms of service.",
restrictions: {}
}
]
};
var createLoginView = function(test) {
// Initialize the login model
model = new LoginModel({}, {
url: FORM_DESCRIPTION.submit_url,
method: FORM_DESCRIPTION.method
});
'use strict';
describe('edx.student.account.LoginView', function() {
var model = null,
view = null,
requests = null,
authComplete = false,
PLATFORM_NAME = 'edX',
USER_DATA = {
email: 'xsy@edx.org',
password: 'xsyisawesome',
remember: true
},
THIRD_PARTY_AUTH = {
currentProvider: null,
providers: [
{
name: 'Google',
iconClass: 'icon-google-plus',
loginUrl: '/auth/login/google-oauth2/?auth_entry=account_login',
registerUrl: '/auth/login/google-oauth2/?auth_entry=account_register'
},
{
name: 'Facebook',
iconClass: 'icon-facebook',
loginUrl: '/auth/login/facebook/?auth_entry=account_login',
registerUrl: '/auth/login/facebook/?auth_entry=account_register'
}
]
},
FORM_DESCRIPTION = {
method: 'post',
submit_url: '/user_api/v1/account/login_session/',
fields: [
{
name: 'email',
label: 'Email',
defaultValue: '',
type: 'email',
required: true,
placeholder: 'place@holder.org',
instructions: 'Enter your email.',
restrictions: {}
},
{
name: 'password',
label: 'Password',
defaultValue: '',
type: 'password',
required: true,
instructions: 'Enter your password.',
restrictions: {}
},
{
name: 'remember',
label: 'Remember me',
defaultValue: '',
type: 'checkbox',
required: true,
instructions: "Agree to the terms of service.",
restrictions: {}
}
]
},
COURSE_ID = "edX/demoX/Fall";
var createLoginView = function(test) {
// Initialize the login model
model = new LoginModel({}, {
url: FORM_DESCRIPTION.submit_url,
method: FORM_DESCRIPTION.method
});
// Initialize the login view
view = new LoginView({
fields: FORM_DESCRIPTION.fields,
model: model,
thirdPartyAuth: THIRD_PARTY_AUTH,
platformName: PLATFORM_NAME
});
// Initialize the login view
view = new LoginView({
fields: FORM_DESCRIPTION.fields,
model: model,
thirdPartyAuth: THIRD_PARTY_AUTH,
platformName: PLATFORM_NAME
});
// Spy on AJAX requests
requests = AjaxHelpers.requests(test);
// Spy on AJAX requests
requests = AjaxHelpers.requests(test);
// Intercept events from the view
authComplete = false;
view.on("auth-complete", function() {
authComplete = true;
// Intercept events from the view
authComplete = false;
view.on("auth-complete", function() {
authComplete = true;
});
};
var submitForm = function(validationSuccess) {
// Simulate manual entry of login form data
$('#login-email').val(USER_DATA.email);
$('#login-password').val(USER_DATA.password);
// Check the "Remember me" checkbox
$('#login-remember').prop('checked', USER_DATA.remember);
// Create a fake click event
var clickEvent = $.Event('click');
// If validationSuccess isn't passed, we avoid
// spying on `view.validate` twice
if ( !_.isUndefined(validationSuccess) ) {
// Force validation to return as expected
spyOn(view, 'validate').andReturn({
isValid: validationSuccess,
message: 'Submission was validated.'
});
};
var submitForm = function(validationSuccess) {
// Simulate manual entry of login form data
$('#login-email').val(USER_DATA.email);
$('#login-password').val(USER_DATA.password);
// Check the "Remember me" checkbox
$('#login-remember').prop('checked', USER_DATA.remember);
// Create a fake click event
var clickEvent = $.Event('click');
// If validationSuccess isn't passed, we avoid
// spying on `view.validate` twice
if ( !_.isUndefined(validationSuccess) ) {
// Force validation to return as expected
spyOn(view, 'validate').andReturn({
isValid: validationSuccess,
message: 'Submission was validated.'
});
}
}
// Submit the email address
view.submitForm(clickEvent);
};
// Submit the email address
view.submitForm(clickEvent);
};
beforeEach(function() {
setFixtures('<div id="login-form"></div>');
TemplateHelpers.installTemplate('templates/student_account/login');
TemplateHelpers.installTemplate('templates/student_account/form_field');
});
beforeEach(function() {
setFixtures('<div id="login-form"></div>');
TemplateHelpers.installTemplate('templates/student_account/login');
TemplateHelpers.installTemplate('templates/student_account/form_field');
});
it('logs the user in', function() {
createLoginView(this);
it('logs the user in', function() {
createLoginView(this);
// Submit the form, with successful validation
submitForm(true);
// Submit the form, with successful validation
submitForm(true);
// Verify that the client contacts the server with the expected data
AjaxHelpers.expectRequest(
requests, 'POST',
FORM_DESCRIPTION.submit_url,
$.param( USER_DATA )
);
// Verify that the client contacts the server with the expected data
AjaxHelpers.expectRequest(
requests, 'POST',
FORM_DESCRIPTION.submit_url,
$.param( USER_DATA )
);
// Respond with status code 200
AjaxHelpers.respondWithJson(requests, {});
// Respond with status code 200
AjaxHelpers.respondWithJson(requests, {});
// Verify that auth-complete is triggered
expect(authComplete).toBe(true);
});
// Verify that auth-complete is triggered
expect(authComplete).toBe(true);
});
it('displays third-party auth login buttons', function() {
createLoginView(this);
it('sends analytics info containing the enrolled course ID', function() {
createLoginView( this );
// Verify that Google and Facebook registration buttons are displayed
expect($('.button-Google')).toBeVisible();
expect($('.button-Facebook')).toBeVisible();
// Simulate that the user is attempting to enroll in a course
// by setting the course_id query string param.
spyOn($, 'url').andCallFake(function( param ) {
if (param === "?course_id") {
return encodeURIComponent( COURSE_ID );
}
});
it('displays a link to the password reset form', function() {
createLoginView(this);
// Attempt to login
submitForm( true );
// Verify that the password reset link is displayed
expect($('.forgot-password')).toBeVisible();
// Verify that the client sent the course ID for analytics
var expectedData = {};
$.extend(expectedData, USER_DATA, {
analytics: JSON.stringify({
enroll_course_id: COURSE_ID
})
});
it('validates login form fields', function() {
createLoginView(this);
AjaxHelpers.expectRequest(
requests, 'POST',
FORM_DESCRIPTION.submit_url,
$.param( expectedData )
);
});
it('displays third-party auth login buttons', function() {
createLoginView(this);
submitForm(true);
// Verify that Google and Facebook registration buttons are displayed
expect($('.button-Google')).toBeVisible();
expect($('.button-Facebook')).toBeVisible();
});
// Verify that validation of form fields occurred
expect(view.validate).toHaveBeenCalledWith($('#login-email')[0]);
expect(view.validate).toHaveBeenCalledWith($('#login-password')[0]);
});
it('displays a link to the password reset form', function() {
createLoginView(this);
it('displays login form validation errors', function() {
createLoginView(this);
// Verify that the password reset link is displayed
expect($('.forgot-password')).toBeVisible();
});
// Submit the form, with failed validation
submitForm(false);
it('validates login form fields', function() {
createLoginView(this);
// Verify that submission errors are visible
expect(view.$errors).not.toHaveClass('hidden');
submitForm(true);
// Expect auth complete NOT to have been triggered
expect(authComplete).toBe(false);
});
// Verify that validation of form fields occurred
expect(view.validate).toHaveBeenCalledWith($('#login-email')[0]);
expect(view.validate).toHaveBeenCalledWith($('#login-password')[0]);
});
it('displays an error if the server returns an error while logging in', function() {
createLoginView(this);
it('displays login form validation errors', function() {
createLoginView(this);
// Submit the form, with successful validation
submitForm(true);
// Submit the form, with failed validation
submitForm(false);
// Simulate an error from the LMS servers
AjaxHelpers.respondWithError(requests);
// Verify that submission errors are visible
expect(view.$errors).not.toHaveClass('hidden');
// Expect that an error is displayed and that auth complete is not triggered
expect(view.$errors).not.toHaveClass('hidden');
expect(authComplete).toBe(false);
// Expect auth complete NOT to have been triggered
expect(authComplete).toBe(false);
});
// If we try again and succeed, the error should go away
submitForm();
it('displays an error if the server returns an error while logging in', function() {
createLoginView(this);
// This time, respond with status code 200
AjaxHelpers.respondWithJson(requests, {});
// Submit the form, with successful validation
submitForm(true);
// Expect that the error is hidden and auth complete is triggered
expect(view.$errors).toHaveClass('hidden');
expect(authComplete).toBe(true);
});
// Simulate an error from the LMS servers
AjaxHelpers.respondWithError(requests);
// Expect that an error is displayed and that auth complete is not triggered
expect(view.$errors).not.toHaveClass('hidden');
expect(authComplete).toBe(false);
// If we try again and succeed, the error should go away
submitForm();
// This time, respond with status code 200
AjaxHelpers.respondWithJson(requests, {});
// Expect that the error is hidden and auth complete is triggered
expect(view.$errors).toHaveClass('hidden');
expect(authComplete).toBe(true);
});
}
);
});
});
......@@ -6,302 +6,332 @@ define([
'js/student_account/models/RegisterModel',
'js/student_account/views/RegisterView'
], function($, _, TemplateHelpers, AjaxHelpers, RegisterModel, RegisterView) {
describe('edx.student.account.RegisterView', function() {
'use strict';
var model = null,
view = null,
requests = null,
authComplete = false,
PLATFORM_NAME = 'edX',
USER_DATA = {
email: 'xsy@edx.org',
name: 'Xsy M. Education',
username: 'Xsy',
password: 'xsyisawesome',
level_of_education: 'p',
gender: 'm',
year_of_birth: 2014,
mailing_address: '141 Portland',
goals: 'To boldly learn what no letter of the alphabet has learned before',
honor_code: true
},
THIRD_PARTY_AUTH = {
currentProvider: null,
providers: [
{
name: 'Google',
iconClass: 'icon-google-plus',
loginUrl: '/auth/login/google-oauth2/?auth_entry=account_login',
registerUrl: '/auth/login/google-oauth2/?auth_entry=account_register'
},
{
name: 'Facebook',
iconClass: 'icon-facebook',
loginUrl: '/auth/login/facebook/?auth_entry=account_login',
registerUrl: '/auth/login/facebook/?auth_entry=account_register'
}
]
},
FORM_DESCRIPTION = {
method: 'post',
submit_url: '/user_api/v1/account/registration/',
fields: [
{
name: 'email',
label: 'Email',
defaultValue: '',
type: 'email',
required: true,
placeholder: 'place@holder.org',
instructions: 'Enter your email.',
restrictions: {}
},
{
name: 'name',
label: 'Full Name',
defaultValue: '',
type: 'text',
required: true,
instructions: 'Enter your username.',
restrictions: {}
},
{
name: 'username',
label: 'Username',
defaultValue: '',
type: 'text',
required: true,
instructions: 'Enter your username.',
restrictions: {}
},
{
name: 'password',
label: 'Password',
defaultValue: '',
type: 'password',
required: true,
instructions: 'Enter your password.',
restrictions: {}
},
{
name: 'level_of_education',
label: 'Highest Level of Education Completed',
defaultValue: '',
type: 'select',
options: [
{value: "", name: "--"},
{value: "p", name: "Doctorate"},
{value: "m", name: "Master's or professional degree"},
{value: "b", name: "Bachelor's degree"},
],
required: false,
instructions: 'Select your education level.',
restrictions: {}
},
{
name: 'gender',
label: 'Gender',
defaultValue: '',
type: 'select',
options: [
{value: "", name: "--"},
{value: "m", name: "Male"},
{value: "f", name: "Female"},
{value: "o", name: "Other"},
],
required: false,
instructions: 'Select your gender.',
restrictions: {}
},
{
name: 'year_of_birth',
label: 'Year of Birth',
defaultValue: '',
type: 'select',
options: [
{value: "", name: "--"},
{value: 1900, name: "1900"},
{value: 1950, name: "1950"},
{value: 2014, name: "2014"},
],
required: false,
instructions: 'Select your year of birth.',
restrictions: {}
},
{
name: 'mailing_address',
label: 'Mailing Address',
defaultValue: '',
type: 'textarea',
required: false,
instructions: 'Enter your mailing address.',
restrictions: {}
},
{
name: 'goals',
label: 'Goals',
defaultValue: '',
type: 'textarea',
required: false,
instructions: "If you'd like, tell us why you're interested in edX.",
restrictions: {}
},
{
name: 'honor_code',
label: 'I agree to the <a href="/honor">Terms of Service and Honor Code</a>',
defaultValue: '',
type: 'checkbox',
required: true,
instructions: '',
restrictions: {}
}
]
};
var createRegisterView = function(that) {
// Initialize the register model
model = new RegisterModel({}, {
url: FORM_DESCRIPTION.submit_url,
method: FORM_DESCRIPTION.method
});
'use strict';
describe('edx.student.account.RegisterView', function() {
var model = null,
view = null,
requests = null,
authComplete = false,
PLATFORM_NAME = 'edX',
COURSE_ID = "edX/DemoX/Fall",
USER_DATA = {
email: 'xsy@edx.org',
name: 'Xsy M. Education',
username: 'Xsy',
password: 'xsyisawesome',
level_of_education: 'p',
gender: 'm',
year_of_birth: 2014,
mailing_address: '141 Portland',
goals: 'To boldly learn what no letter of the alphabet has learned before',
honor_code: true
},
THIRD_PARTY_AUTH = {
currentProvider: null,
providers: [
{
name: 'Google',
iconClass: 'icon-google-plus',
loginUrl: '/auth/login/google-oauth2/?auth_entry=account_login',
registerUrl: '/auth/login/google-oauth2/?auth_entry=account_register'
},
{
name: 'Facebook',
iconClass: 'icon-facebook',
loginUrl: '/auth/login/facebook/?auth_entry=account_login',
registerUrl: '/auth/login/facebook/?auth_entry=account_register'
}
]
},
FORM_DESCRIPTION = {
method: 'post',
submit_url: '/user_api/v1/account/registration/',
fields: [
{
name: 'email',
label: 'Email',
defaultValue: '',
type: 'email',
required: true,
placeholder: 'place@holder.org',
instructions: 'Enter your email.',
restrictions: {}
},
{
name: 'name',
label: 'Full Name',
defaultValue: '',
type: 'text',
required: true,
instructions: 'Enter your username.',
restrictions: {}
},
{
name: 'username',
label: 'Username',
defaultValue: '',
type: 'text',
required: true,
instructions: 'Enter your username.',
restrictions: {}
},
{
name: 'password',
label: 'Password',
defaultValue: '',
type: 'password',
required: true,
instructions: 'Enter your password.',
restrictions: {}
},
{
name: 'level_of_education',
label: 'Highest Level of Education Completed',
defaultValue: '',
type: 'select',
options: [
{value: "", name: "--"},
{value: "p", name: "Doctorate"},
{value: "m", name: "Master's or professional degree"},
{value: "b", name: "Bachelor's degree"},
],
required: false,
instructions: 'Select your education level.',
restrictions: {}
},
{
name: 'gender',
label: 'Gender',
defaultValue: '',
type: 'select',
options: [
{value: "", name: "--"},
{value: "m", name: "Male"},
{value: "f", name: "Female"},
{value: "o", name: "Other"},
],
required: false,
instructions: 'Select your gender.',
restrictions: {}
},
{
name: 'year_of_birth',
label: 'Year of Birth',
defaultValue: '',
type: 'select',
options: [
{value: "", name: "--"},
{value: 1900, name: "1900"},
{value: 1950, name: "1950"},
{value: 2014, name: "2014"},
],
required: false,
instructions: 'Select your year of birth.',
restrictions: {}
},
{
name: 'mailing_address',
label: 'Mailing Address',
defaultValue: '',
type: 'textarea',
required: false,
instructions: 'Enter your mailing address.',
restrictions: {}
},
{
name: 'goals',
label: 'Goals',
defaultValue: '',
type: 'textarea',
required: false,
instructions: "If you'd like, tell us why you're interested in edX.",
restrictions: {}
},
{
name: 'honor_code',
label: 'I agree to the <a href="/honor">Terms of Service and Honor Code</a>',
defaultValue: '',
type: 'checkbox',
required: true,
instructions: '',
restrictions: {}
}
]
};
// Initialize the register view
view = new RegisterView({
fields: FORM_DESCRIPTION.fields,
model: model,
thirdPartyAuth: THIRD_PARTY_AUTH,
platformName: PLATFORM_NAME
});
var createRegisterView = function(that) {
// Initialize the register model
model = new RegisterModel({}, {
url: FORM_DESCRIPTION.submit_url,
method: FORM_DESCRIPTION.method
});
// Spy on AJAX requests
requests = AjaxHelpers.requests(that);
// Initialize the register view
view = new RegisterView({
fields: FORM_DESCRIPTION.fields,
model: model,
thirdPartyAuth: THIRD_PARTY_AUTH,
platformName: PLATFORM_NAME
});
// Spy on AJAX requests
requests = AjaxHelpers.requests(that);
// Intercept events from the view
authComplete = false;
view.on("auth-complete", function() {
authComplete = true;
// Intercept events from the view
authComplete = false;
view.on("auth-complete", function() {
authComplete = true;
});
};
var submitForm = function(validationSuccess) {
// Simulate manual entry of registration form data
$('#register-email').val(USER_DATA.email);
$('#register-name').val(USER_DATA.name);
$('#register-username').val(USER_DATA.username);
$('#register-password').val(USER_DATA.password);
$('#register-level_of_education').val(USER_DATA.level_of_education);
$('#register-gender').val(USER_DATA.gender);
$('#register-year_of_birth').val(USER_DATA.year_of_birth);
$('#register-mailing_address').val(USER_DATA.mailing_address);
$('#register-goals').val(USER_DATA.goals);
// Check the honor code checkbox
$('#register-honor_code').prop('checked', USER_DATA.honor_code);
// Create a fake click event
var clickEvent = $.Event('click');
// If validationSuccess isn't passed, we avoid
// spying on `view.validate` twice
if ( !_.isUndefined(validationSuccess) ) {
// Force validation to return as expected
spyOn(view, 'validate').andReturn({
isValid: validationSuccess,
message: 'Submission was validated.'
});
};
}
var submitForm = function(validationSuccess) {
// Simulate manual entry of registration form data
$('#register-email').val(USER_DATA.email);
$('#register-name').val(USER_DATA.name);
$('#register-username').val(USER_DATA.username);
$('#register-password').val(USER_DATA.password);
$('#register-level_of_education').val(USER_DATA.level_of_education);
$('#register-gender').val(USER_DATA.gender);
$('#register-year_of_birth').val(USER_DATA.year_of_birth);
$('#register-mailing_address').val(USER_DATA.mailing_address);
$('#register-goals').val(USER_DATA.goals);
// Check the honor code checkbox
$('#register-honor_code').prop('checked', USER_DATA.honor_code);
// Create a fake click event
var clickEvent = $.Event('click');
// If validationSuccess isn't passed, we avoid
// spying on `view.validate` twice
if ( !_.isUndefined(validationSuccess) ) {
// Force validation to return as expected
spyOn(view, 'validate').andReturn({
isValid: validationSuccess,
message: 'Submission was validated.'
});
}
// Submit the email address
view.submitForm(clickEvent);
};
// Submit the email address
view.submitForm(clickEvent);
};
beforeEach(function() {
setFixtures('<div id="register-form"></div>');
TemplateHelpers.installTemplate('templates/student_account/register');
TemplateHelpers.installTemplate('templates/student_account/form_field');
});
beforeEach(function() {
setFixtures('<div id="register-form"></div>');
TemplateHelpers.installTemplate('templates/student_account/register');
TemplateHelpers.installTemplate('templates/student_account/form_field');
});
it('registers a new user', function() {
createRegisterView(this);
it('registers a new user', function() {
createRegisterView(this);
// Submit the form, with successful validation
submitForm( true );
// Submit the form, with successful validation
submitForm(true);
// Verify that the client contacts the server with the expected data
AjaxHelpers.expectRequest(
requests, 'POST',
FORM_DESCRIPTION.submit_url,
$.param( USER_DATA )
);
// Verify that the client contacts the server with the expected data
AjaxHelpers.expectRequest(
requests, 'POST',
FORM_DESCRIPTION.submit_url,
$.param( USER_DATA )
);
// Respond with status code 200
AjaxHelpers.respondWithJson(requests, {});
// Respond with status code 200
AjaxHelpers.respondWithJson(requests, {});
// Verify that auth complete is triggered
expect(authComplete).toBe(true);
});
// Verify that auth complete is triggered
expect(authComplete).toBe(true);
it('sends analytics info containing the enrolled course ID', function() {
createRegisterView( this );
// Simulate that the user is attempting to enroll in a course
// by setting the course_id query string param.
spyOn($, 'url').andCallFake(function( param ) {
if (param === "?course_id") {
return encodeURIComponent( COURSE_ID );
}
});
it('displays third-party auth registration buttons', function() {
createRegisterView(this);
// Attempt to register
submitForm( true );
// Verify that Google and Facebook registration buttons are displayed
expect($('.button-Google')).toBeVisible();
expect($('.button-Facebook')).toBeVisible();
// Verify that the client sent the course ID for analytics
var expectedData = {};
$.extend(expectedData, USER_DATA, {
analytics: JSON.stringify({
enroll_course_id: COURSE_ID
})
});
it('validates registration form fields', function() {
createRegisterView(this);
AjaxHelpers.expectRequest(
requests, 'POST',
FORM_DESCRIPTION.submit_url,
$.param( expectedData )
);
});
it('displays third-party auth registration buttons', function() {
createRegisterView(this);
// Submit the form, with successful validation
submitForm(true);
// Verify that Google and Facebook registration buttons are displayed
expect($('.button-Google')).toBeVisible();
expect($('.button-Facebook')).toBeVisible();
});
// Verify that validation of form fields occurred
expect(view.validate).toHaveBeenCalledWith($('#register-email')[0]);
expect(view.validate).toHaveBeenCalledWith($('#register-name')[0]);
expect(view.validate).toHaveBeenCalledWith($('#register-username')[0]);
expect(view.validate).toHaveBeenCalledWith($('#register-password')[0]);
it('validates registration form fields', function() {
createRegisterView(this);
// Verify that no submission errors are visible
expect(view.$errors).toHaveClass('hidden');
});
// Submit the form, with successful validation
submitForm(true);
it('displays registration form validation errors', function() {
createRegisterView(this);
// Verify that validation of form fields occurred
expect(view.validate).toHaveBeenCalledWith($('#register-email')[0]);
expect(view.validate).toHaveBeenCalledWith($('#register-name')[0]);
expect(view.validate).toHaveBeenCalledWith($('#register-username')[0]);
expect(view.validate).toHaveBeenCalledWith($('#register-password')[0]);
// Submit the form, with failed validation
submitForm(false);
// Verify that no submission errors are visible
expect(view.$errors).toHaveClass('hidden');
});
// Verify that submission errors are visible
expect(view.$errors).not.toHaveClass('hidden');
it('displays registration form validation errors', function() {
createRegisterView(this);
// Expect that auth complete is NOT triggered
expect(authComplete).toBe(false);
});
// Submit the form, with failed validation
submitForm(false);
// Verify that submission errors are visible
expect(view.$errors).not.toHaveClass('hidden');
it('displays an error if the server returns an error while registering', function() {
createRegisterView(this);
// Expect that auth complete is NOT triggered
expect(authComplete).toBe(false);
});
// Submit the form, with successful validation
submitForm(true);
it('displays an error if the server returns an error while registering', function() {
createRegisterView(this);
// Simulate an error from the LMS servers
AjaxHelpers.respondWithError(requests);
// Submit the form, with successful validation
submitForm(true);
// Expect that an error is displayed and that auth complete is NOT triggered
expect(view.$errors).not.toHaveClass('hidden');
expect(authComplete).toBe(false);
// Simulate an error from the LMS servers
AjaxHelpers.respondWithError(requests);
// If we try again and succeed, the error should go away
submitForm();
// Expect that an error is displayed and that auth complete is NOT triggered
expect(view.$errors).not.toHaveClass('hidden');
expect(authComplete).toBe(false);
// This time, respond with status code 200
AjaxHelpers.respondWithJson(requests, {});
// If we try again and succeed, the error should go away
submitForm();
// Expect that the error is hidden and that auth complete is triggered
expect(view.$errors).toHaveClass('hidden');
expect(authComplete).toBe(true);
});
// This time, respond with status code 200
AjaxHelpers.respondWithJson(requests, {});
// Expect that the error is hidden and that auth complete is triggered
expect(view.$errors).toHaveClass('hidden');
expect(authComplete).toBe(true);
});
}
);
});
});
......@@ -24,14 +24,27 @@ var edx = edx || {};
},
sync: function(method, model) {
var headers = {
'X-CSRFToken': $.cookie('csrftoken')
};
var headers = { 'X-CSRFToken': $.cookie('csrftoken') },
data = {},
analytics,
courseId = $.url( '?course_id' );
// If there is a course ID in the query string param,
// send that to the server as well so it can be included
// in analytics events.
if ( courseId ) {
analytics = JSON.stringify({
enroll_course_id: decodeURIComponent( courseId )
});
}
// Include all form fields and analytics info in the data sent to the server
$.extend( data, model.attributes, { analytics: analytics });
$.ajax({
url: model.urlRoot,
type: model.ajaxType,
data: model.attributes,
data: data,
headers: headers,
success: function() {
model.trigger('sync');
......
......@@ -30,14 +30,27 @@ var edx = edx || {};
},
sync: function(method, model) {
var headers = {
'X-CSRFToken': $.cookie('csrftoken')
};
var headers = { 'X-CSRFToken': $.cookie('csrftoken') },
data = {},
analytics,
courseId = $.url( '?course_id' );
// If there is a course ID in the query string param,
// send that to the server as well so it can be included
// in analytics events.
if ( courseId ) {
analytics = JSON.stringify({
enroll_course_id: decodeURIComponent( courseId )
});
}
// Include all form fields and analytics info in the data sent to the server
$.extend( data, model.attributes, { analytics: analytics });
$.ajax({
url: model.urlRoot,
type: model.ajaxType,
data: model.attributes,
data: data,
headers: headers,
success: function() {
model.trigger('sync');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment