Commit 8627fdef by Andy Armstrong Committed by cahrens

Support adding students to a cohort via the instructor dashboard.

TNL-163
parent 13882b75
require ["jquery", "backbone", "coffee/src/main", "js/spec_helpers/create_sinon", "jasmine-stealth", "jquery.cookie"], require ["jquery", "backbone", "coffee/src/main", "js/common_helpers/ajax_helpers", "jasmine-stealth", "jquery.cookie"],
($, Backbone, main, create_sinon) -> ($, Backbone, main, AjaxHelpers) ->
describe "CMS", -> describe "CMS", ->
it "should initialize URL", -> it "should initialize URL", ->
expect(window.CMS.URL).toBeDefined() expect(window.CMS.URL).toBeDefined()
...@@ -28,7 +28,7 @@ require ["jquery", "backbone", "coffee/src/main", "js/spec_helpers/create_sinon" ...@@ -28,7 +28,7 @@ require ["jquery", "backbone", "coffee/src/main", "js/spec_helpers/create_sinon"
appendSetFixtures(sandbox({id: "page-notification"})) appendSetFixtures(sandbox({id: "page-notification"}))
it "successful AJAX request does not pop an error notification", -> it "successful AJAX request does not pop an error notification", ->
server = create_sinon['server'](200, this) server = AjaxHelpers['server'](200, this)
expect($("#page-notification")).toBeEmpty() expect($("#page-notification")).toBeEmpty()
$.ajax("/test") $.ajax("/test")
...@@ -37,7 +37,7 @@ require ["jquery", "backbone", "coffee/src/main", "js/spec_helpers/create_sinon" ...@@ -37,7 +37,7 @@ require ["jquery", "backbone", "coffee/src/main", "js/spec_helpers/create_sinon"
expect($("#page-notification")).toBeEmpty() expect($("#page-notification")).toBeEmpty()
it "AJAX request with error should pop an error notification", -> it "AJAX request with error should pop an error notification", ->
server = create_sinon['server'](500, this) server = AjaxHelpers['server'](500, this)
$.ajax("/test") $.ajax("/test")
server.respond() server.respond()
...@@ -45,7 +45,7 @@ require ["jquery", "backbone", "coffee/src/main", "js/spec_helpers/create_sinon" ...@@ -45,7 +45,7 @@ require ["jquery", "backbone", "coffee/src/main", "js/spec_helpers/create_sinon"
expect($("#page-notification")).toContain('div.wrapper-notification-error') expect($("#page-notification")).toContain('div.wrapper-notification-error')
it "can override AJAX request with error so it does not pop an error notification", -> it "can override AJAX request with error so it does not pop an error notification", ->
server = create_sinon['server'](500, this) server = AjaxHelpers['server'](500, this)
$.ajax $.ajax
url: "/test" url: "/test"
......
define ["js/models/section", "js/spec_helpers/create_sinon", "js/utils/module"], (Section, create_sinon, ModuleUtils) -> define ["js/models/section", "js/common_helpers/ajax_helpers", "js/utils/module"], (Section, AjaxHelpers, ModuleUtils) ->
describe "Section", -> describe "Section", ->
describe "basic", -> describe "basic", ->
beforeEach -> beforeEach ->
...@@ -34,7 +34,7 @@ define ["js/models/section", "js/spec_helpers/create_sinon", "js/utils/module"], ...@@ -34,7 +34,7 @@ define ["js/models/section", "js/spec_helpers/create_sinon", "js/utils/module"],
}) })
it "show/hide a notification when it saves to the server", -> it "show/hide a notification when it saves to the server", ->
server = create_sinon['server'](200, this) server = AjaxHelpers['server'](200, this)
@model.save() @model.save()
expect(Section.prototype.showNotification).toHaveBeenCalled() expect(Section.prototype.showNotification).toHaveBeenCalled()
...@@ -43,7 +43,7 @@ define ["js/models/section", "js/spec_helpers/create_sinon", "js/utils/module"], ...@@ -43,7 +43,7 @@ define ["js/models/section", "js/spec_helpers/create_sinon", "js/utils/module"],
it "don't hide notification when saving fails", -> it "don't hide notification when saving fails", ->
# this is handled by the global AJAX error handler # this is handled by the global AJAX error handler
server = create_sinon['server'](500, this) server = AjaxHelpers['server'](500, this)
@model.save() @model.save()
server.respond() server.respond()
......
define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"], define ["jquery", "jasmine", "js/common_helpers/ajax_helpers", "squire"],
($, jasmine, create_sinon, Squire) -> ($, jasmine, AjaxHelpers, Squire) ->
feedbackTpl = readFixtures('system-feedback.underscore') feedbackTpl = readFixtures('system-feedback.underscore')
assetLibraryTpl = readFixtures('asset-library.underscore') assetLibraryTpl = readFixtures('asset-library.underscore')
...@@ -72,7 +72,7 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"], ...@@ -72,7 +72,7 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"],
describe "AJAX", -> describe "AJAX", ->
it "should destroy itself on confirmation", -> it "should destroy itself on confirmation", ->
requests = create_sinon["requests"](this) requests = AjaxHelpers["requests"](this)
@view.render().$(".remove-asset-button").click() @view.render().$(".remove-asset-button").click()
ctorOptions = @promptSpies.constructor.mostRecentCall.args[0] ctorOptions = @promptSpies.constructor.mostRecentCall.args[0]
...@@ -92,7 +92,7 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"], ...@@ -92,7 +92,7 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"],
expect(@collection.contains(@model)).toBeFalsy() expect(@collection.contains(@model)).toBeFalsy()
it "should not destroy itself if server errors", -> it "should not destroy itself if server errors", ->
requests = create_sinon["requests"](this) requests = AjaxHelpers["requests"](this)
@view.render().$(".remove-asset-button").click() @view.render().$(".remove-asset-button").click()
ctorOptions = @promptSpies.constructor.mostRecentCall.args[0] ctorOptions = @promptSpies.constructor.mostRecentCall.args[0]
...@@ -106,7 +106,7 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"], ...@@ -106,7 +106,7 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"],
expect(@collection.contains(@model)).toBeTruthy() expect(@collection.contains(@model)).toBeTruthy()
it "should lock the asset on confirmation", -> it "should lock the asset on confirmation", ->
requests = create_sinon["requests"](this) requests = AjaxHelpers["requests"](this)
@view.render().$(".lock-checkbox").click() @view.render().$(".lock-checkbox").click()
# AJAX request has been sent, but not yet returned # AJAX request has been sent, but not yet returned
...@@ -123,7 +123,7 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"], ...@@ -123,7 +123,7 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"],
expect(@model.get("locked")).toBeTruthy() expect(@model.get("locked")).toBeTruthy()
it "should not lock the asset if server errors", -> it "should not lock the asset if server errors", ->
requests = create_sinon["requests"](this) requests = AjaxHelpers["requests"](this)
@view.render().$(".lock-checkbox").click() @view.render().$(".lock-checkbox").click()
# return an error response # return an error response
...@@ -207,7 +207,7 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"], ...@@ -207,7 +207,7 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"],
thumbnail: null thumbnail: null
id: 'idx' id: 'idx'
@view.addAsset(model) @view.addAsset(model)
create_sinon.respondWithJson(requests, AjaxHelpers.respondWithJson(requests,
{ {
assets: [ assets: [
@mockAsset1, @mockAsset2, @mockAsset1, @mockAsset2,
...@@ -231,9 +231,9 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"], ...@@ -231,9 +231,9 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"],
describe "Basic", -> describe "Basic", ->
# Separate setup method to work-around mis-parenting of beforeEach methods # Separate setup method to work-around mis-parenting of beforeEach methods
setup = -> setup = ->
requests = create_sinon.requests(this) requests = AjaxHelpers.requests(this)
@view.setPage(0) @view.setPage(0)
create_sinon.respondWithJson(requests, @mockAssetsResponse) AjaxHelpers.respondWithJson(requests, @mockAssetsResponse)
return requests return requests
$.fn.fileupload = -> $.fn.fileupload = ->
...@@ -270,11 +270,11 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"], ...@@ -270,11 +270,11 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"],
expect($('.ui-loading').is(':visible')).toBe(false) expect($('.ui-loading').is(':visible')).toBe(false)
it "should hide the status indicator if an error occurs while loading", -> it "should hide the status indicator if an error occurs while loading", ->
requests = create_sinon.requests(this) requests = AjaxHelpers.requests(this)
appendSetFixtures('<div class="ui-loading"/>') appendSetFixtures('<div class="ui-loading"/>')
expect($('.ui-loading').is(':visible')).toBe(true) expect($('.ui-loading').is(':visible')).toBe(true)
@view.setPage(0) @view.setPage(0)
create_sinon.respondWithError(requests) AjaxHelpers.respondWithError(requests)
expect($('.ui-loading').is(':visible')).toBe(false) expect($('.ui-loading').is(':visible')).toBe(false)
it "should render both assets", -> it "should render both assets", ->
...@@ -316,9 +316,9 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"], ...@@ -316,9 +316,9 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"],
describe "Sorting", -> describe "Sorting", ->
# Separate setup method to work-around mis-parenting of beforeEach methods # Separate setup method to work-around mis-parenting of beforeEach methods
setup = -> setup = ->
requests = create_sinon.requests(this) requests = AjaxHelpers.requests(this)
@view.setPage(0) @view.setPage(0)
create_sinon.respondWithJson(requests, @mockAssetsResponse) AjaxHelpers.respondWithJson(requests, @mockAssetsResponse)
return requests return requests
it "should have the correct default sort order", -> it "should have the correct default sort order", ->
...@@ -331,30 +331,30 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"], ...@@ -331,30 +331,30 @@ define ["jquery", "jasmine", "js/spec_helpers/create_sinon", "squire"],
expect(@view.sortDisplayName()).toBe("Date Added") expect(@view.sortDisplayName()).toBe("Date Added")
expect(@view.collection.sortDirection).toBe("desc") expect(@view.collection.sortDirection).toBe("desc")
@view.$("#js-asset-date-col").click() @view.$("#js-asset-date-col").click()
create_sinon.respondWithJson(requests, @mockAssetsResponse) AjaxHelpers.respondWithJson(requests, @mockAssetsResponse)
expect(@view.sortDisplayName()).toBe("Date Added") expect(@view.sortDisplayName()).toBe("Date Added")
expect(@view.collection.sortDirection).toBe("asc") expect(@view.collection.sortDirection).toBe("asc")
@view.$("#js-asset-date-col").click() @view.$("#js-asset-date-col").click()
create_sinon.respondWithJson(requests, @mockAssetsResponse) AjaxHelpers.respondWithJson(requests, @mockAssetsResponse)
expect(@view.sortDisplayName()).toBe("Date Added") expect(@view.sortDisplayName()).toBe("Date Added")
expect(@view.collection.sortDirection).toBe("desc") expect(@view.collection.sortDirection).toBe("desc")
it "should switch the sort order when clicking on a different column", -> it "should switch the sort order when clicking on a different column", ->
requests = setup.call(this) requests = setup.call(this)
@view.$("#js-asset-name-col").click() @view.$("#js-asset-name-col").click()
create_sinon.respondWithJson(requests, @mockAssetsResponse) AjaxHelpers.respondWithJson(requests, @mockAssetsResponse)
expect(@view.sortDisplayName()).toBe("Name") expect(@view.sortDisplayName()).toBe("Name")
expect(@view.collection.sortDirection).toBe("asc") expect(@view.collection.sortDirection).toBe("asc")
@view.$("#js-asset-name-col").click() @view.$("#js-asset-name-col").click()
create_sinon.respondWithJson(requests, @mockAssetsResponse) AjaxHelpers.respondWithJson(requests, @mockAssetsResponse)
expect(@view.sortDisplayName()).toBe("Name") expect(@view.sortDisplayName()).toBe("Name")
expect(@view.collection.sortDirection).toBe("desc") expect(@view.collection.sortDirection).toBe("desc")
it "should switch sort to most recent date added when a new asset is added", -> it "should switch sort to most recent date added when a new asset is added", ->
requests = setup.call(this) requests = setup.call(this)
@view.$("#js-asset-name-col").click() @view.$("#js-asset-name-col").click()
create_sinon.respondWithJson(requests, @mockAssetsResponse) AjaxHelpers.respondWithJson(requests, @mockAssetsResponse)
addMockAsset.call(this, requests) addMockAsset.call(this, requests)
create_sinon.respondWithJson(requests, @mockAssetsResponse) AjaxHelpers.respondWithJson(requests, @mockAssetsResponse)
expect(@view.sortDisplayName()).toBe("Date Added") expect(@view.sortDisplayName()).toBe("Date Added")
expect(@view.collection.sortDirection).toBe("desc") expect(@view.collection.sortDirection).toBe("desc")
define ["js/views/course_info_handout", "js/views/course_info_update", "js/models/module_info", "js/collections/course_update", "js/spec_helpers/create_sinon"], define ["js/views/course_info_handout", "js/views/course_info_update", "js/models/module_info", "js/collections/course_update", "js/common_helpers/ajax_helpers"],
(CourseInfoHandoutsView, CourseInfoUpdateView, ModuleInfo, CourseUpdateCollection, create_sinon) -> (CourseInfoHandoutsView, CourseInfoUpdateView, ModuleInfo, CourseUpdateCollection, AjaxHelpers) ->
describe "Course Updates and Handouts", -> describe "Course Updates and Handouts", ->
courseInfoPage = """ courseInfoPage = """
...@@ -101,7 +101,7 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model ...@@ -101,7 +101,7 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model
modalCover.click() modalCover.click()
it "does not rewrite links on save", -> it "does not rewrite links on save", ->
requests = create_sinon["requests"](this) requests = AjaxHelpers["requests"](this)
# Create a new update, verifying that the model is created # Create a new update, verifying that the model is created
# in the collection and save is called. # in the collection and save is called.
...@@ -168,7 +168,7 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model ...@@ -168,7 +168,7 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model
@handoutsEdit.render() @handoutsEdit.render()
it "does not rewrite links on save", -> it "does not rewrite links on save", ->
requests = create_sinon["requests"](this) requests = AjaxHelpers["requests"](this)
# Enter something in the handouts section, verifying that the model is saved # Enter something in the handouts section, verifying that the model is saved
# when "Save" is clicked. # when "Save" is clicked.
......
define ["js/models/textbook", "js/models/chapter", "js/collections/chapter", "js/models/course", define ["js/models/textbook", "js/models/chapter", "js/collections/chapter", "js/models/course",
"js/collections/textbook", "js/views/show_textbook", "js/views/edit_textbook", "js/views/list_textbooks", "js/collections/textbook", "js/views/show_textbook", "js/views/edit_textbook", "js/views/list_textbooks",
"js/views/edit_chapter", "js/views/feedback_prompt", "js/views/feedback_notification", "js/views/edit_chapter", "js/views/feedback_prompt", "js/views/feedback_notification",
"js/spec_helpers/create_sinon", "js/spec_helpers/modal_helpers", "jasmine-stealth"], "js/common_helpers/ajax_helpers", "js/spec_helpers/modal_helpers", "jasmine-stealth"],
(Textbook, Chapter, ChapterSet, Course, TextbookSet, ShowTextbook, EditTextbook, ListTexbook, EditChapter, Prompt, Notification, create_sinon, modal_helpers) -> (Textbook, Chapter, ChapterSet, Course, TextbookSet, ShowTextbook, EditTextbook, ListTexbook, EditChapter, Prompt, Notification, AjaxHelpers, modal_helpers) ->
feedbackTpl = readFixtures('system-feedback.underscore') feedbackTpl = readFixtures('system-feedback.underscore')
beforeEach -> beforeEach ->
...@@ -83,7 +83,7 @@ define ["js/models/textbook", "js/models/chapter", "js/collections/chapter", "js ...@@ -83,7 +83,7 @@ define ["js/models/textbook", "js/models/chapter", "js/collections/chapter", "js
delete CMS.URL.TEXTBOOKS delete CMS.URL.TEXTBOOKS
it "should destroy itself on confirmation", -> it "should destroy itself on confirmation", ->
requests = create_sinon["requests"](this) requests = AjaxHelpers["requests"](this)
@view.render().$(".delete").click() @view.render().$(".delete").click()
ctorOptions = @promptSpies.constructor.mostRecentCall.args[0] ctorOptions = @promptSpies.constructor.mostRecentCall.args[0]
......
define ["js/models/uploads", "js/views/uploads", "js/models/chapter", "js/spec_helpers/create_sinon", "js/spec_helpers/modal_helpers"], (FileUpload, UploadDialog, Chapter, create_sinon, modal_helpers) -> define ["js/models/uploads", "js/views/uploads", "js/models/chapter", "js/common_helpers/ajax_helpers", "js/spec_helpers/modal_helpers"], (FileUpload, UploadDialog, Chapter, AjaxHelpers, modal_helpers) ->
feedbackTpl = readFixtures('system-feedback.underscore') feedbackTpl = readFixtures('system-feedback.underscore')
...@@ -98,7 +98,7 @@ define ["js/models/uploads", "js/views/uploads", "js/models/chapter", "js/spec_h ...@@ -98,7 +98,7 @@ define ["js/models/uploads", "js/views/uploads", "js/models/chapter", "js/spec_h
@clock.restore() @clock.restore()
it "can upload correctly", -> it "can upload correctly", ->
requests = create_sinon["requests"](this) requests = AjaxHelpers["requests"](this)
@view.render() @view.render()
@view.upload() @view.upload()
...@@ -115,7 +115,7 @@ define ["js/models/uploads", "js/views/uploads", "js/models/chapter", "js/spec_h ...@@ -115,7 +115,7 @@ define ["js/models/uploads", "js/views/uploads", "js/models/chapter", "js/spec_h
expect(@dialogResponse.pop()).toEqual("dummy_response") expect(@dialogResponse.pop()).toEqual("dummy_response")
it "can handle upload errors", -> it "can handle upload errors", ->
requests = create_sinon["requests"](this) requests = AjaxHelpers["requests"](this)
@view.render() @view.render()
@view.upload() @view.upload()
...@@ -124,7 +124,7 @@ define ["js/models/uploads", "js/views/uploads", "js/models/chapter", "js/spec_h ...@@ -124,7 +124,7 @@ define ["js/models/uploads", "js/views/uploads", "js/models/chapter", "js/spec_h
expect(@view.remove).not.toHaveBeenCalled() expect(@view.remove).not.toHaveBeenCalled()
it "removes itself after two seconds on successful upload", -> it "removes itself after two seconds on successful upload", ->
requests = create_sinon["requests"](this) requests = AjaxHelpers["requests"](this)
@view.render() @view.render()
@view.upload() @view.upload()
......
../../../common/static/js/spec_helpers
\ No newline at end of file
define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_helpers/create_sinon", "jquery", "underscore"], define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/common_helpers/ajax_helpers", "jquery", "underscore"],
function (ContentDragger, Notification, create_sinon, $, _) { function (ContentDragger, Notification, AjaxHelpers, $, _) {
describe("Overview drag and drop functionality", function () { describe("Overview drag and drop functionality", function () {
beforeEach(function () { beforeEach(function () {
setFixtures(readFixtures('mock/mock-outline.underscore')); setFixtures(readFixtures('mock/mock-outline.underscore'));
...@@ -310,7 +310,7 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel ...@@ -310,7 +310,7 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
}); });
it("should send an update on reorder from one parent to another", function () { it("should send an update on reorder from one parent to another", function () {
var requests, savingOptions; var requests, savingOptions;
requests = create_sinon["requests"](this); requests = AjaxHelpers["requests"](this);
ContentDragger.dragState.dropDestination = $('#unit-4'); ContentDragger.dragState.dropDestination = $('#unit-4');
ContentDragger.dragState.attachMethod = "after"; ContentDragger.dragState.attachMethod = "after";
ContentDragger.dragState.parentList = $('#subsection-2'); ContentDragger.dragState.parentList = $('#subsection-2');
...@@ -341,7 +341,7 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel ...@@ -341,7 +341,7 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
expect($('#subsection-2').data('refresh')).toHaveBeenCalled(); expect($('#subsection-2').data('refresh')).toHaveBeenCalled();
}); });
it("should send an update on reorder within the same parent", function () { it("should send an update on reorder within the same parent", function () {
var requests = create_sinon["requests"](this); var requests = AjaxHelpers["requests"](this);
ContentDragger.dragState.dropDestination = $('#unit-2'); ContentDragger.dragState.dropDestination = $('#unit-2');
ContentDragger.dragState.attachMethod = "after"; ContentDragger.dragState.attachMethod = "after";
ContentDragger.dragState.parentList = $('#subsection-1'); ContentDragger.dragState.parentList = $('#subsection-1');
......
define( define(
[ [
'jquery', 'underscore', 'js/spec_helpers/create_sinon', 'squire' 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'squire'
], ],
function ($, _, create_sinon, Squire) { function ($, _, AjaxHelpers, Squire) {
'use strict'; 'use strict';
describe('FileUploader', function () { describe('FileUploader', function () {
var FileUploaderTemplate = readFixtures( var FileUploaderTemplate = readFixtures(
......
define( define(
[ [
'jquery', 'underscore', 'js/spec_helpers/create_sinon', 'squire' 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'squire'
], ],
function ($, _, create_sinon, Squire) { function ($, _, AjaxHelpers, Squire) {
'use strict'; 'use strict';
// TODO: fix BLD-1100 Disabled due to intermittent failure on master and in PR builds // TODO: fix BLD-1100 Disabled due to intermittent failure on master and in PR builds
xdescribe('VideoTranslations', function () { xdescribe('VideoTranslations', function () {
......
define([ "jquery", "js/spec_helpers/create_sinon", "js/views/asset", "js/views/assets", define([ "jquery", "js/common_helpers/ajax_helpers", "js/views/asset", "js/views/assets",
"js/models/asset", "js/collections/asset", "js/spec_helpers/view_helpers" ], "js/models/asset", "js/collections/asset", "js/spec_helpers/view_helpers" ],
function ($, create_sinon, AssetView, AssetsView, AssetModel, AssetCollection, view_helpers) { function ($, AjaxHelpers, AssetView, AssetsView, AssetModel, AssetCollection, ViewHelpers) {
describe("Assets", function() { describe("Assets", function() {
var assetsView, mockEmptyAssetsResponse, mockAssetUploadResponse, var assetsView, mockEmptyAssetsResponse, mockAssetUploadResponse,
...@@ -64,18 +64,18 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/views/asset", "js/views/a ...@@ -64,18 +64,18 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/views/asset", "js/views/a
var setup; var setup;
setup = function() { setup = function() {
var requests; var requests;
requests = create_sinon.requests(this); requests = AjaxHelpers.requests(this);
assetsView.setPage(0); assetsView.setPage(0);
create_sinon.respondWithJson(requests, mockEmptyAssetsResponse); AjaxHelpers.respondWithJson(requests, mockEmptyAssetsResponse);
return requests; return requests;
}; };
beforeEach(function () { beforeEach(function () {
view_helpers.installMockAnalytics(); ViewHelpers.installMockAnalytics();
}); });
afterEach(function () { afterEach(function () {
view_helpers.removeMockAnalytics(); ViewHelpers.removeMockAnalytics();
}); });
it('shows the upload modal when clicked on "Upload your first asset" button', function () { it('shows the upload modal when clicked on "Upload your first asset" button', function () {
......
define(["jquery", "underscore", "js/views/baseview", "js/utils/handle_iframe_binding", "sinon", define(["jquery", "underscore", "js/views/baseview", "js/utils/handle_iframe_binding", "sinon"],
"js/spec_helpers/edit_helpers"], function ($, _, BaseView, IframeBinding, sinon) {
function ($, _, BaseView, IframeBinding, sinon, view_helpers) {
describe("BaseView", function() { describe("BaseView", function() {
var baseViewPrototype; var baseViewPrototype;
......
define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers", define([ "jquery", "js/common_helpers/ajax_helpers", "js/spec_helpers/edit_helpers",
"js/views/container", "js/models/xblock_info", "jquery.simulate", "js/views/container", "js/models/xblock_info", "jquery.simulate",
"xmodule", "coffee/src/main", "xblock/cms.runtime.v1"], "xmodule", "coffee/src/main", "xblock/cms.runtime.v1"],
function ($, create_sinon, edit_helpers, ContainerView, XBlockInfo) { function ($, AjaxHelpers, EditHelpers, ContainerView, XBlockInfo) {
describe("Container View", function () { describe("Container View", function () {
...@@ -30,14 +30,14 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers ...@@ -30,14 +30,14 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers
respondWithMockXBlockFragment = function (requests, response) { respondWithMockXBlockFragment = function (requests, response) {
var requestIndex = requests.length - 1; var requestIndex = requests.length - 1;
create_sinon.respondWithJson(requests, response, requestIndex); AjaxHelpers.respondWithJson(requests, response, requestIndex);
}; };
beforeEach(function () { beforeEach(function () {
edit_helpers.installMockXBlock(); EditHelpers.installMockXBlock();
edit_helpers.installViewTemplates(); EditHelpers.installViewTemplates();
appendSetFixtures('<div class="wrapper-xblock level-page studio-xblock-wrapper" data-locator="' + rootLocator + '"></div>'); appendSetFixtures('<div class="wrapper-xblock level-page studio-xblock-wrapper" data-locator="' + rootLocator + '"></div>');
notificationSpy = edit_helpers.createNotificationSpy(); notificationSpy = EditHelpers.createNotificationSpy();
model = new XBlockInfo({ model = new XBlockInfo({
id: rootLocator, id: rootLocator,
display_name: 'Test AB Test', display_name: 'Test AB Test',
...@@ -52,12 +52,12 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers ...@@ -52,12 +52,12 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers
}); });
afterEach(function () { afterEach(function () {
edit_helpers.uninstallMockXBlock(); EditHelpers.uninstallMockXBlock();
containerView.remove(); containerView.remove();
}); });
init = function (caller) { init = function (caller) {
var requests = create_sinon.requests(caller); var requests = AjaxHelpers.requests(caller);
containerView.render(); containerView.render();
respondWithMockXBlockFragment(requests, { respondWithMockXBlockFragment(requests, {
...@@ -188,11 +188,11 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers ...@@ -188,11 +188,11 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers
// Drag the first component in Group B to the first group. // Drag the first component in Group B to the first group.
dragComponentAbove(groupBComponent1, groupAComponent1); dragComponentAbove(groupBComponent1, groupAComponent1);
edit_helpers.verifyNotificationShowing(notificationSpy, 'Saving'); EditHelpers.verifyNotificationShowing(notificationSpy, 'Saving');
respondToRequest(requests, 0, 200); respondToRequest(requests, 0, 200);
edit_helpers.verifyNotificationShowing(notificationSpy, 'Saving'); EditHelpers.verifyNotificationShowing(notificationSpy, 'Saving');
respondToRequest(requests, 1, 200); respondToRequest(requests, 1, 200);
edit_helpers.verifyNotificationHidden(notificationSpy); EditHelpers.verifyNotificationHidden(notificationSpy);
}); });
it('does not hide saving message if failure', function () { it('does not hide saving message if failure', function () {
...@@ -200,9 +200,9 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers ...@@ -200,9 +200,9 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers
// Drag the first component in Group B to the first group. // Drag the first component in Group B to the first group.
dragComponentAbove(groupBComponent1, groupAComponent1); dragComponentAbove(groupBComponent1, groupAComponent1);
edit_helpers.verifyNotificationShowing(notificationSpy, 'Saving'); EditHelpers.verifyNotificationShowing(notificationSpy, 'Saving');
respondToRequest(requests, 0, 500); respondToRequest(requests, 0, 500);
edit_helpers.verifyNotificationShowing(notificationSpy, 'Saving'); EditHelpers.verifyNotificationShowing(notificationSpy, 'Saving');
// Since the first reorder call failed, the removal will not be called. // Since the first reorder call failed, the removal will not be called.
verifyNumReorderCalls(requests, 1); verifyNumReorderCalls(requests, 1);
......
...@@ -5,13 +5,13 @@ define([ ...@@ -5,13 +5,13 @@ define([
'js/views/group_configurations_list', 'js/views/group_configuration_edit', 'js/views/group_configurations_list', 'js/views/group_configuration_edit',
'js/views/group_configuration_item', 'js/models/group', 'js/views/group_configuration_item', 'js/models/group',
'js/collections/group', 'js/views/group_edit', 'js/collections/group', 'js/views/group_edit',
'js/views/feedback_notification', 'js/spec_helpers/create_sinon', 'js/views/feedback_notification', 'js/common_helpers/ajax_helpers', 'js/common_helpers/template_helpers',
'js/spec_helpers/edit_helpers', 'jasmine-stealth' 'js/spec_helpers/view_helpers', 'jasmine-stealth'
], function( ], function(
_, Course, GroupConfigurationModel, GroupConfigurationCollection, _, Course, GroupConfigurationModel, GroupConfigurationCollection,
GroupConfigurationDetails, GroupConfigurationsList, GroupConfigurationEdit, GroupConfigurationDetails, GroupConfigurationsList, GroupConfigurationEdit,
GroupConfigurationItem, GroupModel, GroupCollection, GroupEdit, GroupConfigurationItem, GroupModel, GroupCollection, GroupEdit,
Notification, create_sinon, view_helpers Notification, AjaxHelpers, TemplateHelpers, ViewHelpers
) { ) {
'use strict'; 'use strict';
var SELECTORS = { var SELECTORS = {
...@@ -92,7 +92,7 @@ define([ ...@@ -92,7 +92,7 @@ define([
describe('GroupConfigurationDetails', function() { describe('GroupConfigurationDetails', function() {
beforeEach(function() { beforeEach(function() {
view_helpers.installTemplate('group-configuration-details', true); TemplateHelpers.installTemplate('group-configuration-details', true);
this.model = new GroupConfigurationModel({ this.model = new GroupConfigurationModel({
name: 'Configuration', name: 'Configuration',
...@@ -270,8 +270,8 @@ define([ ...@@ -270,8 +270,8 @@ define([
}; };
beforeEach(function() { beforeEach(function() {
view_helpers.installViewTemplates(); ViewHelpers.installViewTemplates();
view_helpers.installTemplates([ TemplateHelpers.installTemplates([
'group-configuration-edit', 'group-edit' 'group-configuration-edit', 'group-edit'
]); ]);
...@@ -304,8 +304,8 @@ define([ ...@@ -304,8 +304,8 @@ define([
}); });
it('should save properly', function() { it('should save properly', function() {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
notificationSpy = view_helpers.createNotificationSpy(), notificationSpy = ViewHelpers.createNotificationSpy(),
groups; groups;
this.view.$('.action-add-group').click(); this.view.$('.action-add-group').click();
...@@ -315,9 +315,9 @@ define([ ...@@ -315,9 +315,9 @@ define([
}); });
this.view.$('form').submit(); this.view.$('form').submit();
view_helpers.verifyNotificationShowing(notificationSpy, /Saving/); ViewHelpers.verifyNotificationShowing(notificationSpy, /Saving/);
requests[0].respond(200); requests[0].respond(200);
view_helpers.verifyNotificationHidden(notificationSpy); ViewHelpers.verifyNotificationHidden(notificationSpy);
expect(this.model).toBeCorrectValuesInModel({ expect(this.model).toBeCorrectValuesInModel({
name: 'New Configuration', name: 'New Configuration',
...@@ -331,14 +331,14 @@ define([ ...@@ -331,14 +331,14 @@ define([
}); });
it('does not hide saving message if failure', function() { it('does not hide saving message if failure', function() {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
notificationSpy = view_helpers.createNotificationSpy(); notificationSpy = ViewHelpers.createNotificationSpy();
setValuesToInputs(this.view, { inputName: 'New Configuration' }); setValuesToInputs(this.view, { inputName: 'New Configuration' });
this.view.$('form').submit(); this.view.$('form').submit();
view_helpers.verifyNotificationShowing(notificationSpy, /Saving/); ViewHelpers.verifyNotificationShowing(notificationSpy, /Saving/);
create_sinon.respondWithError(requests); AjaxHelpers.respondWithError(requests);
view_helpers.verifyNotificationShowing(notificationSpy, /Saving/); ViewHelpers.verifyNotificationShowing(notificationSpy, /Saving/);
}); });
it('does not save on cancel', function() { it('does not save on cancel', function() {
...@@ -373,7 +373,7 @@ define([ ...@@ -373,7 +373,7 @@ define([
}); });
it('should be possible to correct validation errors', function() { it('should be possible to correct validation errors', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
// Set incorrect value // Set incorrect value
setValuesToInputs(this.view, { inputName: '' }); setValuesToInputs(this.view, { inputName: '' });
...@@ -494,7 +494,7 @@ define([ ...@@ -494,7 +494,7 @@ define([
var emptyMessage = 'You haven\'t created any group configurations yet.'; var emptyMessage = 'You haven\'t created any group configurations yet.';
beforeEach(function() { beforeEach(function() {
view_helpers.installTemplate('no-group-configurations', true); TemplateHelpers.installTemplate('no-group-configurations', true);
this.model = new GroupConfigurationModel({ id: 0 }); this.model = new GroupConfigurationModel({ id: 0 });
this.collection = new GroupConfigurationCollection(); this.collection = new GroupConfigurationCollection();
...@@ -533,7 +533,7 @@ define([ ...@@ -533,7 +533,7 @@ define([
var clickDeleteItem; var clickDeleteItem;
beforeEach(function() { beforeEach(function() {
view_helpers.installTemplates([ TemplateHelpers.installTemplates([
'group-configuration-edit', 'group-configuration-details' 'group-configuration-edit', 'group-configuration-details'
], true); ], true);
this.model = new GroupConfigurationModel({ id: 0 }); this.model = new GroupConfigurationModel({ id: 0 });
...@@ -547,9 +547,9 @@ define([ ...@@ -547,9 +547,9 @@ define([
clickDeleteItem = function (view, promptSpy) { clickDeleteItem = function (view, promptSpy) {
view.$('.delete').click(); view.$('.delete').click();
view_helpers.verifyPromptShowing(promptSpy, /Delete this Group Configuration/); ViewHelpers.verifyPromptShowing(promptSpy, /Delete this Group Configuration/);
view_helpers.confirmPrompt(promptSpy); ViewHelpers.confirmPrompt(promptSpy);
view_helpers.verifyPromptHidden(promptSpy); ViewHelpers.verifyPromptHidden(promptSpy);
}; };
it('should render properly', function() { it('should render properly', function() {
...@@ -564,43 +564,43 @@ define([ ...@@ -564,43 +564,43 @@ define([
}); });
it('should destroy itself on confirmation of deleting', function () { it('should destroy itself on confirmation of deleting', function () {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
promptSpy = view_helpers.createPromptSpy(), promptSpy = ViewHelpers.createPromptSpy(),
notificationSpy = view_helpers.createNotificationSpy(); notificationSpy = ViewHelpers.createNotificationSpy();
clickDeleteItem(this.view, promptSpy); clickDeleteItem(this.view, promptSpy);
// Backbone.emulateHTTP is enabled in our system, so setting this // Backbone.emulateHTTP is enabled in our system, so setting this
// option will fake PUT, PATCH and DELETE requests with a HTTP POST, // option will fake PUT, PATCH and DELETE requests with a HTTP POST,
// setting the X-HTTP-Method-Override header with the true method. // setting the X-HTTP-Method-Override header with the true method.
create_sinon.expectJsonRequest(requests, 'POST', '/group_configurations/0'); AjaxHelpers.expectJsonRequest(requests, 'POST', '/group_configurations/0');
expect(_.last(requests).requestHeaders['X-HTTP-Method-Override']).toBe('DELETE'); expect(_.last(requests).requestHeaders['X-HTTP-Method-Override']).toBe('DELETE');
view_helpers.verifyNotificationShowing(notificationSpy, /Deleting/); ViewHelpers.verifyNotificationShowing(notificationSpy, /Deleting/);
create_sinon.respondToDelete(requests); AjaxHelpers.respondToDelete(requests);
view_helpers.verifyNotificationHidden(notificationSpy); ViewHelpers.verifyNotificationHidden(notificationSpy);
expect($(SELECTORS.itemView)).not.toExist(); expect($(SELECTORS.itemView)).not.toExist();
}); });
it('does not hide deleting message if failure', function() { it('does not hide deleting message if failure', function() {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
promptSpy = view_helpers.createPromptSpy(), promptSpy = ViewHelpers.createPromptSpy(),
notificationSpy = view_helpers.createNotificationSpy(); notificationSpy = ViewHelpers.createNotificationSpy();
clickDeleteItem(this.view, promptSpy); clickDeleteItem(this.view, promptSpy);
// Backbone.emulateHTTP is enabled in our system, so setting this // Backbone.emulateHTTP is enabled in our system, so setting this
// option will fake PUT, PATCH and DELETE requests with a HTTP POST, // option will fake PUT, PATCH and DELETE requests with a HTTP POST,
// setting the X-HTTP-Method-Override header with the true method. // setting the X-HTTP-Method-Override header with the true method.
create_sinon.expectJsonRequest(requests, 'POST', '/group_configurations/0'); AjaxHelpers.expectJsonRequest(requests, 'POST', '/group_configurations/0');
expect(_.last(requests).requestHeaders['X-HTTP-Method-Override']).toBe('DELETE'); expect(_.last(requests).requestHeaders['X-HTTP-Method-Override']).toBe('DELETE');
view_helpers.verifyNotificationShowing(notificationSpy, /Deleting/); ViewHelpers.verifyNotificationShowing(notificationSpy, /Deleting/);
create_sinon.respondWithError(requests); AjaxHelpers.respondWithError(requests);
view_helpers.verifyNotificationShowing(notificationSpy, /Deleting/); ViewHelpers.verifyNotificationShowing(notificationSpy, /Deleting/);
expect($(SELECTORS.itemView)).toExist(); expect($(SELECTORS.itemView)).toExist();
}); });
}); });
describe('GroupEdit', function() { describe('GroupEdit', function() {
beforeEach(function() { beforeEach(function() {
view_helpers.installTemplate('group-edit', true); TemplateHelpers.installTemplate('group-edit', true);
this.model = new GroupModel({ this.model = new GroupModel({
name: 'Group A' name: 'Group A'
......
define(["jquery", "underscore", "js/views/modals/base_modal", "js/spec_helpers/modal_helpers"], define(["jquery", "underscore", "js/views/modals/base_modal", "js/spec_helpers/modal_helpers"],
function ($, _, BaseModal, modal_helpers) { function ($, _, BaseModal, ModelHelpers) {
describe("BaseModal", function() { describe("BaseModal", function() {
var MockModal, modal, showMockModal; var MockModal, modal, showMockModal;
...@@ -18,29 +18,29 @@ define(["jquery", "underscore", "js/views/modals/base_modal", "js/spec_helpers/m ...@@ -18,29 +18,29 @@ define(["jquery", "underscore", "js/views/modals/base_modal", "js/spec_helpers/m
}; };
beforeEach(function () { beforeEach(function () {
modal_helpers.installModalTemplates(); ModelHelpers.installModalTemplates();
}); });
afterEach(function() { afterEach(function() {
modal_helpers.hideModalIfShowing(modal); ModelHelpers.hideModalIfShowing(modal);
}); });
describe("Single Modal", function() { describe("Single Modal", function() {
it('is visible after show is called', function () { it('is visible after show is called', function () {
showMockModal(); showMockModal();
expect(modal_helpers.isShowingModal(modal)).toBeTruthy(); expect(ModelHelpers.isShowingModal(modal)).toBeTruthy();
}); });
it('is removed after hide is called', function () { it('is removed after hide is called', function () {
showMockModal(); showMockModal();
modal.hide(); modal.hide();
expect(modal_helpers.isShowingModal(modal)).toBeFalsy(); expect(ModelHelpers.isShowingModal(modal)).toBeFalsy();
}); });
it('is removed after cancel is clicked', function () { it('is removed after cancel is clicked', function () {
showMockModal(); showMockModal();
modal_helpers.cancelModal(modal); ModelHelpers.cancelModal(modal);
expect(modal_helpers.isShowingModal(modal)).toBeFalsy(); expect(ModelHelpers.isShowingModal(modal)).toBeFalsy();
}); });
}); });
...@@ -57,32 +57,32 @@ define(["jquery", "underscore", "js/views/modals/base_modal", "js/spec_helpers/m ...@@ -57,32 +57,32 @@ define(["jquery", "underscore", "js/views/modals/base_modal", "js/spec_helpers/m
}; };
afterEach(function() { afterEach(function() {
if (nestedModal && modal_helpers.isShowingModal(nestedModal)) { if (nestedModal && ModelHelpers.isShowingModal(nestedModal)) {
nestedModal.hide(); nestedModal.hide();
} }
}); });
it('is visible after show is called', function () { it('is visible after show is called', function () {
showNestedModal(); showNestedModal();
expect(modal_helpers.isShowingModal(nestedModal)).toBeTruthy(); expect(ModelHelpers.isShowingModal(nestedModal)).toBeTruthy();
}); });
it('is removed after hide is called', function () { it('is removed after hide is called', function () {
showNestedModal(); showNestedModal();
nestedModal.hide(); nestedModal.hide();
expect(modal_helpers.isShowingModal(nestedModal)).toBeFalsy(); expect(ModelHelpers.isShowingModal(nestedModal)).toBeFalsy();
// Verify that the parent modal is still showing // Verify that the parent modal is still showing
expect(modal_helpers.isShowingModal(modal)).toBeTruthy(); expect(ModelHelpers.isShowingModal(modal)).toBeTruthy();
}); });
it('is removed after cancel is clicked', function () { it('is removed after cancel is clicked', function () {
showNestedModal(); showNestedModal();
modal_helpers.cancelModal(nestedModal); ModelHelpers.cancelModal(nestedModal);
expect(modal_helpers.isShowingModal(nestedModal)).toBeFalsy(); expect(ModelHelpers.isShowingModal(nestedModal)).toBeFalsy();
// Verify that the parent modal is still showing // Verify that the parent modal is still showing
expect(modal_helpers.isShowingModal(modal)).toBeTruthy(); expect(ModelHelpers.isShowingModal(modal)).toBeTruthy();
}); });
}); });
}); });
......
define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers", define(["jquery", "underscore", "js/common_helpers/ajax_helpers", "js/spec_helpers/edit_helpers",
"js/views/modals/edit_xblock", "js/models/xblock_info"], "js/views/modals/edit_xblock", "js/models/xblock_info"],
function ($, _, create_sinon, edit_helpers, EditXBlockModal, XBlockInfo) { function ($, _, AjaxHelpers, EditHelpers, EditXBlockModal, XBlockInfo) {
describe("EditXBlockModal", function() { describe("EditXBlockModal", function() {
var model, modal, showModal; var model, modal, showModal;
showModal = function(requests, mockHtml, options) { showModal = function(requests, mockHtml, options) {
var xblockElement = $('.xblock'); var xblockElement = $('.xblock');
return edit_helpers.showEditModal(requests, xblockElement, model, mockHtml, options); return EditHelpers.showEditModal(requests, xblockElement, model, mockHtml, options);
}; };
beforeEach(function () { beforeEach(function () {
edit_helpers.installEditTemplates(); EditHelpers.installEditTemplates();
appendSetFixtures('<div class="xblock" data-locator="mock-xblock"></div>'); appendSetFixtures('<div class="xblock" data-locator="mock-xblock"></div>');
model = new XBlockInfo({ model = new XBlockInfo({
id: 'testCourse/branch/draft/block/verticalFFF', id: 'testCourse/branch/draft/block/verticalFFF',
...@@ -21,7 +21,7 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers ...@@ -21,7 +21,7 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
}); });
afterEach(function() { afterEach(function() {
edit_helpers.cancelModalIfShowing(); EditHelpers.cancelModalIfShowing();
}); });
describe("XBlock Editor", function() { describe("XBlock Editor", function() {
...@@ -30,42 +30,42 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers ...@@ -30,42 +30,42 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
mockXBlockEditorHtml = readFixtures('mock/mock-xblock-editor.underscore'); mockXBlockEditorHtml = readFixtures('mock/mock-xblock-editor.underscore');
beforeEach(function () { beforeEach(function () {
edit_helpers.installMockXBlock(); EditHelpers.installMockXBlock();
}); });
afterEach(function() { afterEach(function() {
edit_helpers.uninstallMockXBlock(); EditHelpers.uninstallMockXBlock();
}); });
it('can show itself', function() { it('can show itself', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
modal = showModal(requests, mockXBlockEditorHtml); modal = showModal(requests, mockXBlockEditorHtml);
expect(edit_helpers.isShowingModal(modal)).toBeTruthy(); expect(EditHelpers.isShowingModal(modal)).toBeTruthy();
edit_helpers.cancelModal(modal); EditHelpers.cancelModal(modal);
expect(edit_helpers.isShowingModal(modal)).toBeFalsy(); expect(EditHelpers.isShowingModal(modal)).toBeFalsy();
}); });
it('does not show the "Save" button', function() { it('does not show the "Save" button', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
modal = showModal(requests, mockXBlockEditorHtml); modal = showModal(requests, mockXBlockEditorHtml);
expect(modal.$('.action-save')).not.toBeVisible(); expect(modal.$('.action-save')).not.toBeVisible();
expect(modal.$('.action-cancel').text()).toBe('OK'); expect(modal.$('.action-cancel').text()).toBe('OK');
}); });
it('shows the correct title', function() { it('shows the correct title', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
modal = showModal(requests, mockXBlockEditorHtml); modal = showModal(requests, mockXBlockEditorHtml);
expect(modal.$('.modal-window-title').text()).toBe('Editing: Component'); expect(modal.$('.modal-window-title').text()).toBe('Editing: Component');
}); });
it('does not show any editor mode buttons', function() { it('does not show any editor mode buttons', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
modal = showModal(requests, mockXBlockEditorHtml); modal = showModal(requests, mockXBlockEditorHtml);
expect(modal.$('.editor-modes a').length).toBe(0); expect(modal.$('.editor-modes a').length).toBe(0);
}); });
it('hides itself and refreshes after save notification', function() { it('hides itself and refreshes after save notification', function() {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
refreshed = false, refreshed = false,
refresh = function() { refresh = function() {
refreshed = true; refreshed = true;
...@@ -73,19 +73,19 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers ...@@ -73,19 +73,19 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
modal = showModal(requests, mockXBlockEditorHtml, { refresh: refresh }); modal = showModal(requests, mockXBlockEditorHtml, { refresh: refresh });
modal.editorView.notifyRuntime('save', { state: 'start' }); modal.editorView.notifyRuntime('save', { state: 'start' });
modal.editorView.notifyRuntime('save', { state: 'end' }); modal.editorView.notifyRuntime('save', { state: 'end' });
expect(edit_helpers.isShowingModal(modal)).toBeFalsy(); expect(EditHelpers.isShowingModal(modal)).toBeFalsy();
expect(refreshed).toBeTruthy(); expect(refreshed).toBeTruthy();
}); });
it('hides itself and does not refresh after cancel notification', function() { it('hides itself and does not refresh after cancel notification', function() {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
refreshed = false, refreshed = false,
refresh = function() { refresh = function() {
refreshed = true; refreshed = true;
}; };
modal = showModal(requests, mockXBlockEditorHtml, { refresh: refresh }); modal = showModal(requests, mockXBlockEditorHtml, { refresh: refresh });
modal.editorView.notifyRuntime('cancel'); modal.editorView.notifyRuntime('cancel');
expect(edit_helpers.isShowingModal(modal)).toBeFalsy(); expect(EditHelpers.isShowingModal(modal)).toBeFalsy();
expect(refreshed).toBeFalsy(); expect(refreshed).toBeFalsy();
}); });
...@@ -95,7 +95,7 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers ...@@ -95,7 +95,7 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
mockCustomButtonsHtml = readFixtures('mock/mock-xblock-editor-with-custom-buttons.underscore'); mockCustomButtonsHtml = readFixtures('mock/mock-xblock-editor-with-custom-buttons.underscore');
it('hides the modal\'s button bar', function() { it('hides the modal\'s button bar', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
modal = showModal(requests, mockCustomButtonsHtml); modal = showModal(requests, mockCustomButtonsHtml);
expect(modal.$('.modal-actions')).toBeHidden(); expect(modal.$('.modal-actions')).toBeHidden();
}); });
...@@ -108,29 +108,29 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers ...@@ -108,29 +108,29 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
mockXModuleEditorHtml = readFixtures('mock/mock-xmodule-editor.underscore'); mockXModuleEditorHtml = readFixtures('mock/mock-xmodule-editor.underscore');
beforeEach(function() { beforeEach(function() {
edit_helpers.installMockXModule(); EditHelpers.installMockXModule();
}); });
afterEach(function () { afterEach(function () {
edit_helpers.uninstallMockXModule(); EditHelpers.uninstallMockXModule();
}); });
it('can render itself', function() { it('can render itself', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
modal = showModal(requests, mockXModuleEditorHtml); modal = showModal(requests, mockXModuleEditorHtml);
expect(edit_helpers.isShowingModal(modal)).toBeTruthy(); expect(EditHelpers.isShowingModal(modal)).toBeTruthy();
edit_helpers.cancelModal(modal); EditHelpers.cancelModal(modal);
expect(edit_helpers.isShowingModal(modal)).toBeFalsy(); expect(EditHelpers.isShowingModal(modal)).toBeFalsy();
}); });
it('shows the correct title', function() { it('shows the correct title', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
modal = showModal(requests, mockXModuleEditorHtml); modal = showModal(requests, mockXModuleEditorHtml);
expect(modal.$('.modal-window-title').text()).toBe('Editing: Component'); expect(modal.$('.modal-window-title').text()).toBe('Editing: Component');
}); });
it('shows the correct default buttons', function() { it('shows the correct default buttons', function() {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
editorButton, editorButton,
settingsButton; settingsButton;
modal = showModal(requests, mockXModuleEditorHtml); modal = showModal(requests, mockXModuleEditorHtml);
...@@ -144,7 +144,7 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers ...@@ -144,7 +144,7 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
}); });
it('can switch tabs', function() { it('can switch tabs', function() {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
editorButton, editorButton,
settingsButton; settingsButton;
modal = showModal(requests, mockXModuleEditorHtml); modal = showModal(requests, mockXModuleEditorHtml);
...@@ -164,13 +164,13 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers ...@@ -164,13 +164,13 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
mockCustomTabsHtml = readFixtures('mock/mock-xmodule-editor-with-custom-tabs.underscore'); mockCustomTabsHtml = readFixtures('mock/mock-xmodule-editor-with-custom-tabs.underscore');
it('hides the modal\'s header', function() { it('hides the modal\'s header', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
modal = showModal(requests, mockCustomTabsHtml); modal = showModal(requests, mockCustomTabsHtml);
expect(modal.$('.modal-header')).toBeHidden(); expect(modal.$('.modal-header')).toBeHidden();
}); });
it('shows the correct title', function() { it('shows the correct title', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
modal = showModal(requests, mockCustomTabsHtml); modal = showModal(requests, mockCustomTabsHtml);
expect(modal.$('.component-name').text()).toBe('Editing: Component'); expect(modal.$('.component-name').text()).toBe('Editing: Component');
}); });
...@@ -183,23 +183,23 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers ...@@ -183,23 +183,23 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
mockXModuleEditorHtml = readFixtures('mock/mock-xmodule-settings-only-editor.underscore'); mockXModuleEditorHtml = readFixtures('mock/mock-xmodule-settings-only-editor.underscore');
beforeEach(function() { beforeEach(function() {
edit_helpers.installMockXModule(); EditHelpers.installMockXModule();
}); });
afterEach(function () { afterEach(function () {
edit_helpers.uninstallMockXModule(); EditHelpers.uninstallMockXModule();
}); });
it('can render itself', function() { it('can render itself', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
modal = showModal(requests, mockXModuleEditorHtml); modal = showModal(requests, mockXModuleEditorHtml);
expect(edit_helpers.isShowingModal(modal)).toBeTruthy(); expect(EditHelpers.isShowingModal(modal)).toBeTruthy();
edit_helpers.cancelModal(modal); EditHelpers.cancelModal(modal);
expect(edit_helpers.isShowingModal(modal)).toBeFalsy(); expect(EditHelpers.isShowingModal(modal)).toBeFalsy();
}); });
it('does not show any mode buttons', function() { it('does not show any mode buttons', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
modal = showModal(requests, mockXModuleEditorHtml); modal = showModal(requests, mockXModuleEditorHtml);
expect(modal.$('.editor-modes li').length).toBe(0); expect(modal.$('.editor-modes li').length).toBe(0);
}); });
......
define(['jquery', 'underscore', 'js/spec_helpers/validation_helpers', 'js/views/modals/validation_error_modal'], define(['jquery', 'underscore', 'js/spec_helpers/validation_helpers', 'js/views/modals/validation_error_modal'],
function ($, _, validation_helpers, ValidationErrorModal) { function ($, _, ValidationHelpers, ValidationErrorModal) {
describe('ValidationErrorModal', function() { describe('ValidationErrorModal', function() {
var modal, showModal; var modal, showModal;
...@@ -14,24 +14,24 @@ define(['jquery', 'underscore', 'js/spec_helpers/validation_helpers', 'js/views/ ...@@ -14,24 +14,24 @@ define(['jquery', 'underscore', 'js/spec_helpers/validation_helpers', 'js/views/
/* Before each, install templates required for the base modal /* Before each, install templates required for the base modal
and validation error modal. */ and validation error modal. */
beforeEach(function () { beforeEach(function () {
validation_helpers.installValidationTemplates(); ValidationHelpers.installValidationTemplates();
}); });
afterEach(function() { afterEach(function() {
validation_helpers.hideModalIfShowing(modal); ValidationHelpers.hideModalIfShowing(modal);
}); });
it('is visible after show is called', function () { it('is visible after show is called', function () {
showModal([]); showModal([]);
expect(validation_helpers.isShowingModal(modal)).toBeTruthy(); expect(ValidationHelpers.isShowingModal(modal)).toBeTruthy();
}); });
it('displays none if no error given', function () { it('displays none if no error given', function () {
var errorObjects = []; var errorObjects = [];
showModal(errorObjects); showModal(errorObjects);
expect(validation_helpers.isShowingModal(modal)).toBeTruthy(); expect(ValidationHelpers.isShowingModal(modal)).toBeTruthy();
validation_helpers.checkErrorContents(modal, errorObjects); ValidationHelpers.checkErrorContents(modal, errorObjects);
}); });
it('correctly displays json error message objects', function () { it('correctly displays json error message objects', function () {
...@@ -47,8 +47,8 @@ define(['jquery', 'underscore', 'js/spec_helpers/validation_helpers', 'js/views/ ...@@ -47,8 +47,8 @@ define(['jquery', 'underscore', 'js/spec_helpers/validation_helpers', 'js/views/
]; ];
showModal(errorObjects); showModal(errorObjects);
expect(validation_helpers.isShowingModal(modal)).toBeTruthy(); expect(ValidationHelpers.isShowingModal(modal)).toBeTruthy();
validation_helpers.checkErrorContents(modal, errorObjects); ValidationHelpers.checkErrorContents(modal, errorObjects);
}); });
it('run callback when undo changes button is clicked', function () { it('run callback when undo changes button is clicked', function () {
...@@ -69,8 +69,8 @@ define(['jquery', 'underscore', 'js/spec_helpers/validation_helpers', 'js/views/ ...@@ -69,8 +69,8 @@ define(['jquery', 'underscore', 'js/spec_helpers/validation_helpers', 'js/views/
// Show Modal and click undo changes // Show Modal and click undo changes
showModal(errorObjects, callback); showModal(errorObjects, callback);
expect(validation_helpers.isShowingModal(modal)).toBeTruthy(); expect(ValidationHelpers.isShowingModal(modal)).toBeTruthy();
validation_helpers.undoChanges(modal); ValidationHelpers.undoChanges(modal);
// Wait for the callback to be fired // Wait for the callback to be fired
waitsFor(function () { waitsFor(function () {
...@@ -79,7 +79,7 @@ define(['jquery', 'underscore', 'js/spec_helpers/validation_helpers', 'js/views/ ...@@ -79,7 +79,7 @@ define(['jquery', 'underscore', 'js/spec_helpers/validation_helpers', 'js/views/
// After checking callback fire, check modal hide // After checking callback fire, check modal hide
runs(function () { runs(function () {
expect(validation_helpers.isShowingModal(modal)).toBe(false); expect(ValidationHelpers.isShowingModal(modal)).toBe(false);
}); });
}); });
}); });
......
define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers", define(["jquery", "underscore", "underscore.string", "js/common_helpers/ajax_helpers",
"js/common_helpers/template_helpers", "js/spec_helpers/edit_helpers",
"js/views/pages/container", "js/models/xblock_info", "jquery.simulate"], "js/views/pages/container", "js/models/xblock_info", "jquery.simulate"],
function ($, _, str, create_sinon, edit_helpers, ContainerPage, XBlockInfo) { function ($, _, str, AjaxHelpers, TemplateHelpers, EditHelpers, ContainerPage, XBlockInfo) {
describe("ContainerPage", function() { describe("ContainerPage", function() {
var lastRequest, renderContainerPage, expectComponents, respondWithHtml, var lastRequest, renderContainerPage, expectComponents, respondWithHtml,
...@@ -15,12 +16,12 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -15,12 +16,12 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
beforeEach(function () { beforeEach(function () {
var newDisplayName = 'New Display Name'; var newDisplayName = 'New Display Name';
edit_helpers.installEditTemplates(); EditHelpers.installEditTemplates();
edit_helpers.installTemplate('xblock-string-field-editor'); TemplateHelpers.installTemplate('xblock-string-field-editor');
edit_helpers.installTemplate('container-message'); TemplateHelpers.installTemplate('container-message');
appendSetFixtures(mockContainerPage); appendSetFixtures(mockContainerPage);
edit_helpers.installMockXBlock({ EditHelpers.installMockXBlock({
data: "<p>Some HTML</p>", data: "<p>Some HTML</p>",
metadata: { metadata: {
display_name: newDisplayName display_name: newDisplayName
...@@ -37,14 +38,14 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -37,14 +38,14 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}); });
afterEach(function() { afterEach(function() {
edit_helpers.uninstallMockXBlock(); EditHelpers.uninstallMockXBlock();
}); });
lastRequest = function() { return requests[requests.length - 1]; }; lastRequest = function() { return requests[requests.length - 1]; };
respondWithHtml = function(html) { respondWithHtml = function(html) {
var requestIndex = requests.length - 1; var requestIndex = requests.length - 1;
create_sinon.respondWithJson( AjaxHelpers.respondWithJson(
requests, requests,
{ html: html, "resources": [] }, { html: html, "resources": [] },
requestIndex requestIndex
...@@ -52,10 +53,10 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -52,10 +53,10 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}; };
renderContainerPage = function(test, html, options) { renderContainerPage = function(test, html, options) {
requests = create_sinon.requests(test); requests = AjaxHelpers.requests(test);
containerPage = new ContainerPage(_.extend(options || {}, { containerPage = new ContainerPage(_.extend(options || {}, {
model: model, model: model,
templates: edit_helpers.mockComponentTemplates, templates: EditHelpers.mockComponentTemplates,
el: $('#content') el: $('#content')
})); }));
containerPage.render(); containerPage.render();
...@@ -79,7 +80,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -79,7 +80,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}); });
it('shows a loading indicator', function() { it('shows a loading indicator', function() {
requests = create_sinon.requests(this); requests = AjaxHelpers.requests(this);
containerPage.render(); containerPage.render();
expect(containerPage.$('.ui-loading')).not.toHaveClass('is-hidden'); expect(containerPage.$('.ui-loading')).not.toHaveClass('is-hidden');
respondWithHtml(mockContainerXBlockHtml); respondWithHtml(mockContainerXBlockHtml);
...@@ -113,7 +114,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -113,7 +114,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
getDisplayNameWrapper; getDisplayNameWrapper;
afterEach(function() { afterEach(function() {
edit_helpers.cancelModalIfShowing(); EditHelpers.cancelModalIfShowing();
}); });
getDisplayNameWrapper = function() { getDisplayNameWrapper = function() {
...@@ -131,30 +132,30 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -131,30 +132,30 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
// Expect a request to be made to show the studio view for the container // 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(); expect(str.startsWith(lastRequest().url, '/xblock/locator-container/studio_view')).toBeTruthy();
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
html: mockContainerXBlockHtml, html: mockContainerXBlockHtml,
resources: [] resources: []
}); });
expect(edit_helpers.isShowingModal()).toBeTruthy(); expect(EditHelpers.isShowingModal()).toBeTruthy();
// Expect the correct title to be shown // Expect the correct title to be shown
expect(edit_helpers.getModalTitle()).toBe('Editing: Test Container'); expect(EditHelpers.getModalTitle()).toBe('Editing: Test Container');
// Press the save button and respond with a success message to the save // Press the save button and respond with a success message to the save
edit_helpers.pressModalButton('.action-save'); EditHelpers.pressModalButton('.action-save');
create_sinon.respondWithJson(requests, { }); AjaxHelpers.respondWithJson(requests, { });
expect(edit_helpers.isShowingModal()).toBeFalsy(); expect(EditHelpers.isShowingModal()).toBeFalsy();
// Expect the last request be to refresh the container page // Expect the last request be to refresh the container page
expect(str.startsWith(lastRequest().url, expect(str.startsWith(lastRequest().url,
'/xblock/locator-container/container_preview')).toBeTruthy(); '/xblock/locator-container/container_preview')).toBeTruthy();
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
html: mockUpdatedContainerXBlockHtml, html: mockUpdatedContainerXBlockHtml,
resources: [] resources: []
}); });
// Respond to the subsequent xblock info fetch request. // Respond to the subsequent xblock info fetch request.
create_sinon.respondWithJson(requests, {"display_name": updatedDisplayName}); AjaxHelpers.respondWithJson(requests, {"display_name": updatedDisplayName});
// Expect the title to have been updated // Expect the title to have been updated
expect(displayNameElement.text().trim()).toBe(updatedDisplayName); expect(displayNameElement.text().trim()).toBe(updatedDisplayName);
...@@ -164,20 +165,20 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -164,20 +165,20 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
var displayNameInput, displayNameWrapper; var displayNameInput, displayNameWrapper;
renderContainerPage(this, mockContainerXBlockHtml); renderContainerPage(this, mockContainerXBlockHtml);
displayNameWrapper = getDisplayNameWrapper(); displayNameWrapper = getDisplayNameWrapper();
displayNameInput = edit_helpers.inlineEdit(displayNameWrapper, updatedDisplayName); displayNameInput = EditHelpers.inlineEdit(displayNameWrapper, updatedDisplayName);
displayNameInput.change(); displayNameInput.change();
// This is the response for the change operation. // This is the response for the change operation.
create_sinon.respondWithJson(requests, { }); AjaxHelpers.respondWithJson(requests, { });
// This is the response for the subsequent fetch operation. // This is the response for the subsequent fetch operation.
create_sinon.respondWithJson(requests, {"display_name": updatedDisplayName}); AjaxHelpers.respondWithJson(requests, {"display_name": updatedDisplayName});
edit_helpers.verifyInlineEditChange(displayNameWrapper, updatedDisplayName); EditHelpers.verifyInlineEditChange(displayNameWrapper, updatedDisplayName);
expect(containerPage.model.get('display_name')).toBe(updatedDisplayName); expect(containerPage.model.get('display_name')).toBe(updatedDisplayName);
}); });
}); });
describe("Editing an xblock", function() { describe("Editing an xblock", function() {
afterEach(function() { afterEach(function() {
edit_helpers.cancelModalIfShowing(); EditHelpers.cancelModalIfShowing();
}); });
it('can show an edit modal for a child xblock', function() { it('can show an edit modal for a child xblock', function() {
...@@ -189,11 +190,11 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -189,11 +190,11 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
editButtons[0].click(); editButtons[0].click();
// Make sure that the correct xblock is requested to be edited // Make sure that the correct xblock is requested to be edited
expect(str.startsWith(lastRequest().url, '/xblock/locator-component-A1/studio_view')).toBeTruthy(); expect(str.startsWith(lastRequest().url, '/xblock/locator-component-A1/studio_view')).toBeTruthy();
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
html: mockXBlockEditorHtml, html: mockXBlockEditorHtml,
resources: [] resources: []
}); });
expect(edit_helpers.isShowingModal()).toBeTruthy(); expect(EditHelpers.isShowingModal()).toBeTruthy();
}); });
it('can show an edit modal for a child xblock with broken JavaScript', function() { it('can show an edit modal for a child xblock with broken JavaScript', function() {
...@@ -201,11 +202,11 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -201,11 +202,11 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
renderContainerPage(this, mockBadContainerXBlockHtml); renderContainerPage(this, mockBadContainerXBlockHtml);
editButtons = containerPage.$('.wrapper-xblock .edit-button'); editButtons = containerPage.$('.wrapper-xblock .edit-button');
editButtons[0].click(); editButtons[0].click();
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
html: mockXBlockEditorHtml, html: mockXBlockEditorHtml,
resources: [] resources: []
}); });
expect(edit_helpers.isShowingModal()).toBeTruthy(); expect(EditHelpers.isShowingModal()).toBeTruthy();
}); });
}); });
...@@ -214,7 +215,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -214,7 +215,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
newDisplayName = 'New Display Name'; newDisplayName = 'New Display Name';
beforeEach(function () { beforeEach(function () {
edit_helpers.installMockXModule({ EditHelpers.installMockXModule({
data: "<p>Some HTML</p>", data: "<p>Some HTML</p>",
metadata: { metadata: {
display_name: newDisplayName display_name: newDisplayName
...@@ -223,8 +224,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -223,8 +224,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}); });
afterEach(function() { afterEach(function() {
edit_helpers.uninstallMockXModule(); EditHelpers.uninstallMockXModule();
edit_helpers.cancelModalIfShowing(); EditHelpers.cancelModalIfShowing();
}); });
it('can save changes to settings', function() { it('can save changes to settings', function() {
...@@ -235,7 +236,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -235,7 +236,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
// The container should have rendered six mock xblocks // The container should have rendered six mock xblocks
expect(editButtons.length).toBe(6); expect(editButtons.length).toBe(6);
editButtons[0].click(); editButtons[0].click();
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
html: mockXModuleEditor, html: mockXModuleEditor,
resources: [] resources: []
}); });
...@@ -249,7 +250,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -249,7 +250,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
// Press the save button // Press the save button
modal.find('.action-save').click(); modal.find('.action-save').click();
// Respond to the save // Respond to the save
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
id: model.id id: model.id
}); });
...@@ -278,7 +279,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -278,7 +279,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
promptSpy; promptSpy;
beforeEach(function() { beforeEach(function() {
promptSpy = edit_helpers.createPromptSpy(); promptSpy = EditHelpers.createPromptSpy();
}); });
clickDelete = function(componentIndex, clickNo) { clickDelete = function(componentIndex, clickNo) {
...@@ -291,20 +292,20 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -291,20 +292,20 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
deleteButtons[componentIndex].click(); deleteButtons[componentIndex].click();
// click the 'yes' or 'no' button in the prompt // click the 'yes' or 'no' button in the prompt
edit_helpers.confirmPrompt(promptSpy, clickNo); EditHelpers.confirmPrompt(promptSpy, clickNo);
}; };
deleteComponent = function(componentIndex) { deleteComponent = function(componentIndex) {
clickDelete(componentIndex); clickDelete(componentIndex);
create_sinon.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
// second to last request contains given component's id (to delete the component) // second to last request contains given component's id (to delete the component)
create_sinon.expectJsonRequest(requests, 'DELETE', AjaxHelpers.expectJsonRequest(requests, 'DELETE',
'/xblock/locator-component-' + GROUP_TO_TEST + (componentIndex + 1), '/xblock/locator-component-' + GROUP_TO_TEST + (componentIndex + 1),
null, requests.length - 2); null, requests.length - 2);
// final request to refresh the xblock info // final request to refresh the xblock info
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/locator-container'); AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/locator-container');
}; };
deleteComponentWithSuccess = function(componentIndex) { deleteComponentWithSuccess = function(componentIndex) {
...@@ -335,13 +336,13 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -335,13 +336,13 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it("can delete an xblock with broken JavaScript", function() { it("can delete an xblock with broken JavaScript", function() {
renderContainerPage(this, mockBadContainerXBlockHtml); renderContainerPage(this, mockBadContainerXBlockHtml);
containerPage.$('.delete-button').first().click(); containerPage.$('.delete-button').first().click();
edit_helpers.confirmPrompt(promptSpy); EditHelpers.confirmPrompt(promptSpy);
create_sinon.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
// expect the second to last request to be a delete of the xblock // expect the second to last request to be a delete of the xblock
create_sinon.expectJsonRequest(requests, 'DELETE', '/xblock/locator-broken-javascript', AjaxHelpers.expectJsonRequest(requests, 'DELETE', '/xblock/locator-broken-javascript',
null, requests.length - 2); null, requests.length - 2);
// expect the last request to be a fetch of the xblock info for the parent container // expect the last request to be a fetch of the xblock info for the parent container
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/locator-container'); AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/locator-container');
}); });
it('does not delete when clicking No in prompt', function () { it('does not delete when clicking No in prompt', function () {
...@@ -361,21 +362,21 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -361,21 +362,21 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}); });
it('shows a notification during the delete operation', function() { it('shows a notification during the delete operation', function() {
var notificationSpy = edit_helpers.createNotificationSpy(); var notificationSpy = EditHelpers.createNotificationSpy();
renderContainerPage(this, mockContainerXBlockHtml); renderContainerPage(this, mockContainerXBlockHtml);
clickDelete(0); clickDelete(0);
edit_helpers.verifyNotificationShowing(notificationSpy, /Deleting/); EditHelpers.verifyNotificationShowing(notificationSpy, /Deleting/);
create_sinon.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
edit_helpers.verifyNotificationHidden(notificationSpy); EditHelpers.verifyNotificationHidden(notificationSpy);
}); });
it('does not delete an xblock upon failure', function () { it('does not delete an xblock upon failure', function () {
var notificationSpy = edit_helpers.createNotificationSpy(); var notificationSpy = EditHelpers.createNotificationSpy();
renderContainerPage(this, mockContainerXBlockHtml); renderContainerPage(this, mockContainerXBlockHtml);
clickDelete(0); clickDelete(0);
edit_helpers.verifyNotificationShowing(notificationSpy, /Deleting/); EditHelpers.verifyNotificationShowing(notificationSpy, /Deleting/);
create_sinon.respondWithError(requests); AjaxHelpers.respondWithError(requests);
edit_helpers.verifyNotificationShowing(notificationSpy, /Deleting/); EditHelpers.verifyNotificationShowing(notificationSpy, /Deleting/);
expectComponents(getGroupElement(), allComponentsInGroup); expectComponents(getGroupElement(), allComponentsInGroup);
}); });
}); });
...@@ -400,13 +401,13 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -400,13 +401,13 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
clickDuplicate(componentIndex); clickDuplicate(componentIndex);
// verify content of request // verify content of request
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/', {
'duplicate_source_locator': 'locator-component-' + GROUP_TO_TEST + (componentIndex + 1), 'duplicate_source_locator': 'locator-component-' + GROUP_TO_TEST + (componentIndex + 1),
'parent_locator': 'locator-group-' + GROUP_TO_TEST 'parent_locator': 'locator-group-' + GROUP_TO_TEST
}); });
// send the response // send the response
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
'locator': 'locator-duplicated-component' 'locator': 'locator-duplicated-component'
}); });
...@@ -432,31 +433,31 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -432,31 +433,31 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it("can duplicate an xblock with broken JavaScript", function() { it("can duplicate an xblock with broken JavaScript", function() {
renderContainerPage(this, mockBadContainerXBlockHtml); renderContainerPage(this, mockBadContainerXBlockHtml);
containerPage.$('.duplicate-button').first().click(); containerPage.$('.duplicate-button').first().click();
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/', {
'duplicate_source_locator': 'locator-broken-javascript', 'duplicate_source_locator': 'locator-broken-javascript',
'parent_locator': 'locator-container' 'parent_locator': 'locator-container'
}); });
}); });
it('shows a notification when duplicating', function () { it('shows a notification when duplicating', function () {
var notificationSpy = edit_helpers.createNotificationSpy(); var notificationSpy = EditHelpers.createNotificationSpy();
renderContainerPage(this, mockContainerXBlockHtml); renderContainerPage(this, mockContainerXBlockHtml);
clickDuplicate(0); clickDuplicate(0);
edit_helpers.verifyNotificationShowing(notificationSpy, /Duplicating/); EditHelpers.verifyNotificationShowing(notificationSpy, /Duplicating/);
create_sinon.respondWithJson(requests, {"locator": "new_item"}); AjaxHelpers.respondWithJson(requests, {"locator": "new_item"});
edit_helpers.verifyNotificationHidden(notificationSpy); EditHelpers.verifyNotificationHidden(notificationSpy);
}); });
it('does not duplicate an xblock upon failure', function () { it('does not duplicate an xblock upon failure', function () {
var notificationSpy = edit_helpers.createNotificationSpy(); var notificationSpy = EditHelpers.createNotificationSpy();
renderContainerPage(this, mockContainerXBlockHtml); renderContainerPage(this, mockContainerXBlockHtml);
refreshXBlockSpies = spyOn(containerPage, "refreshXBlock"); refreshXBlockSpies = spyOn(containerPage, "refreshXBlock");
clickDuplicate(0); clickDuplicate(0);
edit_helpers.verifyNotificationShowing(notificationSpy, /Duplicating/); EditHelpers.verifyNotificationShowing(notificationSpy, /Duplicating/);
create_sinon.respondWithError(requests); AjaxHelpers.respondWithError(requests);
expectComponents(getGroupElement(), allComponentsInGroup); expectComponents(getGroupElement(), allComponentsInGroup);
expect(refreshXBlockSpies).not.toHaveBeenCalled(); expect(refreshXBlockSpies).not.toHaveBeenCalled();
edit_helpers.verifyNotificationShowing(notificationSpy, /Duplicating/); EditHelpers.verifyNotificationShowing(notificationSpy, /Duplicating/);
}); });
}); });
...@@ -470,7 +471,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -470,7 +471,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it('sends the correct JSON to the server', function () { it('sends the correct JSON to the server', function () {
renderContainerPage(this, mockContainerXBlockHtml); renderContainerPage(this, mockContainerXBlockHtml);
clickNewComponent(0); clickNewComponent(0);
edit_helpers.verifyXBlockRequest(requests, { EditHelpers.verifyXBlockRequest(requests, {
"category": "discussion", "category": "discussion",
"type": "discussion", "type": "discussion",
"parent_locator": "locator-group-A" "parent_locator": "locator-group-A"
...@@ -478,12 +479,12 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -478,12 +479,12 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}); });
it('shows a notification while creating', function () { it('shows a notification while creating', function () {
var notificationSpy = edit_helpers.createNotificationSpy(); var notificationSpy = EditHelpers.createNotificationSpy();
renderContainerPage(this, mockContainerXBlockHtml); renderContainerPage(this, mockContainerXBlockHtml);
clickNewComponent(0); clickNewComponent(0);
edit_helpers.verifyNotificationShowing(notificationSpy, /Adding/); EditHelpers.verifyNotificationShowing(notificationSpy, /Adding/);
create_sinon.respondWithJson(requests, { }); AjaxHelpers.respondWithJson(requests, { });
edit_helpers.verifyNotificationHidden(notificationSpy); EditHelpers.verifyNotificationHidden(notificationSpy);
}); });
it('does not insert component upon failure', function () { it('does not insert component upon failure', function () {
...@@ -491,7 +492,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -491,7 +492,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
renderContainerPage(this, mockContainerXBlockHtml); renderContainerPage(this, mockContainerXBlockHtml);
clickNewComponent(0); clickNewComponent(0);
requestCount = requests.length; requestCount = requests.length;
create_sinon.respondWithError(requests); AjaxHelpers.respondWithError(requests);
// No new requests should be made to refresh the view // No new requests should be made to refresh the view
expect(requests.length).toBe(requestCount); expect(requests.length).toBe(requestCount);
expectComponents(getGroupElement(), allComponentsInGroup); expectComponents(getGroupElement(), allComponentsInGroup);
...@@ -511,8 +512,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -511,8 +512,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
showTemplatePicker(); showTemplatePicker();
xblockCount = containerPage.$('.studio-xblock-wrapper').length; xblockCount = containerPage.$('.studio-xblock-wrapper').length;
containerPage.$('.new-component-html a')[templateIndex].click(); containerPage.$('.new-component-html a')[templateIndex].click();
edit_helpers.verifyXBlockRequest(requests, expectedRequest); EditHelpers.verifyXBlockRequest(requests, expectedRequest);
create_sinon.respondWithJson(requests, {"locator": "new_item"}); AjaxHelpers.respondWithJson(requests, {"locator": "new_item"});
respondWithHtml(mockXBlockHtml); respondWithHtml(mockXBlockHtml);
expect(containerPage.$('.studio-xblock-wrapper').length).toBe(xblockCount + 1); expect(containerPage.$('.studio-xblock-wrapper').length).toBe(xblockCount + 1);
}; };
......
define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers", define(["jquery", "underscore", "underscore.string", "js/common_helpers/ajax_helpers",
"js/common_helpers/template_helpers", "js/spec_helpers/edit_helpers",
"js/views/feedback_prompt", "js/views/pages/container", "js/views/pages/container_subviews", "js/views/feedback_prompt", "js/views/pages/container", "js/views/pages/container_subviews",
"js/models/xblock_info", "js/views/utils/xblock_utils"], "js/models/xblock_info", "js/views/utils/xblock_utils"],
function ($, _, str, create_sinon, edit_helpers, Prompt, ContainerPage, ContainerSubviews, function ($, _, str, AjaxHelpers, TemplateHelpers, EditHelpers, Prompt, ContainerPage, ContainerSubviews,
XBlockInfo, XBlockUtils) { XBlockInfo, XBlockUtils) {
var VisibilityState = XBlockUtils.VisibilityState; var VisibilityState = XBlockUtils.VisibilityState;
...@@ -13,11 +14,11 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -13,11 +14,11 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
mockContainerXBlockHtml = readFixtures('mock/mock-empty-container-xblock.underscore'); mockContainerXBlockHtml = readFixtures('mock/mock-empty-container-xblock.underscore');
beforeEach(function () { beforeEach(function () {
edit_helpers.installTemplate('xblock-string-field-editor'); TemplateHelpers.installTemplate('xblock-string-field-editor');
edit_helpers.installTemplate('publish-xblock'); TemplateHelpers.installTemplate('publish-xblock');
edit_helpers.installTemplate('publish-history'); TemplateHelpers.installTemplate('publish-history');
edit_helpers.installTemplate('unit-outline'); TemplateHelpers.installTemplate('unit-outline');
edit_helpers.installTemplate('container-message'); TemplateHelpers.installTemplate('container-message');
appendSetFixtures(mockContainerPage); appendSetFixtures(mockContainerPage);
}); });
...@@ -38,11 +39,11 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -38,11 +39,11 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}; };
createContainerPage = function (test, options) { createContainerPage = function (test, options) {
requests = create_sinon.requests(test); requests = AjaxHelpers.requests(test);
model = new XBlockInfo(createXBlockInfo(options), { parse: true }); model = new XBlockInfo(createXBlockInfo(options), { parse: true });
containerPage = new ContainerPage({ containerPage = new ContainerPage({
model: model, model: model,
templates: edit_helpers.mockComponentTemplates, templates: EditHelpers.mockComponentTemplates,
el: $('#content'), el: $('#content'),
isUnitPage: true isUnitPage: true
}); });
...@@ -56,7 +57,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -56,7 +57,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
respondWithHtml = function(html) { respondWithHtml = function(html) {
var requestIndex = requests.length - 1; var requestIndex = requests.length - 1;
create_sinon.respondWithJson( AjaxHelpers.respondWithJson(
requests, requests,
{ html: html, "resources": [] }, { html: html, "resources": [] },
requestIndex requestIndex
...@@ -64,7 +65,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -64,7 +65,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}; };
respondWithJson = function(json, requestIndex) { respondWithJson = function(json, requestIndex) {
create_sinon.respondWithJson( AjaxHelpers.respondWithJson(
requests, requests,
json, json,
requestIndex requestIndex
...@@ -142,7 +143,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -142,7 +143,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
expect(promptSpies.constructor).toHaveBeenCalled(); expect(promptSpies.constructor).toHaveBeenCalled();
promptSpies.constructor.mostRecentCall.args[0].actions.primary.click(promptSpies); promptSpies.constructor.mostRecentCall.args[0].actions.primary.click(promptSpies);
create_sinon.expectJsonRequest(requests, "POST", "/xblock/locator-container", AjaxHelpers.expectJsonRequest(requests, "POST", "/xblock/locator-container",
{"publish": "discard_changes"} {"publish": "discard_changes"}
); );
}; };
...@@ -219,7 +220,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -219,7 +220,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}); });
it('can publish private content', function () { it('can publish private content', function () {
var notificationSpy = edit_helpers.createNotificationSpy(); var notificationSpy = EditHelpers.createNotificationSpy();
renderContainerPage(this, mockContainerXBlockHtml); renderContainerPage(this, mockContainerXBlockHtml);
expect(containerPage.$(bitPublishingCss)).not.toHaveClass(hasWarningsClass); expect(containerPage.$(bitPublishingCss)).not.toHaveClass(hasWarningsClass);
expect(containerPage.$(bitPublishingCss)).not.toHaveClass(readyClass); expect(containerPage.$(bitPublishingCss)).not.toHaveClass(readyClass);
...@@ -227,17 +228,17 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -227,17 +228,17 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
// Click publish // Click publish
containerPage.$(publishButtonCss).click(); containerPage.$(publishButtonCss).click();
edit_helpers.verifyNotificationShowing(notificationSpy, /Publishing/); EditHelpers.verifyNotificationShowing(notificationSpy, /Publishing/);
create_sinon.expectJsonRequest(requests, "POST", "/xblock/locator-container", AjaxHelpers.expectJsonRequest(requests, "POST", "/xblock/locator-container",
{"publish": "make_public"} {"publish": "make_public"}
); );
// Response to publish call // Response to publish call
respondWithJson({"id": "locator-container", "data": null, "metadata":{}}); respondWithJson({"id": "locator-container", "data": null, "metadata":{}});
edit_helpers.verifyNotificationHidden(notificationSpy); EditHelpers.verifyNotificationHidden(notificationSpy);
create_sinon.expectJsonRequest(requests, "GET", "/xblock/locator-container"); AjaxHelpers.expectJsonRequest(requests, "GET", "/xblock/locator-container");
// Response to fetch // Response to fetch
respondWithJson(createXBlockInfo({ respondWithJson(createXBlockInfo({
published: true, has_changes: false, visibility_state: VisibilityState.ready published: true, has_changes: false, visibility_state: VisibilityState.ready
...@@ -258,7 +259,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -258,7 +259,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
var numRequests = requests.length; var numRequests = requests.length;
// Respond with failure // Respond with failure
create_sinon.respondWithError(requests); AjaxHelpers.respondWithError(requests);
expect(requests.length).toEqual(numRequests); expect(requests.length).toEqual(numRequests);
...@@ -271,7 +272,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -271,7 +272,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it('can discard changes', function () { it('can discard changes', function () {
var notificationSpy, renderPageSpy, numRequests; var notificationSpy, renderPageSpy, numRequests;
createContainerPage(this); createContainerPage(this);
notificationSpy = edit_helpers.createNotificationSpy(); notificationSpy = EditHelpers.createNotificationSpy();
renderPageSpy = spyOn(containerPage.xblockPublisher, 'renderPage').andCallThrough(); renderPageSpy = spyOn(containerPage.xblockPublisher, 'renderPage').andCallThrough();
sendDiscardChangesToServer(); sendDiscardChangesToServer();
...@@ -279,7 +280,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -279,7 +280,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
// Respond with success. // Respond with success.
respondWithJson({"id": "locator-container"}); respondWithJson({"id": "locator-container"});
edit_helpers.verifyNotificationHidden(notificationSpy); EditHelpers.verifyNotificationHidden(notificationSpy);
// Verify other requests are sent to the server to update page state. // Verify other requests are sent to the server to update page state.
// Response to fetch, specifying the very next request (as multiple requests will be sent to server) // Response to fetch, specifying the very next request (as multiple requests will be sent to server)
...@@ -297,7 +298,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -297,7 +298,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
numRequests = requests.length; numRequests = requests.length;
// Respond with failure // Respond with failure
create_sinon.respondWithError(requests); AjaxHelpers.respondWithError(requests);
expect(requests.length).toEqual(numRequests); expect(requests.length).toEqual(numRequests);
expect(containerPage.$(discardChangesButtonCss)).not.toHaveClass('is-disabled'); expect(containerPage.$(discardChangesButtonCss)).not.toHaveClass('is-disabled');
...@@ -393,14 +394,14 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -393,14 +394,14 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
// If removing explicit staff lock with no implicit staff lock, click 'Yes' to confirm // If removing explicit staff lock with no implicit staff lock, click 'Yes' to confirm
if (!isStaffOnly && !containerPage.model.get('ancestor_has_staff_lock')) { if (!isStaffOnly && !containerPage.model.get('ancestor_has_staff_lock')) {
edit_helpers.confirmPrompt(promptSpy); EditHelpers.confirmPrompt(promptSpy);
} }
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/locator-container', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/locator-container', {
publish: 'republish', publish: 'republish',
metadata: { visible_to_staff_only: isStaffOnly ? true : null } metadata: { visible_to_staff_only: isStaffOnly ? true : null }
}); });
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
data: null, data: null,
id: "locator-container", id: "locator-container",
metadata: { metadata: {
...@@ -408,13 +409,13 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -408,13 +409,13 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
} }
}); });
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/locator-container'); AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/locator-container');
if (isStaffOnly || containerPage.model.get('ancestor_has_staff_lock')) { if (isStaffOnly || containerPage.model.get('ancestor_has_staff_lock')) {
newVisibilityState = VisibilityState.staffOnly; newVisibilityState = VisibilityState.staffOnly;
} else { } else {
newVisibilityState = VisibilityState.live; newVisibilityState = VisibilityState.live;
} }
create_sinon.respondWithJson(requests, createXBlockInfo({ AjaxHelpers.respondWithJson(requests, createXBlockInfo({
published: containerPage.model.get('published'), published: containerPage.model.get('published'),
has_explicit_staff_lock: isStaffOnly, has_explicit_staff_lock: isStaffOnly,
visibility_state: newVisibilityState, visibility_state: newVisibilityState,
...@@ -423,11 +424,12 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -423,11 +424,12 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}; };
verifyStaffOnly = function(isStaffOnly) { verifyStaffOnly = function(isStaffOnly) {
var visibilityCopy = containerPage.$('.wrapper-visibility .copy').text().trim();
if (isStaffOnly) { if (isStaffOnly) {
expect(containerPage.$('.wrapper-visibility .copy').text()).toContain('Staff Only'); expect(visibilityCopy).toContain('Staff Only');
expect(containerPage.$(bitPublishingCss)).toHaveClass(staffOnlyClass); expect(containerPage.$(bitPublishingCss)).toHaveClass(staffOnlyClass);
} else { } else {
expect(containerPage.$('.wrapper-visibility .copy').text().trim()).toBe('Staff and Students'); expect(visibilityCopy).toBe('Staff and Students');
expect(containerPage.$(bitPublishingCss)).not.toHaveClass(staffOnlyClass); expect(containerPage.$(bitPublishingCss)).not.toHaveClass(staffOnlyClass);
verifyExplicitStaffOnly(false); verifyExplicitStaffOnly(false);
verifyImplicitStaffOnly(false); verifyImplicitStaffOnly(false);
...@@ -506,7 +508,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -506,7 +508,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}); });
it("can remove explicit staff only setting without having implicit staff only", function() { it("can remove explicit staff only setting without having implicit staff only", function() {
promptSpy = edit_helpers.createPromptSpy(); promptSpy = EditHelpers.createPromptSpy();
renderContainerPage(this, mockContainerXBlockHtml, { renderContainerPage(this, mockContainerXBlockHtml, {
visibility_state: VisibilityState.staffOnly, visibility_state: VisibilityState.staffOnly,
has_explicit_staff_lock: true, has_explicit_staff_lock: true,
...@@ -517,7 +519,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -517,7 +519,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}); });
it("can remove explicit staff only setting while having implicit staff only", function() { it("can remove explicit staff only setting while having implicit staff only", function() {
promptSpy = edit_helpers.createPromptSpy(); promptSpy = EditHelpers.createPromptSpy();
renderContainerPage(this, mockContainerXBlockHtml, { renderContainerPage(this, mockContainerXBlockHtml, {
visibility_state: VisibilityState.staffOnly, visibility_state: VisibilityState.staffOnly,
ancestor_has_staff_lock: true, ancestor_has_staff_lock: true,
...@@ -532,7 +534,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -532,7 +534,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it("does not refresh if removing staff only is canceled", function() { it("does not refresh if removing staff only is canceled", function() {
var requestCount; var requestCount;
promptSpy = edit_helpers.createPromptSpy(); promptSpy = EditHelpers.createPromptSpy();
renderContainerPage(this, mockContainerXBlockHtml, { renderContainerPage(this, mockContainerXBlockHtml, {
visibility_state: VisibilityState.staffOnly, visibility_state: VisibilityState.staffOnly,
has_explicit_staff_lock: true, has_explicit_staff_lock: true,
...@@ -540,7 +542,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -540,7 +542,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
}); });
requestCount = requests.length; requestCount = requests.length;
containerPage.$('.action-staff-lock').click(); containerPage.$('.action-staff-lock').click();
edit_helpers.confirmPrompt(promptSpy, true); // Click 'No' to cancel EditHelpers.confirmPrompt(promptSpy, true); // Click 'No' to cancel
expect(requests.length).toBe(requestCount); expect(requests.length).toBe(requestCount);
verifyExplicitStaffOnly(true); verifyExplicitStaffOnly(true);
verifyStaffOnly(true); verifyStaffOnly(true);
...@@ -551,7 +553,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -551,7 +553,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
renderContainerPage(this, mockContainerXBlockHtml); renderContainerPage(this, mockContainerXBlockHtml);
containerPage.$('.lock-checkbox').click(); containerPage.$('.lock-checkbox').click();
requestCount = requests.length; requestCount = requests.length;
create_sinon.respondWithError(requests); AjaxHelpers.respondWithError(requests);
expect(requests.length).toBe(requestCount); expect(requests.length).toBe(requestCount);
verifyStaffOnly(false); verifyStaffOnly(false);
}); });
...@@ -588,7 +590,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -588,7 +590,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
describe("Message Area", function() { describe("Message Area", function() {
var messageSelector = '.container-message .warning', var messageSelector = '.container-message .warning',
warningMessage = 'Caution: The last published version of this unit is live. By publishing changes you will change the student experience.'; warningMessage = 'Caution: The last published version of this unit is live. ' +
'By publishing changes you will change the student experience.';
it('is empty for a unit that is not currently visible to students', function() { it('is empty for a unit that is not currently visible to students', function() {
renderContainerPage(this, mockContainerXBlockHtml, { renderContainerPage(this, mockContainerXBlockHtml, {
......
define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers", "js/views/utils/view_utils", define(["jquery", "js/common_helpers/ajax_helpers", "js/views/utils/view_utils", "js/views/pages/course_outline",
"js/views/pages/course_outline", "js/models/xblock_outline_info", "js/utils/date_utils", "js/spec_helpers/edit_helpers"], "js/models/xblock_outline_info", "js/utils/date_utils", "js/spec_helpers/edit_helpers",
function ($, create_sinon, view_helpers, ViewUtils, CourseOutlinePage, XBlockOutlineInfo, DateUtils, edit_helpers) { "js/common_helpers/template_helpers"],
function($, AjaxHelpers, ViewUtils, CourseOutlinePage, XBlockOutlineInfo, DateUtils, EditHelpers, TemplateHelpers) {
describe("CourseOutlinePage", function() { describe("CourseOutlinePage", function() {
var createCourseOutlinePage, displayNameInput, model, outlinePage, requests, var createCourseOutlinePage, displayNameInput, model, outlinePage, requests,
getItemsOfType, getItemHeaders, verifyItemsExpanded, expandItemsAndVerifyState, collapseItemsAndVerifyState, getItemsOfType, getItemHeaders, verifyItemsExpanded, expandItemsAndVerifyState,
createMockCourseJSON, createMockSectionJSON, createMockSubsectionJSON, verifyTypePublishable, collapseItemsAndVerifyState, createMockCourseJSON, createMockSectionJSON, createMockSubsectionJSON,
mockCourseJSON, mockEmptyCourseJSON, mockSingleSectionCourseJSON, createMockVerticalJSON, verifyTypePublishable, mockCourseJSON, mockEmptyCourseJSON, mockSingleSectionCourseJSON,
createMockVerticalJSON,
mockOutlinePage = readFixtures('mock/mock-course-outline-page.underscore'), mockOutlinePage = readFixtures('mock/mock-course-outline-page.underscore'),
mockRerunNotification = readFixtures('mock/mock-course-rerun-notification.underscore'); mockRerunNotification = readFixtures('mock/mock-course-rerun-notification.underscore');
...@@ -114,7 +116,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -114,7 +116,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
}; };
createCourseOutlinePage = function(test, courseJSON, createOnly) { createCourseOutlinePage = function(test, courseJSON, createOnly) {
requests = create_sinon.requests(test); requests = AjaxHelpers.requests(test);
model = new XBlockOutlineInfo(courseJSON, { parse: true }); model = new XBlockOutlineInfo(courseJSON, { parse: true });
outlinePage = new CourseOutlinePage({ outlinePage = new CourseOutlinePage({
model: model, model: model,
...@@ -148,12 +150,12 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -148,12 +150,12 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
createCourseOutlinePageAndShowUnit(this, mockCourseJSON); createCourseOutlinePageAndShowUnit(this, mockCourseJSON);
getItemHeaders(type).find('.publish-button').click(); getItemHeaders(type).find('.publish-button').click();
$(".wrapper-modal-window .action-publish").click(); $(".wrapper-modal-window .action-publish").click();
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/mock-' + type, { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/mock-' + type, {
publish : 'make_public' publish : 'make_public'
}); });
expect(requests[0].requestHeaders['X-HTTP-Method-Override']).toBe('PATCH'); expect(requests[0].requestHeaders['X-HTTP-Method-Override']).toBe('PATCH');
create_sinon.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section'); AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section');
}); });
it('should show publish button if it is not published and not changed', function() { it('should show publish button if it is not published and not changed', function() {
...@@ -191,9 +193,9 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -191,9 +193,9 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
}; };
beforeEach(function () { beforeEach(function () {
view_helpers.installMockAnalytics(); EditHelpers.installMockAnalytics();
view_helpers.installViewTemplates(); EditHelpers.installViewTemplates();
view_helpers.installTemplates([ TemplateHelpers.installTemplates([
'course-outline', 'xblock-string-field-editor', 'modal-button', 'course-outline', 'xblock-string-field-editor', 'modal-button',
'basic-modal', 'course-outline-modal', 'release-date-editor', 'basic-modal', 'course-outline-modal', 'release-date-editor',
'due-date-editor', 'grading-editor', 'publish-editor', 'due-date-editor', 'grading-editor', 'publish-editor',
...@@ -214,8 +216,8 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -214,8 +216,8 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
}); });
afterEach(function () { afterEach(function () {
view_helpers.removeMockAnalytics(); EditHelpers.removeMockAnalytics();
edit_helpers.cancelModalIfShowing(); EditHelpers.cancelModalIfShowing();
// Clean up after the $.datepicker // Clean up after the $.datepicker
$("#start_date").datepicker( "destroy" ); $("#start_date").datepicker( "destroy" );
$("#due_date").datepicker( "destroy" ); $("#due_date").datepicker( "destroy" );
...@@ -250,8 +252,8 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -250,8 +252,8 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
createCourseOutlinePage(this, mockEmptyCourseJSON); createCourseOutlinePage(this, mockEmptyCourseJSON);
expect($('.wrapper-alert-announcement')).not.toHaveClass('is-hidden'); expect($('.wrapper-alert-announcement')).not.toHaveClass('is-hidden');
$('.dismiss-button').click(); $('.dismiss-button').click();
create_sinon.expectJsonRequest(requests, 'DELETE', 'dummy_dismiss_url'); AjaxHelpers.expectJsonRequest(requests, 'DELETE', 'dummy_dismiss_url');
create_sinon.respondToDelete(requests); AjaxHelpers.respondToDelete(requests);
expect($('.wrapper-alert-announcement')).toHaveClass('is-hidden'); expect($('.wrapper-alert-announcement')).toHaveClass('is-hidden');
}); });
}); });
...@@ -260,17 +262,17 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -260,17 +262,17 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
it('can add a section', function() { it('can add a section', function() {
createCourseOutlinePage(this, mockEmptyCourseJSON); createCourseOutlinePage(this, mockEmptyCourseJSON);
outlinePage.$('.nav-actions .button-new').click(); outlinePage.$('.nav-actions .button-new').click();
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/', {
'category': 'chapter', 'category': 'chapter',
'display_name': 'Section', 'display_name': 'Section',
'parent_locator': 'mock-course' 'parent_locator': 'mock-course'
}); });
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
"locator": 'mock-section', "locator": 'mock-section',
"courseKey": 'slashes:MockCourse' "courseKey": 'slashes:MockCourse'
}); });
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-course'); AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-course');
create_sinon.respondWithJson(requests, mockSingleSectionCourseJSON); AjaxHelpers.respondWithJson(requests, mockSingleSectionCourseJSON);
expect(outlinePage.$('.no-content')).not.toExist(); expect(outlinePage.$('.no-content')).not.toExist();
expect(outlinePage.$('.list-sections li.outline-section').data('locator')).toEqual('mock-section'); expect(outlinePage.$('.list-sections li.outline-section').data('locator')).toEqual('mock-section');
}); });
...@@ -279,18 +281,18 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -279,18 +281,18 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
var sectionElements; var sectionElements;
createCourseOutlinePage(this, mockSingleSectionCourseJSON); createCourseOutlinePage(this, mockSingleSectionCourseJSON);
outlinePage.$('.nav-actions .button-new').click(); outlinePage.$('.nav-actions .button-new').click();
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/', {
'category': 'chapter', 'category': 'chapter',
'display_name': 'Section', 'display_name': 'Section',
'parent_locator': 'mock-course' 'parent_locator': 'mock-course'
}); });
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
"locator": 'mock-section-2', "locator": 'mock-section-2',
"courseKey": 'slashes:MockCourse' "courseKey": 'slashes:MockCourse'
}); });
// Expect the UI to just fetch the new section and repaint it // Expect the UI to just fetch the new section and repaint it
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section-2'); AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section-2');
create_sinon.respondWithJson(requests, AjaxHelpers.respondWithJson(requests,
createMockSectionJSON({id: 'mock-section-2', display_name: 'Mock Section 2'})); createMockSectionJSON({id: 'mock-section-2', display_name: 'Mock Section 2'}));
sectionElements = getItemsOfType('section'); sectionElements = getItemsOfType('section');
expect(sectionElements.length).toBe(2); expect(sectionElements.length).toBe(2);
...@@ -318,17 +320,17 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -318,17 +320,17 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
it('can add a section', function() { it('can add a section', function() {
createCourseOutlinePage(this, mockEmptyCourseJSON); createCourseOutlinePage(this, mockEmptyCourseJSON);
$('.no-content .button-new').click(); $('.no-content .button-new').click();
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/', {
'category': 'chapter', 'category': 'chapter',
'display_name': 'Section', 'display_name': 'Section',
'parent_locator': 'mock-course' 'parent_locator': 'mock-course'
}); });
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
"locator": "mock-section", "locator": "mock-section",
"courseKey": "slashes:MockCourse" "courseKey": "slashes:MockCourse"
}); });
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-course'); AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-course');
create_sinon.respondWithJson(requests, mockSingleSectionCourseJSON); AjaxHelpers.respondWithJson(requests, mockSingleSectionCourseJSON);
expect(outlinePage.$('.no-content')).not.toExist(); expect(outlinePage.$('.no-content')).not.toExist();
expect(outlinePage.$('.list-sections li.outline-section').data('locator')).toEqual('mock-section'); expect(outlinePage.$('.list-sections li.outline-section').data('locator')).toEqual('mock-section');
}); });
...@@ -337,13 +339,13 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -337,13 +339,13 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
var requestCount; var requestCount;
createCourseOutlinePage(this, mockEmptyCourseJSON); createCourseOutlinePage(this, mockEmptyCourseJSON);
$('.no-content .button-new').click(); $('.no-content .button-new').click();
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/', {
'category': 'chapter', 'category': 'chapter',
'display_name': 'Section', 'display_name': 'Section',
'parent_locator': 'mock-course' 'parent_locator': 'mock-course'
}); });
requestCount = requests.length; requestCount = requests.length;
create_sinon.respondWithError(requests); AjaxHelpers.respondWithError(requests);
expect(requests.length).toBe(requestCount); // No additional requests should be made expect(requests.length).toBe(requestCount); // No additional requests should be made
expect(outlinePage.$('.no-content')).not.toHaveClass('is-hidden'); expect(outlinePage.$('.no-content')).not.toHaveClass('is-hidden');
expect(outlinePage.$('.no-content .button-new')).toExist(); expect(outlinePage.$('.no-content .button-new')).toExist();
...@@ -358,43 +360,43 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -358,43 +360,43 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
}; };
it('can be deleted', function() { it('can be deleted', function() {
var promptSpy = view_helpers.createPromptSpy(), requestCount; var promptSpy = EditHelpers.createPromptSpy(), requestCount;
createCourseOutlinePage(this, createMockCourseJSON({}, [ createCourseOutlinePage(this, createMockCourseJSON({}, [
createMockSectionJSON(), createMockSectionJSON(),
createMockSectionJSON({id: 'mock-section-2', display_name: 'Mock Section 2'}) createMockSectionJSON({id: 'mock-section-2', display_name: 'Mock Section 2'})
])); ]));
getItemHeaders('section').find('.delete-button').first().click(); getItemHeaders('section').find('.delete-button').first().click();
view_helpers.confirmPrompt(promptSpy); EditHelpers.confirmPrompt(promptSpy);
requestCount = requests.length; requestCount = requests.length;
create_sinon.expectJsonRequest(requests, 'DELETE', '/xblock/mock-section'); AjaxHelpers.expectJsonRequest(requests, 'DELETE', '/xblock/mock-section');
create_sinon.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
expect(requests.length).toBe(requestCount); // No fetch should be performed expect(requests.length).toBe(requestCount); // No fetch should be performed
expect(outlinePage.$('[data-locator="mock-section"]')).not.toExist(); expect(outlinePage.$('[data-locator="mock-section"]')).not.toExist();
expect(outlinePage.$('[data-locator="mock-section-2"]')).toExist(); expect(outlinePage.$('[data-locator="mock-section-2"]')).toExist();
}); });
it('can be deleted if it is the only section', function() { it('can be deleted if it is the only section', function() {
var promptSpy = view_helpers.createPromptSpy(); var promptSpy = EditHelpers.createPromptSpy();
createCourseOutlinePage(this, mockSingleSectionCourseJSON); createCourseOutlinePage(this, mockSingleSectionCourseJSON);
getItemHeaders('section').find('.delete-button').click(); getItemHeaders('section').find('.delete-button').click();
view_helpers.confirmPrompt(promptSpy); EditHelpers.confirmPrompt(promptSpy);
create_sinon.expectJsonRequest(requests, 'DELETE', '/xblock/mock-section'); AjaxHelpers.expectJsonRequest(requests, 'DELETE', '/xblock/mock-section');
create_sinon.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-course'); AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-course');
create_sinon.respondWithJson(requests, mockEmptyCourseJSON); AjaxHelpers.respondWithJson(requests, mockEmptyCourseJSON);
expect(outlinePage.$('.no-content')).not.toHaveClass('is-hidden'); expect(outlinePage.$('.no-content')).not.toHaveClass('is-hidden');
expect(outlinePage.$('.no-content .button-new')).toExist(); expect(outlinePage.$('.no-content .button-new')).toExist();
}); });
it('remains visible if its deletion fails', function() { it('remains visible if its deletion fails', function() {
var promptSpy = view_helpers.createPromptSpy(), var promptSpy = EditHelpers.createPromptSpy(),
requestCount; requestCount;
createCourseOutlinePage(this, mockSingleSectionCourseJSON); createCourseOutlinePage(this, mockSingleSectionCourseJSON);
getItemHeaders('section').find('.delete-button').click(); getItemHeaders('section').find('.delete-button').click();
view_helpers.confirmPrompt(promptSpy); EditHelpers.confirmPrompt(promptSpy);
create_sinon.expectJsonRequest(requests, 'DELETE', '/xblock/mock-section'); AjaxHelpers.expectJsonRequest(requests, 'DELETE', '/xblock/mock-section');
requestCount = requests.length; requestCount = requests.length;
create_sinon.respondWithError(requests); AjaxHelpers.respondWithError(requests);
expect(requests.length).toBe(requestCount); // No additional requests should be made expect(requests.length).toBe(requestCount); // No additional requests should be made
expect(outlinePage.$('.list-sections li.outline-section').data('locator')).toEqual('mock-section'); expect(outlinePage.$('.list-sections li.outline-section').data('locator')).toEqual('mock-section');
}); });
...@@ -402,18 +404,18 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -402,18 +404,18 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
it('can add a subsection', function() { it('can add a subsection', function() {
createCourseOutlinePage(this, mockCourseJSON); createCourseOutlinePage(this, mockCourseJSON);
getItemsOfType('section').find('> .outline-content > .add-subsection .button-new').click(); getItemsOfType('section').find('> .outline-content > .add-subsection .button-new').click();
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/', {
'category': 'sequential', 'category': 'sequential',
'display_name': 'Subsection', 'display_name': 'Subsection',
'parent_locator': 'mock-section' 'parent_locator': 'mock-section'
}); });
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
"locator": "new-mock-subsection", "locator": "new-mock-subsection",
"courseKey": "slashes:MockCourse" "courseKey": "slashes:MockCourse"
}); });
// Note: verification of the server response and the UI's handling of it // Note: verification of the server response and the UI's handling of it
// is handled in the acceptance tests. // is handled in the acceptance tests.
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section'); AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section');
}); });
...@@ -423,13 +425,13 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -423,13 +425,13 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
sectionModel; sectionModel;
createCourseOutlinePage(this, mockCourseJSON); createCourseOutlinePage(this, mockCourseJSON);
displayNameWrapper = getDisplayNameWrapper(); displayNameWrapper = getDisplayNameWrapper();
displayNameInput = view_helpers.inlineEdit(displayNameWrapper, updatedDisplayName); displayNameInput = EditHelpers.inlineEdit(displayNameWrapper, updatedDisplayName);
displayNameInput.change(); displayNameInput.change();
// This is the response for the change operation. // This is the response for the change operation.
create_sinon.respondWithJson(requests, { }); AjaxHelpers.respondWithJson(requests, { });
// This is the response for the subsequent fetch operation. // This is the response for the subsequent fetch operation.
create_sinon.respondWithJson(requests, {"display_name": updatedDisplayName}); AjaxHelpers.respondWithJson(requests, {"display_name": updatedDisplayName});
view_helpers.verifyInlineEditChange(displayNameWrapper, updatedDisplayName); EditHelpers.verifyInlineEditChange(displayNameWrapper, updatedDisplayName);
sectionModel = outlinePage.model.get('child_info').children[0]; sectionModel = outlinePage.model.get('child_info').children[0];
expect(sectionModel.get('display_name')).toBe(updatedDisplayName); expect(sectionModel.get('display_name')).toBe(updatedDisplayName);
}); });
...@@ -455,7 +457,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -455,7 +457,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
// Staff lock controls are always visible // Staff lock controls are always visible
expect($("#staff_lock")).toExist(); expect($("#staff_lock")).toExist();
$(".wrapper-modal-window .action-save").click(); $(".wrapper-modal-window .action-save").click();
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/mock-section', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/mock-section', {
"metadata":{ "metadata":{
"start":"2015-01-02T00:00:00.000Z" "start":"2015-01-02T00:00:00.000Z"
} }
...@@ -463,7 +465,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -463,7 +465,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
expect(requests[0].requestHeaders['X-HTTP-Method-Override']).toBe('PATCH'); expect(requests[0].requestHeaders['X-HTTP-Method-Override']).toBe('PATCH');
// This is the response for the change operation. // This is the response for the change operation.
create_sinon.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
var mockResponseSectionJSON = createMockSectionJSON({ var mockResponseSectionJSON = createMockSectionJSON({
release_date: 'Jan 02, 2015 at 00:00 UTC' release_date: 'Jan 02, 2015 at 00:00 UTC'
}, [ }, [
...@@ -474,10 +476,10 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -474,10 +476,10 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
}) })
]) ])
]); ]);
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section') AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section');
expect(requests.length).toBe(2); expect(requests.length).toBe(2);
// This is the response for the subsequent fetch operation for the section. // This is the response for the subsequent fetch operation for the section.
create_sinon.respondWithJson(requests, mockResponseSectionJSON); AjaxHelpers.respondWithJson(requests, mockResponseSectionJSON);
expect($(".outline-section .status-release-value")).toContainText("Jan 02, 2015 at 00:00 UTC"); expect($(".outline-section .status-release-value")).toContainText("Jan 02, 2015 at 00:00 UTC");
}); });
...@@ -507,7 +509,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -507,7 +509,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
]), ]),
createMockSectionJSON({has_changes: true}, [ createMockSectionJSON({has_changes: true}, [
createMockSubsectionJSON({has_changes: true}, [ createMockSubsectionJSON({has_changes: true}, [
createMockVerticalJSON({has_changes: true}), createMockVerticalJSON({has_changes: true})
]) ])
]) ])
]), modalWindow; ]), modalWindow;
...@@ -518,7 +520,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -518,7 +520,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
expect(modalWindow.find('.outline-unit').length).toBe(3); expect(modalWindow.find('.outline-unit').length).toBe(3);
expect(_.compact(_.map(modalWindow.find('.outline-unit').text().split("\n"), $.trim))).toEqual( expect(_.compact(_.map(modalWindow.find('.outline-unit').text().split("\n"), $.trim))).toEqual(
['Unit 100', 'Unit 50', 'Unit 1'] ['Unit 100', 'Unit 50', 'Unit 1']
) );
expect(modalWindow.find('.outline-subsection').length).toBe(2); expect(modalWindow.find('.outline-subsection').length).toBe(2);
}); });
}); });
...@@ -538,7 +540,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -538,7 +540,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
}; };
// Contains hard-coded dates because dates are presented in different formats. // Contains hard-coded dates because dates are presented in different formats.
var mockServerValuesJson = createMockSectionJSON({ mockServerValuesJson = createMockSectionJSON({
release_date: 'Jan 01, 2970 at 05:00 UTC' release_date: 'Jan 01, 2970 at 05:00 UTC'
}, [ }, [
createMockSubsectionJSON({ createMockSubsectionJSON({
...@@ -559,15 +561,15 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -559,15 +561,15 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
]); ]);
it('can be deleted', function() { it('can be deleted', function() {
var promptSpy = view_helpers.createPromptSpy(); var promptSpy = EditHelpers.createPromptSpy();
createCourseOutlinePage(this, mockCourseJSON); createCourseOutlinePage(this, mockCourseJSON);
getItemHeaders('subsection').find('.delete-button').click(); getItemHeaders('subsection').find('.delete-button').click();
view_helpers.confirmPrompt(promptSpy); EditHelpers.confirmPrompt(promptSpy);
create_sinon.expectJsonRequest(requests, 'DELETE', '/xblock/mock-subsection'); AjaxHelpers.expectJsonRequest(requests, 'DELETE', '/xblock/mock-subsection');
create_sinon.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
// Note: verification of the server response and the UI's handling of it // Note: verification of the server response and the UI's handling of it
// is handled in the acceptance tests. // is handled in the acceptance tests.
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section'); AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section');
}); });
it('can add a unit', function() { it('can add a unit', function() {
...@@ -575,12 +577,12 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -575,12 +577,12 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
createCourseOutlinePage(this, mockCourseJSON); createCourseOutlinePage(this, mockCourseJSON);
redirectSpy = spyOn(ViewUtils, 'redirect'); redirectSpy = spyOn(ViewUtils, 'redirect');
getItemsOfType('subsection').find('> .outline-content > .add-unit .button-new').click(); getItemsOfType('subsection').find('> .outline-content > .add-unit .button-new').click();
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/', {
'category': 'vertical', 'category': 'vertical',
'display_name': 'Unit', 'display_name': 'Unit',
'parent_locator': 'mock-subsection' 'parent_locator': 'mock-subsection'
}); });
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
"locator": "new-mock-unit", "locator": "new-mock-unit",
"courseKey": "slashes:MockCourse" "courseKey": "slashes:MockCourse"
}); });
...@@ -593,12 +595,12 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -593,12 +595,12 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
subsectionModel; subsectionModel;
createCourseOutlinePage(this, mockCourseJSON); createCourseOutlinePage(this, mockCourseJSON);
displayNameWrapper = getDisplayNameWrapper(); displayNameWrapper = getDisplayNameWrapper();
displayNameInput = view_helpers.inlineEdit(displayNameWrapper, updatedDisplayName); displayNameInput = EditHelpers.inlineEdit(displayNameWrapper, updatedDisplayName);
displayNameInput.change(); displayNameInput.change();
// This is the response for the change operation. // This is the response for the change operation.
create_sinon.respondWithJson(requests, { }); AjaxHelpers.respondWithJson(requests, { });
// This is the response for the subsequent fetch operation for the section. // This is the response for the subsequent fetch operation for the section.
create_sinon.respondWithJson(requests, AjaxHelpers.respondWithJson(requests,
createMockSectionJSON({}, [ createMockSectionJSON({}, [
createMockSubsectionJSON({ createMockSubsectionJSON({
display_name: updatedDisplayName display_name: updatedDisplayName
...@@ -607,7 +609,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -607,7 +609,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
); );
// Find the display name again in the refreshed DOM and verify it // Find the display name again in the refreshed DOM and verify it
displayNameWrapper = getItemHeaders('subsection').find('.wrapper-xblock-field'); displayNameWrapper = getItemHeaders('subsection').find('.wrapper-xblock-field');
view_helpers.verifyInlineEditChange(displayNameWrapper, updatedDisplayName); EditHelpers.verifyInlineEditChange(displayNameWrapper, updatedDisplayName);
subsectionModel = outlinePage.model.get('child_info').children[0].get('child_info').children[0]; subsectionModel = outlinePage.model.get('child_info').children[0].get('child_info').children[0];
expect(subsectionModel.get('display_name')).toBe(updatedDisplayName); expect(subsectionModel.get('display_name')).toBe(updatedDisplayName);
}); });
...@@ -625,7 +627,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -625,7 +627,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
outlinePage.$('.outline-subsection .configure-button').click(); outlinePage.$('.outline-subsection .configure-button').click();
setEditModalValues("7/9/2014", "7/10/2014", "Lab", true); setEditModalValues("7/9/2014", "7/10/2014", "Lab", true);
$(".wrapper-modal-window .action-save").click(); $(".wrapper-modal-window .action-save").click();
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/mock-subsection', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/mock-subsection', {
"graderType":"Lab", "graderType":"Lab",
"publish": "republish", "publish": "republish",
"metadata":{ "metadata":{
...@@ -637,16 +639,24 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -637,16 +639,24 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
expect(requests[0].requestHeaders['X-HTTP-Method-Override']).toBe('PATCH'); expect(requests[0].requestHeaders['X-HTTP-Method-Override']).toBe('PATCH');
// This is the response for the change operation. // This is the response for the change operation.
create_sinon.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section') AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section');
expect(requests.length).toBe(2); expect(requests.length).toBe(2);
// This is the response for the subsequent fetch operation for the section. // This is the response for the subsequent fetch operation for the section.
create_sinon.respondWithJson(requests, mockServerValuesJson); AjaxHelpers.respondWithJson(requests, mockServerValuesJson);
expect($(".outline-subsection .status-release-value")).toContainText("Jul 09, 2014 at 00:00 UTC"); expect($(".outline-subsection .status-release-value")).toContainText(
expect($(".outline-subsection .status-grading-date")).toContainText("Due: Jul 10, 2014 at 00:00 UTC"); "Jul 09, 2014 at 00:00 UTC"
expect($(".outline-subsection .status-grading-value")).toContainText("Lab"); );
expect($(".outline-subsection .status-message-copy")).toContainText("Contains staff only content"); expect($(".outline-subsection .status-grading-date")).toContainText(
"Due: Jul 10, 2014 at 00:00 UTC"
);
expect($(".outline-subsection .status-grading-value")).toContainText(
"Lab"
);
expect($(".outline-subsection .status-message-copy")).toContainText(
"Contains staff only content"
);
expect($(".outline-item .outline-subsection .status-grading-value")).toContainText("Lab"); expect($(".outline-item .outline-subsection .status-grading-value")).toContainText("Lab");
outlinePage.$('.outline-item .outline-subsection .configure-button').click(); outlinePage.$('.outline-item .outline-subsection .configure-button').click();
...@@ -663,14 +673,22 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -663,14 +673,22 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
$(".wrapper-modal-window .action-save").click(); $(".wrapper-modal-window .action-save").click();
// This is the response for the change operation. // This is the response for the change operation.
create_sinon.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
// This is the response for the subsequent fetch operation. // This is the response for the subsequent fetch operation.
create_sinon.respondWithJson(requests, mockServerValuesJson); AjaxHelpers.respondWithJson(requests, mockServerValuesJson);
expect($(".outline-subsection .status-release-value")).toContainText("Jul 09, 2014 at 00:00 UTC"); expect($(".outline-subsection .status-release-value")).toContainText(
expect($(".outline-subsection .status-grading-date")).toContainText("Due: Jul 10, 2014 at 00:00 UTC"); "Jul 09, 2014 at 00:00 UTC"
expect($(".outline-subsection .status-grading-value")).toContainText("Lab"); );
expect($(".outline-subsection .status-message-copy")).toContainText("Contains staff only content"); expect($(".outline-subsection .status-grading-date")).toContainText(
"Due: Jul 10, 2014 at 00:00 UTC"
);
expect($(".outline-subsection .status-grading-value")).toContainText(
"Lab"
);
expect($(".outline-subsection .status-message-copy")).toContainText(
"Contains staff only content"
);
outlinePage.$('.outline-subsection .configure-button').click(); outlinePage.$('.outline-subsection .configure-button').click();
expect($("#start_date").val()).toBe('7/9/2014'); expect($("#start_date").val()).toBe('7/9/2014');
...@@ -689,15 +707,19 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -689,15 +707,19 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
$(".wrapper-modal-window .action-save").click(); $(".wrapper-modal-window .action-save").click();
// This is the response for the change operation. // This is the response for the change operation.
create_sinon.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
// This is the response for the subsequent fetch operation. // This is the response for the subsequent fetch operation.
create_sinon.respondWithJson(requests, AjaxHelpers.respondWithJson(requests,
createMockSectionJSON({}, [createMockSubsectionJSON()]) createMockSectionJSON({}, [createMockSubsectionJSON()])
); );
expect($(".outline-subsection .status-release-value")).not.toContainText("Jul 09, 2014 at 00:00 UTC"); expect($(".outline-subsection .status-release-value")).not.toContainText(
"Jul 09, 2014 at 00:00 UTC"
);
expect($(".outline-subsection .status-grading-date")).not.toExist(); expect($(".outline-subsection .status-grading-date")).not.toExist();
expect($(".outline-subsection .status-grading-value")).not.toExist(); expect($(".outline-subsection .status-grading-value")).not.toExist();
expect($(".outline-subsection .status-message-copy")).not.toContainText("Contains staff only content"); expect($(".outline-subsection .status-message-copy")).not.toContainText(
"Contains staff only content"
);
}); });
verifyTypePublishable('subsection', function (options) { verifyTypePublishable('subsection', function (options) {
...@@ -731,7 +753,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -731,7 +753,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
expect(modalWindow.find('.outline-unit').length).toBe(2); expect(modalWindow.find('.outline-unit').length).toBe(2);
expect(_.compact(_.map(modalWindow.find('.outline-unit').text().split("\n"), $.trim))).toEqual( expect(_.compact(_.map(modalWindow.find('.outline-unit').text().split("\n"), $.trim))).toEqual(
['Unit 100', 'Unit 50'] ['Unit 100', 'Unit 50']
) );
expect(modalWindow.find('.outline-subsection')).not.toExist(); expect(modalWindow.find('.outline-subsection')).not.toExist();
}); });
}); });
...@@ -739,16 +761,16 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -739,16 +761,16 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
// Note: most tests for units can be found in Bok Choy // Note: most tests for units can be found in Bok Choy
describe("Unit", function() { describe("Unit", function() {
it('can be deleted', function() { it('can be deleted', function() {
var promptSpy = view_helpers.createPromptSpy(); var promptSpy = EditHelpers.createPromptSpy();
createCourseOutlinePage(this, mockCourseJSON); createCourseOutlinePage(this, mockCourseJSON);
expandItemsAndVerifyState('subsection'); expandItemsAndVerifyState('subsection');
getItemHeaders('unit').find('.delete-button').click(); getItemHeaders('unit').find('.delete-button').click();
view_helpers.confirmPrompt(promptSpy); EditHelpers.confirmPrompt(promptSpy);
create_sinon.expectJsonRequest(requests, 'DELETE', '/xblock/mock-unit'); AjaxHelpers.expectJsonRequest(requests, 'DELETE', '/xblock/mock-unit');
create_sinon.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
// Note: verification of the server response and the UI's handling of it // Note: verification of the server response and the UI's handling of it
// is handled in the acceptance tests. // is handled in the acceptance tests.
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section'); AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/outline/mock-section');
}); });
it('has a link to the unit page', function() { it('has a link to the unit page', function() {
......
define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers", "js/views/course_rerun", define(["jquery", "js/common_helpers/ajax_helpers", "js/spec_helpers/view_helpers", "js/views/course_rerun",
"js/views/utils/create_course_utils", "js/views/utils/view_utils", "jquery.simulate"], "js/views/utils/create_course_utils", "js/views/utils/view_utils", "jquery.simulate"],
function ($, create_sinon, view_helpers, CourseRerunUtils, CreateCourseUtilsFactory, ViewUtils) { function ($, AjaxHelpers, ViewHelpers, CourseRerunUtils, CreateCourseUtilsFactory, ViewUtils) {
describe("Create course rerun page", function () { describe("Create course rerun page", function () {
var selectors = { var selectors = {
org: '.rerun-course-org', org: '.rerun-course-org',
...@@ -36,14 +36,14 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -36,14 +36,14 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
}; };
beforeEach(function () { beforeEach(function () {
view_helpers.installMockAnalytics(); ViewHelpers.installMockAnalytics();
window.source_course_key = 'test_course_key'; window.source_course_key = 'test_course_key';
appendSetFixtures(mockCreateCourseRerunHTML); appendSetFixtures(mockCreateCourseRerunHTML);
CourseRerunUtils.onReady(); CourseRerunUtils.onReady();
}); });
afterEach(function () { afterEach(function () {
view_helpers.removeMockAnalytics(); ViewHelpers.removeMockAnalytics();
delete window.source_course_key; delete window.source_course_key;
}); });
...@@ -156,11 +156,11 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -156,11 +156,11 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
}); });
it("saves course reruns", function () { it("saves course reruns", function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
var redirectSpy = spyOn(ViewUtils, 'redirect') var redirectSpy = spyOn(ViewUtils, 'redirect')
fillInFields('DemoX', 'DM101', '2014', 'Demo course'); fillInFields('DemoX', 'DM101', '2014', 'Demo course');
$(selectors.save).click(); $(selectors.save).click();
create_sinon.expectJsonRequest(requests, 'POST', '/course/', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/course/', {
source_course_key: 'test_course_key', source_course_key: 'test_course_key',
org: 'DemoX', org: 'DemoX',
number: 'DM101', number: 'DM101',
...@@ -170,17 +170,17 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -170,17 +170,17 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
expect($(selectors.save)).toHaveClass(classes.disabled); expect($(selectors.save)).toHaveClass(classes.disabled);
expect($(selectors.save)).toHaveClass(classes.processing); expect($(selectors.save)).toHaveClass(classes.processing);
expect($(selectors.cancel)).toHaveClass(classes.hidden); expect($(selectors.cancel)).toHaveClass(classes.hidden);
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
url: 'dummy_test_url' url: 'dummy_test_url'
}); });
expect(redirectSpy).toHaveBeenCalledWith('dummy_test_url'); expect(redirectSpy).toHaveBeenCalledWith('dummy_test_url');
}); });
it("displays an error when saving fails", function () { it("displays an error when saving fails", function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
fillInFields('DemoX', 'DM101', '2014', 'Demo course'); fillInFields('DemoX', 'DM101', '2014', 'Demo course');
$(selectors.save).click(); $(selectors.save).click();
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
ErrMsg: 'error message' ErrMsg: 'error message'
}); });
expect($(selectors.errorWrapper)).not.toHaveClass(classes.hidden); expect($(selectors.errorWrapper)).not.toHaveClass(classes.hidden);
...@@ -190,7 +190,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -190,7 +190,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
}); });
it("does not save if there are validation errors", function () { it("does not save if there are validation errors", function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
fillInFields('DemoX', 'DM101', '', 'Demo course'); fillInFields('DemoX', 'DM101', '', 'Demo course');
$(selectors.save).click(); $(selectors.save).click();
expect(requests.length).toBe(0); expect(requests.length).toBe(0);
......
define([ define([
'jquery', 'underscore', 'js/views/pages/group_configurations', 'jquery', 'underscore', 'js/views/pages/group_configurations',
'js/collections/group_configuration', 'js/models/group_configuration', 'js/spec_helpers/edit_helpers' 'js/collections/group_configuration', 'js/common_helpers/template_helpers'
], function ($, _, GroupConfigurationsPage, GroupConfigurationCollection, GroupConfigurationModel, view_helpers) { ], function ($, _, GroupConfigurationsPage, GroupConfigurationCollection, TemplateHelpers) {
'use strict'; 'use strict';
describe('GroupConfigurationsPage', function() { describe('GroupConfigurationsPage', function() {
var mockGroupConfigurationsPage = readFixtures( var mockGroupConfigurationsPage = readFixtures(
...@@ -35,7 +35,7 @@ define([ ...@@ -35,7 +35,7 @@ define([
beforeEach(function () { beforeEach(function () {
setFixtures(mockGroupConfigurationsPage); setFixtures(mockGroupConfigurationsPage);
view_helpers.installTemplates([ TemplateHelpers.installTemplates([
'no-group-configurations', 'group-configuration-edit', 'no-group-configurations', 'group-configuration-edit',
'group-configuration-details' 'group-configuration-details'
]); ]);
...@@ -83,7 +83,7 @@ define([ ...@@ -83,7 +83,7 @@ define([
describe('Check that Group Configuration will focus and expand depending on content of url hash', function() { describe('Check that Group Configuration will focus and expand depending on content of url hash', function() {
beforeEach(function () { beforeEach(function () {
spyOn($.fn, 'focus'); spyOn($.fn, 'focus');
view_helpers.installTemplate('group-configuration-details'); TemplateHelpers.installTemplate('group-configuration-details');
this.view = initializePage(true); this.view = initializePage(true);
}); });
......
define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers", "js/index", define(["jquery", "js/common_helpers/ajax_helpers", "js/spec_helpers/view_helpers", "js/index",
"js/views/utils/view_utils"], "js/views/utils/view_utils"],
function ($, create_sinon, view_helpers, IndexUtils, ViewUtils) { function ($, AjaxHelpers, ViewHelpers, IndexUtils, ViewUtils) {
describe("Course listing page", function () { describe("Course listing page", function () {
var mockIndexPageHTML = readFixtures('mock/mock-index-page.underscore'), fillInFields; var mockIndexPageHTML = readFixtures('mock/mock-index-page.underscore'), fillInFields;
...@@ -12,49 +12,49 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -12,49 +12,49 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
}; };
beforeEach(function () { beforeEach(function () {
view_helpers.installMockAnalytics(); ViewHelpers.installMockAnalytics();
appendSetFixtures(mockIndexPageHTML); appendSetFixtures(mockIndexPageHTML);
IndexUtils.onReady(); IndexUtils.onReady();
}); });
afterEach(function () { afterEach(function () {
view_helpers.removeMockAnalytics(); ViewHelpers.removeMockAnalytics();
delete window.source_course_key; delete window.source_course_key;
}); });
it("can dismiss notifications", function () { it("can dismiss notifications", function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
var reloadSpy = spyOn(ViewUtils, 'reload'); var reloadSpy = spyOn(ViewUtils, 'reload');
$('.dismiss-button').click(); $('.dismiss-button').click();
create_sinon.expectJsonRequest(requests, 'DELETE', 'dummy_dismiss_url'); AjaxHelpers.expectJsonRequest(requests, 'DELETE', 'dummy_dismiss_url');
create_sinon.respondToDelete(requests); AjaxHelpers.respondToDelete(requests);
expect(reloadSpy).toHaveBeenCalled(); expect(reloadSpy).toHaveBeenCalled();
}); });
it("saves new courses", function () { it("saves new courses", function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
var redirectSpy = spyOn(ViewUtils, 'redirect'); var redirectSpy = spyOn(ViewUtils, 'redirect');
$('.new-course-button').click() $('.new-course-button').click()
fillInFields('DemoX', 'DM101', '2014', 'Demo course'); fillInFields('DemoX', 'DM101', '2014', 'Demo course');
$('.new-course-save').click(); $('.new-course-save').click();
create_sinon.expectJsonRequest(requests, 'POST', '/course/', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/course/', {
org: 'DemoX', org: 'DemoX',
number: 'DM101', number: 'DM101',
run: '2014', run: '2014',
display_name: 'Demo course' display_name: 'Demo course'
}); });
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
url: 'dummy_test_url' url: 'dummy_test_url'
}); });
expect(redirectSpy).toHaveBeenCalledWith('dummy_test_url'); expect(redirectSpy).toHaveBeenCalledWith('dummy_test_url');
}); });
it("displays an error when saving fails", function () { it("displays an error when saving fails", function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
$('.new-course-button').click(); $('.new-course-button').click();
fillInFields('DemoX', 'DM101', '2014', 'Demo course'); fillInFields('DemoX', 'DM101', '2014', 'Demo course');
$('.new-course-save').click(); $('.new-course-save').click();
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
ErrMsg: 'error message' ErrMsg: 'error message'
}); });
expect($('.wrap-error')).toHaveClass('is-shown'); expect($('.wrap-error')).toHaveClass('is-shown');
......
define([ "jquery", "js/spec_helpers/create_sinon", "URI", define([ "jquery", "js/common_helpers/ajax_helpers", "URI",
"js/views/paging", "js/views/paging_header", "js/views/paging_footer", "js/views/paging", "js/views/paging_header", "js/views/paging_footer",
"js/models/asset", "js/collections/asset" ], "js/models/asset", "js/collections/asset" ],
function ($, create_sinon, URI, PagingView, PagingHeader, PagingFooter, AssetModel, AssetCollection) { function ($, AjaxHelpers, URI, PagingView, PagingHeader, PagingFooter, AssetModel, AssetCollection) {
var createMockAsset = function(index) { var createMockAsset = function(index) {
var id = 'asset_' + index; var id = 'asset_' + index;
...@@ -50,7 +50,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -50,7 +50,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
var queryParameters = url.query(true); // Returns an object with each query parameter stored as a value var queryParameters = url.query(true); // Returns an object with each query parameter stored as a value
var page = queryParameters.page; var page = queryParameters.page;
var response = page === "0" ? mockFirstPage : mockSecondPage; var response = page === "0" ? mockFirstPage : mockSecondPage;
create_sinon.respondWithJson(requests, response, requestIndex); AjaxHelpers.respondWithJson(requests, response, requestIndex);
}; };
var MockPagingView = PagingView.extend({ var MockPagingView = PagingView.extend({
...@@ -77,7 +77,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -77,7 +77,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
describe("PagingView", function () { describe("PagingView", function () {
describe("setPage", function () { describe("setPage", function () {
it('can set the current page', function () { it('can set the current page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingView.collection.currentPage).toBe(0); expect(pagingView.collection.currentPage).toBe(0);
...@@ -87,7 +87,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -87,7 +87,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('should not change page after a server error', function () { it('should not change page after a server error', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingView.setPage(1); pagingView.setPage(1);
...@@ -98,7 +98,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -98,7 +98,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
describe("nextPage", function () { describe("nextPage", function () {
it('does not move forward after a server error', function () { it('does not move forward after a server error', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingView.nextPage(); pagingView.nextPage();
...@@ -107,7 +107,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -107,7 +107,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('can move to the next page', function () { it('can move to the next page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingView.nextPage(); pagingView.nextPage();
...@@ -116,7 +116,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -116,7 +116,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('can not move forward from the final page', function () { it('can not move forward from the final page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingView.nextPage(); pagingView.nextPage();
...@@ -127,7 +127,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -127,7 +127,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
describe("previousPage", function () { describe("previousPage", function () {
it('can move back a page', function () { it('can move back a page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingView.previousPage(); pagingView.previousPage();
...@@ -136,7 +136,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -136,7 +136,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('can not move back from the first page', function () { it('can not move back from the first page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingView.previousPage(); pagingView.previousPage();
...@@ -144,7 +144,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -144,7 +144,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('does not move back after a server error', function () { it('does not move back after a server error', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingView.previousPage(); pagingView.previousPage();
...@@ -156,7 +156,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -156,7 +156,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
describe("toggleSortOrder", function () { describe("toggleSortOrder", function () {
it('can toggle direction of the current sort', function () { it('can toggle direction of the current sort', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
expect(pagingView.collection.sortDirection).toBe('desc'); expect(pagingView.collection.sortDirection).toBe('desc');
pagingView.toggleSortOrder('date-col'); pagingView.toggleSortOrder('date-col');
respondWithMockAssets(requests); respondWithMockAssets(requests);
...@@ -167,7 +167,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -167,7 +167,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('sets the correct default sort direction for a column', function () { it('sets the correct default sort direction for a column', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.toggleSortOrder('name-col'); pagingView.toggleSortOrder('name-col');
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingView.sortDisplayName()).toBe('Name'); expect(pagingView.sortDisplayName()).toBe('Name');
...@@ -214,7 +214,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -214,7 +214,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('does not move forward if a server error occurs', function () { it('does not move forward if a server error occurs', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingHeader.$('.next-page-link').click(); pagingHeader.$('.next-page-link').click();
...@@ -223,7 +223,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -223,7 +223,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('can move to the next page', function () { it('can move to the next page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingHeader.$('.next-page-link').click(); pagingHeader.$('.next-page-link').click();
...@@ -232,23 +232,23 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -232,23 +232,23 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('should be enabled when there is at least one more page', function () { it('should be enabled when there is at least one more page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingHeader.$('.next-page-link')).not.toHaveClass('is-disabled'); expect(pagingHeader.$('.next-page-link')).not.toHaveClass('is-disabled');
}); });
it('should be disabled on the final page', function () { it('should be disabled on the final page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingHeader.$('.next-page-link')).toHaveClass('is-disabled'); expect(pagingHeader.$('.next-page-link')).toHaveClass('is-disabled');
}); });
it('should be disabled on an empty page', function () { it('should be disabled on an empty page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
create_sinon.respondWithJson(requests, mockEmptyPage); AjaxHelpers.respondWithJson(requests, mockEmptyPage);
expect(pagingHeader.$('.next-page-link')).toHaveClass('is-disabled'); expect(pagingHeader.$('.next-page-link')).toHaveClass('is-disabled');
}); });
}); });
...@@ -261,7 +261,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -261,7 +261,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('does not move back if a server error occurs', function () { it('does not move back if a server error occurs', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingHeader.$('.previous-page-link').click(); pagingHeader.$('.previous-page-link').click();
...@@ -270,7 +270,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -270,7 +270,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('can go back a page', function () { it('can go back a page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingHeader.$('.previous-page-link').click(); pagingHeader.$('.previous-page-link').click();
...@@ -279,30 +279,30 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -279,30 +279,30 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('should be disabled on the first page', function () { it('should be disabled on the first page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingHeader.$('.previous-page-link')).toHaveClass('is-disabled'); expect(pagingHeader.$('.previous-page-link')).toHaveClass('is-disabled');
}); });
it('should be enabled on the second page', function () { it('should be enabled on the second page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingHeader.$('.previous-page-link')).not.toHaveClass('is-disabled'); expect(pagingHeader.$('.previous-page-link')).not.toHaveClass('is-disabled');
}); });
it('should be disabled for an empty page', function () { it('should be disabled for an empty page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
create_sinon.respondWithJson(requests, mockEmptyPage); AjaxHelpers.respondWithJson(requests, mockEmptyPage);
expect(pagingHeader.$('.previous-page-link')).toHaveClass('is-disabled'); expect(pagingHeader.$('.previous-page-link')).toHaveClass('is-disabled');
}); });
}); });
describe("Page metadata section", function() { describe("Page metadata section", function() {
it('shows the correct metadata for the current page', function () { it('shows the correct metadata for the current page', function () {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
message; message;
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
...@@ -313,7 +313,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -313,7 +313,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('shows the correct metadata when sorted ascending', function () { it('shows the correct metadata when sorted ascending', function () {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
message; message;
pagingView.setPage(0); pagingView.setPage(0);
pagingView.toggleSortOrder('name-col'); pagingView.toggleSortOrder('name-col');
...@@ -327,60 +327,60 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -327,60 +327,60 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
describe("Asset count label", function () { describe("Asset count label", function () {
it('should show correct count on first page', function () { it('should show correct count on first page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingHeader.$('.count-current-shown')).toHaveHtml('1-3'); expect(pagingHeader.$('.count-current-shown')).toHaveHtml('1-3');
}); });
it('should show correct count on second page', function () { it('should show correct count on second page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingHeader.$('.count-current-shown')).toHaveHtml('4-4'); expect(pagingHeader.$('.count-current-shown')).toHaveHtml('4-4');
}); });
it('should show correct count for an empty collection', function () { it('should show correct count for an empty collection', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
create_sinon.respondWithJson(requests, mockEmptyPage); AjaxHelpers.respondWithJson(requests, mockEmptyPage);
expect(pagingHeader.$('.count-current-shown')).toHaveHtml('0-0'); expect(pagingHeader.$('.count-current-shown')).toHaveHtml('0-0');
}); });
}); });
describe("Asset total label", function () { describe("Asset total label", function () {
it('should show correct total on the first page', function () { it('should show correct total on the first page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingHeader.$('.count-total')).toHaveText('4 total'); expect(pagingHeader.$('.count-total')).toHaveText('4 total');
}); });
it('should show correct total on the second page', function () { it('should show correct total on the second page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingHeader.$('.count-total')).toHaveText('4 total'); expect(pagingHeader.$('.count-total')).toHaveText('4 total');
}); });
it('should show zero total for an empty collection', function () { it('should show zero total for an empty collection', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
create_sinon.respondWithJson(requests, mockEmptyPage); AjaxHelpers.respondWithJson(requests, mockEmptyPage);
expect(pagingHeader.$('.count-total')).toHaveText('0 total'); expect(pagingHeader.$('.count-total')).toHaveText('0 total');
}); });
}); });
describe("Sort order label", function () { describe("Sort order label", function () {
it('should show correct initial sort order', function () { it('should show correct initial sort order', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingHeader.$('.sort-order')).toHaveText('Date'); expect(pagingHeader.$('.sort-order')).toHaveText('Date');
}); });
it('should show updated sort order', function () { it('should show updated sort order', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.toggleSortOrder('name-col'); pagingView.toggleSortOrder('name-col');
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingHeader.$('.sort-order')).toHaveText('Name'); expect(pagingHeader.$('.sort-order')).toHaveText('Name');
...@@ -405,7 +405,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -405,7 +405,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('does not move forward if a server error occurs', function () { it('does not move forward if a server error occurs', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingFooter.$('.next-page-link').click(); pagingFooter.$('.next-page-link').click();
...@@ -414,7 +414,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -414,7 +414,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('can move to the next page', function () { it('can move to the next page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingFooter.$('.next-page-link').click(); pagingFooter.$('.next-page-link').click();
...@@ -423,23 +423,23 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -423,23 +423,23 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('should be enabled when there is at least one more page', function () { it('should be enabled when there is at least one more page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingFooter.$('.next-page-link')).not.toHaveClass('is-disabled'); expect(pagingFooter.$('.next-page-link')).not.toHaveClass('is-disabled');
}); });
it('should be disabled on the final page', function () { it('should be disabled on the final page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingFooter.$('.next-page-link')).toHaveClass('is-disabled'); expect(pagingFooter.$('.next-page-link')).toHaveClass('is-disabled');
}); });
it('should be disabled on an empty page', function () { it('should be disabled on an empty page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
create_sinon.respondWithJson(requests, mockEmptyPage); AjaxHelpers.respondWithJson(requests, mockEmptyPage);
expect(pagingFooter.$('.next-page-link')).toHaveClass('is-disabled'); expect(pagingFooter.$('.next-page-link')).toHaveClass('is-disabled');
}); });
}); });
...@@ -452,7 +452,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -452,7 +452,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('does not move back if a server error occurs', function () { it('does not move back if a server error occurs', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingFooter.$('.previous-page-link').click(); pagingFooter.$('.previous-page-link').click();
...@@ -461,7 +461,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -461,7 +461,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('can go back a page', function () { it('can go back a page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingFooter.$('.previous-page-link').click(); pagingFooter.$('.previous-page-link').click();
...@@ -470,62 +470,62 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -470,62 +470,62 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('should be disabled on the first page', function () { it('should be disabled on the first page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingFooter.$('.previous-page-link')).toHaveClass('is-disabled'); expect(pagingFooter.$('.previous-page-link')).toHaveClass('is-disabled');
}); });
it('should be enabled on the second page', function () { it('should be enabled on the second page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingFooter.$('.previous-page-link')).not.toHaveClass('is-disabled'); expect(pagingFooter.$('.previous-page-link')).not.toHaveClass('is-disabled');
}); });
it('should be disabled for an empty page', function () { it('should be disabled for an empty page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
create_sinon.respondWithJson(requests, mockEmptyPage); AjaxHelpers.respondWithJson(requests, mockEmptyPage);
expect(pagingFooter.$('.previous-page-link')).toHaveClass('is-disabled'); expect(pagingFooter.$('.previous-page-link')).toHaveClass('is-disabled');
}); });
}); });
describe("Current page label", function () { describe("Current page label", function () {
it('should show 1 on the first page', function () { it('should show 1 on the first page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingFooter.$('.current-page')).toHaveText('1'); expect(pagingFooter.$('.current-page')).toHaveText('1');
}); });
it('should show 2 on the second page', function () { it('should show 2 on the second page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(1); pagingView.setPage(1);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingFooter.$('.current-page')).toHaveText('2'); expect(pagingFooter.$('.current-page')).toHaveText('2');
}); });
it('should show 1 for an empty collection', function () { it('should show 1 for an empty collection', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
create_sinon.respondWithJson(requests, mockEmptyPage); AjaxHelpers.respondWithJson(requests, mockEmptyPage);
expect(pagingFooter.$('.current-page')).toHaveText('1'); expect(pagingFooter.$('.current-page')).toHaveText('1');
}); });
}); });
describe("Page total label", function () { describe("Page total label", function () {
it('should show the correct value with more than one page', function () { it('should show the correct value with more than one page', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingFooter.$('.total-pages')).toHaveText('2'); expect(pagingFooter.$('.total-pages')).toHaveText('2');
}); });
it('should show page 1 when there are no assets', function () { it('should show page 1 when there are no assets', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
create_sinon.respondWithJson(requests, mockEmptyPage); AjaxHelpers.respondWithJson(requests, mockEmptyPage);
expect(pagingFooter.$('.total-pages')).toHaveText('1'); expect(pagingFooter.$('.total-pages')).toHaveText('1');
}); });
}); });
...@@ -538,14 +538,14 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -538,14 +538,14 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('should initially have a blank page input', function () { it('should initially have a blank page input', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
expect(pagingFooter.$('.page-number-input')).toHaveValue(''); expect(pagingFooter.$('.page-number-input')).toHaveValue('');
}); });
it('should handle invalid page requests', function () { it('should handle invalid page requests', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingFooter.$('.page-number-input').val('abc'); pagingFooter.$('.page-number-input').val('abc');
...@@ -555,18 +555,18 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", ...@@ -555,18 +555,18 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI",
}); });
it('should switch pages via the input field', function () { it('should switch pages via the input field', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingFooter.$('.page-number-input').val('2'); pagingFooter.$('.page-number-input').val('2');
pagingFooter.$('.page-number-input').trigger('change'); pagingFooter.$('.page-number-input').trigger('change');
create_sinon.respondWithJson(requests, mockSecondPage); AjaxHelpers.respondWithJson(requests, mockSecondPage);
expect(pagingView.collection.currentPage).toBe(1); expect(pagingView.collection.currentPage).toBe(1);
expect(pagingFooter.$('.page-number-input')).toHaveValue(''); expect(pagingFooter.$('.page-number-input')).toHaveValue('');
}); });
it('should handle AJAX failures when switching pages via the input field', function () { it('should handle AJAX failures when switching pages via the input field', function () {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
pagingView.setPage(0); pagingView.setPage(0);
respondWithMockAssets(requests); respondWithMockAssets(requests);
pagingFooter.$('.page-number-input').val('2'); pagingFooter.$('.page-number-input').val('2');
......
define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers", "js/views/utils/view_utils", define(["jquery", "js/common_helpers/ajax_helpers", "js/common_helpers/template_helpers",
"js/views/unit_outline", "js/models/xblock_info"], "js/spec_helpers/view_helpers", "js/views/utils/view_utils", "js/views/unit_outline", "js/models/xblock_info"],
function ($, create_sinon, view_helpers, ViewUtils, UnitOutlineView, XBlockInfo) { function ($, AjaxHelpers, TemplateHelpers, ViewHelpers, ViewUtils, UnitOutlineView, XBlockInfo) {
describe("UnitOutlineView", function() { describe("UnitOutlineView", function() {
var createUnitOutlineView, createMockXBlockInfo, var createUnitOutlineView, createMockXBlockInfo,
requests, model, unitOutlineView; requests, model, unitOutlineView;
createUnitOutlineView = function(test, unitJSON, createOnly) { createUnitOutlineView = function(test, unitJSON, createOnly) {
requests = create_sinon.requests(test); requests = AjaxHelpers.requests(test);
model = new XBlockInfo(unitJSON, { parse: true }); model = new XBlockInfo(unitJSON, { parse: true });
unitOutlineView = new UnitOutlineView({ unitOutlineView = new UnitOutlineView({
model: model, model: model,
...@@ -71,14 +71,14 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -71,14 +71,14 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
}; };
beforeEach(function () { beforeEach(function () {
view_helpers.installMockAnalytics(); ViewHelpers.installMockAnalytics();
view_helpers.installViewTemplates(); ViewHelpers.installViewTemplates();
view_helpers.installTemplate('unit-outline'); TemplateHelpers.installTemplate('unit-outline');
appendSetFixtures('<div class="wrapper-unit-overview"></div>'); appendSetFixtures('<div class="wrapper-unit-overview"></div>');
}); });
afterEach(function () { afterEach(function () {
view_helpers.removeMockAnalytics(); ViewHelpers.removeMockAnalytics();
}); });
it('can render itself', function() { it('can render itself', function() {
...@@ -93,12 +93,12 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -93,12 +93,12 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
createUnitOutlineView(this, createMockXBlockInfo('Mock Unit')); createUnitOutlineView(this, createMockXBlockInfo('Mock Unit'));
redirectSpy = spyOn(ViewUtils, 'redirect'); redirectSpy = spyOn(ViewUtils, 'redirect');
unitOutlineView.$('.outline-subsection > .outline-content > .add-unit .button-new').click(); unitOutlineView.$('.outline-subsection > .outline-content > .add-unit .button-new').click();
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/', {
category: 'vertical', category: 'vertical',
display_name: 'Unit', display_name: 'Unit',
parent_locator: 'mock-subsection' parent_locator: 'mock-subsection'
}); });
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
locator: "new-mock-unit", locator: "new-mock-unit",
courseKey: "slashes:MockCourse" courseKey: "slashes:MockCourse"
}); });
...@@ -106,11 +106,11 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -106,11 +106,11 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
}); });
it('refreshes when the XBlockInfo model syncs', function() { it('refreshes when the XBlockInfo model syncs', function() {
var updatedDisplayName = 'Mock Unit Updated', unitHeader; var updatedDisplayName = 'Mock Unit Updated';
createUnitOutlineView(this, createMockXBlockInfo('Mock Unit')); createUnitOutlineView(this, createMockXBlockInfo('Mock Unit'));
unitOutlineView.refresh(); unitOutlineView.refresh();
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/mock-unit'); AjaxHelpers.expectJsonRequest(requests, 'GET', '/xblock/mock-unit');
create_sinon.respondWithJson(requests, AjaxHelpers.respondWithJson(requests,
createMockXBlockInfo(updatedDisplayName)); createMockXBlockInfo(updatedDisplayName));
expect(unitOutlineView.$('.outline-unit .unit-title').first().text().trim()).toBe(updatedDisplayName); expect(unitOutlineView.$('.outline-unit .unit-title').first().text().trim()).toBe(updatedDisplayName);
}); });
......
define(["jquery", "underscore", "js/views/baseview", "js/views/utils/view_utils", "js/spec_helpers/edit_helpers"], define(["jquery", "underscore", "js/views/baseview", "js/views/utils/view_utils", "js/spec_helpers/edit_helpers"],
function ($, _, BaseView, ViewUtils, view_helpers) { function ($, _, BaseView, ViewUtils, ViewHelpers) {
describe("ViewUtils", function() { describe("ViewUtils", function() {
describe("disabled element while running", function() { describe("disabled element while running", function() {
...@@ -22,22 +22,22 @@ define(["jquery", "underscore", "js/views/baseview", "js/views/utils/view_utils" ...@@ -22,22 +22,22 @@ define(["jquery", "underscore", "js/views/baseview", "js/views/utils/view_utils"
var testMessage = "Testing...", var testMessage = "Testing...",
deferred = new $.Deferred(), deferred = new $.Deferred(),
promise = deferred.promise(), promise = deferred.promise(),
notificationSpy = view_helpers.createNotificationSpy(); notificationSpy = ViewHelpers.createNotificationSpy();
ViewUtils.runOperationShowingMessage(testMessage, function() { return promise; }); ViewUtils.runOperationShowingMessage(testMessage, function() { return promise; });
view_helpers.verifyNotificationShowing(notificationSpy, /Testing/); ViewHelpers.verifyNotificationShowing(notificationSpy, /Testing/);
deferred.resolve(); deferred.resolve();
view_helpers.verifyNotificationHidden(notificationSpy); ViewHelpers.verifyNotificationHidden(notificationSpy);
}); });
it("shows progress notification and leaves it showing upon failure", function() { it("shows progress notification and leaves it showing upon failure", function() {
var testMessage = "Testing...", var testMessage = "Testing...",
deferred = new $.Deferred(), deferred = new $.Deferred(),
promise = deferred.promise(), promise = deferred.promise(),
notificationSpy = view_helpers.createNotificationSpy(); notificationSpy = ViewHelpers.createNotificationSpy();
ViewUtils.runOperationShowingMessage(testMessage, function() { return promise; }); ViewUtils.runOperationShowingMessage(testMessage, function() { return promise; });
view_helpers.verifyNotificationShowing(notificationSpy, /Testing/); ViewHelpers.verifyNotificationShowing(notificationSpy, /Testing/);
deferred.fail(); deferred.fail();
view_helpers.verifyNotificationShowing(notificationSpy, /Testing/); ViewHelpers.verifyNotificationShowing(notificationSpy, /Testing/);
}); });
}); });
}); });
......
define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers", define([ "jquery", "underscore", "js/common_helpers/ajax_helpers", "js/spec_helpers/edit_helpers",
"js/views/xblock_editor", "js/models/xblock_info"], "js/views/xblock_editor", "js/models/xblock_info"],
function ($, _, create_sinon, edit_helpers, XBlockEditorView, XBlockInfo) { function ($, _, AjaxHelpers, EditHelpers, XBlockEditorView, XBlockInfo) {
describe("XBlockEditorView", function() { describe("XBlockEditorView", function() {
var model, editor, testDisplayName, mockSaveResponse; var model, editor, testDisplayName, mockSaveResponse;
...@@ -14,7 +14,7 @@ define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helper ...@@ -14,7 +14,7 @@ define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helper
}; };
beforeEach(function () { beforeEach(function () {
edit_helpers.installEditTemplates(); EditHelpers.installEditTemplates();
model = new XBlockInfo({ model = new XBlockInfo({
id: 'testCourse/branch/draft/block/verticalFFF', id: 'testCourse/branch/draft/block/verticalFFF',
display_name: 'Test Unit', display_name: 'Test Unit',
...@@ -29,19 +29,19 @@ define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helper ...@@ -29,19 +29,19 @@ define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helper
var mockXBlockEditorHtml; var mockXBlockEditorHtml;
beforeEach(function () { beforeEach(function () {
edit_helpers.installMockXBlock(); EditHelpers.installMockXBlock();
}); });
afterEach(function() { afterEach(function() {
edit_helpers.uninstallMockXBlock(); EditHelpers.uninstallMockXBlock();
}); });
mockXBlockEditorHtml = readFixtures('mock/mock-xblock-editor.underscore'); mockXBlockEditorHtml = readFixtures('mock/mock-xblock-editor.underscore');
it('can render itself', function() { it('can render itself', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
editor.render(); editor.render();
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
html: mockXBlockEditorHtml, html: mockXBlockEditorHtml,
resources: [] resources: []
}); });
...@@ -57,17 +57,17 @@ define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helper ...@@ -57,17 +57,17 @@ define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helper
mockXModuleEditorHtml = readFixtures('mock/mock-xmodule-editor.underscore'); mockXModuleEditorHtml = readFixtures('mock/mock-xmodule-editor.underscore');
beforeEach(function() { beforeEach(function() {
edit_helpers.installMockXModule(mockSaveResponse); EditHelpers.installMockXModule(mockSaveResponse);
}); });
afterEach(function () { afterEach(function () {
edit_helpers.uninstallMockXModule(); EditHelpers.uninstallMockXModule();
}); });
it('can render itself', function() { it('can render itself', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
editor.render(); editor.render();
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
html: mockXModuleEditorHtml, html: mockXModuleEditorHtml,
resources: [] resources: []
}); });
...@@ -77,9 +77,9 @@ define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helper ...@@ -77,9 +77,9 @@ define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helper
}); });
it('saves any custom metadata', function() { it('saves any custom metadata', function() {
var requests = create_sinon.requests(this), request, response; var requests = AjaxHelpers.requests(this), request, response;
editor.render(); editor.render();
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
html: mockXModuleEditorHtml, html: mockXModuleEditorHtml,
resources: [] resources: []
}); });
...@@ -93,11 +93,11 @@ define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helper ...@@ -93,11 +93,11 @@ define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helper
}); });
it('can render a module with only settings', function() { it('can render a module with only settings', function() {
var requests = create_sinon.requests(this), mockXModuleEditorHtml; var requests = AjaxHelpers.requests(this), mockXModuleEditorHtml;
mockXModuleEditorHtml = readFixtures('mock/mock-xmodule-settings-only-editor.underscore'); mockXModuleEditorHtml = readFixtures('mock/mock-xmodule-settings-only-editor.underscore');
editor.render(); editor.render();
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
html: mockXModuleEditorHtml, html: mockXModuleEditorHtml,
resources: [] resources: []
}); });
......
define([ "jquery", "js/spec_helpers/create_sinon", "URI", "js/views/xblock", "js/models/xblock_info", define([ "jquery", "js/common_helpers/ajax_helpers", "URI", "js/views/xblock", "js/models/xblock_info",
"xmodule", "coffee/src/main", "xblock/cms.runtime.v1"], "xmodule", "coffee/src/main", "xblock/cms.runtime.v1"],
function ($, create_sinon, URI, XBlockView, XBlockInfo) { function ($, AjaxHelpers, URI, XBlockView, XBlockInfo) {
describe("XBlockView", function() { describe("XBlockView", function() {
var model, xblockView, mockXBlockHtml, respondWithMockXBlockFragment; var model, xblockView, mockXBlockHtml, respondWithMockXBlockFragment;
...@@ -20,11 +20,11 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", "js/views/xblock", "js ...@@ -20,11 +20,11 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", "js/views/xblock", "js
respondWithMockXBlockFragment = function(requests, response) { respondWithMockXBlockFragment = function(requests, response) {
var requestIndex = requests.length - 1; var requestIndex = requests.length - 1;
create_sinon.respondWithJson(requests, response, requestIndex); AjaxHelpers.respondWithJson(requests, response, requestIndex);
}; };
it('can render a nested xblock', function() { it('can render a nested xblock', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
xblockView.render(); xblockView.render();
respondWithMockXBlockFragment(requests, { respondWithMockXBlockFragment(requests, {
html: mockXBlockHtml, html: mockXBlockHtml,
...@@ -57,12 +57,12 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", "js/views/xblock", "js ...@@ -57,12 +57,12 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", "js/views/xblock", "js
}; };
it('can render an xblock with no CSS or JavaScript', function() { it('can render an xblock with no CSS or JavaScript', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
postXBlockRequest(requests, []); postXBlockRequest(requests, []);
}); });
it('can render an xblock with required CSS', function() { it('can render an xblock with required CSS', function() {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
mockCssText = "// Just a comment", mockCssText = "// Just a comment",
mockCssUrl = "mock.css", mockCssUrl = "mock.css",
headHtml; headHtml;
...@@ -76,7 +76,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", "js/views/xblock", "js ...@@ -76,7 +76,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", "js/views/xblock", "js
}); });
it('can render an xblock with required JavaScript', function() { it('can render an xblock with required JavaScript', function() {
var requests = create_sinon.requests(this); var requests = AjaxHelpers.requests(this);
postXBlockRequest(requests, [ postXBlockRequest(requests, [
["hash3", { mimetype: "application/javascript", kind: "text", data: "window.test = 100;" }] ["hash3", { mimetype: "application/javascript", kind: "text", data: "window.test = 100;" }]
]); ]);
...@@ -84,7 +84,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", "js/views/xblock", "js ...@@ -84,7 +84,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", "js/views/xblock", "js
}); });
it('can render an xblock with required HTML', function() { it('can render an xblock with required HTML', function() {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
mockHeadTag = "<title>Test Title</title>"; mockHeadTag = "<title>Test Title</title>";
postXBlockRequest(requests, [ postXBlockRequest(requests, [
["hash4", { mimetype: "text/html", placement: "head", data: mockHeadTag }] ["hash4", { mimetype: "text/html", placement: "head", data: mockHeadTag }]
...@@ -93,7 +93,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", "js/views/xblock", "js ...@@ -93,7 +93,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", "js/views/xblock", "js
}); });
it('aborts rendering when a dependent script fails to load', function() { it('aborts rendering when a dependent script fails to load', function() {
var requests = create_sinon.requests(this), var requests = AjaxHelpers.requests(this),
mockJavaScriptUrl = "mock.js", mockJavaScriptUrl = "mock.js",
promise; promise;
spyOn($, 'getScript').andReturn($.Deferred().reject().promise()); spyOn($, 'getScript').andReturn($.Deferred().reject().promise());
......
define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers", "js/spec_helpers/edit_helpers", "js/models/xblock_info", "js/views/xblock_string_field_editor"], define(["jquery", "js/common_helpers/ajax_helpers", "js/common_helpers/template_helpers",
function ($, create_sinon, view_helpers, edit_helpers, XBlockInfo, XBlockStringFieldEditor) { "js/spec_helpers/edit_helpers", "js/models/xblock_info", "js/views/xblock_string_field_editor"],
function ($, AjaxHelpers, TemplateHelpers, EditHelpers, XBlockInfo, XBlockStringFieldEditor) {
describe("XBlockStringFieldEditorView", function () { describe("XBlockStringFieldEditorView", function () {
var initialDisplayName, updatedDisplayName, getXBlockInfo, getFieldEditorView; var initialDisplayName, updatedDisplayName, getXBlockInfo, getFieldEditorView;
...@@ -26,11 +27,13 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -26,11 +27,13 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
beforeEach(function () { beforeEach(function () {
initialDisplayName = "Default Display Name"; initialDisplayName = "Default Display Name";
updatedDisplayName = "Updated Display Name"; updatedDisplayName = "Updated Display Name";
view_helpers.installTemplate('xblock-string-field-editor'); TemplateHelpers.installTemplate('xblock-string-field-editor');
appendSetFixtures( appendSetFixtures(
'<div class="wrapper-xblock-field incontext-editor is-editable"' + '<div class="wrapper-xblock-field incontext-editor is-editable"' +
'data-field="display_name" data-field-display-name="Display Name">' + 'data-field="display_name" data-field-display-name="Display Name">' +
'<h1 class="page-header-title xblock-field-value incontext-editor-value"><span class="title-value">' + initialDisplayName + '</span></h1>' + '<h1 class="page-header-title xblock-field-value incontext-editor-value">' +
'<span class="title-value">' + initialDisplayName + '</span>' +
'</h1>' +
'</div>' '</div>'
); );
}); });
...@@ -39,7 +42,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -39,7 +42,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
var expectPostedNewDisplayName, expectEditCanceled; var expectPostedNewDisplayName, expectEditCanceled;
expectPostedNewDisplayName = function (requests, displayName) { expectPostedNewDisplayName = function (requests, displayName) {
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/my_xblock', { AjaxHelpers.expectJsonRequest(requests, 'POST', '/xblock/my_xblock', {
metadata: { metadata: {
display_name: displayName display_name: displayName
} }
...@@ -48,9 +51,9 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -48,9 +51,9 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
expectEditCanceled = function (test, fieldEditorView, options) { expectEditCanceled = function (test, fieldEditorView, options) {
var requests, initialRequests, displayNameInput; var requests, initialRequests, displayNameInput;
requests = create_sinon.requests(test); requests = AjaxHelpers.requests(test);
initialRequests = requests.length; initialRequests = requests.length;
displayNameInput = edit_helpers.inlineEdit(fieldEditorView.$el, options.newTitle); displayNameInput = EditHelpers.inlineEdit(fieldEditorView.$el, options.newTitle);
if (options.pressEscape) { if (options.pressEscape) {
displayNameInput.simulate("keydown", { keyCode: $.simulate.keyCode.ESCAPE }); displayNameInput.simulate("keydown", { keyCode: $.simulate.keyCode.ESCAPE });
displayNameInput.simulate("keyup", { keyCode: $.simulate.keyCode.ESCAPE }); displayNameInput.simulate("keyup", { keyCode: $.simulate.keyCode.ESCAPE });
...@@ -61,51 +64,51 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers" ...@@ -61,51 +64,51 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
} }
// No requests should be made when the edit is cancelled client-side // No requests should be made when the edit is cancelled client-side
expect(initialRequests).toBe(requests.length); expect(initialRequests).toBe(requests.length);
edit_helpers.verifyInlineEditChange(fieldEditorView.$el, initialDisplayName); EditHelpers.verifyInlineEditChange(fieldEditorView.$el, initialDisplayName);
expect(fieldEditorView.model.get('display_name')).toBe(initialDisplayName); expect(fieldEditorView.model.get('display_name')).toBe(initialDisplayName);
}; };
it('can inline edit the display name', function () { it('can inline edit the display name', function () {
var requests, fieldEditorView; var requests, fieldEditorView;
requests = create_sinon.requests(this); requests = AjaxHelpers.requests(this);
fieldEditorView = getFieldEditorView().render(); fieldEditorView = getFieldEditorView().render();
edit_helpers.inlineEdit(fieldEditorView.$el, updatedDisplayName); EditHelpers.inlineEdit(fieldEditorView.$el, updatedDisplayName);
fieldEditorView.$('button[name=submit]').click(); fieldEditorView.$('button[name=submit]').click();
expectPostedNewDisplayName(requests, updatedDisplayName); expectPostedNewDisplayName(requests, updatedDisplayName);
// This is the response for the change operation. // This is the response for the change operation.
create_sinon.respondWithJson(requests, { }); AjaxHelpers.respondWithJson(requests, { });
// This is the response for the subsequent fetch operation. // This is the response for the subsequent fetch operation.
create_sinon.respondWithJson(requests, {display_name: updatedDisplayName}); AjaxHelpers.respondWithJson(requests, {display_name: updatedDisplayName});
edit_helpers.verifyInlineEditChange(fieldEditorView.$el, updatedDisplayName); EditHelpers.verifyInlineEditChange(fieldEditorView.$el, updatedDisplayName);
}); });
it('does not change the title when a display name update fails', function () { it('does not change the title when a display name update fails', function () {
var requests, fieldEditorView, initialRequests; var requests, fieldEditorView, initialRequests;
requests = create_sinon.requests(this); requests = AjaxHelpers.requests(this);
initialRequests = requests.length; initialRequests = requests.length;
fieldEditorView = getFieldEditorView().render(); fieldEditorView = getFieldEditorView().render();
edit_helpers.inlineEdit(fieldEditorView.$el, updatedDisplayName); EditHelpers.inlineEdit(fieldEditorView.$el, updatedDisplayName);
fieldEditorView.$('button[name=submit]').click(); fieldEditorView.$('button[name=submit]').click();
expectPostedNewDisplayName(requests, updatedDisplayName); expectPostedNewDisplayName(requests, updatedDisplayName);
create_sinon.respondWithError(requests); AjaxHelpers.respondWithError(requests);
// No fetch operation should occur. // No fetch operation should occur.
expect(initialRequests + 1).toBe(requests.length); expect(initialRequests + 1).toBe(requests.length);
edit_helpers.verifyInlineEditChange(fieldEditorView.$el, initialDisplayName, updatedDisplayName); EditHelpers.verifyInlineEditChange(fieldEditorView.$el, initialDisplayName, updatedDisplayName);
}); });
it('trims whitespace from the display name', function () { it('trims whitespace from the display name', function () {
var requests, fieldEditorView; var requests, fieldEditorView;
requests = create_sinon.requests(this); requests = AjaxHelpers.requests(this);
fieldEditorView = getFieldEditorView().render(); fieldEditorView = getFieldEditorView().render();
updatedDisplayName += ' '; updatedDisplayName += ' ';
edit_helpers.inlineEdit(fieldEditorView.$el, updatedDisplayName); EditHelpers.inlineEdit(fieldEditorView.$el, updatedDisplayName);
fieldEditorView.$('button[name=submit]').click(); fieldEditorView.$('button[name=submit]').click();
expectPostedNewDisplayName(requests, updatedDisplayName.trim()); expectPostedNewDisplayName(requests, updatedDisplayName.trim());
// This is the response for the change operation. // This is the response for the change operation.
create_sinon.respondWithJson(requests, { }); AjaxHelpers.respondWithJson(requests, { });
// This is the response for the subsequent fetch operation. // This is the response for the subsequent fetch operation.
create_sinon.respondWithJson(requests, {display_name: updatedDisplayName.trim()}); AjaxHelpers.respondWithJson(requests, {display_name: updatedDisplayName.trim()});
edit_helpers.verifyInlineEditChange(fieldEditorView.$el, updatedDisplayName.trim()); EditHelpers.verifyInlineEditChange(fieldEditorView.$el, updatedDisplayName.trim());
}); });
it('does not change the title when input is the empty string', function () { it('does not change the title when input is the empty string', function () {
......
define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cms.runtime.v1"], define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cms.runtime.v1"],
function (edit_helpers, BaseModal) { function (EditHelpers, BaseModal) {
describe("Studio Runtime v1", function() { describe("Studio Runtime v1", function() {
var runtime; var runtime;
beforeEach(function () { beforeEach(function () {
edit_helpers.installEditTemplates(); EditHelpers.installEditTemplates();
runtime = new window.StudioRuntime.v1(); runtime = new window.StudioRuntime.v1();
}); });
...@@ -21,27 +21,27 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm ...@@ -21,27 +21,27 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm
it('shows save notifications', function() { it('shows save notifications', function() {
var title = "Mock saving...", var title = "Mock saving...",
notificationSpy = edit_helpers.createNotificationSpy(); notificationSpy = EditHelpers.createNotificationSpy();
runtime.notify('save', { runtime.notify('save', {
state: 'start', state: 'start',
message: title message: title
}); });
edit_helpers.verifyNotificationShowing(notificationSpy, title); EditHelpers.verifyNotificationShowing(notificationSpy, title);
runtime.notify('save', { runtime.notify('save', {
state: 'end' state: 'end'
}); });
edit_helpers.verifyNotificationHidden(notificationSpy); EditHelpers.verifyNotificationHidden(notificationSpy);
}); });
it('shows error messages', function() { it('shows error messages', function() {
var title = "Mock Error", var title = "Mock Error",
message = "This is a mock error.", message = "This is a mock error.",
notificationSpy = edit_helpers.createNotificationSpy("Error"); notificationSpy = EditHelpers.createNotificationSpy("Error");
runtime.notify('error', { runtime.notify('error', {
title: title, title: title,
message: message message: message
}); });
edit_helpers.verifyNotificationShowing(notificationSpy, title); EditHelpers.verifyNotificationShowing(notificationSpy, title);
}); });
describe("Modal Dialogs", function() { describe("Modal Dialogs", function() {
...@@ -61,19 +61,19 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm ...@@ -61,19 +61,19 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm
}; };
beforeEach(function () { beforeEach(function () {
edit_helpers.installEditTemplates(); EditHelpers.installEditTemplates();
}); });
afterEach(function() { afterEach(function() {
edit_helpers.hideModalIfShowing(modal); EditHelpers.hideModalIfShowing(modal);
}); });
it('cancels a modal dialog', function () { it('cancels a modal dialog', function () {
showMockModal(); showMockModal();
runtime.notify('modal-shown', modal); runtime.notify('modal-shown', modal);
expect(edit_helpers.isShowingModal(modal)).toBeTruthy(); expect(EditHelpers.isShowingModal(modal)).toBeTruthy();
runtime.notify('cancel'); runtime.notify('cancel');
expect(edit_helpers.isShowingModal(modal)).toBeFalsy(); expect(EditHelpers.isShowingModal(modal)).toBeFalsy();
}); });
}); });
}); });
......
/** /**
* Provides helper methods for invoking Studio editors in Jasmine tests. * Provides helper methods for invoking Studio editors in Jasmine tests.
*/ */
define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers/modal_helpers", define(["jquery", "underscore", "js/common_helpers/ajax_helpers", "js/common_helpers/template_helpers",
"js/views/modals/edit_xblock", "js/collections/component_template", "js/spec_helpers/modal_helpers", "js/views/modals/edit_xblock", "js/collections/component_template",
"xmodule", "coffee/src/main", "xblock/cms.runtime.v1"], "xmodule", "coffee/src/main", "xblock/cms.runtime.v1"],
function($, _, create_sinon, modal_helpers, EditXBlockModal, ComponentTemplates) { function($, _, AjaxHelpers, TemplateHelpers, modal_helpers, EditXBlockModal, ComponentTemplates) {
var installMockXBlock, uninstallMockXBlock, installMockXModule, uninstallMockXModule, var installMockXBlock, uninstallMockXBlock, installMockXModule, uninstallMockXModule,
mockComponentTemplates, installEditTemplates, showEditModal, verifyXBlockRequest; mockComponentTemplates, installEditTemplates, showEditModal, verifyXBlockRequest;
...@@ -72,25 +72,25 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers ...@@ -72,25 +72,25 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
modal_helpers.installModalTemplates(append); modal_helpers.installModalTemplates(append);
// Add templates needed by the add XBlock menu // Add templates needed by the add XBlock menu
modal_helpers.installTemplate('add-xblock-component'); TemplateHelpers.installTemplate('add-xblock-component');
modal_helpers.installTemplate('add-xblock-component-button'); TemplateHelpers.installTemplate('add-xblock-component-button');
modal_helpers.installTemplate('add-xblock-component-menu'); TemplateHelpers.installTemplate('add-xblock-component-menu');
modal_helpers.installTemplate('add-xblock-component-menu-problem'); TemplateHelpers.installTemplate('add-xblock-component-menu-problem');
// Add templates needed by the edit XBlock modal // Add templates needed by the edit XBlock modal
modal_helpers.installTemplate('edit-xblock-modal'); TemplateHelpers.installTemplate('edit-xblock-modal');
modal_helpers.installTemplate('editor-mode-button'); TemplateHelpers.installTemplate('editor-mode-button');
// Add templates needed by the settings editor // Add templates needed by the settings editor
modal_helpers.installTemplate('metadata-editor'); TemplateHelpers.installTemplate('metadata-editor');
modal_helpers.installTemplate('metadata-number-entry', false, 'metadata-number-entry'); TemplateHelpers.installTemplate('metadata-number-entry', false, 'metadata-number-entry');
modal_helpers.installTemplate('metadata-string-entry', false, 'metadata-string-entry'); TemplateHelpers.installTemplate('metadata-string-entry', false, 'metadata-string-entry');
}; };
showEditModal = function(requests, xblockElement, model, mockHtml, options) { showEditModal = function(requests, xblockElement, model, mockHtml, options) {
var modal = new EditXBlockModal({}); var modal = new EditXBlockModal({});
modal.edit(xblockElement, model, options); modal.edit(xblockElement, model, options);
create_sinon.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
html: mockHtml, html: mockHtml,
"resources": [] "resources": []
}); });
......
/** /**
* Provides helper methods for invoking Studio modal windows in Jasmine tests. * Provides helper methods for invoking Studio modal windows in Jasmine tests.
*/ */
define(["jquery", "js/spec_helpers/view_helpers"], define(["jquery", "js/common_helpers/template_helpers", "js/spec_helpers/view_helpers"],
function($, view_helpers) { function($, TemplateHelpers, ViewHelpers) {
var installModalTemplates, getModalElement, getModalTitle, isShowingModal, hideModalIfShowing, var installModalTemplates, getModalElement, getModalTitle, isShowingModal, hideModalIfShowing,
pressModalButton, cancelModal, cancelModalIfShowing; pressModalButton, cancelModal, cancelModalIfShowing;
installModalTemplates = function(append) { installModalTemplates = function(append) {
view_helpers.installViewTemplates(append); ViewHelpers.installViewTemplates(append);
view_helpers.installTemplate('basic-modal'); TemplateHelpers.installTemplate('basic-modal');
view_helpers.installTemplate('modal-button'); TemplateHelpers.installTemplate('modal-button');
}; };
getModalElement = function(modal) { getModalElement = function(modal) {
...@@ -56,7 +56,7 @@ define(["jquery", "js/spec_helpers/view_helpers"], ...@@ -56,7 +56,7 @@ define(["jquery", "js/spec_helpers/view_helpers"],
} }
}; };
return $.extend(view_helpers, { return $.extend(ViewHelpers, {
'getModalElement': getModalElement, 'getModalElement': getModalElement,
'getModalTitle': getModalTitle, 'getModalTitle': getModalTitle,
'installModalTemplates': installModalTemplates, 'installModalTemplates': installModalTemplates,
......
/** /**
* Provides helper methods for invoking Validation modal in Jasmine tests. * Provides helper methods for invoking Validation modal in Jasmine tests.
*/ */
define(['jquery', 'js/spec_helpers/modal_helpers', 'js/spec_helpers/view_helpers'], define(['jquery', 'js/spec_helpers/modal_helpers', 'js/common_helpers/template_helpers'],
function($, modal_helpers, view_helpers) { function($, ModalHelpers, TemplateHelpers) {
var installValidationTemplates, checkErrorContents, undoChanges; var installValidationTemplates, checkErrorContents, undoChanges;
installValidationTemplates = function () { installValidationTemplates = function () {
modal_helpers.installModalTemplates(); ModalHelpers.installModalTemplates();
view_helpers.installTemplate('validation-error-modal'); TemplateHelpers.installTemplate('validation-error-modal');
}; };
checkErrorContents = function(validationModal, errorObjects) { checkErrorContents = function(validationModal, errorObjects) {
...@@ -23,10 +23,10 @@ define(['jquery', 'js/spec_helpers/modal_helpers', 'js/spec_helpers/view_helpers ...@@ -23,10 +23,10 @@ define(['jquery', 'js/spec_helpers/modal_helpers', 'js/spec_helpers/view_helpers
}; };
undoChanges = function(validationModal) { undoChanges = function(validationModal) {
modal_helpers.pressModalButton('.action-undo', validationModal); ModalHelpers.pressModalButton('.action-undo', validationModal);
}; };
return $.extend(modal_helpers, { return $.extend(ModalHelpers, {
'installValidationTemplates': installValidationTemplates, 'installValidationTemplates': installValidationTemplates,
'checkErrorContents': checkErrorContents, 'checkErrorContents': checkErrorContents,
'undoChanges': undoChanges, 'undoChanges': undoChanges,
......
/** /**
* Provides helper methods for invoking Studio modal windows in Jasmine tests. * Provides helper methods for invoking Studio modal windows in Jasmine tests.
*/ */
define(["jquery", "js/views/feedback_notification", "js/views/feedback_prompt"], define(["jquery", "js/views/feedback_notification", "js/views/feedback_prompt", "js/common_helpers/template_helpers"],
function($, NotificationView, Prompt) { function($, NotificationView, Prompt, TemplateHelpers) {
var installTemplate, installTemplates, installViewTemplates, createFeedbackSpy, verifyFeedbackShowing, var installViewTemplates, createFeedbackSpy, verifyFeedbackShowing,
verifyFeedbackHidden, createNotificationSpy, verifyNotificationShowing, verifyFeedbackHidden, createNotificationSpy, verifyNotificationShowing,
verifyNotificationHidden, createPromptSpy, confirmPrompt, inlineEdit, verifyInlineEditChange, verifyNotificationHidden, createPromptSpy, confirmPrompt, inlineEdit, verifyInlineEditChange,
installMockAnalytics, removeMockAnalytics, verifyPromptShowing, verifyPromptHidden; installMockAnalytics, removeMockAnalytics, verifyPromptShowing, verifyPromptHidden;
installTemplate = function(templateName, isFirst, templateId) {
var template = readFixtures(templateName + '.underscore');
if (!templateId) {
templateId = templateName + '-tpl';
}
if (isFirst) {
setFixtures($('<script>', { id: templateId, type: 'text/template' }).text(template));
} else {
appendSetFixtures($('<script>', { id: templateId, type: 'text/template' }).text(template));
}
};
installTemplates = function(templateNames, isFirst) {
if (!$.isArray(templateNames)) {
templateNames = [templateNames];
}
$.each(templateNames, function(index, templateName) {
installTemplate(templateName, isFirst);
if (isFirst) {
isFirst = false;
}
});
};
installViewTemplates = function(append) { installViewTemplates = function(append) {
installTemplate('system-feedback', !append); TemplateHelpers.installTemplate('system-feedback', !append);
appendSetFixtures('<div id="page-notification"></div>'); appendSetFixtures('<div id="page-notification"></div>');
}; };
...@@ -121,8 +95,6 @@ define(["jquery", "js/views/feedback_notification", "js/views/feedback_prompt"], ...@@ -121,8 +95,6 @@ define(["jquery", "js/views/feedback_notification", "js/views/feedback_prompt"],
}; };
return { return {
'installTemplate': installTemplate,
'installTemplates': installTemplates,
'installViewTemplates': installViewTemplates, 'installViewTemplates': installViewTemplates,
'createNotificationSpy': createNotificationSpy, 'createNotificationSpy': createNotificationSpy,
'verifyNotificationShowing': verifyNotificationShowing, 'verifyNotificationShowing': verifyNotificationShowing,
......
...@@ -67,6 +67,7 @@ lib_paths: ...@@ -67,6 +67,7 @@ lib_paths:
src_paths: src_paths:
- coffee/src - coffee/src
- js - js
- js/common_helpers
# Paths to spec (test) JavaScript files # Paths to spec (test) JavaScript files
spec_paths: spec_paths:
......
...@@ -62,11 +62,13 @@ lib_paths: ...@@ -62,11 +62,13 @@ lib_paths:
src_paths: src_paths:
- coffee/src - coffee/src
- js - js
- js/common_helpers
# Paths to spec (test) JavaScript files # Paths to spec (test) JavaScript files
spec_paths: spec_paths:
- coffee/spec/main.js - coffee/spec/main.js
- coffee/spec - coffee/spec
- js/spec
# Paths to fixture files (optional) # Paths to fixture files (optional)
# The fixture path will be set automatically when using jasmine-jquery. # The fixture path will be set automatically when using jasmine-jquery.
......
describe('interpolate_ntext', function () {
it('replaces placeholder values', function () {
expect(interpolate_ntext('contains {count} student', 'contains {count} students', 1, {count: 1})).
toBe('contains 1 student');
expect(interpolate_ntext('contains {count} student', 'contains {count} students', 5, {count: 2})).
toBe('contains 2 students');
});
});
describe('interpolate_text', function () {
it('replaces placeholder values', function () {
expect(interpolate_text('contains {adjective} students', {adjective: 'awesome'})).
toBe('contains awesome students');
});
});
define(["sinon", "underscore"], function(sinon, _) { define(['sinon', 'underscore'], function(sinon, _) {
var fakeServer, fakeRequests, expectJsonRequest, respondWithJson, respondWithError, respondToDelete; var fakeServer, fakeRequests, expectRequest, expectJsonRequest,
respondWithJson, respondWithError, respondToDelete;
/* These utility methods are used by Jasmine tests to create a mock server or /* 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 * get reference to mock requests. In either case, the cleanup (restore) is done with
...@@ -45,6 +46,17 @@ define(["sinon", "underscore"], function(sinon, _) { ...@@ -45,6 +46,17 @@ define(["sinon", "underscore"], function(sinon, _) {
return requests; return requests;
}; };
expectRequest = function(requests, method, url, body, requestIndex) {
var request;
if (_.isUndefined(requestIndex)) {
requestIndex = requests.length - 1;
}
request = requests[requestIndex];
expect(request.url).toEqual(url);
expect(request.method).toEqual(method);
expect(request.requestBody).toEqual(body);
};
expectJsonRequest = function(requests, method, url, jsonRequest, requestIndex) { expectJsonRequest = function(requests, method, url, jsonRequest, requestIndex) {
var request; var request;
if (_.isUndefined(requestIndex)) { if (_.isUndefined(requestIndex)) {
...@@ -61,7 +73,7 @@ define(["sinon", "underscore"], function(sinon, _) { ...@@ -61,7 +73,7 @@ define(["sinon", "underscore"], function(sinon, _) {
requestIndex = requests.length - 1; requestIndex = requests.length - 1;
} }
requests[requestIndex].respond(200, requests[requestIndex].respond(200,
{ "Content-Type": "application/json" }, { 'Content-Type': 'application/json' },
JSON.stringify(jsonResponse)); JSON.stringify(jsonResponse));
}; };
...@@ -70,7 +82,7 @@ define(["sinon", "underscore"], function(sinon, _) { ...@@ -70,7 +82,7 @@ define(["sinon", "underscore"], function(sinon, _) {
requestIndex = requests.length - 1; requestIndex = requests.length - 1;
} }
requests[requestIndex].respond(500, requests[requestIndex].respond(500,
{ "Content-Type": "application/json" }, { 'Content-Type': 'application/json' },
JSON.stringify({ })); JSON.stringify({ }));
}; };
...@@ -79,15 +91,16 @@ define(["sinon", "underscore"], function(sinon, _) { ...@@ -79,15 +91,16 @@ define(["sinon", "underscore"], function(sinon, _) {
requestIndex = requests.length - 1; requestIndex = requests.length - 1;
} }
requests[requestIndex].respond(204, requests[requestIndex].respond(204,
{ "Content-Type": "application/json" }); { 'Content-Type': 'application/json' });
}; };
return { return {
"server": fakeServer, 'server': fakeServer,
"requests": fakeRequests, 'requests': fakeRequests,
"expectJsonRequest": expectJsonRequest, 'expectRequest': expectRequest,
"respondWithJson": respondWithJson, 'expectJsonRequest': expectJsonRequest,
"respondWithError": respondWithError, 'respondWithJson': respondWithJson,
"respondToDelete": respondToDelete 'respondWithError': respondWithError,
'respondToDelete': respondToDelete
}; };
}); });
/**
* Provides helper methods for invoking Studio modal windows in Jasmine tests.
*/
define(["jquery", "underscore"],
function($, _) {
var installTemplate, installTemplates;
installTemplate = function(templateFile, isFirst, templateId) {
var template = readFixtures(templateFile + '.underscore'),
templateName = templateFile,
slashIndex = _.lastIndexOf(templateName, "/");
if (slashIndex >= 0) {
templateName = templateFile.substring(slashIndex + 1);
}
if (!templateId) {
templateId = templateName + '-tpl';
}
if (isFirst) {
setFixtures($('<script>', { id: templateId, type: 'text/template' }).text(template));
} else {
appendSetFixtures($('<script>', { id: templateId, type: 'text/template' }).text(template));
}
};
installTemplates = function(templateNames, isFirst) {
if (!$.isArray(templateNames)) {
templateNames = [templateNames];
}
$.each(templateNames, function(index, templateName) {
installTemplate(templateName, isFirst);
if (isFirst) {
isFirst = false;
}
});
};
return {
'installTemplate': installTemplate,
'installTemplates': installTemplates
};
});
// String utility methods.
(function(_) {
/**
* Takes both a singular and plural version of a templatized string and plugs
* in the placeholder values. Assumes that internationalization has already been
* handled if necessary. Note that for text that needs to be internationalized,
* normally ngettext and interpolate_text would be used instead of this method.
*
* Example usage:
* interpolate_ntext('(contains {count} student)', '(contains {count} students)',
* expectedCount, {count: expectedCount}
* )
*
* @param singular the singular version of the templatized text
* @param plural the plural version of the templatized text
* @param count the count on which to base singular vs. plural text. Since this method is only
* intended for text that does not need to be passed through ngettext for internationalization,
* the simplistic English rule of count == 1 indicating singular is used.
* @param values the templatized dictionary values
* @returns the text with placeholder values filled in
*/
var interpolate_ntext = function (singular, plural, count, values) {
var text = count === 1 ? singular : plural;
return _.template(text, values, {interpolate: /\{(.+?)\}/g});
};
this.interpolate_ntext = interpolate_ntext;
/**
* Takes a templatized string and plugs in the placeholder values. Assumes that internationalization
* has already been handled if necessary.
*
* Example usages:
* interpolate_text('{title} ({count})', {title: expectedTitle, count: expectedCount}
* interpolate_text(
* ngettext("{numUsersAdded} student has been added to this cohort group",
* "{numUsersAdded} students have been added to this cohort group", numUsersAdded),
* {numUsersAdded: numUsersAdded}
* );
*
* @param text the templatized text
* @param values the templatized dictionary values
* @returns the text with placeholder values filled in
*/
var interpolate_text = function (text, values) {
return _.template(text, values, {interpolate: /\{(.+?)\}/g});
};
this.interpolate_text = interpolate_text;
}).call(this, _);
...@@ -178,7 +178,7 @@ drag = $special.drag = { ...@@ -178,7 +178,7 @@ drag = $special.drag = {
case !dd.dragging && 'touchmove': case !dd.dragging && 'touchmove':
event.preventDefault(); event.preventDefault();
case !dd.dragging && 'mousemove': case !dd.dragging && 'mousemove':
// drag tolerance, x² + y² = distance² // drag tolerance, x^2 + y^2 = distance^2
if ( Math.pow( event.pageX-dd.pageX, 2 ) + Math.pow( event.pageY-dd.pageY, 2 ) < Math.pow( dd.distance, 2 ) ) if ( Math.pow( event.pageX-dd.pageX, 2 ) + Math.pow( event.pageY-dd.pageY, 2 ) < Math.pow( dd.distance, 2 ) )
break; // distance tolerance not reached break; // distance tolerance not reached
event.target = dd.target; // force target from "mousedown" event (fix distance issue) event.target = dd.target; // force target from "mousedown" event (fix distance issue)
......
...@@ -41,18 +41,24 @@ class MembershipPage(PageObject): ...@@ -41,18 +41,24 @@ class MembershipPage(PageObject):
""" """
return self.q(css=".cohort-management #cohort-select option") return self.q(css=".cohort-management #cohort-select option")
def _name_without_count(self, name_with_count): def _cohort_name(self, label):
""" """
Returns the name of the cohort with the count information excluded. Returns the name of the cohort with the count information excluded.
""" """
return name_with_count.split(' (')[0] return label.split(' (')[0]
def _cohort_count(self, label):
"""
Returns the count for the cohort (as specified in the label in the selector).
"""
return int(label.split(' (')[1].split(')')[0])
def get_cohorts(self): def get_cohorts(self):
""" """
Returns, as a list, the names of the available cohorts in the drop-down, filtering out "Select a cohort". Returns, as a list, the names of the available cohorts in the drop-down, filtering out "Select a cohort".
""" """
return [ return [
self._name_without_count(opt.text) self._cohort_name(opt.text)
for opt in self._get_cohort_options().filter(lambda el: el.get_attribute('value') != "") for opt in self._get_cohort_options().filter(lambda el: el.get_attribute('value') != "")
] ]
...@@ -60,7 +66,15 @@ class MembershipPage(PageObject): ...@@ -60,7 +66,15 @@ class MembershipPage(PageObject):
""" """
Returns the name of the selected cohort. Returns the name of the selected cohort.
""" """
return self._name_without_count( return self._cohort_name(
self._get_cohort_options().filter(lambda el: el.is_selected()).first.text[0]
)
def get_selected_cohort_count(self):
"""
Returns the number of users in the selected cohort.
"""
return self._cohort_count(
self._get_cohort_options().filter(lambda el: el.is_selected()).first.text[0] self._get_cohort_options().filter(lambda el: el.is_selected()).first.text[0]
) )
...@@ -69,7 +83,7 @@ class MembershipPage(PageObject): ...@@ -69,7 +83,7 @@ class MembershipPage(PageObject):
Selects the given cohort in the drop-down. Selects the given cohort in the drop-down.
""" """
self.q(css=".cohort-management #cohort-select option").filter( self.q(css=".cohort-management #cohort-select option").filter(
lambda el: self._name_without_count(el.text) == cohort_name lambda el: self._cohort_name(el.text) == cohort_name
).first.click() ).first.click()
def get_cohort_group_setup(self): def get_cohort_group_setup(self):
...@@ -80,3 +94,46 @@ class MembershipPage(PageObject): ...@@ -80,3 +94,46 @@ class MembershipPage(PageObject):
def select_edit_settings(self): def select_edit_settings(self):
self.q(css=".action-edit").first.click() self.q(css=".action-edit").first.click()
def add_students_to_selected_cohort(self, users):
"""
Adds a list of users (either usernames or email addresses) to the currently selected cohort.
"""
textinput = self.q(css="#cohort-management-group-add-students").results[0]
for user in users:
textinput.send_keys(user)
textinput.send_keys(",")
self.q(css="div.cohort-management-group-add .action-primary").first.click()
def get_cohort_student_input_field_value(self):
"""
Returns the contents of the input field where students can be added to a cohort.
"""
return self.q(css="#cohort-management-group-add-students").results[0].get_attribute("value")
def _get_cohort_messages(self, type):
"""
Returns array of messages for given type.
"""
message_title = self.q(css="div.cohort-management-group-add .cohort-" + type + " .message-title")
if len(message_title.results) == 0:
return []
messages = [message_title.first.text[0]]
details = self.q(css="div.cohort-management-group-add .cohort-" + type + " .summary-item").results
for detail in details:
messages.append(detail.text)
return messages
def get_cohort_confirmation_messages(self):
"""
Returns an array of messages present in the confirmation area of the cohort management UI.
The first entry in the array is the title. Any further entries are the details.
"""
return self._get_cohort_messages("confirmations")
def get_cohort_error_messages(self):
"""
Returns an array of messages present in the error area of the cohort management UI.
The first entry in the array is the title. Any further entries are the details.
"""
return self._get_cohort_messages("errors")
...@@ -9,6 +9,7 @@ from ...fixtures.discussion import ( ...@@ -9,6 +9,7 @@ from ...fixtures.discussion import (
Thread, Thread,
Response, Response,
) )
from ...fixtures import LMS_BASE_URL
class BaseDiscussionMixin(object): class BaseDiscussionMixin(object):
...@@ -29,3 +30,42 @@ class BaseDiscussionMixin(object): ...@@ -29,3 +30,42 @@ class BaseDiscussionMixin(object):
thread_fixture.addResponse(Response(id=str(i), body=str(i))) thread_fixture.addResponse(Response(id=str(i), body=str(i)))
thread_fixture.push() thread_fixture.push()
self.setup_thread_page(thread_id) self.setup_thread_page(thread_id)
class CohortTestMixin(object):
"""
Mixin for tests of cohorted courses
"""
def setup_cohort_config(self, course_fixture, auto_cohort_groups=None):
"""
Sets up the course to use cohorting with the given list of auto_cohort_groups.
If auto_cohort_groups is None, no auto cohort groups are set.
"""
course_fixture._update_xblock(course_fixture._course_location, {
"metadata": {
u"cohort_config": {
"auto_cohort_groups": auto_cohort_groups or [],
"cohorted_discussions": [],
"cohorted": True
},
},
})
def add_manual_cohort(self, course_fixture, cohort_name):
"""
Adds a cohort group by name, returning the ID for the group.
"""
url = LMS_BASE_URL + "/courses/" + course_fixture._course_key + '/cohorts/add'
data = {"name": cohort_name}
response = course_fixture.session.post(url, data=data, headers=course_fixture.headers)
self.assertTrue(response.ok, "Failed to create cohort")
return response.json()['cohort']['id']
def add_user_to_cohort(self, course_fixture, username, cohort_id):
"""
Adds a user to the specified cohort group.
"""
url = LMS_BASE_URL + "/courses/" + course_fixture._course_key + "/cohorts/{}/add".format(cohort_id)
data = {"users": username}
response = course_fixture.session.post(url, data=data, headers=course_fixture.headers)
self.assertTrue(response.ok, "Failed to add user to cohort")
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
End-to-end tests related to the cohort management on the LMS Instructor Dashboard End-to-end tests related to the cohort management on the LMS Instructor Dashboard
""" """
from bok_choy.promise import EmptyPromise
from .helpers import CohortTestMixin from .helpers import CohortTestMixin
from ..helpers import UniqueCourseTest from ..helpers import UniqueCourseTest
from ...fixtures.course import CourseFixture from ...fixtures.course import CourseFixture
...@@ -11,7 +12,7 @@ from ...pages.lms.instructor_dashboard import InstructorDashboardPage ...@@ -11,7 +12,7 @@ from ...pages.lms.instructor_dashboard import InstructorDashboardPage
from ...pages.studio.settings_advanced import AdvancedSettingsPage from ...pages.studio.settings_advanced import AdvancedSettingsPage
class CohortTest(UniqueCourseTest, CohortTestMixin): class CohortConfigurationTest(UniqueCourseTest, CohortTestMixin):
""" """
Tests for cohort management on the LMS Instructor Dashboard Tests for cohort management on the LMS Instructor Dashboard
""" """
...@@ -20,17 +21,27 @@ class CohortTest(UniqueCourseTest, CohortTestMixin): ...@@ -20,17 +21,27 @@ class CohortTest(UniqueCourseTest, CohortTestMixin):
""" """
Set up a cohorted course Set up a cohorted course
""" """
super(CohortTest, self).setUp() super(CohortConfigurationTest, self).setUp()
# create course with cohorts # create course with cohorts
self.manual_cohort_name = "ManualCohort1" self.manual_cohort_name = "ManualCohort1"
self.auto_cohort_name = "AutoCohort1" self.auto_cohort_name = "AutoCohort1"
self.course_fixture = CourseFixture(**self.course_info).install() self.course_fixture = CourseFixture(**self.course_info).install()
self.setup_cohort_config(self.course_fixture, auto_cohort_groups=[self.auto_cohort_name]) self.setup_cohort_config(self.course_fixture, auto_cohort_groups=[self.auto_cohort_name])
self.add_manual_cohort(self.course_fixture, self.manual_cohort_name) self.manual_cohort_id = self.add_manual_cohort(self.course_fixture, self.manual_cohort_name)
# create a non-instructor who will be registered for the course and in the manual cohort.
self.student_name = "student_user"
self.student_id = AutoAuthPage(
self.browser, username=self.student_name, course_id=self.course_id, staff=False
).visit().get_user_id()
self.add_user_to_cohort(self.course_fixture, self.student_name, self.manual_cohort_id)
# login as an instructor # login as an instructor
self.user_id = AutoAuthPage(self.browser, course_id=self.course_id, staff=True).visit().get_user_id() self.instructor_name = "instructor_user"
self.instructor_id = AutoAuthPage(
self.browser, username=self.instructor_name, course_id=self.course_id, staff=True
).visit().get_user_id()
# go to the membership page on the instructor dashboard # go to the membership page on the instructor dashboard
instructor_dashboard_page = InstructorDashboardPage(self.browser, self.course_id) instructor_dashboard_page = InstructorDashboardPage(self.browser, self.course_id)
...@@ -47,7 +58,14 @@ class CohortTest(UniqueCourseTest, CohortTestMixin): ...@@ -47,7 +58,14 @@ class CohortTest(UniqueCourseTest, CohortTestMixin):
def test_cohort_description(self): def test_cohort_description(self):
""" """
Tests the description presented for manual and auto cohort types. Scenario: the cohort configuration management in the instructor dashboard specifies whether
students are automatically or manually assigned to specific cohorts.
Given I have a course with a manual cohort and an automatic cohort defined
When I view the manual cohort in the instructor dashboard
There is text specifying that students are only added to the cohort manually
And when I vew the automatic cohort in the instructor dashboard
There is text specifying that students are automatically added to the cohort
""" """
self.verify_cohort_description( self.verify_cohort_description(
self.manual_cohort_name, self.manual_cohort_name,
...@@ -60,7 +78,12 @@ class CohortTest(UniqueCourseTest, CohortTestMixin): ...@@ -60,7 +78,12 @@ class CohortTest(UniqueCourseTest, CohortTestMixin):
def test_link_to_studio(self): def test_link_to_studio(self):
""" """
Tests the link to the Advanced Settings page in Studio. Scenario: a link is present from the cohort configuration in the instructor dashboard
to the Studio Advanced Settings.
Given I have a course with a cohort defined
When I view the cohort in the LMS instructor dashboard
There is a link to take me to the Studio Advanced Settings for the course
""" """
self.membership_page.select_cohort(self.manual_cohort_name) self.membership_page.select_cohort(self.manual_cohort_name)
self.membership_page.select_edit_settings() self.membership_page.select_edit_settings()
...@@ -68,3 +91,64 @@ class CohortTest(UniqueCourseTest, CohortTestMixin): ...@@ -68,3 +91,64 @@ class CohortTest(UniqueCourseTest, CohortTestMixin):
self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run']
) )
advanced_settings_page.wait_for_page() advanced_settings_page.wait_for_page()
def test_add_students_to_cohort_success(self):
"""
Scenario: When students are added to a cohort, the appropriate notification is shown.
Given I have a course with two cohorts
And there is a user in one cohort
And there is a user in neither cohort
When I add the two users to the cohort that initially had no users
Then there are 2 users in total in the cohort
And I get a notification that 2 users have been added to the cohort
And I get a notification that 1 user was moved from the other cohort
And the user input field is empty
"""
self.membership_page.select_cohort(self.auto_cohort_name)
self.assertEqual(0, self.membership_page.get_selected_cohort_count())
self.membership_page.add_students_to_selected_cohort([self.student_name, self.instructor_name])
# Wait for the number of users in the cohort to change, indicating that the add operation is complete.
EmptyPromise(
lambda: 2 == self.membership_page.get_selected_cohort_count(), 'Waiting for added students'
).fulfill()
confirmation_messages = self.membership_page.get_cohort_confirmation_messages()
self.assertEqual(2, len(confirmation_messages))
self.assertEqual("2 students have been added to this cohort group", confirmation_messages[0])
self.assertEqual("1 student was removed from " + self.manual_cohort_name, confirmation_messages[1])
self.assertEqual("", self.membership_page.get_cohort_student_input_field_value())
def test_add_students_to_cohort_failure(self):
"""
Scenario: When errors occur when adding students to a cohort, the appropriate notification is shown.
Given I have a course with a cohort and a user already in it
When I add the user already in a cohort to that same cohort
And I add a non-existing user to that cohort
Then there is no change in the number of students in the cohort
And I get a notification that one user was already in the cohort
And I get a notification that one user is unknown
And the user input field still contains the incorrect email addresses
"""
self.membership_page.select_cohort(self.manual_cohort_name)
self.assertEqual(1, self.membership_page.get_selected_cohort_count())
self.membership_page.add_students_to_selected_cohort([self.student_name, "unknown_user"])
# Wait for notification messages to appear, indicating that the add operation is complete.
EmptyPromise(
lambda: 2 == len(self.membership_page.get_cohort_confirmation_messages()), 'Waiting for notification'
).fulfill()
self.assertEqual(1, self.membership_page.get_selected_cohort_count())
confirmation_messages = self.membership_page.get_cohort_confirmation_messages()
self.assertEqual(2, len(confirmation_messages))
self.assertEqual("0 students have been added to this cohort group", confirmation_messages[0])
self.assertEqual("1 student was already in the cohort group", confirmation_messages[1])
error_messages = self.membership_page.get_cohort_error_messages()
self.assertEqual(2, len(error_messages))
self.assertEqual("There was an error when trying to add students:", error_messages[0])
self.assertEqual("Unknown user: unknown_user", error_messages[1])
self.assertEqual(
self.student_name+",unknown_user,",
self.membership_page.get_cohort_student_input_field_value()
)
...@@ -4,7 +4,7 @@ Tests related to the cohorting feature. ...@@ -4,7 +4,7 @@ Tests related to the cohorting feature.
from uuid import uuid4 from uuid import uuid4
from .helpers import BaseDiscussionMixin from .helpers import BaseDiscussionMixin
from ..lms.helpers import CohortTestMixin from .helpers import CohortTestMixin
from ..helpers import UniqueCourseTest from ..helpers import UniqueCourseTest
from ...pages.lms.auto_auth import AutoAuthPage from ...pages.lms.auto_auth import AutoAuthPage
from ...fixtures.course import (CourseFixture, XBlockFixtureDesc) from ...fixtures.course import (CourseFixture, XBlockFixtureDesc)
......
"""
Helper functions and classes for LMS tests.
"""
from ...fixtures import LMS_BASE_URL
class CohortTestMixin(object):
"""
Mixin for tests of cohorted courses
"""
def setup_cohort_config(self, course_fixture, auto_cohort_groups=None):
"""
Sets up the course to use cohorting with the given list of auto_cohort_groups.
If auto_cohort_groups is None, no auto cohort groups are set.
"""
course_fixture._update_xblock(course_fixture._course_location, {
"metadata": {
u"cohort_config": {
"auto_cohort_groups": auto_cohort_groups or [],
"cohorted_discussions": [],
"cohorted": True
},
},
})
def add_manual_cohort(self, course_fixture, name):
"""
Adds a cohort group by name, returning the ID for the group.
"""
url = LMS_BASE_URL + "/courses/" + course_fixture._course_key + '/cohorts/add'
data = {"name": name}
response = course_fixture.session.post(url, data=data, headers=course_fixture.headers)
self.assertTrue(response.ok, "Failed to create cohort")
return response.json()['cohort']['id']
...@@ -209,6 +209,7 @@ We use Jasmine to run JavaScript unit tests. To run all the JavaScript tests: ...@@ -209,6 +209,7 @@ We use Jasmine to run JavaScript unit tests. To run all the JavaScript tests:
To run a specific set of JavaScript tests and print the results to the console: To run a specific set of JavaScript tests and print the results to the console:
paver test_js_run -s lms paver test_js_run -s lms
paver test_js_run -s lms-coffee
paver test_js_run -s cms paver test_js_run -s cms
paver test_js_run -s cms-squire paver test_js_run -s cms-squire
paver test_js_run -s xmodule paver test_js_run -s xmodule
...@@ -217,6 +218,7 @@ To run a specific set of JavaScript tests and print the results to the console: ...@@ -217,6 +218,7 @@ To run a specific set of JavaScript tests and print the results to the console:
To run JavaScript tests in your default browser: To run JavaScript tests in your default browser:
paver test_js_dev -s lms paver test_js_dev -s lms
paver test_js_dev -s lms-coffee
paver test_js_dev -s cms paver test_js_dev -s cms
paver test_js_dev -s cms-squire paver test_js_dev -s cms-squire
paver test_js_dev -s xmodule paver test_js_dev -s xmodule
......
...@@ -1129,6 +1129,7 @@ PIPELINE_JS = { ...@@ -1129,6 +1129,7 @@ PIPELINE_JS = {
'js/src/utility.js', 'js/src/utility.js',
'js/src/accessibility_tools.js', 'js/src/accessibility_tools.js',
'js/src/ie_shim.js', 'js/src/ie_shim.js',
'js/src/string_utils.js',
], ],
'output_filename': 'js/lms-application.js', 'output_filename': 'js/lms-application.js',
}, },
......
../../../common/static/js/spec_helpers
\ No newline at end of file
(function(Backbone) {
var NotificationModel = Backbone.Model.extend({
defaults: {
// Supported types are "confirmation" and "error".
type: "confirmation",
title: "",
details: [],
actionText: "",
actionCallback: null
}
});
this.NotificationModel = NotificationModel;
}).call(this, Backbone);
(function(requirejs, define) {
// TODO: how can we share the vast majority of this config that is in common with CMS?
requirejs.config({
paths: {
'gettext': 'xmodule_js/common_static/js/test/i18n',
'mustache': 'xmodule_js/common_static/js/vendor/mustache',
'codemirror': 'xmodule_js/common_static/js/vendor/CodeMirror/codemirror',
'jquery': 'xmodule_js/common_static/js/vendor/jquery.min',
'jquery.ui': 'xmodule_js/common_static/js/vendor/jquery-ui.min',
'jquery.flot': 'xmodule_js/common_static/js/vendor/flot/jquery.flot.min',
'jquery.form': 'xmodule_js/common_static/js/vendor/jquery.form',
'jquery.markitup': 'xmodule_js/common_static/js/vendor/markitup/jquery.markitup',
'jquery.leanModal': 'xmodule_js/common_static/js/vendor/jquery.leanModal.min',
'jquery.ajaxQueue': 'xmodule_js/common_static/js/vendor/jquery.ajaxQueue',
'jquery.smoothScroll': 'xmodule_js/common_static/js/vendor/jquery.smooth-scroll.min',
'jquery.scrollTo': 'xmodule_js/common_static/js/vendor/jquery.scrollTo-1.4.2-min',
'jquery.timepicker': 'xmodule_js/common_static/js/vendor/timepicker/jquery.timepicker',
'jquery.cookie': 'xmodule_js/common_static/js/vendor/jquery.cookie',
'jquery.qtip': 'xmodule_js/common_static/js/vendor/jquery.qtip.min',
'jquery.fileupload': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload',
'jquery.iframe-transport': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport',
'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill',
'jquery.immediateDescendents': 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents',
'jquery.simulate': 'xmodule_js/common_static/js/vendor/jquery.simulate',
'datepair': 'xmodule_js/common_static/js/vendor/timepicker/datepair',
'date': 'xmodule_js/common_static/js/vendor/date',
'underscore': 'xmodule_js/common_static/js/vendor/underscore-min',
'underscore.string': 'xmodule_js/common_static/js/vendor/underscore.string.min',
'backbone': 'xmodule_js/common_static/js/vendor/backbone-min',
'backbone.associations': 'xmodule_js/common_static/js/vendor/backbone-associations-min',
'backbone.paginator': 'xmodule_js/common_static/js/vendor/backbone.paginator.min',
'tinymce': 'xmodule_js/common_static/js/vendor/tinymce/js/tinymce/tinymce.full.min',
'jquery.tinymce': 'xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce',
'xmodule': 'xmodule_js/src/xmodule',
'utility': 'xmodule_js/common_static/js/src/utility',
'accessibility': 'xmodule_js/common_static/js/src/accessibility_tools',
'sinon': 'xmodule_js/common_static/js/vendor/sinon-1.7.1',
'squire': 'xmodule_js/common_static/js/vendor/Squire',
'jasmine-jquery': 'xmodule_js/common_static/js/vendor/jasmine-jquery',
'jasmine-imagediff': 'xmodule_js/common_static/js/vendor/jasmine-imagediff',
'jasmine-stealth': 'xmodule_js/common_static/js/vendor/jasmine-stealth',
'jasmine.async': 'xmodule_js/common_static/js/vendor/jasmine.async',
'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly.pkgd',
'domReady': 'xmodule_js/common_static/js/vendor/domReady',
'URI': 'xmodule_js/common_static/js/vendor/URI.min',
'mathjax': '//edx-static.s3.amazonaws.com/mathjax-MathJax-727332c/MathJax.js?config=TeX-MML-AM_HTMLorMML-full&delayStartupUntil=configured',
'youtube': '//www.youtube.com/player_api?noext',
'tender': '//edxedge.tenderapp.com/tender_widget',
'coffee/src/ajax_prefix': 'xmodule_js/common_static/coffee/src/ajax_prefix',
'xmodule_js/common_static/js/test/add_ajax_prefix': 'xmodule_js/common_static/js/test/add_ajax_prefix',
'xblock/core': 'xmodule_js/common_static/coffee/src/xblock/core',
'xblock/runtime.v1': 'xmodule_js/common_static/coffee/src/xblock/runtime.v1',
'xblock/lms.runtime.v1': 'coffee/src/xblock/lms.runtime.v1',
'capa/display': 'xmodule_js/src/capa/display',
'string_utils': 'xmodule_js/common_static/js/src/string_utils',
// Manually specify LMS files that are not converted to RequireJS
'js/verify_student/photocapture': 'js/verify_student/photocapture',
'js/staff_debug_actions': 'js/staff_debug_actions',
// Backbone classes loaded explicitly until they are converted to use RequireJS
'js/models/cohort': 'js/models/cohort',
'js/collections/cohort': 'js/collections/cohort',
'js/views/cohort_editor': 'js/views/cohort_editor',
'js/views/cohorts': 'js/views/cohorts',
'js/views/notification': 'js/views/notification',
'js/models/notification': 'js/models/notification'
},
shim: {
'gettext': {
exports: 'gettext'
},
'string_utils': {
deps: ['underscore']
},
'date': {
exports: 'Date'
},
'jquery.ui': {
deps: ['jquery'],
exports: 'jQuery.ui'
},
'jquery.flot': {
deps: ['jquery'],
exports: 'jQuery.flot'
},
'jquery.form': {
deps: ['jquery'],
exports: 'jQuery.fn.ajaxForm'
},
'jquery.markitup': {
deps: ['jquery'],
exports: 'jQuery.fn.markitup'
},
'jquery.leanModal': {
deps: ['jquery'],
exports: 'jQuery.fn.leanModal'
},
'jquery.smoothScroll': {
deps: ['jquery'],
exports: 'jQuery.fn.smoothScroll'
},
'jquery.ajaxQueue': {
deps: ['jquery'],
exports: 'jQuery.fn.ajaxQueue'
},
'jquery.scrollTo': {
deps: ['jquery'],
exports: 'jQuery.fn.scrollTo'
},
'jquery.cookie': {
deps: ['jquery'],
exports: 'jQuery.fn.cookie'
},
'jquery.qtip': {
deps: ['jquery'],
exports: 'jQuery.fn.qtip'
},
'jquery.fileupload': {
deps: ['jquery.iframe-transport'],
exports: 'jQuery.fn.fileupload'
},
'jquery.inputnumber': {
deps: ['jquery'],
exports: 'jQuery.fn.inputNumber'
},
'jquery.simulate': {
deps: ['jquery'],
exports: 'jQuery.fn.simulate'
},
'jquery.tinymce': {
deps: ['jquery', 'tinymce'],
exports: 'jQuery.fn.tinymce'
},
'datepair': {
deps: ['jquery.ui', 'jquery.timepicker']
},
'underscore': {
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'backbone.associations': {
deps: ['backbone'],
exports: 'Backbone.Associations'
},
'backbone.paginator': {
deps: ['backbone'],
exports: 'Backbone.Paginator'
},
'youtube': {
exports: 'YT'
},
'codemirror': {
exports: 'CodeMirror'
},
'tinymce': {
exports: 'tinymce'
},
'mathjax': {
exports: 'MathJax',
init: function() {
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['\\(', '\\)'], ['[mathjaxinline]', '[/mathjaxinline]']],
displayMath: [['\\[', '\\]'], ['[mathjax]', '[/mathjax]']]
}
});
return MathJax.Hub.Configured();
}
},
'URI': {
exports: 'URI'
},
'xmodule': {
exports: 'XModule'
},
'sinon': {
exports: 'sinon'
},
'jasmine-jquery': {
deps: ['jasmine']
},
'jasmine-imagediff': {
deps: ['jasmine']
},
'jasmine-stealth': {
deps: ['jasmine']
},
'jasmine.async': {
deps: ['jasmine'],
exports: 'AsyncSpec'
},
'xblock/core': {
exports: 'XBlock',
deps: ['jquery', 'jquery.immediateDescendents']
},
'xblock/runtime.v1': {
exports: 'XBlock.Runtime.v1',
deps: ['xblock/core']
},
'xblock/lms.runtime.v1': {
exports: 'LmsRuntime.v1',
deps: ['xblock/runtime.v1']
},
'xmodule_js/common_static/js/test/add_ajax_prefix': {
exports: 'AjaxPrefix',
deps: ['coffee/src/ajax_prefix']
},
// LMS class loaded explicitly until they are converted to use RequireJS
'js/verify_student/photocapture': {
exports: 'js/verify_student/photocapture'
},
'js/staff_debug_actions': {
exports: 'js/staff_debug_actions',
deps: ['gettext']
},
// Backbone classes loaded explicitly until they are converted to use RequireJS
'js/models/cohort': {
exports: 'CohortModel',
deps: ['backbone']
},
'js/collections/cohort': {
exports: 'CohortCollection',
deps: ['backbone', 'js/models/cohort']
},
'js/views/cohort_editor': {
exports: 'CohortsEditor',
deps: ['backbone', 'jquery', 'underscore', 'js/views/notification', 'js/models/notification',
'string_utils'
]
},
'js/views/cohorts': {
exports: 'CohortsView',
deps: ['backbone', 'js/views/cohort_editor']
},
'js/models/notification': {
exports: 'NotificationModel',
deps: ['backbone']
},
'js/views/notification': {
exports: 'NotificationView',
deps: ['backbone', 'jquery', 'underscore']
}
},
});
// TODO: why do these need 'lms/include' at the front but the CMS equivalent logic doesn't?
define([
// Run the LMS tests
'lms/include/js/spec/views/cohorts_spec.js',
'lms/include/js/spec/photocapture_spec.js',
'lms/include/js/spec/staff_debug_actions_spec.js',
'lms/include/js/spec/views/notification_spec.js'
]);
}).call(this, requirejs, define);
describe("Photo Verification", function() { define(['backbone', 'jquery', 'js/verify_student/photocapture'],
function (Backbone, $) {
beforeEach(function() { describe("Photo Verification", function () {
beforeEach(function () {
setFixtures('<div id="order-error" style="display: none;"></div><input type="radio" name="contribution" value="35" id="contribution-35" checked="checked"><input type="radio" id="contribution-other" name="contribution" value=""><input type="text" size="9" name="contribution-other-amt" id="contribution-other-amt" value="30"><img id="face_image" src="src="data:image/png;base64,dummy"><img id="photo_id_image" src="src="data:image/png;base64,dummy">'); setFixtures('<div id="order-error" style="display: none;"></div><input type="radio" name="contribution" value="35" id="contribution-35" checked="checked"><input type="radio" id="contribution-other" name="contribution" value=""><input type="text" size="9" name="contribution-other-amt" id="contribution-other-amt" value="30"><img id="face_image" src="src="data:image/png;base64,dummy"><img id="photo_id_image" src="src="data:image/png;base64,dummy">');
}); });
it('retake photo', function() { it('retake photo', function () {
spyOn(window,"refereshPageMessage").andCallFake(function(){ spyOn(window, "refereshPageMessage").andCallFake(function () {
return return;
}) });
spyOn($, "ajax").andCallFake(function(e) { spyOn($, "ajax").andCallFake(function (e) {
e.success({"success":false}); e.success({"success": false});
}); });
submitToPaymentProcessing(); submitToPaymentProcessing();
expect(window.refereshPageMessage).toHaveBeenCalled(); expect(window.refereshPageMessage).toHaveBeenCalled();
}); });
it('successful submission', function() { it('successful submission', function () {
spyOn(window,"submitForm").andCallFake(function(){ spyOn(window, "submitForm").andCallFake(function () {
return return;
}) });
spyOn($, "ajax").andCallFake(function(e) { spyOn($, "ajax").andCallFake(function (e) {
e.success({"success":true}); e.success({"success": true});
}); });
submitToPaymentProcessing(); submitToPaymentProcessing();
expect(window.submitForm).toHaveBeenCalled(); expect(window.submitForm).toHaveBeenCalled();
}); });
it('Error during process', function() { it('Error during process', function () {
spyOn(window,"showSubmissionError").andCallFake(function(){ spyOn(window, "showSubmissionError").andCallFake(function () {
return return;
}) });
spyOn($, "ajax").andCallFake(function(e) { spyOn($, "ajax").andCallFake(function (e) {
e.error({}); e.error({});
}); });
submitToPaymentProcessing(); submitToPaymentProcessing();
expect(window.showSubmissionError).toHaveBeenCalled(); expect(window.showSubmissionError).toHaveBeenCalled();
}); });
}); });
});
\ No newline at end of file
describe('StaffDebugActions', function() { define(['backbone', 'jquery', 'js/staff_debug_actions'],
function (Backbone, $) {
describe('StaffDebugActions', function () {
var location = 'i4x://edX/Open_DemoX/edx_demo_course/problem/test_loc'; var location = 'i4x://edX/Open_DemoX/edx_demo_course/problem/test_loc';
var locationName = 'test_loc' var locationName = 'test_loc';
var fixture_id = 'sd_fu_' + locationName; var fixture_id = 'sd_fu_' + locationName;
var fixture = $('<input>', { id: fixture_id, placeholder: "userman" }); var fixture = $('<input>', { id: fixture_id, placeholder: "userman" });
describe('get_url ', function() { describe('get_url ', function () {
it('defines url to courseware ajax entry point', function() { it('defines url to courseware ajax entry point', function () {
spyOn(StaffDebug, "get_current_url").andReturn("/courses/edX/Open_DemoX/edx_demo_course/courseware/stuff"); spyOn(StaffDebug, "get_current_url").andReturn("/courses/edX/Open_DemoX/edx_demo_course/courseware/stuff");
expect(StaffDebug.get_url('rescore_problem')).toBe('/courses/edX/Open_DemoX/edx_demo_course/instructor/api/rescore_problem'); expect(StaffDebug.get_url('rescore_problem')).toBe('/courses/edX/Open_DemoX/edx_demo_course/instructor/api/rescore_problem');
}); });
}); });
describe('get_user', function() { describe('get_user', function () {
it('gets the placeholder username if input field is empty', function() { it('gets the placeholder username if input field is empty', function () {
$('body').append(fixture); $('body').append(fixture);
expect(StaffDebug.get_user(locationName)).toBe('userman'); expect(StaffDebug.get_user(locationName)).toBe('userman');
$('#' + fixture_id).remove(); $('#' + fixture_id).remove();
}); });
it('gets a filled in name if there is one', function() { it('gets a filled in name if there is one', function () {
$('body').append(fixture); $('body').append(fixture);
$('#' + fixture_id).val('notuserman'); $('#' + fixture_id).val('notuserman');
expect(StaffDebug.get_user(locationName)).toBe('notuserman'); expect(StaffDebug.get_user(locationName)).toBe('notuserman');
...@@ -27,8 +30,8 @@ describe('StaffDebugActions', function() { ...@@ -27,8 +30,8 @@ describe('StaffDebugActions', function() {
$('#' + fixture_id).remove(); $('#' + fixture_id).remove();
}); });
}); });
describe('reset', function() { describe('reset', function () {
it('makes an ajax call with the expected parameters', function() { it('makes an ajax call with the expected parameters', function () {
$('body').append(fixture); $('body').append(fixture);
spyOn($, 'ajax'); spyOn($, 'ajax');
...@@ -46,8 +49,8 @@ describe('StaffDebugActions', function() { ...@@ -46,8 +49,8 @@ describe('StaffDebugActions', function() {
$('#' + fixture_id).remove(); $('#' + fixture_id).remove();
}); });
}); });
describe('sdelete', function() { describe('sdelete', function () {
it('makes an ajax call with the expected parameters', function() { it('makes an ajax call with the expected parameters', function () {
$('body').append(fixture); $('body').append(fixture);
spyOn($, 'ajax'); spyOn($, 'ajax');
...@@ -66,8 +69,8 @@ describe('StaffDebugActions', function() { ...@@ -66,8 +69,8 @@ describe('StaffDebugActions', function() {
$('#' + fixture_id).remove(); $('#' + fixture_id).remove();
}); });
}); });
describe('rescore', function() { describe('rescore', function () {
it('makes an ajax call with the expected parameters', function() { it('makes an ajax call with the expected parameters', function () {
$('body').append(fixture); $('body').append(fixture);
spyOn($, 'ajax'); spyOn($, 'ajax');
...@@ -85,6 +88,5 @@ describe('StaffDebugActions', function() { ...@@ -85,6 +88,5 @@ describe('StaffDebugActions', function() {
$('#' + fixture_id).remove(); $('#' + fixture_id).remove();
}); });
}); });
});
}); });
\ No newline at end of file
describe("Cohorts View", function() { define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpers/template_helpers',
var createMockCohorts, createCohortsView, installTemplateFixture; 'js/views/cohorts', 'js/collections/cohort', 'string_utils'],
function (Backbone, $, AjaxHelpers, TemplateHelpers, CohortsView, CohortCollection) {
describe("Cohorts View", function () {
var catLoversInitialCount = 123, dogLoversInitialCount = 456, unknownUserMessage,
createMockCohorts, createCohortsView, cohortsView, requests, verifyMessage, verifyHeader;
createMockCohorts = function() { createMockCohorts = function (catCount, dogCount) {
return { return {
cohorts: [{ cohorts: [
{
id: 1, id: 1,
name: 'Cat Lovers', name: 'Cat Lovers',
user_count: 123 user_count: catCount || catLoversInitialCount
},{ },
{
id: 2, id: 2,
name: 'Dog Lovers', name: 'Dog Lovers',
user_count: 456 user_count: dogCount || dogLoversInitialCount
}] }
]
}; };
}; };
createCohortsView = function() { createCohortsView = function (test, initialCohortID) {
var cohorts, view; var cohorts = new CohortCollection(createMockCohorts(), {parse: true});
cohorts = new CohortCollection(createMockCohorts(), {parse: true}); cohorts.url = '/mock_service';
view = new CohortsView({ requests = AjaxHelpers.requests(test);
cohortsView = new CohortsView({
model: cohorts model: cohorts
}); });
view.render(); cohortsView.render();
return view; if (initialCohortID) {
cohortsView.$('.cohort-select').val(initialCohortID).change();
}
}; };
installTemplateFixture = function(templateName, templateDirectory) { verifyMessage = function(expectedTitle, messageType, expectedDetails, expectedAction) {
var templateFixture = readFixtures(templateDirectory + templateName + '.underscore'); var numDetails = cohortsView.$('.summary-items').children().length;
appendSetFixtures($('<script>', { id: templateName + '-tpl', type: 'text/template' })
.text(templateFixture)); expect(cohortsView.$('.message-title').text().trim()).toBe(expectedTitle);
expect(cohortsView.$('div.message').hasClass('message-' + messageType)).toBe(true);
if (expectedAction) {
expect(cohortsView.$('.message-actions .action-primary').text()).toBe(expectedAction);
}
else {
expect(cohortsView.$('.message-actions .action-primary').length).toBe(0);
}
if (expectedDetails) {
expect(numDetails).toBe(expectedDetails.length);
cohortsView.$('.summary-item').each(function (index) {
expect($(this).text().trim()).toBe(expectedDetails[index]);
});
}
else {
expect(numDetails).toBe(0);
}
};
verifyHeader = function(expectedCohortId, expectedTitle, expectedCount) {
var header = cohortsView.$('.cohort-management-group-header');
expect(cohortsView.$('.cohort-select').val()).toBe(expectedCohortId.toString());
expect(cohortsView.$('.cohort-select option:selected').text()).toBe(
interpolate_text(
'{title} ({count})', {title: expectedTitle, count: expectedCount}
)
);
expect(header.find('.title-value').text()).toBe(expectedTitle);
expect(header.find('.group-count').text()).toBe(
interpolate_ntext(
'(contains {count} student)',
'(contains {count} students)',
expectedCount,
{count: expectedCount}
)
);
};
unknownUserMessage = function (name) {
return "Unknown user: " + name;
}; };
beforeEach(function() { beforeEach(function () {
setFixtures("<div></div>"); setFixtures("<div></div>");
installTemplateFixture('cohort-editor', 'templates/instructor/instructor_dashboard_2/'); TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/cohorts');
installTemplateFixture('cohorts', 'templates/instructor/instructor_dashboard_2/'); TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/cohort-selector');
TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/cohort-editor');
TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/notification');
});
describe("Cohort Selector", function () {
it('has no initial selection', function () {
createCohortsView(this);
expect(cohortsView.$('.cohort-select').val()).toBe('');
expect(cohortsView.$('.cohort-management-group-header .title-value').text()).toBe('');
});
it('can select a cohort', function () {
createCohortsView(this, "1");
verifyHeader(1, 'Cat Lovers', catLoversInitialCount);
}); });
describe("Cohort Selector", function() { it('can switch cohort', function () {
it('has no initial selection', function() { createCohortsView(this, "1");
var view = createCohortsView(); cohortsView.$('.cohort-select').val("2").change();
expect(view.$('.cohort-select').val()).toBe(''); verifyHeader(2, 'Dog Lovers', dogLoversInitialCount);
expect(view.$('.cohort-management-group-header .title-value').text()).toBe('');
}); });
});
describe("Add Students Button", function () {
var getStudentInput, addStudents, respondToAdd, respondToRefresh;
getStudentInput = function() {
return cohortsView.$('.cohort-management-group-add-students');
};
addStudents = function(students) {
getStudentInput().val(students);
cohortsView.$('.cohort-management-group-add-form').submit();
};
respondToAdd = function(result) {
AjaxHelpers.respondWithJson(
requests,
_.extend({ unknown: [], added: [], present: [], changed: [], success: true }, result)
);
};
respondToRefresh = function(catCount, dogCount) {
AjaxHelpers.respondWithJson(requests, createMockCohorts(catCount, dogCount));
};
it('can select a cohort', function() { it('shows an error when adding with no students specified', function() {
var view = createCohortsView(); createCohortsView(this, "1");
view.$('.cohort-select').val("1").change(); addStudents(' ');
expect(view.$('.cohort-select').val()).toBe('1'); expect(requests.length).toBe(0);
expect(view.$('.cohort-management-group-header .title-value').text()).toBe('Cat Lovers'); verifyMessage('Please enter a username or email.', 'error');
expect(view.$('.cohort-management-group-header .group-count').text()).toBe('123'); expect(getStudentInput().val()).toBe('');
}); });
it('can switch cohort', function() { it('can add a single student', function() {
var view = createCohortsView(); var catLoversUpdatedCount = catLoversInitialCount + 1;
view.$('.cohort-select').val("1").change(); createCohortsView(this, "1");
view.$('.cohort-select').val("2").change(); addStudents('student@sample.com');
expect(view.$('.cohort-select').val()).toBe('2'); AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/1/add', 'users=student%40sample.com');
expect(view.$('.cohort-management-group-header .title-value').text()).toBe('Dog Lovers'); respondToAdd({ added: ['student@sample.com'] });
expect(view.$('.cohort-management-group-header .group-count').text()).toBe('456'); respondToRefresh(catLoversUpdatedCount, dogLoversInitialCount);
verifyHeader(1, 'Cat Lovers', catLoversUpdatedCount);
verifyMessage('1 student has been added to this cohort group', 'confirmation');
expect(getStudentInput().val()).toBe('');
});
it('shows an error when adding a student that does not exist', function() {
createCohortsView(this, "1");
addStudents('unknown@sample.com');
AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/1/add', 'users=unknown%40sample.com');
respondToAdd({ unknown: ['unknown@sample.com'] });
respondToRefresh(catLoversInitialCount, dogLoversInitialCount);
verifyHeader(1, 'Cat Lovers', catLoversInitialCount);
verifyMessage('There was an error when trying to add students:', 'error',
[unknownUserMessage('unknown@sample.com')]
);
expect(getStudentInput().val()).toBe('unknown@sample.com');
});
it('shows a "view all" button when more than 5 students do not exist', function() {
var sixUsers = 'unknown1@sample.com, unknown2@sample.com, unknown3@sample.com, unknown4@sample.com, unknown5@sample.com, unknown6@sample.com';
createCohortsView(this, "1");
addStudents(sixUsers);
AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/1/add',
'users=' + sixUsers.replace(/@/g, "%40").replace(/, /g, "%2C+")
);
respondToAdd({ unknown: [
'unknown1@sample.com',
'unknown2@sample.com',
'unknown3@sample.com',
'unknown4@sample.com',
'unknown5@sample.com',
'unknown6@sample.com']
});
respondToRefresh(catLoversInitialCount + 6, dogLoversInitialCount);
verifyMessage('There were 6 errors when trying to add students:', 'error',
[
unknownUserMessage('unknown1@sample.com'), unknownUserMessage('unknown2@sample.com'),
unknownUserMessage('unknown3@sample.com'), unknownUserMessage('unknown4@sample.com'),
unknownUserMessage('unknown5@sample.com')
],
'View all errors'
);
expect(getStudentInput().val()).toBe(sixUsers);
// Click "View all"
cohortsView.$('a.action-primary').click();
verifyMessage('There were 6 errors when trying to add students:', 'error',
[
unknownUserMessage('unknown1@sample.com'), unknownUserMessage('unknown2@sample.com'),
unknownUserMessage('unknown3@sample.com'), unknownUserMessage('unknown4@sample.com'),
unknownUserMessage('unknown5@sample.com'), unknownUserMessage('unknown6@sample.com')
]
);
});
it('shows students moved from one cohort to another', function() {
var sixUsers = 'moved1@sample.com, moved2@sample.com, moved3@sample.com, alreadypresent@sample.com';
createCohortsView(this, "1");
addStudents(sixUsers);
AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/1/add',
'users=' + sixUsers.replace(/@/g, "%40").replace(/, /g, "%2C+")
);
respondToAdd({
changed: [
{email: 'moved1@sample.com', name: 'moved1', previous_cohort: 'group 2', username: 'moved1'},
{email: 'moved2@sample.com', name: 'moved2', previous_cohort: 'group 2', username: 'moved2'},
{email: 'moved3@sample.com', name: 'moved3', previous_cohort: 'group 3', username: 'moved3'}
],
present: ['alreadypresent@sample.com']
});
respondToRefresh();
verifyMessage('3 students have been added to this cohort group', 'confirmation',
[
"2 students were removed from group 2",
"1 student was removed from group 3",
"1 student was already in the cohort group"
]
);
expect(getStudentInput().val()).toBe('');
});
it('shows a message when the add fails', function() {
createCohortsView(this, "1");
addStudents('student@sample.com');
AjaxHelpers.respondWithError(requests);
verifyMessage('Error adding students.', 'error');
expect(getStudentInput().val()).toBe('student@sample.com');
});
it('clears an error message on subsequent add', function() {
createCohortsView(this, "1");
// First verify that an error is shown
addStudents('student@sample.com');
AjaxHelpers.respondWithError(requests);
verifyMessage('Error adding students.', 'error');
// Now verify that the error is removed on a subsequent add
addStudents('student@sample.com');
respondToAdd({ added: ['student@sample.com'] });
respondToRefresh(catLoversInitialCount + 1, dogLoversInitialCount);
verifyMessage('1 student has been added to this cohort group', 'confirmation');
});
});
}); });
}); });
});
define(['backbone', 'jquery', 'js/models/notification', 'js/views/notification', 'js/common_helpers/template_helpers'],
function (Backbone, $, NotificationModel, NotificationView, TemplateHelpers) {
describe("NotificationView", function () {
var createNotification, verifyTitle, verifyDetails, verifyAction, notificationView;
createNotification = function (modelVals) {
var notificationModel = new NotificationModel(modelVals);
notificationView = new NotificationView({
model: notificationModel
});
notificationView.render();
return notificationView;
};
verifyTitle = function (expectedTitle) {
expect(notificationView.$('.message-title').text().trim()).toBe(expectedTitle);
};
verifyDetails = function (expectedDetails) {
var details = notificationView.$('.summary-item');
expect(details.length).toBe(expectedDetails.length);
details.each(function (index) {
expect($(this).text().trim()).toBe(expectedDetails[index]);
});
};
verifyAction = function (expectedActionText) {
var actionButton = notificationView.$('.action-primary');
if (expectedActionText) {
expect(actionButton.text().trim()).toBe(expectedActionText);
}
else {
expect(actionButton.length).toBe(0);
}
};
beforeEach(function () {
setFixtures("<div></div>");
TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/notification');
});
it('has default values', function () {
createNotification({});
expect(notificationView.$('div.message').hasClass('message-confirmation')).toBe(true);
verifyTitle('');
verifyDetails([]);
verifyAction(null);
});
it('can use an error type', function () {
createNotification({type: 'error'});
expect(notificationView.$('div.message').hasClass('message-error')).toBe(true);
expect(notificationView.$('div.message').hasClass('message-confirmation')).toBe(false);
});
it('can specify a title', function () {
createNotification({title: 'notification title'});
verifyTitle('notification title');
});
it('can specify details', function () {
var expectedDetails = ['detail 1', 'detail 2'];
createNotification({details: expectedDetails});
verifyDetails(expectedDetails);
});
it ('shows an action button if text and callback are provided', function () {
createNotification({actionText: 'action text', actionCallback: function () {}});
verifyAction('action text');
});
it ('does not show an action button if callback is not provided', function () {
createNotification({actionText: 'action text'});
verifyAction(null);
});
it ('does not show an action button if text is not provided', function () {
createNotification({actionCallback: function () {}});
verifyAction(null);
});
it ('triggers the callback when the action button is clicked', function () {
var actionCallback = jasmine.createSpy('Spy on callback');
var view = createNotification({actionText: 'action text', actionCallback: actionCallback});
notificationView.$('a.action-primary').click();
expect(actionCallback).toHaveBeenCalledWith(view);
});
});
});
(function(Backbone) { (function(Backbone, _, $, gettext, ngettext, interpolate_text, NotificationModel, NotificationView) {
var CohortEditorView = Backbone.View.extend({ var CohortEditorView = Backbone.View.extend({
events : {
"submit .cohort-management-group-add-form": "addStudents"
},
initialize: function(options) { initialize: function(options) {
this.template = _.template($('#cohort-editor-tpl').text()); this.template = _.template($('#cohort-editor-tpl').text());
this.cohorts = options.cohorts;
this.advanced_settings_url = options.advanced_settings_url; this.advanced_settings_url = options.advanced_settings_url;
}, },
// Any errors that are currently being displayed to the instructor (for example, unknown email addresses).
errorNotifications: null,
// Any confirmation messages that are currently being displayed (for example, number of students added).
confirmationNotifications: null,
render: function() { render: function() {
this.$el.html(this.template({ this.$el.html(this.template({
cohort: this.model, cohort: this.model,
advanced_settings_url: this.advanced_settings_url advanced_settings_url: this.advanced_settings_url
})); }));
return this; return this;
},
setCohort: function(cohort) {
this.model = cohort;
this.render();
},
addStudents: function(event) {
event.preventDefault();
var self = this,
cohorts = this.cohorts,
input = this.$('.cohort-management-group-add-students'),
add_url = this.model.url() + '/add',
students = input.val().trim(),
cohortId = this.model.id;
if (students.length > 0) {
$.post(
add_url, {'users': students}
).done(function(modifiedUsers) {
self.refreshCohorts().done(function() {
// Find the equivalent cohort in the new collection and select it
var cohort = cohorts.get(cohortId);
self.setCohort(cohort);
// Show the notifications
self.addNotifications(modifiedUsers);
// If an unknown user was specified then update the new input to have
// the original input's value. This is to allow the user to correct the
// value in case it was a typo.
if (modifiedUsers.unknown.length > 0) {
self.$('.cohort-management-group-add-students').val(students);
}
});
}).fail(function() {
self.showErrorMessage(gettext('Error adding students.'), true);
});
} else {
self.showErrorMessage(gettext('Please enter a username or email.'), true);
input.val('');
}
},
/**
* Refresh the cohort collection to get the latest set as well as up-to-date counts.
*/
refreshCohorts: function() {
return this.cohorts.fetch();
},
undelegateViewEvents: function (view) {
if (view) {
view.undelegateEvents();
}
},
showErrorMessage: function(message, removeConfirmations, model) {
if (removeConfirmations && this.confirmationNotifications) {
this.undelegateViewEvents(this.confirmationNotifications);
this.confirmationNotifications.$el.html('');
this.confirmationNotifications = null;
}
if (model === undefined) {
model = new NotificationModel();
}
model.set('type', 'error');
model.set('title', message);
this.undelegateViewEvents(this.errorNotifications);
this.errorNotifications = new NotificationView({
el: this.$('.cohort-errors'),
model: model
});
this.errorNotifications.render();
},
addNotifications: function(modifiedUsers) {
var oldCohort, title, details, numPresent, numUsersAdded, numErrors,
createErrorDetails, errorActionCallback, errorModel;
// Show confirmation messages.
this.undelegateViewEvents(this.confirmationNotifications);
numUsersAdded = modifiedUsers.added.length + modifiedUsers.changed.length;
numPresent = modifiedUsers.present.length;
if (numUsersAdded > 0 || numPresent > 0) {
title = interpolate_text(
ngettext("{numUsersAdded} student has been added to this cohort group",
"{numUsersAdded} students have been added to this cohort group", numUsersAdded),
{numUsersAdded: numUsersAdded}
);
var movedByCohort = {};
_.each(modifiedUsers.changed, function (changedInfo) {
oldCohort = changedInfo.previous_cohort;
if (oldCohort in movedByCohort) {
movedByCohort[oldCohort] = movedByCohort[oldCohort] + 1;
}
else {
movedByCohort[oldCohort] = 1;
}
});
details = [];
for (oldCohort in movedByCohort) {
details.push(
interpolate_text(
ngettext("{numMoved} student was removed from {oldCohort}",
"{numMoved} students were removed from {oldCohort}", movedByCohort[oldCohort]),
{numMoved: movedByCohort[oldCohort], oldCohort: oldCohort}
)
);
}
if (numPresent > 0) {
details.push(
interpolate_text(
ngettext("{numPresent} student was already in the cohort group",
"{numPresent} students were already in the cohort group", numPresent),
{numPresent: numPresent}
)
);
}
this.confirmationNotifications = new NotificationView({
el: this.$('.cohort-confirmations'),
model: new NotificationModel({
type: "confirmation",
title: title,
details: details
})
});
this.confirmationNotifications.render();
}
else if (this.confirmationNotifications) {
this.confirmationNotifications.$el.html('');
this.confirmationNotifications = null;
}
// Show error messages.
this.undelegateViewEvents(this.errorNotifications);
numErrors = modifiedUsers.unknown.length;
if (numErrors > 0) {
createErrorDetails = function (unknownUsers, showAllErrors) {
var numErrors = unknownUsers.length, details = [], errorLimit = 5;
for (var i = 0; i < (showAllErrors ? numErrors : Math.min(errorLimit, numErrors)); i++) {
details.push(interpolate_text(gettext("Unknown user: {user}"), {user: unknownUsers[i]}));
}
return details;
};
title = interpolate_text(
ngettext("There was an error when trying to add students:",
"There were {numErrors} errors when trying to add students:", numErrors),
{numErrors: numErrors}
);
details = createErrorDetails(modifiedUsers.unknown, false);
errorActionCallback = function (view) {
view.model.set("actionCallback", null);
view.model.set("details", createErrorDetails(modifiedUsers.unknown, true));
view.render();
};
errorModel = new NotificationModel({
details: details,
actionText: gettext("View all errors"),
actionCallback: numErrors > 5 ? errorActionCallback : null
});
this.showErrorMessage(title, false, errorModel);
}
else if (this.errorNotifications) {
this.errorNotifications.$el.html('');
this.errorNotifications = null;
}
} }
}); });
this.CohortEditorView = CohortEditorView; this.CohortEditorView = CohortEditorView;
}).call(this, Backbone); }).call(this, Backbone, _, $, gettext, ngettext, interpolate_text, NotificationModel, NotificationView);
...@@ -6,31 +6,50 @@ ...@@ -6,31 +6,50 @@
initialize: function(options) { initialize: function(options) {
this.template = _.template($('#cohorts-tpl').text()); this.template = _.template($('#cohorts-tpl').text());
this.selectorTemplate = _.template($('#cohort-selector-tpl').text());
this.advanced_settings_url = options.advanced_settings_url; this.advanced_settings_url = options.advanced_settings_url;
this.model.on('sync', this.onSync, this);
}, },
render: function() { render: function() {
this.$el.html(this.template({ this.$el.html(this.template({
cohorts: this.model.models cohorts: this.model.models
})); }));
this.renderSelector();
return this; return this;
}, },
renderSelector: function(selectedCohort) {
this.$('.cohort-select').html(this.selectorTemplate({
cohorts: this.model.models,
selectedCohort: selectedCohort
}));
},
onSync: function() {
this.renderSelector(this.getSelectedCohort());
},
getSelectedCohort: function() { getSelectedCohort: function() {
var id = this.$('.cohort-select').val(); var id = this.$('.cohort-select').val();
return this.model.get(parseInt(id)); return id && this.model.get(parseInt(id));
}, },
showCohortEditor: function(event) { showCohortEditor: function(event) {
event.preventDefault(); event.preventDefault();
var selectedCohort = this.getSelectedCohort(); var selectedCohort = this.getSelectedCohort();
if (this.editor) {
this.editor.setCohort(selectedCohort);
} else {
this.editor = new CohortEditorView({ this.editor = new CohortEditorView({
el: this.$('.cohort-management-group'), el: this.$('.cohort-management-group'),
model: selectedCohort, model: selectedCohort,
cohorts: this.model,
advanced_settings_url: this.advanced_settings_url advanced_settings_url: this.advanced_settings_url
}); });
this.editor.render(); this.editor.render();
} }
}
}); });
this.CohortsView = CohortsView; this.CohortsView = CohortsView;
......
(function(Backbone, $, _) {
var NotificationView = Backbone.View.extend({
events : {
"click .action-primary": "triggerCallback"
},
initialize: function() {
this.template = _.template($('#notification-tpl').text());
},
render: function() {
var actionText = null;
// If no actionText is passed to the template, the action button
// will not be shown.
if (this.model.get("actionText") && this.model.get("actionCallback")) {
actionText = this.model.get("actionText");
}
this.$el.html(this.template({
type: this.model.get("type"),
title: this.model.get("title"),
details: this.model.get("details"),
actionText: actionText
}));
return this;
},
triggerCallback: function(event) {
event.preventDefault();
var actionCallback = this.model.get("actionCallback");
if (actionCallback) {
actionCallback(this);
}
}
});
this.NotificationView = NotificationView;
}).call(this, Backbone, $, _);
--- ---
# JavaScript test suite description # LMS JavaScript tests (using RequireJS).
# #
# #
# To run all the tests and print results to the console: # To run all the tests and print results to the console:
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
test_suite_name: lms test_suite_name: lms
test_runner: jasmine test_runner: jasmine_requirejs
# Path prepended to source files in the coverage report (optional) # Path prepended to source files in the coverage report (optional)
# For example, if the source path # For example, if the source path
...@@ -48,19 +48,16 @@ lib_paths: ...@@ -48,19 +48,16 @@ lib_paths:
- xmodule_js/src/xmodule.js - xmodule_js/src/xmodule.js
- xmodule_js/common_static/js/vendor/underscore-min.js - xmodule_js/common_static/js/vendor/underscore-min.js
- xmodule_js/common_static/js/vendor/backbone-min.js - xmodule_js/common_static/js/vendor/backbone-min.js
- js/models/cohort.js
- js/collections/cohort.js
- js/views/cohort_editor.js
- js/views/cohorts.js
# Paths to source JavaScript files # Paths to source JavaScript files
src_paths: src_paths:
- coffee/src
- js - js
- js/common_helpers
- xmodule_js
- xmodule_js/common_static
# Paths to spec (test) JavaScript files # Paths to spec (test) JavaScript files
spec_paths: spec_paths:
- coffee/spec
- js/spec - js/spec
# Paths to fixture files (optional) # Paths to fixture files (optional)
...@@ -73,23 +70,13 @@ spec_paths: ...@@ -73,23 +70,13 @@ spec_paths:
# loadFixtures('path/to/fixture/fixture.html'); # loadFixtures('path/to/fixture/fixture.html');
# #
fixture_paths: fixture_paths:
- coffee/fixtures
- templates/instructor/instructor_dashboard_2 - templates/instructor/instructor_dashboard_2
# Regular expressions used to exclude *.js files from requirejs:
# appearing in the test runner page. paths:
# Files are included by default, which means that they main: js/spec/main
# are loaded using a <script> tag in the test runner page.
# When loading many files, this can be slow, so
# exclude any files you don't need.
#exclude_from_page:
# - path/to/lib/exclude/*
# Regular expression used to guarantee that a *.js file # Because require.js is responsible for loading all dependencies, we exclude
# is included in the test runner page. # all files from being included in <script> tags
# If a file name matches both `exclude_from_page` and exclude_from_page:
# `include_in_page`, the file WILL be included. - .*
# You can use this to exclude all files in a directory,
# but make an exception for particular files.
#include_in_page:
# - path/to/lib/include/*
---
# LMS CoffeeScript tests that are not yet using RequireJS.
#
#
# To run all the tests and print results to the console:
#
# js-test-tool run TEST_SUITE --use-firefox
#
# where `TEST_SUITE` is this file.
#
#
# To run the tests in your default browser ("dev mode"):
#
# js-test-tool dev TEST_SUITE
#
test_suite_name: lms-coffee
test_runner: jasmine
# Path prepended to source files in the coverage report (optional)
# For example, if the source path
# is "src/source.js" (relative to this YAML file)
# and the prepend path is "base/dir"
# then the coverage report will show
# "base/dir/src/source.js"
prepend_path: lms/static
# Paths to library JavaScript files (optional)
lib_paths:
- xmodule_js/common_static/js/test/i18n.js
- xmodule_js/common_static/coffee/src/ajax_prefix.js
- xmodule_js/common_static/coffee/src/logger.js
- xmodule_js/common_static/js/vendor/jasmine-jquery.js
- xmodule_js/common_static/js/vendor/jasmine-imagediff.js
- xmodule_js/common_static/js/vendor/require.js
- js/RequireJS-namespace-undefine.js
- xmodule_js/common_static/js/vendor/jquery.min.js
- xmodule_js/common_static/js/vendor/jquery-ui.min.js
- xmodule_js/common_static/js/vendor/jquery.cookie.js
- xmodule_js/common_static/js/vendor/flot/jquery.flot.js
- xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js
- xmodule_js/common_static/js/vendor/URI.min.js
- xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js
- xmodule_js/common_static/coffee/src/xblock
- xmodule_js/src/capa/
- xmodule_js/src/video/
- xmodule_js/src/xmodule.js
# Paths to source JavaScript files
src_paths:
- coffee/src
# Paths to spec (test) JavaScript files
spec_paths:
- coffee/spec
# Paths to fixture files (optional)
# The fixture path will be set automatically when using jasmine-jquery.
# (https://github.com/velesin/jasmine-jquery)
#
# You can then access fixtures using paths relative to
# the test suite description:
#
# loadFixtures('path/to/fixture/fixture.html');
#
fixture_paths:
- coffee/fixtures
# Regular expressions used to exclude *.js files from
# appearing in the test runner page.
# Files are included by default, which means that they
# are loaded using a <script> tag in the test runner page.
# When loading many files, this can be slow, so
# exclude any files you don't need.
#exclude_from_page:
# - path/to/lib/exclude/*
# Regular expression used to guarantee that a *.js file
# is included in the test runner page.
# If a file name matches both `exclude_from_page` and
# `include_in_page`, the file WILL be included.
# You can use this to exclude all files in a directory,
# but make an exception for particular files.
#include_in_page:
# - path/to/lib/include/*
<header class="cohort-management-group-header"> <header class="cohort-management-group-header">
<h3 class="group-header-title"> <h3 class="group-header-title">
<span class="title-value"><%- cohort.get('name') %></span> <span class="title-value"><%- cohort.get('name') %></span>
<span class="group-count"><%- cohort.get('user_count') %></span> <span class="group-count"><%-
interpolate(
ngettext(
'(contains 1 student)',
'(contains %(student_count)s students)',
cohort.get('user_count')
),
{ student_count: cohort.get('user_count') },
true
)
%></span>
</h3> </h3>
<div class="cohort-management-group-setup"> <div class="cohort-management-group-setup">
<div class="setup-value"> <div class="setup-value">
...@@ -19,3 +29,38 @@ ...@@ -19,3 +29,38 @@
</div> </div>
</div> </div>
</header> </header>
<!-- individual group - form -->
<div class="cohort-management-group-add">
<form action="" method="post" id="cohort-management-group-add-form" class="cohort-management-group-add-form">
<h4 class="form-title"><%- gettext('Add students to this cohort group') %></h4>
<div class="form-introduction">
<p><%- gettext('Note: Students can only be in one cohort group. Adding students to this group overrides any previous group assignment.') %></p>
</div>
<div class="cohort-confirmations"></div>
<div class="cohort-errors"></div>
<div class="form-fields">
<div class="field field-textarea is-required">
<label for="cohort-management-group-add-students" class="label">
<%- gettext('Enter email addresses and/or usernames separated by new lines or commas for students to add. *') %>
<span class="sr"><%- gettext('(Required Field)') %></span>
</label>
<textarea name="cohort-management-group-add-students" id="cohort-management-group-add-students"
class="input cohort-management-group-add-students"
placeholder="<%- gettext('e.g. johndoe@example.com, JaneDoe, joeydoe@example.com') %>"></textarea>
<span class="tip"><%- gettext('You will not get notification for emails that bounce, so please double-check spelling.') %></span>
</div>
</div>
<div class="form-actions">
<button class="form-submit button action-primary action-view">
<i class="button-icon icon icon-plus"></i> <%- gettext('Add Students') %>
</button>
</div>
</form>
</div>
<option value=""><%- gettext('Select a cohort') %></option>
<% _.each(cohorts, function(cohort) { %>
<%
var label = interpolate(
gettext('%(cohort_name)s (%(user_count)s)'),
{ cohort_name: cohort.get('name'), user_count: cohort.get('user_count') },
true
);
var isSelected = selectedCohort && selectedCohort.get('id') === cohort.get('id')
%>
<option value="<%- cohort.get('id') %>" <%= isSelected ? 'selected' : '' %>><%- label %></option>
<% }); %>
...@@ -7,22 +7,9 @@ ...@@ -7,22 +7,9 @@
<% if (cohorts.length > 0) { %> <% if (cohorts.length > 0) { %>
<div class="cohort-management-nav"> <div class="cohort-management-nav">
<form action="" method="post" name="" id="cohort-management-nav-form" class="cohort-management-nav-form"> <form action="" method="post" name="" id="cohort-management-nav-form" class="cohort-management-nav-form">
<div class="cohort-management-nav-form-select field field-select"> <div class="cohort-management-nav-form-select field field-select">
<label for="cohort-select" class="label sr">${_("Select a cohort to manage")}</label> <label for="cohort-select" class="label sr">${_("Select a cohort to manage")}</label>
<select class="input cohort-select" name="cohort-select" id="cohort-select"> <select class="input cohort-select" name="cohort-select" id="cohort-select">
<option value=""><%- gettext('Select a cohort') %></option>
<% _.each(cohorts, function(cohort) { %>
<%
var label = interpolate(
gettext('%(cohort_name)s (%(user_count)s)'),
{ cohort_name: cohort.get('name'), user_count: cohort.get('user_count') },
true
);
%>
<option value="<%- cohort.get('id') %>"><%- label %></option>
<% }); %>
</select> </select>
</div> </div>
......
...@@ -50,17 +50,20 @@ ...@@ -50,17 +50,20 @@
<script type="text/javascript" src="${static.url('js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js')}"></script>
<%static:js group='module-descriptor-js'/> <%static:js group='module-descriptor-js'/>
<%static:js group='instructor_dash'/> <%static:js group='instructor_dash'/>
<%static:js group='application'/>
## Backbone classes declared explicitly until RequireJS is supported ## Backbone classes declared explicitly until RequireJS is supported
<script type="text/javascript" src="${static.url('js/models/notification.js')}"></script>
<script type="text/javascript" src="${static.url('js/models/cohort.js')}"></script> <script type="text/javascript" src="${static.url('js/models/cohort.js')}"></script>
<script type="text/javascript" src="${static.url('js/collections/cohort.js')}"></script> <script type="text/javascript" src="${static.url('js/collections/cohort.js')}"></script>
<script type="text/javascript" src="${static.url('js/views/notification.js')}"></script>
<script type="text/javascript" src="${static.url('js/views/cohort_editor.js')}"></script> <script type="text/javascript" src="${static.url('js/views/cohort_editor.js')}"></script>
<script type="text/javascript" src="${static.url('js/views/cohorts.js')}"></script> <script type="text/javascript" src="${static.url('js/views/cohorts.js')}"></script>
</%block> </%block>
## Include Underscore templates ## Include Underscore templates
<%block name="header_extras"> <%block name="header_extras">
% for template_name in ["cohorts", "cohort-editor"]: % for template_name in ["cohorts", "cohort-editor", "cohort-selector", "notification"]:
<script type="text/template" id="${template_name}-tpl"> <script type="text/template" id="${template_name}-tpl">
<%static:include path="instructor/instructor_dashboard_2/${template_name}.underscore" /> <%static:include path="instructor/instructor_dashboard_2/${template_name}.underscore" />
</script> </script>
......
<div class="message message-<%= type %> is-shown">
<h3 class="message-title">
<%- title %>
</h3>
<% if (details.length > 0) { %>
<div class="message-copy">
<ul class="list-summary summary-items">
<% for (var i = 0; i < details.length; i++) { %>
<li class="summary-item">
<%- details[i] %>
</li>
<% } %>
</ul>
</div>
<% } %>
<% if (actionText) { %>
<div class="message-actions">
<a href="" class="action-primary"><%- actionText %></a>
</div>
<% } %>
</div>
...@@ -88,6 +88,7 @@ class Env(object): ...@@ -88,6 +88,7 @@ class Env(object):
# reason. See issue TE-415. # reason. See issue TE-415.
JS_TEST_ID_FILES = [ JS_TEST_ID_FILES = [
REPO_ROOT / 'lms/static/js_test.yml', REPO_ROOT / 'lms/static/js_test.yml',
REPO_ROOT / 'lms/static/js_test_coffee.yml',
REPO_ROOT / 'cms/static/js_test.yml', REPO_ROOT / 'cms/static/js_test.yml',
REPO_ROOT / 'cms/static/js_test_squire.yml', REPO_ROOT / 'cms/static/js_test_squire.yml',
REPO_ROOT / 'common/lib/xmodule/xmodule/js/js_test.yml', REPO_ROOT / 'common/lib/xmodule/xmodule/js/js_test.yml',
...@@ -96,6 +97,7 @@ class Env(object): ...@@ -96,6 +97,7 @@ class Env(object):
JS_TEST_ID_KEYS = [ JS_TEST_ID_KEYS = [
'lms', 'lms',
'lms-coffee',
'cms', 'cms',
'cms-squire', 'cms-squire',
'xmodule', 'xmodule',
......
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