Commit 2ae28c5d by Andy Armstrong

Improve unit testing of xblock editing

parent 9de6f101
......@@ -30,13 +30,11 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
mockXBlockEditorHtml = readFixtures('mock/mock-xblock-editor.underscore');
beforeEach(function () {
window.MockXBlock = function(runtime, element) {
return { };
};
edit_helpers.installMockXBlock();
});
afterEach(function() {
window.MockXBlock = null;
edit_helpers.uninstallMockXBlock();
});
it('can show itself', function() {
......
define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers",
"js/views/pages/container", "js/models/xblock_info"],
function ($, create_sinon, edit_helpers, XBlockContainerPage, XBlockInfo) {
function ($, create_sinon, edit_helpers, ContainerPage, XBlockInfo) {
describe("XBlockContainerView", function() {
var model, containerView, respondWithMockXBlockEditorFragment, mockContainerPage;
describe("ContainerPage", function() {
var model, containerPage, respondWithMockXBlockEditorFragment, mockContainerPage;
mockContainerPage = readFixtures('mock/mock-container-page.underscore');
......@@ -16,7 +16,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers"
display_name: 'Test Unit',
category: 'vertical'
});
containerView = new XBlockContainerPage({
containerPage = new ContainerPage({
model: model,
el: $('#content')
});
......@@ -32,26 +32,26 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers"
it('can render itself', function() {
var requests = create_sinon.requests(this);
containerView.render();
containerPage.render();
respondWithMockXBlockEditorFragment(requests, {
html: mockContainerXBlockHtml,
"resources": []
});
expect(containerView.$el.select('.xblock-header')).toBeTruthy();
expect(containerView.$('.wrapper-xblock')).not.toHaveClass('is-hidden');
expect(containerView.$('.no-container-content')).toHaveClass('is-hidden');
expect(containerPage.$el.select('.xblock-header')).toBeTruthy();
expect(containerPage.$('.wrapper-xblock')).not.toHaveClass('is-hidden');
expect(containerPage.$('.no-container-content')).toHaveClass('is-hidden');
});
it('shows a loading indicator', function() {
var requests = create_sinon.requests(this);
containerView.render();
expect(containerView.$('.ui-loading')).not.toHaveClass('is-hidden');
containerPage.render();
expect(containerPage.$('.ui-loading')).not.toHaveClass('is-hidden');
respondWithMockXBlockEditorFragment(requests, {
html: mockContainerXBlockHtml,
"resources": []
});
expect(containerView.$('.ui-loading')).toHaveClass('is-hidden');
expect(containerPage.$('.ui-loading')).toHaveClass('is-hidden');
});
});
......@@ -59,28 +59,19 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers"
describe("Editing an xblock", function() {
var mockContainerXBlockHtml,
mockXBlockEditorHtml,
saved,
newDisplayName = 'New Display Name';
beforeEach(function () {
saved = false;
window.MockXBlock = function(runtime, element) {
return {
save: function() {
saved = true;
return {
data: "<p>Some HTML</p>",
metadata: {
display_name: newDisplayName
}
};
}
};
};
edit_helpers.installMockXBlock({
data: "<p>Some HTML</p>",
metadata: {
display_name: newDisplayName
}
});
});
afterEach(function() {
window.MockXBlock = null;
edit_helpers.uninstallMockXBlock();
edit_helpers.cancelModalIfShowing();
});
......@@ -90,12 +81,12 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers"
it('can show an edit modal for a child xblock', function() {
var requests = create_sinon.requests(this),
editButtons;
containerView.render();
containerPage.render();
respondWithMockXBlockEditorFragment(requests, {
html: mockContainerXBlockHtml,
"resources": []
});
editButtons = containerView.$('.edit-button');
editButtons = containerPage.$('.edit-button');
// The container renders four mock xblocks, so there should be four edit buttons
expect(editButtons.length).toBe(4);
editButtons.first().click();
......@@ -111,14 +102,15 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers"
});
it('can save changes to settings', function() {
var requests, editButtons, modal;
var requests, editButtons, modal, mockUpdatedXBlockHtml;
mockUpdatedXBlockHtml = readFixtures('mock/mock-updated-xblock.underscore');
requests = create_sinon.requests(this);
containerView.render();
containerPage.render();
respondWithMockXBlockEditorFragment(requests, {
html: mockContainerXBlockHtml,
"resources": []
});
editButtons = containerView.$('.edit-button');
editButtons = containerPage.$('.edit-button');
// The container renders four mock xblocks, so there should be four edit buttons
expect(editButtons.length).toBe(4);
editButtons.first().click();
......@@ -131,10 +123,21 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers"
// Click on the settings tab
modal.find('.settings-button').click();
// Change the display name's text
modal.find('.setting-input').text("New display name");
modal.find('.setting-input').text("Mock Update");
// Press the save button
modal.find('.action-save').click();
expect(saved).toBe(true);
// Respond to the save
create_sinon.respondWithJson(requests, {
id: model.id
});
// Respond to the request to refresh
respondWithMockXBlockEditorFragment(requests, {
html: mockUpdatedXBlockHtml,
"resources": []
});
// Verify that the xblock was updated
expect(containerPage.$('.mock-updated-content').text()).toBe('Mock Update');
expect(edit_helpers.hasSavedMockXBlock()).toBe(true);
});
});
......@@ -143,14 +146,14 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers"
it('shows the "no children" message', function() {
var requests = create_sinon.requests(this);
containerView.render();
containerPage.render();
respondWithMockXBlockEditorFragment(requests, {
html: mockContainerXBlockHtml,
"resources": []
});
expect(containerView.$('.no-container-content')).not.toHaveClass('is-hidden');
expect(containerView.$('.wrapper-xblock')).toHaveClass('is-hidden');
expect(containerPage.$('.no-container-content')).not.toHaveClass('is-hidden');
expect(containerPage.$('.wrapper-xblock')).toHaveClass('is-hidden');
});
});
});
......
define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers",
"js/views/xblock_editor", "js/models/xblock_info"],
function ($, create_sinon, edit_helpers, XBlockEditorView, XBlockInfo) {
define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers",
"js/views/xblock_editor", "js/models/xblock_info"],
function ($, _, create_sinon, edit_helpers, XBlockEditorView, XBlockInfo) {
describe("XBlockEditorView", function() {
var model, editor;
var model, editor, testDisplayName, mockSaveResponse;
testDisplayName = 'Test Display Name';
mockSaveResponse = {
data: "<p>Some HTML</p>",
metadata: {
display_name: testDisplayName
}
};
beforeEach(function () {
edit_helpers.installEditTemplates();
......@@ -21,13 +29,11 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers
var mockXBlockEditorHtml;
beforeEach(function () {
window.MockXBlock = function(runtime, element) {
return { };
};
edit_helpers.installMockXBlock(mockSaveResponse);
});
afterEach(function() {
window.MockXBlock = null;
edit_helpers.uninstallMockXBlock();
});
mockXBlockEditorHtml = readFixtures('mock/mock-xblock-editor.underscore');
......@@ -41,7 +47,22 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers
});
expect(editor.$el.select('.xblock-header')).toBeTruthy();
expect(editor.getMode()).toEqual('editor');
expect(editor.getMode()).toEqual('settings');
});
it('saves any custom metadata', function() {
var requests = create_sinon.requests(this), request, response;
editor.render();
create_sinon.respondWithJson(requests, {
html: mockXBlockEditorHtml,
"resources": []
});
editor.save();
request = requests[requests.length - 1];
response = JSON.parse(request.requestBody);
expect(edit_helpers.hasSavedMockXBlock()).toBeTruthy();
expect(response.metadata.display_name).toBe(testDisplayName);
expect(response.metadata.custom_field).toBe('Custom Value');
});
});
......@@ -51,12 +72,11 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers
mockXModuleEditorHtml = readFixtures('mock/mock-xmodule-editor.underscore');
beforeEach(function() {
// Mock the VerticalDescriptor so that the module can be rendered
window.VerticalDescriptor = XModule.Descriptor;
edit_helpers.installMockXModule(mockSaveResponse);
});
afterEach(function () {
window.VerticalDescriptor = null;
edit_helpers.uninstallMockXModule();
});
it('can render itself', function() {
......@@ -70,26 +90,28 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers
expect(editor.$el.select('.xblock-header')).toBeTruthy();
expect(editor.getMode()).toEqual('editor');
});
});
describe("Editing an xmodule (settings only)", function() {
var mockXModuleEditorHtml;
mockXModuleEditorHtml = readFixtures('mock/mock-xmodule-settings-only-editor.underscore');
beforeEach(function() {
edit_helpers.installEditTemplates();
// Mock the VerticalDescriptor so that the module can be rendered
window.VerticalDescriptor = XModule.Descriptor;
it('saves any custom metadata', function() {
var requests = create_sinon.requests(this), request, response;
editor.render();
create_sinon.respondWithJson(requests, {
html: mockXModuleEditorHtml,
"resources": []
});
// Give the mock xblock a save method...
editor.xblock.save = window.MockDescriptor.save;
editor.save();
request = requests[requests.length - 1];
response = JSON.parse(request.requestBody);
expect(edit_helpers.hasSavedMockXModule()).toBeTruthy();
expect(response.metadata.display_name).toBe(testDisplayName);
expect(response.metadata.custom_field).toBe('Custom Value');
});
afterEach(function () {
window.VerticalDescriptor = null;
});
it('can render a module with only settings', function() {
var requests = create_sinon.requests(this), mockXModuleEditorHtml;
mockXModuleEditorHtml = readFixtures('mock/mock-xmodule-settings-only-editor.underscore');
it('can render itself', function() {
var requests = create_sinon.requests(this);
editor.render();
create_sinon.respondWithJson(requests, {
html: mockXModuleEditorHtml,
......
......@@ -10,9 +10,55 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/modal_helpers
stringEntryTemplate = readFixtures('metadata-string-entry.underscore'),
editXBlockModalTemplate = readFixtures('edit-xblock-modal.underscore'),
editorModeButtonTemplate = readFixtures('editor-mode-button.underscore'),
xblockSaved,
installMockXBlock,
uninstallMockXBlock,
hasSavedMockXBlock,
xmoduleSaved,
installMockXModule,
uninstallMockXModule,
hasSavedMockXModule,
installEditTemplates,
showEditModal;
installMockXBlock = function(mockResult) {
xblockSaved = false;
window.MockXBlock = function(runtime, element) {
return {
save: function() {
xblockSaved = true;
return mockResult;
}
};
};
};
uninstallMockXBlock = function() {
window.MockXBlock = null;
};
hasSavedMockXBlock = function() {
return xblockSaved;
};
installMockXModule = function(mockResult) {
xmoduleSaved = false;
window.MockDescriptor = _.extend(XModule.Descriptor, {
save: function() {
xmoduleSaved = true;
return mockResult;
}
});
};
uninstallMockXModule = function() {
window.MockDescriptor = null;
};
hasSavedMockXModule = function() {
return xmoduleSaved;
};
installEditTemplates = function(append) {
modal_helpers.installModalTemplates(append);
......@@ -37,6 +83,12 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/modal_helpers
};
return $.extend(modal_helpers, {
'installMockXBlock': installMockXBlock,
'hasSavedMockXBlock': hasSavedMockXBlock,
'uninstallMockXBlock': uninstallMockXBlock,
'installMockXModule': installMockXModule,
'hasSavedMockXModule': hasSavedMockXModule,
'uninstallMockXModule': uninstallMockXModule,
'installEditTemplates': installEditTemplates,
'showEditModal': showEditModal
});
......
......@@ -85,8 +85,7 @@ define(["jquery", "underscore", "gettext", "js/views/feedback_notification", "js
},
save: function(options) {
var xblock = this.xblock,
xblockInfo = this.model,
var xblockInfo = this.model,
data,
saving;
data = this.getXBlockData();
......@@ -131,14 +130,14 @@ define(["jquery", "underscore", "gettext", "js/views/feedback_notification", "js
// Walk through the set of elements which have the 'data-metadata_name' attribute and
// build up an object to pass back to the server on the subsequent POST.
// Note that these values will always be sent back on POST, even if they did not actually change.
var metadata = {},
metadataNameElements;
var metadata, metadataNameElements, i, element, metadataName;
metadata = {};
metadataNameElements = this.$('[data-metadata-name]');
metadataNameElements.each(function (element) {
var key = $(element).data("metadata-name"),
value = element.value;
metadata[key] = value;
});
for (i = 0; i < metadataNameElements.length; i++) {
element = metadataNameElements[i];
metadataName = $(element).data("metadata-name");
metadata[metadataName] = element.value;
}
return metadata;
},
......
......@@ -32,12 +32,12 @@ main_xblock_info = {
<script type='text/javascript'>
require(["domReady!", "jquery", "js/models/xblock_info", "js/views/pages/container",
"xmodule", "coffee/src/main", "xblock/cms.runtime.v1"],
function(doc, $, XBlockInfo, XBlockContainerPage) {
function(doc, $, XBlockInfo, ContainerPage) {
var view, mainXBlockInfo;
mainXBlockInfo = new XBlockInfo(${json.dumps(main_xblock_info) | n});
view = new XBlockContainerPage({
view = new ContainerPage({
el: $('#content'),
model: mainXBlockInfo
});
......
<header class="xblock-header">
<div class="header-details">
<span>Mock XBlock</span>
</div>
<div class="header-actions">
<ul class="actions-list">
<li class="sr action-item">No Actions</li>
</ul>
</div>
</header>
<article class="xblock-render">
<div class="xblock xblock-student_view xmodule_display xmodule_VerticalModule"
data-runtime-class="PreviewRuntime" data-init="XBlockToXModuleShim" data-runtime-version="1"
data-type="None">
<div class="mock-updated-content">Mock Update</div>
</div>
</article>
<div class="xblock xblock-studio_view" data-runtime-version="1" data-usage-id="i4x:;_;_edX;_mock"
data-init="MockXBlock" data-runtime-class="StudioRuntime" data-block-type="mock" tabindex="0">
<div class="mock-xblock">
<h3>Mock XBlock Editor</h3>
</div>
<div class="mock-xblock">
<h3>Mock XBlock Editor</h3>
<div class="metadata_edit"></div>
<textarea data-metadata-name="custom_field">Custom Value</textarea>
</div>
</div>
<div class="xblock xblock-studio_view xmodule_edit xmodule_WrapperDescriptor" data-runtime-class="StudioRuntime" data-init="XBlockToXModuleShim" data-runtime-version="1" data-usage-id="i4x:;_;_AndyA;_ABT101;_wrapper;_wrapper_l1_poll" data-type="VerticalDescriptor" data-block-type="wrapper" tabindex="0">
<div class="xblock xblock-studio_view xmodule_edit xmodule_WrapperDescriptor" data-runtime-class="StudioRuntime" data-init="XBlockToXModuleShim" data-runtime-version="1" data-usage-id="i4x:;_;_AndyA;_ABT101;_wrapper;_wrapper_l1_poll" data-type="MockDescriptor" data-block-type="wrapper" tabindex="0">
<div class="wrapper-comp-editor is-active" id="editor-tab" data-base-asset-url="/c4x/AndyA/ABT101/asset/">
</div>
<section class="sequence-edit">
......@@ -25,5 +25,6 @@
</script>
<div class="wrapper-comp-settings metadata_edit" id="settings-tab" data-metadata='{&#34;display_name&#34;: {&#34;default_value&#34;: null, &#34;explicitly_set&#34;: true, &#34;display_name&#34;: &#34;Display Name&#34;, &#34;help&#34;: &#34;This name appears in the horizontal navigation at the top of the page.&#34;, &#34;type&#34;: &#34;Generic&#34;, &#34;value&#34;: &#34;Poll Question&#34;, &#34;field_name&#34;: &#34;display_name&#34;, &#34;options&#34;: []}, &#34;due&#34;: {&#34;default_value&#34;: null, &#34;explicitly_set&#34;: false, &#34;display_name&#34;: &#34;due&#34;, &#34;help&#34;: &#34;Date that this problem is due by&#34;, &#34;type&#34;: &#34;Generic&#34;, &#34;value&#34;: null, &#34;field_name&#34;: &#34;due&#34;, &#34;options&#34;: []}}'/>
<textarea data-metadata-name="custom_field">Custom Value</textarea>
</section>
</div>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment