Files
edx-platform/cms/static/js/spec/views/unit_spec.js
Adam Palay 7c13ba0c3b Disable draft and edit links during ajax calls
STUD-1485
STUD-1499
2014-05-02 09:11:46 -04:00

241 lines
11 KiB
JavaScript

define(["coffee/src/views/unit", "js/models/module_info", "js/spec_helpers/create_sinon", "js/views/feedback_notification",
"jasmine-stealth"],
function (UnitEditView, ModuleModel, create_sinon, NotificationView) {
var verifyJSON = function (requests, json) {
var request = requests[requests.length - 1];
expect(request.url).toEqual("/xblock");
expect(request.method).toEqual("POST");
// There was a problem with order of returned parameters in strings.
// Changed to compare objects instead strings.
expect(JSON.parse(request.requestBody)).toEqual(JSON.parse(json));
};
var verifyComponents = function (unit, locators) {
var components = unit.$(".component");
expect(components.length).toBe(locators.length);
for (var i=0; i < locators.length; i++) {
expect($(components[i]).data('locator')).toBe(locators[i]);
}
};
var verifyNotification = function (notificationSpy, text, requests) {
expect(notificationSpy.constructor).toHaveBeenCalled();
expect(notificationSpy.show).toHaveBeenCalled();
expect(notificationSpy.hide).not.toHaveBeenCalled();
var options = notificationSpy.constructor.mostRecentCall.args[0];
expect(options.title).toMatch(text);
create_sinon.respondWithJson(requests, {"locator": "new_item"});
expect(notificationSpy.hide).toHaveBeenCalled();
};
describe('duplicateComponent ', function () {
var duplicateFixture =
'<div class="main-wrapper edit-state-draft" data-locator="unit_locator"> \
<ol class="components"> \
<li class="component" data-locator="loc_1"> \
<div class="wrapper wrapper-component-editor"/> \
<ul class="component-actions"> \
<a href="#" data-tooltip="Duplicate" class="duplicate-button action-button"><i class="icon-copy"></i><span class="sr"></span>Duplicate</span></a> \
</ul> \
</li> \
<li class="component" data-locator="loc_2"> \
<div class="wrapper wrapper-component-editor"/> \
<ul class="component-actions"> \
<a href="#" data-tooltip="Duplicate" class="duplicate-button action-button"><i class="icon-copy"></i><span class="sr"></span>Duplicate</span></a> \
</ul> \
</li> \
</ol> \
</div>';
var unit;
var clickDuplicate = function (index) {
unit.$(".duplicate-button")[index].click();
};
beforeEach(function () {
setFixtures(duplicateFixture);
unit = new UnitEditView({
el: $('.main-wrapper'),
model: new ModuleModel({
id: 'unit_locator',
state: 'draft'
})
});
});
it('sends the correct JSON to the server', function () {
var requests = create_sinon.requests(this);
clickDuplicate(0);
verifyJSON(requests, '{"duplicate_source_locator":"loc_1","parent_locator":"unit_locator"}');
});
it('inserts duplicated component immediately after source upon success', function () {
var requests = create_sinon.requests(this);
clickDuplicate(0);
create_sinon.respondWithJson(requests, {"locator": "duplicated_item"});
verifyComponents(unit, ['loc_1', 'duplicated_item', 'loc_2']);
});
it('inserts duplicated component at end if source at end', function () {
var requests = create_sinon.requests(this);
clickDuplicate(1);
create_sinon.respondWithJson(requests, {"locator": "duplicated_item"});
verifyComponents(unit, ['loc_1', 'loc_2', 'duplicated_item']);
});
it('shows a notification while duplicating', function () {
var notificationSpy = spyOnConstructor(NotificationView, "Mini", ["show", "hide"]);
notificationSpy.show.andReturn(notificationSpy);
var requests = create_sinon.requests(this);
clickDuplicate(0);
verifyNotification(notificationSpy, /Duplicating/, requests);
});
it('does not insert duplicated component upon failure', function () {
var server = create_sinon.server(500, this);
clickDuplicate(0);
server.respond();
verifyComponents(unit, ['loc_1', 'loc_2']);
});
});
describe('saveNewComponent ', function () {
var newComponentFixture =
'<div class="main-wrapper edit-state-draft" data-locator="unit_locator"> \
<ol class="components"> \
<li class="component" data-locator="loc_1"> \
<div class="wrapper wrapper-component-editor"/> \
</li> \
<li class="component" data-locator="loc_2"> \
<div class="wrapper wrapper-component-editor"/> \
</li> \
<li class="new-component-item adding"> \
<div class="new-component"> \
<ul class="new-component-type"> \
<li> \
<a href="#" class="single-template" data-type="discussion" data-category="discussion"/> \
</li> \
</ul> \
</div> \
</li> \
</ol> \
</div>';
var unit;
var clickNewComponent = function () {
unit.$(".new-component .new-component-type a.single-template").click();
};
beforeEach(function () {
setFixtures(newComponentFixture);
unit = new UnitEditView({
el: $('.main-wrapper'),
model: new ModuleModel({
id: 'unit_locator',
state: 'draft'
})
});
});
it('sends the correct JSON to the server', function () {
var requests = create_sinon.requests(this);
clickNewComponent();
verifyJSON(requests, '{"category":"discussion","type":"discussion","parent_locator":"unit_locator"}');
});
it('inserts new component at end', function () {
var requests = create_sinon.requests(this);
clickNewComponent();
create_sinon.respondWithJson(requests, {"locator": "new_item"});
verifyComponents(unit, ['loc_1', 'loc_2', 'new_item']);
});
it('shows a notification while creating', function () {
var notificationSpy = spyOnConstructor(NotificationView, "Mini", ["show", "hide"]);
notificationSpy.show.andReturn(notificationSpy);
var requests = create_sinon.requests(this);
clickNewComponent();
verifyNotification(notificationSpy, /Adding/, requests);
});
it('does not insert duplicated component upon failure', function () {
var server = create_sinon.server(500, this);
clickNewComponent();
server.respond();
verifyComponents(unit, ['loc_1', 'loc_2']);
});
});
describe("Disabled edit/publish links during ajax call", function() {
var unit,
link,
draft_states = [
{
state: "draft",
selector: ".publish-draft"
},
{
state: "public",
selector: ".create-draft"
}
],
editLinkFixture =
'<div class="main-wrapper edit-state-draft" data-locator="unit_locator"> \
<div class="unit-settings window"> \
<h4 class="header">Unit Settings</h4> \
<div class="window-contents"> \
<div class="row published-alert"> \
<p class="edit-draft-message"> \
<a href="#" class="create-draft">edit a draft</a> \
</p> \
<p class="publish-draft-message"> \
<a href="#" class="publish-draft">replace it with this draft</a> \
</p> \
</div> \
</div> \
</div> \
</div>';
function test_link_disabled_during_ajax_call(draft_state) {
beforeEach(function () {
setFixtures(editLinkFixture);
unit = new UnitEditView({
el: $('.main-wrapper'),
model: new ModuleModel({
id: 'unit_locator',
state: draft_state['state']
})
});
// needed to stub out the ajax
window.analytics = jasmine.createSpyObj('analytics', ['track']);
window.course_location_analytics = jasmine.createSpy('course_location_analytics');
window.unit_location_analytics = jasmine.createSpy('unit_location_analytics');
});
it("reenables the " + draft_state['selector'] + " link once the ajax call returns", function() {
runs(function(){
spyOn($, "ajax").andCallThrough();
spyOn($.fn, 'addClass').andCallThrough();
spyOn($.fn, 'removeClass').andCallThrough();
link = $(draft_state['selector']);
link.click();
});
waitsFor(function(){
// wait for "is-disabled" to be removed as a class
return !($(draft_state['selector']).hasClass("is-disabled"));
}, 500);
runs(function(){
// check that the `is-disabled` class was added and removed
expect($.fn.addClass).toHaveBeenCalledWith("is-disabled");
expect($.fn.removeClass).toHaveBeenCalledWith("is-disabled");
// make sure the link finishes without the `is-disabled` class
expect(link).not.toHaveClass("is-disabled");
// affirm that ajax was called
expect($.ajax).toHaveBeenCalled();
});
});
};
for (var i = 0; i < draft_states.length; i++) {
test_link_disabled_during_ajax_call(draft_states[i]);
};
});
}
);