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
ca1f2f77
Commit
ca1f2f77
authored
Apr 13, 2015
by
muhammad-ammar
Committed by
Andy Armstrong
Apr 17, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Jasmine tests for upload/remove profile image on learner profile page.
TNL-1538
parent
adf111e4
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
355 additions
and
34 deletions
+355
-34
lms/djangoapps/student_profile/test/test_views.py
+20
-0
lms/static/js/spec/main.js
+1
-0
lms/static/js/spec/student_account/helpers.js
+8
-2
lms/static/js/spec/student_profile/helpers.js
+17
-11
lms/static/js/spec/student_profile/learner_profile_factory_spec.js
+10
-3
lms/static/js/spec/student_profile/learner_profile_fields_spec.js
+276
-0
lms/static/js/spec/student_profile/learner_profile_view_spec.js
+4
-3
lms/static/js/student_profile/views/learner_profile_fields.js
+7
-3
lms/static/js/views/fields.js
+10
-5
lms/static/sass/views/_learner-profile.scss
+1
-0
lms/templates/fields/message_banner.underscore
+0
-0
lms/templates/student_profile/learner_profile.html
+1
-7
No files found.
lms/djangoapps/student_profile/test/test_views.py
View file @
ca1f2f77
...
@@ -53,6 +53,26 @@ class LearnerProfileViewTest(UrlResetMixin, TestCase):
...
@@ -53,6 +53,26 @@ class LearnerProfileViewTest(UrlResetMixin, TestCase):
reverse
(
'preferences_api'
,
kwargs
=
{
'username'
:
self
.
user
.
username
})
reverse
(
'preferences_api'
,
kwargs
=
{
'username'
:
self
.
user
.
username
})
)
)
self
.
assertEqual
(
context
[
'data'
][
'profile_image_upload_url'
],
reverse
(
"profile_image_upload"
,
kwargs
=
{
'username'
:
self
.
user
.
username
})
)
self
.
assertEqual
(
context
[
'data'
][
'profile_image_remove_url'
],
reverse
(
'profile_image_remove'
,
kwargs
=
{
'username'
:
self
.
user
.
username
})
)
self
.
assertEqual
(
context
[
'data'
][
'profile_image_max_bytes'
],
settings
.
PROFILE_IMAGE_MAX_BYTES
)
self
.
assertEqual
(
context
[
'data'
][
'profile_image_min_bytes'
],
settings
.
PROFILE_IMAGE_MIN_BYTES
)
self
.
assertEqual
(
context
[
'data'
][
'account_settings_page_url'
],
reverse
(
'account_settings'
))
self
.
assertEqual
(
context
[
'data'
][
'account_settings_page_url'
],
reverse
(
'account_settings'
))
for
attribute
in
self
.
CONTEXT_DATA
:
for
attribute
in
self
.
CONTEXT_DATA
:
...
...
lms/static/js/spec/main.js
View file @
ca1f2f77
...
@@ -598,6 +598,7 @@
...
@@ -598,6 +598,7 @@
'lms/include/js/spec/views/fields_spec.js'
,
'lms/include/js/spec/views/fields_spec.js'
,
'lms/include/js/spec/student_profile/learner_profile_factory_spec.js'
,
'lms/include/js/spec/student_profile/learner_profile_factory_spec.js'
,
'lms/include/js/spec/student_profile/learner_profile_view_spec.js'
,
'lms/include/js/spec/student_profile/learner_profile_view_spec.js'
,
'lms/include/js/spec/student_profile/learner_profile_fields_spec.js'
,
'lms/include/js/spec/verify_student/pay_and_verify_view_spec.js'
,
'lms/include/js/spec/verify_student/pay_and_verify_view_spec.js'
,
'lms/include/js/spec/verify_student/webcam_photo_view_spec.js'
,
'lms/include/js/spec/verify_student/webcam_photo_view_spec.js'
,
'lms/include/js/spec/verify_student/image_input_spec.js'
,
'lms/include/js/spec/verify_student/image_input_spec.js'
,
...
...
lms/static/js/spec/student_account/helpers.js
View file @
ca1f2f77
...
@@ -6,11 +6,15 @@ define(['underscore'], function(_) {
...
@@ -6,11 +6,15 @@ define(['underscore'], function(_) {
var
IMAGE_UPLOAD_API_URL
=
'/api/profile_images/v0/staff/upload'
;
var
IMAGE_UPLOAD_API_URL
=
'/api/profile_images/v0/staff/upload'
;
var
IMAGE_REMOVE_API_URL
=
'/api/profile_images/v0/staff/remove'
;
var
IMAGE_REMOVE_API_URL
=
'/api/profile_images/v0/staff/remove'
;
var
PROFILE_IMAGE
=
{
image_url_large
:
'/media/profile-images/image.jpg'
,
has_image
:
true
};
var
USER_ACCOUNTS_DATA
=
{
var
USER_ACCOUNTS_DATA
=
{
username
:
'student'
,
username
:
'student'
,
name
:
'Student'
,
name
:
'Student'
,
email
:
'student@edx.org'
,
email
:
'student@edx.org'
,
level_of_education
:
'0'
,
level_of_education
:
'0'
,
gender
:
'0'
,
gender
:
'0'
,
year_of_birth
:
'0'
,
year_of_birth
:
'0'
,
...
@@ -18,7 +22,8 @@ define(['underscore'], function(_) {
...
@@ -18,7 +22,8 @@ define(['underscore'], function(_) {
language
:
'0'
,
language
:
'0'
,
bio
:
"About the student"
,
bio
:
"About the student"
,
language_proficiencies
:
[{
code
:
'1'
}],
language_proficiencies
:
[{
code
:
'1'
}],
requires_parental_consent
:
true
requires_parental_consent
:
true
,
profile_image
:
PROFILE_IMAGE
};
};
var
USER_PREFERENCES_DATA
=
{
var
USER_PREFERENCES_DATA
=
{
...
@@ -101,6 +106,7 @@ define(['underscore'], function(_) {
...
@@ -101,6 +106,7 @@ define(['underscore'], function(_) {
IMAGE_REMOVE_API_URL
:
IMAGE_REMOVE_API_URL
,
IMAGE_REMOVE_API_URL
:
IMAGE_REMOVE_API_URL
,
IMAGE_MAX_BYTES
:
IMAGE_MAX_BYTES
,
IMAGE_MAX_BYTES
:
IMAGE_MAX_BYTES
,
IMAGE_MIN_BYTES
:
IMAGE_MIN_BYTES
,
IMAGE_MIN_BYTES
:
IMAGE_MIN_BYTES
,
PROFILE_IMAGE
:
PROFILE_IMAGE
,
USER_ACCOUNTS_DATA
:
USER_ACCOUNTS_DATA
,
USER_ACCOUNTS_DATA
:
USER_ACCOUNTS_DATA
,
USER_PREFERENCES_DATA
:
USER_PREFERENCES_DATA
,
USER_PREFERENCES_DATA
:
USER_PREFERENCES_DATA
,
FIELD_OPTIONS
:
FIELD_OPTIONS
,
FIELD_OPTIONS
:
FIELD_OPTIONS
,
...
...
lms/static/js/spec/student_profile/helpers.js
View file @
ca1f2f77
...
@@ -9,10 +9,12 @@ define(['underscore'], function(_) {
...
@@ -9,10 +9,12 @@ define(['underscore'], function(_) {
expect
(
fieldTitle
).
toBe
(
view
.
options
.
title
);
expect
(
fieldTitle
).
toBe
(
view
.
options
.
title
);
}
}
if
(
'fieldValue'
in
view
)
{
if
(
'fieldValue'
in
view
||
'imageUrl'
in
view
)
{
expect
(
view
.
model
.
get
(
view
.
options
.
valueAttribute
)).
toBeTruthy
();
expect
(
view
.
model
.
get
(
view
.
options
.
valueAttribute
)).
toBeTruthy
();
if
(
view
.
fieldValue
())
{
if
(
'imageUrl'
in
view
)
{
expect
(
$
(
$element
.
find
(
'.image-frame'
)[
0
]).
attr
(
'src'
)).
toBe
(
view
.
imageUrl
());
}
else
if
(
view
.
fieldValue
())
{
expect
(
view
.
fieldValue
()).
toBe
(
view
.
modelValue
());
expect
(
view
.
fieldValue
()).
toBe
(
view
.
modelValue
());
}
else
if
(
'optionForValue'
in
view
)
{
}
else
if
(
'optionForValue'
in
view
)
{
...
@@ -43,9 +45,11 @@ define(['underscore'], function(_) {
...
@@ -43,9 +45,11 @@ define(['underscore'], function(_) {
var
sectionOneFieldElements
=
$
(
learnerProfileView
.
$
(
'.wrapper-profile-section-one'
)).
find
(
'.u-field'
);
var
sectionOneFieldElements
=
$
(
learnerProfileView
.
$
(
'.wrapper-profile-section-one'
)).
find
(
'.u-field'
);
expect
(
sectionOneFieldElements
.
length
).
toBe
(
learnerProfileView
.
options
.
sectionOneFieldViews
.
length
);
expect
(
sectionOneFieldElements
.
length
).
toBe
(
4
);
expectProfileElementContainsField
(
sectionOneFieldElements
[
0
],
learnerProfileView
.
options
.
profileImageFieldView
);
expectProfileElementContainsField
(
sectionOneFieldElements
[
1
],
learnerProfileView
.
options
.
usernameFieldView
);
_
.
each
(
sectionOneFieldElements
,
function
(
sectionFieldElement
,
fieldIndex
)
{
_
.
each
(
_
.
rest
(
sectionOneFieldElements
,
2
)
,
function
(
sectionFieldElement
,
fieldIndex
)
{
expectProfileElementContainsField
(
expectProfileElementContainsField
(
sectionFieldElement
,
sectionFieldElement
,
learnerProfileView
.
options
.
sectionOneFieldViews
[
fieldIndex
]
learnerProfileView
.
options
.
sectionOneFieldViews
[
fieldIndex
]
...
@@ -79,13 +83,15 @@ define(['underscore'], function(_) {
...
@@ -79,13 +83,15 @@ define(['underscore'], function(_) {
var
sectionOneFieldElements
=
$
(
learnerProfileView
.
$
(
'.wrapper-profile-section-one'
)).
find
(
'.u-field'
);
var
sectionOneFieldElements
=
$
(
learnerProfileView
.
$
(
'.wrapper-profile-section-one'
)).
find
(
'.u-field'
);
expect
(
sectionOneFieldElements
.
length
).
toBe
(
1
);
expect
(
sectionOneFieldElements
.
length
).
toBe
(
2
);
_
.
each
(
sectionOneFieldElements
,
function
(
sectionFieldElement
,
fieldIndex
)
{
expectProfileElementContainsField
(
expectProfileElementContainsField
(
sectionOneFieldElements
[
0
],
sectionFieldElement
,
learnerProfileView
.
options
.
profileImageFieldView
learnerProfileView
.
options
.
sectionOneFieldViews
[
fieldIndex
]
);
);
expectProfileElementContainsField
(
});
sectionOneFieldElements
[
1
],
learnerProfileView
.
options
.
usernameFieldView
);
if
(
othersProfile
)
{
if
(
othersProfile
)
{
expect
(
$
(
'.profile-private--message'
).
text
())
expect
(
$
(
'.profile-private--message'
).
text
())
...
...
lms/static/js/spec/student_profile/learner_profile_factory_spec.js
View file @
ca1f2f77
...
@@ -6,7 +6,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
...
@@ -6,7 +6,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
'js/student_account/models/user_preferences_model'
,
'js/student_account/models/user_preferences_model'
,
'js/student_profile/views/learner_profile_view'
,
'js/student_profile/views/learner_profile_view'
,
'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/views/message_banner'
],
],
function
(
Backbone
,
$
,
_
,
AjaxHelpers
,
TemplateHelpers
,
Helpers
,
LearnerProfileHelpers
,
FieldViews
,
function
(
Backbone
,
$
,
_
,
AjaxHelpers
,
TemplateHelpers
,
Helpers
,
LearnerProfileHelpers
,
FieldViews
,
UserAccountModel
,
UserPreferencesModel
,
LearnerProfileView
,
LearnerProfileFields
,
LearnerProfilePage
)
{
UserAccountModel
,
UserPreferencesModel
,
LearnerProfileView
,
LearnerProfileFields
,
LearnerProfilePage
)
{
...
@@ -17,10 +18,12 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
...
@@ -17,10 +18,12 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
var
requests
;
var
requests
;
beforeEach
(
function
()
{
beforeEach
(
function
()
{
setFixtures
(
'<div class="wrapper-profile"><div class="ui-loading-indicator"><p><span class="spin"><i class="icon fa fa-refresh"></i></span> <span class="copy">Loading</span></p></div><div class="ui-loading-error is-hidden"><i class="fa fa-exclamation-triangle message-error" aria-hidden=true></i><span class="copy">An error occurred. Please reload the page.</span></div></div>'
);
setFixtures
(
'<div class="
message-banner"></div><div class="
wrapper-profile"><div class="ui-loading-indicator"><p><span class="spin"><i class="icon fa fa-refresh"></i></span> <span class="copy">Loading</span></p></div><div class="ui-loading-error is-hidden"><i class="fa fa-exclamation-triangle message-error" aria-hidden=true></i><span class="copy">An error occurred. Please reload the page.</span></div></div>'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_readonly'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_readonly'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_dropdown'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_dropdown'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_textarea'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_textarea'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_image'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/message_banner'
);
TemplateHelpers
.
installTemplate
(
'templates/student_profile/learner_profile'
);
TemplateHelpers
.
installTemplate
(
'templates/student_profile/learner_profile'
);
});
});
...
@@ -32,7 +35,11 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
...
@@ -32,7 +35,11 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
'account_settings_page_url'
:
Helpers
.
USER_ACCOUNTS_API_URL
,
'account_settings_page_url'
:
Helpers
.
USER_ACCOUNTS_API_URL
,
'country_options'
:
Helpers
.
FIELD_OPTIONS
,
'country_options'
:
Helpers
.
FIELD_OPTIONS
,
'language_options'
:
Helpers
.
FIELD_OPTIONS
,
'language_options'
:
Helpers
.
FIELD_OPTIONS
,
'has_preferences_access'
:
true
'has_preferences_access'
:
true
,
'profile_image_max_bytes'
:
Helpers
.
IMAGE_MAX_BYTES
,
'profile_image_min_bytes'
:
Helpers
.
IMAGE_MIN_BYTES
,
'profile_image_upload_url'
:
Helpers
.
IMAGE_UPLOAD_API_URL
,
'profile_image_remove_url'
:
Helpers
.
IMAGE_REMOVE_API_URL
});
});
};
};
...
...
lms/static/js/spec/student_profile/learner_profile_fields_spec.js
0 → 100644
View file @
ca1f2f77
define
([
'backbone'
,
'jquery'
,
'underscore'
,
'js/common_helpers/ajax_helpers'
,
'js/common_helpers/template_helpers'
,
'js/spec/student_account/helpers'
,
'js/student_account/models/user_account_model'
,
'js/student_profile/views/learner_profile_fields'
,
'js/views/message_banner'
],
function
(
Backbone
,
$
,
_
,
AjaxHelpers
,
TemplateHelpers
,
Helpers
,
UserAccountModel
,
LearnerProfileFields
,
MessageBannerView
)
{
'use strict'
;
describe
(
"edx.user.LearnerProfileFields"
,
function
()
{
var
createImageView
=
function
(
ownProfile
,
hasImage
,
imageMaxBytes
,
imageMinBytes
,
yearOfBirth
)
{
var
imageData
=
{
image_url_large
:
'/media/profile-images/default.jpg'
,
has_image
:
hasImage
?
true
:
false
};
yearOfBirth
=
_
.
isUndefined
(
yearOfBirth
)
?
1989
:
yearOfBirth
;
var
accountSettingsModel
=
new
UserAccountModel
();
accountSettingsModel
.
set
({
'profile_image'
:
imageData
});
accountSettingsModel
.
set
({
'year_of_birth'
:
yearOfBirth
});
accountSettingsModel
.
set
({
'requires_parental_consent'
:
_
.
isEmpty
(
yearOfBirth
)
?
true
:
false
});
accountSettingsModel
.
url
=
Helpers
.
USER_ACCOUNTS_API_URL
;
var
messageView
=
new
MessageBannerView
({
el
:
$
(
'.message-banner'
)
});
imageMaxBytes
=
imageMaxBytes
||
64
;
imageMinBytes
=
imageMinBytes
||
16
;
var
editable
=
ownProfile
?
'toggle'
:
'never'
;
return
new
LearnerProfileFields
.
ProfileImageFieldView
({
model
:
accountSettingsModel
,
valueAttribute
:
"profile_image"
,
editable
:
editable
===
'toggle'
,
messageView
:
messageView
,
imageMaxBytes
:
imageMaxBytes
,
imageMinBytes
:
imageMinBytes
,
imageUploadUrl
:
Helpers
.
IMAGE_UPLOAD_API_URL
,
imageRemoveUrl
:
Helpers
.
IMAGE_REMOVE_API_URL
});
};
beforeEach
(
function
()
{
setFixtures
(
'<div class="message-banner"></div><div class="wrapper-profile"><div class="ui-loading-indicator"><p><span class="spin"><i class="icon fa fa-refresh"></i></span> <span class="copy">Loading</span></p></div><div class="ui-loading-error is-hidden"><i class="fa fa-exclamation-triangle message-error" aria-hidden=true></i><span class="copy">An error occurred. Please reload the page.</span></div></div>'
);
TemplateHelpers
.
installTemplate
(
'templates/student_profile/learner_profile'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_image'
);
TemplateHelpers
.
installTemplate
(
"templates/fields/message_banner"
);
});
var
createFakeImageFile
=
function
(
size
)
{
var
fileFakeData
=
'i63ljc6giwoskyb9x5sw0169bdcmcxr3cdz8boqv0lik971972cmd6yknvcxr5sw0nvc169bdcmcxsdf'
;
return
new
Blob
(
[
fileFakeData
.
substr
(
0
,
size
)
],
{
type
:
'image/jpg'
}
);
};
it
(
"can upload profile image"
,
function
()
{
var
imageView
=
createImageView
(
true
,
false
);
imageView
.
render
();
var
requests
=
AjaxHelpers
.
requests
(
this
);
var
imageName
=
'profile_image.jpg'
;
// Initialize jquery file uploader
imageView
.
$
(
'.upload-button-input'
).
fileupload
({
url
:
Helpers
.
IMAGE_UPLOAD_API_URL
,
type
:
'POST'
,
add
:
imageView
.
fileSelected
,
done
:
imageView
.
imageChangeSucceeded
,
fail
:
imageView
.
imageChangeFailed
});
// Remove button should not be present for default image
expect
(
imageView
.
$
(
'.u-field-remove-button'
).
css
(
'display'
)
===
'none'
).
toBeTruthy
();
// For default image, image title should be `Upload an image`
expect
(
imageView
.
$
(
'.upload-button-title'
).
text
().
trim
()).
toBe
(
imageView
.
titleAdd
);
// Add image to upload queue, this will validate the image size and send POST request to upload image
imageView
.
$
(
'.upload-button-input'
).
fileupload
(
'add'
,
{
files
:
[
createFakeImageFile
(
60
)]});
// Verify image upload progress message
expect
(
imageView
.
$
(
'.upload-button-title'
).
text
().
trim
()).
toBe
(
imageView
.
titleUploading
);
// Verify if POST request received for image upload
AjaxHelpers
.
expectRequest
(
requests
,
'POST'
,
Helpers
.
IMAGE_UPLOAD_API_URL
,
new
FormData
());
// Send 204 NO CONTENT to confirm the image upload success
AjaxHelpers
.
respondWithNoContent
(
requests
);
// Upon successful image upload, account settings model will be fetched to get the url for newly uploaded image
// So we need to send the response for that GET
var
data
=
{
profile_image
:
{
image_url_large
:
'/media/profile-images/'
+
imageName
,
has_image
:
true
}};
AjaxHelpers
.
respondWithJson
(
requests
,
data
);
// Verify uploaded image name
expect
(
imageView
.
$
(
'.image-frame'
).
attr
(
'src'
)).
toContain
(
imageName
);
// Remove button should be present after successful image upload
expect
(
imageView
.
$
(
'.u-field-remove-button'
).
css
(
'display'
)
!==
'none'
).
toBeTruthy
();
// After image upload, image title should be `Change image`
expect
(
imageView
.
$
(
'.upload-button-title'
).
text
().
trim
()).
toBe
(
imageView
.
titleEdit
);
});
it
(
"can remove profile image"
,
function
()
{
var
imageView
=
createImageView
(
true
,
true
);
imageView
.
render
();
var
requests
=
AjaxHelpers
.
requests
(
this
);
imageView
.
$
(
'.u-field-remove-button'
).
click
();
// Verify image remove progress message
expect
(
imageView
.
$
(
'.remove-button-title'
).
text
().
trim
()).
toBe
(
imageView
.
titleRemoving
);
// Verify if POST request received for image remove
AjaxHelpers
.
expectRequest
(
requests
,
'POST'
,
Helpers
.
IMAGE_REMOVE_API_URL
,
null
);
// Send 204 NO CONTENT to confirm the image removal success
AjaxHelpers
.
respondWithNoContent
(
requests
);
// Upon successful image removal, account settings model will be fetched to get the default image url
// So we need to send the response for that GET
var
data
=
{
profile_image
:
{
image_url_large
:
'/media/profile-images/default.jpg'
,
has_image
:
false
}};
AjaxHelpers
.
respondWithJson
(
requests
,
data
);
// Remove button should not be present for default image
expect
(
imageView
.
$
(
'.u-field-remove-button'
).
css
(
'display'
)
===
'none'
).
toBeTruthy
();
});
it
(
"can't remove default profile image"
,
function
()
{
var
imageView
=
createImageView
(
true
,
false
);
imageView
.
render
();
spyOn
(
imageView
,
'clickedRemoveButton'
);
// Remove button should not be present for default image
expect
(
imageView
.
$
(
'.u-field-remove-button'
).
css
(
'display'
)
===
'none'
).
toBeTruthy
();
imageView
.
$
(
'.u-field-remove-button'
).
click
();
// Remove button click handler should not be called
expect
(
imageView
.
clickedRemoveButton
).
not
.
toHaveBeenCalled
();
});
it
(
"can't upload image having size greater than max size"
,
function
()
{
var
imageView
=
createImageView
(
true
,
false
);
imageView
.
render
();
// Initialize jquery file uploader
imageView
.
$
(
'.upload-button-input'
).
fileupload
({
url
:
Helpers
.
IMAGE_UPLOAD_API_URL
,
type
:
'POST'
,
add
:
imageView
.
fileSelected
,
done
:
imageView
.
imageChangeSucceeded
,
fail
:
imageView
.
imageChangeFailed
});
// Add image to upload queue, this will validate the image size
imageView
.
$
(
'.upload-button-input'
).
fileupload
(
'add'
,
{
files
:
[
createFakeImageFile
(
70
)]});
// Verify error message
expect
(
$
(
'.message-banner'
).
text
().
trim
()).
toBe
(
'Your image must be smaller than 64 Bytes in size.'
);
});
it
(
"can't upload image having size less than min size"
,
function
()
{
var
imageView
=
createImageView
(
true
,
false
);
imageView
.
render
();
// Initialize jquery file uploader
imageView
.
$
(
'.upload-button-input'
).
fileupload
({
url
:
Helpers
.
IMAGE_UPLOAD_API_URL
,
type
:
'POST'
,
add
:
imageView
.
fileSelected
,
done
:
imageView
.
imageChangeSucceeded
,
fail
:
imageView
.
imageChangeFailed
});
// Add image to upload queue, this will validate the image size
imageView
.
$
(
'.upload-button-input'
).
fileupload
(
'add'
,
{
files
:
[
createFakeImageFile
(
10
)]});
// Verify error message
expect
(
$
(
'.message-banner'
).
text
().
trim
()).
toBe
(
'Your image must be at least 16 Bytes in size.'
);
});
it
(
"can't upload/remove image if parental consent required"
,
function
()
{
var
imageView
=
createImageView
(
true
,
false
,
64
,
16
,
''
);
imageView
.
render
();
spyOn
(
imageView
,
'clickedUploadButton'
);
spyOn
(
imageView
,
'clickedRemoveButton'
);
expect
(
imageView
.
$
(
'.u-field-upload-button'
).
css
(
'display'
)
===
'none'
).
toBeTruthy
();
expect
(
imageView
.
$
(
'.u-field-remove-button'
).
css
(
'display'
)
===
'none'
).
toBeTruthy
();
imageView
.
$
(
'.u-field-upload-button'
).
click
();
imageView
.
$
(
'.u-field-remove-button'
).
click
();
expect
(
imageView
.
clickedUploadButton
).
not
.
toHaveBeenCalled
();
expect
(
imageView
.
clickedRemoveButton
).
not
.
toHaveBeenCalled
();
});
it
(
"can't upload image on others profile"
,
function
()
{
var
imageView
=
createImageView
(
false
);
imageView
.
render
();
spyOn
(
imageView
,
'clickedUploadButton'
);
spyOn
(
imageView
,
'clickedRemoveButton'
);
expect
(
imageView
.
$
(
'.u-field-upload-button'
).
css
(
'display'
)
===
'none'
).
toBeTruthy
();
expect
(
imageView
.
$
(
'.u-field-remove-button'
).
css
(
'display'
)
===
'none'
).
toBeTruthy
();
imageView
.
$
(
'.u-field-upload-button'
).
click
();
imageView
.
$
(
'.u-field-remove-button'
).
click
();
expect
(
imageView
.
clickedUploadButton
).
not
.
toHaveBeenCalled
();
expect
(
imageView
.
clickedRemoveButton
).
not
.
toHaveBeenCalled
();
});
it
(
"shows message if we try to navigate away during image upload/remove"
,
function
()
{
var
imageView
=
createImageView
(
true
,
false
);
spyOn
(
imageView
,
'onBeforeUnload'
);
imageView
.
render
();
// Initialize jquery file uploader
imageView
.
$
(
'.upload-button-input'
).
fileupload
({
url
:
Helpers
.
IMAGE_UPLOAD_API_URL
,
type
:
'POST'
,
add
:
imageView
.
fileSelected
,
done
:
imageView
.
imageChangeSucceeded
,
fail
:
imageView
.
imageChangeFailed
});
// Add image to upload queue, this will validate the image size and send POST request to upload image
imageView
.
$
(
'.upload-button-input'
).
fileupload
(
'add'
,
{
files
:
[
createFakeImageFile
(
60
)]});
// Verify image upload progress message
expect
(
imageView
.
$
(
'.upload-button-title'
).
text
().
trim
()).
toBe
(
imageView
.
titleUploading
);
$
(
window
).
trigger
(
'beforeunload'
);
expect
(
imageView
.
onBeforeUnload
).
toHaveBeenCalled
();
});
it
(
'renders message correctly'
,
function
()
{
var
messageSelector
=
'.message-banner'
;
var
messageView
=
new
MessageBannerView
({
el
:
$
(
messageSelector
)
});
messageView
.
showMessage
(
'I am message view'
);
// Verify error message
expect
(
$
(
messageSelector
).
text
().
trim
()).
toBe
(
'I am message view'
);
messageView
.
hideMessage
();
expect
(
$
(
messageSelector
).
text
().
trim
()).
toBe
(
''
);
});
});
});
lms/static/js/spec/student_profile/learner_profile_view_spec.js
View file @
ca1f2f77
...
@@ -24,6 +24,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
...
@@ -24,6 +24,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
accountSettingsData
.
requires_parental_consent
=
false
;
accountSettingsData
.
requires_parental_consent
=
false
;
accountSettingsModel
.
set
(
accountSettingsData
);
accountSettingsModel
.
set
(
accountSettingsData
);
accountSettingsModel
.
set
({
'profile_is_public'
:
profileIsPublic
});
accountSettingsModel
.
set
({
'profile_is_public'
:
profileIsPublic
});
accountSettingsModel
.
set
({
'profile_image'
:
Helpers
.
PROFILE_IMAGE
});
var
accountPreferencesModel
=
new
AccountPreferencesModel
();
var
accountPreferencesModel
=
new
AccountPreferencesModel
();
accountPreferencesModel
.
set
({
account_privacy
:
accountPrivacy
});
accountPreferencesModel
.
set
({
account_privacy
:
accountPrivacy
});
...
@@ -51,7 +52,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
...
@@ -51,7 +52,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
el
:
$
(
'.message-banner'
)
el
:
$
(
'.message-banner'
)
});
});
var
profileImageFieldView
=
new
FieldsView
.
ImageFieldView
({
var
profileImageFieldView
=
new
LearnerProfileFields
.
Profile
ImageFieldView
({
model
:
accountSettingsModel
,
model
:
accountSettingsModel
,
valueAttribute
:
"profile_image"
,
valueAttribute
:
"profile_image"
,
editable
:
editable
,
editable
:
editable
,
...
@@ -69,7 +70,6 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
...
@@ -69,7 +70,6 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
});
});
var
sectionOneFieldViews
=
[
var
sectionOneFieldViews
=
[
usernameFieldView
,
new
FieldViews
.
DropdownFieldView
({
new
FieldViews
.
DropdownFieldView
({
model
:
accountSettingsModel
,
model
:
accountSettingsModel
,
required
:
false
,
required
:
false
,
...
@@ -117,6 +117,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
...
@@ -117,6 +117,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
preferencesModel
:
accountPreferencesModel
,
preferencesModel
:
accountPreferencesModel
,
accountPrivacyFieldView
:
accountPrivacyFieldView
,
accountPrivacyFieldView
:
accountPrivacyFieldView
,
usernameFieldView
:
usernameFieldView
,
usernameFieldView
:
usernameFieldView
,
profileImageFieldView
:
profileImageFieldView
,
sectionOneFieldViews
:
sectionOneFieldViews
,
sectionOneFieldViews
:
sectionOneFieldViews
,
sectionTwoFieldViews
:
sectionTwoFieldViews
sectionTwoFieldViews
:
sectionTwoFieldViews
});
});
...
@@ -128,7 +129,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
...
@@ -128,7 +129,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
TemplateHelpers
.
installTemplate
(
'templates/fields/field_dropdown'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_dropdown'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_textarea'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_textarea'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_image'
);
TemplateHelpers
.
installTemplate
(
'templates/fields/field_image'
);
TemplateHelpers
.
installTemplate
(
'templates/message_banner'
);
TemplateHelpers
.
installTemplate
(
'templates/
fields/
message_banner'
);
TemplateHelpers
.
installTemplate
(
'templates/student_profile/learner_profile'
);
TemplateHelpers
.
installTemplate
(
'templates/student_profile/learner_profile'
);
});
});
...
...
lms/static/js/student_profile/views/learner_profile_fields.js
View file @
ca1f2f77
...
@@ -70,9 +70,14 @@
...
@@ -70,9 +70,14 @@
imageChangeFailed
:
function
(
e
,
data
)
{
imageChangeFailed
:
function
(
e
,
data
)
{
this
.
setCurrentStatus
(
''
);
this
.
setCurrentStatus
(
''
);
if
(
_
.
contains
([
400
,
404
],
data
.
jqXHR
.
status
))
{
this
.
showImageChangeFailedMessage
(
data
.
jqXHR
.
status
,
data
.
jqXHR
.
responseText
);
this
.
render
();
},
showImageChangeFailedMessage
:
function
(
status
,
responseText
)
{
if
(
_
.
contains
([
400
,
404
],
status
))
{
try
{
try
{
var
errors
=
JSON
.
parse
(
data
.
jqXHR
.
responseText
);
var
errors
=
JSON
.
parse
(
responseText
);
this
.
showErrorMessage
(
errors
.
user_message
);
this
.
showErrorMessage
(
errors
.
user_message
);
}
catch
(
error
)
{
}
catch
(
error
)
{
this
.
showErrorMessage
(
this
.
errorMessage
);
this
.
showErrorMessage
(
this
.
errorMessage
);
...
@@ -80,7 +85,6 @@
...
@@ -80,7 +85,6 @@
}
else
{
}
else
{
this
.
showErrorMessage
(
this
.
errorMessage
);
this
.
showErrorMessage
(
this
.
errorMessage
);
}
}
this
.
render
();
},
},
showErrorMessage
:
function
(
message
)
{
showErrorMessage
:
function
(
message
)
{
...
...
lms/static/js/views/fields.js
View file @
ca1f2f77
...
@@ -548,7 +548,8 @@
...
@@ -548,7 +548,8 @@
return
this
;
return
this
;
},
},
showErrorMessage
:
function
()
{
showErrorMessage
:
function
(
message
)
{
return
message
;
},
},
imageUrl
:
function
()
{
imageUrl
:
function
()
{
...
@@ -593,7 +594,7 @@
...
@@ -593,7 +594,7 @@
}
}
},
},
clickedUploadButton
:
function
()
{
clickedUploadButton
:
function
(
e
,
data
)
{
$
(
this
.
uploadButtonSelector
).
fileupload
({
$
(
this
.
uploadButtonSelector
).
fileupload
({
url
:
this
.
options
.
imageUploadUrl
,
url
:
this
.
options
.
imageUploadUrl
,
type
:
'POST'
,
type
:
'POST'
,
...
@@ -603,7 +604,7 @@
...
@@ -603,7 +604,7 @@
});
});
},
},
clickedRemoveButton
:
function
()
{
clickedRemoveButton
:
function
(
e
,
data
)
{
var
view
=
this
;
var
view
=
this
;
this
.
setCurrentStatus
(
'removing'
);
this
.
setCurrentStatus
(
'removing'
);
this
.
setUploadButtonVisibility
(
'none'
);
this
.
setUploadButtonVisibility
(
'none'
);
...
@@ -615,7 +616,7 @@
...
@@ -615,7 +616,7 @@
view
.
imageChangeSucceeded
();
view
.
imageChangeSucceeded
();
},
},
error
:
function
(
xhr
,
status
,
error
)
{
error
:
function
(
xhr
,
status
,
error
)
{
view
.
imageChangeFailed
(
);
view
.
showImageChangeFailedMessage
(
xhr
.
status
,
xhr
.
responseText
);
}
}
});
});
},
},
...
@@ -627,8 +628,11 @@
...
@@ -627,8 +628,11 @@
imageChangeFailed
:
function
(
e
,
data
)
{
imageChangeFailed
:
function
(
e
,
data
)
{
},
},
showImageChangeFailedMessage
:
function
(
status
,
responseText
)
{
},
fileSelected
:
function
(
e
,
data
)
{
fileSelected
:
function
(
e
,
data
)
{
if
(
this
.
validateImageSize
(
data
.
files
[
0
].
size
))
{
if
(
_
.
isUndefined
(
data
.
files
[
0
].
size
)
||
this
.
validateImageSize
(
data
.
files
[
0
].
size
))
{
data
.
formData
=
{
file
:
data
.
files
[
0
]};
data
.
formData
=
{
file
:
data
.
files
[
0
]};
this
.
setCurrentStatus
(
'uploading'
);
this
.
setCurrentStatus
(
'uploading'
);
this
.
setRemoveButtonVisibility
(
'none'
);
this
.
setRemoveButtonVisibility
(
'none'
);
...
@@ -681,6 +685,7 @@
...
@@ -681,6 +685,7 @@
},
},
onBeforeUnload
:
function
()
{
onBeforeUnload
:
function
()
{
console
.
log
(
'Do you really want to go away?'
);
var
status
=
this
.
getCurrentStatus
();
var
status
=
this
.
getCurrentStatus
();
if
(
status
===
'uploading'
)
{
if
(
status
===
'uploading'
)
{
return
gettext
(
"Upload is in progress. To avoid errors, stay on this page until the process is complete."
);
return
gettext
(
"Upload is in progress. To avoid errors, stay on this page until the process is complete."
);
...
...
lms/static/sass/views/_learner-profile.scss
View file @
ca1f2f77
...
@@ -30,6 +30,7 @@
...
@@ -30,6 +30,7 @@
background
:
transparent
!
important
;
background
:
transparent
!
important
;
border
:
none
!
important
;
border
:
none
!
important
;
padding
:
0
;
padding
:
0
;
-webkit-tap-highlight-color
:
transparent
;
}
}
.u-field-image
{
.u-field-image
{
...
...
lms/templates/message_banner.underscore
→
lms/templates/
fields/
message_banner.underscore
View file @
ca1f2f77
File moved
lms/templates/student_profile/learner_profile.html
View file @
ca1f2f77
...
@@ -10,7 +10,7 @@
...
@@ -10,7 +10,7 @@
<
%
block
name=
"bodyclass"
>
view-profile
</
%
block>
<
%
block
name=
"bodyclass"
>
view-profile
</
%
block>
<
%
block
name=
"header_extras"
>
<
%
block
name=
"header_extras"
>
% for template_name in ["field_dropdown", "field_image", "field_textarea", "field_readonly"]:
% for template_name in ["field_dropdown", "field_image", "field_textarea", "field_readonly"
, "message_banner"
]:
<script
type=
"text/template"
id=
"${template_name}-tpl"
>
<script
type=
"text/template"
id=
"${template_name}-tpl"
>
<%
static
:
include
path
=
"fields/${template_name}.underscore"
/>
<%
static
:
include
path
=
"fields/${template_name}.underscore"
/>
</script>
</script>
...
@@ -21,12 +21,6 @@
...
@@ -21,12 +21,6 @@
<%
static
:
include
path
=
"student_profile/${template_name}.underscore"
/>
<%
static
:
include
path
=
"student_profile/${template_name}.underscore"
/>
</script>
</script>
% endfor
% endfor
% for template_name in ["message_banner"]:
<script
type=
"text/template"
id=
"${template_name}-tpl"
>
<%
static
:
include
path
=
"${template_name}.underscore"
/>
</script>
% endfor
</
%
block>
</
%
block>
<div
class=
"message-banner"
aria-live=
"polite"
></div>
<div
class=
"message-banner"
aria-live=
"polite"
></div>
...
...
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