Commit a86c80bb by Renzo Lucioni

Merge pull request #5857 from edx/renzo/add-js-tests

Fix logistration Jasmine tests
parents d512fe86 f9ecd884
...@@ -728,10 +728,6 @@ class LoginSessionViewTest(ApiTestCase): ...@@ -728,10 +728,6 @@ class LoginSessionViewTest(ApiTestCase):
class PasswordResetViewTest(ApiTestCase): class PasswordResetViewTest(ApiTestCase):
"""Tests of the user API's password reset endpoint. """ """Tests of the user API's password reset endpoint. """
USERNAME = "bob"
EMAIL = "bob@example.com"
PASSWORD = "password"
def setUp(self): def setUp(self):
super(PasswordResetViewTest, self).setUp() super(PasswordResetViewTest, self).setUp()
self.url = reverse("user_api_password_reset") self.url = reverse("user_api_password_reset")
......
/*! url - v1.8.4 - 2013-08-14 */window.url=function(){function a(a){return!isNaN(parseFloat(a))&&isFinite(a)}return function(b,c){var d=c||window.location.toString();if(!b)return d;b=b.toString(),"//"===d.substring(0,2)?d="http:"+d:1===d.split("://").length&&(d="http://"+d),c=d.split("/");var e={auth:""},f=c[2].split("@");1===f.length?f=f[0].split(":"):(e.auth=f[0],f=f[1].split(":")),e.protocol=c[0],e.hostname=f[0],e.port=f[1]||"80",e.pathname=(c.length>3?"/":"")+c.slice(3,c.length).join("/").split("?")[0].split("#")[0];var g=e.pathname;"/"===g.charAt(g.length-1)&&(g=g.substring(0,g.length-1));var h=e.hostname,i=h.split("."),j=g.split("/");if("hostname"===b)return h;if("domain"===b)return i.slice(-2).join(".");if("sub"===b)return i.slice(0,i.length-2).join(".");if("port"===b)return e.port||"80";if("protocol"===b)return e.protocol.split(":")[0];if("auth"===b)return e.auth;if("user"===b)return e.auth.split(":")[0];if("pass"===b)return e.auth.split(":")[1]||"";if("path"===b)return e.pathname;if("."===b.charAt(0)){if(b=b.substring(1),a(b))return b=parseInt(b,10),i[0>b?i.length+b:b-1]||""}else{if(a(b))return b=parseInt(b,10),j[0>b?j.length+b:b]||"";if("file"===b)return j.slice(-1)[0];if("filename"===b)return j.slice(-1)[0].split(".")[0];if("fileext"===b)return j.slice(-1)[0].split(".")[1]||"";if("?"===b.charAt(0)||"#"===b.charAt(0)){var k=d,l=null;if("?"===b.charAt(0)?k=(k.split("?")[1]||"").split("#")[0]:"#"===b.charAt(0)&&(k=k.split("#")[1]||""),!b.charAt(1))return k;b=b.substring(1),k=k.split("&");for(var m=0,n=k.length;n>m;m++)if(l=k[m].split("="),l[0]===b)return l[1]||"";return null}}return""}}(),"undefined"!=typeof jQuery&&jQuery.extend({url:function(a,b){return window.url(a,b)}});
\ No newline at end of file
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill', 'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill',
'jquery.immediateDescendents': 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents', 'jquery.immediateDescendents': 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents',
'jquery.simulate': 'xmodule_js/common_static/js/vendor/jquery.simulate', 'jquery.simulate': 'xmodule_js/common_static/js/vendor/jquery.simulate',
'jquery.url': 'xmodule_js/common_static/js/vendor/url.min',
'datepair': 'xmodule_js/common_static/js/vendor/timepicker/datepair', 'datepair': 'xmodule_js/common_static/js/vendor/timepicker/datepair',
'date': 'xmodule_js/common_static/js/vendor/date', 'date': 'xmodule_js/common_static/js/vendor/date',
'underscore': 'xmodule_js/common_static/js/vendor/underscore-min', 'underscore': 'xmodule_js/common_static/js/vendor/underscore-min',
...@@ -43,7 +44,6 @@ ...@@ -43,7 +44,6 @@
'jasmine.async': 'xmodule_js/common_static/js/vendor/jasmine.async', 'jasmine.async': 'xmodule_js/common_static/js/vendor/jasmine.async',
'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly.pkgd', 'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly.pkgd',
'domReady': 'xmodule_js/common_static/js/vendor/domReady', 'domReady': 'xmodule_js/common_static/js/vendor/domReady',
'URI': 'xmodule_js/common_static/js/vendor/URI.min',
'mathjax': '//edx-static.s3.amazonaws.com/mathjax-MathJax-727332c/MathJax.js?config=TeX-MML-AM_HTMLorMML-full&delayStartupUntil=configured', 'mathjax': '//edx-static.s3.amazonaws.com/mathjax-MathJax-727332c/MathJax.js?config=TeX-MML-AM_HTMLorMML-full&delayStartupUntil=configured',
'youtube': '//www.youtube.com/player_api?noext', 'youtube': '//www.youtube.com/player_api?noext',
'tender': '//edxedge.tenderapp.com/tender_widget', 'tender': '//edxedge.tenderapp.com/tender_widget',
...@@ -65,7 +65,17 @@ ...@@ -65,7 +65,17 @@
'js/views/cohort_editor': 'js/views/cohort_editor', 'js/views/cohort_editor': 'js/views/cohort_editor',
'js/views/cohorts': 'js/views/cohorts', 'js/views/cohorts': 'js/views/cohorts',
'js/views/notification': 'js/views/notification', 'js/views/notification': 'js/views/notification',
'js/models/notification': 'js/models/notification' 'js/models/notification': 'js/models/notification',
'js/student_account/account': 'js/student_account/account',
'js/student_account/views/FormView': 'js/student_account/views/FormView',
'js/student_account/models/LoginModel': 'js/student_account/models/LoginModel',
'js/student_account/views/LoginView': 'js/student_account/views/LoginView',
'js/student_account/models/PasswordResetModel': 'js/student_account/models/PasswordResetModel',
'js/student_account/views/PasswordResetView': 'js/student_account/views/PasswordResetView',
'js/student_account/models/RegisterModel': 'js/student_account/models/RegisterModel',
'js/student_account/views/RegisterView': 'js/student_account/views/RegisterView',
'js/student_account/views/AccessView': 'js/student_account/views/AccessView',
'js/student_profile/profile': 'js/student_profile/profile'
}, },
shim: { shim: {
'gettext': { 'gettext': {
...@@ -133,11 +143,31 @@ ...@@ -133,11 +143,31 @@
deps: ['jquery', 'tinymce'], deps: ['jquery', 'tinymce'],
exports: 'jQuery.fn.tinymce' exports: 'jQuery.fn.tinymce'
}, },
'jquery.url': {
deps: ['jquery'],
exports: 'jQuery.fn.url'
},
'datepair': { 'datepair': {
deps: ['jquery.ui', 'jquery.timepicker'] deps: ['jquery.ui', 'jquery.timepicker']
}, },
'underscore': { 'underscore': {
exports: '_' deps: ['underscore.string'],
exports: '_',
init: function(UnderscoreString) {
/* Mix non-conflicting functions from underscore.string
* (all but include, contains, and reverse) into the
* Underscore namespace. This allows the login, register,
* and password reset templates to render independent of the
* access view.
*/
_.mixin(UnderscoreString.exports());
/* Since the access view is not using RequireJS, we also
* expose underscore.string at _.str, so that the access
* view can perform the mixin on its own.
*/
_.str = UnderscoreString;
}
}, },
'backbone': { 'backbone': {
deps: ['underscore', 'jquery'], deps: ['underscore', 'jquery'],
...@@ -216,7 +246,6 @@ ...@@ -216,7 +246,6 @@
exports: 'js/student_account/account', exports: 'js/student_account/account',
deps: ['jquery', 'underscore', 'backbone', 'gettext', 'jquery.cookie'] deps: ['jquery', 'underscore', 'backbone', 'gettext', 'jquery.cookie']
}, },
'js/student_profile/profile': { 'js/student_profile/profile': {
exports: 'js/student_profile/profile', exports: 'js/student_profile/profile',
deps: ['jquery', 'underscore', 'backbone', 'gettext', 'jquery.cookie'] deps: ['jquery', 'underscore', 'backbone', 'gettext', 'jquery.cookie']
...@@ -261,60 +290,76 @@ ...@@ -261,60 +290,76 @@
deps: ['backbone', 'jquery', 'underscore'] deps: ['backbone', 'jquery', 'underscore']
}, },
'js/student_account/enrollment_interface': { 'js/student_account/enrollment_interface': {
exports: 'js/student_account/enrollment_interface', exports: 'edx.student.account.EnrollmentInterface',
deps: ['jquery', 'underscore', 'gettext'] deps: ['jquery', 'jquery.cookie', 'underscore', 'gettext']
}, },
// Student account registration/login // Student account registration/login
// Loaded explicitly until these are converted to RequireJS // Loaded explicitly until these are converted to RequireJS
'js/student_account/views/FormView': { 'js/student_account/views/FormView': {
exports: 'js/student_account/views/FormView', exports: 'edx.student.account.FormView',
deps: ['jquery', 'underscore', 'backbone', 'gettext'] deps: ['jquery', 'underscore', 'backbone', 'gettext']
}, },
'js/student_account/models/LoginModel': { 'js/student_account/models/LoginModel': {
exports: 'js/student_account/models/LoginModel', exports: 'edx.student.account.LoginModel',
deps: ['jquery', 'underscore', 'backbone', 'gettext', 'jquery.cookie'] deps: ['jquery', 'jquery.cookie', 'backbone']
}, },
'js/student_account/views/LoginView': { 'js/student_account/views/LoginView': {
exports: 'js/student_account/views/LoginView', exports: 'edx.student.account.LoginView',
deps: [ deps: [
'jquery',
'jquery.url',
'underscore',
'gettext',
'js/student_account/models/LoginModel', 'js/student_account/models/LoginModel',
'js/student_account/views/FormView', 'js/student_account/views/FormView'
'underscore.string'
] ]
}, },
'js/student_account/models/PasswordResetModel': { 'js/student_account/models/PasswordResetModel': {
exports: 'js/student_account/models/PasswordResetModel', exports: 'edx.student.account.PasswordResetModel',
deps: ['jquery', 'underscore', 'backbone', 'gettext', 'jquery.cookie'] deps: ['jquery', 'jquery.cookie', 'backbone']
}, },
'js/student_account/views/PasswordResetView': { 'js/student_account/views/PasswordResetView': {
exports: 'js/student_account/views/PasswordResetView', exports: 'edx.student.account.PasswordResetView',
deps: [ deps: [
'jquery',
'underscore',
'gettext',
'js/student_account/models/PasswordResetModel', 'js/student_account/models/PasswordResetModel',
'js/student_account/views/FormView' 'js/student_account/views/FormView'
] ]
}, },
'js/student_account/models/RegisterModel': { 'js/student_account/models/RegisterModel': {
exports: 'js/student_account/models/RegisterModel', exports: 'edx.student.account.RegisterModel',
deps: ['jquery', 'underscore', 'backbone', 'gettext', 'jquery.cookie'] deps: ['jquery', 'jquery.cookie', 'backbone']
}, },
'js/student_account/views/RegisterView': { 'js/student_account/views/RegisterView': {
exports: 'js/student_account/views/RegisterView', exports: 'edx.student.account.RegisterView',
deps: [ deps: [
'jquery',
'jquery.url',
'underscore',
'gettext',
'js/student_account/models/RegisterModel', 'js/student_account/models/RegisterModel',
'js/student_account/views/FormView', 'js/student_account/views/FormView'
'underscore.string'
] ]
}, },
'js/student_account/views/AccessView': { 'js/student_account/views/AccessView': {
exports: 'js/student_account/views/AccessView', exports: 'edx.student.account.AccessView',
deps: [ deps: [
'jquery',
'underscore',
'backbone',
'gettext',
'js/student_account/views/LoginView', 'js/student_account/views/LoginView',
'js/student_account/views/PasswordResetView', 'js/student_account/views/PasswordResetView',
'js/student_account/views/RegisterView', 'js/student_account/views/RegisterView',
'underscore.string' 'js/student_account/models/LoginModel',
'js/student_account/models/PasswordResetModel',
'js/student_account/models/RegisterModel',
'js/student_account/views/FormView'
] ]
} }
}, }
}); });
// TODO: why do these need 'lms/include' at the front but the CMS equivalent logic doesn't? // TODO: why do these need 'lms/include' at the front but the CMS equivalent logic doesn't?
...@@ -325,13 +370,13 @@ ...@@ -325,13 +370,13 @@
'lms/include/js/spec/staff_debug_actions_spec.js', 'lms/include/js/spec/staff_debug_actions_spec.js',
'lms/include/js/spec/views/notification_spec.js', 'lms/include/js/spec/views/notification_spec.js',
'lms/include/js/spec/dashboard/donation.js', 'lms/include/js/spec/dashboard/donation.js',
'lms/include/js/spec/student_account/account.js', 'lms/include/js/spec/student_account/account_spec.js',
'lms/include/js/spec/student_account/access_spec.js', 'lms/include/js/spec/student_account/access_spec.js',
'lms/include/js/spec/student_account/login_spec.js', 'lms/include/js/spec/student_account/login_spec.js',
'lms/include/js/spec/student_account/register_spec.js', 'lms/include/js/spec/student_account/register_spec.js',
'lms/include/js/spec/student_account/password_reset_spec.js', 'lms/include/js/spec/student_account/password_reset_spec.js',
'lms/include/js/spec/student_account/enrollment_interface_spec.js', 'lms/include/js/spec/student_account/enrollment_interface_spec.js',
'lms/include/js/spec/student_profile/profile.js', 'lms/include/js/spec/student_profile/profile_spec.js'
]); ]);
}).call(this, requirejs, define); }).call(this, requirejs, define);
define(['js/common_helpers/template_helpers', 'js/student_account/views/AccessView'], define([
function(TemplateHelpers, AccessView) { 'jquery',
'js/common_helpers/template_helpers',
'js/common_helpers/ajax_helpers',
'js/student_account/views/AccessView',
'js/student_account/views/FormView'
], function($, TemplateHelpers, AjaxHelpers, AccessView) {
describe('edx.student.account.AccessView', function() { describe('edx.student.account.AccessView', function() {
'use strict'; 'use strict';
var view = null, var requests = null,
ajaxSuccess = true; view = null,
AJAX_INFO = {
var assertForms = function(visible, hidden) { register: {
expect($(visible)).not.toHaveClass('hidden'); url: '/user_api/v1/account/registration/',
expect($(hidden)).toHaveClass('hidden'); requestIndex: 1
expect($('#password-reset-wrapper')).toBeEmpty(); },
}; login: {
url: '/user_api/v1/account/login_session/',
beforeEach(function() { requestIndex: 0
setFixtures("<div id='login-and-registration-container'></div>"); },
TemplateHelpers.installTemplate('templates/student_account/access'); password_reset: {
TemplateHelpers.installTemplate('templates/student_account/login'); url: '/user_api/v1/account/password_reset/',
TemplateHelpers.installTemplate('templates/student_account/register'); requestIndex: 1
TemplateHelpers.installTemplate('templates/student_account/password_reset'); }
TemplateHelpers.installTemplate('templates/student_account/form_field'); },
FORM_DESCRIPTION = {
// Used to populate forms method: 'post',
var form_description = { submit_url: '/submit',
"method": "post", fields: [
"submit_url": "/submit",
"fields": [
{ {
"name": "email", name: 'email',
"label": "Email", label: 'Email',
"default": "", defaultValue: '',
"type": "text", type: 'text',
"required": true, required: true,
"placeholder": "xsy@edx.org", placeholder: 'xsy@edx.org',
"instructions": "Enter your email here.", instructions: 'Enter your email here.',
"restrictions": {}, restrictions: {},
}, },
{ {
"name": "username", name: 'username',
"label": "Username", label: 'Username',
"default": "", defaultValue: '',
"type": "text", type: 'text',
"required": true, required: true,
"placeholder": "Xsy", placeholder: 'Xsy',
"instructions": "Enter your username here.", instructions: 'Enter your username here.',
"restrictions": { restrictions: {
"max_length": 200 max_length: 200
} }
} }
] ]
}; };
// Stub AJAX calls and force them to return a form description var ajaxAssertAndRespond = function(url, requestIndex) {
spyOn($, 'ajax').andCallFake(function() { // Verify that the client contacts the server as expected
return $.Deferred(function(defer) { AjaxHelpers.expectJsonRequest(requests, 'GET', url, null, requestIndex);
if (ajaxSuccess) {
defer.resolveWith(this, [form_description]); /* Simulate a response from the server containing
} else { /* a dummy form description
defer.reject(); */
} AjaxHelpers.respondWithJson(requests, FORM_DESCRIPTION);
}).promise(); };
});
var ajaxSpyAndInitialize = function(that, mode) {
// Spy on AJAX requests
requests = AjaxHelpers.requests(that);
view = new edx.student.account.AccessView({ // Initialize the access view
mode: 'login', view = new AccessView({
mode: mode,
thirdPartyAuth: { thirdPartyAuth: {
currentProvider: null, currentProvider: null,
providers: [] providers: []
} },
platformName: 'edX'
}); });
ajaxAssertAndRespond(AJAX_INFO[mode].url);
};
var assertForms = function(visibleType, hiddenType) {
expect($(visibleType)).not.toHaveClass('hidden');
expect($(hiddenType)).toHaveClass('hidden');
expect($('#password-reset-wrapper')).toBeEmpty();
};
var selectForm = function(type) {
// Create a fake change event to control form toggling
var changeEvent = $.Event('change');
changeEvent.currentTarget = $('#' + type + '-option');
// Load form corresponding to the change event
view.toggleForm(changeEvent);
ajaxAssertAndRespond(AJAX_INFO[type].url, AJAX_INFO[type].requestIndex);
};
beforeEach(function() {
setFixtures('<div id="login-and-registration-container"></div>');
TemplateHelpers.installTemplate('templates/student_account/access');
TemplateHelpers.installTemplate('templates/student_account/login');
TemplateHelpers.installTemplate('templates/student_account/register');
TemplateHelpers.installTemplate('templates/student_account/password_reset');
TemplateHelpers.installTemplate('templates/student_account/form_field');
});
it('can initially display the login form', function() {
ajaxSpyAndInitialize(this, 'login');
/* Verify that the login form is expanded, and that the
/* registration form is collapsed.
*/
assertForms('#login-form', '#register-form');
}); });
it("initially displays the correct form", function() { it('can initially display the registration form', function() {
assertForms($('#login-form'), $('#register-form')); ajaxSpyAndInitialize(this, 'register');
/* Verify that the registration form is expanded, and that the
/* login form is collapsed.
*/
assertForms('#register-form', '#login-form');
}); });
it("toggles between the login and registration forms", function() { it('toggles between the login and registration forms', function() {
var registerChangeEvent = $.Event('change', {currentTarget: $('#register-option')}), ajaxSpyAndInitialize(this, 'login');
loginChangeEvent = $.Event('change', {currentTarget: $('#login-option')});
// Simulate selection of the registration form // Simulate selection of the registration form
view.toggleForm(registerChangeEvent) selectForm('register');
assertForms($('#register-form'), $('#login-form')); assertForms('#register-form', '#login-form');
// Simulate selection of the login form // Simulate selection of the login form
view.toggleForm(loginChangeEvent) selectForm('login');
assertForms($('#login-form'), $('#register-form')); assertForms('#login-form', '#register-form');
}); });
it("displays the reset password form", function() { it('displays the reset password form', function() {
ajaxSpyAndInitialize(this, 'login');
// Simulate a click on the reset password link
view.resetPassword(); view.resetPassword();
ajaxAssertAndRespond(
AJAX_INFO['password_reset'].url,
AJAX_INFO['password_reset'].requestIndex
);
// Verify that the password reset wrapper is populated
expect($('#password-reset-wrapper')).not.toBeEmpty(); expect($('#password-reset-wrapper')).not.toBeEmpty();
}); });
it('displays an error if a form definition could not be loaded', function() {
/* TODO: Not yet implemeted in the access view; currently, it only
* logs to the console.
*/
});
}); });
} }
); );
define(['js/common_helpers/template_helpers', 'js/student_account/enrollment_interface'], define(['js/student_account/enrollment_interface'],
function(TemplateHelpers, EnrollmentInterface) { function(EnrollmentInterface) {
describe("edx.student.account.EnrollmentInterface", function() { describe("edx.student.account.EnrollmentInterface", function() {
'use strict'; 'use strict';
it("find course modes using modeInArray ", function() { it('checks if a given course mode slug exists in an array of mode objects', function() {
var course_modes = [ var courseModes = [ { slug: 'honor' }, { slug: 'professional' } ]
{
slug: 'honor'
},
{
slug: 'professional'
}
],
expect(EnrollmentInterface.modeInArray('professional')).toBe(true);
expect(EnrollmentInterface.modeInArray('audit')).toBe(false);
expect( EnrollmentInterface.modeInArray( courseModes, 'professional' ) ).toBe(true);
expect( EnrollmentInterface.modeInArray( courseModes, 'audit' ) ).toBe(false);
}); });
}); });
} }
......
define(['js/common_helpers/template_helpers', 'js/student_account/views/LoginView'], define([
function(TemplateHelpers) { 'jquery',
describe("edx.student.account.LoginView", function() { 'underscore',
'js/common_helpers/template_helpers',
'js/common_helpers/ajax_helpers',
'js/student_account/models/LoginModel',
'js/student_account/views/LoginView'
], function($, _, TemplateHelpers, AjaxHelpers, LoginModel, LoginView) {
describe('edx.student.account.LoginView', function() {
'use strict'; 'use strict';
beforeEach(function() { var model = null,
setFixtures("<div></div>"); view = null,
TemplateHelpers.installTemplate("templates/student_account/login"); requests = null,
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 });
// Initialize the login view
view = new LoginView({
fields: FORM_DESCRIPTION.fields,
model: model,
thirdPartyAuth: THIRD_PARTY_AUTH,
platformName: PLATFORM_NAME
}); });
it("logs the user in", function() { // Spy on AJAX requests
// TODO requests = AjaxHelpers.requests(test);
// Mock out redirection logic
spyOn(view, 'redirect').andCallFake(function() {
return true;
}); });
};
var submitForm = function(validationSuccess) {
// Simulate manual entry of login form data
$('#login-email').val(USER_DATA.email);
$('#login-password').val(USER_DATA.password);
it("displays third party auth login buttons", function() { // Check the "Remember me" checkbox
// TODO $('#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);
};
it("validates the email field", function() { beforeEach(function() {
// TODO setFixtures('<div id="login-form"></div>');
TemplateHelpers.installTemplate('templates/student_account/login');
TemplateHelpers.installTemplate('templates/student_account/form_field');
}); });
it("validates the password field", function() { it('logs the user in', function() {
// TODO createLoginView(this);
// 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(
$.extend({url: FORM_DESCRIPTION.submit_url}, USER_DATA)
)
);
// Respond with status code 200
AjaxHelpers.respondWithJson(requests, {});
// Verify that the user is redirected to the dashboard
expect(view.redirect).toHaveBeenCalledWith('/dashboard');
}); });
it("displays login errors", function() { it('displays third-party auth login buttons', function() {
// TODO createLoginView(this);
// Verify that Google and Facebook registration buttons are displayed
expect($('.button-Google')).toBeVisible();
expect($('.button-Facebook')).toBeVisible();
}); });
it("displays an error if the form definition could not be loaded", function() { it('displays a link to the password reset form', function() {
// TODO createLoginView(this);
// Verify that the password reset link is displayed
expect($('.forgot-password')).toBeVisible();
}); });
it("displays an error if the server could not be contacted while logging in", function() { it('validates login form fields', function() {
// TODO createLoginView(this);
submitForm(true);
// Verify that validation of form fields occurred
expect(view.validate).toHaveBeenCalledWith($('#login-email')[0]);
expect(view.validate).toHaveBeenCalledWith($('#login-password')[0]);
}); });
it("allows the user to navigate to the password assistance form", function() { it('displays login form validation errors', function() {
// TODO createLoginView(this);
// Submit the form, with failed validation
submitForm(false);
// Verify that submission errors are visible
expect(view.$errors).not.toHaveClass('hidden');
}); });
it("enrolls the student into the right location and forwards them properly", function() { it('displays an error if the server returns an error while logging in', function() {
// TODO createLoginView(this);
// Submit the form, with successful validation
submitForm(true);
// Simulate an error from the LMS servers
AjaxHelpers.respondWithError(requests);
// Expect that an error is displayed, and that we haven't been redirected
expect(view.$errors).not.toHaveClass('hidden');
expect(view.redirect).not.toHaveBeenCalled();
// 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
expect(view.$errors).toHaveClass('hidden');
}); });
}); });
} }
......
define(['js/common_helpers/template_helpers', 'js/student_account/views/PasswordResetView'], define([
function(TemplateHelpers) { 'jquery',
'underscore',
'js/common_helpers/template_helpers',
'js/common_helpers/ajax_helpers',
'js/student_account/models/PasswordResetModel',
'js/student_account/views/PasswordResetView',
], function($, _, TemplateHelpers, AjaxHelpers, PasswordResetModel, PasswordResetView) {
describe('edx.student.account.PasswordResetView', function() { describe('edx.student.account.PasswordResetView', function() {
'use strict'; 'use strict';
var view = null, var model = null,
ajaxSuccess = true, view = null,
model = new edx.student.account.PasswordResetModel(), requests = null,
data = [{ EMAIL = 'xsy@edx.org',
label: 'E-mail', FORM_DESCRIPTION = {
instructions: 'This is the e-mail address you used to register with edX', method: 'post',
submit_url: '/account/password',
fields: [{
name: 'email', name: 'email',
label: 'Email',
defaultValue: '',
type: 'text',
required: true, required: true,
type: 'email', placeholder: 'place@holder.org',
restrictions: [], instructions: 'Enter your email.',
defaultValue: '' restrictions: {}
}]; }]
};
var createPasswordResetView = function(that) {
// Initialize the password reset model
model = new PasswordResetModel({ url: FORM_DESCRIPTION.submit_url });
// Initialize the password reset view
view = new PasswordResetView({
fields: FORM_DESCRIPTION.fields,
model: model
});
// Spy on AJAX requests
requests = AjaxHelpers.requests(that);
};
var submitEmail = function(validationSuccess) { var submitEmail = function(validationSuccess) {
// Simulate manual entry of an email address // Simulate manual entry of an email address
$('#password-reset-email').val('foo@bar.baz'); $('#password-reset-email').val(EMAIL);
// Create a fake click event // Create a fake click event
var clickEvent = $.Event('click'); var clickEvent = $.Event('click');
// Used to avoid spying on view.validate twice // If validationSuccess isn't passed, we avoid
if (typeof validationSuccess !== 'undefined') { // spying on `view.validate` twice
if ( !_.isUndefined(validationSuccess) ) {
// Force validation to return as expected // Force validation to return as expected
spyOn(view, 'validate').andReturn({ spyOn(view, 'validate').andReturn({
isValid: validationSuccess, isValid: validationSuccess,
message: "We're all good." message: 'Submission was validated.'
}); });
} }
...@@ -36,65 +63,74 @@ define(['js/common_helpers/template_helpers', 'js/student_account/views/Password ...@@ -36,65 +63,74 @@ define(['js/common_helpers/template_helpers', 'js/student_account/views/Password
view.submitForm(clickEvent); view.submitForm(clickEvent);
}; };
var assertAjax = function(url, method, data) {
expect($.ajax).toHaveBeenCalled();
var ajaxArgs = $.ajax.mostRecentCall.args[0];
expect(ajaxArgs.url).toEqual(url);
expect(ajaxArgs.type).toEqual(method);
expect(ajaxArgs.data).toEqual(data)
expect(ajaxArgs.headers.hasOwnProperty("X-CSRFToken")).toBe(true);
};
beforeEach(function() { beforeEach(function() {
setFixtures("<div id='password-reset-wrapper'></div>"); setFixtures('<div id="password-reset-wrapper"></div>');
TemplateHelpers.installTemplate('templates/student_account/password_reset'); TemplateHelpers.installTemplate('templates/student_account/password_reset');
TemplateHelpers.installTemplate('templates/student_account/form_field'); TemplateHelpers.installTemplate('templates/student_account/form_field');
// Stub AJAX calls
spyOn($, 'ajax').andCallFake(function() {
return $.Deferred(function(defer) {
if (ajaxSuccess) {
defer.resolve();
} else {
defer.rejectWith(this, ["The server could not be contacted."]);
}
}).promise();
}); });
view = new edx.student.account.PasswordResetView({ it('allows the user to request a new password', function() {
fields: data, createPasswordResetView(this);
model: model
});
});
it("allows the user to request a new password", function() { // Submit the form, with successful validation
submitEmail(true); submitEmail(true);
assertAjax('/account/password', 'POST', {email: 'foo@bar.baz'});
// Verify that the client contacts the server with the expected data
AjaxHelpers.expectRequest(
requests, 'POST', FORM_DESCRIPTION.submit_url, $.param({
url: FORM_DESCRIPTION.submit_url,
email: EMAIL
})
);
// Respond with status code 200
AjaxHelpers.respondWithJson(requests, {});
// Verify that the success message is visible
expect($('.js-reset-success')).not.toHaveClass('hidden'); expect($('.js-reset-success')).not.toHaveClass('hidden');
}); });
it("validates the email field", function() { it('validates the email field', function() {
createPasswordResetView(this);
// Submit the form, with successful validation
submitEmail(true); submitEmail(true);
expect(view.validate).toHaveBeenCalled()
// Verify that validation of the email field occurred
expect(view.validate).toHaveBeenCalledWith($('#password-reset-email')[0]);
// Verify that no submission errors are visible
expect(view.$errors).toHaveClass('hidden'); expect(view.$errors).toHaveClass('hidden');
}); });
it("displays password reset validation errors", function() { it('displays password reset validation errors', function() {
createPasswordResetView(this);
// Submit the form, with failed validation
submitEmail(false); submitEmail(false);
// Verify that submission errors are visible
expect(view.$errors).not.toHaveClass('hidden'); expect(view.$errors).not.toHaveClass('hidden');
}); });
it("displays an error if the server could not be contacted", function() { it('displays an error if the server returns an error while sending a password reset email', function() {
// If we get an error status on the AJAX request, display an error createPasswordResetView(this);
ajaxSuccess = false;
submitEmail(true); submitEmail(true);
expect(view.$'#submission-error').not.toHaveClass('hidden');
// Simulate an error from the LMS servers
AjaxHelpers.respondWithError(requests);
// Expect that an error is displayed
expect(view.$errors).not.toHaveClass('hidden');
// If we try again and succeed, the error should go away // If we try again and succeed, the error should go away
ajaxSuccess = true;
// No argument means we won't spy on view.validate again
submitEmail(); submitEmail();
expect(view.$'#submission-error').toHaveClass('hidden');
// This time, respond with status code 200
AjaxHelpers.respondWithJson(requests, {});
// Expect that the error is hidden
expect(view.$errors).toHaveClass('hidden');
}); });
}); });
} }
......
define(['js/common_helpers/template_helpers', 'js/student_account/views/RegisterView'], define([
function(TemplateHelpers) { 'jquery',
describe("edx.student.account.RegisterView", function() { 'underscore',
'js/common_helpers/template_helpers',
'js/common_helpers/ajax_helpers',
'js/student_account/models/RegisterModel',
'js/student_account/views/RegisterView'
], function($, _, TemplateHelpers, AjaxHelpers, RegisterModel, RegisterView) {
describe('edx.student.account.RegisterView', function() {
'use strict'; 'use strict';
beforeEach(function() { var model = null,
setFixtures("<div></div>"); view = null,
TemplateHelpers.installTemplate("templates/student_account/register"); requests = null,
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',
terms_of_service: 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: 'terms_of_service',
label: 'Terms of Service',
defaultValue: '',
type: 'checkbox',
required: true,
instructions: "Agree to the terms of service.",
restrictions: {}
}
]
};
var createRegisterView = function(that) {
// Initialize the register model
model = new RegisterModel({ url: FORM_DESCRIPTION.submit_url });
// 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);
// Mock out redirection logic
spyOn(view, 'redirect').andCallFake(function() {
return true;
}); });
};
it("registers a new user", function() { var submitForm = function(validationSuccess) {
// TODO // 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 terms of service checkbox
$('#register-terms_of_service').prop('checked', USER_DATA.terms_of_service);
// 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);
};
beforeEach(function() {
setFixtures('<div id="register-form"></div>');
TemplateHelpers.installTemplate('templates/student_account/register');
TemplateHelpers.installTemplate('templates/student_account/form_field');
}); });
it("displays third party auth registration buttons", function() { it('registers a new user', function() {
// TODO createRegisterView(this);
// 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(
$.extend({url: FORM_DESCRIPTION.submit_url}, USER_DATA)
)
);
// Respond with status code 200
AjaxHelpers.respondWithJson(requests, {});
// Verify that the user is redirected to the dashboard
expect(view.redirect).toHaveBeenCalledWith('/dashboard');
}); });
it("validates form fields", function() { it('displays third-party auth registration buttons', function() {
// TODO createRegisterView(this);
// Verify that Google and Facebook registration buttons are displayed
expect($('.button-Google')).toBeVisible();
expect($('.button-Facebook')).toBeVisible();
}); });
it("displays registration errors", function() { it('validates registration form fields', function() {
// TODO createRegisterView(this);
// Submit the form, with successful validation
submitForm(true);
// 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]);
// Verify that no submission errors are visible
expect(view.$errors).toHaveClass('hidden');
}); });
it("displays an error if the form definition could not be loaded", function() { it('displays registration form validation errors', function() {
// TODO createRegisterView(this);
// 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 could not be contacted while registering", function() { it('displays an error if the server returns an error while registering', function() {
// TODO createRegisterView(this);
// Submit the form, with successful validation
submitForm(true);
// Simulate an error from the LMS servers
AjaxHelpers.respondWithError(requests);
// Expect that an error is displayed
expect(view.$errors).not.toHaveClass('hidden');
// 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
expect(view.$errors).toHaveClass('hidden');
}); });
}); });
} }
......
...@@ -4,7 +4,7 @@ var edx = edx || {}; ...@@ -4,7 +4,7 @@ var edx = edx || {};
'use strict'; 'use strict';
edx.student = edx.student || {}; edx.student = edx.student || {};
edx.student.account = {}; edx.student.account = edx.student.account || {};
edx.student.account.AccountModel = Backbone.Model.extend({ edx.student.account.AccountModel = Backbone.Model.extend({
// These should be the same length limits enforced by the server // These should be the same length limits enforced by the server
......
...@@ -8,71 +8,80 @@ var edx = edx || {}; ...@@ -8,71 +8,80 @@ var edx = edx || {};
edx.student.account.EnrollmentInterface = { edx.student.account.EnrollmentInterface = {
courseUrl: '/enrollment/v0/course/', courseUrl: '/enrollment/v0/course/',
studentUrl: '/enrollment/v0/student', studentUrl: '/enrollment/v0/student',
trackSelectionUrl: '/course_modes/choose/', trackSelectionUrl: '/course_modes/choose/',
headers: { headers: {
'X-CSRFToken': $.cookie('csrftoken') 'X-CSRFToken': $.cookie('csrftoken')
}, },
studentInformation: function(course_key) { studentInformation: function(courseKey) {
// retrieve student enrollment information // retrieve student enrollment information
}, },
courseInformation: function(course_key) { courseInformation: function(courseKey) {
// retrieve course information from the enrollment API // retrieve course information from the enrollment API
}, },
modeInArray: function(mode_slug, course_modes) { modeInArray: function(modeObjects, targetMode) {
// finds whether or not a particular course mode slug exists // Check if a given course mode slug exists in an array of mode objects
// in an array of course modes var result = _.find(modeObjects, function(mode) {
var result = _.find(course_modes, function(mode){ return mode.slug === mode_slug; }); return mode.slug === targetMode;
return result != undefined; });
/* _.find returns the first value which passes the provided truth test,
/* or undefined if no values pass the test
*/
return !_.isUndefined(result);
}, },
enroll: function(course_key, forward_url){ enroll: function(courseKey, forwardUrl){
var me = this; var me = this;
// attempt to enroll a student in a course // attempt to enroll a student in a course
$.ajax({ $.ajax({
url: this.courseUrl + course_key, url: this.courseUrl + courseKey,
type: 'POST', type: 'POST',
data: {}, data: {},
headers: this.headers headers: this.headers
}).done(function(data){ }).done(function(data){
me.postEnrollmentHandler(course_key, data, forward_url); me.postEnrollmentHandler(courseKey, data, forwardUrl);
} }
).fail(function(data, textStatus) { ).fail(function(data, textStatus) {
me.enrollmentFailureHandler(course_key, data, forward_url); me.enrollmentFailureHandler(courseKey, data, forwardUrl);
}); });
}, },
enrollmentFailureHandler: function(course_key, data, forward_url) { enrollmentFailureHandler: function(courseKey, data, forwardUrl) {
// handle failures to enroll via the API // handle failures to enroll via the API
if(data.status == 400) { if(data.status == 400) {
// This status code probably means we don't have permissions to register for this course. /* This status code probably means we don't have permissions to register
// look at the contents of the response /* for this course; look at the contents of the response
*/
var course = $.parseJSON(data.responseText); var course = $.parseJSON(data.responseText);
// see if it's a professional ed course // see if it's a professional ed course
if('course_modes' in course && this.modeInArray('professional', course.course_modes)) { if( 'course_modes' in course && this.modeInArray(course.course_modes, 'professional') ) {
// forward appropriately // forward appropriately
forward_url = this.trackSelectionUrl + course_key; forwardUrl = this.trackSelectionUrl + courseKey;
} }
} }
// TODO: if we have a paid registration mode, add item to the cart and send them along // TODO: if we have a paid registration mode, add item to the cart and send them along
// TODO: we should figure out how to handle errors here eventually // TODO: we should figure out how to handle errors here
window.location.href = forward_url; window.location.href = forwardUrl;
}, },
postEnrollmentHandler: function(course_key, data, forward_url) { postEnrollmentHandler: function(courseKey, data, forwardUrl) {
// Determine whether or not the course needs to be redirected to // Determine whether or not the course needs to be redirected to
// a particular page. // a particular page.
var course = data.course, var course = data.course,
course_modes = course.course_modes; course_modes = course.course_modes;
// send the user to the track selection page, because it will do the right thing // send the user to the track selection page, because it will do the right thing
forward_url = this.trackSelectionUrl + course_key; forwardUrl = this.trackSelectionUrl + courseKey;
window.location.href = forward_url; window.location.href = forwardUrl;
} }
}; };
})(jQuery, _, gettext); })(jQuery, _, gettext);
var edx = edx || {}; var edx = edx || {};
(function($, _, Backbone, gettext) { (function($, Backbone) {
'use strict'; 'use strict';
edx.student = edx.student || {}; edx.student = edx.student || {};
edx.student.account = edx.student.account || {}; edx.student.account = edx.student.account || {};
edx.student.account.LoginModel = Backbone.Model.extend({ edx.student.account.LoginModel = Backbone.Model.extend({
defaults: { defaults: {
...@@ -33,35 +32,11 @@ var edx = edx || {}; ...@@ -33,35 +32,11 @@ var edx = edx || {};
headers: headers headers: headers
}) })
.done(function() { .done(function() {
var enrollment = edx.student.account.EnrollmentInterface,
query = new URI(window.location.search),
url = '/dashboard',
query_map = query.search(true),
next = '';
// check for forwarding url
if("next" in query_map) {
next = query_map['next'];
if(!window.isExternal(next)){
url = next;
}
}
model.trigger('sync'); model.trigger('sync');
// if we need to enroll in the course, mark as enrolled
if('enrollment_action' in query_map && query_map['enrollment_action'] === 'enroll'){
enrollment.enroll(query_map['course_id'], url);
}
else {
window.location.href = url;
}
}) })
.fail( function( error ) { .fail( function( error ) {
model.trigger('error', error); model.trigger('error', error);
}); });
} }
}); });
})(jQuery, _, Backbone, gettext); })(jQuery, Backbone);
var edx = edx || {}; var edx = edx || {};
(function($, _, Backbone, gettext) { (function($, Backbone) {
'use strict'; 'use strict';
edx.student = edx.student || {}; edx.student = edx.student || {};
...@@ -31,11 +31,11 @@ var edx = edx || {}; ...@@ -31,11 +31,11 @@ var edx = edx || {};
headers: headers headers: headers
}) })
.done(function() { .done(function() {
model.trigger('success'); model.trigger('sync');
}) })
.fail( function( error ) { .fail( function( error ) {
model.trigger( 'error', error ); model.trigger('error', error);
}); });
} }
}); });
})(jQuery, _, Backbone, gettext); })(jQuery, Backbone);
var edx = edx || {}; var edx = edx || {};
(function($, _, Backbone, gettext) { (function($, Backbone) {
'use strict'; 'use strict';
edx.student = edx.student || {}; edx.student = edx.student || {};
...@@ -18,7 +18,7 @@ var edx = edx || {}; ...@@ -18,7 +18,7 @@ var edx = edx || {};
year_of_birth: '', year_of_birth: '',
mailing_address: '', mailing_address: '',
goals: '', goals: '',
termsofservice: false terms_of_service: false
}, },
urlRoot: '', urlRoot: '',
...@@ -39,33 +39,11 @@ var edx = edx || {}; ...@@ -39,33 +39,11 @@ var edx = edx || {};
headers: headers headers: headers
}) })
.done(function() { .done(function() {
var enrollment = edx.student.account.EnrollmentInterface,
query = new URI(window.location.search),
url = '/dashboard',
query_map = query.search(true),
next = '';
// check for forwarding url
if("next" in query_map) {
next = query_map['next'];
if(!window.isExternal(next)){
url = next;
}
}
model.trigger('sync'); model.trigger('sync');
// if we need to enroll in the course, mark as enrolled
if('enrollment_action' in query_map && query_map['enrollment_action'] === 'enroll'){
enrollment.enroll(query_map['course_id'], url);
}
else {
window.location.href = url;
}
}) })
.fail( function( error ) { .fail( function( error ) {
model.trigger('error', error); model.trigger('error', error);
}); });
} }
}); });
})(jQuery, _, Backbone, gettext); })(jQuery, Backbone);
var edx = edx || {}; var edx = edx || {};
(function($, _, Backbone, gettext, analytics) { (function($, _, _s, Backbone, gettext) {
'use strict'; 'use strict';
edx.student = edx.student || {}; edx.student = edx.student || {};
...@@ -29,7 +29,7 @@ var edx = edx || {}; ...@@ -29,7 +29,7 @@ var edx = edx || {};
* (all but include, contains, and reverse) into the * (all but include, contains, and reverse) into the
* Underscore namespace * Underscore namespace
*/ */
_.mixin( _.str.exports() ); _.mixin( _s.exports() );
this.tpl = $(this.tpl).html(); this.tpl = $(this.tpl).html();
this.activeForm = obj.mode || 'login'; this.activeForm = obj.mode || 'login';
...@@ -112,20 +112,20 @@ var edx = edx || {}; ...@@ -112,20 +112,20 @@ var edx = edx || {};
}; };
$.ajax({ $.ajax({
type: 'GET',
dataType: 'json',
url: '/user_api/v1/account/' + urls[type] + '/', url: '/user_api/v1/account/' + urls[type] + '/',
success: function( data ) { type: 'GET',
dataType: 'json'
})
.done(function( data ) {
callback( data, context ); callback( data, context );
}, })
error: function( jqXHR, textStatus, errorThrown ) { .fail(function( jqXHR, textStatus, errorThrown ) {
console.log('fail ', errorThrown); console.log('fail ', errorThrown);
}
}); });
}, },
resetPassword: function() { resetPassword: function() {
analytics.track('edx.bi.password_reset_form.viewed', { window.analytics.track('edx.bi.password_reset_form.viewed', {
category: 'user-engagement' category: 'user-engagement'
}); });
...@@ -139,7 +139,7 @@ var edx = edx || {}; ...@@ -139,7 +139,7 @@ var edx = edx || {};
$form = $('#' + type + '-form'), $form = $('#' + type + '-form'),
$anchor = $('#' + type + '-anchor'); $anchor = $('#' + type + '-anchor');
analytics.track('edx.bi.' + type + '_form.toggled', { window.analytics.track('edx.bi.' + type + '_form.toggled', {
category: 'user-engagement' category: 'user-engagement'
}); });
...@@ -177,5 +177,4 @@ var edx = edx || {}; ...@@ -177,5 +177,4 @@ var edx = edx || {};
} }
} }
}); });
})(jQuery, _, _.str, Backbone, gettext);
})(jQuery, _, Backbone, gettext, analytics);
...@@ -29,12 +29,12 @@ var edx = edx || {}; ...@@ -29,12 +29,12 @@ var edx = edx || {};
requiredStr: '*', requiredStr: '*',
initialize: function( data ) { initialize: function( data ) {
this.model = data.model;
this.preRender( data ); this.preRender( data );
this.tpl = $(this.tpl).html(); this.tpl = $(this.tpl).html();
this.fieldTpl = $(this.fieldTpl).html(); this.fieldTpl = $(this.fieldTpl).html();
this.buildForm( data.fields ); this.buildForm( data.fields );
this.model = data.model;
this.listenTo( this.model, 'error', this.saveError ); this.listenTo( this.model, 'error', this.saveError );
}, },
......
...@@ -25,6 +25,8 @@ var edx = edx || {}; ...@@ -25,6 +25,8 @@ var edx = edx || {};
this.providers = data.thirdPartyAuth.providers || []; this.providers = data.thirdPartyAuth.providers || [];
this.currentProvider = data.thirdPartyAuth.currentProvider || ''; this.currentProvider = data.thirdPartyAuth.currentProvider || '';
this.platformName = data.platformName; this.platformName = data.platformName;
this.listenTo( this.model, 'sync', this.saveSuccess );
}, },
render: function( html ) { render: function( html ) {
...@@ -76,6 +78,32 @@ var edx = edx || {}; ...@@ -76,6 +78,32 @@ var edx = edx || {};
} }
}, },
saveSuccess: function () {
var enrollment = edx.student.account.EnrollmentInterface,
redirectUrl = '/dashboard',
next = null;
// Check for forwarding url
if ( !_.isNull( $.url('?next') ) ) {
next = decodeURIComponent( $.url('?next') );
if ( !window.isExternal(next) ) {
redirectUrl = next;
}
}
// If we need to enroll in a course, mark as enrolled
if ( $.url('?enrollment_action') === 'enroll' ) {
enrollment.enroll( decodeURIComponent( $.url('?course_id') ), redirectUrl );
} else {
this.redirect(redirectUrl);
}
},
redirect: function( url ) {
window.location.href = url;
},
saveError: function( error ) { saveError: function( error ) {
this.errors = ['<li>' + error.responseText + '</li>']; this.errors = ['<li>' + error.responseText + '</li>'];
this.setErrors(); this.setErrors();
......
...@@ -19,15 +19,8 @@ var edx = edx || {}; ...@@ -19,15 +19,8 @@ var edx = edx || {};
requiredStr: '', requiredStr: '',
postRender: function() { preRender: function( data ) {
var $container = $(this.el); this.listenTo( this.model, 'sync', this.saveSuccess );
this.$form = $container.find('form');
this.$errors = $container.find('.submission-error');
this.listenTo( this.model, 'success', this.resetComplete );
this.listenTo( this.model, 'error', this.saveError );
}, },
toggleErrorMsg: function( show ) { toggleErrorMsg: function( show ) {
...@@ -38,7 +31,7 @@ var edx = edx || {}; ...@@ -38,7 +31,7 @@ var edx = edx || {};
} }
}, },
resetComplete: function() { saveSuccess: function() {
var $el = $(this.el); var $el = $(this.el);
this.element.hide( $el.find('#password-reset-form') ); this.element.hide( $el.find('#password-reset-form') );
......
...@@ -22,6 +22,8 @@ var edx = edx || {}; ...@@ -22,6 +22,8 @@ var edx = edx || {};
this.providers = data.thirdPartyAuth.providers || []; this.providers = data.thirdPartyAuth.providers || [];
this.currentProvider = data.thirdPartyAuth.currentProvider || ''; this.currentProvider = data.thirdPartyAuth.currentProvider || '';
this.platformName = data.platformName; this.platformName = data.platformName;
this.listenTo( this.model, 'sync', this.saveSuccess );
}, },
render: function( html ) { render: function( html ) {
...@@ -50,7 +52,32 @@ var edx = edx || {}; ...@@ -50,7 +52,32 @@ var edx = edx || {};
if ( providerUrl ) { if ( providerUrl ) {
window.location.href = providerUrl; window.location.href = providerUrl;
} }
},
saveSuccess: function() {
var enrollment = edx.student.account.EnrollmentInterface,
redirectUrl = '/dashboard',
next = null;
// Check for forwarding url
if ( !_.isNull( $.url('?next') ) ) {
next = decodeURIComponent( $.url('?next') );
if ( !window.isExternal(next) ) {
redirectUrl = next;
} }
}); }
// If we need to enroll in a course, mark as enrolled
if ( $.url('?enrollment_action') === 'enroll' ) {
enrollment.enroll( decodeURIComponent( $.url('?course_id') ), redirectUrl );
} else {
this.redirect(redirectUrl);
}
},
redirect: function( url ) {
window.location.href = url;
}
});
})(jQuery, _, gettext); })(jQuery, _, gettext);
...@@ -4,7 +4,7 @@ var edx = edx || {}; ...@@ -4,7 +4,7 @@ var edx = edx || {};
'use strict'; 'use strict';
edx.student = edx.student || {}; edx.student = edx.student || {};
edx.student.profile = {}; edx.student.profile = edx.student.profile || {};
var syncErrorMessage = gettext("The data could not be saved."); var syncErrorMessage = gettext("The data could not be saved.");
......
...@@ -41,6 +41,7 @@ lib_paths: ...@@ -41,6 +41,7 @@ lib_paths:
- xmodule_js/common_static/js/vendor/flot/jquery.flot.js - xmodule_js/common_static/js/vendor/flot/jquery.flot.js
- xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js - xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js
- xmodule_js/common_static/js/vendor/URI.min.js - xmodule_js/common_static/js/vendor/URI.min.js
- xmodule_js/common_static/js/vendor/url.min.js
- xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js - xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js
- xmodule_js/common_static/coffee/src/xblock - xmodule_js/common_static/coffee/src/xblock
- xmodule_js/common_static/js/vendor/sinon-1.7.1.js - xmodule_js/common_static/js/vendor/sinon-1.7.1.js
...@@ -49,6 +50,7 @@ lib_paths: ...@@ -49,6 +50,7 @@ lib_paths:
- xmodule_js/src/xmodule.js - xmodule_js/src/xmodule.js
- xmodule_js/common_static/js/src/ - xmodule_js/common_static/js/src/
- xmodule_js/common_static/js/vendor/underscore-min.js - xmodule_js/common_static/js/vendor/underscore-min.js
- xmodule_js/common_static/js/vendor/underscore.string.min.js
- xmodule_js/common_static/js/vendor/backbone-min.js - xmodule_js/common_static/js/vendor/backbone-min.js
# Paths to source JavaScript files # Paths to source JavaScript files
......
...@@ -6,9 +6,10 @@ ...@@ -6,9 +6,10 @@
<%block name="pagetitle">${_("Log in or Register")}</%block> <%block name="pagetitle">${_("Log in or Register")}</%block>
<%block name="js_extra"> <%block name="js_extra">
<script type="text/javascript" src="${static.url('js/vendor/backbone-min.js')}"></script> <script src="${static.url('js/vendor/underscore-min.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/underscore.string.min.js')}"></script> <script src="${static.url('js/vendor/underscore.string.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/URI.min.js')}"></script> <script src="${static.url('js/vendor/backbone-min.js')}"></script>
<script src="${static.url('js/vendor/url.min.js')}"></script>
<%static:js group='student_account'/> <%static:js group='student_account'/>
</%block> </%block>
......
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