Merge pull request #997 from MITx/feature/cale/js-tests
Feature/cale/js tests
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "common/test/phantom-jasmine"]
|
||||||
|
path = common/test/phantom-jasmine
|
||||||
|
url = https://github.com/jcarver989/phantom-jasmine.git
|
||||||
|
|||||||
2
Gemfile
2
Gemfile
@@ -3,3 +3,5 @@ ruby "1.9.3"
|
|||||||
gem 'rake'
|
gem 'rake'
|
||||||
gem 'sass', '3.1.15'
|
gem 'sass', '3.1.15'
|
||||||
gem 'bourbon', '~> 1.3.6'
|
gem 'bourbon', '~> 1.3.6'
|
||||||
|
gem 'colorize'
|
||||||
|
gem 'launchy'
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ MITX_FEATURES = {
|
|||||||
'ENABLE_DISCUSSION_SERVICE': False,
|
'ENABLE_DISCUSSION_SERVICE': False,
|
||||||
'AUTH_USE_MIT_CERTIFICATES' : False,
|
'AUTH_USE_MIT_CERTIFICATES' : False,
|
||||||
}
|
}
|
||||||
|
ENABLE_JASMINE = False
|
||||||
|
|
||||||
# needed to use lms student app
|
# needed to use lms student app
|
||||||
GENERATE_RANDOM_USER_CREDENTIALS = False
|
GENERATE_RANDOM_USER_CREDENTIALS = False
|
||||||
@@ -68,9 +69,7 @@ MAKO_TEMPLATES['main'] = [
|
|||||||
for namespace, template_dirs in lms.envs.common.MAKO_TEMPLATES.iteritems():
|
for namespace, template_dirs in lms.envs.common.MAKO_TEMPLATES.iteritems():
|
||||||
MAKO_TEMPLATES['lms.' + namespace] = template_dirs
|
MAKO_TEMPLATES['lms.' + namespace] = template_dirs
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
TEMPLATE_DIRS = MAKO_TEMPLATES['main']
|
||||||
PROJECT_ROOT / "templates",
|
|
||||||
)
|
|
||||||
|
|
||||||
MITX_ROOT_URL = ''
|
MITX_ROOT_URL = ''
|
||||||
|
|
||||||
@@ -88,10 +87,6 @@ TEMPLATE_CONTEXT_PROCESSORS = (
|
|||||||
|
|
||||||
LMS_BASE = None
|
LMS_BASE = None
|
||||||
|
|
||||||
################################# Jasmine ###################################
|
|
||||||
JASMINE_TEST_DIRECTORY = PROJECT_ROOT + '/static/coffee'
|
|
||||||
|
|
||||||
|
|
||||||
#################### CAPA External Code Evaluation #############################
|
#################### CAPA External Code Evaluation #############################
|
||||||
XQUEUE_INTERFACE = {
|
XQUEUE_INTERFACE = {
|
||||||
'url': 'http://localhost:8888',
|
'url': 'http://localhost:8888',
|
||||||
@@ -289,7 +284,4 @@ INSTALLED_APPS = (
|
|||||||
# For asset pipelining
|
# For asset pipelining
|
||||||
'pipeline',
|
'pipeline',
|
||||||
'staticfiles',
|
'staticfiles',
|
||||||
|
|
||||||
# For testing
|
|
||||||
'django_jasmine',
|
|
||||||
)
|
)
|
||||||
|
|||||||
36
cms/envs/jasmine.py
Normal file
36
cms/envs/jasmine.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
"""
|
||||||
|
This configuration is used for running jasmine tests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .test import *
|
||||||
|
from logsettings import get_logger_config
|
||||||
|
|
||||||
|
ENABLE_JASMINE = True
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
LOGGING = get_logger_config(TEST_ROOT / "log",
|
||||||
|
logging_env="dev",
|
||||||
|
tracking_filename="tracking.log",
|
||||||
|
dev_env=True,
|
||||||
|
debug=True)
|
||||||
|
|
||||||
|
PIPELINE_JS['js-test-source'] = {
|
||||||
|
'source_filenames': sum([
|
||||||
|
pipeline_group['source_filenames']
|
||||||
|
for group_name, pipeline_group
|
||||||
|
in PIPELINE_JS.items()
|
||||||
|
if group_name != 'spec'
|
||||||
|
], []),
|
||||||
|
'output_filename': 'js/cms-test-source.js'
|
||||||
|
}
|
||||||
|
|
||||||
|
PIPELINE_JS['spec'] = {
|
||||||
|
'source_filenames': sorted(rooted_glob(PROJECT_ROOT / 'static/', 'coffee/spec/**/*.coffee')),
|
||||||
|
'output_filename': 'js/cms-spec.js'
|
||||||
|
}
|
||||||
|
|
||||||
|
JASMINE_TEST_DIRECTORY = PROJECT_ROOT + '/static/coffee'
|
||||||
|
|
||||||
|
STATICFILES_DIRS.append(COMMON_ROOT / 'test' / 'phantom-jasmine' / 'lib')
|
||||||
|
|
||||||
|
INSTALLED_APPS += ('django_jasmine', )
|
||||||
@@ -8,72 +8,6 @@ describe "CMS", ->
|
|||||||
it "should initialize Views", ->
|
it "should initialize Views", ->
|
||||||
expect(CMS.Views).toBeDefined()
|
expect(CMS.Views).toBeDefined()
|
||||||
|
|
||||||
describe "start", ->
|
|
||||||
beforeEach ->
|
|
||||||
@element = $("<div>")
|
|
||||||
spyOn(CMS.Views, "Course").andReturn(jasmine.createSpyObj("Course", ["render"]))
|
|
||||||
CMS.start(@element)
|
|
||||||
|
|
||||||
it "create the Course", ->
|
|
||||||
expect(CMS.Views.Course).toHaveBeenCalledWith(el: @element)
|
|
||||||
expect(CMS.Views.Course().render).toHaveBeenCalled()
|
|
||||||
|
|
||||||
describe "view stack", ->
|
|
||||||
beforeEach ->
|
|
||||||
@currentView = jasmine.createSpy("currentView")
|
|
||||||
CMS.viewStack = [@currentView]
|
|
||||||
|
|
||||||
describe "replaceView", ->
|
|
||||||
beforeEach ->
|
|
||||||
@newView = jasmine.createSpy("newView")
|
|
||||||
CMS.on("content.show", (@expectedView) =>)
|
|
||||||
CMS.replaceView(@newView)
|
|
||||||
|
|
||||||
it "replace the views on the viewStack", ->
|
|
||||||
expect(CMS.viewStack).toEqual([@newView])
|
|
||||||
|
|
||||||
it "trigger content.show on CMS", ->
|
|
||||||
expect(@expectedView).toEqual(@newView)
|
|
||||||
|
|
||||||
describe "pushView", ->
|
|
||||||
beforeEach ->
|
|
||||||
@newView = jasmine.createSpy("newView")
|
|
||||||
CMS.on("content.show", (@expectedView) =>)
|
|
||||||
CMS.pushView(@newView)
|
|
||||||
|
|
||||||
it "push new view onto viewStack", ->
|
|
||||||
expect(CMS.viewStack).toEqual([@currentView, @newView])
|
|
||||||
|
|
||||||
it "trigger content.show on CMS", ->
|
|
||||||
expect(@expectedView).toEqual(@newView)
|
|
||||||
|
|
||||||
describe "popView", ->
|
|
||||||
it "remove the current view from the viewStack", ->
|
|
||||||
CMS.popView()
|
|
||||||
expect(CMS.viewStack).toEqual([])
|
|
||||||
|
|
||||||
describe "when there's no view on the viewStack", ->
|
|
||||||
beforeEach ->
|
|
||||||
CMS.viewStack = [@currentView]
|
|
||||||
CMS.on("content.hide", => @eventTriggered = true)
|
|
||||||
CMS.popView()
|
|
||||||
|
|
||||||
it "trigger content.hide on CMS", ->
|
|
||||||
expect(@eventTriggered).toBeTruthy
|
|
||||||
|
|
||||||
describe "when there's previous view on the viewStack", ->
|
|
||||||
beforeEach ->
|
|
||||||
@parentView = jasmine.createSpyObj("parentView", ["delegateEvents"])
|
|
||||||
CMS.viewStack = [@parentView, @currentView]
|
|
||||||
CMS.on("content.show", (@expectedView) =>)
|
|
||||||
CMS.popView()
|
|
||||||
|
|
||||||
it "trigger content.show with the previous view on CMS", ->
|
|
||||||
expect(@expectedView).toEqual @parentView
|
|
||||||
|
|
||||||
it "re-bind events on the view", ->
|
|
||||||
expect(@parentView.delegateEvents).toHaveBeenCalled()
|
|
||||||
|
|
||||||
describe "main helper", ->
|
describe "main helper", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@previousAjaxSettings = $.extend(true, {}, $.ajaxSettings)
|
@previousAjaxSettings = $.extend(true, {}, $.ajaxSettings)
|
||||||
|
|||||||
@@ -3,75 +3,4 @@ describe "CMS.Models.Module", ->
|
|||||||
expect(new CMS.Models.Module().url).toEqual("/save_item")
|
expect(new CMS.Models.Module().url).toEqual("/save_item")
|
||||||
|
|
||||||
it "set the correct default", ->
|
it "set the correct default", ->
|
||||||
expect(new CMS.Models.Module().defaults).toEqual({data: ""})
|
expect(new CMS.Models.Module().defaults).toEqual(undefined)
|
||||||
|
|
||||||
describe "loadModule", ->
|
|
||||||
describe "when the module exists", ->
|
|
||||||
beforeEach ->
|
|
||||||
@fakeModule = jasmine.createSpy("fakeModuleObject")
|
|
||||||
window.FakeModule = jasmine.createSpy("FakeModule").andReturn(@fakeModule)
|
|
||||||
@module = new CMS.Models.Module(type: "FakeModule")
|
|
||||||
@stubDiv = $('<div />')
|
|
||||||
@stubElement = $('<div class="xmodule_edit" />')
|
|
||||||
@stubElement.data('type', "FakeModule")
|
|
||||||
|
|
||||||
@stubDiv.append(@stubElement)
|
|
||||||
@module.loadModule(@stubDiv)
|
|
||||||
|
|
||||||
afterEach ->
|
|
||||||
window.FakeModule = undefined
|
|
||||||
|
|
||||||
it "initialize the module", ->
|
|
||||||
expect(window.FakeModule).toHaveBeenCalled()
|
|
||||||
# Need to compare underlying nodes, because jquery selectors
|
|
||||||
# aren't equal even when they point to the same node.
|
|
||||||
# http://stackoverflow.com/questions/9505437/how-to-test-jquery-with-jasmine-for-element-id-if-used-as-this
|
|
||||||
expectedNode = @stubElement[0]
|
|
||||||
actualNode = window.FakeModule.mostRecentCall.args[0][0]
|
|
||||||
|
|
||||||
expect(actualNode).toEqual(expectedNode)
|
|
||||||
expect(@module.module).toEqual(@fakeModule)
|
|
||||||
|
|
||||||
describe "when the module does not exists", ->
|
|
||||||
beforeEach ->
|
|
||||||
@previousConsole = window.console
|
|
||||||
window.console = jasmine.createSpyObj("fakeConsole", ["error"])
|
|
||||||
@module = new CMS.Models.Module(type: "HTML")
|
|
||||||
@module.loadModule($("<div>"))
|
|
||||||
|
|
||||||
afterEach ->
|
|
||||||
window.console = @previousConsole
|
|
||||||
|
|
||||||
it "print out error to log", ->
|
|
||||||
expect(window.console.error).toHaveBeenCalled()
|
|
||||||
expect(window.console.error.mostRecentCall.args[0]).toMatch("^Unable to load")
|
|
||||||
|
|
||||||
|
|
||||||
describe "editUrl", ->
|
|
||||||
it "construct the correct URL based on id", ->
|
|
||||||
expect(new CMS.Models.Module(id: "i4x://mit.edu/module/html_123").editUrl())
|
|
||||||
.toEqual("/edit_item?id=i4x%3A%2F%2Fmit.edu%2Fmodule%2Fhtml_123")
|
|
||||||
|
|
||||||
describe "save", ->
|
|
||||||
beforeEach ->
|
|
||||||
spyOn(Backbone.Model.prototype, "save")
|
|
||||||
@module = new CMS.Models.Module()
|
|
||||||
|
|
||||||
describe "when the module exists", ->
|
|
||||||
beforeEach ->
|
|
||||||
@module.module = jasmine.createSpyObj("FakeModule", ["save"])
|
|
||||||
@module.module.save.andReturn("module data")
|
|
||||||
@module.save()
|
|
||||||
|
|
||||||
it "set the data and call save on the module", ->
|
|
||||||
expect(@module.get("data")).toEqual("\"module data\"")
|
|
||||||
|
|
||||||
it "call save on the backbone model", ->
|
|
||||||
expect(Backbone.Model.prototype.save).toHaveBeenCalled()
|
|
||||||
|
|
||||||
describe "when the module does not exists", ->
|
|
||||||
beforeEach ->
|
|
||||||
@module.save()
|
|
||||||
|
|
||||||
it "call save on the backbone model", ->
|
|
||||||
expect(Backbone.Model.prototype.save).toHaveBeenCalled()
|
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
describe "CMS.Views.Course", ->
|
|
||||||
beforeEach ->
|
|
||||||
setFixtures """
|
|
||||||
<section id="main-section">
|
|
||||||
<section class="main-content"></section>
|
|
||||||
<ol id="weeks">
|
|
||||||
<li class="cal week-one" style="height: 50px"></li>
|
|
||||||
<li class="cal week-two" style="height: 100px"></li>
|
|
||||||
</ol>
|
|
||||||
</section>
|
|
||||||
"""
|
|
||||||
CMS.unbind()
|
|
||||||
|
|
||||||
describe "render", ->
|
|
||||||
beforeEach ->
|
|
||||||
spyOn(CMS.Views, "Week").andReturn(jasmine.createSpyObj("Week", ["render"]))
|
|
||||||
new CMS.Views.Course(el: $("#main-section")).render()
|
|
||||||
|
|
||||||
it "create week view for each week",->
|
|
||||||
expect(CMS.Views.Week.calls[0].args[0])
|
|
||||||
.toEqual({ el: $(".week-one").get(0), height: 101 })
|
|
||||||
expect(CMS.Views.Week.calls[1].args[0])
|
|
||||||
.toEqual({ el: $(".week-two").get(0), height: 101 })
|
|
||||||
|
|
||||||
describe "on content.show", ->
|
|
||||||
beforeEach ->
|
|
||||||
@view = new CMS.Views.Course(el: $("#main-section"))
|
|
||||||
@subView = jasmine.createSpyObj("subView", ["render"])
|
|
||||||
@subView.render.andReturn(el: "Subview Content")
|
|
||||||
spyOn(@view, "contentHeight").andReturn(100)
|
|
||||||
CMS.trigger("content.show", @subView)
|
|
||||||
|
|
||||||
afterEach ->
|
|
||||||
$("body").removeClass("content")
|
|
||||||
|
|
||||||
it "add content class to body", ->
|
|
||||||
expect($("body").attr("class")).toEqual("content")
|
|
||||||
|
|
||||||
it "replace content in .main-content", ->
|
|
||||||
expect($(".main-content")).toHaveHtml("Subview Content")
|
|
||||||
|
|
||||||
it "set height on calendar", ->
|
|
||||||
expect($(".cal")).toHaveCss(height: "100px")
|
|
||||||
|
|
||||||
it "set minimum height on all sections", ->
|
|
||||||
expect($("#main-section>section")).toHaveCss(minHeight: "100px")
|
|
||||||
|
|
||||||
describe "on content.hide", ->
|
|
||||||
beforeEach ->
|
|
||||||
$("body").addClass("content")
|
|
||||||
@view = new CMS.Views.Course(el: $("#main-section"))
|
|
||||||
$(".cal").css(height: 100)
|
|
||||||
$("#main-section>section").css(minHeight: 100)
|
|
||||||
CMS.trigger("content.hide")
|
|
||||||
|
|
||||||
afterEach ->
|
|
||||||
$("body").removeClass("content")
|
|
||||||
|
|
||||||
it "remove content class from body", ->
|
|
||||||
expect($("body").attr("class")).toEqual("")
|
|
||||||
|
|
||||||
it "remove content from .main-content", ->
|
|
||||||
expect($(".main-content")).toHaveHtml("")
|
|
||||||
|
|
||||||
it "reset height on calendar", ->
|
|
||||||
expect($(".cal")).not.toHaveCss(height: "100px")
|
|
||||||
|
|
||||||
it "reset minimum height on all sections", ->
|
|
||||||
expect($("#main-section>section")).not.toHaveCss(minHeight: "100px")
|
|
||||||
|
|
||||||
describe "maxWeekHeight", ->
|
|
||||||
it "return maximum height of the week element", ->
|
|
||||||
@view = new CMS.Views.Course(el: $("#main-section"))
|
|
||||||
expect(@view.maxWeekHeight()).toEqual(101)
|
|
||||||
|
|
||||||
describe "contentHeight", ->
|
|
||||||
beforeEach ->
|
|
||||||
$("body").append($('<header id="test">').height(100).hide())
|
|
||||||
|
|
||||||
afterEach ->
|
|
||||||
$("body>header#test").remove()
|
|
||||||
|
|
||||||
it "return the window height minus the header bar", ->
|
|
||||||
@view = new CMS.Views.Course(el: $("#main-section"))
|
|
||||||
expect(@view.contentHeight()).toEqual($(window).height() - 100)
|
|
||||||
@@ -1,81 +1,74 @@
|
|||||||
describe "CMS.Views.ModuleEdit", ->
|
describe "CMS.Views.ModuleEdit", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@stubModule = jasmine.createSpyObj("Module", ["editUrl", "loadModule"])
|
@stubModule = jasmine.createSpy("CMS.Models.Module")
|
||||||
spyOn($.fn, "load")
|
@stubModule.id = 'stub-id'
|
||||||
|
|
||||||
|
|
||||||
setFixtures """
|
setFixtures """
|
||||||
<div id="module-edit">
|
<li class="component" id="stub-id">
|
||||||
<a href="#" class="save-update">save</a>
|
<div class="component-editor">
|
||||||
<a href="#" class="cancel">cancel</a>
|
<div class="module-editor">
|
||||||
<ol>
|
${editor}
|
||||||
<li>
|
</div>
|
||||||
<a href="#" class="module-edit" data-id="i4x://mitx/course/html/module" data-type="html">submodule</a>
|
<a href="#" class="save-button">Save</a>
|
||||||
</li>
|
<a href="#" class="cancel-button">Cancel</a>
|
||||||
</ol>
|
|
||||||
</div>
|
</div>
|
||||||
""" #"
|
<div class="component-actions">
|
||||||
|
<a href="#" class="edit-button"><span class="edit-icon white"></span>Edit</a>
|
||||||
|
<a href="#" class="delete-button"><span class="delete-icon white"></span>Delete</a>
|
||||||
|
</div>
|
||||||
|
<a href="#" class="drag-handle"></a>
|
||||||
|
<section class="xmodule_display xmodule_stub" data-type="StubModule">
|
||||||
|
<div id="stub-module-content"/>
|
||||||
|
</section>
|
||||||
|
</li>
|
||||||
|
"""
|
||||||
|
spyOn($.fn, 'load').andReturn(@moduleData)
|
||||||
|
|
||||||
|
@moduleEdit = new CMS.Views.ModuleEdit(
|
||||||
|
el: $(".component")
|
||||||
|
model: @stubModule
|
||||||
|
onDelete: jasmine.createSpy()
|
||||||
|
)
|
||||||
CMS.unbind()
|
CMS.unbind()
|
||||||
|
|
||||||
describe "defaults", ->
|
describe "class definition", ->
|
||||||
it "set the correct tagName", ->
|
it "sets the correct tagName", ->
|
||||||
expect(new CMS.Views.ModuleEdit(model: @stubModule).tagName).toEqual("section")
|
expect(@moduleEdit.tagName).toEqual("li")
|
||||||
|
|
||||||
it "set the correct className", ->
|
it "sets the correct className", ->
|
||||||
expect(new CMS.Views.ModuleEdit(model: @stubModule).className).toEqual("edit-pane")
|
expect(@moduleEdit.className).toEqual("component")
|
||||||
|
|
||||||
describe "view creation", ->
|
describe "methods", ->
|
||||||
beforeEach ->
|
describe "initialize", ->
|
||||||
@stubModule.editUrl.andReturn("/edit_item?id=stub_module")
|
beforeEach ->
|
||||||
new CMS.Views.ModuleEdit(el: $("#module-edit"), model: @stubModule)
|
spyOn(CMS.Views.ModuleEdit.prototype, 'render')
|
||||||
|
@moduleEdit = new CMS.Views.ModuleEdit(
|
||||||
|
el: $(".component")
|
||||||
|
model: @stubModule
|
||||||
|
onDelete: jasmine.createSpy()
|
||||||
|
)
|
||||||
|
|
||||||
it "load the edit via ajax and pass to the model", ->
|
it "renders the module editor", ->
|
||||||
expect($.fn.load).toHaveBeenCalledWith("/edit_item?id=stub_module", jasmine.any(Function))
|
expect(@moduleEdit.render).toHaveBeenCalled()
|
||||||
if $.fn.load.mostRecentCall
|
|
||||||
$.fn.load.mostRecentCall.args[1]()
|
|
||||||
expect(@stubModule.loadModule).toHaveBeenCalledWith($("#module-edit").get(0))
|
|
||||||
|
|
||||||
describe "save", ->
|
describe "render", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@stubJqXHR = jasmine.createSpy("stubJqXHR")
|
spyOn(@moduleEdit, 'loadDisplay')
|
||||||
@stubJqXHR.success = jasmine.createSpy("stubJqXHR.success").andReturn(@stubJqXHR)
|
spyOn(@moduleEdit, 'delegateEvents')
|
||||||
@stubJqXHR.error = jasmine.createSpy("stubJqXHR.error").andReturn(@stubJqXHR)
|
@moduleEdit.render()
|
||||||
@stubModule.save = jasmine.createSpy("stubModule.save").andReturn(@stubJqXHR)
|
|
||||||
new CMS.Views.ModuleEdit(el: $(".module-edit"), model: @stubModule)
|
|
||||||
spyOn(window, "alert")
|
|
||||||
$(".save-update").click()
|
|
||||||
|
|
||||||
it "call save on the model", ->
|
it "loads the module preview and editor via ajax on the view element", ->
|
||||||
expect(@stubModule.save).toHaveBeenCalled()
|
expect(@moduleEdit.$el.load).toHaveBeenCalledWith("/preview_component/#{@moduleEdit.model.id}", jasmine.any(Function))
|
||||||
|
@moduleEdit.$el.load.mostRecentCall.args[1]()
|
||||||
|
expect(@moduleEdit.loadDisplay).toHaveBeenCalled()
|
||||||
|
expect(@moduleEdit.delegateEvents).toHaveBeenCalled()
|
||||||
|
|
||||||
it "alert user on success", ->
|
describe "loadDisplay", ->
|
||||||
@stubJqXHR.success.mostRecentCall.args[0]()
|
beforeEach ->
|
||||||
expect(window.alert).toHaveBeenCalledWith("Your changes have been saved.")
|
spyOn(XModule, 'loadModule')
|
||||||
|
@moduleEdit.loadDisplay()
|
||||||
|
|
||||||
it "alert user on error", ->
|
it "loads the .xmodule-display inside the module editor", ->
|
||||||
@stubJqXHR.error.mostRecentCall.args[0]()
|
expect(XModule.loadModule).toHaveBeenCalled()
|
||||||
expect(window.alert).toHaveBeenCalledWith("There was an error saving your changes. Please try again.")
|
expect(XModule.loadModule.mostRecentCall.args[0]).toBe($('.xmodule_display'))
|
||||||
|
|
||||||
describe "cancel", ->
|
|
||||||
beforeEach ->
|
|
||||||
spyOn(CMS, "popView")
|
|
||||||
@view = new CMS.Views.ModuleEdit(el: $("#module-edit"), model: @stubModule)
|
|
||||||
$(".cancel").click()
|
|
||||||
|
|
||||||
it "pop current view from viewStack", ->
|
|
||||||
expect(CMS.popView).toHaveBeenCalled()
|
|
||||||
|
|
||||||
describe "editSubmodule", ->
|
|
||||||
beforeEach ->
|
|
||||||
@view = new CMS.Views.ModuleEdit(el: $("#module-edit"), model: @stubModule)
|
|
||||||
spyOn(CMS, "pushView")
|
|
||||||
spyOn(CMS.Views, "ModuleEdit")
|
|
||||||
.andReturn(@view = jasmine.createSpy("Views.ModuleEdit"))
|
|
||||||
spyOn(CMS.Models, "Module")
|
|
||||||
.andReturn(@model = jasmine.createSpy("Models.Module"))
|
|
||||||
$(".module-edit").click()
|
|
||||||
|
|
||||||
it "push another module editing view into viewStack", ->
|
|
||||||
expect(CMS.pushView).toHaveBeenCalledWith @view
|
|
||||||
expect(CMS.Views.ModuleEdit).toHaveBeenCalledWith model: @model
|
|
||||||
expect(CMS.Models.Module).toHaveBeenCalledWith
|
|
||||||
id: "i4x://mitx/course/html/module"
|
|
||||||
type: "html"
|
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
describe "CMS.Views.Module", ->
|
|
||||||
beforeEach ->
|
|
||||||
setFixtures """
|
|
||||||
<div id="module" data-id="i4x://mitx/course/html/module" data-type="html">
|
|
||||||
<a href="#" class="module-edit">edit</a>
|
|
||||||
</div>
|
|
||||||
"""
|
|
||||||
|
|
||||||
describe "edit", ->
|
|
||||||
beforeEach ->
|
|
||||||
@view = new CMS.Views.Module(el: $("#module"))
|
|
||||||
spyOn(CMS, "replaceView")
|
|
||||||
spyOn(CMS.Views, "ModuleEdit")
|
|
||||||
.andReturn(@view = jasmine.createSpy("Views.ModuleEdit"))
|
|
||||||
spyOn(CMS.Models, "Module")
|
|
||||||
.andReturn(@model = jasmine.createSpy("Models.Module"))
|
|
||||||
$(".module-edit").click()
|
|
||||||
|
|
||||||
it "replace the main view with ModuleEdit view", ->
|
|
||||||
expect(CMS.replaceView).toHaveBeenCalledWith @view
|
|
||||||
expect(CMS.Views.ModuleEdit).toHaveBeenCalledWith model: @model
|
|
||||||
expect(CMS.Models.Module).toHaveBeenCalledWith
|
|
||||||
id: "i4x://mitx/course/html/module"
|
|
||||||
type: "html"
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
describe "CMS.Views.WeekEdit", ->
|
|
||||||
describe "defaults", ->
|
|
||||||
it "set the correct tagName", ->
|
|
||||||
expect(new CMS.Views.WeekEdit().tagName).toEqual("section")
|
|
||||||
|
|
||||||
it "set the correct className", ->
|
|
||||||
expect(new CMS.Views.WeekEdit().className).toEqual("edit-pane")
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
describe "CMS.Views.Week", ->
|
|
||||||
beforeEach ->
|
|
||||||
setFixtures """
|
|
||||||
<div id="week" data-id="i4x://mitx/course/chapter/week">
|
|
||||||
<div class="editable"></div>
|
|
||||||
<textarea class="editable-textarea"></textarea>
|
|
||||||
<a href="#" class="week-edit" >edit</a>
|
|
||||||
<ul class="modules">
|
|
||||||
<li id="module-one" class="module"></li>
|
|
||||||
<li id="module-two" class="module"></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
"""
|
|
||||||
CMS.unbind()
|
|
||||||
|
|
||||||
describe "render", ->
|
|
||||||
beforeEach ->
|
|
||||||
spyOn(CMS.Views, "Module").andReturn(jasmine.createSpyObj("Module", ["render"]))
|
|
||||||
$.fn.inlineEdit = jasmine.createSpy("$.fn.inlineEdit")
|
|
||||||
@view = new CMS.Views.Week(el: $("#week"), height: 100).render()
|
|
||||||
|
|
||||||
it "set the height of the element", ->
|
|
||||||
expect(@view.el).toHaveCss(height: "100px")
|
|
||||||
|
|
||||||
it "make .editable as inline editor", ->
|
|
||||||
expect($.fn.inlineEdit.calls[0].object.get(0))
|
|
||||||
.toEqual($(".editable").get(0))
|
|
||||||
|
|
||||||
it "make .editable-test as inline editor", ->
|
|
||||||
expect($.fn.inlineEdit.calls[1].object.get(0))
|
|
||||||
.toEqual($(".editable-textarea").get(0))
|
|
||||||
|
|
||||||
it "create module subview for each module", ->
|
|
||||||
expect(CMS.Views.Module.calls[0].args[0])
|
|
||||||
.toEqual({ el: $("#module-one").get(0) })
|
|
||||||
expect(CMS.Views.Module.calls[1].args[0])
|
|
||||||
.toEqual({ el: $("#module-two").get(0) })
|
|
||||||
|
|
||||||
describe "edit", ->
|
|
||||||
beforeEach ->
|
|
||||||
new CMS.Views.Week(el: $("#week"), height: 100).render()
|
|
||||||
spyOn(CMS, "replaceView")
|
|
||||||
spyOn(CMS.Views, "WeekEdit")
|
|
||||||
.andReturn(@view = jasmine.createSpy("Views.WeekEdit"))
|
|
||||||
$(".week-edit").click()
|
|
||||||
|
|
||||||
it "replace the content with edit week view", ->
|
|
||||||
expect(CMS.replaceView).toHaveBeenCalledWith @view
|
|
||||||
expect(CMS.Views.WeekEdit).toHaveBeenCalled()
|
|
||||||
|
|
||||||
describe "on content.show", ->
|
|
||||||
beforeEach ->
|
|
||||||
@view = new CMS.Views.Week(el: $("#week"), height: 100).render()
|
|
||||||
@view.$el.height("")
|
|
||||||
@view.setHeight()
|
|
||||||
|
|
||||||
it "set the correct height", ->
|
|
||||||
expect(@view.el).toHaveCss(height: "100px")
|
|
||||||
|
|
||||||
describe "on content.hide", ->
|
|
||||||
beforeEach ->
|
|
||||||
@view = new CMS.Views.Week(el: $("#week"), height: 100).render()
|
|
||||||
@view.$el.height("100px")
|
|
||||||
@view.resetHeight()
|
|
||||||
|
|
||||||
it "remove height from the element", ->
|
|
||||||
expect(@view.el).not.toHaveCss(height: "100px")
|
|
||||||
@@ -6,28 +6,6 @@ AjaxPrefix.addAjaxPrefix(jQuery, -> CMS.prefix)
|
|||||||
|
|
||||||
prefix: $("meta[name='path_prefix']").attr('content')
|
prefix: $("meta[name='path_prefix']").attr('content')
|
||||||
|
|
||||||
viewStack: []
|
|
||||||
|
|
||||||
start: (el) ->
|
|
||||||
new CMS.Views.Course(el: el).render()
|
|
||||||
|
|
||||||
replaceView: (view) ->
|
|
||||||
@viewStack = [view]
|
|
||||||
CMS.trigger('content.show', view)
|
|
||||||
|
|
||||||
pushView: (view) ->
|
|
||||||
@viewStack.push(view)
|
|
||||||
CMS.trigger('content.show', view)
|
|
||||||
|
|
||||||
popView: ->
|
|
||||||
@viewStack.pop()
|
|
||||||
if _.isEmpty(@viewStack)
|
|
||||||
CMS.trigger('content.hide')
|
|
||||||
else
|
|
||||||
view = _.last(@viewStack)
|
|
||||||
CMS.trigger('content.show', view)
|
|
||||||
view.delegateEvents()
|
|
||||||
|
|
||||||
_.extend CMS, Backbone.Events
|
_.extend CMS, Backbone.Events
|
||||||
|
|
||||||
$ ->
|
$ ->
|
||||||
@@ -41,7 +19,3 @@ $ ->
|
|||||||
navigator.userAgent.match /iPhone|iPod|iPad/i
|
navigator.userAgent.match /iPhone|iPod|iPad/i
|
||||||
|
|
||||||
$('body').addClass 'touch-based-device' if onTouchBasedDevice()
|
$('body').addClass 'touch-based-device' if onTouchBasedDevice()
|
||||||
|
|
||||||
|
|
||||||
CMS.start($('section.main-container'))
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
class CMS.Models.NewModule extends Backbone.Model
|
|
||||||
url: '/clone_item'
|
|
||||||
|
|
||||||
newUrl: ->
|
|
||||||
"/new_item?#{$.param(parent_location: @get('parent_location'))}"
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
class CMS.Views.Course extends Backbone.View
|
|
||||||
initialize: ->
|
|
||||||
CMS.on('content.show', @showContent)
|
|
||||||
CMS.on('content.hide', @hideContent)
|
|
||||||
|
|
||||||
render: ->
|
|
||||||
@$('#weeks > li').each (index, week) =>
|
|
||||||
new CMS.Views.Week(el: week, height: @maxWeekHeight()).render()
|
|
||||||
return @
|
|
||||||
|
|
||||||
showContent: (subview) =>
|
|
||||||
$('body').addClass('content')
|
|
||||||
@$('.main-content').html(subview.render().el)
|
|
||||||
@$('.cal').css height: @contentHeight()
|
|
||||||
@$('>section').css minHeight: @contentHeight()
|
|
||||||
|
|
||||||
hideContent: =>
|
|
||||||
$('body').removeClass('content')
|
|
||||||
@$('.main-content').empty()
|
|
||||||
@$('.cal').css height: ''
|
|
||||||
@$('>section').css minHeight: ''
|
|
||||||
|
|
||||||
maxWeekHeight: ->
|
|
||||||
weekElementBorderSize = 1
|
|
||||||
_.max($('#weeks > li').map -> $(this).height()) + weekElementBorderSize
|
|
||||||
|
|
||||||
contentHeight: ->
|
|
||||||
$(window).height() - $('body>header').outerHeight()
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
class CMS.Views.Module extends Backbone.View
|
|
||||||
events:
|
|
||||||
"click .module-edit": "edit"
|
|
||||||
|
|
||||||
edit: (event) =>
|
|
||||||
event.preventDefault()
|
|
||||||
previewType = @$el.data('preview-type')
|
|
||||||
moduleType = @$el.data('type')
|
|
||||||
CMS.replaceView new CMS.Views.ModuleEdit
|
|
||||||
model: new CMS.Models.Module
|
|
||||||
id: @$el.data('id')
|
|
||||||
type: if moduleType == 'None' then null else moduleType
|
|
||||||
previewType: if previewType == 'None' then null else previewType
|
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
class CMS.Views.ModuleAdd extends Backbone.View
|
|
||||||
tagName: 'section'
|
|
||||||
className: 'add-pane'
|
|
||||||
|
|
||||||
events:
|
|
||||||
'click .cancel': 'cancel'
|
|
||||||
'click .save': 'save'
|
|
||||||
|
|
||||||
initialize: ->
|
|
||||||
@$el.load @model.newUrl()
|
|
||||||
|
|
||||||
save: (event) ->
|
|
||||||
event.preventDefault()
|
|
||||||
@model.save({
|
|
||||||
name: @$el.find('.name').val()
|
|
||||||
template: $(event.target).data('template-id')
|
|
||||||
}, {
|
|
||||||
success: -> CMS.popView()
|
|
||||||
error: -> alert('Create failed')
|
|
||||||
})
|
|
||||||
|
|
||||||
cancel: (event) ->
|
|
||||||
event.preventDefault()
|
|
||||||
CMS.popView()
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
class CMS.Views.Week extends Backbone.View
|
|
||||||
events:
|
|
||||||
'click .week-edit': 'edit'
|
|
||||||
'click .new-module': 'new'
|
|
||||||
|
|
||||||
initialize: ->
|
|
||||||
CMS.on('content.show', @resetHeight)
|
|
||||||
CMS.on('content.hide', @setHeight)
|
|
||||||
|
|
||||||
render: ->
|
|
||||||
@setHeight()
|
|
||||||
@$('.editable').inlineEdit()
|
|
||||||
@$('.editable-textarea').inlineEdit(control: 'textarea')
|
|
||||||
@$('.modules .module').each ->
|
|
||||||
new CMS.Views.Module(el: this).render()
|
|
||||||
return @
|
|
||||||
|
|
||||||
edit: (event) ->
|
|
||||||
event.preventDefault()
|
|
||||||
CMS.replaceView(new CMS.Views.WeekEdit())
|
|
||||||
|
|
||||||
setHeight: =>
|
|
||||||
@$el.height(@options.height)
|
|
||||||
|
|
||||||
resetHeight: =>
|
|
||||||
@$el.height('')
|
|
||||||
|
|
||||||
new: (event) =>
|
|
||||||
event.preventDefault()
|
|
||||||
CMS.replaceView new CMS.Views.ModuleAdd
|
|
||||||
model: new CMS.Models.NewModule
|
|
||||||
parent_location: @$el.data('id')
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
class CMS.Views.WeekEdit extends Backbone.View
|
|
||||||
tagName: 'section'
|
|
||||||
className: 'edit-pane'
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Jasmine Spec Runner</title>
|
|
||||||
|
|
||||||
{% load staticfiles %}
|
|
||||||
<link rel="stylesheet" href="{% static 'jasmine-latest/jasmine.css' %}" media="screen">
|
|
||||||
|
|
||||||
{# core files #}
|
|
||||||
<script src="{% static 'jasmine-latest/jasmine.js' %}"></script>
|
|
||||||
<script src="{% static 'jasmine-latest/jasmine-html.js' %}"></script>
|
|
||||||
<script src="{% static 'js/vendor/jasmine-jquery.js' %}"></script>
|
|
||||||
|
|
||||||
{# source files #}
|
|
||||||
{% for url in suite.js_files %}
|
|
||||||
<script src="{{ url }}"></script>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% load compressed %}
|
|
||||||
{# static files #}
|
|
||||||
{% compressed_js 'main' %}
|
|
||||||
|
|
||||||
{# spec files #}
|
|
||||||
{% compressed_js 'spec' %}
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<h1>Jasmine Spec Runner</h1>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
{% block jasmine %}
|
|
||||||
(function() {
|
|
||||||
var jasmineEnv = jasmine.getEnv();
|
|
||||||
jasmineEnv.updateInterval = 1000;
|
|
||||||
|
|
||||||
var trivialReporter = new jasmine.TrivialReporter();
|
|
||||||
|
|
||||||
jasmineEnv.addReporter(trivialReporter);
|
|
||||||
|
|
||||||
jasmineEnv.specFilter = function(spec) {
|
|
||||||
return trivialReporter.specFilter(spec);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Additional configuration can be done in this block
|
|
||||||
{% block jasmine_extra %}{% endblock %}
|
|
||||||
|
|
||||||
var currentWindowOnload = window.onload;
|
|
||||||
|
|
||||||
window.onload = function() {
|
|
||||||
if (currentWindowOnload) {
|
|
||||||
currentWindowOnload();
|
|
||||||
}
|
|
||||||
execJasmine();
|
|
||||||
};
|
|
||||||
|
|
||||||
function execJasmine() {
|
|
||||||
jasmineEnv.execute();
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
{% endblock %}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -68,7 +68,7 @@ urlpatterns += (
|
|||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.ENABLE_JASMINE:
|
||||||
## Jasmine
|
## Jasmine
|
||||||
urlpatterns = urlpatterns + (url(r'^_jasmine/', include('django_jasmine.urls')),)
|
urlpatterns = urlpatterns + (url(r'^_jasmine/', include('django_jasmine.urls')),)
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
<script src="{% static 'jasmine-latest/jasmine.js' %}"></script>
|
<script src="{% static 'jasmine-latest/jasmine.js' %}"></script>
|
||||||
<script src="{% static 'jasmine-latest/jasmine-html.js' %}"></script>
|
<script src="{% static 'jasmine-latest/jasmine-html.js' %}"></script>
|
||||||
<script src="{% static 'js/vendor/jasmine-jquery.js' %}"></script>
|
<script src="{% static 'js/vendor/jasmine-jquery.js' %}"></script>
|
||||||
|
<script src="{% static 'console-runner.js' %}"></script>
|
||||||
|
|
||||||
{# source files #}
|
{# source files #}
|
||||||
{% for url in suite.js_files %}
|
{% for url in suite.js_files %}
|
||||||
@@ -19,8 +20,7 @@
|
|||||||
|
|
||||||
{% load compressed %}
|
{% load compressed %}
|
||||||
{# static files #}
|
{# static files #}
|
||||||
{% compressed_js 'application' %}
|
{% compressed_js 'js-test-source' %}
|
||||||
{% compressed_js 'module-js' %}
|
|
||||||
|
|
||||||
{# spec files #}
|
{# spec files #}
|
||||||
{% compressed_js 'spec' %}
|
{% compressed_js 'spec' %}
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
{% block jasmine %}
|
{% block jasmine %}
|
||||||
|
var console_reporter = new jasmine.ConsoleReporter();
|
||||||
(function() {
|
(function() {
|
||||||
var jasmineEnv = jasmine.getEnv();
|
var jasmineEnv = jasmine.getEnv();
|
||||||
jasmineEnv.updateInterval = 1000;
|
jasmineEnv.updateInterval = 1000;
|
||||||
@@ -39,6 +40,7 @@
|
|||||||
var trivialReporter = new jasmine.TrivialReporter();
|
var trivialReporter = new jasmine.TrivialReporter();
|
||||||
|
|
||||||
jasmineEnv.addReporter(trivialReporter);
|
jasmineEnv.addReporter(trivialReporter);
|
||||||
|
jasmine.getEnv().addReporter(console_reporter);
|
||||||
|
|
||||||
jasmineEnv.specFilter = function(spec) {
|
jasmineEnv.specFilter = function(spec) {
|
||||||
return trivialReporter.specFilter(spec);
|
return trivialReporter.specFilter(spec);
|
||||||
1
common/test/phantom-jasmine
Submodule
1
common/test/phantom-jasmine
Submodule
Submodule common/test/phantom-jasmine added at a54d435b55
@@ -1,35 +1,55 @@
|
|||||||
# Running the CMS
|
# Development Tasks
|
||||||
|
|
||||||
One can start the CMS by running `rake cms`. This will run the server on localhost
|
## Prerequisites
|
||||||
port 8001.
|
|
||||||
|
|
||||||
However, the server also needs data to work from.
|
### Ruby
|
||||||
|
|
||||||
## Installing Mongodb
|
To install all of the libraries needed for our rake commands, run `bundle install`.
|
||||||
|
This will read the `Gemfile` and install all of the gems specified there.
|
||||||
|
|
||||||
Please see http://www.mongodb.org/downloads for more detailed instructions.
|
### Python
|
||||||
|
|
||||||
### Ubuntu
|
In order, run the following:
|
||||||
|
|
||||||
sudo apt-get install mongodb
|
pip install -r pre-requirements.txt
|
||||||
|
pip install -r requirements.txt
|
||||||
|
pip install -r test-requirements.txt
|
||||||
|
|
||||||
### OSX
|
### Binaries
|
||||||
|
|
||||||
Use the MacPorts package `mongodb` or the Homebrew formula `mongodb`
|
Install the following:
|
||||||
|
|
||||||
## Initializing Mongodb
|
* Mongodb (http://www.mongodb.org/)
|
||||||
|
|
||||||
Check out the course data directories that you want to work with into the
|
### Databases
|
||||||
`GITHUB_REPO_ROOT` (by default, `../data`). Then run the following command:
|
|
||||||
|
|
||||||
|
Run the following to setup the relational database before starting servers:
|
||||||
|
|
||||||
rake django-admin[import,cms,dev,../data]
|
rake resetdb
|
||||||
|
|
||||||
Replace `../data` with your `GITHUB_REPO_ROOT` if it's not the default value.
|
## Starting development servers
|
||||||
|
|
||||||
This will import all courses in your data directory into mongodb
|
Both the LMS and Studio can be started using the following shortcut tasks
|
||||||
|
|
||||||
## Unit tests
|
rake lms # Start the LMS
|
||||||
|
rake cms # Start studio
|
||||||
|
rake lms[cms.dev] # Start LMS to run alongside Studio
|
||||||
|
rake lms[cms.dev_preview] # Start LMS to run alongside Studio in preview mode
|
||||||
|
|
||||||
|
Under the hood, this executes `django-admin.py runserver --pythonpath=$WORKING_DIRECTORY --settings=lms.envs.dev`,
|
||||||
|
which starts a local development server.
|
||||||
|
|
||||||
|
Both of these commands take arguments to start the servers in different environments
|
||||||
|
or with additional options:
|
||||||
|
|
||||||
|
# Start the LMS using the test configuration, on port 5000
|
||||||
|
rake lms[test,5000] # Executes django-admin.py runserver --pythonpath=$WORKING_DIRECTORY --setings=lms.envs.test 5000
|
||||||
|
|
||||||
|
*N.B.* You may have to escape the `[` characters, depending on your shell: `rake "lms[test,5000]"`
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
### Python Tests
|
||||||
|
|
||||||
This runs all the tests (long, uses collectstatic):
|
This runs all the tests (long, uses collectstatic):
|
||||||
|
|
||||||
@@ -43,10 +63,6 @@ xmodule can be tested independently, with this:
|
|||||||
|
|
||||||
rake test_common/lib/xmodule
|
rake test_common/lib/xmodule
|
||||||
|
|
||||||
To see all available rake commands, do this:
|
|
||||||
|
|
||||||
rake -T
|
|
||||||
|
|
||||||
To run a single django test class:
|
To run a single django test class:
|
||||||
|
|
||||||
django-admin.py test --settings=lms.envs.test --pythonpath=. lms/djangoapps/courseware/tests/tests.py:TestViewAuth
|
django-admin.py test --settings=lms.envs.test --pythonpath=. lms/djangoapps/courseware/tests/tests.py:TestViewAuth
|
||||||
@@ -67,6 +83,28 @@ To run a single nose test:
|
|||||||
|
|
||||||
Very handy: if you uncomment the `--pdb` argument in `NOSE_ARGS` in `lms/envs/test.py`, it will drop you into pdb on error. This lets you go up and down the stack and see what the values of the variables are. Check out http://docs.python.org/library/pdb.html
|
Very handy: if you uncomment the `--pdb` argument in `NOSE_ARGS` in `lms/envs/test.py`, it will drop you into pdb on error. This lets you go up and down the stack and see what the values of the variables are. Check out http://docs.python.org/library/pdb.html
|
||||||
|
|
||||||
|
### Javascript Tests
|
||||||
|
|
||||||
|
These commands start a development server with jasmine testing enabled, and launch your default browser
|
||||||
|
pointing to those tests
|
||||||
|
|
||||||
|
rake browse_jasmine_{lms,cms}
|
||||||
|
|
||||||
|
To run the tests headless, you must install phantomjs (http://phantomjs.org/download.html).
|
||||||
|
|
||||||
|
rake phantomjs_jasmine_{lms,cms}
|
||||||
|
|
||||||
|
If the `phantomjs` binary is not on the path, set the `PHANTOMJS_PATH` environment variable to point to it
|
||||||
|
|
||||||
|
PHANTOMJS_PATH=/path/to/phantomjs rake phantomjs_jasmine_{lms,cms}
|
||||||
|
|
||||||
|
|
||||||
|
## Getting More Information
|
||||||
|
|
||||||
|
Run the following to see a list of all rake tasks available and their arguments
|
||||||
|
|
||||||
|
rake -T
|
||||||
|
|
||||||
## Content development
|
## Content development
|
||||||
|
|
||||||
If you change course content, while running the LMS in dev mode, it is unnecessary to restart to refresh the modulestore.
|
If you change course content, while running the LMS in dev mode, it is unnecessary to restart to refresh the modulestore.
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ from .discussionsettings import *
|
|||||||
|
|
||||||
################################### FEATURES ###################################
|
################################### FEATURES ###################################
|
||||||
COURSEWARE_ENABLED = True
|
COURSEWARE_ENABLED = True
|
||||||
|
ENABLE_JASMINE = False
|
||||||
GENERATE_RANDOM_USER_CREDENTIALS = False
|
GENERATE_RANDOM_USER_CREDENTIALS = False
|
||||||
PERFSTATS = False
|
PERFSTATS = False
|
||||||
|
|
||||||
@@ -446,16 +447,13 @@ PIPELINE_JS = {
|
|||||||
'source_filenames': module_js,
|
'source_filenames': module_js,
|
||||||
'output_filename': 'js/lms-modules.js',
|
'output_filename': 'js/lms-modules.js',
|
||||||
},
|
},
|
||||||
'spec': {
|
|
||||||
'source_filenames': sorted(rooted_glob(PROJECT_ROOT / 'static/', 'coffee/spec/**/*.coffee')),
|
|
||||||
'output_filename': 'js/lms-spec.js'
|
|
||||||
},
|
|
||||||
'discussion': {
|
'discussion': {
|
||||||
'source_filenames': discussion_js,
|
'source_filenames': discussion_js,
|
||||||
'output_filename': 'js/discussion.js'
|
'output_filename': 'js/discussion.js'
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIPELINE_DISABLE_WRAPPER = True
|
PIPELINE_DISABLE_WRAPPER = True
|
||||||
|
|
||||||
# Compile all coffee files in course data directories if they are out of date.
|
# Compile all coffee files in course data directories if they are out of date.
|
||||||
@@ -540,9 +538,6 @@ INSTALLED_APPS = (
|
|||||||
'wiki.plugins.notifications',
|
'wiki.plugins.notifications',
|
||||||
'course_wiki.plugins.markdownedx',
|
'course_wiki.plugins.markdownedx',
|
||||||
|
|
||||||
# For testing
|
|
||||||
'django_jasmine',
|
|
||||||
|
|
||||||
# Discussion
|
# Discussion
|
||||||
'django_comment_client',
|
'django_comment_client',
|
||||||
|
|
||||||
|
|||||||
36
lms/envs/jasmine.py
Normal file
36
lms/envs/jasmine.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
"""
|
||||||
|
This configuration is used for running jasmine tests
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .test import *
|
||||||
|
from logsettings import get_logger_config
|
||||||
|
|
||||||
|
ENABLE_JASMINE = True
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
LOGGING = get_logger_config(TEST_ROOT / "log",
|
||||||
|
logging_env="dev",
|
||||||
|
tracking_filename="tracking.log",
|
||||||
|
dev_env=True,
|
||||||
|
debug=True)
|
||||||
|
|
||||||
|
PIPELINE_JS['js-test-source'] = {
|
||||||
|
'source_filenames': sum([
|
||||||
|
pipeline_group['source_filenames']
|
||||||
|
for group_name, pipeline_group
|
||||||
|
in PIPELINE_JS.items()
|
||||||
|
if group_name != 'spec'
|
||||||
|
], []),
|
||||||
|
'output_filename': 'js/lms-test-source.js'
|
||||||
|
}
|
||||||
|
|
||||||
|
PIPELINE_JS['spec'] = {
|
||||||
|
'source_filenames': sorted(rooted_glob(PROJECT_ROOT / 'static/', 'coffee/spec/**/*.coffee')),
|
||||||
|
'output_filename': 'js/lms-spec.js'
|
||||||
|
}
|
||||||
|
|
||||||
|
JASMINE_TEST_DIRECTORY = PROJECT_ROOT + '/static/coffee'
|
||||||
|
|
||||||
|
STATICFILES_DIRS.append(COMMON_ROOT / 'test' / 'phantom-jasmine' / 'lib')
|
||||||
|
|
||||||
|
INSTALLED_APPS += ('django_jasmine', )
|
||||||
@@ -242,7 +242,7 @@ if settings.QUICKEDIT:
|
|||||||
urlpatterns += (url(r'^dogfood/(?P<id>[^/]*)$', 'dogfood.views.df_capa_problem'),)
|
urlpatterns += (url(r'^dogfood/(?P<id>[^/]*)$', 'dogfood.views.df_capa_problem'),)
|
||||||
|
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.ENABLE_JASMINE:
|
||||||
## Jasmine and admin
|
## Jasmine and admin
|
||||||
urlpatterns=urlpatterns + (url(r'^_jasmine/', include('django_jasmine.urls')),
|
urlpatterns=urlpatterns + (url(r'^_jasmine/', include('django_jasmine.urls')),
|
||||||
url(r'^admin/', include(admin.site.urls)),
|
url(r'^admin/', include(admin.site.urls)),
|
||||||
|
|||||||
73
rakefile
73
rakefile
@@ -1,5 +1,8 @@
|
|||||||
require 'rake/clean'
|
require 'rake/clean'
|
||||||
require 'tempfile'
|
require 'tempfile'
|
||||||
|
require 'net/http'
|
||||||
|
require 'launchy'
|
||||||
|
require 'colorize'
|
||||||
|
|
||||||
# Build Constants
|
# Build Constants
|
||||||
REPO_ROOT = File.dirname(__FILE__)
|
REPO_ROOT = File.dirname(__FILE__)
|
||||||
@@ -38,6 +41,43 @@ def django_admin(system, env, command, *args)
|
|||||||
return "#{django_admin} #{command} --settings=#{system}.envs.#{env} --pythonpath=. #{args.join(' ')}"
|
return "#{django_admin} #{command} --settings=#{system}.envs.#{env} --pythonpath=. #{args.join(' ')}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def django_for_jasmine(system, django_reload)
|
||||||
|
if !django_reload
|
||||||
|
reload_arg = '--noreload'
|
||||||
|
end
|
||||||
|
|
||||||
|
django_pid = fork do
|
||||||
|
exec(*django_admin(system, 'jasmine', 'runserver', "12345", reload_arg).split(' '))
|
||||||
|
end
|
||||||
|
jasmine_url = 'http://localhost:12345/_jasmine/'
|
||||||
|
up = false
|
||||||
|
start_time = Time.now
|
||||||
|
until up do
|
||||||
|
if Time.now - start_time > 30
|
||||||
|
abort "Timed out waiting for server to start to run jasmine tests"
|
||||||
|
end
|
||||||
|
begin
|
||||||
|
response = Net::HTTP.get_response(URI(jasmine_url))
|
||||||
|
puts response.code
|
||||||
|
up = response.code == '200'
|
||||||
|
rescue => e
|
||||||
|
puts e.message
|
||||||
|
ensure
|
||||||
|
puts('Waiting server to start')
|
||||||
|
sleep(0.5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
begin
|
||||||
|
yield jasmine_url
|
||||||
|
ensure
|
||||||
|
if django_reload
|
||||||
|
Process.kill(:SIGKILL, -Process.getpgid(django_pid))
|
||||||
|
else
|
||||||
|
Process.kill(:SIGKILL, django_pid)
|
||||||
|
end
|
||||||
|
Process.wait(django_pid)
|
||||||
|
end
|
||||||
|
end
|
||||||
task :default => [:test, :pep8, :pylint]
|
task :default => [:test, :pep8, :pylint]
|
||||||
|
|
||||||
directory REPORT_DIR
|
directory REPORT_DIR
|
||||||
@@ -80,6 +120,23 @@ end
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
task :pylint => "pylint_#{system}"
|
task :pylint => "pylint_#{system}"
|
||||||
|
|
||||||
|
desc "Open jasmine tests in your default browser"
|
||||||
|
task "browse_jasmine_#{system}" do
|
||||||
|
django_for_jasmine(system, true) do |jasmine_url|
|
||||||
|
Launchy.open(jasmine_url)
|
||||||
|
puts "Press ENTER to terminate".red
|
||||||
|
$stdin.gets
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Use phantomjs to run jasmine tests from the console"
|
||||||
|
task "phantomjs_jasmine_#{system}" do
|
||||||
|
phantomjs = ENV['PHANTOMJS_PATH'] || 'phantomjs'
|
||||||
|
django_for_jasmine(system, false) do |jasmine_url|
|
||||||
|
sh("#{phantomjs} common/test/phantom-jasmine/lib/run_jasmine_test.coffee #{jasmine_url}")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
$failed_tests = 0
|
$failed_tests = 0
|
||||||
@@ -139,6 +196,20 @@ TEST_TASKS = []
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
desc "Reset the relational database used by django. WARNING: this will delete all of your existing users"
|
||||||
|
task :resetdb, [:env] do |t, args|
|
||||||
|
args.with_defaults(:env => 'dev')
|
||||||
|
sh(django_admin(:lms, args.env, 'syncdb'))
|
||||||
|
sh(django_admin(:lms, args.env, 'migrate'))
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Update the relational database to the latest migration"
|
||||||
|
task :migrate, [:env] do |t, args|
|
||||||
|
args.with_defaults(:env => 'dev')
|
||||||
|
sh(django_admin(:lms, args.env, 'migrate'))
|
||||||
|
end
|
||||||
|
|
||||||
Dir["common/lib/*"].each do |lib|
|
Dir["common/lib/*"].each do |lib|
|
||||||
task_name = "test_#{lib}"
|
task_name = "test_#{lib}"
|
||||||
|
|
||||||
@@ -270,4 +341,4 @@ task :doc => :builddocs do
|
|||||||
Dir.chdir('docs/build/html') do
|
Dir.chdir('docs/build/html') do
|
||||||
sh('open index.html')
|
sh('open index.html')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user