Merge pull request #5857 from edx/renzo/add-js-tests
Fix logistration Jasmine tests
This commit is contained in:
@@ -728,10 +728,6 @@ class LoginSessionViewTest(ApiTestCase):
|
||||
class PasswordResetViewTest(ApiTestCase):
|
||||
"""Tests of the user API's password reset endpoint. """
|
||||
|
||||
USERNAME = "bob"
|
||||
EMAIL = "bob@example.com"
|
||||
PASSWORD = "password"
|
||||
|
||||
def setUp(self):
|
||||
super(PasswordResetViewTest, self).setUp()
|
||||
self.url = reverse("user_api_password_reset")
|
||||
|
||||
1
common/static/js/vendor/url.min.js
vendored
Normal file
1
common/static/js/vendor/url.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/*! 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)}});
|
||||
@@ -23,6 +23,7 @@
|
||||
'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill',
|
||||
'jquery.immediateDescendents': 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents',
|
||||
'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',
|
||||
'date': 'xmodule_js/common_static/js/vendor/date',
|
||||
'underscore': 'xmodule_js/common_static/js/vendor/underscore-min',
|
||||
@@ -43,7 +44,6 @@
|
||||
'jasmine.async': 'xmodule_js/common_static/js/vendor/jasmine.async',
|
||||
'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly.pkgd',
|
||||
'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',
|
||||
'youtube': '//www.youtube.com/player_api?noext',
|
||||
'tender': '//edxedge.tenderapp.com/tender_widget',
|
||||
@@ -65,7 +65,17 @@
|
||||
'js/views/cohort_editor': 'js/views/cohort_editor',
|
||||
'js/views/cohorts': 'js/views/cohorts',
|
||||
'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: {
|
||||
'gettext': {
|
||||
@@ -133,11 +143,31 @@
|
||||
deps: ['jquery', 'tinymce'],
|
||||
exports: 'jQuery.fn.tinymce'
|
||||
},
|
||||
'jquery.url': {
|
||||
deps: ['jquery'],
|
||||
exports: 'jQuery.fn.url'
|
||||
},
|
||||
'datepair': {
|
||||
deps: ['jquery.ui', 'jquery.timepicker']
|
||||
},
|
||||
'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': {
|
||||
deps: ['underscore', 'jquery'],
|
||||
@@ -216,7 +246,6 @@
|
||||
exports: 'js/student_account/account',
|
||||
deps: ['jquery', 'underscore', 'backbone', 'gettext', 'jquery.cookie']
|
||||
},
|
||||
|
||||
'js/student_profile/profile': {
|
||||
exports: 'js/student_profile/profile',
|
||||
deps: ['jquery', 'underscore', 'backbone', 'gettext', 'jquery.cookie']
|
||||
@@ -261,60 +290,76 @@
|
||||
deps: ['backbone', 'jquery', 'underscore']
|
||||
},
|
||||
'js/student_account/enrollment_interface': {
|
||||
exports: 'js/student_account/enrollment_interface',
|
||||
deps: ['jquery', 'underscore', 'gettext']
|
||||
exports: 'edx.student.account.EnrollmentInterface',
|
||||
deps: ['jquery', 'jquery.cookie', 'underscore', 'gettext']
|
||||
},
|
||||
// Student account registration/login
|
||||
// Loaded explicitly until these are converted to RequireJS
|
||||
'js/student_account/views/FormView': {
|
||||
exports: 'js/student_account/views/FormView',
|
||||
exports: 'edx.student.account.FormView',
|
||||
deps: ['jquery', 'underscore', 'backbone', 'gettext']
|
||||
},
|
||||
'js/student_account/models/LoginModel': {
|
||||
exports: 'js/student_account/models/LoginModel',
|
||||
deps: ['jquery', 'underscore', 'backbone', 'gettext', 'jquery.cookie']
|
||||
exports: 'edx.student.account.LoginModel',
|
||||
deps: ['jquery', 'jquery.cookie', 'backbone']
|
||||
},
|
||||
'js/student_account/views/LoginView': {
|
||||
exports: 'js/student_account/views/LoginView',
|
||||
exports: 'edx.student.account.LoginView',
|
||||
deps: [
|
||||
'jquery',
|
||||
'jquery.url',
|
||||
'underscore',
|
||||
'gettext',
|
||||
'js/student_account/models/LoginModel',
|
||||
'js/student_account/views/FormView',
|
||||
'underscore.string'
|
||||
'js/student_account/views/FormView'
|
||||
]
|
||||
},
|
||||
'js/student_account/models/PasswordResetModel': {
|
||||
exports: 'js/student_account/models/PasswordResetModel',
|
||||
deps: ['jquery', 'underscore', 'backbone', 'gettext', 'jquery.cookie']
|
||||
exports: 'edx.student.account.PasswordResetModel',
|
||||
deps: ['jquery', 'jquery.cookie', 'backbone']
|
||||
},
|
||||
'js/student_account/views/PasswordResetView': {
|
||||
exports: 'js/student_account/views/PasswordResetView',
|
||||
exports: 'edx.student.account.PasswordResetView',
|
||||
deps: [
|
||||
'jquery',
|
||||
'underscore',
|
||||
'gettext',
|
||||
'js/student_account/models/PasswordResetModel',
|
||||
'js/student_account/views/FormView'
|
||||
]
|
||||
},
|
||||
'js/student_account/models/RegisterModel': {
|
||||
exports: 'js/student_account/models/RegisterModel',
|
||||
deps: ['jquery', 'underscore', 'backbone', 'gettext', 'jquery.cookie']
|
||||
exports: 'edx.student.account.RegisterModel',
|
||||
deps: ['jquery', 'jquery.cookie', 'backbone']
|
||||
},
|
||||
'js/student_account/views/RegisterView': {
|
||||
exports: 'js/student_account/views/RegisterView',
|
||||
exports: 'edx.student.account.RegisterView',
|
||||
deps: [
|
||||
'jquery',
|
||||
'jquery.url',
|
||||
'underscore',
|
||||
'gettext',
|
||||
'js/student_account/models/RegisterModel',
|
||||
'js/student_account/views/FormView',
|
||||
'underscore.string'
|
||||
'js/student_account/views/FormView'
|
||||
]
|
||||
},
|
||||
'js/student_account/views/AccessView': {
|
||||
exports: 'js/student_account/views/AccessView',
|
||||
exports: 'edx.student.account.AccessView',
|
||||
deps: [
|
||||
'jquery',
|
||||
'underscore',
|
||||
'backbone',
|
||||
'gettext',
|
||||
'js/student_account/views/LoginView',
|
||||
'js/student_account/views/PasswordResetView',
|
||||
'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?
|
||||
@@ -325,13 +370,13 @@
|
||||
'lms/include/js/spec/staff_debug_actions_spec.js',
|
||||
'lms/include/js/spec/views/notification_spec.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/login_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/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);
|
||||
|
||||
@@ -1,96 +1,161 @@
|
||||
define(['js/common_helpers/template_helpers', 'js/student_account/views/AccessView'],
|
||||
function(TemplateHelpers, AccessView) {
|
||||
define([
|
||||
'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() {
|
||||
'use strict';
|
||||
|
||||
var view = null,
|
||||
ajaxSuccess = true;
|
||||
|
||||
var assertForms = function(visible, hidden) {
|
||||
expect($(visible)).not.toHaveClass('hidden');
|
||||
expect($(hidden)).toHaveClass('hidden');
|
||||
expect($('#password-reset-wrapper')).toBeEmpty();
|
||||
};
|
||||
|
||||
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');
|
||||
|
||||
// Used to populate forms
|
||||
var form_description = {
|
||||
"method": "post",
|
||||
"submit_url": "/submit",
|
||||
"fields": [
|
||||
var requests = null,
|
||||
view = null,
|
||||
AJAX_INFO = {
|
||||
register: {
|
||||
url: '/user_api/v1/account/registration/',
|
||||
requestIndex: 1
|
||||
},
|
||||
login: {
|
||||
url: '/user_api/v1/account/login_session/',
|
||||
requestIndex: 0
|
||||
},
|
||||
password_reset: {
|
||||
url: '/user_api/v1/account/password_reset/',
|
||||
requestIndex: 1
|
||||
}
|
||||
},
|
||||
FORM_DESCRIPTION = {
|
||||
method: 'post',
|
||||
submit_url: '/submit',
|
||||
fields: [
|
||||
{
|
||||
"name": "email",
|
||||
"label": "Email",
|
||||
"default": "",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"placeholder": "xsy@edx.org",
|
||||
"instructions": "Enter your email here.",
|
||||
"restrictions": {},
|
||||
name: 'email',
|
||||
label: 'Email',
|
||||
defaultValue: '',
|
||||
type: 'text',
|
||||
required: true,
|
||||
placeholder: 'xsy@edx.org',
|
||||
instructions: 'Enter your email here.',
|
||||
restrictions: {},
|
||||
},
|
||||
{
|
||||
"name": "username",
|
||||
"label": "Username",
|
||||
"default": "",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"placeholder": "Xsy",
|
||||
"instructions": "Enter your username here.",
|
||||
"restrictions": {
|
||||
"max_length": 200
|
||||
name: 'username',
|
||||
label: 'Username',
|
||||
defaultValue: '',
|
||||
type: 'text',
|
||||
required: true,
|
||||
placeholder: 'Xsy',
|
||||
instructions: 'Enter your username here.',
|
||||
restrictions: {
|
||||
max_length: 200
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Stub AJAX calls and force them to return a form description
|
||||
spyOn($, 'ajax').andCallFake(function() {
|
||||
return $.Deferred(function(defer) {
|
||||
if (ajaxSuccess) {
|
||||
defer.resolveWith(this, [form_description]);
|
||||
} else {
|
||||
defer.reject();
|
||||
}
|
||||
}).promise();
|
||||
});
|
||||
var ajaxAssertAndRespond = function(url, requestIndex) {
|
||||
// Verify that the client contacts the server as expected
|
||||
AjaxHelpers.expectJsonRequest(requests, 'GET', url, null, requestIndex);
|
||||
|
||||
view = new edx.student.account.AccessView({
|
||||
mode: 'login',
|
||||
/* Simulate a response from the server containing
|
||||
/* a dummy form description
|
||||
*/
|
||||
AjaxHelpers.respondWithJson(requests, FORM_DESCRIPTION);
|
||||
};
|
||||
|
||||
var ajaxSpyAndInitialize = function(that, mode) {
|
||||
// Spy on AJAX requests
|
||||
requests = AjaxHelpers.requests(that);
|
||||
|
||||
// Initialize the access view
|
||||
view = new AccessView({
|
||||
mode: mode,
|
||||
thirdPartyAuth: {
|
||||
currentProvider: null,
|
||||
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("initially displays the correct form", function() {
|
||||
assertForms($('#login-form'), $('#register-form'));
|
||||
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("toggles between the login and registration forms", function() {
|
||||
var registerChangeEvent = $.Event('change', {currentTarget: $('#register-option')}),
|
||||
loginChangeEvent = $.Event('change', {currentTarget: $('#login-option')});
|
||||
it('can initially display the registration form', function() {
|
||||
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() {
|
||||
ajaxSpyAndInitialize(this, 'login');
|
||||
|
||||
// Simulate selection of the registration form
|
||||
view.toggleForm(registerChangeEvent)
|
||||
assertForms($('#register-form'), $('#login-form'));
|
||||
selectForm('register');
|
||||
assertForms('#register-form', '#login-form');
|
||||
|
||||
// Simulate selection of the login form
|
||||
view.toggleForm(loginChangeEvent)
|
||||
assertForms($('#login-form'), $('#register-form'));
|
||||
selectForm('login');
|
||||
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();
|
||||
|
||||
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();
|
||||
});
|
||||
|
||||
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.
|
||||
*/
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
define(['js/common_helpers/template_helpers', 'js/student_account/enrollment_interface'],
|
||||
function(TemplateHelpers, EnrollmentInterface) {
|
||||
define(['js/student_account/enrollment_interface'],
|
||||
function(EnrollmentInterface) {
|
||||
describe("edx.student.account.EnrollmentInterface", function() {
|
||||
'use strict';
|
||||
|
||||
it("find course modes using modeInArray ", function() {
|
||||
var course_modes = [
|
||||
{
|
||||
slug: 'honor'
|
||||
},
|
||||
{
|
||||
slug: 'professional'
|
||||
}
|
||||
],
|
||||
|
||||
expect(EnrollmentInterface.modeInArray('professional')).toBe(true);
|
||||
expect(EnrollmentInterface.modeInArray('audit')).toBe(false);
|
||||
it('checks if a given course mode slug exists in an array of mode objects', function() {
|
||||
var courseModes = [ { slug: 'honor' }, { slug: 'professional' } ]
|
||||
|
||||
expect( EnrollmentInterface.modeInArray( courseModes, 'professional' ) ).toBe(true);
|
||||
expect( EnrollmentInterface.modeInArray( courseModes, 'audit' ) ).toBe(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,47 +1,203 @@
|
||||
define(['js/common_helpers/template_helpers', 'js/student_account/views/LoginView'],
|
||||
function(TemplateHelpers) {
|
||||
describe("edx.student.account.LoginView", function() {
|
||||
define([
|
||||
'jquery',
|
||||
'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';
|
||||
|
||||
var model = null,
|
||||
view = null,
|
||||
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
|
||||
});
|
||||
|
||||
// Spy on AJAX requests
|
||||
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);
|
||||
|
||||
// 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);
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures("<div></div>");
|
||||
TemplateHelpers.installTemplate("templates/student_account/login");
|
||||
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() {
|
||||
// TODO
|
||||
it('logs the user in', function() {
|
||||
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 third party auth login buttons", function() {
|
||||
// TODO
|
||||
it('displays third-party auth login buttons', function() {
|
||||
createLoginView(this);
|
||||
|
||||
// Verify that Google and Facebook registration buttons are displayed
|
||||
expect($('.button-Google')).toBeVisible();
|
||||
expect($('.button-Facebook')).toBeVisible();
|
||||
});
|
||||
|
||||
it("validates the email field", function() {
|
||||
// TODO
|
||||
it('displays a link to the password reset form', function() {
|
||||
createLoginView(this);
|
||||
|
||||
// Verify that the password reset link is displayed
|
||||
expect($('.forgot-password')).toBeVisible();
|
||||
});
|
||||
|
||||
it("validates the password field", function() {
|
||||
// TODO
|
||||
it('validates login form fields', function() {
|
||||
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("displays login errors", function() {
|
||||
// TODO
|
||||
it('displays login form validation errors', function() {
|
||||
createLoginView(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 form definition could not be loaded", function() {
|
||||
// TODO
|
||||
});
|
||||
it('displays an error if the server returns an error while logging in', function() {
|
||||
createLoginView(this);
|
||||
|
||||
it("displays an error if the server could not be contacted while logging in", function() {
|
||||
// TODO
|
||||
});
|
||||
// Submit the form, with successful validation
|
||||
submitForm(true);
|
||||
|
||||
it("allows the user to navigate to the password assistance form", function() {
|
||||
// TODO
|
||||
});
|
||||
// Simulate an error from the LMS servers
|
||||
AjaxHelpers.respondWithError(requests);
|
||||
|
||||
it("enrolls the student into the right location and forwards them properly", function() {
|
||||
// TODO
|
||||
// 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');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,34 +1,61 @@
|
||||
define(['js/common_helpers/template_helpers', 'js/student_account/views/PasswordResetView'],
|
||||
function(TemplateHelpers) {
|
||||
define([
|
||||
'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() {
|
||||
'use strict';
|
||||
|
||||
var view = null,
|
||||
ajaxSuccess = true,
|
||||
model = new edx.student.account.PasswordResetModel(),
|
||||
data = [{
|
||||
label: 'E-mail',
|
||||
instructions: 'This is the e-mail address you used to register with edX',
|
||||
name: 'email',
|
||||
required: true,
|
||||
type: 'email',
|
||||
restrictions: [],
|
||||
defaultValue: ''
|
||||
}];
|
||||
var model = null,
|
||||
view = null,
|
||||
requests = null,
|
||||
EMAIL = 'xsy@edx.org',
|
||||
FORM_DESCRIPTION = {
|
||||
method: 'post',
|
||||
submit_url: '/account/password',
|
||||
fields: [{
|
||||
name: 'email',
|
||||
label: 'Email',
|
||||
defaultValue: '',
|
||||
type: 'text',
|
||||
required: true,
|
||||
placeholder: 'place@holder.org',
|
||||
instructions: 'Enter your email.',
|
||||
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) {
|
||||
// Simulate manual entry of an email address
|
||||
$('#password-reset-email').val('foo@bar.baz');
|
||||
$('#password-reset-email').val(EMAIL);
|
||||
|
||||
// Create a fake click event
|
||||
var clickEvent = $.Event('click');
|
||||
|
||||
// Used to avoid spying on view.validate twice
|
||||
if (typeof validationSuccess !== 'undefined') {
|
||||
// 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: "We're all good."
|
||||
message: 'Submission was validated.'
|
||||
});
|
||||
}
|
||||
|
||||
@@ -36,65 +63,74 @@ define(['js/common_helpers/template_helpers', 'js/student_account/views/Password
|
||||
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() {
|
||||
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/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({
|
||||
fields: data,
|
||||
model: model
|
||||
});
|
||||
});
|
||||
|
||||
it("allows the user to request a new password", function() {
|
||||
it('allows the user to request a new password', function() {
|
||||
createPasswordResetView(this);
|
||||
|
||||
// Submit the form, with successful validation
|
||||
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');
|
||||
});
|
||||
|
||||
it("validates the email field", function() {
|
||||
it('validates the email field', function() {
|
||||
createPasswordResetView(this);
|
||||
|
||||
// Submit the form, with successful validation
|
||||
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');
|
||||
});
|
||||
|
||||
it("displays password reset validation errors", function() {
|
||||
it('displays password reset validation errors', function() {
|
||||
createPasswordResetView(this);
|
||||
|
||||
// Submit the form, with failed validation
|
||||
submitEmail(false);
|
||||
|
||||
// Verify that submission errors are visible
|
||||
expect(view.$errors).not.toHaveClass('hidden');
|
||||
});
|
||||
|
||||
it("displays an error if the server could not be contacted", function() {
|
||||
// If we get an error status on the AJAX request, display an error
|
||||
ajaxSuccess = false;
|
||||
it('displays an error if the server returns an error while sending a password reset email', function() {
|
||||
createPasswordResetView(this);
|
||||
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
|
||||
ajaxSuccess = true;
|
||||
// No argument means we won't spy on view.validate again
|
||||
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');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,35 +1,296 @@
|
||||
define(['js/common_helpers/template_helpers', 'js/student_account/views/RegisterView'],
|
||||
function(TemplateHelpers) {
|
||||
describe("edx.student.account.RegisterView", function() {
|
||||
define([
|
||||
'jquery',
|
||||
'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';
|
||||
|
||||
var model = null,
|
||||
view = null,
|
||||
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;
|
||||
});
|
||||
};
|
||||
|
||||
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 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></div>");
|
||||
TemplateHelpers.installTemplate("templates/student_account/register");
|
||||
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() {
|
||||
// TODO
|
||||
it('registers a new user', function() {
|
||||
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("displays third party auth registration buttons", function() {
|
||||
// TODO
|
||||
it('displays third-party auth registration buttons', function() {
|
||||
createRegisterView(this);
|
||||
|
||||
// Verify that Google and Facebook registration buttons are displayed
|
||||
expect($('.button-Google')).toBeVisible();
|
||||
expect($('.button-Facebook')).toBeVisible();
|
||||
});
|
||||
|
||||
it("validates form fields", function() {
|
||||
// TODO
|
||||
it('validates registration form fields', function() {
|
||||
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 registration errors", function() {
|
||||
// TODO
|
||||
it('displays registration form validation errors', function() {
|
||||
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 form definition could not be loaded", function() {
|
||||
// TODO
|
||||
});
|
||||
it('displays an error if the server returns an error while registering', function() {
|
||||
createRegisterView(this);
|
||||
|
||||
it("displays an error if the server could not be contacted while registering", function() {
|
||||
// TODO
|
||||
// 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 || {};
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
edx.student.account = {};
|
||||
edx.student.account = edx.student.account || {};
|
||||
|
||||
edx.student.account.AccountModel = Backbone.Model.extend({
|
||||
// These should be the same length limits enforced by the server
|
||||
|
||||
@@ -8,71 +8,80 @@ var edx = edx || {};
|
||||
|
||||
edx.student.account.EnrollmentInterface = {
|
||||
courseUrl: '/enrollment/v0/course/',
|
||||
|
||||
studentUrl: '/enrollment/v0/student',
|
||||
|
||||
trackSelectionUrl: '/course_modes/choose/',
|
||||
|
||||
headers: {
|
||||
'X-CSRFToken': $.cookie('csrftoken')
|
||||
},
|
||||
|
||||
studentInformation: function(course_key) {
|
||||
studentInformation: function(courseKey) {
|
||||
// retrieve student enrollment information
|
||||
},
|
||||
|
||||
courseInformation: function(course_key) {
|
||||
courseInformation: function(courseKey) {
|
||||
// retrieve course information from the enrollment API
|
||||
},
|
||||
|
||||
modeInArray: function(mode_slug, course_modes) {
|
||||
// finds whether or not a particular course mode slug exists
|
||||
// in an array of course modes
|
||||
var result = _.find(course_modes, function(mode){ return mode.slug === mode_slug; });
|
||||
return result != undefined;
|
||||
modeInArray: function(modeObjects, targetMode) {
|
||||
// Check if a given course mode slug exists in an array of mode objects
|
||||
var result = _.find(modeObjects, function(mode) {
|
||||
return mode.slug === targetMode;
|
||||
});
|
||||
|
||||
/* _.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;
|
||||
// attempt to enroll a student in a course
|
||||
$.ajax({
|
||||
url: this.courseUrl + course_key,
|
||||
url: this.courseUrl + courseKey,
|
||||
type: 'POST',
|
||||
data: {},
|
||||
headers: this.headers
|
||||
}).done(function(data){
|
||||
me.postEnrollmentHandler(course_key, data, forward_url);
|
||||
me.postEnrollmentHandler(courseKey, data, forwardUrl);
|
||||
}
|
||||
).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
|
||||
if(data.status == 400) {
|
||||
// This status code probably means we don't have permissions to register for this course.
|
||||
// look at the contents of the response
|
||||
/* This status code probably means we don't have permissions to register
|
||||
/* for this course; look at the contents of the response
|
||||
*/
|
||||
var course = $.parseJSON(data.responseText);
|
||||
// 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_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: we should figure out how to handle errors here eventually
|
||||
window.location.href = forward_url;
|
||||
// TODO: we should figure out how to handle errors here
|
||||
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
|
||||
// a particular page.
|
||||
var course = data.course,
|
||||
course_modes = course.course_modes;
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function($, _, Backbone, gettext) {
|
||||
(function($, Backbone) {
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
edx.student.account = edx.student.account || {};
|
||||
|
||||
|
||||
edx.student.account.LoginModel = Backbone.Model.extend({
|
||||
|
||||
defaults: {
|
||||
@@ -33,35 +32,11 @@ var edx = edx || {};
|
||||
headers: headers
|
||||
})
|
||||
.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');
|
||||
|
||||
// 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 ) {
|
||||
model.trigger('error', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
})(jQuery, _, Backbone, gettext);
|
||||
})(jQuery, Backbone);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function($, _, Backbone, gettext) {
|
||||
(function($, Backbone) {
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
@@ -31,11 +31,11 @@ var edx = edx || {};
|
||||
headers: headers
|
||||
})
|
||||
.done(function() {
|
||||
model.trigger('success');
|
||||
model.trigger('sync');
|
||||
})
|
||||
.fail( function( error ) {
|
||||
model.trigger( 'error', error );
|
||||
model.trigger('error', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
})(jQuery, _, Backbone, gettext);
|
||||
})(jQuery, Backbone);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function($, _, Backbone, gettext) {
|
||||
(function($, Backbone) {
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
@@ -18,7 +18,7 @@ var edx = edx || {};
|
||||
year_of_birth: '',
|
||||
mailing_address: '',
|
||||
goals: '',
|
||||
termsofservice: false
|
||||
terms_of_service: false
|
||||
},
|
||||
|
||||
urlRoot: '',
|
||||
@@ -39,33 +39,11 @@ var edx = edx || {};
|
||||
headers: headers
|
||||
})
|
||||
.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');
|
||||
|
||||
// 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 ) {
|
||||
model.trigger('error', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
})(jQuery, _, Backbone, gettext);
|
||||
})(jQuery, Backbone);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function($, _, Backbone, gettext, analytics) {
|
||||
(function($, _, _s, Backbone, gettext) {
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
@@ -29,7 +29,7 @@ var edx = edx || {};
|
||||
* (all but include, contains, and reverse) into the
|
||||
* Underscore namespace
|
||||
*/
|
||||
_.mixin( _.str.exports() );
|
||||
_.mixin( _s.exports() );
|
||||
|
||||
this.tpl = $(this.tpl).html();
|
||||
this.activeForm = obj.mode || 'login';
|
||||
@@ -112,20 +112,20 @@ var edx = edx || {};
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
url: '/user_api/v1/account/' + urls[type] + '/',
|
||||
success: function( data ) {
|
||||
callback( data, context );
|
||||
},
|
||||
error: function( jqXHR, textStatus, errorThrown ) {
|
||||
console.log('fail ', errorThrown);
|
||||
}
|
||||
type: 'GET',
|
||||
dataType: 'json'
|
||||
})
|
||||
.done(function( data ) {
|
||||
callback( data, context );
|
||||
})
|
||||
.fail(function( jqXHR, textStatus, errorThrown ) {
|
||||
console.log('fail ', errorThrown);
|
||||
});
|
||||
},
|
||||
|
||||
resetPassword: function() {
|
||||
analytics.track('edx.bi.password_reset_form.viewed', {
|
||||
window.analytics.track('edx.bi.password_reset_form.viewed', {
|
||||
category: 'user-engagement'
|
||||
});
|
||||
|
||||
@@ -139,7 +139,7 @@ var edx = edx || {};
|
||||
$form = $('#' + type + '-form'),
|
||||
$anchor = $('#' + type + '-anchor');
|
||||
|
||||
analytics.track('edx.bi.' + type + '_form.toggled', {
|
||||
window.analytics.track('edx.bi.' + type + '_form.toggled', {
|
||||
category: 'user-engagement'
|
||||
});
|
||||
|
||||
@@ -177,5 +177,4 @@ var edx = edx || {};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery, _, Backbone, gettext, analytics);
|
||||
})(jQuery, _, _.str, Backbone, gettext);
|
||||
|
||||
@@ -29,12 +29,12 @@ var edx = edx || {};
|
||||
requiredStr: '*',
|
||||
|
||||
initialize: function( data ) {
|
||||
this.model = data.model;
|
||||
this.preRender( data );
|
||||
|
||||
this.tpl = $(this.tpl).html();
|
||||
this.fieldTpl = $(this.fieldTpl).html();
|
||||
|
||||
this.buildForm( data.fields );
|
||||
this.model = data.model;
|
||||
|
||||
this.listenTo( this.model, 'error', this.saveError );
|
||||
},
|
||||
|
||||
@@ -25,6 +25,8 @@ var edx = edx || {};
|
||||
this.providers = data.thirdPartyAuth.providers || [];
|
||||
this.currentProvider = data.thirdPartyAuth.currentProvider || '';
|
||||
this.platformName = data.platformName;
|
||||
|
||||
this.listenTo( this.model, 'sync', this.saveSuccess );
|
||||
},
|
||||
|
||||
render: function( html ) {
|
||||
@@ -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 ) {
|
||||
this.errors = ['<li>' + error.responseText + '</li>'];
|
||||
this.setErrors();
|
||||
|
||||
@@ -19,15 +19,8 @@ var edx = edx || {};
|
||||
|
||||
requiredStr: '',
|
||||
|
||||
postRender: function() {
|
||||
var $container = $(this.el);
|
||||
|
||||
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 );
|
||||
preRender: function( data ) {
|
||||
this.listenTo( this.model, 'sync', this.saveSuccess );
|
||||
},
|
||||
|
||||
toggleErrorMsg: function( show ) {
|
||||
@@ -38,7 +31,7 @@ var edx = edx || {};
|
||||
}
|
||||
},
|
||||
|
||||
resetComplete: function() {
|
||||
saveSuccess: function() {
|
||||
var $el = $(this.el);
|
||||
|
||||
this.element.hide( $el.find('#password-reset-form') );
|
||||
|
||||
@@ -22,6 +22,8 @@ var edx = edx || {};
|
||||
this.providers = data.thirdPartyAuth.providers || [];
|
||||
this.currentProvider = data.thirdPartyAuth.currentProvider || '';
|
||||
this.platformName = data.platformName;
|
||||
|
||||
this.listenTo( this.model, 'sync', this.saveSuccess );
|
||||
},
|
||||
|
||||
render: function( html ) {
|
||||
@@ -50,7 +52,32 @@ var edx = edx || {};
|
||||
if ( 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);
|
||||
|
||||
@@ -4,7 +4,7 @@ var edx = edx || {};
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
edx.student.profile = {};
|
||||
edx.student.profile = edx.student.profile || {};
|
||||
|
||||
var syncErrorMessage = gettext("The data could not be saved.");
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ lib_paths:
|
||||
- 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/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/xblock
|
||||
- xmodule_js/common_static/js/vendor/sinon-1.7.1.js
|
||||
@@ -49,6 +50,7 @@ lib_paths:
|
||||
- xmodule_js/src/xmodule.js
|
||||
- xmodule_js/common_static/js/src/
|
||||
- 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
|
||||
|
||||
# Paths to source JavaScript files
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
<%block name="pagetitle">${_("Log in or Register")}</%block>
|
||||
|
||||
<%block name="js_extra">
|
||||
<script type="text/javascript" src="${static.url('js/vendor/backbone-min.js')}"></script>
|
||||
<script type="text/javascript" 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/underscore-min.js')}"></script>
|
||||
<script src="${static.url('js/vendor/underscore.string.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'/>
|
||||
</%block>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user