Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
d2a47908
Commit
d2a47908
authored
Sep 07, 2015
by
zubair-arbi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
use the standard syntax to load JavaScript dependencies on logistration js files
ECOM-2044
parent
1ba4200a
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
2232 additions
and
2166 deletions
+2232
-2166
common/djangoapps/third_party_auth/tests/specs/test_lti.py
+4
-4
common/djangoapps/third_party_auth/tests/specs/test_testshib.py
+17
-10
common/static/js/spec/edx.utils.validate_spec.js
+154
-151
common/static/js/utils/edx.utils.validate.js
+164
-157
lms/djangoapps/student_account/test/test_views.py
+14
-13
lms/djangoapps/student_account/views.py
+17
-14
lms/envs/common.py
+0
-24
lms/static/js/spec/main.js
+5
-96
lms/static/js/spec/student_account/access_spec.js
+42
-29
lms/static/js/spec/student_account/finish_auth_spec.js
+17
-12
lms/static/js/spec/student_account/hinted_login_spec.js
+75
-72
lms/static/js/spec/student_account/institution_login_spec.js
+77
-70
lms/static/js/spec/student_account/login_spec.js
+230
-225
lms/static/js/spec/student_account/logistration_factory_spec.js
+130
-0
lms/static/js/spec/student_account/password_reset_spec.js
+17
-15
lms/static/js/spec/student_account/register_spec.js
+319
-315
lms/static/js/student_account/accessApp.js
+0
-21
lms/static/js/student_account/logistration_factory.js
+15
-0
lms/static/js/student_account/models/LoginModel.js
+52
-53
lms/static/js/student_account/models/PasswordResetModel.js
+37
-42
lms/static/js/student_account/models/RegisterModel.js
+52
-57
lms/static/js/student_account/views/AccessView.js
+254
-240
lms/static/js/student_account/views/FormView.js
+216
-215
lms/static/js/student_account/views/HintedLoginView.js
+44
-46
lms/static/js/student_account/views/InstitutionLoginView.js
+22
-24
lms/static/js/student_account/views/LoginView.js
+119
-121
lms/static/js/student_account/views/PasswordResetView.js
+36
-36
lms/static/js/student_account/views/RegisterView.js
+91
-89
lms/static/js_test.yml
+1
-0
lms/static/lms/js/build.js
+1
-0
lms/templates/student_account/login_and_register.html
+10
-15
No files found.
common/djangoapps/third_party_auth/tests/specs/test_lti.py
View file @
d2a47908
...
@@ -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
)
common/djangoapps/third_party_auth/tests/specs/test_testshib.py
View file @
d2a47908
"""
"""
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
):
...
...
common/static/js/spec/edx.utils.validate_spec.js
View file @
d2a47908
describe
(
'edx.utils.validate'
,
function
(
)
{
;(
function
(
define
)
{
'use strict'
;
'use strict'
;
define
([
'jquery'
,
'js/utils/edx.utils.validate'
],
var
fixture
=
null
,
function
(
$
)
{
field
=
null
,
result
=
null
,
var
fixture
=
null
,
MIN_LENGTH
=
2
,
field
=
null
,
MAX_LENGTH
=
20
,
result
=
null
,
VALID_STRING
=
'xsy_is_awesome'
,
MIN_LENGTH
=
2
,
SHORT_STRING
=
'x'
,
MAX_LENGTH
=
20
,
LONG_STRING
=
'xsy_is_way_too_awesome'
,
VALID_STRING
=
'xsy_is_awesome'
,
EMAIL_ERROR_FRAGMENT
=
'formatted'
,
SHORT_STRING
=
'x'
,
MIN_ERROR_FRAGMENT
=
'least'
,
LONG_STRING
=
'xsy_is_way_too_awesome'
,
MAX_ERROR_FRAGMENT
=
'up to'
,
EMAIL_ERROR_FRAGMENT
=
'formatted'
,
REQUIRED_ERROR_FRAGMENT
=
'Please enter your'
,
MIN_ERROR_FRAGMENT
=
'least'
,
CUSTOM_MESSAGE
=
'custom message'
;
MAX_ERROR_FRAGMENT
=
'up to'
,
REQUIRED_ERROR_FRAGMENT
=
'Please enter your'
,
var
createFixture
=
function
(
type
,
name
,
required
,
minlength
,
maxlength
,
value
)
{
CUSTOM_MESSAGE
=
'custom message'
;
setFixtures
(
'<input id="field" type='
+
type
+
'>'
);
var
createFixture
=
function
(
type
,
name
,
required
,
minlength
,
maxlength
,
value
)
{
field
=
$
(
'#field'
);
setFixtures
(
'<input id="field" type='
+
type
+
'>'
);
field
.
prop
(
'required'
,
required
);
field
.
attr
({
field
=
$
(
'#field'
);
name
:
name
,
field
.
prop
(
'required'
,
required
);
minlength
:
minlength
,
field
.
attr
({
maxlength
:
maxlength
,
name
:
name
,
value
:
value
minlength
:
minlength
,
maxlength
:
maxlength
,
value
:
value
});
};
var
expectValid
=
function
()
{
result
=
edx
.
utils
.
validate
(
field
);
expect
(
result
.
isValid
).
toBe
(
true
);
};
var
expectInvalid
=
function
(
errorFragment
)
{
result
=
edx
.
utils
.
validate
(
field
);
expect
(
result
.
isValid
).
toBe
(
false
);
expect
(
result
.
message
).
toMatch
(
errorFragment
);
};
it
(
'succeeds if an optional field is left blank'
,
function
()
{
createFixture
(
'text'
,
'username'
,
false
,
MIN_LENGTH
,
MAX_LENGTH
,
''
);
expectValid
();
});
});
};
var
expectValid
=
function
()
{
result
=
edx
.
utils
.
validate
(
field
);
expect
(
result
.
isValid
).
toBe
(
true
);
};
var
expectInvalid
=
function
(
errorFragment
)
{
result
=
edx
.
utils
.
validate
(
field
);
expect
(
result
.
isValid
).
toBe
(
false
);
expect
(
result
.
message
).
toMatch
(
errorFragment
);
};
it
(
'succeeds if an optional field is left blank'
,
function
()
{
createFixture
(
'text'
,
'username'
,
false
,
MIN_LENGTH
,
MAX_LENGTH
,
''
);
expectValid
();
});
it
(
'succeeds if a required field is provided a valid value'
,
function
()
{
it
(
'succeeds if a required field is provided a valid value'
,
function
()
{
createFixture
(
'text'
,
'username'
,
true
,
MIN_LENGTH
,
MAX_LENGTH
,
VALID_STRING
);
createFixture
(
'text'
,
'username'
,
true
,
MIN_LENGTH
,
MAX_LENGTH
,
VALID_STRING
);
expectValid
();
expectValid
();
});
});
it
(
'fails if a required field is left blank'
,
function
()
{
it
(
'fails if a required field is left blank'
,
function
()
{
createFixture
(
'text'
,
'username'
,
true
,
MIN_LENGTH
,
MAX_LENGTH
,
''
);
createFixture
(
'text'
,
'username'
,
true
,
MIN_LENGTH
,
MAX_LENGTH
,
''
);
expectInvalid
(
REQUIRED_ERROR_FRAGMENT
);
expectInvalid
(
REQUIRED_ERROR_FRAGMENT
);
});
});
it
(
'fails if a field is provided a value below its minimum character limit'
,
function
()
{
it
(
'fails if a field is provided a value below its minimum character limit'
,
function
()
{
createFixture
(
'text'
,
'username'
,
false
,
MIN_LENGTH
,
MAX_LENGTH
,
SHORT_STRING
);
createFixture
(
'text'
,
'username'
,
false
,
MIN_LENGTH
,
MAX_LENGTH
,
SHORT_STRING
);
// Verify optional field behavior
// Verify optional field behavior
expectInvalid
(
MIN_ERROR_FRAGMENT
);
expectInvalid
(
MIN_ERROR_FRAGMENT
);
// Verify required field behavior
// Verify required field behavior
field
.
prop
(
'required'
,
true
);
field
.
prop
(
'required'
,
true
);
expectInvalid
(
MIN_ERROR_FRAGMENT
);
expectInvalid
(
MIN_ERROR_FRAGMENT
);
});
});
it
(
'succeeds if a field with no minimum character limit is provided a value below its maximum character limit'
,
function
()
{
it
(
'succeeds if a field with no minimum character limit is provided a value below its maximum character limit'
,
function
()
{
createFixture
(
'text'
,
'username'
,
false
,
null
,
MAX_LENGTH
,
SHORT_STRING
);
createFixture
(
'text'
,
'username'
,
false
,
null
,
MAX_LENGTH
,
SHORT_STRING
);
// Verify optional field behavior
// Verify optional field behavior
expectValid
();
expectValid
();
// Verify required field behavior
// Verify required field behavior
field
.
prop
(
'required'
,
true
);
field
.
prop
(
'required'
,
true
);
expectValid
();
expectValid
();
});
});
it
(
'fails if a required field with no minimum character limit is left blank'
,
function
()
{
it
(
'fails if a required field with no minimum character limit is left blank'
,
function
()
{
createFixture
(
'text'
,
'username'
,
true
,
null
,
MAX_LENGTH
,
''
);
createFixture
(
'text'
,
'username'
,
true
,
null
,
MAX_LENGTH
,
''
);
expectInvalid
(
REQUIRED_ERROR_FRAGMENT
);
expectInvalid
(
REQUIRED_ERROR_FRAGMENT
);
});
});
it
(
'fails if a field is provided a value above its maximum character limit'
,
function
()
{
it
(
'fails if a field is provided a value above its maximum character limit'
,
function
()
{
createFixture
(
'text'
,
'username'
,
false
,
MIN_LENGTH
,
MAX_LENGTH
,
LONG_STRING
);
createFixture
(
'text'
,
'username'
,
false
,
MIN_LENGTH
,
MAX_LENGTH
,
LONG_STRING
);
// Verify optional field behavior
// Verify optional field behavior
expectInvalid
(
MAX_ERROR_FRAGMENT
);
expectInvalid
(
MAX_ERROR_FRAGMENT
);
// Verify required field behavior
// Verify required field behavior
field
.
prop
(
'required'
,
true
);
field
.
prop
(
'required'
,
true
);
expectInvalid
(
MAX_ERROR_FRAGMENT
);
expectInvalid
(
MAX_ERROR_FRAGMENT
);
});
});
it
(
'succeeds if a field with no maximum character limit is provided a value above its minimum character limit'
,
function
()
{
it
(
'succeeds if a field with no maximum character limit is provided a value above its minimum character limit'
,
function
()
{
createFixture
(
'text'
,
'username'
,
false
,
MIN_LENGTH
,
null
,
LONG_STRING
);
createFixture
(
'text'
,
'username'
,
false
,
MIN_LENGTH
,
null
,
LONG_STRING
);
// Verify optional field behavior
// Verify optional field behavior
expectValid
();
expectValid
();
// Verify required field behavior
// Verify required field behavior
field
.
prop
(
'required'
,
true
);
field
.
prop
(
'required'
,
true
);
expectValid
();
expectValid
();
});
});
it
(
'succeeds if a field with no character limits is provided a value'
,
function
()
{
it
(
'succeeds if a field with no character limits is provided a value'
,
function
()
{
createFixture
(
'text'
,
'username'
,
false
,
null
,
null
,
VALID_STRING
);
createFixture
(
'text'
,
'username'
,
false
,
null
,
null
,
VALID_STRING
);
// Verify optional field behavior
// Verify optional field behavior
expectValid
();
expectValid
();
// Verify required field behavior
// Verify required field behavior
field
.
prop
(
'required'
,
true
);
field
.
prop
(
'required'
,
true
);
expectValid
();
expectValid
();
});
});
it
(
'fails if an email field is provided an invalid address'
,
function
()
{
it
(
'fails if an email field is provided an invalid address'
,
function
()
{
createFixture
(
'email'
,
'email'
,
false
,
MIN_LENGTH
,
MAX_LENGTH
,
'localpart'
);
createFixture
(
'email'
,
'email'
,
false
,
MIN_LENGTH
,
MAX_LENGTH
,
'localpart'
);
// Verify optional field behavior
// Verify optional field behavior
expectInvalid
(
EMAIL_ERROR_FRAGMENT
);
expectInvalid
(
EMAIL_ERROR_FRAGMENT
);
// Verify required field behavior
// Verify required field behavior
field
.
prop
(
'required'
,
false
);
field
.
prop
(
'required'
,
false
);
expectInvalid
(
EMAIL_ERROR_FRAGMENT
);
expectInvalid
(
EMAIL_ERROR_FRAGMENT
);
});
});
it
(
'succeeds if an email field is provided a valid address'
,
function
()
{
it
(
'succeeds if an email field is provided a valid address'
,
function
()
{
createFixture
(
'email'
,
'email'
,
false
,
MIN_LENGTH
,
MAX_LENGTH
,
'localpart@label.tld'
);
createFixture
(
'email'
,
'email'
,
false
,
MIN_LENGTH
,
MAX_LENGTH
,
'localpart@label.tld'
);
// Verify optional field behavior
// Verify optional field behavior
expectValid
();
expectValid
();
// Verify required field behavior
// Verify required field behavior
field
.
prop
(
'required'
,
true
);
field
.
prop
(
'required'
,
true
);
expectValid
();
expectValid
();
});
});
it
(
'succeeds if a checkbox is optional, or required and checked, but fails if a required checkbox is unchecked'
,
function
()
{
it
(
'succeeds if a checkbox is optional, or required and checked, but fails if a required checkbox is unchecked'
,
function
()
{
createFixture
(
'checkbox'
,
'checkbox'
,
false
,
null
,
null
,
'value'
);
createFixture
(
'checkbox'
,
'checkbox'
,
false
,
null
,
null
,
'value'
);
// Optional, unchecked
// Optional, unchecked
expectValid
();
expectValid
();
// Optional, checked
// Optional, checked
field
.
prop
(
'checked'
,
true
);
field
.
prop
(
'checked'
,
true
);
expectValid
();
expectValid
();
// Required, checked
// Required, checked
field
.
prop
(
'required'
,
true
);
field
.
prop
(
'required'
,
true
);
expectValid
();
expectValid
();
// Required, unchecked
// Required, unchecked
field
.
prop
(
'checked'
,
false
);
field
.
prop
(
'checked'
,
false
);
expectInvalid
(
REQUIRED_ERROR_FRAGMENT
);
expectInvalid
(
REQUIRED_ERROR_FRAGMENT
);
});
});
it
(
'succeeds if a select is optional, or required and default is selected, but fails if a required select has the default option selected'
,
function
()
{
it
(
'succeeds if a select is optional, or required and default is selected, but fails if a required select has the default option selected'
,
function
()
{
var
select
=
[
var
select
=
[
'<select id="dropdown" name="country">'
,
'<select id="dropdown" name="country">'
,
'<option value="" data-isdefault="true">Please select a country</option>'
,
'<option value="" data-isdefault="true">Please select a country</option>'
,
'<option value="BE">Belgium</option>'
,
'<option value="BE">Belgium</option>'
,
'<option value="DE">Germany</option>'
,
'<option value="DE">Germany</option>'
,
'</select>'
'</select>'
].
join
(
''
);
].
join
(
''
);
setFixtures
(
select
);
setFixtures
(
select
);
field
=
$
(
'#dropdown'
);
field
=
$
(
'#dropdown'
);
// Optional
// Optional
expectValid
();
expectValid
();
// Required, default text selected
// Required, default text selected
field
.
attr
(
'required'
,
true
);
field
.
attr
(
'required'
,
true
);
expectInvalid
(
REQUIRED_ERROR_FRAGMENT
);
expectInvalid
(
REQUIRED_ERROR_FRAGMENT
);
// Required, country selected
// Required, country selected
field
.
val
(
'BE'
);
field
.
val
(
'BE'
);
expectValid
();
expectValid
();
});
});
it
(
'returns a custom error message if an invalid field has one attached'
,
function
()
{
it
(
'returns a custom error message if an invalid field has one attached'
,
function
()
{
// Create a blank required field
// Create a blank required field
createFixture
(
'text'
,
'username'
,
true
,
MIN_LENGTH
,
MAX_LENGTH
,
''
);
createFixture
(
'text'
,
'username'
,
true
,
MIN_LENGTH
,
MAX_LENGTH
,
''
);
// Attach a custom error message to the field
// Attach a custom error message to the field
field
.
data
(
'errormsg-required'
,
CUSTOM_MESSAGE
);
field
.
data
(
'errormsg-required'
,
CUSTOM_MESSAGE
);
expectInvalid
(
CUSTOM_MESSAGE
);
expectInvalid
(
CUSTOM_MESSAGE
);
});
});
});
});
})
.
call
(
this
,
define
||
RequireJS
.
define
)
;
common/static/js/utils/edx.utils.validate.js
View file @
d2a47908
var
edx
=
edx
||
{};
;(
function
(
define
)
{
(
function
(
$
,
_
,
_s
,
gettext
)
{
'use strict'
;
'use strict'
;
define
([
'jquery'
,
'underscore'
,
'underscore.string'
,
'gettext'
],
function
(
$
,
_
,
_s
,
gettext
)
{
var
utils
;
/* Mix non-conflicting functions from underscore.string
* (all but include, contains, and reverse) into the
* Underscore namespace. In practice, this mixin is done
* by the access view, but doing it here helps keep the
* utility self-contained.
*/
if
(
_
.
isUndefined
(
_s
))
{
_s
=
_
.
str
;
}
_
.
mixin
(
_s
.
exports
()
);
utils
=
(
function
(){
var
_fn
=
{
validate
:
{
msg
:
{
email
:
'<li><%- gettext("The email address you
\'
ve provided isn
\'
t formatted correctly.") %></li>'
,
min
:
'<li><%- _.sprintf( gettext("%(field)s must have at least %(count)d characters."), context ) %></li>'
,
max
:
'<li><%- _.sprintf( gettext("%(field)s can only contain up to %(count)d characters."), context ) %></li>'
,
required
:
'<li><%- _.sprintf( gettext("Please enter your %(field)s."), context ) %></li>'
,
custom
:
'<li><%= content %></li>'
},
/* Mix non-conflicting functions from underscore.string
field
:
function
(
el
)
{
* (all but include, contains, and reverse) into the
var
$el
=
$
(
el
),
* Underscore namespace. In practice, this mixin is done
required
=
true
,
* by the access view, but doing it here helps keep the
min
=
true
,
* utility self-contained.
max
=
true
,
*/
email
=
true
,
_
.
mixin
(
_
.
str
.
exports
()
);
response
=
{},
isBlank
=
_fn
.
validate
.
isBlank
(
$el
);
edx
.
utils
=
edx
.
utils
||
{};
if
(
_fn
.
validate
.
isRequired
(
$el
)
)
{
var
utils
=
(
function
(){
if
(
isBlank
)
{
var
_fn
=
{
required
=
false
;
validate
:
{
}
else
{
min
=
_fn
.
validate
.
str
.
minlength
(
$el
);
msg
:
{
max
=
_fn
.
validate
.
str
.
maxlength
(
$el
);
email
:
'<li><%- gettext("The email address you
\'
ve provided isn
\'
t formatted correctly.") %></li>'
,
email
=
_fn
.
validate
.
email
.
valid
(
$el
);
min
:
'<li><%- _.sprintf( gettext("%(field)s must have at least %(count)d characters."), context ) %></li>'
,
}
max
:
'<li><%- _.sprintf( gettext("%(field)s can only contain up to %(count)d characters."), context ) %></li>'
,
}
else
if
(
!
isBlank
)
{
required
:
'<li><%- _.sprintf( gettext("Please enter your %(field)s."), context ) %></li>'
,
custom
:
'<li><%= content %></li>'
},
field
:
function
(
el
)
{
var
$el
=
$
(
el
),
required
=
true
,
min
=
true
,
max
=
true
,
email
=
true
,
response
=
{},
isBlank
=
_fn
.
validate
.
isBlank
(
$el
);
if
(
_fn
.
validate
.
isRequired
(
$el
)
)
{
if
(
isBlank
)
{
required
=
false
;
}
else
{
min
=
_fn
.
validate
.
str
.
minlength
(
$el
);
min
=
_fn
.
validate
.
str
.
minlength
(
$el
);
max
=
_fn
.
validate
.
str
.
maxlength
(
$el
);
max
=
_fn
.
validate
.
str
.
maxlength
(
$el
);
email
=
_fn
.
validate
.
email
.
valid
(
$el
);
email
=
_fn
.
validate
.
email
.
valid
(
$el
);
}
}
}
else
if
(
!
isBlank
)
{
min
=
_fn
.
validate
.
str
.
minlength
(
$el
);
max
=
_fn
.
validate
.
str
.
maxlength
(
$el
);
email
=
_fn
.
validate
.
email
.
valid
(
$el
);
}
response
.
isValid
=
required
&&
min
&&
max
&&
email
;
response
.
isValid
=
required
&&
min
&&
max
&&
email
;
if
(
!
response
.
isValid
)
{
if
(
!
response
.
isValid
)
{
_fn
.
validate
.
removeDefault
(
$el
);
_fn
.
validate
.
removeDefault
(
$el
);
response
.
message
=
_fn
.
validate
.
getMessage
(
$el
,
{
response
.
message
=
_fn
.
validate
.
getMessage
(
$el
,
{
required
:
required
,
required
:
required
,
min
:
min
,
min
:
min
,
max
:
max
,
max
:
max
,
email
:
email
email
:
email
});
});
}
}
return
response
;
return
response
;
},
},
str
:
{
minlength
:
function
(
$el
)
{
var
min
=
$el
.
attr
(
'minlength'
)
||
0
;
str
:
{
return
min
<=
$el
.
val
().
length
;
minlength
:
function
(
$el
)
{
},
var
min
=
$el
.
attr
(
'minlength'
)
||
0
;
return
min
<=
$el
.
val
().
length
;
maxlength
:
function
(
$el
)
{
var
max
=
$el
.
attr
(
'maxlength'
)
||
false
;
return
(
!!
max
)
?
max
>=
$el
.
val
().
length
:
true
;
}
},
},
maxlength
:
function
(
$el
)
{
isRequired
:
function
(
$el
)
{
var
max
=
$el
.
attr
(
'maxlength'
)
||
false
;
return
$el
.
attr
(
'required'
);
},
return
(
!!
max
)
?
max
>=
$el
.
val
().
length
:
true
;
isBlank
:
function
(
$el
)
{
}
var
type
=
$el
.
attr
(
'type'
),
},
isBlank
;
isRequired
:
function
(
$el
)
{
return
$el
.
attr
(
'required'
);
},
isBlank
:
function
(
$el
)
{
var
type
=
$el
.
attr
(
'type'
),
isBlank
;
if
(
type
===
'checkbox'
)
{
isBlank
=
!
$el
.
prop
(
'checked'
);
}
else
if
(
type
===
'select'
)
{
isBlank
=
(
$el
.
data
(
'isdefault'
)
===
true
);
}
else
{
isBlank
=
!
$el
.
val
();
}
return
isBlank
;
if
(
type
===
'checkbox'
)
{
},
isBlank
=
!
$el
.
prop
(
'checked'
);
}
else
if
(
type
===
'select'
)
{
email
:
{
isBlank
=
(
$el
.
data
(
'isdefault'
)
===
true
);
// This is the same regex used to validate email addresses in Django 1.4
}
else
{
regex
:
new
RegExp
(
isBlank
=
!
$el
.
val
();
[
}
'(^[-!#$%&
\'
*+/=?^_`{}|~0-9A-Z]+(
\\
.[-!#$%&
\'
*+/=?^_`{}|~0-9A-Z]+)*'
,
'|^"([
\\
001-
\\
010
\\
013
\\
014
\\
016-
\\
037!#-
\\
[
\\
]-
\\
177]|
\\\\
[
\\
001-
\\
011
\\
013
\\
014
\\
016-
\\
177])*"'
,
return
isBlank
;
')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?
\\
.)+[A-Z]{2,6}
\\
.?$)'
,
'|
\\
[(25[0-5]|2[0-4]
\\
d|[0-1]?
\\
d?
\\
d)(
\\
.(25[0-5]|2[0-4]
\\
d|[0-1]?
\\
d?
\\
d)){3}
\\
]$'
].
join
(
''
),
'i'
),
valid
:
function
(
$el
)
{
return
$el
.
attr
(
'type'
)
===
'email'
?
_fn
.
validate
.
email
.
format
(
$el
.
val
()
)
:
true
;
},
},
format
:
function
(
str
)
{
email
:
{
return
_fn
.
validate
.
email
.
regex
.
test
(
str
);
// This is the same regex used to validate email addresses in Django 1.4
}
regex
:
new
RegExp
(
},
[
'(^[-!#$%&
\'
*+/=?^_`{}|~0-9A-Z]+(
\\
.[-!#$%&
\'
*+/=?^_`{}|~0-9A-Z]+)*'
,
getLabel
:
function
(
id
)
{
'|^"([
\\
001-
\\
010
\\
013
\\
014
\\
016-
\\
037!#-
\\
[
\\
]-
\\
177]|
\\\\
[
\\
001-
\\
011
\\
013
\\
014
\\
016-
\\
177])*"'
,
// Extract the field label, remove the asterisk (if it appears) and any extra whitespace
')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?
\\
.)+[A-Z]{2,6}
\\
.?$)'
,
return
$
(
"label[for="
+
id
+
"]"
).
text
().
split
(
"*"
)[
0
].
trim
();
'|
\\
[(25[0-5]|2[0-4]
\\
d|[0-1]?
\\
d?
\\
d)(
\\
.(25[0-5]|2[0-4]
\\
d|[0-1]?
\\
d?
\\
d)){3}
\\
]$'
},
].
join
(
''
),
'i'
),
getMessage
:
function
(
$el
,
tests
)
{
var
txt
=
[],
valid
:
function
(
$el
)
{
tpl
,
return
$el
.
attr
(
'type'
)
===
'email'
?
_fn
.
validate
.
email
.
format
(
$el
.
val
()
)
:
true
;
label
,
},
obj
,
customMsg
;
format
:
function
(
str
)
{
return
_fn
.
validate
.
email
.
regex
.
test
(
str
);
_
.
each
(
tests
,
function
(
value
,
key
)
{
}
if
(
!
value
)
{
},
label
=
_fn
.
validate
.
getLabel
(
$el
.
attr
(
'id'
)
);
customMsg
=
$el
.
data
(
'errormsg-'
+
key
)
||
false
;
// If the field has a custom error msg attached, use it
if
(
customMsg
)
{
tpl
=
_fn
.
validate
.
msg
.
custom
;
obj
=
{
content
:
customMsg
};
}
else
{
tpl
=
_fn
.
validate
.
msg
[
key
];
obj
=
{
getLabel
:
function
(
id
)
{
// We pass the context object to the template so that
// Extract the field label, remove the asterisk (if it appears) and any extra whitespace
// we can perform variable interpolation using sprintf
return
$
(
"label[for="
+
id
+
"]"
).
text
().
split
(
"*"
)[
0
].
trim
();
context
:
{
},
field
:
label
}
};
if
(
key
===
'min'
)
{
getMessage
:
function
(
$el
,
tests
)
{
obj
.
context
.
count
=
parseInt
(
$el
.
attr
(
'minlength'
),
10
);
var
txt
=
[],
}
else
if
(
key
===
'max'
)
{
tpl
,
obj
.
context
.
count
=
parseInt
(
$el
.
attr
(
'maxlength'
),
10
);
label
,
obj
,
customMsg
;
_
.
each
(
tests
,
function
(
value
,
key
)
{
if
(
!
value
)
{
label
=
_fn
.
validate
.
getLabel
(
$el
.
attr
(
'id'
)
);
customMsg
=
$el
.
data
(
'errormsg-'
+
key
)
||
false
;
// If the field has a custom error msg attached, use it
if
(
customMsg
)
{
tpl
=
_fn
.
validate
.
msg
.
custom
;
obj
=
{
content
:
customMsg
};
}
else
{
tpl
=
_fn
.
validate
.
msg
[
key
];
obj
=
{
// We pass the context object to the template so that
// we can perform variable interpolation using sprintf
context
:
{
field
:
label
}
};
if
(
key
===
'min'
)
{
obj
.
context
.
count
=
parseInt
(
$el
.
attr
(
'minlength'
),
10
);
}
else
if
(
key
===
'max'
)
{
obj
.
context
.
count
=
parseInt
(
$el
.
attr
(
'maxlength'
),
10
);
}
}
}
}
txt
.
push
(
_
.
template
(
tpl
,
obj
)
);
txt
.
push
(
_
.
template
(
tpl
,
obj
)
);
}
}
});
});
return
txt
.
join
(
' '
);
return
txt
.
join
(
' '
);
},
},
// Removes the default HTML5 validation pop-up
// Removes the default HTML5 validation pop-up
removeDefault
:
function
(
$el
)
{
removeDefault
:
function
(
$el
)
{
if
(
$el
.
setCustomValidity
)
{
if
(
$el
.
setCustomValidity
)
{
$el
.
setCustomValidity
(
' '
);
$el
.
setCustomValidity
(
' '
);
}
}
}
}
}
}
};
};
return
{
validate
:
_fn
.
validate
.
field
};
})();
return
{
validate
:
_fn
.
validate
.
field
};
edx
.
utils
.
validate
=
utils
.
validate
;
})()
;
})(
jQuery
,
_
,
_
.
str
,
gettext
);
return
utils
;
});
}).
call
(
this
,
define
||
RequireJS
.
define
);
lms/djangoapps/student_account/test/test_views.py
View file @
d2a47908
...
@@ -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
)
)
...
...
lms/djangoapps/student_account/views.py
View file @
d2a47908
...
@@ -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
)
...
...
lms/envs/common.py
View file @
d2a47908
...
@@ -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'
...
...
lms/static/js/spec/main.js
View file @
d2a47908
...
@@ -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'
,
...
...
lms/static/js/spec/student_account/access_spec.js
View file @
d2a47908
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
);
lms/static/js/spec/student_account/finish_auth_spec.js
View file @
d2a47908
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
);
lms/static/js/spec/student_account/hinted_login_spec.js
View file @
d2a47908
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
)
;
lms/static/js/spec/student_account/institution_login_spec.js
View file @
d2a47908
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
)
;
lms/static/js/spec/student_account/login_spec.js
View file @
d2a47908
define
([
;(
function
(
define
)
{
'jquery'
,
'underscore'
,
'common/js/spec_helpers/template_helpers'
,
'common/js/spec_helpers/ajax_helpers'
,
'js/student_account/models/LoginModel'
,
'js/student_account/views/LoginView'
,
'js/student_account/models/PasswordResetModel'
],
function
(
$
,
_
,
TemplateHelpers
,
AjaxHelpers
,
LoginModel
,
LoginView
,
PasswordResetModel
)
{
'use strict'
;
'use strict'
;
describe
(
'edx.student.account.LoginView'
,
function
()
{
define
([
'jquery'
,
var
model
=
null
,
'underscore'
,
resetModel
=
null
,
'common/js/spec_helpers/template_helpers'
,
view
=
null
,
'common/js/spec_helpers/ajax_helpers'
,
requests
=
null
,
'js/student_account/models/LoginModel'
,
authComplete
=
false
,
'js/student_account/views/LoginView'
,
PLATFORM_NAME
=
'edX'
,
'js/student_account/models/PasswordResetModel'
USER_DATA
=
{
],
email
:
'xsy@edx.org'
,
function
(
$
,
_
,
TemplateHelpers
,
AjaxHelpers
,
LoginModel
,
LoginView
,
PasswordResetModel
)
{
password
:
'xsyisawesome'
,
remember
:
true
describe
(
'edx.student.account.LoginView'
,
function
()
{
},
var
model
=
null
,
THIRD_PARTY_AUTH
=
{
resetModel
=
null
,
currentProvider
:
null
,
view
=
null
,
providers
:
[
requests
=
null
,
{
authComplete
=
false
,
id
:
'oa2-google-oauth2'
,
PLATFORM_NAME
=
'edX'
,
name
:
'Google'
,
USER_DATA
=
{
iconClass
:
'fa-google-plus'
,
email
:
'xsy@edx.org'
,
loginUrl
:
'/auth/login/google-oauth2/?auth_entry=account_login'
,
password
:
'xsyisawesome'
,
registerUrl
:
'/auth/login/google-oauth2/?auth_entry=account_register'
remember
:
true
},
},
{
THIRD_PARTY_AUTH
=
{
id
:
'oa2-facebook'
,
currentProvider
:
null
,
name
:
'Facebook'
,
providers
:
[
iconClass
:
'fa-facebook'
,
{
loginUrl
:
'/auth/login/facebook/?auth_entry=account_login'
,
id
:
'oa2-google-oauth2'
,
registerUrl
:
'/auth/login/facebook/?auth_entry=account_register'
name
:
'Google'
,
}
iconClass
:
'fa-google-plus'
,
]
loginUrl
:
'/auth/login/google-oauth2/?auth_entry=account_login'
,
},
registerUrl
:
'/auth/login/google-oauth2/?auth_entry=account_register'
FORM_DESCRIPTION
=
{
},
method
:
'post'
,
{
submit_url
:
'/user_api/v1/account/login_session/'
,
id
:
'oa2-facebook'
,
fields
:
[
name
:
'Facebook'
,
{
iconClass
:
'fa-facebook'
,
placeholder
:
'username@domain.com'
,
loginUrl
:
'/auth/login/facebook/?auth_entry=account_login'
,
name
:
'email'
,
registerUrl
:
'/auth/login/facebook/?auth_entry=account_register'
label
:
'Email'
,
}
defaultValue
:
''
,
]
type
:
'email'
,
},
required
:
true
,
FORM_DESCRIPTION
=
{
instructions
:
'Enter your email.'
,
method
:
'post'
,
restrictions
:
{}
submit_url
:
'/user_api/v1/account/login_session/'
,
},
fields
:
[
{
{
placeholder
:
''
,
placeholder
:
'username@domain.com'
,
name
:
'password'
,
name
:
'email'
,
label
:
'Password'
,
label
:
'Email'
,
defaultValue
:
''
,
defaultValue
:
''
,
type
:
'password'
,
type
:
'email'
,
required
:
true
,
required
:
true
,
instructions
:
'Enter your password.'
,
instructions
:
'Enter your email.'
,
restrictions
:
{}
restrictions
:
{}
},
},
{
{
placeholder
:
''
,
placeholder
:
''
,
name
:
'remember'
,
name
:
'password'
,
label
:
'Remember me'
,
label
:
'Password'
,
defaultValue
:
''
,
defaultValue
:
''
,
type
:
'checkbox'
,
type
:
'password'
,
required
:
true
,
required
:
true
,
instructions
:
"Agree to the terms of service."
,
instructions
:
'Enter your password.'
,
restrictions
:
{}
restrictions
:
{}
}
},
]
{
},
placeholder
:
''
,
COURSE_ID
=
"edX/demoX/Fall"
;
name
:
'remember'
,
label
:
'Remember me'
,
var
createLoginView
=
function
(
test
)
{
defaultValue
:
''
,
// Initialize the login model
type
:
'checkbox'
,
model
=
new
LoginModel
({},
{
required
:
true
,
url
:
FORM_DESCRIPTION
.
submit_url
,
instructions
:
'Agree to the terms of service.'
,
method
:
FORM_DESCRIPTION
.
method
restrictions
:
{}
});
}
]
},
COURSE_ID
=
'edX/demoX/Fall'
;
var
createLoginView
=
function
(
test
)
{
// Initialize the login model
model
=
new
LoginModel
({},
{
url
:
FORM_DESCRIPTION
.
submit_url
,
method
:
FORM_DESCRIPTION
.
method
});
// Initialize the passwordReset model
// Initialize the passwordReset model
resetModel
=
new
PasswordResetModel
({},
{
resetModel
=
new
PasswordResetModel
({},
{
method
:
'GET'
,
method
:
'GET'
,
url
:
'#'
url
:
'#'
});
});
// Initialize the login view
// Initialize the login view
view
=
new
LoginView
({
view
=
new
LoginView
({
fields
:
FORM_DESCRIPTION
.
fields
,
fields
:
FORM_DESCRIPTION
.
fields
,
model
:
model
,
model
:
model
,
resetModel
:
resetModel
,
resetModel
:
resetModel
,
thirdPartyAuth
:
THIRD_PARTY_AUTH
,
thirdPartyAuth
:
THIRD_PARTY_AUTH
,
platformName
:
PLATFORM_NAME
platformName
:
PLATFORM_NAME
});
});
// Spy on AJAX requests
// Spy on AJAX requests
requests
=
AjaxHelpers
.
requests
(
test
);
requests
=
AjaxHelpers
.
requests
(
test
);
// Intercept events from the view
// Intercept events from the view
authComplete
=
false
;
authComplete
=
false
;
view
.
on
(
"auth-complete"
,
function
()
{
view
.
on
(
"auth-complete"
,
function
()
{
authComplete
=
true
;
authComplete
=
true
;
});
};
var
submitForm
=
function
(
validationSuccess
)
{
// Simulate manual entry of login form data
$
(
'#login-email'
).
val
(
USER_DATA
.
email
);
$
(
'#login-password'
).
val
(
USER_DATA
.
password
);
// Check the "Remember me" checkbox
$
(
'#login-remember'
).
prop
(
'checked'
,
USER_DATA
.
remember
);
// Create a fake click event
var
clickEvent
=
$
.
Event
(
'click'
);
// If validationSuccess isn't passed, we avoid
// spying on `view.validate` twice
if
(
!
_
.
isUndefined
(
validationSuccess
)
)
{
// Force validation to return as expected
spyOn
(
view
,
'validate'
).
andReturn
({
isValid
:
validationSuccess
,
message
:
'Submission was validated.'
});
});
}
};
var
submitForm
=
function
(
validationSuccess
)
{
// Create a fake click event
var
clickEvent
=
$
.
Event
(
'click'
);
// 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
);
// 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
// Submit the email address
view
.
submitForm
(
clickEvent
);
view
.
submitForm
(
clickEvent
);
};
};
beforeEach
(
function
()
{
beforeEach
(
function
()
{
setFixtures
(
'<div id="login-form"></div>'
);
setFixtures
(
'<div id="login-form"></div>'
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/login'
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/login'
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/form_field'
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/form_field'
);
});
});
it
(
'logs the user in'
,
function
()
{
it
(
'logs the user in'
,
function
()
{
createLoginView
(
this
);
createLoginView
(
this
);
// Submit the form, with successful validation
// Submit the form, with successful validation
submitForm
(
true
);
submitForm
(
true
);
// Form button should be disabled on success.
// Form button should be disabled on success.
expect
(
view
.
$submitButton
).
toHaveAttr
(
'disabled'
);
expect
(
view
.
$submitButton
).
toHaveAttr
(
'disabled'
);
// Verify that the client contacts the server with the expected data
// Verify that the client contacts the server with the expected data
AjaxHelpers
.
expectRequest
(
AjaxHelpers
.
expectRequest
(
requests
,
'POST'
,
requests
,
'POST'
,
FORM_DESCRIPTION
.
submit_url
,
FORM_DESCRIPTION
.
submit_url
,
$
.
param
(
USER_DATA
)
$
.
param
(
USER_DATA
)
);
);
// Respond with status code 200
// Respond with status code 200
AjaxHelpers
.
respondWithJson
(
requests
,
{});
AjaxHelpers
.
respondWithJson
(
requests
,
{});
// Verify that auth-complete is triggered
// Verify that auth-complete is triggered
expect
(
authComplete
).
toBe
(
true
);
expect
(
authComplete
).
toBe
(
true
);
});
});
it
(
'sends analytics info containing the enrolled course ID'
,
function
()
{
it
(
'sends analytics info containing the enrolled course ID'
,
function
()
{
createLoginView
(
this
)
;
var
expectedData
;
// Simulate that the user is attempting to enroll in a course
createLoginView
(
this
);
// by setting the course_id query string param.
spyOn
(
$
,
'url'
).
andCallFake
(
function
(
param
)
{
if
(
param
===
"?course_id"
)
{
return
encodeURIComponent
(
COURSE_ID
);
}
});
// Attempt to login
// Simulate that the user is attempting to enroll in a course
submitForm
(
true
);
// by setting the course_id query string param.
spyOn
(
$
,
'url'
).
andCallFake
(
function
(
param
)
{
if
(
param
===
'?course_id'
)
{
return
encodeURIComponent
(
COURSE_ID
);
}
});
// Verify that the client sent the course ID for analytics
// Attempt to login
var
expectedData
=
{};
submitForm
(
true
);
$
.
extend
(
expectedData
,
USER_DATA
,
{
analytics
:
JSON
.
stringify
({
enroll_course_id
:
COURSE_ID
})
});
AjaxHelpers
.
expectRequest
(
// Verify that the client sent the course ID for analytics
requests
,
'POST'
,
expectedData
=
{};
FORM_DESCRIPTION
.
submit_url
,
$
.
extend
(
expectedData
,
USER_DATA
,
{
$
.
param
(
expectedData
)
analytics
:
JSON
.
stringify
({
);
enroll_course_id
:
COURSE_ID
});
})
});
AjaxHelpers
.
expectRequest
(
requests
,
'POST'
,
FORM_DESCRIPTION
.
submit_url
,
$
.
param
(
expectedData
)
);
});
it
(
'displays third-party auth login buttons'
,
function
()
{
it
(
'displays third-party auth login buttons'
,
function
()
{
createLoginView
(
this
);
createLoginView
(
this
);
// Verify that Google and Facebook registration buttons are displayed
// Verify that Google and Facebook registration buttons are displayed
expect
(
$
(
'.button-oa2-google-oauth2'
)).
toBeVisible
();
expect
(
$
(
'.button-oa2-google-oauth2'
)).
toBeVisible
();
expect
(
$
(
'.button-oa2-facebook'
)).
toBeVisible
();
expect
(
$
(
'.button-oa2-facebook'
)).
toBeVisible
();
});
});
it
(
'displays a link to the password reset form'
,
function
()
{
it
(
'displays a link to the password reset form'
,
function
()
{
createLoginView
(
this
);
createLoginView
(
this
);
// Verify that the password reset link is displayed
// Verify that the password reset link is displayed
expect
(
$
(
'.forgot-password'
)).
toBeVisible
();
expect
(
$
(
'.forgot-password'
)).
toBeVisible
();
});
});
it
(
'validates login form fields'
,
function
()
{
it
(
'validates login form fields'
,
function
()
{
createLoginView
(
this
);
createLoginView
(
this
);
submitForm
(
true
);
submitForm
(
true
);
// Verify that validation of form fields occurred
// Verify that validation of form fields occurred
expect
(
view
.
validate
).
toHaveBeenCalledWith
(
$
(
'#login-email'
)[
0
]);
expect
(
view
.
validate
).
toHaveBeenCalledWith
(
$
(
'#login-email'
)[
0
]);
expect
(
view
.
validate
).
toHaveBeenCalledWith
(
$
(
'#login-password'
)[
0
]);
expect
(
view
.
validate
).
toHaveBeenCalledWith
(
$
(
'#login-password'
)[
0
]);
});
});
it
(
'displays login form validation errors'
,
function
()
{
it
(
'displays login form validation errors'
,
function
()
{
createLoginView
(
this
);
createLoginView
(
this
);
// Submit the form, with failed validation
// Submit the form, with failed validation
submitForm
(
false
);
submitForm
(
false
);
// Verify that submission errors are visible
// Verify that submission errors are visible
expect
(
view
.
$errors
).
not
.
toHaveClass
(
'hidden'
);
expect
(
view
.
$errors
).
not
.
toHaveClass
(
'hidden'
);
// Expect auth complete NOT to have been triggered
// Expect auth complete NOT to have been triggered
expect
(
authComplete
).
toBe
(
false
);
expect
(
authComplete
).
toBe
(
false
);
// Form button should be re-enabled when errors occur
// Form button should be re-enabled when errors occur
expect
(
view
.
$submitButton
).
not
.
toHaveAttr
(
'disabled'
);
expect
(
view
.
$submitButton
).
not
.
toHaveAttr
(
'disabled'
);
});
});
it
(
'displays an error if the server returns an error while logging in'
,
function
()
{
it
(
'displays an error if the server returns an error while logging in'
,
function
()
{
createLoginView
(
this
);
createLoginView
(
this
);
// Submit the form, with successful validation
// Submit the form, with successful validation
submitForm
(
true
);
submitForm
(
true
);
// Simulate an error from the LMS servers
// Simulate an error from the LMS servers
AjaxHelpers
.
respondWithError
(
requests
);
AjaxHelpers
.
respondWithError
(
requests
);
// Expect that an error is displayed and that auth complete is not triggered
// Expect that an error is displayed and that auth complete is not triggered
expect
(
view
.
$errors
).
not
.
toHaveClass
(
'hidden'
);
expect
(
view
.
$errors
).
not
.
toHaveClass
(
'hidden'
);
expect
(
authComplete
).
toBe
(
false
);
expect
(
authComplete
).
toBe
(
false
);
// Form button should be re-enabled on server failure.
// Form button should be re-enabled on server failure.
expect
(
view
.
$submitButton
).
not
.
toHaveAttr
(
'disabled'
);
expect
(
view
.
$submitButton
).
not
.
toHaveAttr
(
'disabled'
);
// If we try again and succeed, the error should go away
// If we try again and succeed, the error should go away
submitForm
();
submitForm
();
// Form button should be disabled on success.
// Form button should be disabled on success.
expect
(
view
.
$submitButton
).
toHaveAttr
(
'disabled'
);
expect
(
view
.
$submitButton
).
toHaveAttr
(
'disabled'
);
// This time, respond with status code 200
// This time, respond with status code 200
AjaxHelpers
.
respondWithJson
(
requests
,
{});
AjaxHelpers
.
respondWithJson
(
requests
,
{});
// Expect that the error is hidden and auth complete is triggered
// Expect that the error is hidden and auth complete is triggered
expect
(
view
.
$errors
).
toHaveClass
(
'hidden'
);
expect
(
view
.
$errors
).
toHaveClass
(
'hidden'
);
expect
(
authComplete
).
toBe
(
true
);
expect
(
authComplete
).
toBe
(
true
);
});
});
});
});
});
});
})
.
call
(
this
,
define
||
RequireJS
.
define
)
;
lms/static/js/spec/student_account/logistration_factory_spec.js
0 → 100644
View file @
d2a47908
;(
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
);
lms/static/js/spec/student_account/password_reset_spec.js
View file @
d2a47908
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
);
lms/static/js/spec/student_account/register_spec.js
View file @
d2a47908
define
([
;(
function
(
define
)
{
'jquery'
,
'underscore'
,
'common/js/spec_helpers/template_helpers'
,
'common/js/spec_helpers/ajax_helpers'
,
'js/student_account/models/RegisterModel'
,
'js/student_account/views/RegisterView'
],
function
(
$
,
_
,
TemplateHelpers
,
AjaxHelpers
,
RegisterModel
,
RegisterView
)
{
'use strict'
;
'use strict'
;
define
([
'jquery'
,
'underscore'
,
'common/js/spec_helpers/template_helpers'
,
'common/js/spec_helpers/ajax_helpers'
,
'js/student_account/models/RegisterModel'
,
'js/student_account/views/RegisterView'
],
function
(
$
,
_
,
TemplateHelpers
,
AjaxHelpers
,
RegisterModel
,
RegisterView
)
{
describe
(
'edx.student.account.RegisterView'
,
function
()
{
var
model
=
null
,
view
=
null
,
requests
=
null
,
authComplete
=
false
,
PLATFORM_NAME
=
'edX'
,
COURSE_ID
=
'edX/DemoX/Fall'
,
USER_DATA
=
{
email
:
'xsy@edx.org'
,
name
:
'Xsy M. Education'
,
username
:
'Xsy'
,
password
:
'xsyisawesome'
,
level_of_education
:
'p'
,
gender
:
'm'
,
year_of_birth
:
2014
,
mailing_address
:
'141 Portland'
,
goals
:
'To boldly learn what no letter of the alphabet has learned before'
,
honor_code
:
true
},
THIRD_PARTY_AUTH
=
{
currentProvider
:
null
,
providers
:
[
{
id
:
'oa2-google-oauth2'
,
name
:
'Google'
,
iconClass
:
'fa-google-plus'
,
loginUrl
:
'/auth/login/google-oauth2/?auth_entry=account_login'
,
registerUrl
:
'/auth/login/google-oauth2/?auth_entry=account_register'
},
{
id
:
'oa2-facebook'
,
name
:
'Facebook'
,
iconClass
:
'fa-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
:
[
{
placeholder
:
'username@domain.com'
,
name
:
'email'
,
label
:
'Email'
,
defaultValue
:
''
,
type
:
'email'
,
required
:
true
,
instructions
:
'Enter your email.'
,
restrictions
:
{}
},
{
placeholder
:
'Jane Doe'
,
name
:
'name'
,
label
:
'Full Name'
,
defaultValue
:
''
,
type
:
'text'
,
required
:
true
,
instructions
:
'Enter your username.'
,
restrictions
:
{}
},
{
placeholder
:
'JaneDoe'
,
name
:
'username'
,
label
:
'Username'
,
defaultValue
:
''
,
type
:
'text'
,
required
:
true
,
instructions
:
'Enter your username.'
,
restrictions
:
{}
},
{
placeholder
:
''
,
name
:
'password'
,
label
:
'Password'
,
defaultValue
:
''
,
type
:
'password'
,
required
:
true
,
instructions
:
'Enter your password.'
,
restrictions
:
{}
},
{
placeholder
:
''
,
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
:
{}
},
{
placeholder
:
''
,
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
:
{}
},
{
placeholder
:
''
,
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
:
{}
},
{
placeholder
:
''
,
name
:
'mailing_address'
,
label
:
'Mailing Address'
,
defaultValue
:
''
,
type
:
'textarea'
,
required
:
false
,
instructions
:
'Enter your mailing address.'
,
restrictions
:
{}
},
{
placeholder
:
''
,
name
:
'goals'
,
label
:
'Goals'
,
defaultValue
:
''
,
type
:
'textarea'
,
required
:
false
,
instructions
:
"If you'd like, tell us why you're interested in edX."
,
restrictions
:
{}
},
{
placeholder
:
''
,
name
:
'honor_code'
,
label
:
'I agree to the <a href="/honor">Terms of Service and Honor Code</a>'
,
defaultValue
:
''
,
type
:
'checkbox'
,
required
:
true
,
instructions
:
''
,
restrictions
:
{}
}
]
};
var
createRegisterView
=
function
(
that
)
{
// Initialize the register model
model
=
new
RegisterModel
({},
{
url
:
FORM_DESCRIPTION
.
submit_url
,
method
:
FORM_DESCRIPTION
.
method
});
describe
(
'edx.student.account.RegisterView'
,
function
()
{
// Initialize the register view
view
=
new
RegisterView
({
var
model
=
null
,
fields
:
FORM_DESCRIPTION
.
fields
,
view
=
null
,
model
:
model
,
requests
=
null
,
thirdPartyAuth
:
THIRD_PARTY_AUTH
,
authComplete
=
false
,
platformName
:
PLATFORM_NAME
PLATFORM_NAME
=
'edX'
,
});
COURSE_ID
=
"edX/DemoX/Fall"
,
USER_DATA
=
{
email
:
'xsy@edx.org'
,
name
:
'Xsy M. Education'
,
username
:
'Xsy'
,
password
:
'xsyisawesome'
,
level_of_education
:
'p'
,
gender
:
'm'
,
year_of_birth
:
2014
,
mailing_address
:
'141 Portland'
,
goals
:
'To boldly learn what no letter of the alphabet has learned before'
,
honor_code
:
true
},
THIRD_PARTY_AUTH
=
{
currentProvider
:
null
,
providers
:
[
{
id
:
'oa2-google-oauth2'
,
name
:
'Google'
,
iconClass
:
'fa-google-plus'
,
loginUrl
:
'/auth/login/google-oauth2/?auth_entry=account_login'
,
registerUrl
:
'/auth/login/google-oauth2/?auth_entry=account_register'
},
{
id
:
'oa2-facebook'
,
name
:
'Facebook'
,
iconClass
:
'fa-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
:
[
{
placeholder
:
'username@domain.com'
,
name
:
'email'
,
label
:
'Email'
,
defaultValue
:
''
,
type
:
'email'
,
required
:
true
,
instructions
:
'Enter your email.'
,
restrictions
:
{}
},
{
placeholder
:
'Jane Doe'
,
name
:
'name'
,
label
:
'Full Name'
,
defaultValue
:
''
,
type
:
'text'
,
required
:
true
,
instructions
:
'Enter your username.'
,
restrictions
:
{}
},
{
placeholder
:
'JaneDoe'
,
name
:
'username'
,
label
:
'Username'
,
defaultValue
:
''
,
type
:
'text'
,
required
:
true
,
instructions
:
'Enter your username.'
,
restrictions
:
{}
},
{
placeholder
:
''
,
name
:
'password'
,
label
:
'Password'
,
defaultValue
:
''
,
type
:
'password'
,
required
:
true
,
instructions
:
'Enter your password.'
,
restrictions
:
{}
},
{
placeholder
:
''
,
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
:
{}
},
{
placeholder
:
''
,
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
:
{}
},
{
placeholder
:
''
,
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
:
{}
},
{
placeholder
:
''
,
name
:
'mailing_address'
,
label
:
'Mailing Address'
,
defaultValue
:
''
,
type
:
'textarea'
,
required
:
false
,
instructions
:
'Enter your mailing address.'
,
restrictions
:
{}
},
{
placeholder
:
''
,
name
:
'goals'
,
label
:
'Goals'
,
defaultValue
:
''
,
type
:
'textarea'
,
required
:
false
,
instructions
:
"If you'd like, tell us why you're interested in edX."
,
restrictions
:
{}
},
{
placeholder
:
''
,
name
:
'honor_code'
,
label
:
'I agree to the <a href="/honor">Terms of Service and Honor Code</a>'
,
defaultValue
:
''
,
type
:
'checkbox'
,
required
:
true
,
instructions
:
''
,
restrictions
:
{}
}
]
};
var
createRegisterView
=
function
(
that
)
{
// Spy on AJAX requests
// Initialize the register model
requests
=
AjaxHelpers
.
requests
(
that
);
model
=
new
RegisterModel
({},
{
url
:
FORM_DESCRIPTION
.
submit_url
,
method
:
FORM_DESCRIPTION
.
method
});
// Initialize the register view
// Intercept events from the view
view
=
new
RegisterView
({
authComplete
=
false
;
fields
:
FORM_DESCRIPTION
.
fields
,
view
.
on
(
"auth-complete"
,
function
()
{
model
:
model
,
authComplete
=
true
;
thirdPartyAuth
:
THIRD_PARTY_AUTH
,
});
platformName
:
PLATFORM_NAME
};
});
// Spy on AJAX requests
var
submitForm
=
function
(
validationSuccess
)
{
requests
=
AjaxHelpers
.
requests
(
that
);
// Create a fake click event
var
clickEvent
=
$
.
Event
(
'click'
);
// Simulate manual entry of registration form data
$
(
'#register-email'
).
val
(
USER_DATA
.
email
);
$
(
'#register-name'
).
val
(
USER_DATA
.
name
);
$
(
'#register-username'
).
val
(
USER_DATA
.
username
);
$
(
'#register-password'
).
val
(
USER_DATA
.
password
);
$
(
'#register-level_of_education'
).
val
(
USER_DATA
.
level_of_education
);
$
(
'#register-gender'
).
val
(
USER_DATA
.
gender
);
$
(
'#register-year_of_birth'
).
val
(
USER_DATA
.
year_of_birth
);
$
(
'#register-mailing_address'
).
val
(
USER_DATA
.
mailing_address
);
$
(
'#register-goals'
).
val
(
USER_DATA
.
goals
);
// Check the honor code checkbox
$
(
'#register-honor_code'
).
prop
(
'checked'
,
USER_DATA
.
honor_code
);
// 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.'
});
}
// Intercept events from the view
// Submit the email address
authComplete
=
false
;
view
.
submitForm
(
clickEvent
);
view
.
on
(
"auth-complete"
,
function
()
{
};
authComplete
=
true
;
});
};
var
submitForm
=
function
(
validationSuccess
)
{
// Simulate manual entry of registration form data
$
(
'#register-email'
).
val
(
USER_DATA
.
email
);
$
(
'#register-name'
).
val
(
USER_DATA
.
name
);
$
(
'#register-username'
).
val
(
USER_DATA
.
username
);
$
(
'#register-password'
).
val
(
USER_DATA
.
password
);
$
(
'#register-level_of_education'
).
val
(
USER_DATA
.
level_of_education
);
$
(
'#register-gender'
).
val
(
USER_DATA
.
gender
);
$
(
'#register-year_of_birth'
).
val
(
USER_DATA
.
year_of_birth
);
$
(
'#register-mailing_address'
).
val
(
USER_DATA
.
mailing_address
);
$
(
'#register-goals'
).
val
(
USER_DATA
.
goals
);
// Check the honor code checkbox
$
(
'#register-honor_code'
).
prop
(
'checked'
,
USER_DATA
.
honor_code
);
// Create a fake click event
var
clickEvent
=
$
.
Event
(
'click'
);
// If validationSuccess isn't passed, we avoid
// spying on `view.validate` twice
if
(
!
_
.
isUndefined
(
validationSuccess
)
)
{
// Force validation to return as expected
spyOn
(
view
,
'validate'
).
andReturn
({
isValid
:
validationSuccess
,
message
:
'Submission was validated.'
});
}
// Submit the email address
beforeEach
(
function
()
{
view
.
submitForm
(
clickEvent
);
setFixtures
(
'<div id="register-form"></div>'
);
};
TemplateHelpers
.
installTemplate
(
'templates/student_account/register'
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/form_field'
);
});
beforeEach
(
function
()
{
it
(
'registers a new user'
,
function
()
{
setFixtures
(
'<div id="register-form"></div>'
);
createRegisterView
(
this
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/register'
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/form_field'
);
});
it
(
'registers a new user'
,
function
()
{
// Submit the form, with successful validation
createRegisterView
(
this
);
submitForm
(
true
);
// Submit the form, with successful validation
// Verify that the client contacts the server with the expected data
submitForm
(
true
);
AjaxHelpers
.
expectRequest
(
requests
,
'POST'
,
FORM_DESCRIPTION
.
submit_url
,
$
.
param
(
USER_DATA
)
);
// Verify that the client contacts the server with the expected data
// Respond with status code 200
AjaxHelpers
.
expectRequest
(
AjaxHelpers
.
respondWithJson
(
requests
,
{});
requests
,
'POST'
,
FORM_DESCRIPTION
.
submit_url
,
$
.
param
(
USER_DATA
)
);
// Respond with status code 200
// Verify that auth complete is triggered
AjaxHelpers
.
respondWithJson
(
requests
,
{});
expect
(
authComplete
).
toBe
(
true
);
// Form button should be disabled on success.
expect
(
view
.
$submitButton
).
toHaveAttr
(
'disabled'
);
});
// Verify that auth complete is triggered
it
(
'sends analytics info containing the enrolled course ID'
,
function
()
{
expect
(
authComplete
).
toBe
(
true
);
var
expectedData
;
// Form button should be disabled on success.
expect
(
view
.
$submitButton
).
toHaveAttr
(
'disabled'
);
});
it
(
'sends analytics info containing the enrolled course ID'
,
function
()
{
createRegisterView
(
this
);
createRegisterView
(
this
);
// Simulate that the user is attempting to enroll in a course
// Simulate that the user is attempting to enroll in a course
// by setting the course_id query string param.
// by setting the course_id query string param.
spyOn
(
$
,
'url'
).
andCallFake
(
function
(
param
)
{
spyOn
(
$
,
'url'
).
andCallFake
(
function
(
param
)
{
if
(
param
===
"?course_id"
)
{
if
(
param
===
'?course_id'
)
{
return
encodeURIComponent
(
COURSE_ID
);
return
encodeURIComponent
(
COURSE_ID
);
}
}
});
});
// Attempt to register
// Attempt to register
submitForm
(
true
);
submitForm
(
true
);
// Verify that the client sent the course ID for analytics
// Verify that the client sent the course ID for analytics
var
expectedData
=
{
course_id
:
COURSE_ID
};
expectedData
=
{
course_id
:
COURSE_ID
};
$
.
extend
(
expectedData
,
USER_DATA
);
$
.
extend
(
expectedData
,
USER_DATA
);
AjaxHelpers
.
expectRequest
(
AjaxHelpers
.
expectRequest
(
requests
,
'POST'
,
requests
,
'POST'
,
FORM_DESCRIPTION
.
submit_url
,
FORM_DESCRIPTION
.
submit_url
,
$
.
param
(
expectedData
)
$
.
param
(
expectedData
)
);
);
});
});
it
(
'displays third-party auth registration buttons'
,
function
()
{
it
(
'displays third-party auth registration buttons'
,
function
()
{
createRegisterView
(
this
);
createRegisterView
(
this
);
// Verify that Google and Facebook registration buttons are displayed
// Verify that Google and Facebook registration buttons are displayed
expect
(
$
(
'.button-oa2-google-oauth2'
)).
toBeVisible
();
expect
(
$
(
'.button-oa2-google-oauth2'
)).
toBeVisible
();
expect
(
$
(
'.button-oa2-facebook'
)).
toBeVisible
();
expect
(
$
(
'.button-oa2-facebook'
)).
toBeVisible
();
});
});
it
(
'validates registration form fields'
,
function
()
{
it
(
'validates registration form fields'
,
function
()
{
createRegisterView
(
this
);
createRegisterView
(
this
);
// Submit the form, with successful validation
// Submit the form, with successful validation
submitForm
(
true
);
submitForm
(
true
);
// Verify that validation of form fields occurred
// Verify that validation of form fields occurred
expect
(
view
.
validate
).
toHaveBeenCalledWith
(
$
(
'#register-email'
)[
0
]);
expect
(
view
.
validate
).
toHaveBeenCalledWith
(
$
(
'#register-email'
)[
0
]);
expect
(
view
.
validate
).
toHaveBeenCalledWith
(
$
(
'#register-name'
)[
0
]);
expect
(
view
.
validate
).
toHaveBeenCalledWith
(
$
(
'#register-name'
)[
0
]);
expect
(
view
.
validate
).
toHaveBeenCalledWith
(
$
(
'#register-username'
)[
0
]);
expect
(
view
.
validate
).
toHaveBeenCalledWith
(
$
(
'#register-username'
)[
0
]);
expect
(
view
.
validate
).
toHaveBeenCalledWith
(
$
(
'#register-password'
)[
0
]);
expect
(
view
.
validate
).
toHaveBeenCalledWith
(
$
(
'#register-password'
)[
0
]);
// Verify that no submission errors are visible
// Verify that no submission errors are visible
expect
(
view
.
$errors
).
toHaveClass
(
'hidden'
);
expect
(
view
.
$errors
).
toHaveClass
(
'hidden'
);
// Form button should be disabled on success.
// Form button should be disabled on success.
expect
(
view
.
$submitButton
).
toHaveAttr
(
'disabled'
);
expect
(
view
.
$submitButton
).
toHaveAttr
(
'disabled'
);
});
});
it
(
'displays registration form validation errors'
,
function
()
{
it
(
'displays registration form validation errors'
,
function
()
{
createRegisterView
(
this
);
createRegisterView
(
this
);
// Submit the form, with failed validation
// Submit the form, with failed validation
submitForm
(
false
);
submitForm
(
false
);
// Verify that submission errors are visible
// Verify that submission errors are visible
expect
(
view
.
$errors
).
not
.
toHaveClass
(
'hidden'
);
expect
(
view
.
$errors
).
not
.
toHaveClass
(
'hidden'
);
// Expect that auth complete is NOT triggered
// Expect that auth complete is NOT triggered
expect
(
authComplete
).
toBe
(
false
);
expect
(
authComplete
).
toBe
(
false
);
// Form button should be re-enabled on error.
// Form button should be re-enabled on error.
expect
(
view
.
$submitButton
).
not
.
toHaveAttr
(
'disabled'
);
expect
(
view
.
$submitButton
).
not
.
toHaveAttr
(
'disabled'
);
});
});
it
(
'displays an error if the server returns an error while registering'
,
function
()
{
it
(
'displays an error if the server returns an error while registering'
,
function
()
{
createRegisterView
(
this
);
createRegisterView
(
this
);
// Submit the form, with successful validation
// Submit the form, with successful validation
submitForm
(
true
);
submitForm
(
true
);
// Simulate an error from the LMS servers
// Simulate an error from the LMS servers
AjaxHelpers
.
respondWithError
(
requests
);
AjaxHelpers
.
respondWithError
(
requests
);
// Expect that an error is displayed and that auth complete is NOT triggered
// Expect that an error is displayed and that auth complete is NOT triggered
expect
(
view
.
$errors
).
not
.
toHaveClass
(
'hidden'
);
expect
(
view
.
$errors
).
not
.
toHaveClass
(
'hidden'
);
expect
(
authComplete
).
toBe
(
false
);
expect
(
authComplete
).
toBe
(
false
);
// If we try again and succeed, the error should go away
// If we try again and succeed, the error should go away
submitForm
();
submitForm
();
// This time, respond with status code 200
// This time, respond with status code 200
AjaxHelpers
.
respondWithJson
(
requests
,
{});
AjaxHelpers
.
respondWithJson
(
requests
,
{});
// Expect that the error is hidden and that auth complete is triggered
// Expect that the error is hidden and that auth complete is triggered
expect
(
view
.
$errors
).
toHaveClass
(
'hidden'
);
expect
(
view
.
$errors
).
toHaveClass
(
'hidden'
);
expect
(
authComplete
).
toBe
(
true
);
expect
(
authComplete
).
toBe
(
true
);
// Form button should be disabled on success.
// Form button should be disabled on success.
expect
(
view
.
$submitButton
).
toHaveAttr
(
'disabled'
);
expect
(
view
.
$submitButton
).
toHaveAttr
(
'disabled'
);
});
});
});
});
});
});
})
.
call
(
this
,
define
||
RequireJS
.
define
)
;
lms/static/js/student_account/accessApp.js
deleted
100644 → 0
View file @
1ba4200a
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
);
lms/static/js/student_account/logistration_factory.js
0 → 100644
View file @
d2a47908
;(
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
);
lms/static/js/student_account/models/LoginModel.js
View file @
d2a47908
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
,
Backbo
ne
);
})
.
call
(
this
,
define
||
RequireJS
.
defi
ne
);
lms/static/js/student_account/models/PasswordResetModel.js
View file @
d2a47908
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
,
Backbo
ne
);
})
.
call
(
this
,
define
||
RequireJS
.
defi
ne
);
lms/static/js/student_account/models/RegisterModel.js
View file @
d2a47908
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
,
Backbo
ne
);
})
.
call
(
this
,
define
||
RequireJS
.
defi
ne
);
lms/static/js/student_account/views/AccessView.js
View file @
d2a47908
var
edx
=
edx
||
{};
;(
function
(
define
)
{
(
function
(
$
,
_
,
_s
,
Backbone
,
History
)
{
'use strict'
;
'use strict'
;
define
([
'jquery'
,
'utility'
,
'underscore'
,
'underscore.string'
,
'backbone'
,
'js/student_account/models/LoginModel'
,
'js/student_account/models/PasswordResetModel'
,
'js/student_account/models/RegisterModel'
,
'js/student_account/views/LoginView'
,
'js/student_account/views/PasswordResetView'
,
'js/student_account/views/RegisterView'
,
'js/student_account/views/InstitutionLoginView'
,
'js/student_account/views/HintedLoginView'
,
'js/vendor/history'
],
function
(
$
,
utility
,
_
,
_s
,
Backbone
,
LoginModel
,
PasswordResetModel
,
RegisterModel
,
LoginView
,
PasswordResetView
,
RegisterView
,
InstitutionLoginView
,
HintedLoginView
)
{
if
(
_
.
isUndefined
(
_s
))
{
_s
=
_
.
str
;
}
edx
.
student
=
edx
.
student
||
{};
return
Backbone
.
View
.
extend
({
edx
.
student
.
account
=
edx
.
student
.
account
||
{};
tpl
:
'#access-tpl'
,
events
:
{
edx
.
student
.
account
.
AccessView
=
Backbone
.
View
.
extend
({
'click .form-toggle'
:
'toggleForm'
el
:
'#login-and-registration-container'
,
},
subview
:
{
tpl
:
'#access-tpl'
,
login
:
{},
register
:
{},
events
:
{
passwordHelp
:
{},
'click .form-toggle'
:
'toggleForm'
institutionLogin
:
{},
},
hintedLogin
:
{}
},
subview
:
{
nextUrl
:
'/dashboard'
,
login
:
{},
// The form currently loaded
register
:
{},
activeForm
:
''
,
passwordHelp
:
{},
institutionLogin
:
{},
hintedLogin
:
{}
},
nextUrl
:
'/dashboard'
,
// The form currently loaded
initialize
:
function
(
options
)
{
activeForm
:
''
,
initialize
:
function
(
obj
)
{
/* Mix non-conflicting functions from underscore.string
/* Mix non-conflicting functions from underscore.string
* (all but include, contains, and reverse) into the
* (all but include, contains, and reverse) into the
* Underscore namespace
* Underscore namespace
*/
*/
_
.
mixin
(
_s
.
exports
()
);
_
.
mixin
(
_s
.
exports
()
);
this
.
tpl
=
$
(
this
.
tpl
).
html
();
this
.
tpl
=
$
(
this
.
tpl
).
html
();
this
.
activeForm
=
obj
.
mode
||
'login'
;
this
.
activeForm
=
options
.
initial_
mode
||
'login'
;
this
.
thirdPartyAuth
=
obj
.
thirdPartyA
uth
||
{
this
.
thirdPartyAuth
=
options
.
third_party_a
uth
||
{
currentProvider
:
null
,
currentProvider
:
null
,
providers
:
[]
providers
:
[]
};
};
this
.
thirdPartyAuthHint
=
obj
.
thirdPartyAuthH
int
||
null
;
this
.
thirdPartyAuthHint
=
options
.
third_party_auth_h
int
||
null
;
if
(
obj
.
nextUrl
)
{
if
(
options
.
login_redirect_url
)
{
// Ensure that the next URL is internal for security reasons
// Ensure that the next URL is internal for security reasons
if
(
!
window
.
isExternal
(
obj
.
nextUrl
)
)
{
if
(
!
window
.
isExternal
(
options
.
login_redirect_url
)
)
{
this
.
nextUrl
=
obj
.
nextUrl
;
this
.
nextUrl
=
options
.
login_redirect_url
;
}
}
}
}
this
.
formDescriptions
=
{
this
.
formDescriptions
=
{
login
:
obj
.
loginFormDesc
,
login
:
options
.
login_form_desc
,
register
:
obj
.
registrationFormDesc
,
register
:
options
.
registration_form_desc
,
reset
:
obj
.
passwordResetFormDesc
,
reset
:
options
.
password_reset_form_desc
,
institution_login
:
null
,
institution_login
:
null
,
hinted_login
:
null
hinted_login
:
null
};
};
this
.
platformName
=
obj
.
platformName
;
// The login view listens for 'sync' events from the reset model
this
.
resetModel
=
new
edx
.
student
.
account
.
PasswordResetModel
({},
{
method
:
'GET'
,
url
:
'#'
});
this
.
render
();
// Once the third party error message has been shown once,
// there is no need to show it again, if the user changes mode:
this
.
thirdPartyAuth
.
errorMessage
=
null
;
},
render
:
function
()
{
$
(
this
.
el
).
html
(
_
.
template
(
this
.
tpl
,
{
mode
:
this
.
activeForm
}));
this
.
postRender
();
return
this
;
},
postRender
:
function
()
{
//get & check current url hash part & load form accordingly
if
(
Backbone
.
history
.
getHash
()
===
"forgot-password-modal"
)
{
this
.
resetPassword
();
}
else
{
this
.
loadForm
(
this
.
activeForm
);
}
},
loadForm
:
function
(
type
)
{
var
loadFunc
=
_
.
bind
(
this
.
load
[
type
],
this
);
loadFunc
(
this
.
formDescriptions
[
type
]
);
},
load
:
{
login
:
function
(
data
)
{
var
model
=
new
edx
.
student
.
account
.
LoginModel
({},
{
method
:
data
.
method
,
url
:
data
.
submit_url
});
this
.
subview
.
login
=
new
edx
.
student
.
account
.
LoginView
({
this
.
platformName
=
options
.
platform_name
;
fields
:
data
.
fields
,
model
:
model
,
resetModel
:
this
.
resetModel
,
thirdPartyAuth
:
this
.
thirdPartyAuth
,
platformName
:
this
.
platformName
});
// Listen for 'password-help' event to toggle sub-views
// The login view listens for 'sync' events from the reset model
this
.
listenTo
(
this
.
subview
.
login
,
'password-help'
,
this
.
resetPassword
);
this
.
resetModel
=
new
PasswordResetModel
({},
{
method
:
'GET'
,
url
:
'#'
});
// Listen for 'auth-complete' event so we can enroll/redirect the user appropriately.
this
.
render
();
this
.
listenTo
(
this
.
subview
.
login
,
'auth-complete'
,
this
.
authComplete
);
// Once the third party error message has been shown once,
// there is no need to show it again, if the user changes mode:
this
.
thirdPartyAuth
.
errorMessage
=
null
;
},
},
reset
:
function
(
data
)
{
render
:
function
()
{
this
.
resetModel
.
ajaxType
=
data
.
method
;
$
(
this
.
el
).
html
(
_
.
template
(
this
.
tpl
,
{
this
.
resetModel
.
urlRoot
=
data
.
submit_url
;
mode
:
this
.
activeForm
}));
this
.
subview
.
passwordHelp
=
new
edx
.
student
.
account
.
PasswordResetView
({
this
.
postRender
();
fields
:
data
.
fields
,
model
:
this
.
resetModel
});
// Listen for 'password-email-sent' event to toggle sub-views
return
this
;
this
.
listenTo
(
this
.
subview
.
passwordHelp
,
'password-email-sent'
,
this
.
passwordEmailSent
);
},
// Focus on the form
postRender
:
function
()
{
$
(
'.password-reset-form'
).
focus
();
//get & check current url hash part & load form accordingly
if
(
Backbone
.
history
.
getHash
()
===
'forgot-password-modal'
)
{
this
.
resetPassword
();
}
else
{
this
.
loadForm
(
this
.
activeForm
);
}
},
},
register
:
function
(
data
)
{
loadForm
:
function
(
type
)
{
var
model
=
new
edx
.
student
.
account
.
RegisterModel
({},
{
var
loadFunc
=
_
.
bind
(
this
.
load
[
type
],
this
);
method
:
data
.
method
,
loadFunc
(
this
.
formDescriptions
[
type
]
);
url
:
data
.
submit_url
},
});
this
.
subview
.
register
=
new
edx
.
student
.
account
.
RegisterView
({
load
:
{
fields
:
data
.
fields
,
login
:
function
(
data
)
{
model
:
model
,
var
model
=
new
LoginModel
({},
{
thirdPartyAuth
:
this
.
thirdPartyAuth
,
method
:
data
.
method
,
platformName
:
this
.
platformName
url
:
data
.
submit_url
});
});
this
.
subview
.
login
=
new
LoginView
({
fields
:
data
.
fields
,
model
:
model
,
resetModel
:
this
.
resetModel
,
thirdPartyAuth
:
this
.
thirdPartyAuth
,
platformName
:
this
.
platformName
});
// Listen for 'password-help' event to toggle sub-views
this
.
listenTo
(
this
.
subview
.
login
,
'password-help'
,
this
.
resetPassword
);
// Listen for 'auth-complete' event so we can enroll/redirect the user appropriately.
this
.
listenTo
(
this
.
subview
.
login
,
'auth-complete'
,
this
.
authComplete
);
},
reset
:
function
(
data
)
{
this
.
resetModel
.
ajaxType
=
data
.
method
;
this
.
resetModel
.
urlRoot
=
data
.
submit_url
;
this
.
subview
.
passwordHelp
=
new
PasswordResetView
({
fields
:
data
.
fields
,
model
:
this
.
resetModel
});
// Listen for 'password-email-sent' event to toggle sub-views
this
.
listenTo
(
this
.
subview
.
passwordHelp
,
'password-email-sent'
,
this
.
passwordEmailSent
);
// Focus on the form
$
(
'.password-reset-form'
).
focus
();
},
register
:
function
(
data
)
{
var
model
=
new
RegisterModel
({},
{
method
:
data
.
method
,
url
:
data
.
submit_url
});
this
.
subview
.
register
=
new
RegisterView
({
fields
:
data
.
fields
,
model
:
model
,
thirdPartyAuth
:
this
.
thirdPartyAuth
,
platformName
:
this
.
platformName
});
// Listen for 'auth-complete' event so we can enroll/redirect the user appropriately.
this
.
listenTo
(
this
.
subview
.
register
,
'auth-complete'
,
this
.
authComplete
);
},
institution_login
:
function
(
unused
)
{
this
.
subview
.
institutionLogin
=
new
InstitutionLoginView
({
thirdPartyAuth
:
this
.
thirdPartyAuth
,
platformName
:
this
.
platformName
,
mode
:
this
.
activeForm
});
this
.
subview
.
institutionLogin
.
render
();
},
hinted_login
:
function
(
unused
)
{
this
.
subview
.
hintedLogin
=
new
HintedLoginView
({
thirdPartyAuth
:
this
.
thirdPartyAuth
,
hintedProvider
:
this
.
thirdPartyAuthHint
,
platformName
:
this
.
platformName
});
this
.
subview
.
hintedLogin
.
render
();
}
},
// Listen for 'auth-complete' event so we can enroll/redirect the user appropriately.
passwordEmailSent
:
function
()
{
this
.
listenTo
(
this
.
subview
.
register
,
'auth-complete'
,
this
.
authComplete
);
var
$loginAnchorElement
=
$
(
'#login-anchor'
);
this
.
element
.
hide
(
$
(
this
.
el
).
find
(
'#password-reset-anchor'
)
);
this
.
element
.
show
(
$loginAnchorElement
);
this
.
element
.
scrollTop
(
$loginAnchorElement
);
},
},
institution_login
:
function
(
unused
)
{
resetPassword
:
function
()
{
this
.
subview
.
institutionLogin
=
new
edx
.
student
.
account
.
InstitutionLoginView
({
window
.
analytics
.
track
(
'edx.bi.password_reset_form.viewed'
,
{
thirdPartyAuth
:
this
.
thirdPartyAuth
,
category
:
'user-engagement'
platformName
:
this
.
platformName
,
mode
:
this
.
activeForm
});
});
this
.
subview
.
institutionLogin
.
render
();
this
.
element
.
hide
(
$
(
this
.
el
).
find
(
'#login-anchor'
)
);
this
.
loadForm
(
'reset'
);
this
.
element
.
scrollTop
(
$
(
'#password-reset-anchor'
)
);
},
},
hinted_login
:
function
(
unused
)
{
toggleForm
:
function
(
e
)
{
this
.
subview
.
hintedLogin
=
new
edx
.
student
.
account
.
HintedLoginView
({
var
type
=
$
(
e
.
currentTarget
).
data
(
'type'
),
thirdPartyAuth
:
this
.
thirdPartyAuth
,
$form
=
$
(
'#'
+
type
+
'-form'
),
hintedProvider
:
this
.
thirdPartyAuthHint
,
$anchor
=
$
(
'#'
+
type
+
'-anchor'
),
platformName
:
this
.
platformName
queryParams
=
url
(
'?'
),
queryStr
=
queryParams
.
length
>
0
?
'?'
+
queryParams
:
''
;
e
.
preventDefault
();
window
.
analytics
.
track
(
'edx.bi.'
+
type
+
'_form.toggled'
,
{
category
:
'user-engagement'
});
});
this
.
subview
.
hintedLogin
.
render
();
// Load the form. Institution login is always refreshed since it changes based on the previous form.
}
if
(
!
this
.
form
.
isLoaded
(
$form
)
||
type
==
'institution_login'
)
{
},
this
.
loadForm
(
type
);
}
passwordEmailSent
:
function
()
{
this
.
activeForm
=
type
;
this
.
element
.
hide
(
$
(
this
.
el
).
find
(
'#password-reset-anchor'
)
);
this
.
element
.
show
(
$
(
'#login-anchor'
)
);
this
.
element
.
scrollTop
(
$
(
'#login-anchor'
)
);
},
resetPassword
:
function
()
{
window
.
analytics
.
track
(
'edx.bi.password_reset_form.viewed'
,
{
category
:
'user-engagement'
});
this
.
element
.
hide
(
$
(
this
.
el
).
find
(
'#login-anchor'
)
);
this
.
loadForm
(
'reset'
);
this
.
element
.
scrollTop
(
$
(
'#password-reset-anchor'
)
);
},
toggleForm
:
function
(
e
)
{
var
type
=
$
(
e
.
currentTarget
).
data
(
'type'
),
$form
=
$
(
'#'
+
type
+
'-form'
),
$anchor
=
$
(
'#'
+
type
+
'-anchor'
),
queryParams
=
url
(
'?'
),
queryStr
=
queryParams
.
length
>
0
?
'?'
+
queryParams
:
''
;
e
.
preventDefault
();
window
.
analytics
.
track
(
'edx.bi.'
+
type
+
'_form.toggled'
,
{
category
:
'user-engagement'
});
// Load the form. Institution login is always refreshed since it changes based on the previous form.
if
(
!
this
.
form
.
isLoaded
(
$form
)
||
type
==
"institution_login"
)
{
this
.
loadForm
(
type
);
}
this
.
activeForm
=
type
;
this
.
element
.
hide
(
$
(
this
.
el
).
find
(
'.submission-success'
)
);
this
.
element
.
hide
(
$
(
this
.
el
).
find
(
'.submission-success'
)
);
this
.
element
.
hide
(
$
(
this
.
el
).
find
(
'.form-wrapper'
)
);
this
.
element
.
hide
(
$
(
this
.
el
).
find
(
'.form-wrapper'
)
);
this
.
element
.
show
(
$form
);
this
.
element
.
show
(
$form
);
this
.
element
.
scrollTop
(
$anchor
);
this
.
element
.
scrollTop
(
$anchor
);
// Update url without reloading page
// Update url without reloading page
if
(
type
!=
"institution_login"
)
{
if
(
type
!=
'institution_login'
)
{
History
.
pushState
(
null
,
document
.
title
,
'/'
+
type
+
queryStr
);
History
.
pushState
(
null
,
document
.
title
,
'/'
+
type
+
queryStr
);
}
}
analytics
.
page
(
'login_and_registration'
,
type
);
analytics
.
page
(
'login_and_registration'
,
type
);
// Focus on the form
// Focus on the form
$
(
"#"
+
type
).
focus
();
$
(
'#'
+
type
).
focus
();
},
},
/**
/**
* Once authentication has completed successfully:
* Once authentication has completed successfully:
*
*
* If we're in a third party auth pipeline, we must complete the pipeline.
* If we're in a third party auth pipeline, we must complete the pipeline.
* Otherwise, redirect to the specified next step.
* Otherwise, redirect to the specified next step.
*
*
*/
*/
authComplete
:
function
()
{
authComplete
:
function
()
{
if
(
this
.
thirdPartyAuth
&&
this
.
thirdPartyAuth
.
finishAuthUrl
)
{
if
(
this
.
thirdPartyAuth
&&
this
.
thirdPartyAuth
.
finishAuthUrl
)
{
this
.
redirect
(
this
.
thirdPartyAuth
.
finishAuthUrl
);
this
.
redirect
(
this
.
thirdPartyAuth
.
finishAuthUrl
);
// Note: the third party auth URL likely contains another redirect URL embedded inside
// Note: the third party auth URL likely contains another redirect URL embedded inside
}
else
{
}
else
{
this
.
redirect
(
this
.
nextUrl
);
this
.
redirect
(
this
.
nextUrl
);
}
}
},
},
/**
/**
* 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
.
replace
(
url
);
window
.
location
.
replace
(
url
);
},
form
:
{
isLoaded
:
function
(
$form
)
{
return
$form
.
html
().
length
>
0
;
}
},
/* Helper method to toggle display
* including accessibility considerations
*/
element
:
{
hide
:
function
(
$el
)
{
$el
.
addClass
(
'hidden'
);
},
},
scrollTop
:
function
(
$el
)
{
form
:
{
// Scroll to top of selected element
isLoaded
:
function
(
$form
)
{
$
(
'html,body'
).
animate
({
return
$form
.
html
().
length
>
0
;
scrollTop
:
$el
.
offset
().
top
}
},
'slow'
);
},
},
show
:
function
(
$el
)
{
/* Helper method to toggle display
$el
.
removeClass
(
'hidden'
);
* including accessibility considerations
*/
element
:
{
hide
:
function
(
$el
)
{
$el
.
addClass
(
'hidden'
);
},
scrollTop
:
function
(
$el
)
{
// Scroll to top of selected element
$
(
'html,body'
).
animate
({
scrollTop
:
$el
.
offset
().
top
},
'slow'
);
},
show
:
function
(
$el
)
{
$el
.
removeClass
(
'hidden'
);
}
}
}
}
}
);
});
});
})
(
jQuery
,
_
,
_
.
str
,
Backbone
,
History
);
})
.
call
(
this
,
define
||
RequireJS
.
define
);
lms/static/js/student_account/views/FormView.js
View file @
d2a47908
var
edx
=
edx
||
{};
;(
function
(
define
)
{
(
function
(
$
,
_
,
Backbone
,
gettext
)
{
'use strict'
;
'use strict'
;
define
([
'jquery'
,
'underscore'
,
'backbone'
,
'js/utils/edx.utils.validate'
],
function
(
$
,
_
,
Backbone
,
EdxUtilsValidate
)
{
edx
.
student
=
edx
.
student
||
{};
return
Backbone
.
View
.
extend
({
edx
.
student
.
account
=
edx
.
student
.
account
||
{};
tagName
:
'form'
,
edx
.
student
.
account
.
FormView
=
Backbone
.
View
.
extend
({
tagName
:
'form'
,
el
:
''
,
el
:
''
,
tpl
:
''
,
tpl
:
''
,
fieldTpl
:
'#form_field-tpl'
,
fieldTpl
:
'#form_field-tpl'
,
events
:
{},
events
:
{},
errors
:
[],
errors
:
[],
formType
:
''
,
formType
:
''
,
$form
:
{},
$form
:
{},
fields
:
[],
fields
:
[],
// String to append to required label fields
// String to append to required label fields
requiredStr
:
'*'
,
requiredStr
:
'*'
,
submitButton
:
''
,
submitButton
:
''
,
initialize
:
function
(
data
)
{
initialize
:
function
(
data
)
{
this
.
model
=
data
.
model
;
this
.
model
=
data
.
model
;
this
.
preRender
(
data
);
this
.
preRender
(
data
);
this
.
tpl
=
$
(
this
.
tpl
).
html
();
this
.
tpl
=
$
(
this
.
tpl
).
html
();
this
.
fieldTpl
=
$
(
this
.
fieldTpl
).
html
();
this
.
fieldTpl
=
$
(
this
.
fieldTpl
).
html
();
this
.
buildForm
(
data
.
fields
);
this
.
buildForm
(
data
.
fields
);
this
.
listenTo
(
this
.
model
,
'error'
,
this
.
saveError
);
this
.
listenTo
(
this
.
model
,
'error'
,
this
.
saveError
);
},
},
/* Allows extended views to add custom
/* Allows extended views to add custom
* init steps without needing to repeat
* init steps without needing to repeat
* default init steps
* default init steps
*/
*/
preRender
:
function
(
data
)
{
preRender
:
function
(
data
)
{
/* Custom code goes here */
/* Custom code goes here */
return
data
;
return
data
;
},
},
render
:
function
(
html
)
{
render
:
function
(
html
)
{
var
fields
=
html
||
''
;
var
fields
=
html
||
''
;
$
(
this
.
el
).
html
(
_
.
template
(
this
.
tpl
,
{
$
(
this
.
el
).
html
(
_
.
template
(
this
.
tpl
,
{
fields
:
fields
fields
:
fields
}));
}));
this
.
postRender
();
this
.
postRender
();
return
this
;
return
this
;
},
},
postRender
:
function
()
{
postRender
:
function
()
{
var
$container
=
$
(
this
.
el
);
var
$container
=
$
(
this
.
el
);
this
.
$form
=
$container
.
find
(
'form'
);
this
.
$errors
=
$container
.
find
(
'.submission-error'
);
this
.
$submitButton
=
$container
.
find
(
this
.
submitButton
);
},
this
.
$form
=
$container
.
find
(
'form'
);
buildForm
:
function
(
data
)
{
this
.
$errors
=
$container
.
find
(
'.submission-error'
);
var
html
=
[],
this
.
$submitButton
=
$container
.
find
(
this
.
submitButton
);
i
,
},
len
=
data
.
length
,
fieldTpl
=
this
.
fieldTpl
;
buildForm
:
function
(
data
)
{
this
.
fields
=
data
;
var
html
=
[],
i
,
len
=
data
.
length
,
fieldTpl
=
this
.
fieldTpl
;
this
.
fields
=
data
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
data
[
i
].
errorMessages
)
{
data
[
i
].
errorMessages
=
this
.
escapeStrings
(
data
[
i
].
errorMessages
);
}
for
(
i
=
0
;
i
<
len
;
i
++
)
{
html
.
push
(
_
.
template
(
fieldTpl
,
$
.
extend
(
data
[
i
],
{
if
(
data
[
i
].
errorMessages
)
{
form
:
this
.
formType
,
data
[
i
].
errorMessages
=
this
.
escapeStrings
(
data
[
i
].
errorMessages
);
requiredStr
:
this
.
requiredStr
})
)
);
}
}
html
.
push
(
_
.
template
(
fieldTpl
,
$
.
extend
(
data
[
i
],
{
this
.
render
(
html
.
join
(
''
)
);
form
:
this
.
formType
,
},
requiredStr
:
this
.
requiredStr
})
)
);
}
this
.
render
(
html
.
join
(
''
)
);
},
/* Helper method to toggle display
/* Helper method to toggle display
* including accessibility considerations
* including accessibility considerations
*/
*/
element
:
{
element
:
{
hide
:
function
(
$el
)
{
hide
:
function
(
$el
)
{
if
(
$el
)
{
if
(
$el
)
{
$el
.
addClass
(
'hidden'
);
$el
.
addClass
(
'hidden'
);
}
},
scrollTop
:
function
(
$el
)
{
// Scroll to top of selected element
$
(
'html,body'
).
animate
({
scrollTop
:
$el
.
offset
().
top
},
'slow'
);
},
show
:
function
(
$el
)
{
if
(
$el
)
{
$el
.
removeClass
(
'hidden'
);
}
}
}
},
},
scrollTop
:
function
(
$el
)
{
escapeStrings
:
function
(
obj
)
{
// Scroll to top of selected element
_
.
each
(
obj
,
function
(
val
,
key
)
{
$
(
'html,body'
).
animate
({
obj
[
key
]
=
_
.
escape
(
val
);
scrollTop
:
$el
.
offset
().
top
});
},
'slow'
);
return
obj
;
},
},
show
:
function
(
$el
)
{
focusFirstError
:
function
()
{
if
(
$el
)
{
var
$error
=
this
.
$form
.
find
(
'.error'
).
first
(),
$el
.
removeClass
(
'hidden'
);
$field
=
{},
$parent
=
{};
if
(
$error
.
is
(
'label'
)
)
{
$parent
=
$error
.
parent
(
'.form-field'
);
$error
=
$parent
.
find
(
'input'
)
||
$parent
.
find
(
'select'
);
}
else
{
$field
=
$error
;
}
}
}
},
escapeStrings
:
function
(
obj
)
{
_
.
each
(
obj
,
function
(
val
,
key
)
{
obj
[
key
]
=
_
.
escape
(
val
);
});
return
obj
;
},
focusFirstError
:
function
()
{
var
$error
=
this
.
$form
.
find
(
'.error'
).
first
(),
$field
=
{},
$parent
=
{};
if
(
$error
.
is
(
'label'
)
)
{
$parent
=
$error
.
parent
(
'.form-field'
);
$error
=
$parent
.
find
(
'input'
)
||
$parent
.
find
(
'select'
);
}
else
{
$field
=
$error
;
}
$error
.
focus
();
$error
.
focus
();
},
},
forgotPassword
:
function
(
event
)
{
forgotPassword
:
function
(
event
)
{
event
.
preventDefault
();
event
.
preventDefault
();
this
.
trigger
(
'password-help'
);
this
.
trigger
(
'password-help'
);
},
},
getFormData
:
function
()
{
getFormData
:
function
()
{
var
obj
=
{},
var
obj
=
{},
$form
=
this
.
$form
,
$form
=
this
.
$form
,
elements
=
$form
[
0
].
elements
,
elements
=
$form
[
0
].
elements
,
i
,
i
,
len
=
elements
.
length
,
len
=
elements
.
length
,
$el
,
$el
,
$label
,
$label
,
key
=
''
,
key
=
''
,
errors
=
[],
errors
=
[],
test
=
{};
test
=
{};
for
(
i
=
0
;
i
<
len
;
i
++
)
{
for
(
i
=
0
;
i
<
len
;
i
++
)
{
$el
=
$
(
elements
[
i
]
);
$el
=
$
(
elements
[
i
]
);
$label
=
$form
.
find
(
'label[for='
+
$el
.
attr
(
'id'
)
+
']'
);
$label
=
$form
.
find
(
'label[for='
+
$el
.
attr
(
'id'
)
+
']'
);
key
=
$el
.
attr
(
'name'
)
||
false
;
key
=
$el
.
attr
(
'name'
)
||
false
;
if
(
key
)
{
if
(
key
)
{
test
=
this
.
validate
(
elements
[
i
]
);
test
=
this
.
validate
(
elements
[
i
]
);
if
(
test
.
isValid
)
{
if
(
test
.
isValid
)
{
obj
[
key
]
=
$el
.
attr
(
'type'
)
===
'checkbox'
?
$el
.
is
(
':checked'
)
:
$el
.
val
();
obj
[
key
]
=
$el
.
attr
(
'type'
)
===
'checkbox'
?
$el
.
is
(
':checked'
)
:
$el
.
val
();
$el
.
removeClass
(
'error'
);
$el
.
removeClass
(
'error'
);
$label
.
removeClass
(
'error'
);
$label
.
removeClass
(
'error'
);
}
else
{
}
else
{
errors
.
push
(
test
.
message
);
errors
.
push
(
test
.
message
);
$el
.
addClass
(
'error'
);
$el
.
addClass
(
'error'
);
$label
.
addClass
(
'error'
);
$label
.
addClass
(
'error'
);
}
}
}
}
}
}
this
.
errors
=
_
.
uniq
(
errors
);
this
.
errors
=
_
.
uniq
(
errors
);
return
obj
;
},
return
obj
;
saveError
:
function
(
error
)
{
},
this
.
errors
=
[
'<li>'
+
error
.
responseText
+
'</li>'
];
this
.
setErrors
();
this
.
toggleDisableButton
(
false
);
},
saveError
:
function
(
error
)
{
setErrors
:
function
()
{
this
.
errors
=
[
'<li>'
+
error
.
responseText
+
'</li>'
];
var
$msg
=
this
.
$errors
.
find
(
'.message-copy'
),
this
.
setErrors
();
html
=
[],
this
.
toggleDisableButton
(
false
);
errors
=
this
.
errors
,
},
i
,
len
=
errors
.
length
;
setErrors
:
function
()
{
for
(
i
=
0
;
i
<
len
;
i
++
)
{
var
$msg
=
this
.
$errors
.
find
(
'.message-copy'
),
html
.
push
(
errors
[
i
]
);
html
=
[],
}
errors
=
this
.
errors
,
i
,
len
=
errors
.
length
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
$msg
.
html
(
html
.
join
(
''
)
);
html
.
push
(
errors
[
i
]
);
}
$msg
.
html
(
html
.
join
(
''
)
);
this
.
element
.
show
(
this
.
$errors
);
this
.
element
.
show
(
this
.
$errors
);
// Scroll to error messages
$
(
'html,body'
).
animate
({
scrollTop
:
this
.
$errors
.
offset
().
top
},
'slow'
);
// Focus on first error field
this
.
focusFirstError
();
},
// Scroll to error messages
submitForm
:
function
(
event
)
{
$
(
'html,body'
).
animate
({
var
data
=
this
.
getFormData
();
scrollTop
:
this
.
$errors
.
offset
().
top
},
'slow'
);
// Focus on first error field
if
(
!
_
.
isUndefined
(
event
))
{
this
.
focusFirstError
();
event
.
preventDefault
();
},
}
submitForm
:
function
(
event
)
{
this
.
toggleDisableButton
(
true
);
var
data
=
this
.
getFormData
();
if
(
!
_
.
isUndefined
(
event
))
{
if
(
!
_
.
compact
(
this
.
errors
).
length
)
{
event
.
preventDefault
();
this
.
model
.
set
(
data
);
}
this
.
model
.
save
();
this
.
toggleErrorMsg
(
false
);
}
else
{
this
.
toggleErrorMsg
(
true
);
}
this
.
toggleDisableButton
(
true
);
this
.
postFormSubmission
();
},
if
(
!
_
.
compact
(
this
.
errors
).
length
)
{
/* Allows extended views to add custom
this
.
model
.
set
(
data
);
* code after form submission
this
.
model
.
save
();
*/
this
.
toggleErrorMsg
(
false
);
postFormSubmission
:
function
()
{
}
else
{
return
true
;
this
.
toggleErrorMsg
(
true
);
},
}
this
.
postFormSubmission
();
toggleErrorMsg
:
function
(
show
)
{
},
if
(
show
)
{
this
.
setErrors
();
this
.
toggleDisableButton
(
false
);
}
else
{
this
.
element
.
hide
(
this
.
$errors
);
}
},
/* Allows extended views to add custom
/**
* code after form submission
* If a form button is defined for this form, this will disable the button on
*/
* submit, and re-enable the button if an error occurs.
postFormSubmission
:
function
()
{
*
return
true
;
* Args:
},
* disabled (boolean): If set to TRUE, disable the button.
*
*/
toggleDisableButton
:
function
(
disabled
)
{
if
(
this
.
$submitButton
)
{
this
.
$submitButton
.
attr
(
'disabled'
,
disabled
);
}
},
toggleErrorMsg
:
function
(
show
)
{
validate
:
function
(
$el
)
{
if
(
show
)
{
return
EdxUtilsValidate
.
validate
(
$el
);
this
.
setErrors
();
this
.
toggleDisableButton
(
false
);
}
else
{
this
.
element
.
hide
(
this
.
$errors
);
}
}
},
});
/**
* If a form button is defined for this form, this will disable the button on
* submit, and re-enable the button if an error occurs.
*
* Args:
* disabled (boolean): If set to TRUE, disable the button.
*
*/
toggleDisableButton
:
function
(
disabled
)
{
if
(
this
.
$submitButton
)
{
this
.
$submitButton
.
attr
(
'disabled'
,
disabled
);
}
},
validate
:
function
(
$el
)
{
return
edx
.
utils
.
validate
(
$el
);
}
});
});
}).
call
(
this
,
define
||
RequireJS
.
define
);
})(
jQuery
,
_
,
Backbone
,
gettext
);
lms/static/js/student_account/views/HintedLoginView.js
View file @
d2a47908
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
);
lms/static/js/student_account/views/InstitutionLoginView.js
View file @
d2a47908
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
,
_
,
Backbo
ne
);
})
.
call
(
this
,
define
||
RequireJS
.
defi
ne
);
lms/static/js/student_account/views/LoginView.js
View file @
d2a47908
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
);
lms/static/js/student_account/views/PasswordResetView.js
View file @
d2a47908
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
);
lms/static/js/student_account/views/RegisterView.js
View file @
d2a47908
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
);
lms/static/js_test.yml
View file @
d2a47908
...
@@ -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
:
...
...
lms/static/lms/js/build.js
View file @
d2a47908
...
@@ -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'
,
...
...
lms/templates/student_account/login_and_register.html
View file @
d2a47908
<
%!
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'):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment