Commit d2a47908 by zubair-arbi

use the standard syntax to load JavaScript dependencies on logistration js files

ECOM-2044
parent 1ba4200a
...@@ -69,8 +69,8 @@ class IntegrationTestLTI(testutil.TestCase): ...@@ -69,8 +69,8 @@ class IntegrationTestLTI(testutil.TestCase):
self.assertTrue(login_response['Location'].endswith(reverse('signin_user'))) self.assertTrue(login_response['Location'].endswith(reverse('signin_user')))
register_response = self.client.get(login_response['Location']) register_response = self.client.get(login_response['Location'])
self.assertEqual(register_response.status_code, 200) self.assertEqual(register_response.status_code, 200)
self.assertIn('currentProvider": "LTI Test Tool Consumer"', register_response.content) self.assertIn('"currentProvider": "LTI Test Tool Consumer"', register_response.content)
self.assertIn('"errorMessage": null', register_response.content) self.assertIn('"errorMessage": null', register_response.content)
# Now complete the form: # Now complete the form:
ajax_register_response = self.client.post( ajax_register_response = self.client.post(
...@@ -153,7 +153,7 @@ class IntegrationTestLTI(testutil.TestCase): ...@@ -153,7 +153,7 @@ class IntegrationTestLTI(testutil.TestCase):
register_response = self.client.get(login_response['Location']) register_response = self.client.get(login_response['Location'])
self.assertEqual(register_response.status_code, 200) self.assertEqual(register_response.status_code, 200)
self.assertIn( self.assertIn(
'currentProvider": "Tool Consumer with Secret in Settings"', '"currentProvider": "Tool Consumer with Secret in Settings"',
register_response.content register_response.content
) )
self.assertIn('"errorMessage": null', register_response.content) self.assertIn('"errorMessage": null', register_response.content)
""" """
Third_party_auth integration tests using a mock version of the TestShib provider Third_party_auth integration tests using a mock version of the TestShib provider
""" """
from django.core.urlresolvers import reverse
import json
import unittest
import httpretty import httpretty
from mock import patch from mock import patch
from django.core.urlresolvers import reverse
from openedx.core.lib.json_utils import EscapedEdxJSONEncoder
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from third_party_auth.tasks import fetch_saml_metadata from third_party_auth.tasks import fetch_saml_metadata
from third_party_auth.tests import testutil from third_party_auth.tests import testutil
import unittest
TESTSHIB_ENTITY_ID = 'https://idp.testshib.org/idp/shibboleth' TESTSHIB_ENTITY_ID = 'https://idp.testshib.org/idp/shibboleth'
TESTSHIB_METADATA_URL = 'https://mock.testshib.org/metadata/testshib-providers.xml' TESTSHIB_METADATA_URL = 'https://mock.testshib.org/metadata/testshib-providers.xml'
...@@ -81,11 +88,11 @@ class TestShibIntegrationTest(testutil.SAMLTestCase): ...@@ -81,11 +88,11 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
# We'd now like to see if the "You've successfully signed into TestShib" message is # We'd now like to see if the "You've successfully signed into TestShib" message is
# shown, but it's managed by a JavaScript runtime template, and we can't run JS in this # shown, but it's managed by a JavaScript runtime template, and we can't run JS in this
# type of test, so we just check for the variable that triggers that message. # type of test, so we just check for the variable that triggers that message.
self.assertIn('"currentProvider": "TestShib"', register_response.content) self.assertIn('"currentProvider": "TestShib"', register_response.content)
self.assertIn('"errorMessage": null', register_response.content) self.assertIn('"errorMessage": null', register_response.content)
# Now do a crude check that the data (e.g. email) from the provider is displayed in the form: # Now do a crude check that the data (e.g. email) from the provider is displayed in the form:
self.assertIn('"defaultValue": "myself@testshib.org"', register_response.content) self.assertIn('"defaultValue": "myself@testshib.org"', register_response.content)
self.assertIn('"defaultValue": "Me Myself And I"', register_response.content) self.assertIn('"defaultValue": "Me Myself And I"', register_response.content)
# Now complete the form: # Now complete the form:
ajax_register_response = self.client.post( ajax_register_response = self.client.post(
reverse('user_api_registration'), reverse('user_api_registration'),
...@@ -128,8 +135,8 @@ class TestShibIntegrationTest(testutil.SAMLTestCase): ...@@ -128,8 +135,8 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
# We'd now like to see if the "You've successfully signed into TestShib" message is # We'd now like to see if the "You've successfully signed into TestShib" message is
# shown, but it's managed by a JavaScript runtime template, and we can't run JS in this # shown, but it's managed by a JavaScript runtime template, and we can't run JS in this
# type of test, so we just check for the variable that triggers that message. # type of test, so we just check for the variable that triggers that message.
self.assertIn('"currentProvider": "TestShib"', login_response.content) self.assertIn('"currentProvider": "TestShib"', login_response.content)
self.assertIn('"errorMessage": null', login_response.content) self.assertIn('"errorMessage": null', login_response.content)
# Now the user enters their username and password. # Now the user enters their username and password.
# The AJAX on the page will log them in: # The AJAX on the page will log them in:
ajax_login_response = self.client.post( ajax_login_response = self.client.post(
...@@ -183,7 +190,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase): ...@@ -183,7 +190,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
response = self.client.get(self.login_page_url) response = self.client.get(self.login_page_url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertIn("TestShib", response.content) self.assertIn("TestShib", response.content)
self.assertIn(TPA_TESTSHIB_LOGIN_URL.replace('&', '&'), response.content) self.assertIn(json.dumps(TPA_TESTSHIB_LOGIN_URL, cls=EscapedEdxJSONEncoder), response.content)
return response return response
def _check_register_page(self): def _check_register_page(self):
...@@ -191,7 +198,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase): ...@@ -191,7 +198,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
response = self.client.get(self.register_page_url) response = self.client.get(self.register_page_url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertIn("TestShib", response.content) self.assertIn("TestShib", response.content)
self.assertIn(TPA_TESTSHIB_REGISTER_URL.replace('&', '&'), response.content) self.assertIn(json.dumps(TPA_TESTSHIB_REGISTER_URL, cls=EscapedEdxJSONEncoder), response.content)
return response return response
def _configure_testshib_provider(self, **kwargs): def _configure_testshib_provider(self, **kwargs):
......
...@@ -8,7 +8,6 @@ import json ...@@ -8,7 +8,6 @@ import json
import mock import mock
import ddt import ddt
import markupsafe
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core import mail from django.core import mail
...@@ -20,6 +19,7 @@ from django.test.client import RequestFactory ...@@ -20,6 +19,7 @@ from django.test.client import RequestFactory
from openedx.core.djangoapps.user_api.accounts.api import activate_account, create_account from openedx.core.djangoapps.user_api.accounts.api import activate_account, create_account
from openedx.core.djangoapps.user_api.accounts import EMAIL_MAX_LENGTH from openedx.core.djangoapps.user_api.accounts import EMAIL_MAX_LENGTH
from openedx.core.lib.json_utils import EscapedEdxJSONEncoder
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from student_account.views import account_settings_context from student_account.views import account_settings_context
from third_party_auth.tests.testutil import simulate_running_pipeline, ThirdPartyAuthTestMixin from third_party_auth.tests.testutil import simulate_running_pipeline, ThirdPartyAuthTestMixin
...@@ -223,7 +223,7 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi ...@@ -223,7 +223,7 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
@ddt.unpack @ddt.unpack
def test_login_and_registration_form(self, url_name, initial_mode): def test_login_and_registration_form(self, url_name, initial_mode):
response = self.client.get(reverse(url_name)) response = self.client.get(reverse(url_name))
expected_data = u"data-initial-mode=\"{mode}\"".format(mode=initial_mode) expected_data = '"initial_mode": "{mode}"'.format(mode=initial_mode)
self.assertContains(response, expected_data) self.assertContains(response, expected_data)
@ddt.data("signin_user", "register_user") @ddt.data("signin_user", "register_user")
...@@ -255,6 +255,7 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi ...@@ -255,6 +255,7 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
# that preserves the querystring params # that preserves the querystring params
with mock.patch.dict(settings.FEATURES, {'IS_EDX_DOMAIN': is_edx_domain}): with mock.patch.dict(settings.FEATURES, {'IS_EDX_DOMAIN': is_edx_domain}):
response = self.client.get(reverse(url_name), params) response = self.client.get(reverse(url_name), params)
expected_url = '/login?{}'.format(self._finish_auth_url_param(params + [('next', '/dashboard')])) expected_url = '/login?{}'.format(self._finish_auth_url_param(params + [('next', '/dashboard')]))
self.assertContains(response, expected_url) self.assertContains(response, expected_url)
...@@ -330,7 +331,7 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi ...@@ -330,7 +331,7 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
def test_hinted_login(self): def test_hinted_login(self):
params = [("next", "/courses/something/?tpa_hint=oa2-google-oauth2")] params = [("next", "/courses/something/?tpa_hint=oa2-google-oauth2")]
response = self.client.get(reverse('signin_user'), params) response = self.client.get(reverse('signin_user'), params)
self.assertContains(response, "data-third-party-auth-hint='oa2-google-oauth2'") self.assertContains(response, '"third_party_auth_hint": "oa2-google-oauth2"')
@override_settings(SITE_NAME=settings.MICROSITE_TEST_HOSTNAME) @override_settings(SITE_NAME=settings.MICROSITE_TEST_HOSTNAME)
def test_microsite_uses_old_login_page(self): def test_microsite_uses_old_login_page(self):
...@@ -358,17 +359,17 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi ...@@ -358,17 +359,17 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
finish_auth_url = None finish_auth_url = None
if current_backend: if current_backend:
finish_auth_url = reverse("social:complete", kwargs={"backend": current_backend}) + "?" finish_auth_url = reverse("social:complete", kwargs={"backend": current_backend}) + "?"
auth_info = markupsafe.escape(
json.dumps({
"currentProvider": current_provider,
"providers": providers,
"secondaryProviders": [],
"finishAuthUrl": finish_auth_url,
"errorMessage": None,
})
)
expected_data = u"data-third-party-auth='{auth_info}'".format( auth_info = {
"currentProvider": current_provider,
"providers": providers,
"secondaryProviders": [],
"finishAuthUrl": finish_auth_url,
"errorMessage": None,
}
auth_info = json.dumps(auth_info, cls=EscapedEdxJSONEncoder)
expected_data = '"third_party_auth": {auth_info}'.format(
auth_info=auth_info auth_info=auth_info
) )
......
...@@ -95,22 +95,25 @@ def login_and_registration_form(request, initial_mode="login"): ...@@ -95,22 +95,25 @@ def login_and_registration_form(request, initial_mode="login"):
# Otherwise, render the combined login/registration page # Otherwise, render the combined login/registration page
context = { context = {
'login_redirect_url': redirect_to, # This gets added to the query string of the "Sign In" button in the header 'data': {
'disable_courseware_js': True, 'login_redirect_url': redirect_to,
'initial_mode': initial_mode, 'initial_mode': initial_mode,
'third_party_auth': json.dumps(_third_party_auth_context(request, redirect_to)), 'third_party_auth': _third_party_auth_context(request, redirect_to),
'third_party_auth_hint': third_party_auth_hint or '', 'third_party_auth_hint': third_party_auth_hint or '',
'platform_name': settings.PLATFORM_NAME, 'platform_name': settings.PLATFORM_NAME,
# Include form descriptions retrieved from the user API.
# We could have the JS client make these requests directly,
# but we include them in the initial page load to avoid
# the additional round-trip to the server.
'login_form_desc': json.loads(form_descriptions['login']),
'registration_form_desc': json.loads(form_descriptions['registration']),
'password_reset_form_desc': json.loads(form_descriptions['password_reset']),
},
'login_redirect_url': redirect_to, # This gets added to the query string of the "Sign In" button in header
'responsive': True, 'responsive': True,
'allow_iframing': True, 'allow_iframing': True,
'disable_courseware_js': True,
# Include form descriptions retrieved from the user API.
# We could have the JS client make these requests directly,
# but we include them in the initial page load to avoid
# the additional round-trip to the server.
'login_form_desc': form_descriptions['login'],
'registration_form_desc': form_descriptions['registration'],
'password_reset_form_desc': form_descriptions['password_reset'],
} }
return render_to_response('student_account/login_and_register.html', context) return render_to_response('student_account/login_and_register.html', context)
......
...@@ -1303,26 +1303,6 @@ instructor_dash_js = ( ...@@ -1303,26 +1303,6 @@ instructor_dash_js = (
sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/instructor_dashboard/**/*.js')) sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/instructor_dashboard/**/*.js'))
) )
# JavaScript used by the student account and profile pages
# These are not courseware, so they do not need many of the courseware-specific
# JavaScript modules.
student_account_js = [
'js/utils/edx.utils.validate.js',
'js/sticky_filter.js',
'js/query-params.js',
'js/student_account/models/LoginModel.js',
'js/student_account/models/RegisterModel.js',
'js/student_account/models/PasswordResetModel.js',
'js/student_account/views/FormView.js',
'js/student_account/views/LoginView.js',
'js/student_account/views/HintedLoginView.js',
'js/student_account/views/RegisterView.js',
'js/student_account/views/PasswordResetView.js',
'js/student_account/views/AccessView.js',
'js/student_account/views/InstitutionLoginView.js',
'js/student_account/accessApp.js',
]
verify_student_js = [ verify_student_js = [
'js/sticky_filter.js', 'js/sticky_filter.js',
'js/query-params.js', 'js/query-params.js',
...@@ -1574,10 +1554,6 @@ PIPELINE_JS = { ...@@ -1574,10 +1554,6 @@ PIPELINE_JS = {
'source_filenames': dashboard_js, 'source_filenames': dashboard_js,
'output_filename': 'js/dashboard.js' 'output_filename': 'js/dashboard.js'
}, },
'student_account': {
'source_filenames': student_account_js,
'output_filename': 'js/student_account.js'
},
'verify_student': { 'verify_student': {
'source_filenames': verify_student_js, 'source_filenames': verify_student_js,
'output_filename': 'js/verify_student.js' 'output_filename': 'js/verify_student.js'
......
...@@ -75,16 +75,6 @@ ...@@ -75,16 +75,6 @@
'js/views/file_uploader': 'js/views/file_uploader', 'js/views/file_uploader': 'js/views/file_uploader',
'js/views/notification': 'js/views/notification', 'js/views/notification': 'js/views/notification',
'js/student_account/account': 'js/student_account/account', '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/views/InstitutionLoginView': 'js/student_account/views/InstitutionLoginView',
'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_account/views/HintedLoginView': 'js/student_account/views/HintedLoginView',
'js/student_profile/views/learner_profile_fields': 'js/student_profile/views/learner_profile_fields', 'js/student_profile/views/learner_profile_fields': 'js/student_profile/views/learner_profile_fields',
'js/student_profile/views/learner_profile_factory': 'js/student_profile/views/learner_profile_factory', 'js/student_profile/views/learner_profile_factory': 'js/student_profile/views/learner_profile_factory',
'js/student_profile/views/learner_profile_view': 'js/student_profile/views/learner_profile_view', 'js/student_profile/views/learner_profile_view': 'js/student_profile/views/learner_profile_view',
...@@ -94,7 +84,10 @@ ...@@ -94,7 +84,10 @@
'DiscussionModuleView': 'xmodule_js/common_static/coffee/src/discussion/discussion_module_view', 'DiscussionModuleView': 'xmodule_js/common_static/coffee/src/discussion/discussion_module_view',
// edxnotes // edxnotes
'annotator_1.2.9': 'xmodule_js/common_static/js/vendor/edxnotes/annotator-full.min' 'annotator_1.2.9': 'xmodule_js/common_static/js/vendor/edxnotes/annotator-full.min',
// Common edx utils
'js/utils/edx.utils.validate': 'xmodule_js/common_static/js/utils/edx.utils.validate'
}, },
shim: { shim: {
'gettext': { 'gettext': {
...@@ -337,91 +330,6 @@ ...@@ -337,91 +330,6 @@
'js/models/notification', 'jquery.fileupload' 'js/models/notification', 'jquery.fileupload'
] ]
}, },
// Student account registration/login
// Loaded explicitly until these are converted to RequireJS
'js/student_account/views/FormView': {
exports: 'edx.student.account.FormView',
deps: ['jquery', 'underscore', 'backbone', 'gettext']
},
'js/student_account/models/LoginModel': {
exports: 'edx.student.account.LoginModel',
deps: ['jquery', 'jquery.cookie', 'backbone']
},
'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'
]
},
'js/student_account/views/InstitutionLoginView': {
exports: 'edx.student.account.InstitutionLoginView',
deps: [
'jquery',
'underscore',
'backbone'
]
},
'js/student_account/models/PasswordResetModel': {
exports: 'edx.student.account.PasswordResetModel',
deps: ['jquery', 'jquery.cookie', 'backbone']
},
'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: 'edx.student.account.RegisterModel',
deps: ['jquery', 'jquery.cookie', 'backbone']
},
'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'
]
},
'js/student_account/views/HintedLoginView': {
exports: 'edx.student.account.HintedLoginView',
deps: [
'jquery',
'underscore',
'backbone',
'gettext'
]
},
'js/student_account/views/AccessView': {
exports: 'edx.student.account.AccessView',
deps: [
'jquery',
'underscore',
'backbone',
'history',
'utility',
'js/student_account/views/LoginView',
'js/student_account/views/PasswordResetView',
'js/student_account/views/RegisterView',
'js/student_account/views/InstitutionLoginView',
'js/student_account/models/LoginModel',
'js/student_account/models/PasswordResetModel',
'js/student_account/models/RegisterModel',
'js/student_account/views/FormView'
]
},
'js/verify_student/models/verification_model': { 'js/verify_student/models/verification_model': {
exports: 'edx.verify_student.VerificationModel', exports: 'edx.verify_student.VerificationModel',
deps: [ 'jquery', 'underscore', 'backbone', 'jquery.cookie' ] deps: [ 'jquery', 'underscore', 'backbone', 'jquery.cookie' ]
...@@ -731,6 +639,7 @@ ...@@ -731,6 +639,7 @@
'lms/include/js/spec/instructor_dashboard/student_admin_spec.js', 'lms/include/js/spec/instructor_dashboard/student_admin_spec.js',
'lms/include/js/spec/student_account/account_spec.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/logistration_factory_spec.js',
'lms/include/js/spec/student_account/finish_auth_spec.js', 'lms/include/js/spec/student_account/finish_auth_spec.js',
'lms/include/js/spec/student_account/hinted_login_spec.js', 'lms/include/js/spec/student_account/hinted_login_spec.js',
'lms/include/js/spec/student_account/login_spec.js', 'lms/include/js/spec/student_account/login_spec.js',
......
define([ ;(function (define) {
'jquery', 'use strict';
'common/js/spec_helpers/template_helpers', define([
'common/js/spec_helpers/ajax_helpers', 'jquery',
'js/student_account/views/AccessView', 'underscore',
'js/student_account/views/FormView', 'backbone',
'js/student_account/enrollment', 'common/js/spec_helpers/template_helpers',
'js/student_account/shoppingcart', 'common/js/spec_helpers/ajax_helpers',
'js/student_account/emailoptin' 'js/student_account/views/AccessView',
], function($, TemplateHelpers, AjaxHelpers, AccessView, FormView, EnrollmentInterface, ShoppingCartInterface) { 'js/student_account/views/FormView',
"use strict"; 'js/student_account/enrollment',
'js/student_account/shoppingcart',
'js/student_account/emailoptin'
],
function($, _, Backbone, TemplateHelpers, AjaxHelpers, AccessView, FormView, EnrollmentInterface,
ShoppingCartInterface) {
describe('edx.student.account.AccessView', function() { describe('edx.student.account.AccessView', function() {
var requests = null, var requests = null,
view = null, view = null,
...@@ -24,7 +30,7 @@ define([ ...@@ -24,7 +30,7 @@ define([
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',
...@@ -49,24 +55,27 @@ define([ ...@@ -49,24 +55,27 @@ define([
THIRD_PARTY_COMPLETE_URL = '/auth/complete/provider/'; THIRD_PARTY_COMPLETE_URL = '/auth/complete/provider/';
var ajaxSpyAndInitialize = function(that, mode, nextUrl, finishAuthUrl) { var ajaxSpyAndInitialize = function(that, mode, nextUrl, finishAuthUrl) {
var options = {
initial_mode: mode,
third_party_auth: {
currentProvider: null,
providers: [],
secondaryProviders: [{name: "provider"}],
finishAuthUrl: finishAuthUrl
},
login_redirect_url: nextUrl, // undefined for default
platform_name: 'edX',
login_form_desc: FORM_DESCRIPTION,
registration_form_desc: FORM_DESCRIPTION,
password_reset_form_desc: FORM_DESCRIPTION
},
$logistrationElement = $('#login-and-registration-container');
// Spy on AJAX requests // Spy on AJAX requests
requests = AjaxHelpers.requests(that); requests = AjaxHelpers.requests(that);
// Initialize the access view // Initialize the access view
view = new AccessView({ view = new AccessView(_.extend(options, {el: $logistrationElement}));
mode: mode,
thirdPartyAuth: {
currentProvider: null,
providers: [],
secondaryProviders: [{name: "provider"}],
finishAuthUrl: finishAuthUrl
},
nextUrl: nextUrl, // undefined for default
platformName: 'edX',
loginFormDesc: FORM_DESCRIPTION,
registrationFormDesc: FORM_DESCRIPTION,
passwordResetFormDesc: FORM_DESCRIPTION
});
// Mock the redirect call // Mock the redirect call
spyOn( view, 'redirect' ).andCallFake( function() {} ); spyOn( view, 'redirect' ).andCallFake( function() {} );
...@@ -92,7 +101,7 @@ define([ ...@@ -92,7 +101,7 @@ define([
}; };
beforeEach(function() { beforeEach(function() {
setFixtures('<div id="login-and-registration-container"></div>'); setFixtures('<div id="login-and-registration-container" class="login-register" />');
TemplateHelpers.installTemplate('templates/student_account/access'); TemplateHelpers.installTemplate('templates/student_account/access');
TemplateHelpers.installTemplate('templates/student_account/login'); TemplateHelpers.installTemplate('templates/student_account/login');
TemplateHelpers.installTemplate('templates/student_account/register'); TemplateHelpers.installTemplate('templates/student_account/register');
...@@ -105,6 +114,10 @@ define([ ...@@ -105,6 +114,10 @@ define([
window.analytics = jasmine.createSpyObj('analytics', ['track', 'page', 'pageview', 'trackLink']); window.analytics = jasmine.createSpyObj('analytics', ['track', 'page', 'pageview', 'trackLink']);
}); });
afterEach(function() {
Backbone.history.stop();
});
it('can initially display the login form', function() { it('can initially display the login form', function() {
ajaxSpyAndInitialize(this, 'login'); ajaxSpyAndInitialize(this, 'login');
...@@ -217,5 +230,5 @@ define([ ...@@ -217,5 +230,5 @@ define([
}); });
}); });
} });
); }).call(this, define || RequireJS.define);
define([ ;(function (define) {
'jquery', 'use strict';
'utility', define([
'common/js/spec_helpers/ajax_helpers', 'jquery',
'js/student_account/views/FinishAuthView', 'jquery.url',
'js/student_account/enrollment', 'utility',
'js/student_account/shoppingcart', 'common/js/spec_helpers/ajax_helpers',
'js/student_account/emailoptin' 'js/student_account/views/FinishAuthView',
], function($, utility, AjaxHelpers, FinishAuthView, EnrollmentInterface, ShoppingCartInterface, EmailOptInInterface) { 'js/student_account/enrollment',
'use strict'; 'js/student_account/shoppingcart',
'js/student_account/emailoptin'
],
function($, url, utility, AjaxHelpers, FinishAuthView, EnrollmentInterface, ShoppingCartInterface,
EmailOptInInterface) {
describe('FinishAuthView', function() { describe('FinishAuthView', function() {
var requests = null, var requests = null,
view = null, view = null,
...@@ -167,5 +172,5 @@ define([ ...@@ -167,5 +172,5 @@ define([
expect( view.redirect ).toHaveBeenCalledWith( "/dashboard" ); expect( view.redirect ).toHaveBeenCalledWith( "/dashboard" );
}); });
}); });
} });
); }).call(this, define || RequireJS.define);
define([ ;(function (define) {
'jquery',
'underscore',
'common/js/spec_helpers/template_helpers',
'common/js/spec_helpers/ajax_helpers',
'js/student_account/views/HintedLoginView',
], function($, _, TemplateHelpers, AjaxHelpers, HintedLoginView) {
'use strict'; 'use strict';
describe('edx.student.account.HintedLoginView', function() { define([
'jquery',
'underscore',
'common/js/spec_helpers/template_helpers',
'common/js/spec_helpers/ajax_helpers',
'js/student_account/views/HintedLoginView'
],
function($, _, TemplateHelpers, AjaxHelpers, HintedLoginView) {
var view = null, describe('edx.student.account.HintedLoginView', function() {
requests = null, var view = null,
PLATFORM_NAME = 'edX', requests = null,
THIRD_PARTY_AUTH = { PLATFORM_NAME = 'edX',
currentProvider: null, THIRD_PARTY_AUTH = {
providers: [ currentProvider: null,
{ providers: [
id: 'oa2-google-oauth2', {
name: 'Google', id: 'oa2-google-oauth2',
iconClass: 'fa-google-plus', name: 'Google',
loginUrl: '/auth/login/google-oauth2/?auth_entry=account_login', iconClass: 'fa-google-plus',
registerUrl: '/auth/login/google-oauth2/?auth_entry=account_register' loginUrl: '/auth/login/google-oauth2/?auth_entry=account_login',
}, registerUrl: '/auth/login/google-oauth2/?auth_entry=account_register'
{ },
id: 'oa2-facebook', {
name: 'Facebook', id: 'oa2-facebook',
iconClass: 'fa-facebook', name: 'Facebook',
loginUrl: '/auth/login/facebook/?auth_entry=account_login', iconClass: 'fa-facebook',
registerUrl: '/auth/login/facebook/?auth_entry=account_register' loginUrl: '/auth/login/facebook/?auth_entry=account_login',
} registerUrl: '/auth/login/facebook/?auth_entry=account_register'
], }
secondaryProviders: [ ],
{ secondaryProviders: [
id: 'saml-harvard', {
name: 'Harvard', id: 'saml-harvard',
iconClass: 'fa-university', name: 'Harvard',
loginUrl: '/auth/login/tpa-saml/?auth_entry=account_login&idp=harvard', iconClass: 'fa-university',
registerUrl: '/auth/login/tpa-saml/?auth_entry=account_register&idp=harvard' loginUrl: '/auth/login/tpa-saml/?auth_entry=account_login&idp=harvard',
} registerUrl: '/auth/login/tpa-saml/?auth_entry=account_register&idp=harvard'
] }
}; ]
};
var createHintedLoginView = function(hintedProvider) { var createHintedLoginView = function(hintedProvider) {
// Initialize the login view // Initialize the login view
view = new HintedLoginView({ view = new HintedLoginView({
thirdPartyAuth: THIRD_PARTY_AUTH, thirdPartyAuth: THIRD_PARTY_AUTH,
hintedProvider: hintedProvider, hintedProvider: hintedProvider,
platformName: PLATFORM_NAME platformName: PLATFORM_NAME
}); });
// Mock the redirect call // Mock the redirect call
spyOn( view, 'redirect' ).andCallFake( function() {} ); spyOn( view, 'redirect' ).andCallFake( function() {} );
view.render(); view.render();
}; };
beforeEach(function() { beforeEach(function() {
setFixtures('<div id="hinted-login-form"></div>'); setFixtures('<div id="hinted-login-form"></div>');
TemplateHelpers.installTemplate('templates/student_account/hinted_login'); TemplateHelpers.installTemplate('templates/student_account/hinted_login');
}); });
it('displays a choice as two buttons', function() { it('displays a choice as two buttons', function() {
createHintedLoginView("oa2-google-oauth2"); createHintedLoginView("oa2-google-oauth2");
expect($('.proceed-button.button-oa2-google-oauth2')).toBeVisible(); expect($('.proceed-button.button-oa2-google-oauth2')).toBeVisible();
expect($('.form-toggle')).toBeVisible(); expect($('.form-toggle')).toBeVisible();
expect($('.proceed-button.button-oa2-facebook')).not.toBeVisible(); expect($('.proceed-button.button-oa2-facebook')).not.toBeVisible();
}); });
it('works with secondary providers as well', function() { it('works with secondary providers as well', function() {
createHintedLoginView("saml-harvard"); createHintedLoginView("saml-harvard");
expect($('.proceed-button.button-saml-harvard')).toBeVisible(); expect($('.proceed-button.button-saml-harvard')).toBeVisible();
expect($('.form-toggle')).toBeVisible(); expect($('.form-toggle')).toBeVisible();
expect($('.proceed-button.button-oa2-google-oauth2')).not.toBeVisible(); expect($('.proceed-button.button-oa2-google-oauth2')).not.toBeVisible();
}); });
it('redirects the user to the hinted provider if the user clicks the proceed button', function() { it('redirects the user to the hinted provider if the user clicks the proceed button', function() {
createHintedLoginView("oa2-google-oauth2"); createHintedLoginView('oa2-google-oauth2');
// Click the "Yes, proceed" button // Click the "Yes, proceed" button
$('.proceed-button').click(); $('.proceed-button').click();
expect(view.redirect).toHaveBeenCalledWith( '/auth/login/google-oauth2/?auth_entry=account_login' ); expect(view.redirect).toHaveBeenCalledWith( '/auth/login/google-oauth2/?auth_entry=account_login' );
});
}); });
}); });
}); }).call(this, define || RequireJS.define);
define([ ;(function (define) {
'jquery',
'underscore',
'common/js/spec_helpers/template_helpers',
'js/student_account/views/InstitutionLoginView',
], function($, _, TemplateHelpers, InstitutionLoginView) {
'use strict'; 'use strict';
describe('edx.student.account.InstitutionLoginView', function() { define([
'jquery',
'underscore',
'common/js/spec_helpers/template_helpers',
'js/student_account/views/InstitutionLoginView'
],
function($, _, TemplateHelpers, InstitutionLoginView) {
var view = null, describe('edx.student.account.InstitutionLoginView', function() {
PLATFORM_NAME = 'edX', var view = null,
THIRD_PARTY_AUTH = { PLATFORM_NAME = 'edX',
currentProvider: null, THIRD_PARTY_AUTH = {
providers: [], currentProvider: null,
secondaryProviders: [ providers: [],
{ secondaryProviders: [
id: 'oa2-google-oauth2', {
name: 'Google', id: 'oa2-google-oauth2',
iconClass: 'fa-google-plus', name: 'Google',
loginUrl: '/auth/login/google-oauth2/?auth_entry=account_login', iconClass: 'fa-google-plus',
registerUrl: '/auth/login/google-oauth2/?auth_entry=account_register' loginUrl: '/auth/login/google-oauth2/?auth_entry=account_login',
}, registerUrl: '/auth/login/google-oauth2/?auth_entry=account_register'
{ },
id: 'oa2-facebook', {
name: 'Facebook', id: 'oa2-facebook',
iconClass: 'fa-facebook', name: 'Facebook',
loginUrl: '/auth/login/facebook/?auth_entry=account_login', iconClass: 'fa-facebook',
registerUrl: '/auth/login/facebook/?auth_entry=account_register' loginUrl: '/auth/login/facebook/?auth_entry=account_login',
} registerUrl: '/auth/login/facebook/?auth_entry=account_register'
] }
]
};
var createInstLoginView = function(mode) {
// Initialize the login view
view = new InstitutionLoginView({
mode: mode,
thirdPartyAuth: THIRD_PARTY_AUTH,
platformName: PLATFORM_NAME
});
view.render();
}; };
var createInstLoginView = function(mode) { beforeEach(function() {
// Initialize the login view setFixtures('<div id="institution_login-form"></div>');
view = new InstitutionLoginView({ TemplateHelpers.installTemplate('templates/student_account/institution_login');
mode: mode, TemplateHelpers.installTemplate('templates/student_account/institution_register');
thirdPartyAuth: THIRD_PARTY_AUTH,
platformName: PLATFORM_NAME
}); });
view.render();
};
beforeEach(function() { it('displays a list of providers', function() {
setFixtures('<div id="institution_login-form"></div>'); var $google, $facebook;
TemplateHelpers.installTemplate('templates/student_account/institution_login');
TemplateHelpers.installTemplate('templates/student_account/institution_register');
});
it('displays a list of providers', function() { createInstLoginView('login');
createInstLoginView('login'); expect($('#institution_login-form').html()).not.toBe("");
expect($('#institution_login-form').html()).not.toBe(""); $google = $('li a:contains("Google")');
var $google = $('li a:contains("Google")'); expect($google).toBeVisible();
expect($google).toBeVisible(); expect($google).toHaveAttr(
expect($google).toHaveAttr( 'href', '/auth/login/google-oauth2/?auth_entry=account_login'
'href', '/auth/login/google-oauth2/?auth_entry=account_login' );
); $facebook = $('li a:contains("Facebook")');
var $facebook = $('li a:contains("Facebook")'); expect($facebook).toBeVisible();
expect($facebook).toBeVisible(); expect($facebook).toHaveAttr(
expect($facebook).toHaveAttr( 'href', '/auth/login/facebook/?auth_entry=account_login'
'href', '/auth/login/facebook/?auth_entry=account_login' );
); });
});
it('displays a list of providers', function() { it('displays a list of providers', function() {
createInstLoginView('register'); var $google, $facebook;
expect($('#institution_login-form').html()).not.toBe("");
var $google = $('li a:contains("Google")'); createInstLoginView('register');
expect($google).toBeVisible(); expect($('#institution_login-form').html()).not.toBe("");
expect($google).toHaveAttr( $google = $('li a:contains("Google")');
'href', '/auth/login/google-oauth2/?auth_entry=account_register' expect($google).toBeVisible();
); expect($google).toHaveAttr(
var $facebook = $('li a:contains("Facebook")'); 'href', '/auth/login/google-oauth2/?auth_entry=account_register'
expect($facebook).toBeVisible(); );
expect($facebook).toHaveAttr( $facebook = $('li a:contains("Facebook")');
'href', '/auth/login/facebook/?auth_entry=account_register' expect($facebook).toBeVisible();
); expect($facebook).toHaveAttr(
}); 'href', '/auth/login/facebook/?auth_entry=account_register'
);
});
});
}); });
}); }).call(this, define || RequireJS.define);
;(function (define) {
'use strict';
define([
'jquery',
'underscore',
'backbone',
'common/js/spec_helpers/template_helpers',
'common/js/spec_helpers/ajax_helpers',
'js/student_account/logistration_factory'
],
function($, _, Backbone, TemplateHelpers, AjaxHelpers, LogistrationFactory) {
describe('Logistration Factory', function() {
var FORM_DESCRIPTION = {
method: 'post',
submit_url: '/submit',
fields: [
{
name: 'email',
label: 'Email',
defaultValue: '',
type: 'text',
required: true,
placeholder: 'xsy@edx.org',
instructions: 'Enter your email here.',
restrictions: {}
},
{
name: 'username',
label: 'Username',
defaultValue: '',
type: 'text',
required: true,
placeholder: 'Xsy',
instructions: 'Enter your username here.',
restrictions: {
max_length: 200
}
}
]
};
var initializeLogistrationFactory = function(that, mode, nextUrl, finishAuthUrl) {
var options = {
initial_mode: mode,
third_party_auth: {
currentProvider: null,
providers: [],
secondaryProviders: [{name: 'provider'}],
finishAuthUrl: finishAuthUrl
},
login_redirect_url: nextUrl, // undefined for default
platform_name: 'edX',
login_form_desc: FORM_DESCRIPTION,
registration_form_desc: FORM_DESCRIPTION,
password_reset_form_desc: FORM_DESCRIPTION
};
// Initialize the logistration Factory
LogistrationFactory(options);
};
var assertForms = function(visibleForm, hiddenFormsList) {
expect($(visibleForm)).not.toHaveClass('hidden');
_.each(hiddenFormsList, function (hiddenForm) {
expect($(hiddenForm)).toHaveClass('hidden');
}, this);
};
beforeEach(function() {
setFixtures('<div id="login-and-registration-container" class="login-register" />');
TemplateHelpers.installTemplate('templates/student_account/access');
TemplateHelpers.installTemplate('templates/student_account/form_field');
TemplateHelpers.installTemplate('templates/student_account/login');
TemplateHelpers.installTemplate('templates/student_account/register');
TemplateHelpers.installTemplate('templates/student_account/password_reset')
});
afterEach(function() {
Backbone.history.stop();
});
it('can initially render the login form', function() {
var hiddenFormsList;
initializeLogistrationFactory(this, 'login');
/* Verify that only login form is expanded, and that the
/* all other logistration forms are collapsed.
*/
hiddenFormsList = [
'#register-form',
'#password-reset-form'
];
assertForms('#login-form', hiddenFormsList);
});
it('can initially render the registration form', function() {
var hiddenFormsList;
initializeLogistrationFactory(this, 'register');
/* Verify that only registration form is expanded, and that the
/* all other logistration forms are collapsed.
*/
hiddenFormsList = [
'#login-form',
'#password-reset-form'
];
assertForms('#register-form', hiddenFormsList);
});
it('can initially render the password reset form', function() {
var hiddenFormsList;
initializeLogistrationFactory(this, 'reset');
/* Verify that only password reset form is expanded, and that the
/* all other logistration forms are collapsed.
*/
hiddenFormsList = [
'#login-form',
'#register-form'
];
assertForms('#password-reset-form', hiddenFormsList);
});
});
});
}).call(this, define || RequireJS.define);
define([ ;(function (define) {
'jquery', 'use strict';
'underscore', define([
'common/js/spec_helpers/template_helpers', 'jquery',
'common/js/spec_helpers/ajax_helpers', 'underscore',
'js/student_account/models/PasswordResetModel', 'common/js/spec_helpers/template_helpers',
'js/student_account/views/PasswordResetView', 'common/js/spec_helpers/ajax_helpers',
], function($, _, TemplateHelpers, AjaxHelpers, PasswordResetModel, PasswordResetView) { 'js/student_account/models/PasswordResetModel',
describe('edx.student.account.PasswordResetView', function() { 'js/student_account/views/PasswordResetView'
'use strict'; ],
function($, _, TemplateHelpers, AjaxHelpers, PasswordResetModel, PasswordResetView) {
describe('edx.student.account.PasswordResetView', function() {
var model = null, var model = null,
view = null, view = null,
requests = null, requests = null,
...@@ -46,12 +48,12 @@ define([ ...@@ -46,12 +48,12 @@ define([
}; };
var submitEmail = function(validationSuccess) { var submitEmail = function(validationSuccess) {
// Simulate manual entry of an email address
$('#password-reset-email').val(EMAIL);
// Create a fake click event // Create a fake click event
var clickEvent = $.Event('click'); var clickEvent = $.Event('click');
// Simulate manual entry of an email address
$('#password-reset-email').val(EMAIL);
// If validationSuccess isn't passed, we avoid // If validationSuccess isn't passed, we avoid
// spying on `view.validate` twice // spying on `view.validate` twice
if ( !_.isUndefined(validationSuccess) ) { if ( !_.isUndefined(validationSuccess) ) {
...@@ -141,5 +143,5 @@ define([ ...@@ -141,5 +143,5 @@ define([
expect(view.$errors).toHaveClass('hidden'); expect(view.$errors).toHaveClass('hidden');
}); });
}); });
} });
); }).call(this, define || RequireJS.define);
var edx = edx || {};
(function($) {
'use strict';
edx.student = edx.student || {};
edx.student.account = edx.student.account || {};
var container = $('#login-and-registration-container');
return new edx.student.account.AccessView({
mode: container.data('initial-mode'),
thirdPartyAuth: container.data('third-party-auth'),
thirdPartyAuthHint: container.data('third-party-auth-hint'),
nextUrl: container.data('next-url'),
platformName: container.data('platform-name'),
loginFormDesc: container.data('login-form-desc'),
registrationFormDesc: container.data('registration-form-desc'),
passwordResetFormDesc: container.data('password-reset-form-desc')
});
})(jQuery);
;(function (define) {
'use strict';
define([
'jquery',
'js/student_account/views/AccessView'
],
function($, AccessView) {
return function(options) {
var $logistrationElement = $('#login-and-registration-container');
new AccessView(_.extend(options, {el: $logistrationElement}));
};
}
);
}).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function($, Backbone) {
'use strict'; 'use strict';
define([
'jquery',
'backbone',
'jquery.url'
], function ($, Backbone) {
return Backbone.Model.extend({
defaults: {
email: '',
password: '',
remember: false
},
ajaxType: '',
urlRoot: '',
initialize: function (attributes, options) {
this.ajaxType = options.method;
this.urlRoot = options.url;
},
sync: function (method, model) {
var headers = {'X-CSRFToken': $.cookie('csrftoken')},
data = {},
analytics,
courseId = $.url('?course_id');
// If there is a course ID in the query string param,
// send that to the server as well so it can be included
// in analytics events.
if (courseId) {
analytics = JSON.stringify({
enroll_course_id: decodeURIComponent(courseId)
});
}
edx.student = edx.student || {}; // Include all form fields and analytics info in the data sent to the server
edx.student.account = edx.student.account || {}; $.extend(data, model.attributes, {analytics: analytics});
edx.student.account.LoginModel = Backbone.Model.extend({ $.ajax({
url: model.urlRoot,
defaults: { type: model.ajaxType,
email: '', data: data,
password: '', headers: headers,
remember: false success: function () {
}, model.trigger('sync');
},
ajaxType: '', error: function (error) {
model.trigger('error', error);
urlRoot: '', }
initialize: function( attributes, options ) {
this.ajaxType = options.method;
this.urlRoot = options.url;
},
sync: function(method, model) {
var headers = { 'X-CSRFToken': $.cookie('csrftoken') },
data = {},
analytics,
courseId = $.url( '?course_id' );
// If there is a course ID in the query string param,
// send that to the server as well so it can be included
// in analytics events.
if ( courseId ) {
analytics = JSON.stringify({
enroll_course_id: decodeURIComponent( courseId )
}); });
} }
});
// Include all form fields and analytics info in the data sent to the server
$.extend( data, model.attributes, { analytics: analytics });
$.ajax({
url: model.urlRoot,
type: model.ajaxType,
data: data,
headers: headers,
success: function() {
model.trigger('sync');
},
error: function( error ) {
model.trigger('error', error);
}
});
}
}); });
})(jQuery, Backbone); }).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function($, Backbone) {
'use strict'; 'use strict';
define(['jquery', 'backbone'],
edx.student = edx.student || {}; function($, Backbone) {
edx.student.account = edx.student.account || {};
return Backbone.Model.extend({
edx.student.account.PasswordResetModel = Backbone.Model.extend({ defaults: {
email: ''
defaults: { },
email: '' ajaxType: '',
}, urlRoot: '',
ajaxType: '', initialize: function( attributes, options ) {
this.ajaxType = options.method;
urlRoot: '', this.urlRoot = options.url;
},
initialize: function( attributes, options ) {
this.ajaxType = options.method; sync: function( method, model ) {
this.urlRoot = options.url; var headers = {
}, 'X-CSRFToken': $.cookie('csrftoken')
};
sync: function( method, model ) {
var headers = { // Only expects an email address.
'X-CSRFToken': $.cookie('csrftoken') $.ajax({
}; url: model.urlRoot,
type: model.ajaxType,
// Only expects an email address. data: model.attributes,
$.ajax({ headers: headers,
url: model.urlRoot, success: function() {
type: model.ajaxType, model.trigger('sync');
data: model.attributes, },
headers: headers, error: function( error ) {
success: function() { model.trigger('error', error);
model.trigger('sync'); }
}, });
error: function( error ) { }
model.trigger('error', error); });
}
});
}
}); });
})(jQuery, Backbone); }).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function($, Backbone) {
'use strict'; 'use strict';
define(['jquery', 'backbone', 'jquery.url'],
function($, Backbone) {
return Backbone.Model.extend({
defaults: {
email: '',
name: '',
username: '',
password: '',
level_of_education: '',
gender: '',
year_of_birth: '',
mailing_address: '',
goals: ''
},
ajaxType: '',
urlRoot: '',
initialize: function( attributes, options ) {
this.ajaxType = options.method;
this.urlRoot = options.url;
},
sync: function(method, model) {
var headers = { 'X-CSRFToken': $.cookie('csrftoken') },
data = {},
courseId = $.url( '?course_id' );
// If there is a course ID in the query string param,
// send that to the server as well so it can be included
// in analytics events.
if ( courseId ) {
data.course_id = decodeURIComponent(courseId);
}
edx.student = edx.student || {}; // Include all form fields and analytics info in the data sent to the server
edx.student.account = edx.student.account || {}; $.extend( data, model.attributes);
edx.student.account.RegisterModel = Backbone.Model.extend({ $.ajax({
url: model.urlRoot,
defaults: { type: model.ajaxType,
email: '', data: data,
name: '', headers: headers,
username: '', success: function() {
password: '', model.trigger('sync');
level_of_education: '', },
gender: '', error: function( error ) {
year_of_birth: '', model.trigger('error', error);
mailing_address: '', }
goals: '', });
},
ajaxType: '',
urlRoot: '',
initialize: function( attributes, options ) {
this.ajaxType = options.method;
this.urlRoot = options.url;
},
sync: function(method, model) {
var headers = { 'X-CSRFToken': $.cookie('csrftoken') },
data = {},
courseId = $.url( '?course_id' );
// If there is a course ID in the query string param,
// send that to the server as well so it can be included
// in analytics events.
if ( courseId ) {
data.course_id = decodeURIComponent(courseId);
} }
});
// Include all form fields and analytics info in the data sent to the server
$.extend( data, model.attributes);
$.ajax({
url: model.urlRoot,
type: model.ajaxType,
data: data,
headers: headers,
success: function() {
model.trigger('sync');
},
error: function( error ) {
model.trigger('error', error);
}
});
}
}); });
})(jQuery, Backbone); }).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function($, _, gettext) {
'use strict'; 'use strict';
define(['jquery', 'underscore', 'backbone'],
edx.student = edx.student || {}; function($, _, Backbone) {
edx.student.account = edx.student.account || {};
return Backbone.View.extend({
edx.student.account.HintedLoginView = Backbone.View.extend({ el: '#hinted-login-form',
el: '#hinted-login-form',
tpl: '#hinted_login-tpl',
tpl: '#hinted_login-tpl',
events: {
events: { 'click .proceed-button': 'proceedWithHintedAuth'
'click .proceed-button': 'proceedWithHintedAuth' },
},
formType: 'hinted-login',
formType: 'hinted-login',
initialize: function( data ) {
initialize: function( data ) { this.tpl = $(this.tpl).html();
this.tpl = $(this.tpl).html(); this.hintedProvider = (
this.hintedProvider = ( _.findWhere(data.thirdPartyAuth.providers, {id: data.hintedProvider}) ||
_.findWhere(data.thirdPartyAuth.providers, {id: data.hintedProvider}) || _.findWhere(data.thirdPartyAuth.secondaryProviders, {id: data.hintedProvider})
_.findWhere(data.thirdPartyAuth.secondaryProviders, {id: data.hintedProvider}) );
); },
},
render: function() {
render: function() { $(this.el).html( _.template( this.tpl, {
$(this.el).html( _.template( this.tpl, { hintedProvider: this.hintedProvider
hintedProvider: this.hintedProvider }));
}));
return this;
return this; },
},
proceedWithHintedAuth: function( event ) {
proceedWithHintedAuth: function( event ) { this.redirect(this.hintedProvider.loginUrl);
this.redirect(this.hintedProvider.loginUrl); },
},
/**
/** * Redirect to a URL. Mainly useful for mocking out in tests.
* Redirect to a URL. Mainly useful for mocking out in tests. * @param {string} url The URL to redirect to.
* @param {string} url The URL to redirect to. */
*/ redirect: function( url ) {
redirect: function( url ) { window.location.href = url;
window.location.href = url; }
} });
}); });
})(jQuery, _, gettext); }).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function($, _, Backbone) {
'use strict'; 'use strict';
define(['jquery', 'underscore', 'backbone'],
function($, _, Backbone) {
edx.student = edx.student || {}; return Backbone.View.extend({
edx.student.account = edx.student.account || {}; el: '#institution_login-form',
edx.student.account.InstitutionLoginView = Backbone.View.extend({
el: '#institution_login-form',
initialize: function( data ) { initialize: function( data ) {
var tpl = data.mode == "register" ? '#institution_register-tpl' : '#institution_login-tpl'; var tpl = data.mode == "register" ? '#institution_register-tpl' : '#institution_login-tpl';
this.tpl = $(tpl).html(); this.tpl = $(tpl).html();
this.providers = data.thirdPartyAuth.secondaryProviders || []; this.providers = data.thirdPartyAuth.secondaryProviders || [];
this.platformName = data.platformName; this.platformName = data.platformName;
}, },
render: function() { render: function() {
$(this.el).html( _.template( this.tpl, { $(this.el).html( _.template( this.tpl, {
// We pass the context object to the template so that // We pass the context object to the template so that
// we can perform variable interpolation using sprintf // we can perform variable interpolation using sprintf
providers: this.providers, providers: this.providers,
platformName: this.platformName platformName: this.platformName
})); }));
return this; return this;
} }
});
}); });
})(jQuery, _, Backbone); }).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function($, _, gettext) {
'use strict'; 'use strict';
define([
edx.student = edx.student || {}; 'jquery',
edx.student.account = edx.student.account || {}; 'underscore',
'js/student_account/views/FormView'
edx.student.account.LoginView = edx.student.account.FormView.extend({ ],
el: '#login-form', function($, _, FormView) {
tpl: '#login-tpl', return FormView.extend({
el: '#login-form',
events: { tpl: '#login-tpl',
'click .js-login': 'submitForm', events: {
'click .forgot-password': 'forgotPassword', 'click .js-login': 'submitForm',
'click .login-provider': 'thirdPartyAuth' 'click .forgot-password': 'forgotPassword',
}, 'click .login-provider': 'thirdPartyAuth'
},
formType: 'login', formType: 'login',
requiredStr: '',
requiredStr: '', submitButton: '.js-login',
submitButton: '.js-login', preRender: function( data ) {
this.providers = data.thirdPartyAuth.providers || [];
preRender: function( data ) { this.hasSecondaryProviders = (
this.providers = data.thirdPartyAuth.providers || []; data.thirdPartyAuth.secondaryProviders && data.thirdPartyAuth.secondaryProviders.length
this.hasSecondaryProviders = ( );
data.thirdPartyAuth.secondaryProviders && data.thirdPartyAuth.secondaryProviders.length this.currentProvider = data.thirdPartyAuth.currentProvider || '';
); this.errorMessage = data.thirdPartyAuth.errorMessage || '';
this.currentProvider = data.thirdPartyAuth.currentProvider || ''; this.platformName = data.platformName;
this.errorMessage = data.thirdPartyAuth.errorMessage || ''; this.resetModel = data.resetModel;
this.platformName = data.platformName;
this.resetModel = data.resetModel; this.listenTo( this.model, 'sync', this.saveSuccess );
this.listenTo( this.resetModel, 'sync', this.resetEmail );
this.listenTo( this.model, 'sync', this.saveSuccess ); },
this.listenTo( this.resetModel, 'sync', this.resetEmail );
}, render: function( html ) {
var fields = html || '';
render: function( html ) {
var fields = html || ''; $(this.el).html( _.template( this.tpl, {
// We pass the context object to the template so that
$(this.el).html( _.template( this.tpl, { // we can perform variable interpolation using sprintf
// We pass the context object to the template so that context: {
// we can perform variable interpolation using sprintf fields: fields,
context: { currentProvider: this.currentProvider,
fields: fields, errorMessage: this.errorMessage,
currentProvider: this.currentProvider, providers: this.providers,
errorMessage: this.errorMessage, hasSecondaryProviders: this.hasSecondaryProviders,
providers: this.providers, platformName: this.platformName
hasSecondaryProviders: this.hasSecondaryProviders, }
platformName: this.platformName }));
this.postRender();
return this;
},
postRender: function() {
this.$container = $(this.el);
this.$form = this.$container.find('form');
this.$errors = this.$container.find('.submission-error');
this.$resetSuccess = this.$container.find('.js-reset-success');
this.$authError = this.$container.find('.already-authenticated-msg');
this.$submitButton = this.$container.find(this.submitButton);
/* If we're already authenticated with a third-party
* provider, try logging in. The easiest way to do this
* is to simply submit the form.
*/
if (this.currentProvider) {
this.model.save();
} }
})); },
this.postRender();
return this;
},
postRender: function() {
this.$container = $(this.el);
this.$form = this.$container.find('form');
this.$errors = this.$container.find('.submission-error');
this.$resetSuccess = this.$container.find('.js-reset-success');
this.$authError = this.$container.find('.already-authenticated-msg');
this.$submitButton = this.$container.find(this.submitButton);
/* If we're already authenticated with a third-party
* provider, try logging in. The easiest way to do this
* is to simply submit the form.
*/
if (this.currentProvider) {
this.model.save();
}
},
forgotPassword: function( event ) { forgotPassword: function( event ) {
event.preventDefault(); event.preventDefault();
this.trigger('password-help'); this.trigger('password-help');
this.element.hide( this.$resetSuccess ); this.element.hide( this.$resetSuccess );
}, },
postFormSubmission: function() { postFormSubmission: function() {
this.element.hide( this.$resetSuccess ); this.element.hide( this.$resetSuccess );
}, },
resetEmail: function() { resetEmail: function() {
this.element.hide( this.$errors ); this.element.hide( this.$errors );
this.element.show( this.$resetSuccess ); this.element.show( this.$resetSuccess );
}, },
thirdPartyAuth: function( event ) { thirdPartyAuth: function( event ) {
var providerUrl = $(event.currentTarget).data('provider-url') || ''; var providerUrl = $(event.currentTarget).data('provider-url') || '';
if (providerUrl) { if (providerUrl) {
window.location.href = providerUrl; window.location.href = providerUrl;
} }
}, },
saveSuccess: function() { saveSuccess: function() {
this.trigger('auth-complete'); this.trigger('auth-complete');
this.element.hide( this.$resetSuccess ); this.element.hide( this.$resetSuccess );
}, },
saveError: function( error ) { saveError: function( error ) {
this.errors = ['<li>' + error.responseText + '</li>']; this.errors = ['<li>' + error.responseText + '</li>'];
this.setErrors(); this.setErrors();
this.element.hide( this.$resetSuccess ); this.element.hide( this.$resetSuccess );
/* If we've gotten a 403 error, it means that we've successfully /* If we've gotten a 403 error, it means that we've successfully
* authenticated with a third-party provider, but we haven't * authenticated with a third-party provider, but we haven't
* linked the account to an EdX account. In this case, * linked the account to an EdX account. In this case,
* we need to prompt the user to enter a little more information * we need to prompt the user to enter a little more information
* to complete the registration process. * to complete the registration process.
*/ */
if ( error.status === 403 && if ( error.status === 403 &&
error.responseText === 'third-party-auth' && error.responseText === 'third-party-auth' &&
this.currentProvider ) { this.currentProvider ) {
this.element.show( this.$authError ); this.element.show( this.$authError );
this.element.hide( this.$errors ); this.element.hide( this.$errors );
} else { } else {
this.element.hide( this.$authError ); this.element.hide( this.$authError );
this.element.show( this.$errors ); this.element.show( this.$errors );
}
this.toggleDisableButton(false);
} }
this.toggleDisableButton(false); });
}
}); });
})(jQuery, _, gettext); }).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function($, gettext) {
'use strict'; 'use strict';
define([
'jquery',
'js/student_account/views/FormView'
],
function($, FormView) {
edx.student = edx.student || {}; return FormView.extend({
edx.student.account = edx.student.account || {}; el: '#password-reset-form',
edx.student.account.PasswordResetView = edx.student.account.FormView.extend({
el: '#password-reset-form',
tpl: '#password_reset-tpl', tpl: '#password_reset-tpl',
events: { events: {
'click .js-reset': 'submitForm' 'click .js-reset': 'submitForm'
}, },
formType: 'password-reset', formType: 'password-reset',
requiredStr: '', requiredStr: '',
submitButton: '.js-reset', submitButton: '.js-reset',
preRender: function() { preRender: function() {
this.element.show( $( this.el ) ); this.element.show( $( this.el ) );
this.element.show( $( this.el ).parent() ); this.element.show( $( this.el ).parent() );
this.listenTo( this.model, 'sync', this.saveSuccess ); this.listenTo( this.model, 'sync', this.saveSuccess );
}, },
toggleErrorMsg: function( show ) { toggleErrorMsg: function( show ) {
if ( show ) { if ( show ) {
this.setErrors(); this.setErrors();
this.toggleDisableButton(false); this.toggleDisableButton(false);
} else { } else {
this.element.hide( this.$errors ); this.element.hide( this.$errors );
} }
}, },
saveSuccess: function() { saveSuccess: function() {
this.trigger('password-email-sent'); this.trigger('password-email-sent');
// Destroy the view (but not el) and unbind events // Destroy the view (but not el) and unbind events
this.$el.empty().off(); this.$el.empty().off();
this.stopListening(); this.stopListening();
} }
});
}); });
}).call(this, define || RequireJS.define);
})(jQuery, gettext);
var edx = edx || {}; ;(function (define) {
(function($, _, gettext) {
'use strict'; 'use strict';
define([
'jquery',
'underscore',
'js/student_account/views/FormView'
],
function($, _, FormView) {
return FormView.extend({
el: '#register-form',
tpl: '#register-tpl',
events: {
'click .js-register': 'submitForm',
'click .login-provider': 'thirdPartyAuth'
},
formType: 'register',
submitButton: '.js-register',
preRender: function( data ) {
this.providers = data.thirdPartyAuth.providers || [];
this.hasSecondaryProviders = (
data.thirdPartyAuth.secondaryProviders && data.thirdPartyAuth.secondaryProviders.length
);
this.currentProvider = data.thirdPartyAuth.currentProvider || '';
this.errorMessage = data.thirdPartyAuth.errorMessage || '';
this.platformName = data.platformName;
this.autoSubmit = data.thirdPartyAuth.autoSubmitRegForm;
this.listenTo( this.model, 'sync', this.saveSuccess );
},
render: function( html ) {
var fields = html || '';
$(this.el).html( _.template( this.tpl, {
/* We pass the context object to the template so that
* we can perform variable interpolation using sprintf
*/
context: {
fields: fields,
currentProvider: this.currentProvider,
errorMessage: this.errorMessage,
providers: this.providers,
hasSecondaryProviders: this.hasSecondaryProviders,
platformName: this.platformName
}
}));
edx.student = edx.student || {}; this.postRender();
edx.student.account = edx.student.account || {};
if (this.autoSubmit) {
edx.student.account.RegisterView = edx.student.account.FormView.extend({ $(this.el).hide();
el: '#register-form', $('#register-honor_code').prop('checked', true);
this.submitForm();
tpl: '#register-tpl',
events: {
'click .js-register': 'submitForm',
'click .login-provider': 'thirdPartyAuth'
},
formType: 'register',
submitButton: '.js-register',
preRender: function( data ) {
this.providers = data.thirdPartyAuth.providers || [];
this.hasSecondaryProviders = (
data.thirdPartyAuth.secondaryProviders && data.thirdPartyAuth.secondaryProviders.length
);
this.currentProvider = data.thirdPartyAuth.currentProvider || '';
this.errorMessage = data.thirdPartyAuth.errorMessage || '';
this.platformName = data.platformName;
this.autoSubmit = data.thirdPartyAuth.autoSubmitRegForm;
this.listenTo( this.model, 'sync', this.saveSuccess );
},
render: function( html ) {
var fields = html || '';
$(this.el).html( _.template( this.tpl, {
/* We pass the context object to the template so that
* we can perform variable interpolation using sprintf
*/
context: {
fields: fields,
currentProvider: this.currentProvider,
errorMessage: this.errorMessage,
providers: this.providers,
hasSecondaryProviders: this.hasSecondaryProviders,
platformName: this.platformName
} }
}));
this.postRender(); return this;
},
if (this.autoSubmit) { thirdPartyAuth: function( event ) {
$(this.el).hide(); var providerUrl = $(event.currentTarget).data('provider-url') || '';
$('#register-honor_code').prop('checked', true);
this.submitForm();
}
return this; if ( providerUrl ) {
}, window.location.href = providerUrl;
}
},
thirdPartyAuth: function( event ) { saveSuccess: function() {
var providerUrl = $(event.currentTarget).data('provider-url') || ''; this.trigger('auth-complete');
},
if ( providerUrl ) { saveError: function( error ) {
window.location.href = providerUrl;
}
},
saveSuccess: function() {
this.trigger('auth-complete');
},
saveError: function( error ) {
$(this.el).show(); // Show in case the form was hidden for auto-submission
this.errors = _.flatten(
_.map(
JSON.parse(error.responseText),
function(error_list) {
return _.map(
error_list,
function(error) { return "<li>" + error.user_message + "</li>"; }
);
}
)
);
this.setErrors();
this.toggleDisableButton(false);
},
postFormSubmission: function() {
if (_.compact(this.errors).length) {
// The form did not get submitted due to validation errors.
$(this.el).show(); // Show in case the form was hidden for auto-submission $(this.el).show(); // Show in case the form was hidden for auto-submission
this.errors = _.flatten(
_.map(
JSON.parse(error.responseText),
function(error_list) {
return _.map(
error_list,
function(error) { return '<li>' + error.user_message + '</li>'; }
);
}
)
);
this.setErrors();
this.toggleDisableButton(false);
},
postFormSubmission: function() {
if (_.compact(this.errors).length) {
// The form did not get submitted due to validation errors.
$(this.el).show(); // Show in case the form was hidden for auto-submission
}
} }
}, });
}); });
})(jQuery, _, gettext); }).call(this, define || RequireJS.define);
...@@ -63,6 +63,7 @@ lib_paths: ...@@ -63,6 +63,7 @@ lib_paths:
- xmodule_js/common_static/js/test/i18n.js - xmodule_js/common_static/js/test/i18n.js
- xmodule_js/common_static/js/vendor/date.js - xmodule_js/common_static/js/vendor/date.js
- xmodule_js/common_static/js/vendor/moment.min.js - xmodule_js/common_static/js/vendor/moment.min.js
- xmodule_js/common_static/js/utils/edx.utils.validate.js
# Paths to source JavaScript files # Paths to source JavaScript files
src_paths: src_paths:
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
'js/groups/views/cohorts_dashboard_factory', 'js/groups/views/cohorts_dashboard_factory',
'js/search/course/course_search_factory', 'js/search/course/course_search_factory',
'js/search/dashboard/dashboard_search_factory', 'js/search/dashboard/dashboard_search_factory',
'js/student_account/logistration_factory',
'js/student_account/views/account_settings_factory', 'js/student_account/views/account_settings_factory',
'js/student_account/views/finish_auth_factory', 'js/student_account/views/finish_auth_factory',
'js/student_profile/views/learner_profile_factory', 'js/student_profile/views/learner_profile_factory',
......
<%! from django.utils.translation import ugettext as _ %> <%!
import json
from django.utils.translation import ugettext as _
from openedx.core.lib.json_utils import EscapedEdxJSONEncoder
%>
<%namespace name='static' file='/static_content.html'/> <%namespace name='static' file='/static_content.html'/>
<%inherit file="../main.html" /> <%inherit file="../main.html" />
...@@ -6,9 +10,10 @@ ...@@ -6,9 +10,10 @@
<%block name="pagetitle">${_("Sign in or Register")}</%block> <%block name="pagetitle">${_("Sign in or Register")}</%block>
<%block name="js_extra"> <%block name="js_extra">
<script src="${static.url('js/vendor/underscore.string.min.js')}"></script> <%static:require_module module_name="js/student_account/logistration_factory" class_name="LogistrationFactory">
<script src="${static.url('js/vendor/history.js')}"></script> var options = ${ json.dumps(data, cls=EscapedEdxJSONEncoder) };
<%static:js group='student_account'/> LogistrationFactory(options);
</%static:require_module>
</%block> </%block>
<%block name="header_extras"> <%block name="header_extras">
...@@ -20,17 +25,7 @@ ...@@ -20,17 +25,7 @@
</%block> </%block>
<div class="section-bkg-wrapper"> <div class="section-bkg-wrapper">
<div id="login-and-registration-container" <div id="login-and-registration-container" class="login-register" />
class="login-register"
data-initial-mode="${initial_mode}"
data-third-party-auth='${third_party_auth|h}'
data-third-party-auth-hint='${third_party_auth_hint}'
data-next-url='${login_redirect_url|h}'
data-platform-name='${platform_name}'
data-login-form-desc='${login_form_desc|h}'
data-registration-form-desc='${registration_form_desc|h}'
data-password-reset-form-desc='${password_reset_form_desc|h}'
/>
</div> </div>
% if settings.FEATURES.get('ENABLE_COMBINED_LOGIN_REGISTRATION'): % if settings.FEATURES.get('ENABLE_COMBINED_LOGIN_REGISTRATION'):
......
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