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
31993cf4
Commit
31993cf4
authored
Jul 16, 2014
by
Daniel Friedman
Committed by
cahrens
Aug 07, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Escape xblock model field in string editor
Also add standalone spec STUD-1984
parent
285beb38
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
165 additions
and
61 deletions
+165
-61
cms/static/coffee/spec/main.coffee
+1
-0
cms/static/js/spec/views/pages/container_spec.js
+1
-59
cms/static/js/spec/views/xblock_string_field_editor_spec.js
+155
-0
cms/static/js/views/xblock_string_field_editor.js
+8
-2
No files found.
cms/static/coffee/spec/main.coffee
View file @
31993cf4
...
@@ -227,6 +227,7 @@ define([
...
@@ -227,6 +227,7 @@ define([
"js/spec/views/unit_outline_spec"
,
"js/spec/views/unit_outline_spec"
,
"js/spec/views/xblock_spec"
,
"js/spec/views/xblock_spec"
,
"js/spec/views/xblock_editor_spec"
,
"js/spec/views/xblock_editor_spec"
,
"js/spec/views/xblock_string_field_editor_spec"
,
"js/spec/views/pages/container_spec"
,
"js/spec/views/pages/container_spec"
,
"js/spec/views/pages/container_subviews_spec"
,
"js/spec/views/pages/container_subviews_spec"
,
...
...
cms/static/js/spec/views/pages/container_spec.js
View file @
31993cf4
...
@@ -95,7 +95,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -95,7 +95,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
describe
(
"Editing the container"
,
function
()
{
describe
(
"Editing the container"
,
function
()
{
var
updatedDisplayName
=
'Updated Test Container'
,
var
updatedDisplayName
=
'Updated Test Container'
,
expectEditCanceled
,
getDisplayNameWrapper
;
getDisplayNameWrapper
;
afterEach
(
function
()
{
afterEach
(
function
()
{
edit_helpers
.
cancelModalIfShowing
();
edit_helpers
.
cancelModalIfShowing
();
...
@@ -105,24 +105,6 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -105,24 +105,6 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
return
containerPage
.
$
(
'.wrapper-xblock-field'
);
return
containerPage
.
$
(
'.wrapper-xblock-field'
);
};
};
expectEditCanceled
=
function
(
test
,
options
)
{
var
initialRequests
,
displayNameWrapper
,
displayNameInput
;
renderContainerPage
(
test
,
mockContainerXBlockHtml
);
displayNameWrapper
=
getDisplayNameWrapper
();
initialRequests
=
requests
.
length
;
displayNameInput
=
edit_helpers
.
inlineEdit
(
displayNameWrapper
,
options
.
newTitle
);
if
(
options
.
pressEscape
)
{
displayNameInput
.
simulate
(
"keydown"
,
{
keyCode
:
$
.
simulate
.
keyCode
.
ESCAPE
});
displayNameInput
.
simulate
(
"keyup"
,
{
keyCode
:
$
.
simulate
.
keyCode
.
ESCAPE
});
}
else
{
displayNameInput
.
change
();
}
// No requests should be made when the edit is cancelled client-side
expect
(
initialRequests
).
toBe
(
requests
.
length
);
edit_helpers
.
verifyInlineEditChange
(
displayNameWrapper
,
initialDisplayName
);
expect
(
containerPage
.
model
.
get
(
'display_name'
)).
toBe
(
initialDisplayName
);
};
it
(
'can edit itself'
,
function
()
{
it
(
'can edit itself'
,
function
()
{
var
editButtons
,
displayNameElement
;
var
editButtons
,
displayNameElement
;
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
...
@@ -173,46 +155,6 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -173,46 +155,6 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
edit_helpers
.
verifyInlineEditChange
(
displayNameWrapper
,
updatedDisplayName
);
edit_helpers
.
verifyInlineEditChange
(
displayNameWrapper
,
updatedDisplayName
);
expect
(
containerPage
.
model
.
get
(
'display_name'
)).
toBe
(
updatedDisplayName
);
expect
(
containerPage
.
model
.
get
(
'display_name'
)).
toBe
(
updatedDisplayName
);
});
});
it
(
'does not change the title when a display name update fails'
,
function
()
{
var
initialRequests
,
displayNameInput
,
displayNameWrapper
;
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
displayNameWrapper
=
getDisplayNameWrapper
();
displayNameInput
=
edit_helpers
.
inlineEdit
(
displayNameWrapper
,
updatedDisplayName
);
initialRequests
=
requests
.
length
;
displayNameInput
.
change
();
create_sinon
.
respondWithError
(
requests
);
// No fetch operation should occur.
expect
(
initialRequests
+
1
).
toBe
(
requests
.
length
);
edit_helpers
.
verifyInlineEditChange
(
displayNameWrapper
,
initialDisplayName
,
updatedDisplayName
);
expect
(
containerPage
.
model
.
get
(
'display_name'
)).
toBe
(
initialDisplayName
);
});
it
(
'trims whitespace from the display name'
,
function
()
{
var
displayNameInput
,
displayNameWrapper
;
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
displayNameWrapper
=
getDisplayNameWrapper
();
displayNameInput
=
edit_helpers
.
inlineEdit
(
displayNameWrapper
,
updatedDisplayName
+
' '
);
displayNameInput
.
change
();
// This is the response for the change operation.
create_sinon
.
respondWithJson
(
requests
,
{
});
// This is the response for the subsequent fetch operation.
create_sinon
.
respondWithJson
(
requests
,
{
"display_name"
:
updatedDisplayName
});
edit_helpers
.
verifyInlineEditChange
(
displayNameWrapper
,
updatedDisplayName
);
expect
(
containerPage
.
model
.
get
(
'display_name'
)).
toBe
(
updatedDisplayName
);
});
it
(
'does not change the title when input is the empty string'
,
function
()
{
expectEditCanceled
(
this
,
{
newTitle
:
''
});
});
it
(
'does not change the title when input is whitespace-only'
,
function
()
{
expectEditCanceled
(
this
,
{
newTitle
:
' '
});
});
it
(
'can cancel an inline edit'
,
function
()
{
expectEditCanceled
(
this
,
{
newTitle
:
updatedDisplayName
,
pressEscape
:
true
});
});
});
});
describe
(
"Editing an xblock"
,
function
()
{
describe
(
"Editing an xblock"
,
function
()
{
...
...
cms/static/js/spec/views/xblock_string_field_editor_spec.js
0 → 100644
View file @
31993cf4
define
([
"jquery"
,
"js/spec_helpers/create_sinon"
,
"js/spec_helpers/view_helpers"
,
"js/spec_helpers/edit_helpers"
,
"js/models/xblock_info"
,
"js/views/xblock_string_field_editor"
],
function
(
$
,
create_sinon
,
view_helpers
,
edit_helpers
,
XBlockInfo
,
XBlockStringFieldEditor
)
{
describe
(
"XBlockStringFieldEditorView"
,
function
()
{
var
initialDisplayName
,
updatedDisplayName
,
getXBlockInfo
,
getFieldEditorView
;
getXBlockInfo
=
function
(
displayName
)
{
return
new
XBlockInfo
(
{
display_name
:
displayName
,
id
:
"my_xblock"
},
{
parse
:
true
}
);
};
getFieldEditorView
=
function
(
xblockInfo
)
{
if
(
xblockInfo
===
undefined
)
{
xblockInfo
=
getXBlockInfo
(
initialDisplayName
);
}
return
new
XBlockStringFieldEditor
({
model
:
xblockInfo
,
el
:
$
(
'.wrapper-xblock-field'
)
});
};
beforeEach
(
function
()
{
initialDisplayName
=
"Default Display Name"
;
updatedDisplayName
=
"Updated Display Name"
;
view_helpers
.
installTemplate
(
'xblock-string-field-editor'
);
appendSetFixtures
(
'<div class="wrapper-xblock-field incontext-editor is-editable"'
+
'data-field="display_name" data-field-display-name="Display Name">'
+
'<h1 class="page-header-title xblock-field-value incontext-editor-value"><span class="title-value">'
+
initialDisplayName
+
'</span></h1>'
+
'</div>'
);
});
describe
(
'Editing'
,
function
()
{
var
expectPostedNewDisplayName
,
expectEditCanceled
;
expectPostedNewDisplayName
=
function
(
requests
,
displayName
)
{
create_sinon
.
expectJsonRequest
(
requests
,
'POST'
,
'/xblock/my_xblock'
,
{
metadata
:
{
display_name
:
displayName
}
});
};
expectEditCanceled
=
function
(
test
,
fieldEditorView
,
options
)
{
var
requests
,
initialRequests
,
displayNameInput
;
requests
=
create_sinon
.
requests
(
test
);
initialRequests
=
requests
.
length
;
displayNameInput
=
edit_helpers
.
inlineEdit
(
fieldEditorView
.
$el
,
options
.
newTitle
);
if
(
options
.
pressEscape
)
{
displayNameInput
.
simulate
(
"keydown"
,
{
keyCode
:
$
.
simulate
.
keyCode
.
ESCAPE
});
displayNameInput
.
simulate
(
"keyup"
,
{
keyCode
:
$
.
simulate
.
keyCode
.
ESCAPE
});
}
else
if
(
options
.
clickCancel
)
{
fieldEditorView
.
$
(
'button[name=cancel]'
).
click
();
}
else
{
displayNameInput
.
change
();
}
// No requests should be made when the edit is cancelled client-side
expect
(
initialRequests
).
toBe
(
requests
.
length
);
edit_helpers
.
verifyInlineEditChange
(
fieldEditorView
.
$el
,
initialDisplayName
);
expect
(
fieldEditorView
.
model
.
get
(
'display_name'
)).
toBe
(
initialDisplayName
);
};
it
(
'can inline edit the display name'
,
function
()
{
var
requests
,
fieldEditorView
;
requests
=
create_sinon
.
requests
(
this
);
fieldEditorView
=
getFieldEditorView
().
render
();
edit_helpers
.
inlineEdit
(
fieldEditorView
.
$el
,
updatedDisplayName
);
fieldEditorView
.
$
(
'button[name=submit]'
).
click
();
expectPostedNewDisplayName
(
requests
,
updatedDisplayName
);
// This is the response for the change operation.
create_sinon
.
respondWithJson
(
requests
,
{
});
// This is the response for the subsequent fetch operation.
create_sinon
.
respondWithJson
(
requests
,
{
display_name
:
updatedDisplayName
});
edit_helpers
.
verifyInlineEditChange
(
fieldEditorView
.
$el
,
updatedDisplayName
);
});
it
(
'does not change the title when a display name update fails'
,
function
()
{
var
requests
,
fieldEditorView
,
initialRequests
;
requests
=
create_sinon
.
requests
(
this
);
initialRequests
=
requests
.
length
;
fieldEditorView
=
getFieldEditorView
().
render
();
edit_helpers
.
inlineEdit
(
fieldEditorView
.
$el
,
updatedDisplayName
);
fieldEditorView
.
$
(
'button[name=submit]'
).
click
();
expectPostedNewDisplayName
(
requests
,
updatedDisplayName
);
create_sinon
.
respondWithError
(
requests
);
// No fetch operation should occur.
expect
(
initialRequests
+
1
).
toBe
(
requests
.
length
);
edit_helpers
.
verifyInlineEditChange
(
fieldEditorView
.
$el
,
initialDisplayName
,
updatedDisplayName
);
});
it
(
'trims whitespace from the display name'
,
function
()
{
var
requests
,
fieldEditorView
;
requests
=
create_sinon
.
requests
(
this
);
fieldEditorView
=
getFieldEditorView
().
render
();
updatedDisplayName
+=
' '
;
edit_helpers
.
inlineEdit
(
fieldEditorView
.
$el
,
updatedDisplayName
);
fieldEditorView
.
$
(
'button[name=submit]'
).
click
();
expectPostedNewDisplayName
(
requests
,
updatedDisplayName
.
trim
());
// This is the response for the change operation.
create_sinon
.
respondWithJson
(
requests
,
{
});
// This is the response for the subsequent fetch operation.
create_sinon
.
respondWithJson
(
requests
,
{
display_name
:
updatedDisplayName
.
trim
()});
edit_helpers
.
verifyInlineEditChange
(
fieldEditorView
.
$el
,
updatedDisplayName
.
trim
());
});
it
(
'does not change the title when input is the empty string'
,
function
()
{
var
fieldEditorView
=
getFieldEditorView
().
render
();
expectEditCanceled
(
this
,
fieldEditorView
,
{
newTitle
:
''
});
});
it
(
'does not change the title when input is whitespace-only'
,
function
()
{
var
fieldEditorView
=
getFieldEditorView
().
render
();
expectEditCanceled
(
this
,
fieldEditorView
,
{
newTitle
:
' '
});
});
it
(
'can cancel an inline edit by pressing escape'
,
function
()
{
var
fieldEditorView
=
getFieldEditorView
().
render
();
expectEditCanceled
(
this
,
fieldEditorView
,
{
newTitle
:
updatedDisplayName
,
pressEscape
:
true
});
});
it
(
'can cancel an inline edit by clicking cancel'
,
function
()
{
var
fieldEditorView
=
getFieldEditorView
().
render
();
expectEditCanceled
(
this
,
fieldEditorView
,
{
newTitle
:
updatedDisplayName
,
clickCancel
:
true
});
});
});
describe
(
'Rendering'
,
function
()
{
var
expectInputMatchesModelDisplayName
=
function
(
displayName
)
{
var
fieldEditorView
=
getFieldEditorView
(
getXBlockInfo
(
displayName
)).
render
();
expect
(
fieldEditorView
.
$
(
'.xblock-field-input'
).
val
()).
toBe
(
displayName
);
};
it
(
'renders single quotes in input field'
,
function
()
{
expectInputMatchesModelDisplayName
(
'Updated
\'
Display Name
\'
'
);
});
it
(
'renders double quotes in input field'
,
function
()
{
expectInputMatchesModelDisplayName
(
'Updated "Display Name"'
);
});
it
(
'renders open angle bracket in input field'
,
function
()
{
expectInputMatchesModelDisplayName
(
updatedDisplayName
+
'<'
);
});
it
(
'renders close angle bracket in input field'
,
function
()
{
expectInputMatchesModelDisplayName
(
'>'
+
updatedDisplayName
);
});
});
});
});
cms/static/js/views/xblock_string_field_editor.js
View file @
31993cf4
...
@@ -11,7 +11,8 @@ define(["js/views/baseview", "js/views/utils/xblock_utils"],
...
@@ -11,7 +11,8 @@ define(["js/views/baseview", "js/views/utils/xblock_utils"],
var
XBlockStringFieldEditor
=
BaseView
.
extend
({
var
XBlockStringFieldEditor
=
BaseView
.
extend
({
events
:
{
events
:
{
'click .xblock-field-value-edit'
:
'showInput'
,
'click .xblock-field-value-edit'
:
'showInput'
,
'click button[type=submit]'
:
'onClickSubmit'
,
'click button[name=submit]'
:
'onClickSubmit'
,
'click button[name=cancel]'
:
'onClickCancel'
,
'change .xblock-field-input'
:
'updateField'
,
'change .xblock-field-input'
:
'updateField'
,
'focusout .xblock-field-input'
:
'onInputFocusLost'
,
'focusout .xblock-field-input'
:
'onInputFocusLost'
,
'keyup .xblock-field-input'
:
'handleKeyUp'
'keyup .xblock-field-input'
:
'handleKeyUp'
...
@@ -29,7 +30,7 @@ define(["js/views/baseview", "js/views/utils/xblock_utils"],
...
@@ -29,7 +30,7 @@ define(["js/views/baseview", "js/views/utils/xblock_utils"],
render
:
function
()
{
render
:
function
()
{
this
.
$el
.
append
(
this
.
template
({
this
.
$el
.
append
(
this
.
template
({
value
:
this
.
model
.
get
(
this
.
fieldName
),
value
:
this
.
model
.
escape
(
this
.
fieldName
),
fieldName
:
this
.
fieldName
,
fieldName
:
this
.
fieldName
,
fieldDisplayName
:
this
.
fieldDisplayName
fieldDisplayName
:
this
.
fieldDisplayName
}));
}));
...
@@ -56,6 +57,11 @@ define(["js/views/baseview", "js/views/utils/xblock_utils"],
...
@@ -56,6 +57,11 @@ define(["js/views/baseview", "js/views/utils/xblock_utils"],
this
.
updateField
();
this
.
updateField
();
},
},
onClickCancel
:
function
(
event
)
{
event
.
preventDefault
();
this
.
cancelInput
();
},
onChangeField
:
function
()
{
onChangeField
:
function
()
{
var
value
=
this
.
model
.
get
(
this
.
fieldName
);
var
value
=
this
.
model
.
get
(
this
.
fieldName
);
this
.
getLabel
().
text
(
value
);
this
.
getLabel
().
text
(
value
);
...
...
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