Files
edx-platform/cms/static/js/spec/views/container_spec.js
Andy Armstrong 541d20ef83 Allow creation of components on container page
This commit implements STUD-1490, allowing creation of components
on the container page. It also enables the delete and duplicate
buttons now that new content can be created that would benefit.

Note that it also creates shared functionality for adding components,
and refactors the unit page to use it too.
2014-05-21 15:40:31 -04:00

212 lines
10 KiB
JavaScript

define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers",
"js/views/container", "js/models/xblock_info", "jquery.simulate",
"xmodule", "coffee/src/main", "xblock/cms.runtime.v1"],
function ($, create_sinon, view_helpers, ContainerView, XBlockInfo) {
describe("Container View", function () {
describe("Supports reordering components", function () {
var model, containerView, mockContainerHTML, respondWithMockXBlockFragment, init, getComponent,
getDragHandle, dragComponentVertically, dragComponentAbove,
verifyRequest, verifyNumReorderCalls, respondToRequest, notificationSpy,
rootLocator = 'testCourse/branch/draft/split_test/splitFFF',
containerTestUrl = '/xblock/' + rootLocator,
groupAUrl = "/xblock/locator-group-A",
groupA = "locator-group-A",
groupAComponent1 = "locator-component-A1",
groupAComponent2 = "locator-component-A2",
groupAComponent3 = "locator-component-A3",
groupBUrl = "/xblock/locator-group-B",
groupB = "locator-group-B",
groupBComponent1 = "locator-component-B1",
groupBComponent2 = "locator-component-B2",
groupBComponent3 = "locator-component-B3";
mockContainerHTML = readFixtures('mock/mock-container-xblock.underscore');
respondWithMockXBlockFragment = function (requests, response) {
var requestIndex = requests.length - 1;
create_sinon.respondWithJson(requests, response, requestIndex);
};
beforeEach(function () {
view_helpers.installViewTemplates();
appendSetFixtures('<div class="wrapper-xblock level-page studio-xblock-wrapper" data-locator="' + rootLocator + '"></div>');
notificationSpy = view_helpers.createNotificationSpy();
model = new XBlockInfo({
id: rootLocator,
display_name: 'Test AB Test',
category: 'split_test'
});
containerView = new ContainerView({
model: model,
view: 'container_preview',
el: $('.wrapper-xblock')
});
});
afterEach(function () {
containerView.remove();
});
init = function (caller) {
var requests = create_sinon.requests(caller);
containerView.render();
respondWithMockXBlockFragment(requests, {
html: mockContainerHTML,
"resources": []
});
$('body').append(containerView.$el);
// Give the whole container enough height to contain everything.
$('.xblock[data-locator=locator-container]').css('height', 2000);
// Give the groups enough height to contain their child vertical elements.
$('.is-draggable[data-locator=locator-group-A]').css('height', 800);
$('.is-draggable[data-locator=locator-group-B]').css('height', 800);
// Give the leaf elements some height to mimic actual components. Otherwise
// drag and drop fails as the elements on bunched on top of each other.
$('.level-element').css('height', 200);
return requests;
};
getComponent = function(locator) {
return containerView.$('.studio-xblock-wrapper[data-locator="' + locator + '"]');
};
getDragHandle = function(locator) {
var component = getComponent(locator);
return $(component.find('.drag-handle')[0]);
};
dragComponentVertically = function (locator, dy) {
var handle = getDragHandle(locator);
handle.simulate("drag", {dy: dy});
};
dragComponentAbove = function (sourceLocator, targetLocator) {
var targetElement = getComponent(targetLocator),
targetTop = targetElement.offset().top + 1,
handle = getDragHandle(sourceLocator),
handleY = handle.offset().top + (handle.height() / 2),
dy = targetTop - handleY;
handle.simulate("drag", {dy: dy});
};
verifyRequest = function (requests, reorderCallIndex, expectedURL, expectedChildren) {
var actualIndex, request, children, i;
// 0th call is the response to the initial render call to get HTML.
actualIndex = reorderCallIndex + 1;
expect(requests.length).toBeGreaterThan(actualIndex);
request = requests[actualIndex];
expect(request.url).toEqual(expectedURL);
children = (JSON.parse(request.requestBody)).children;
expect(children.length).toEqual(expectedChildren.length);
for (i = 0; i < children.length; i++) {
expect(children[i]).toEqual(expectedChildren[i]);
}
};
verifyNumReorderCalls = function (requests, expectedCalls) {
// Number of calls will be 1 more than expected because of the initial render call to get HTML.
expect(requests.length).toEqual(expectedCalls + 1);
};
respondToRequest = function (requests, reorderCallIndex, status) {
var actualIndex;
// Number of calls will be 1 more than expected because of the initial render call to get HTML.
actualIndex = reorderCallIndex + 1;
expect(requests.length).toBeGreaterThan(actualIndex);
requests[actualIndex].respond(status);
};
it('does nothing if item not moved far enough', function () {
var requests = init(this);
// Drag the first component in Group A down very slightly but not enough to move it.
dragComponentVertically(groupAComponent1, 5);
verifyNumReorderCalls(requests, 0);
});
it('can reorder within a group', function () {
var requests = init(this);
// Drag the third component in Group A to be the first
dragComponentAbove(groupAComponent3, groupAComponent1);
respondToRequest(requests, 0, 200);
verifyRequest(requests, 0, groupAUrl, [groupAComponent3, groupAComponent1, groupAComponent2]);
});
it('can drag from one group to another', function () {
var requests = init(this);
// Drag the first component in Group B to the top of group A.
dragComponentAbove(groupBComponent1, groupAComponent1);
// Respond to the two requests: add the component to Group A, then remove it from Group B.
respondToRequest(requests, 0, 200);
respondToRequest(requests, 1, 200);
verifyRequest(requests, 0, groupAUrl,
[groupBComponent1, groupAComponent1, groupAComponent2, groupAComponent3]);
verifyRequest(requests, 1, groupBUrl, [groupBComponent2, groupBComponent3]);
});
it('does not remove from old group if addition to new group fails', function () {
var requests = init(this);
// Drag the first component in Group B to the first group.
dragComponentAbove(groupBComponent1, groupAComponent1);
respondToRequest(requests, 0, 500);
// Send failure for addition to new group -- no removal event should be received.
verifyRequest(requests, 0, groupAUrl,
[groupBComponent1, groupAComponent1, groupAComponent2, groupAComponent3]);
// Verify that a second request was not issued
verifyNumReorderCalls(requests, 1);
});
it('can swap group A and group B', function () {
var requests = init(this);
// Drag Group B before group A.
dragComponentAbove(groupB, groupA);
respondToRequest(requests, 0, 200);
verifyRequest(requests, 0, containerTestUrl, [groupB, groupA]);
});
describe("Shows a saving message", function () {
it('hides saving message upon success', function () {
var requests, savingOptions;
requests = init(this);
// Drag the first component in Group B to the first group.
dragComponentAbove(groupBComponent1, groupAComponent1);
view_helpers.verifyNotificationShowing(notificationSpy, 'Saving');
respondToRequest(requests, 0, 200);
view_helpers.verifyNotificationShowing(notificationSpy, 'Saving');
respondToRequest(requests, 1, 200);
view_helpers.verifyNotificationHidden(notificationSpy);
});
it('does not hide saving message if failure', function () {
var requests = init(this);
// Drag the first component in Group B to the first group.
dragComponentAbove(groupBComponent1, groupAComponent1);
view_helpers.verifyNotificationShowing(notificationSpy, 'Saving');
respondToRequest(requests, 0, 500);
view_helpers.verifyNotificationShowing(notificationSpy, 'Saving');
// Since the first reorder call failed, the removal will not be called.
verifyNumReorderCalls(requests, 1);
});
});
});
});
});