Commit b2a0b2f7 by Andy Armstrong

Improve response handling in AjaxHelpers

I've changed the logic so that AjaxHelpers keeps
track of which requests have not yet had mock
responses sent. This ensures that every response
is handled before moving on to the next one,
rather than always handling the last request.
My intention is that this won't allow bugs to creep
in where a request isn't fired and instead the test
responds to an old request. It also should ensure
that extra events aren't accidentally fired.
parent 7280a587
......@@ -290,6 +290,7 @@ define ["jquery", "jasmine", "common/js/spec_helpers/ajax_helpers", "squire"],
it "should remove the deleted asset from the view", ->
{view: @view, requests: requests} = @createAssetsView(this)
AjaxHelpers.respondWithJson(requests, @mockAssetsResponse)
setup.call(this, requests)
# Delete the 2nd asset with success from server.
@view.$(".remove-asset-button")[1].click()
......
......@@ -309,7 +309,7 @@ define(["js/utils/drag_and_drop", "common/js/components/views/feedback_notificat
this.clock.restore();
});
it("should send an update on reorder from one parent to another", function () {
var requests, savingOptions;
var requests, request, savingOptions;
requests = AjaxHelpers["requests"](this);
ContentDragger.dragState.dropDestination = $('#unit-4');
ContentDragger.dragState.attachMethod = "after";
......@@ -323,15 +323,15 @@ define(["js/utils/drag_and_drop", "common/js/components/views/feedback_notificat
}, null, {
clientX: $('#unit-1').offset().left
});
expect(requests.length).toEqual(1);
request = AjaxHelpers.currentRequest(requests);
expect(this.savingSpies.constructor).toHaveBeenCalled();
expect(this.savingSpies.show).toHaveBeenCalled();
expect(this.savingSpies.hide).not.toHaveBeenCalled();
savingOptions = this.savingSpies.constructor.mostRecentCall.args[0];
expect(savingOptions.title).toMatch(/Saving/);
expect($('#unit-1')).toHaveClass('was-dropped');
expect(requests[0].requestBody).toEqual('{"children":["fourth-unit-id","first-unit-id"]}');
requests[0].respond(200);
expect(request.requestBody).toEqual('{"children":["fourth-unit-id","first-unit-id"]}');
request.respond(200);
expect(this.savingSpies.hide).toHaveBeenCalled();
this.clock.tick(1001);
expect($('#unit-1')).not.toHaveClass('was-dropped');
......@@ -341,7 +341,8 @@ define(["js/utils/drag_and_drop", "common/js/components/views/feedback_notificat
expect($('#subsection-2').data('refresh')).toHaveBeenCalled();
});
it("should send an update on reorder within the same parent", function () {
var requests = AjaxHelpers["requests"](this);
var requests = AjaxHelpers["requests"](this),
request;
ContentDragger.dragState.dropDestination = $('#unit-2');
ContentDragger.dragState.attachMethod = "after";
ContentDragger.dragState.parentList = $('#subsection-1');
......@@ -354,12 +355,12 @@ define(["js/utils/drag_and_drop", "common/js/components/views/feedback_notificat
}, null, {
clientX: $('#unit-1').offset().left
});
expect(requests.length).toEqual(1);
request = AjaxHelpers.currentRequest(requests);
expect($('#unit-1')).toHaveClass('was-dropped');
expect(requests[0].requestBody).toEqual(
expect(request.requestBody).toEqual(
'{"children":["second-unit-id","first-unit-id","third-unit-id"]}'
);
requests[0].respond(200);
request.respond(200);
this.clock.tick(1001);
expect($('#unit-1')).not.toHaveClass('was-dropped');
// parent
......
......@@ -119,13 +119,12 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/asset
};
var respondWithMockAssets = function(requests) {
var requestIndex = requests.length - 1;
var request = requests[requestIndex];
var request = AjaxHelpers.currentRequest(requests);
var url = new URI(request.url);
var queryParameters = url.query(true); // Returns an object with each query parameter stored as a value
var asset_type = queryParameters.asset_type;
var response = asset_type !== '' ? mockExampleFilteredAssetsResponse : mockExampleAssetsResponse;
AjaxHelpers.respondWithJson(requests, response, requestIndex);
AjaxHelpers.respondWithJson(requests, response);
};
var event = {};
......
......@@ -7,7 +7,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "js/spec_helpers/edit_
describe("Supports reordering components", function () {
var model, containerView, mockContainerHTML, respondWithMockXBlockFragment, init, getComponent,
var model, containerView, mockContainerHTML, init, getComponent,
getDragHandle, dragComponentVertically, dragComponentAbove,
verifyRequest, verifyNumReorderCalls, respondToRequest, notificationSpy,
......@@ -28,11 +28,6 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "js/spec_helpers/edit_
mockContainerHTML = readFixtures('mock/mock-container-xblock.underscore');
respondWithMockXBlockFragment = function (requests, response) {
var requestIndex = requests.length - 1;
AjaxHelpers.respondWithJson(requests, response, requestIndex);
};
beforeEach(function () {
EditHelpers.installMockXBlock();
EditHelpers.installViewTemplates();
......@@ -60,7 +55,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "js/spec_helpers/edit_
var requests = AjaxHelpers.requests(caller);
containerView.render();
respondWithMockXBlockFragment(requests, {
AjaxHelpers.respondWithJson(requests, {
html: mockContainerHTML,
"resources": []
});
......
......@@ -443,19 +443,19 @@ define([
'Group Configuration name is required'
);
// No request
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
// Set correct value
setValuesToInputs(this.view, { inputName: 'New Configuration' });
// Try to save
this.view.$('form').submit();
requests[0].respond(200);
AjaxHelpers.respondWithJson(requests, {});
// Model is updated
expect(this.model).toBeCorrectValuesInModel({
name: 'New Configuration'
});
// Error message disappear
expect(this.view.$(SELECTORS.errorMessage)).not.toExist();
expect(requests.length).toBe(1);
AjaxHelpers.expectNoRequests(requests);
});
it('should have appropriate class names on focus/blur', function () {
......@@ -733,9 +733,9 @@ define([
};
respondToSave = function(requests, view) {
expect(requests.length).toBe(1);
expect(requests[0].method).toBe('POST');
expect(requests[0].url).toBe('/mock_url/0');
var request = AjaxHelpers.currentRequest(requests);
expect(request.method).toBe('POST');
expect(request.url).toBe('/mock_url/0');
AjaxHelpers.respondWithJson(requests, {
name: 'Content Group Configuration',
groups: view.collection.map(function(groupModel, index) {
......@@ -803,7 +803,7 @@ define([
newGroupName = 'New Group Name',
view = renderView();
editNewGroup(view, {newName: newGroupName, cancel: true});
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
verifyEditingGroup(view, false);
expect(view.$()).not.toContainText(newGroupName);
});
......@@ -814,7 +814,7 @@ define([
view = renderView([originalGroupName]);
editExistingGroup(view, {newName: 'New Group Name', cancel: true});
verifyEditingGroup(view, false);
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
expect(view.collection.at(0).get('name')).toBe(originalGroupName);
});
......@@ -823,7 +823,7 @@ define([
newGroupName = 'New Group Name',
view = renderView();
editNewGroup(view, {newName: '', save: true});
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
correctValidationError(view, requests, newGroupName);
});
......@@ -832,7 +832,7 @@ define([
oldGroupName = 'Old Group Name',
view = renderView([oldGroupName]);
editExistingGroup(view, {newName: '', save: true});
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
correctValidationError(view, requests, oldGroupName);
});
......
......@@ -54,15 +54,14 @@ define(["jquery", "underscore", "common/js/spec_helpers/ajax_helpers", "URI", "j
});
var respondWithMockPage = function(requests, mockPage) {
var requestIndex = requests.length - 1;
var request = AjaxHelpers.currentRequest(requests);
if (typeof mockPage == 'undefined') {
var request = requests[requestIndex];
var url = new URI(request.url);
var queryParameters = url.query(true); // Returns an object with each query parameter stored as a value
var page = queryParameters.page_number;
mockPage = page === "0" ? mockFirstPage : mockSecondPage;
}
AjaxHelpers.respondWithJson(requests, mockPage, requestIndex);
AjaxHelpers.respondWithJson(requests, mockPage);
};
var MockPagingView = PagedContainer.extend({
......@@ -140,7 +139,7 @@ define(["jquery", "underscore", "common/js/spec_helpers/ajax_helpers", "URI", "j
pagingContainer.setPage(1);
respondWithMockPage(requests);
pagingContainer.nextPage();
expect(requests.length).toBe(1);
AjaxHelpers.expectNoRequests(requests);
});
});
......@@ -159,7 +158,7 @@ define(["jquery", "underscore", "common/js/spec_helpers/ajax_helpers", "URI", "j
pagingContainer.setPage(0);
respondWithMockPage(requests);
pagingContainer.previousPage();
expect(requests.length).toBe(1);
AjaxHelpers.expectNoRequests(requests);
});
it('does not move back after a server error', function () {
......
......@@ -2,22 +2,23 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
"common/js/spec_helpers/template_helpers", "js/spec_helpers/edit_helpers",
"js/views/pages/container", "js/views/pages/paged_container", "js/models/xblock_info", "jquery.simulate"],
function ($, _, str, AjaxHelpers, TemplateHelpers, EditHelpers, ContainerPage, PagedContainerPage, XBlockInfo) {
'use strict';
function parameterized_suite(label, global_page_options, fixtures) {
function parameterized_suite(label, globalPageOptions) {
describe(label + " ContainerPage", function () {
var lastRequest, getContainerPage, renderContainerPage, expectComponents, respondWithHtml,
model, containerPage, requests, initialDisplayName,
var getContainerPage, renderContainerPage, handleContainerPageRefresh, expectComponents,
respondWithHtml, model, containerPage, requests, initialDisplayName,
mockContainerPage = readFixtures('mock/mock-container-page.underscore'),
mockContainerXBlockHtml = readFixtures(fixtures.initial),
mockXBlockHtml = readFixtures(fixtures.add_response),
mockContainerXBlockHtml = readFixtures(globalPageOptions.initial),
mockXBlockHtml = readFixtures(globalPageOptions.addResponse),
mockBadContainerXBlockHtml = readFixtures('mock/mock-bad-javascript-container-xblock.underscore'),
mockBadXBlockContainerXBlockHtml = readFixtures('mock/mock-bad-xblock-container-xblock.underscore'),
mockUpdatedContainerXBlockHtml = readFixtures('mock/mock-updated-container-xblock.underscore'),
mockXBlockEditorHtml = readFixtures('mock/mock-xblock-editor.underscore'),
mockXBlockVisibilityEditorHtml = readFixtures('mock/mock-xblock-visibility-editor.underscore'),
PageClass = fixtures.page,
pagedSpecificTests = fixtures.paged_specific_tests,
hasVisibilityEditor = fixtures.has_visibility_editor;
PageClass = globalPageOptions.page,
pagedSpecificTests = globalPageOptions.pagedSpecificTests,
hasVisibilityEditor = globalPageOptions.hasVisibilityEditor;
beforeEach(function () {
var newDisplayName = 'New Display Name';
......@@ -47,16 +48,10 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
EditHelpers.uninstallMockXBlock();
});
lastRequest = function () {
return requests[requests.length - 1];
};
respondWithHtml = function (html) {
var requestIndex = requests.length - 1;
AjaxHelpers.respondWithJson(
requests,
{ html: html, "resources": [] },
requestIndex
{ html: html, "resources": [] }
);
};
......@@ -66,7 +61,7 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
templates: EditHelpers.mockComponentTemplates,
el: $('#content')
};
return new PageClass(_.extend(options || {}, global_page_options, default_options));
return new PageClass(_.extend(options || {}, globalPageOptions, default_options));
};
renderContainerPage = function (test, html, options) {
......@@ -74,6 +69,18 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
containerPage = getContainerPage(options);
containerPage.render();
respondWithHtml(html);
AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/locator-container');
AjaxHelpers.respondWithJson(requests, options);
};
handleContainerPageRefresh = function(requests) {
var request = AjaxHelpers.currentRequest(requests);
expect(str.startsWith(request.url,
'/xblock/locator-container/container_preview')).toBeTruthy();
AjaxHelpers.respondWithJson(requests, {
html: mockUpdatedContainerXBlockHtml,
resources: []
});
};
expectComponents = function (container, locators) {
......@@ -136,7 +143,7 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
};
it('can edit itself', function () {
var editButtons, displayNameElement;
var editButtons, displayNameElement, request;
renderContainerPage(this, mockContainerXBlockHtml);
displayNameElement = containerPage.$('.page-header-title');
......@@ -145,7 +152,8 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
editButtons.first().click();
// Expect a request to be made to show the studio view for the container
expect(str.startsWith(lastRequest().url, '/xblock/locator-container/studio_view')).toBeTruthy();
request = AjaxHelpers.currentRequest(requests);
expect(str.startsWith(request.url, '/xblock/locator-container/studio_view')).toBeTruthy();
AjaxHelpers.respondWithJson(requests, {
html: mockContainerXBlockHtml,
resources: []
......@@ -161,12 +169,7 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
expect(EditHelpers.isShowingModal()).toBeFalsy();
// Expect the last request be to refresh the container page
expect(str.startsWith(lastRequest().url,
'/xblock/locator-container/container_preview')).toBeTruthy();
AjaxHelpers.respondWithJson(requests, {
html: mockUpdatedContainerXBlockHtml,
resources: []
});
handleContainerPageRefresh(requests);
// Respond to the subsequent xblock info fetch request.
AjaxHelpers.respondWithJson(requests, {"display_name": updatedDisplayName});
......@@ -196,14 +199,15 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
});
it('can show an edit modal for a child xblock', function () {
var editButtons;
var editButtons, request;
renderContainerPage(this, mockContainerXBlockHtml);
editButtons = containerPage.$('.wrapper-xblock .edit-button');
// The container should have rendered six mock xblocks
expect(editButtons.length).toBe(6);
editButtons[0].click();
// Make sure that the correct xblock is requested to be edited
expect(str.startsWith(lastRequest().url, '/xblock/locator-component-A1/studio_view')).toBeTruthy();
request = AjaxHelpers.currentRequest(requests);
expect(str.startsWith(request.url, '/xblock/locator-component-A1/studio_view')).toBeTruthy();
AjaxHelpers.respondWithJson(requests, {
html: mockXBlockEditorHtml,
resources: []
......@@ -224,13 +228,14 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
});
it('can show a visibility modal for a child xblock if supported for the page', function() {
var visibilityButtons;
var visibilityButtons, request;
renderContainerPage(this, mockContainerXBlockHtml);
visibilityButtons = containerPage.$('.wrapper-xblock .visibility-button');
if (hasVisibilityEditor) {
expect(visibilityButtons.length).toBe(6);
visibilityButtons[0].click();
expect(str.startsWith(lastRequest().url, '/xblock/locator-component-A1/visibility_view'))
request = AjaxHelpers.currentRequest(requests);
expect(str.startsWith(request.url, '/xblock/locator-component-A1/visibility_view'))
.toBeTruthy();
AjaxHelpers.respondWithJson(requests, {
html: mockXBlockVisibilityEditorHtml,
......@@ -297,7 +302,7 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
});
describe("xblock operations", function () {
var getGroupElement, paginated, getDeleteOffset,
var getGroupElement,
NUM_COMPONENTS_PER_GROUP = 3, GROUP_TO_TEST = "A",
allComponentsInGroup = _.map(
_.range(NUM_COMPONENTS_PER_GROUP),
......@@ -306,11 +311,6 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
}
);
getDeleteOffset = function () {
// Paginated containers will make an additional AJAX request.
return pagedSpecificTests ? 3 : 2;
};
getGroupElement = function () {
return containerPage.$("[data-locator='locator-group-" + GROUP_TO_TEST + "']");
};
......@@ -337,28 +337,35 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
EditHelpers.confirmPrompt(promptSpy, clickNo);
};
deleteComponent = function (componentIndex, requestOffset) {
deleteComponent = function (componentIndex) {
clickDelete(componentIndex);
AjaxHelpers.respondWithJson(requests, {});
// first request to delete the component
AjaxHelpers.expectJsonRequest(requests, 'DELETE',
'/xblock/locator-component-' + GROUP_TO_TEST + (componentIndex + 1),
null, requests.length - requestOffset);
null);
AjaxHelpers.respondWithNoContent(requests);
// then handle the request to refresh the preview
if (globalPageOptions.requiresPageRefresh) {
handleContainerPageRefresh(requests);
}
// final request to refresh the xblock info
AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/locator-container');
AjaxHelpers.respondWithJson(requests, {});
};
deleteComponentWithSuccess = function (componentIndex) {
var deleteOffset;
deleteComponent(componentIndex);
deleteOffset = getDeleteOffset();
deleteComponent(componentIndex, deleteOffset);
// verify the new list of components within the group
// verify the new list of components within the group (unless reloading)
if (!globalPageOptions.requiresPageRefresh) {
expectComponents(
getGroupElement(),
_.without(allComponentsInGroup, allComponentsInGroup[componentIndex])
);
}
};
it("can delete the first xblock", function () {
......@@ -377,24 +384,25 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
});
it("can delete an xblock with broken JavaScript", function () {
var deleteOffset = getDeleteOffset();
renderContainerPage(this, mockBadContainerXBlockHtml);
containerPage.$('.delete-button').first().click();
EditHelpers.confirmPrompt(promptSpy);
AjaxHelpers.respondWithJson(requests, {});
// expect the second to last request to be a delete of the xblock
AjaxHelpers.expectJsonRequest(requests, 'DELETE', '/xblock/locator-broken-javascript',
null, requests.length - deleteOffset);
AjaxHelpers.expectJsonRequest(requests, 'DELETE', '/xblock/locator-broken-javascript');
AjaxHelpers.respondWithNoContent(requests);
// handle the refresh request for pages that require a full refresh on delete
if (globalPageOptions.requiresPageRefresh) {
handleContainerPageRefresh(requests);
}
// expect the last request to be a fetch of the xblock info for the parent container
AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/locator-container');
});
it('does not delete when clicking No in prompt', function () {
var numRequests;
renderContainerPage(this, mockContainerXBlockHtml);
numRequests = requests.length;
// click delete on the first component but press no
clickDelete(0, true);
......@@ -403,7 +411,7 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
expectComponents(getGroupElement(), allComponentsInGroup);
// no requests should have been sent to the server
expect(requests.length).toBe(numRequests);
AjaxHelpers.expectNoRequests(requests);
});
it('shows a notification during the delete operation', function () {
......@@ -526,13 +534,13 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
expect(getButtonText(containerPage)).toBe("");
});
function updatePreviewButtonTest(show_previews, expected_text) {
var updatePreviewButtonTest = function(show_previews, expected_text) {
it('can set preview button to "' + expected_text + '"', function () {
containerPage = getContainerPage();
containerPage.updatePreviewButton(show_previews);
expect(getButtonText(containerPage)).toBe(expected_text);
});
}
};
updatePreviewButtonTest(true, 'Hide Previews');
updatePreviewButtonTest(false, 'Show Previews');
......@@ -603,13 +611,11 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
});
it('does not insert component upon failure', function () {
var requestCount;
renderContainerPage(this, mockContainerXBlockHtml);
clickNewComponent(0);
requestCount = requests.length;
AjaxHelpers.respondWithError(requests);
// No new requests should be made to refresh the view
expect(requests.length).toBe(requestCount);
AjaxHelpers.expectNoRequests(requests);
expectComponents(getGroupElement(), allComponentsInGroup);
});
......@@ -649,31 +655,31 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
});
});
});
});
}
// Create a suite for a non-paged container that includes 'edit visibility' buttons
parameterized_suite("Non paged",
{ },
{
page: ContainerPage,
requiresPageRefresh: false,
initial: 'mock/mock-container-xblock.underscore',
add_response: 'mock/mock-xblock.underscore',
has_visibility_editor: true,
paged_specific_tests: false
addResponse: 'mock/mock-xblock.underscore',
hasVisibilityEditor: true,
pagedSpecificTests: false
}
);
// Create a suite for a paged container that does not include 'edit visibility' buttons
parameterized_suite("Paged",
{ page_size: 42 },
{
page: PagedContainerPage,
page_size: 42,
requiresPageRefresh: true,
initial: 'mock/mock-container-paged-xblock.underscore',
add_response: 'mock/mock-xblock-paged.underscore',
has_visibility_editor: false,
paged_specific_tests: true
addResponse: 'mock/mock-xblock-paged.underscore',
hasVisibilityEditor: false,
pagedSpecificTests: true
}
);
});
......@@ -8,7 +8,7 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
describe("Container Subviews", function() {
var model, containerPage, requests, createContainerPage, renderContainerPage,
respondWithHtml, respondWithJson, fetch,
respondWithHtml, fetch,
disabledCss = "is-disabled", defaultXBlockInfo, createXBlockInfo,
mockContainerPage = readFixtures('mock/mock-container-page.underscore'),
mockContainerXBlockHtml = readFixtures('mock/mock-empty-container-xblock.underscore');
......@@ -52,30 +52,23 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
renderContainerPage = function (test, html, options) {
createContainerPage(test, options);
containerPage.render();
respondWithHtml(html);
respondWithHtml(html, options);
};
respondWithHtml = function(html) {
var requestIndex = requests.length - 1;
respondWithHtml = function(html, options) {
AjaxHelpers.respondWithJson(
requests,
{ html: html, "resources": [] },
requestIndex
);
};
respondWithJson = function(json, requestIndex) {
AjaxHelpers.respondWithJson(
requests,
json,
requestIndex
{ html: html, "resources": [] }
);
AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/locator-container');
AjaxHelpers.respondWithJson(requests, createXBlockInfo(options));
};
fetch = function (json) {
json = createXBlockInfo(json);
model.fetch();
respondWithJson(json);
AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/locator-container');
AjaxHelpers.respondWithJson(requests, json);
};
describe("ViewLiveButtonController", function () {
......@@ -236,14 +229,17 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
);
// Response to publish call
respondWithJson({"id": "locator-container", "data": null, "metadata":{}});
AjaxHelpers.respondWithJson(requests, {"id": "locator-container", "data": null, "metadata":{}});
EditHelpers.verifyNotificationHidden(notificationSpy);
AjaxHelpers.expectJsonRequest(requests, "GET", "/xblock/locator-container");
// Response to fetch
respondWithJson(createXBlockInfo({
AjaxHelpers.respondWithJson(
requests,
createXBlockInfo({
published: true, has_changes: false, visibility_state: VisibilityState.ready
}));
})
);
// Verify updates displayed
expect(containerPage.$(bitPublishingCss)).toHaveClass(readyClass);
......@@ -258,11 +254,9 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
// Click publish
containerPage.$(publishButtonCss).click();
var numRequests = requests.length;
// Respond with failure
AjaxHelpers.respondWithError(requests);
expect(requests.length).toEqual(numRequests);
AjaxHelpers.expectNoRequests(requests);
// Verify still in draft (unscheduled) state.
verifyPublishingBitUnscheduled();
......@@ -280,7 +274,7 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
numRequests = requests.length;
// Respond with success.
respondWithJson({"id": "locator-container"});
AjaxHelpers.respondWithJson(requests, {"id": "locator-container"});
EditHelpers.verifyNotificationHidden(notificationSpy);
// Verify other requests are sent to the server to update page state.
......@@ -296,12 +290,10 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
renderPageSpy = spyOn(containerPage.xblockPublisher, 'renderPage').andCallThrough();
sendDiscardChangesToServer();
numRequests = requests.length;
// Respond with failure
AjaxHelpers.respondWithError(requests);
expect(requests.length).toEqual(numRequests);
AjaxHelpers.expectNoRequests(requests);
expect(containerPage.$(discardChangesButtonCss)).not.toHaveClass('is-disabled');
expect(containerPage.model.get("publish")).toBeNull();
expect(renderPageSpy).not.toHaveBeenCalled();
......@@ -310,7 +302,6 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
it('does not discard changes on cancel', function () {
renderContainerPage(this, mockContainerXBlockHtml);
fetch({published: true, has_changes: true, visibility_state: VisibilityState.needsAttention});
var numRequests = requests.length;
// Click discard changes
expect(containerPage.$(discardChangesButtonCss)).not.toHaveClass('is-disabled');
......@@ -319,8 +310,7 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
// Click cancel to confirmation.
expect(promptSpies.constructor).toHaveBeenCalled();
promptSpies.constructor.mostRecentCall.args[0].actions.secondary.click(promptSpies);
expect(requests.length).toEqual(numRequests);
AjaxHelpers.expectNoRequests(requests);
expect(containerPage.$(discardChangesButtonCss)).not.toHaveClass('is-disabled');
});
......@@ -534,28 +524,24 @@ define(["jquery", "underscore", "underscore.string", "common/js/spec_helpers/aja
});
it("does not refresh if removing staff only is canceled", function() {
var requestCount;
promptSpy = EditHelpers.createPromptSpy();
renderContainerPage(this, mockContainerXBlockHtml, {
visibility_state: VisibilityState.staffOnly,
has_explicit_staff_lock: true,
ancestor_has_staff_lock: false
});
requestCount = requests.length;
containerPage.$('.action-staff-lock').click();
EditHelpers.confirmPrompt(promptSpy, true); // Click 'No' to cancel
expect(requests.length).toBe(requestCount);
AjaxHelpers.expectNoRequests(requests);
verifyExplicitStaffOnly(true);
verifyStaffOnly(true);
});
it("does not refresh when failing to set staff only", function() {
var requestCount;
renderContainerPage(this, mockContainerXBlockHtml);
containerPage.$('.lock-checkbox').click();
requestCount = requests.length;
containerPage.$('.action-staff-lock').click();
AjaxHelpers.respondWithError(requests);
expect(requests.length).toBe(requestCount);
AjaxHelpers.expectNoRequests(requests);
verifyStaffOnly(false);
});
});
......
......@@ -401,9 +401,8 @@ define(["jquery", "common/js/spec_helpers/ajax_helpers", "common/js/components/u
'display_name': 'Section',
'parent_locator': 'mock-course'
});
requestCount = requests.length;
AjaxHelpers.respondWithError(requests);
expect(requests.length).toBe(requestCount); // No additional requests should be made
AjaxHelpers.expectNoRequests(requests);
expect(outlinePage.$('.no-content')).not.toHaveClass('is-hidden');
expect(outlinePage.$('.no-content .button-new')).toExist();
});
......@@ -424,10 +423,9 @@ define(["jquery", "common/js/spec_helpers/ajax_helpers", "common/js/components/u
]));
getItemHeaders('section').find('.delete-button').first().click();
EditHelpers.confirmPrompt(promptSpy);
requestCount = requests.length;
AjaxHelpers.expectJsonRequest(requests, 'DELETE', '/xblock/mock-section');
AjaxHelpers.respondWithJson(requests, {});
expect(requests.length).toBe(requestCount); // No fetch should be performed
AjaxHelpers.expectNoRequests(requests); // No fetch should be performed
expect(outlinePage.$('[data-locator="mock-section"]')).not.toExist();
expect(outlinePage.$('[data-locator="mock-section-2"]')).toExist();
});
......@@ -452,9 +450,8 @@ define(["jquery", "common/js/spec_helpers/ajax_helpers", "common/js/components/u
getItemHeaders('section').find('.delete-button').click();
EditHelpers.confirmPrompt(promptSpy);
AjaxHelpers.expectJsonRequest(requests, 'DELETE', '/xblock/mock-section');
requestCount = requests.length;
AjaxHelpers.respondWithError(requests);
expect(requests.length).toBe(requestCount); // No additional requests should be made
AjaxHelpers.expectNoRequests(requests);
expect(outlinePage.$('.list-sections li.outline-section').data('locator')).toEqual('mock-section');
});
......@@ -534,10 +531,8 @@ define(["jquery", "common/js/spec_helpers/ajax_helpers", "common/js/components/u
])
]);
AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section');
expect(requests.length).toBe(2);
// This is the response for the subsequent fetch operation for the section.
AjaxHelpers.respondWithJson(requests, mockResponseSectionJSON);
AjaxHelpers.expectNoRequests(requests);
expect($(".outline-section .status-release-value")).toContainText("Jan 02, 2015 at 00:00 UTC");
});
......@@ -713,13 +708,11 @@ define(["jquery", "common/js/spec_helpers/ajax_helpers", "common/js/components/u
}
});
expect(requests[0].requestHeaders['X-HTTP-Method-Override']).toBe('PATCH');
// This is the response for the change operation.
AjaxHelpers.respondWithJson(requests, {});
AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section');
expect(requests.length).toBe(2);
// This is the response for the subsequent fetch operation for the section.
AjaxHelpers.respondWithJson(requests, mockServerValuesJson);
AjaxHelpers.expectNoRequests(requests);
expect($(".outline-subsection .status-release-value")).toContainText(
"Jul 09, 2014 at 00:00 UTC"
......
......@@ -193,7 +193,7 @@ define(["jquery", "common/js/spec_helpers/ajax_helpers", "common/js/spec_helpers
var requests = AjaxHelpers.requests(this);
fillInFields('DemoX', 'DM101', '', 'Demo course');
$(selectors.save).click();
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
});
it("can be canceled", function () {
......
......@@ -88,7 +88,6 @@ define(["jquery", "common/js/spec_helpers/ajax_helpers", "common/js/spec_helpers
it("displays an error when a required field is blank", function () {
var requests = AjaxHelpers.requests(this);
var requests_count = requests.length;
$('.new-library-button').click();
var values = ['DemoX', 'DM101', 'Demo library'];
// Try making each of these three values empty one at a time and ensure the form won't submit:
......@@ -100,7 +99,7 @@ define(["jquery", "common/js/spec_helpers/ajax_helpers", "common/js/spec_helpers
expect($('.new-library-save')).toHaveClass('is-disabled');
expect($('.new-library-save')).toHaveAttr('aria-disabled', 'true');
$('.new-library-save').click();
expect(requests.length).toEqual(requests_count); // Expect no new requests
AjaxHelpers.expectNoRequests(requests);
}
});
......
......@@ -84,7 +84,7 @@ function ($, AjaxHelpers, ViewHelpers, ManageUsersFactory, ViewUtils) {
$('.form-create.create-user .action-primary').click();
expect($(errorPromptSelector).length).toEqual(1);
expect($(errorPromptSelector)).toContainText('You must enter a valid email address');
expect(requests.length).toEqual(0);
AjaxHelpers.expectNoRequests(requests);
});
it("displays an error when the user has already been added", function () {
......@@ -94,7 +94,7 @@ function ($, AjaxHelpers, ViewHelpers, ManageUsersFactory, ViewUtils) {
$('.user-email-input').val('honor@example.com');
$('.form-create.create-user .action-primary').click();
ViewHelpers.verifyPromptShowing(promptSpy, 'Already a library team member');
expect(requests.length).toEqual(0);
AjaxHelpers.expectNoRequests(requests);
});
......
......@@ -51,13 +51,12 @@ define([
};
var respondWithMockItems = function(requests) {
var requestIndex = requests.length - 1;
var request = requests[requestIndex];
var request = AjaxHelpers.currentRequest(requests);
var url = new URI(request.url);
var queryParameters = url.query(true); // Returns an object with each query parameter stored as a value
var page = queryParameters.page;
var response = page === "0" ? mockFirstPage : mockSecondPage;
AjaxHelpers.respondWithJson(requests, response, requestIndex);
AjaxHelpers.respondWithJson(requests, response);
};
var MockPagingView = PagingView.extend({
......@@ -124,7 +123,7 @@ define([
pagingView.setPage(2);
respondWithMockItems(requests);
pagingView.nextPage();
expect(requests.length).toBe(1);
AjaxHelpers.expectNoRequests(requests);
});
});
......@@ -144,7 +143,7 @@ define([
pagingView.setPage(1);
respondWithMockItems(requests);
pagingView.previousPage();
expect(requests.length).toBe(1);
AjaxHelpers.expectNoRequests(requests);
});
it('does not move back after a server error', function () {
......
......@@ -86,7 +86,7 @@ define([ "jquery", "underscore", "common/js/spec_helpers/ajax_helpers", "js/spec
// Give the mock xblock a save method...
editor.xblock.save = window.MockDescriptor.save;
editor.model.save(editor.getXBlockFieldData());
request = requests[requests.length - 1];
request = AjaxHelpers.currentRequest(requests);
response = JSON.parse(request.requestBody);
expect(response.metadata.display_name).toBe(testDisplayName);
expect(response.metadata.custom_field).toBe('Custom Value');
......
......@@ -3,7 +3,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/xbloc
function ($, AjaxHelpers, URI, XBlockView, XBlockInfo) {
describe("XBlockView", function() {
var model, xblockView, mockXBlockHtml, respondWithMockXBlockFragment;
var model, xblockView, mockXBlockHtml;
beforeEach(function () {
model = new XBlockInfo({
......@@ -18,15 +18,10 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/xbloc
mockXBlockHtml = readFixtures('mock/mock-xblock.underscore');
respondWithMockXBlockFragment = function(requests, response) {
var requestIndex = requests.length - 1;
AjaxHelpers.respondWithJson(requests, response, requestIndex);
};
it('can render a nested xblock', function() {
var requests = AjaxHelpers.requests(this);
xblockView.render();
respondWithMockXBlockFragment(requests, {
AjaxHelpers.respondWithJson(requests, {
html: mockXBlockHtml,
resources: []
});
......@@ -48,7 +43,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/xbloc
});
// Note: this mock response will call the AJAX success function synchronously
// so the promise variable defined above will be available.
respondWithMockXBlockFragment(requests, {
AjaxHelpers.respondWithJson(requests, {
html: mockXBlockHtml,
resources: resources
});
......
......@@ -52,7 +52,6 @@ define(["jquery", "common/js/spec_helpers/ajax_helpers", "common/js/spec_helpers
expectEditCanceled = function (test, fieldEditorView, options) {
var requests, initialRequests, displayNameInput;
requests = AjaxHelpers.requests(test);
initialRequests = requests.length;
displayNameInput = EditHelpers.inlineEdit(fieldEditorView.$el, options.newTitle);
if (options.pressEscape) {
displayNameInput.simulate("keydown", { keyCode: $.simulate.keyCode.ESCAPE });
......@@ -63,7 +62,7 @@ define(["jquery", "common/js/spec_helpers/ajax_helpers", "common/js/spec_helpers
displayNameInput.change();
}
// No requests should be made when the edit is cancelled client-side
expect(initialRequests).toBe(requests.length);
AjaxHelpers.expectNoRequests(requests);
EditHelpers.verifyInlineEditChange(fieldEditorView.$el, initialDisplayName);
expect(fieldEditorView.model.get('display_name')).toBe(initialDisplayName);
};
......@@ -85,14 +84,13 @@ define(["jquery", "common/js/spec_helpers/ajax_helpers", "common/js/spec_helpers
it('does not change the title when a display name update fails', function () {
var requests, fieldEditorView, initialRequests;
requests = AjaxHelpers.requests(this);
initialRequests = requests.length;
fieldEditorView = getFieldEditorView().render();
EditHelpers.inlineEdit(fieldEditorView.$el, updatedDisplayName);
fieldEditorView.$('button[name=submit]').click();
expectPostedNewDisplayName(requests, updatedDisplayName);
AjaxHelpers.respondWithError(requests);
// No fetch operation should occur.
expect(initialRequests + 1).toBe(requests.length);
AjaxHelpers.expectNoRequests(requests);
EditHelpers.verifyInlineEditChange(fieldEditorView.$el, initialDisplayName, updatedDisplayName);
});
......
......@@ -98,7 +98,7 @@ define(["jquery", "underscore", "common/js/spec_helpers/ajax_helpers", "common/j
};
verifyXBlockRequest = function (requests, expectedJson) {
var request = requests[requests.length - 1],
var request = AjaxHelpers.currentRequest(requests),
actualJson = JSON.parse(request.requestBody);
expect(request.url).toEqual("/xblock/");
expect(request.method).toEqual("POST");
......
......@@ -109,9 +109,8 @@ define([
expectHeader('Showing 1-5 out of 6 total');
expectItems(initialItems);
expectFooter({currentPage: 1, totalPages: 2, isHidden: false});
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
testView.$(nextPageButtonCss).click();
expect(requests.length).toBe(1);
AjaxHelpers.respondWithJson(requests, {
"count": 6,
"num_pages": 2,
......
......@@ -15,7 +15,8 @@ define(['jquery',
isZeroIndexed: false,
count: 43,
respond: function (requests) {
var params = (new URI(requests[requests.length - 1].url)).query(true),
var request = AjaxHelpers.currentRequest(requests),
params = (new URI(request.url)).query(true),
page = parseInt(params['page'], 10),
page_size = parseInt(params['page_size'], 10),
page_count = Math.ceil(this.count / page_size);
......@@ -23,7 +24,7 @@ define(['jquery',
// Make zeroPage consistently start at zero for ease of calculation
var zeroPage = page - (this.isZeroIndexed ? 0 : 1);
if (zeroPage < 0 || zeroPage > page_count) {
AjaxHelpers.respondWithError(requests, 404, {}, requests.length - 1);
AjaxHelpers.respondWithError(requests, 404);
} else {
AjaxHelpers.respondWithJson(requests, {
'count': this.count,
......@@ -31,12 +32,13 @@ define(['jquery',
'num_pages': page_count,
'start': zeroPage * page_size,
'results': []
}, requests.length - 1);
});
}
}
};
var assertQueryParams = function (requests, params) {
var urlParams = (new URI(requests[requests.length - 1].url)).query(true);
var request = AjaxHelpers.currentRequest(requests),
urlParams = (new URI(request.url)).query(true);
_.each(params, function (value, key) {
expect(urlParams[key]).toBe(value);
});
......@@ -153,7 +155,7 @@ define(['jquery',
expect(collection.getPage()).toBe(2);
server.respond(requests);
collection.setPage(3);
AjaxHelpers.respondWithError(requests, 500, {}, requests.length - 1);
AjaxHelpers.respondWithError(requests, 500);
expect(errorTriggered).toBe(true);
expect(collection.getPage()).toBe(2);
});
......
define(['sinon', 'underscore', 'URI'], function(sinon, _, URI) {
'use strict';
var fakeServer, fakeRequests, expectRequest, expectJsonRequest, expectPostRequest, expectRequestURL,
var XML_HTTP_READY_STATES, fakeServer, fakeRequests, currentRequest, expectRequest, expectNoRequests,
expectJsonRequest, expectPostRequest, expectRequestURL, skipResetRequest,
respondWithJson, respondWithError, respondWithTextError, respondWithNoContent;
XML_HTTP_READY_STATES = {
UNSENT: 0,
OPENED: 1,
LOADING: 3,
DONE: 4
};
/* These utility methods are used by Jasmine tests to create a mock server or
* get reference to mock requests. In either case, the cleanup (restore) is done with
* an after function.
......@@ -37,6 +45,7 @@ define(['sinon', 'underscore', 'URI'], function(sinon, _, URI) {
fakeRequests = function (that) {
var requests = [],
xhr = sinon.useFakeXMLHttpRequest();
requests.currentIndex = 0;
xhr.onCreate = function(request) {
requests.push(request);
};
......@@ -44,27 +53,38 @@ define(['sinon', 'underscore', 'URI'], function(sinon, _, URI) {
that.after(function() {
xhr.restore();
});
return requests;
};
expectRequest = function(requests, method, url, body, requestIndex) {
var request;
if (_.isUndefined(requestIndex)) {
requestIndex = requests.length - 1;
}
request = requests[requestIndex];
/**
* Returns the request that has not yet been responded to. If no such request
* is available then the current test will fail.
* @param requests The Sinon requests list.
* @returns {*} The current request.
*/
currentRequest = function(requests) {
expect(requests.length).toBeGreaterThan(requests.currentIndex);
return requests[requests.currentIndex];
};
expectRequest = function(requests, method, url, body) {
var request = currentRequest(requests);
expect(request.readyState).toEqual(XML_HTTP_READY_STATES.OPENED);
expect(request.url).toEqual(url);
expect(request.method).toEqual(method);
expect(request.requestBody).toEqual(body);
};
expectJsonRequest = function(requests, method, url, jsonRequest, requestIndex) {
var request;
if (_.isUndefined(requestIndex)) {
requestIndex = requests.length - 1;
}
request = requests[requestIndex];
/**
* Verifies the there are no unconsumed requests.
*/
expectNoRequests = function(requests) {
expect(requests.length).toEqual(requests.currentIndex);
};
expectJsonRequest = function(requests, method, url, jsonRequest) {
var request = currentRequest(requests);
expect(request.readyState).toEqual(XML_HTTP_READY_STATES.OPENED);
expect(request.url).toEqual(url);
expect(request.method).toEqual(method);
expect(JSON.parse(request.requestBody)).toEqual(jsonRequest);
......@@ -75,14 +95,10 @@ define(['sinon', 'underscore', 'URI'], function(sinon, _, URI) {
* @param requests The collected requests
* @param expectedUrl The expected URL excluding the parameters
* @param expectedParameters An object representing the URL parameters
* @param requestIndex An optional index for the request (by default, the last request is used)
*/
expectRequestURL = function(requests, expectedUrl, expectedParameters, requestIndex) {
var request, parameters;
if (_.isUndefined(requestIndex)) {
requestIndex = requests.length - 1;
}
request = requests[requestIndex];
expectRequestURL = function(requests, expectedUrl, expectedParameters) {
var request = currentRequest(requests),
parameters;
expect(new URI(request.url).path()).toEqual(expectedUrl);
parameters = new URI(request.url).query(true);
delete parameters._; // Ignore the cache-busting argument
......@@ -92,73 +108,82 @@ define(['sinon', 'underscore', 'URI'], function(sinon, _, URI) {
/**
* Intended for use with POST requests using application/x-www-form-urlencoded.
*/
expectPostRequest = function(requests, url, body, requestIndex) {
var request;
if (_.isUndefined(requestIndex)) {
requestIndex = requests.length - 1;
}
request = requests[requestIndex];
expectPostRequest = function(requests, url, body) {
var request = currentRequest(requests);
expect(request.readyState).toEqual(XML_HTTP_READY_STATES.OPENED);
expect(request.url).toEqual(url);
expect(request.method).toEqual("POST");
expect(_.difference(request.requestBody.split('&'), body.split('&'))).toEqual([]);
};
respondWithJson = function(requests, jsonResponse, requestIndex) {
if (_.isUndefined(requestIndex)) {
requestIndex = requests.length - 1;
}
requests[requestIndex].respond(200,
/**
* Verify that the request was reset, and then skip it.
*/
skipResetRequest = function(requests) {
var request = currentRequest(requests);
expect(request.readyState).toEqual(XML_HTTP_READY_STATES.UNSENT);
requests.currentIndex++;
};
respondWithJson = function(requests, jsonResponse) {
var request = currentRequest(requests);
request.respond(200,
{ 'Content-Type': 'application/json' },
JSON.stringify(jsonResponse));
requests.currentIndex++;
};
respondWithError = function(requests, statusCode, jsonResponse, requestIndex) {
if (_.isUndefined(requestIndex)) {
requestIndex = requests.length - 1;
}
respondWithError = function(requests, statusCode, jsonResponse) {
var request = currentRequest(requests);
if (_.isUndefined(statusCode)) {
statusCode = 500;
}
if (_.isUndefined(jsonResponse)) {
jsonResponse = {};
}
requests[requestIndex].respond(statusCode,
request.respond(
statusCode,
{ 'Content-Type': 'application/json' },
JSON.stringify(jsonResponse)
);
requests.currentIndex++;
};
respondWithTextError = function(requests, statusCode, textResponse, requestIndex) {
if (_.isUndefined(requestIndex)) {
requestIndex = requests.length - 1;
}
respondWithTextError = function(requests, statusCode, textResponse) {
var request = currentRequest(requests);
if (_.isUndefined(statusCode)) {
statusCode = 500;
}
if (_.isUndefined(textResponse)) {
textResponse = "";
}
requests[requestIndex].respond(statusCode,
request.respond(
statusCode,
{ 'Content-Type': 'text/plain' },
textResponse
);
requests.currentIndex++;
};
respondWithNoContent = function(requests, requestIndex) {
if (_.isUndefined(requestIndex)) {
requestIndex = requests.length - 1;
}
requests[requestIndex].respond(204,
{ 'Content-Type': 'application/json' });
respondWithNoContent = function(requests) {
var request = currentRequest(requests);
request.respond(
204,
{ 'Content-Type': 'application/json' }
);
requests.currentIndex++;
};
return {
server: fakeServer,
requests: fakeRequests,
currentRequest: currentRequest,
expectRequest: expectRequest,
expectNoRequests: expectNoRequests,
expectJsonRequest: expectJsonRequest,
expectPostRequest: expectPostRequest,
expectRequestURL: expectRequestURL,
skipResetRequest: skipResetRequest,
respondWithJson: respondWithJson,
respondWithError: respondWithError,
respondWithTextError: respondWithTextError,
......
......@@ -10,11 +10,12 @@ define(['backbone', 'URI', 'underscore', 'common/js/spec_helpers/ajax_helpers',
var testRequestParam = function (self, param, value) {
var requests = AjaxHelpers.requests(self),
request,
url,
params;
topicCollection.fetch();
expect(requests.length).toBe(1);
url = new URI(requests[0].url);
request = AjaxHelpers.currentRequest(requests);
url = new URI(request.url);
params = url.query(true);
expect(params[param]).toBe(value);
};
......
......@@ -138,7 +138,7 @@ define([
verifyTeamMembersView(view);
deleteTeamMemember(view, false);
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
expect(view.teamEvents.trigger).not.toHaveBeenCalled();
verifyTeamMembersView(view);
});
......
......@@ -55,7 +55,8 @@ define([
}
});
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
},
editTeamID = 'av',
teamAction;
......
......@@ -72,7 +72,7 @@ define([
it('can cancel team deletion', function () {
var requests = AjaxHelpers.requests(this);
deleteTeam(view, false);
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
expect(Backbone.history.navigate).not.toHaveBeenCalled();
});
......
......@@ -168,7 +168,7 @@ define([
expect(view.$('.join-team-message').text().trim()).toBe(view.teamFullMessage);
// there should be no request made
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
});
it('shows correct error message if user fails to join team', function () {
......
......@@ -85,10 +85,9 @@ define([
AjaxHelpers.expectJsonRequest(requests, 'GET', '/api/team/v0/teams/test-team');
AjaxHelpers.respondWithJson(requests, createTeamModelData({country: 'US', language: 'en'}));
} else {
var requestCount = requests.length;
// click on Cancel button on dialog
$('.prompt.warning .action-secondary').click();
expect(requests.length).toBe(requestCount);
AjaxHelpers.expectNoRequests(requests);
}
};
......
......@@ -174,7 +174,7 @@ define([
userInfo: TeamSpecHelpers.createMockUserInfo({staff: true})
});
teamsTabView.router.navigate(url, {trigger: true});
if (requests.length) {
if (AjaxHelpers.currentRequest(requests)) {
AjaxHelpers.respondWithJson(requests, {});
}
expect(Logger.log).toHaveBeenCalledWith('edx.team.page_viewed', expectedEvent);
......@@ -229,24 +229,22 @@ define([
text_search: 'foo'
});
AjaxHelpers.respondWithJson(requests, TeamSpecHelpers.createMockTeamsResponse({results: []}));
// Expect exactly one search request to be fired
AjaxHelpers.expectNoRequests(requests);
};
it('can search teams', function () {
var teamsTabView = createTeamsTabView(this),
requestCountBeforeSearch;
var teamsTabView = createTeamsTabView(this);
teamsTabView.browseTopic(TeamSpecHelpers.testTopicID);
verifyTeamsRequest({
order_by: 'last_activity_at',
text_search: ''
});
AjaxHelpers.respondWithJson(requests, {});
requestCountBeforeSearch = requests.length;
performSearch(requests, teamsTabView);
expect(teamsTabView.$('.page-title').text()).toBe('Team Search');
expect(teamsTabView.$('.page-description').text()).toBe('Showing results for "foo"');
// Expect exactly one search request to be fired
expect(requests.length).toBe(requestCountBeforeSearch + 1);
});
it('can clear a search', function () {
......
......@@ -130,6 +130,9 @@ define([
window.scroll(0, $(document).height());
$(window).trigger('scroll');
jasmine.Clock.tick(500);
// TODO: determine why the search API is invoked twice
AjaxHelpers.respondWithJson(requests, JSON_RESPONSE);
AjaxHelpers.respondWithJson(requests, JSON_RESPONSE);
expect($('.courses-listing article').length).toEqual(2);
});
......
......@@ -70,6 +70,16 @@ define([
expect(this.toggleMessage).toContainText('Notes visible');
expect(Annotator._instances).toHaveLength(2);
// TODO: why is the same search request made twice?
AjaxHelpers.expectJsonRequest(requests, 'GET',
'/test_endpoint/search/?user=a+user&usage_id=an+usage&course_id=a+course'
);
AjaxHelpers.respondWithJson(requests, {});
AjaxHelpers.expectJsonRequest(requests, 'GET',
'/test_endpoint/search/?user=a+user&usage_id=an+usage&course_id=a+course'
);
AjaxHelpers.respondWithJson(requests, {});
AjaxHelpers.expectJsonRequest(requests, 'PUT', '/test_url', {
'visibility': true
});
......@@ -90,6 +100,17 @@ define([
expect(errorContainer).toHaveClass('annotator-notice-error');
this.button.click();
// TODO: why is the same search request made twice?
AjaxHelpers.expectJsonRequest(requests, 'GET',
'/test_endpoint/search/?user=a+user&usage_id=an+usage&course_id=a+course'
);
AjaxHelpers.respondWithJson(requests, {});
AjaxHelpers.expectJsonRequest(requests, 'GET',
'/test_endpoint/search/?user=a+user&usage_id=an+usage&course_id=a+course'
);
AjaxHelpers.respondWithJson(requests, {});
AjaxHelpers.respondWithJson(requests, {});
expect(errorContainer).not.toHaveClass('annotator-notice-show');
});
......
......@@ -32,7 +32,7 @@ define([
total: 3,
rows: notes
},
getView, submitForm;
getView, submitForm, respondToSearch;
getView = function (tabsCollection, options) {
options = _.defaults(options || {}, {
......@@ -50,6 +50,14 @@ define([
searchBox.$('.search-notes-submit').click();
};
respondToSearch = function(requests, responseJson) {
// First respond to the analytics event
AjaxHelpers.respondWithNoContent(requests);
// Now process the search request
AjaxHelpers.respondWithJson(requests, responseJson);
};
beforeEach(function () {
customMatchers(this);
loadFixtures('js/fixtures/edxnotes/edxnotes.html');
......@@ -71,7 +79,7 @@ define([
requests = AjaxHelpers.requests(this);
submitForm(view.searchBox, 'second');
AjaxHelpers.respondWithJson(requests, responseJson);
respondToSearch(requests, responseJson);
expect(this.tabsCollection).toHaveLength(1);
expect(this.tabsCollection.at(0).toJSON()).toEqual({
......@@ -100,7 +108,7 @@ define([
expect(this.tabsCollection).toHaveLength(1);
expect(view.searchResults).toBeNull();
expect(view.$('.tab-panel')).not.toExist();
AjaxHelpers.respondWithJson(requests, responseJson);
respondToSearch(requests, responseJson);
expect(view.$('.ui-loading')).toHaveClass('is-hidden');
});
......@@ -109,7 +117,7 @@ define([
requests = AjaxHelpers.requests(this);
submitForm(view.searchBox, 'some text');
AjaxHelpers.respondWithJson(requests, {
respondToSearch(requests, {
total: 0,
rows: []
});
......@@ -147,7 +155,7 @@ define([
requests = AjaxHelpers.requests(this);
submitForm(view.searchBox, 'test_query');
AjaxHelpers.respondWithJson(requests, responseJson);
respondToSearch(requests, responseJson);
expect(view.searchResults).toBeDefined();
this.tabsCollection.at(0).destroy();
expect(view.searchResults).toBeNull();
......@@ -158,6 +166,11 @@ define([
requests = AjaxHelpers.requests(this);
submitForm(view.searchBox, 'test error');
// First respond to the analytics event
AjaxHelpers.respondWithNoContent(requests);
// Now respond to the search with a 500 error
AjaxHelpers.respondWithError(requests, 500, {error: 'test error message'});
expect(view.$('.wrapper-msg')).not.toHaveClass('is-hidden');
......@@ -182,12 +195,12 @@ define([
}];
submitForm(view.searchBox, 'test_query');
AjaxHelpers.respondWithJson(requests, responseJson);
respondToSearch(requests, responseJson);
expect(view.$('.note')).toHaveLength(3);
submitForm(view.searchBox, 'new_test_query');
AjaxHelpers.respondWithJson(requests, {
respondToSearch(requests, {
total: 1,
rows: newNotes
});
......
......@@ -247,8 +247,7 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/
};
saveFormAndExpectErrors = function(action, errors) {
var requestCount = requests.length,
form, expectedTitle;
var form, expectedTitle;
if (action === 'add') {
expectedTitle = 'The cohort cannot be added';
form = getAddModal();
......@@ -257,7 +256,7 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/
form = cohortsView.$('.cohort-management-settings-form');
}
form.find('.action-save').click();
expect(requests.length).toBe(requestCount);
AjaxHelpers.expectNoRequests(requests);
verifyDetailedMessage(expectedTitle, 'error', errors);
};
......@@ -360,6 +359,9 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/
cohortsView.$(fileUploadForm).fileupload('add', {files: [{name: 'upload_file.txt'}]});
cohortsView.$('.submit-file-button').click();
// Respond to the event request
AjaxHelpers.respondWithNoContent(requests);
// No file will actually be uploaded because "uploaded_file.txt" doesn't actually exist.
AjaxHelpers.expectRequest(requests, 'POST', MOCK_UPLOAD_COHORTS_CSV_URL, new FormData());
AjaxHelpers.respondWithJson(requests, {});
......@@ -706,7 +708,7 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/
it('shows an error when adding with no students specified', function() {
createCohortsView(this, {selectCohort: 1});
addStudents(' ');
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
verifyMessage('Enter a username or email.', 'error');
expect(getStudentInput().val()).toBe('');
});
......
......@@ -162,16 +162,18 @@ define([
this.collection.performSearch('old search');
this.collection.performSearch('new search');
AjaxHelpers.skipResetRequest(requests);
AjaxHelpers.respondWithJson(requests, response);
expect(this.onSearch.calls.length).toEqual(1);
this.collection.performSearch('old search');
this.collection.cancelSearch();
AjaxHelpers.respondWithJson(requests, response);
AjaxHelpers.skipResetRequest(requests);
expect(this.onSearch.calls.length).toEqual(1);
this.collection.loadNextPage();
this.collection.loadNextPage();
AjaxHelpers.skipResetRequest(requests);
AjaxHelpers.respondWithJson(requests, response);
expect(this.onNext.calls.length).toEqual(1);
});
......
......@@ -139,6 +139,7 @@ define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers
AjaxHelpers.respondWithJson(requests, Helpers.createAccountSettingsData());
AjaxHelpers.respondWithJson(requests, Helpers.createUserPreferencesData());
AjaxHelpers.respondWithJson(requests, {}); // Page viewed analytics event
var sectionsData = accountSettingsView.options.sectionsData;
......
......@@ -42,16 +42,13 @@ define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers
});
};
it("renders the full profile after data is successfully fetched", function() {
it("renders the full profile for a user", function() {
requests = AjaxHelpers.requests(this);
var context = createProfilePage(true),
learnerProfileView = context.learnerProfileView;
AjaxHelpers.respondWithJson(requests, Helpers.createAccountSettingsData());
AjaxHelpers.respondWithJson(requests, Helpers.createUserPreferencesData());
// sets the profile for full view.
context.accountPreferencesModel.set({account_privacy: 'all_users'});
LearnerProfileHelpers.expectProfileSectionsAndFieldsToBeRendered(learnerProfileView, false);
......
......@@ -110,6 +110,9 @@ define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers
// Verify image upload progress message
verifyImageUploadButtonMessage(imageView, true);
// Respond to the analytics event
AjaxHelpers.respondWithJson(requests, {});
// Verify if POST request received for image upload
AjaxHelpers.expectRequest(requests, 'POST', Helpers.IMAGE_UPLOAD_API_URL, new FormData());
......@@ -278,6 +281,9 @@ define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers
// Verify image upload progress message
verifyImageUploadButtonMessage(imageView, true);
// Respond to the analytics event
AjaxHelpers.respondWithJson(requests, {});
// Verify if POST request received for image upload
AjaxHelpers.expectRequest(requests, 'POST', Helpers.IMAGE_UPLOAD_API_URL, new FormData());
......
......@@ -83,7 +83,7 @@ define([
// TODO put fixture responses in the right place
AjaxHelpers.respondWithJson( requests, {payment_page_url: 'http://payment-page-url/', payment_form_data: {foo: 'bar'}} );
} else {
AjaxHelpers.respondWithTextError( requests, 400, SERVER_ERROR_MSG );
AjaxHelpers.respondWithTextError( requests, 400, SERVER_ERROR_MSG);
}
};
......@@ -102,7 +102,8 @@ define([
var $el = $( '.payment-button' );
expect($el.length).toEqual(_.size(buttons));
_.each(buttons, function( expectedText, expectedId ) {
var buttonEl = $( '#' + expectedId );
var buttonEl = $( '#' + expectedId),
request;
buttonEl.removeAttr('disabled');
expect( buttonEl.length ).toEqual( 1 );
......@@ -112,7 +113,9 @@ define([
buttonEl[0].click();
expect( buttonEl[0] ).toHaveClass( 'is-selected' );
expectPaymentButtonEnabled( false );
expect(requests[requests.length - 1].requestBody.split('&')).toContain('processor=' + expectedId);
request = AjaxHelpers.currentRequest(requests);
expect(request.requestBody.split('&')).toContain('processor=' + expectedId);
AjaxHelpers.respondWithJson(requests, {});
});
};
......
......@@ -154,7 +154,7 @@ define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers
view.$(valueInputSelector).val(fieldData.validValue).change();
expect(view.fieldValue()).toBe(fieldData.validValue);
expectMessageContains(view, view.helpMessage);
expect(requests.length).toBe(0);
AjaxHelpers.expectNoRequests(requests);
};
var verifyEditableField = function (view, data, requests) {
......
......@@ -54,6 +54,9 @@ define(['backbone', 'jquery', 'js/views/file_uploader', 'common/js/spec_helpers/
verifySubmitButtonEnabled(true);
fileUploaderView.$('.submit-file-button').click();
// Respond to the analytics event first
AjaxHelpers.respondWithJson(requests, {});
// No file will actually be uploaded because "uploaded_file.txt" doesn't actually exist.
AjaxHelpers.expectRequest(requests, 'POST', url, new FormData());
return requests;
......
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