From b2a0b2f728621013365c5ae1f3282f20e1ce0120 Mon Sep 17 00:00:00 2001 From: Andy Armstrong Date: Mon, 21 Sep 2015 17:21:44 -0400 Subject: [PATCH] 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. --- .../coffee/spec/views/assets_spec.coffee | 1 + .../js/spec/utils/drag_and_drop_spec.js | 17 ++- cms/static/js/spec/views/assets_spec.js | 5 +- cms/static/js/spec/views/container_spec.js | 9 +- .../js/spec/views/group_configuration_spec.js | 20 +-- .../js/spec/views/paged_container_spec.js | 9 +- .../js/spec/views/pages/container_spec.js | 144 +++++++++--------- .../views/pages/container_subviews_spec.js | 58 +++---- .../spec/views/pages/course_outline_spec.js | 19 +-- .../js/spec/views/pages/course_rerun_spec.js | 2 +- cms/static/js/spec/views/pages/index_spec.js | 3 +- .../js/spec/views/pages/library_users_spec.js | 4 +- cms/static/js/spec/views/paging_spec.js | 9 +- .../js/spec/views/xblock_editor_spec.js | 2 +- cms/static/js/spec/views/xblock_spec.js | 11 +- .../views/xblock_string_field_editor_spec.js | 6 +- cms/static/js/spec_helpers/edit_helpers.js | 2 +- .../js/spec/components/paginated_view_spec.js | 3 +- .../spec/components/paging_collection_spec.js | 12 +- .../common/js/spec_helpers/ajax_helpers.js | 125 +++++++++------ .../spec/collections/topic_collection_spec.js | 5 +- .../js/spec/views/edit_team_members_spec.js | 2 +- .../teams/js/spec/views/edit_team_spec.js | 3 +- .../js/spec/views/instructor_tools_spec.js | 2 +- .../views/team_profile_header_actions_spec.js | 2 +- .../teams/js/spec/views/team_profile_spec.js | 3 +- .../teams/js/spec/views/teams_tab_spec.js | 12 +- .../spec/discovery/discovery_factory_spec.js | 3 + .../views/notes_visibility_factory_spec.js | 21 +++ .../views/tabs/search_results_spec.js | 71 +++++---- .../js/spec/groups/views/cohorts_spec.js | 10 +- lms/static/js/spec/search/search_spec.js | 4 +- .../account_settings_factory_spec.js | 1 + .../learner_profile_factory_spec.js | 5 +- .../learner_profile_fields_spec.js | 6 + .../make_payment_step_view_spec.js | 9 +- lms/static/js/spec/views/fields_helpers.js | 2 +- .../js/spec/views/file_uploader_spec.js | 3 + 38 files changed, 336 insertions(+), 289 deletions(-) diff --git a/cms/static/coffee/spec/views/assets_spec.coffee b/cms/static/coffee/spec/views/assets_spec.coffee index 0c0a5f42c9..8a795b63b6 100644 --- a/cms/static/coffee/spec/views/assets_spec.coffee +++ b/cms/static/coffee/spec/views/assets_spec.coffee @@ -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() diff --git a/cms/static/js/spec/utils/drag_and_drop_spec.js b/cms/static/js/spec/utils/drag_and_drop_spec.js index a1db0401d7..e53a07e3f5 100644 --- a/cms/static/js/spec/utils/drag_and_drop_spec.js +++ b/cms/static/js/spec/utils/drag_and_drop_spec.js @@ -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 diff --git a/cms/static/js/spec/views/assets_spec.js b/cms/static/js/spec/views/assets_spec.js index 1d85367ffd..87c5006bc2 100644 --- a/cms/static/js/spec/views/assets_spec.js +++ b/cms/static/js/spec/views/assets_spec.js @@ -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 = {}; diff --git a/cms/static/js/spec/views/container_spec.js b/cms/static/js/spec/views/container_spec.js index 4cbb0f91d4..919e27a885 100644 --- a/cms/static/js/spec/views/container_spec.js +++ b/cms/static/js/spec/views/container_spec.js @@ -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": [] }); diff --git a/cms/static/js/spec/views/group_configuration_spec.js b/cms/static/js/spec/views/group_configuration_spec.js index 430c47e2f9..29488b551b 100644 --- a/cms/static/js/spec/views/group_configuration_spec.js +++ b/cms/static/js/spec/views/group_configuration_spec.js @@ -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); }); diff --git a/cms/static/js/spec/views/paged_container_spec.js b/cms/static/js/spec/views/paged_container_spec.js index 6a636555a4..fd55c3e2be 100644 --- a/cms/static/js/spec/views/paged_container_spec.js +++ b/cms/static/js/spec/views/paged_container_spec.js @@ -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 () { diff --git a/cms/static/js/spec/views/pages/container_spec.js b/cms/static/js/spec/views/pages/container_spec.js index c9eb7c270d..fe78638a57 100644 --- a/cms/static/js/spec/views/pages/container_spec.js +++ b/cms/static/js/spec/views/pages/container_spec.js @@ -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); + '/xblock/locator-component-' + GROUP_TO_TEST + (componentIndex + 1), + 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 - expectComponents( - getGroupElement(), - _.without(allComponentsInGroup, allComponentsInGroup[componentIndex]) - ); + // 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 } ); }); diff --git a/cms/static/js/spec/views/pages/container_subviews_spec.js b/cms/static/js/spec/views/pages/container_subviews_spec.js index 97bf656e26..744b991e6b 100644 --- a/cms/static/js/spec/views/pages/container_subviews_spec.js +++ b/cms/static/js/spec/views/pages/container_subviews_spec.js @@ -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({ - published: true, has_changes: false, visibility_state: VisibilityState.ready - })); + 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); }); }); diff --git a/cms/static/js/spec/views/pages/course_outline_spec.js b/cms/static/js/spec/views/pages/course_outline_spec.js index f69bf31e8e..02860f4e3f 100644 --- a/cms/static/js/spec/views/pages/course_outline_spec.js +++ b/cms/static/js/spec/views/pages/course_outline_spec.js @@ -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" diff --git a/cms/static/js/spec/views/pages/course_rerun_spec.js b/cms/static/js/spec/views/pages/course_rerun_spec.js index 08c45c53de..f9d62ed2ba 100644 --- a/cms/static/js/spec/views/pages/course_rerun_spec.js +++ b/cms/static/js/spec/views/pages/course_rerun_spec.js @@ -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 () { diff --git a/cms/static/js/spec/views/pages/index_spec.js b/cms/static/js/spec/views/pages/index_spec.js index 1a06273f26..e9a1d4310a 100644 --- a/cms/static/js/spec/views/pages/index_spec.js +++ b/cms/static/js/spec/views/pages/index_spec.js @@ -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); } }); diff --git a/cms/static/js/spec/views/pages/library_users_spec.js b/cms/static/js/spec/views/pages/library_users_spec.js index 876a6fe30e..3a747d97c2 100644 --- a/cms/static/js/spec/views/pages/library_users_spec.js +++ b/cms/static/js/spec/views/pages/library_users_spec.js @@ -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); }); diff --git a/cms/static/js/spec/views/paging_spec.js b/cms/static/js/spec/views/paging_spec.js index ff9c7a865a..19e1dfedec 100644 --- a/cms/static/js/spec/views/paging_spec.js +++ b/cms/static/js/spec/views/paging_spec.js @@ -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 () { diff --git a/cms/static/js/spec/views/xblock_editor_spec.js b/cms/static/js/spec/views/xblock_editor_spec.js index 5dcafb443e..701c71c499 100644 --- a/cms/static/js/spec/views/xblock_editor_spec.js +++ b/cms/static/js/spec/views/xblock_editor_spec.js @@ -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'); diff --git a/cms/static/js/spec/views/xblock_spec.js b/cms/static/js/spec/views/xblock_spec.js index 5e0c1fe246..6eb9753b63 100644 --- a/cms/static/js/spec/views/xblock_spec.js +++ b/cms/static/js/spec/views/xblock_spec.js @@ -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 }); diff --git a/cms/static/js/spec/views/xblock_string_field_editor_spec.js b/cms/static/js/spec/views/xblock_string_field_editor_spec.js index 883e32a207..b3fa04a7db 100644 --- a/cms/static/js/spec/views/xblock_string_field_editor_spec.js +++ b/cms/static/js/spec/views/xblock_string_field_editor_spec.js @@ -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); }); diff --git a/cms/static/js/spec_helpers/edit_helpers.js b/cms/static/js/spec_helpers/edit_helpers.js index 6f1359d43e..fa100d7907 100644 --- a/cms/static/js/spec_helpers/edit_helpers.js +++ b/cms/static/js/spec_helpers/edit_helpers.js @@ -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"); diff --git a/common/static/common/js/spec/components/paginated_view_spec.js b/common/static/common/js/spec/components/paginated_view_spec.js index 186f711af7..b7b0e4c396 100644 --- a/common/static/common/js/spec/components/paginated_view_spec.js +++ b/common/static/common/js/spec/components/paginated_view_spec.js @@ -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, diff --git a/common/static/common/js/spec/components/paging_collection_spec.js b/common/static/common/js/spec/components/paging_collection_spec.js index 0d5f668e97..6a49b787eb 100644 --- a/common/static/common/js/spec/components/paging_collection_spec.js +++ b/common/static/common/js/spec/components/paging_collection_spec.js @@ -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); }); diff --git a/common/static/common/js/spec_helpers/ajax_helpers.js b/common/static/common/js/spec_helpers/ajax_helpers.js index e699805512..c501f7006f 100644 --- a/common/static/common/js/spec_helpers/ajax_helpers.js +++ b/common/static/common/js/spec_helpers/ajax_helpers.js @@ -1,9 +1,17 @@ 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, - { 'Content-Type': 'application/json' }, - JSON.stringify(jsonResponse)); + /** + * 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++; }; - respondWithError = function(requests, statusCode, jsonResponse, requestIndex) { - if (_.isUndefined(requestIndex)) { - requestIndex = requests.length - 1; - } + 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) { + 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, diff --git a/lms/djangoapps/teams/static/teams/js/spec/collections/topic_collection_spec.js b/lms/djangoapps/teams/static/teams/js/spec/collections/topic_collection_spec.js index 241ef6bf03..272a1827dd 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/collections/topic_collection_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/collections/topic_collection_spec.js @@ -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); }; diff --git a/lms/djangoapps/teams/static/teams/js/spec/views/edit_team_members_spec.js b/lms/djangoapps/teams/static/teams/js/spec/views/edit_team_members_spec.js index aa241b6b5a..f2d28dd507 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/views/edit_team_members_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/views/edit_team_members_spec.js @@ -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); }); diff --git a/lms/djangoapps/teams/static/teams/js/spec/views/edit_team_spec.js b/lms/djangoapps/teams/static/teams/js/spec/views/edit_team_spec.js index f2ddf34382..70f0e59e82 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/views/edit_team_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/views/edit_team_spec.js @@ -55,7 +55,8 @@ define([ } }); - expect(requests.length).toBe(0); + AjaxHelpers.expectNoRequests(requests); + }, editTeamID = 'av', teamAction; diff --git a/lms/djangoapps/teams/static/teams/js/spec/views/instructor_tools_spec.js b/lms/djangoapps/teams/static/teams/js/spec/views/instructor_tools_spec.js index 12bb27d8d1..a556dcab44 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/views/instructor_tools_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/views/instructor_tools_spec.js @@ -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(); }); diff --git a/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_header_actions_spec.js b/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_header_actions_spec.js index af509310ba..5f50e216e1 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_header_actions_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_header_actions_spec.js @@ -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 () { diff --git a/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_spec.js b/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_spec.js index 8e295fb611..7483e64a6f 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_spec.js @@ -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); } }; diff --git a/lms/djangoapps/teams/static/teams/js/spec/views/teams_tab_spec.js b/lms/djangoapps/teams/static/teams/js/spec/views/teams_tab_spec.js index 0665d50e28..e366d004f7 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/views/teams_tab_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/views/teams_tab_spec.js @@ -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 () { diff --git a/lms/static/js/spec/discovery/discovery_factory_spec.js b/lms/static/js/spec/discovery/discovery_factory_spec.js index cef435ed23..199323d0ea 100644 --- a/lms/static/js/spec/discovery/discovery_factory_spec.js +++ b/lms/static/js/spec/discovery/discovery_factory_spec.js @@ -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); }); diff --git a/lms/static/js/spec/edxnotes/views/notes_visibility_factory_spec.js b/lms/static/js/spec/edxnotes/views/notes_visibility_factory_spec.js index 2014d40d34..977b381c07 100644 --- a/lms/static/js/spec/edxnotes/views/notes_visibility_factory_spec.js +++ b/lms/static/js/spec/edxnotes/views/notes_visibility_factory_spec.js @@ -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'); }); diff --git a/lms/static/js/spec/edxnotes/views/tabs/search_results_spec.js b/lms/static/js/spec/edxnotes/views/tabs/search_results_spec.js index 3f01ca9cfe..f828e2d63a 100644 --- a/lms/static/js/spec/edxnotes/views/tabs/search_results_spec.js +++ b/lms/static/js/spec/edxnotes/views/tabs/search_results_spec.js @@ -9,30 +9,30 @@ define([ 'use strict'; describe('EdxNotes SearchResultsView', function() { var notes = [ - { - created: 'December 11, 2014 at 11:12AM', - updated: 'December 11, 2014 at 11:12AM', - text: 'Third added model', - quote: 'Should be listed first' + { + created: 'December 11, 2014 at 11:12AM', + updated: 'December 11, 2014 at 11:12AM', + text: 'Third added model', + quote: 'Should be listed first' + }, + { + created: 'December 11, 2014 at 11:11AM', + updated: 'December 11, 2014 at 11:11AM', + text: 'Second added model', + quote: 'Should be listed second' + }, + { + created: 'December 11, 2014 at 11:10AM', + updated: 'December 11, 2014 at 11:10AM', + text: 'First added model', + quote: 'Should be listed third' + } + ], + responseJson = { + total: 3, + rows: notes }, - { - created: 'December 11, 2014 at 11:11AM', - updated: 'December 11, 2014 at 11:11AM', - text: 'Second added model', - quote: 'Should be listed second' - }, - { - created: 'December 11, 2014 at 11:10AM', - updated: 'December 11, 2014 at 11:10AM', - text: 'First added model', - quote: 'Should be listed third' - } - ], - responseJson = { - 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 }); diff --git a/lms/static/js/spec/groups/views/cohorts_spec.js b/lms/static/js/spec/groups/views/cohorts_spec.js index 975dfa7491..44ad1d2d3f 100644 --- a/lms/static/js/spec/groups/views/cohorts_spec.js +++ b/lms/static/js/spec/groups/views/cohorts_spec.js @@ -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(''); }); diff --git a/lms/static/js/spec/search/search_spec.js b/lms/static/js/spec/search/search_spec.js index e907d88072..af76009741 100644 --- a/lms/static/js/spec/search/search_spec.js +++ b/lms/static/js/spec/search/search_spec.js @@ -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); }); diff --git a/lms/static/js/spec/student_account/account_settings_factory_spec.js b/lms/static/js/spec/student_account/account_settings_factory_spec.js index 12cdda51f5..656f696ae8 100644 --- a/lms/static/js/spec/student_account/account_settings_factory_spec.js +++ b/lms/static/js/spec/student_account/account_settings_factory_spec.js @@ -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; diff --git a/lms/static/js/spec/student_profile/learner_profile_factory_spec.js b/lms/static/js/spec/student_profile/learner_profile_factory_spec.js index c6bc477b38..638a51d48c 100644 --- a/lms/static/js/spec/student_profile/learner_profile_factory_spec.js +++ b/lms/static/js/spec/student_profile/learner_profile_factory_spec.js @@ -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); diff --git a/lms/static/js/spec/student_profile/learner_profile_fields_spec.js b/lms/static/js/spec/student_profile/learner_profile_fields_spec.js index 694171335c..ab5a86c0e1 100644 --- a/lms/static/js/spec/student_profile/learner_profile_fields_spec.js +++ b/lms/static/js/spec/student_profile/learner_profile_fields_spec.js @@ -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()); diff --git a/lms/static/js/spec/verify_student/make_payment_step_view_spec.js b/lms/static/js/spec/verify_student/make_payment_step_view_spec.js index 7e59684588..44d7403313 100644 --- a/lms/static/js/spec/verify_student/make_payment_step_view_spec.js +++ b/lms/static/js/spec/verify_student/make_payment_step_view_spec.js @@ -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, {}); }); }; diff --git a/lms/static/js/spec/views/fields_helpers.js b/lms/static/js/spec/views/fields_helpers.js index 5d322d2c40..1fe74c2b48 100644 --- a/lms/static/js/spec/views/fields_helpers.js +++ b/lms/static/js/spec/views/fields_helpers.js @@ -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) { diff --git a/lms/static/js/spec/views/file_uploader_spec.js b/lms/static/js/spec/views/file_uploader_spec.js index 0e5e47322c..40d3c0b703 100644 --- a/lms/static/js/spec/views/file_uploader_spec.js +++ b/lms/static/js/spec/views/file_uploader_spec.js @@ -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;