Commit 3b2b8ad4 by Calen Pennington

Merge pull request #1053 from MITx/feature/jzoldak/common-jasmine-tests

Capa Problem jasmine tests running independently
parents 71927787 8d0abcb9
*/jasmine_test_runner.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Test Runner</title>
<link rel="stylesheet" type="text/css" href="<%= phantom_jasmine_path %>/vendor/jasmine-1.2.0/jasmine.css">
<script type="text/javascript" src="<%= phantom_jasmine_path %>/vendor/jasmine-1.2.0/jasmine.js"></script>
<script type="text/javascript" src="<%= phantom_jasmine_path %>/vendor/jasmine-1.2.0/jasmine-html.js"></script>
<script type="text/javascript" src="<%= phantom_jasmine_path %>/lib/console-runner.js"></script>
<script type="text/javascript" src="<%= common_coffee_root %>/ajax_prefix.js"></script>
<script type="text/javascript" src="<%= common_coffee_root %>/logger.js"></script>
<script type="text/javascript" src="<%= common_js_root %>/vendor/jquery.min.js"></script>
<script type="text/javascript" src="<%= common_js_root %>/vendor/jasmine-jquery.js"></script>
<script type="text/javascript" src="<%= common_js_root %>/vendor/mathjax-MathJax-c9db6ac/MathJax.js"></script>
<script type="text/javascript">
AjaxPrefix.addAjaxPrefix(jQuery, function() {
return "";
});
</script>
<!-- SOURCE FILES -->
<% for src in js_source %>
<script type="text/javascript" src="<%= src %>"></script>
<% end %>
<!-- SPEC FILES -->
<% for src in js_specs %>
<script type="text/javascript" src="<%= src %>"></script>
<% end %>
</head>
<body>
<script type="text/javascript">
var console_reporter = new jasmine.ConsoleReporter()
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
jasmine.getEnv().addReporter(console_reporter);
jasmine.getEnv().execute();
</script>
</body>
</html>
<section id="problem_1" class="problems-wrapper" data-url="/problem/url/"></section>
<section class='xmodule_display xmodule_CapaModule' data-type='Problem'>
<section id='problem_1'
class='problems-wrapper'
data-problem-id='i4x://edX/101/problem/Problem1'
data-url='/problem/Problem1'>
</section>
</section>
\ No newline at end of file
......@@ -8,25 +8,43 @@ describe 'Problem', ->
MathJax.Hub.getAllJax.andReturn [@stubbedJax]
window.update_schematics = ->
# Load this function from spec/helper.coffee
# Note that if your test fails with a message like:
# 'External request attempted for blah, which is not defined.'
# this msg is coming from the stubRequests function else clause.
jasmine.stubRequests()
# note that the fixturesPath is set in spec/helper.coffee
loadFixtures 'problem.html'
spyOn Logger, 'log'
spyOn($.fn, 'load').andCallFake (url, callback) ->
$(@).html readFixtures('problem_content.html')
callback()
jasmine.stubRequests()
describe 'constructor', ->
beforeEach ->
@problem = new Problem 1, "problem_1", "/problem/url/"
it 'set the element', ->
expect(@problem.el).toBe '#problem_1'
it 'set the element from html', ->
@problem999 = new Problem ("
<section class='xmodule_display xmodule_CapaModule' data-type='Problem'>
<section id='problem_999'
class='problems-wrapper'
data-problem-id='i4x://edX/999/problem/Quiz'
data-url='/problem/quiz/'>
</section>
</section>
")
expect(@problem999.element_id).toBe 'problem_999'
it 'set the element from loadFixtures', ->
@problem1 = new Problem($('.xmodule_display'))
expect(@problem1.element_id).toBe 'problem_1'
describe 'bind', ->
beforeEach ->
spyOn window, 'update_schematics'
MathJax.Hub.getAllJax.andReturn [@stubbedJax]
@problem = new Problem 1, "problem_1", "/problem/url/"
@problem = new Problem($('.xmodule_display'))
it 'set mathjax typeset', ->
expect(MathJax.Hub.Queue).toHaveBeenCalled()
......@@ -38,7 +56,7 @@ describe 'Problem', ->
expect($('section.action input:button')).toHandleWith 'click', @problem.refreshAnswers
it 'bind the check button', ->
expect($('section.action input.check')).toHandleWith 'click', @problem.check
expect($('section.action input.check')).toHandleWith 'click', @problem.check_fd
it 'bind the reset button', ->
expect($('section.action input.reset')).toHandleWith 'click', @problem.reset
......@@ -60,7 +78,7 @@ describe 'Problem', ->
describe 'render', ->
beforeEach ->
@problem = new Problem 1, "problem_1", "/problem/url/"
@problem = new Problem($('.xmodule_display'))
@bind = @problem.bind
spyOn @problem, 'bind'
......@@ -86,9 +104,13 @@ describe 'Problem', ->
it 're-bind the content', ->
expect(@problem.bind).toHaveBeenCalled()
describe 'check_fd', ->
xit 'should have specs written for this functionality', ->
expect(false)
describe 'check', ->
beforeEach ->
@problem = new Problem 1, "problem_1", "/problem/url/"
@problem = new Problem($('.xmodule_display'))
@problem.answers = 'foo=1&bar=2'
it 'log the problem_check event', ->
......@@ -98,30 +120,34 @@ describe 'Problem', ->
it 'submit the answer for check', ->
spyOn $, 'postWithPrefix'
@problem.check()
expect($.postWithPrefix).toHaveBeenCalledWith '/modx/1/problem_check', 'foo=1&bar=2', jasmine.any(Function)
expect($.postWithPrefix).toHaveBeenCalledWith '/problem/Problem1/problem_check',
'foo=1&bar=2', jasmine.any(Function)
describe 'when the response is correct', ->
it 'call render with returned content', ->
spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) -> callback(success: 'correct', contents: 'Correct!')
spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) ->
callback(success: 'correct', contents: 'Correct!')
@problem.check()
expect(@problem.el.html()).toEqual 'Correct!'
describe 'when the response is incorrect', ->
it 'call render with returned content', ->
spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) -> callback(success: 'incorrect', contents: 'Correct!')
spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) ->
callback(success: 'incorrect', contents: 'Incorrect!')
@problem.check()
expect(@problem.el.html()).toEqual 'Correct!'
expect(@problem.el.html()).toEqual 'Incorrect!'
describe 'when the response is undetermined', ->
it 'alert the response', ->
spyOn window, 'alert'
spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) -> callback(success: 'Number Only!')
spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) ->
callback(success: 'Number Only!')
@problem.check()
expect(window.alert).toHaveBeenCalledWith 'Number Only!'
describe 'reset', ->
beforeEach ->
@problem = new Problem 1, "problem_1", "/problem/url/"
@problem = new Problem($('.xmodule_display'))
it 'log the problem_reset event', ->
@problem.answers = 'foo=1&bar=2'
......@@ -131,7 +157,8 @@ describe 'Problem', ->
it 'POST to the problem reset page', ->
spyOn $, 'postWithPrefix'
@problem.reset()
expect($.postWithPrefix).toHaveBeenCalledWith '/modx/1/problem_reset', { id: 1 }, jasmine.any(Function)
expect($.postWithPrefix).toHaveBeenCalledWith '/problem/Problem1/problem_reset',
{ id: 'i4x://edX/101/problem/Problem1' }, jasmine.any(Function)
it 'render the returned content', ->
spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) ->
......@@ -141,7 +168,7 @@ describe 'Problem', ->
describe 'show', ->
beforeEach ->
@problem = new Problem 1, "problem_1", "/problem/url/"
@problem = new Problem($('.xmodule_display'))
@problem.el.prepend '<div id="answer_1_1" /><div id="answer_1_2" />'
describe 'when the answer has not yet shown', ->
......@@ -150,12 +177,14 @@ describe 'Problem', ->
it 'log the problem_show event', ->
@problem.show()
expect(Logger.log).toHaveBeenCalledWith 'problem_show', problem: 1
expect(Logger.log).toHaveBeenCalledWith 'problem_show',
problem: 'i4x://edX/101/problem/Problem1'
it 'fetch the answers', ->
spyOn $, 'postWithPrefix'
@problem.show()
expect($.postWithPrefix).toHaveBeenCalledWith '/modx/1/problem_show', jasmine.any(Function)
expect($.postWithPrefix).toHaveBeenCalledWith '/problem/Problem1/problem_show',
jasmine.any(Function)
it 'show the answers', ->
spyOn($, 'postWithPrefix').andCallFake (url, callback) ->
......@@ -220,7 +249,7 @@ describe 'Problem', ->
describe 'save', ->
beforeEach ->
@problem = new Problem 1, "problem_1", "/problem/url/"
@problem = new Problem($('.xmodule_display'))
@problem.answers = 'foo=1&bar=2'
it 'log the problem_save event', ->
......@@ -230,7 +259,8 @@ describe 'Problem', ->
it 'POST to save problem', ->
spyOn $, 'postWithPrefix'
@problem.save()
expect($.postWithPrefix).toHaveBeenCalledWith '/modx/1/problem_save', 'foo=1&bar=2', jasmine.any(Function)
expect($.postWithPrefix).toHaveBeenCalledWith '/problem/Problem1/problem_save',
'foo=1&bar=2', jasmine.any(Function)
it 'alert to the user', ->
spyOn window, 'alert'
......@@ -240,7 +270,7 @@ describe 'Problem', ->
describe 'refreshMath', ->
beforeEach ->
@problem = new Problem 1, "problem_1", "/problem/url/"
@problem = new Problem($('.xmodule_display'))
$('#input_example_1').val 'E=mc^2'
@problem.refreshMath target: $('#input_example_1').get(0)
......@@ -250,7 +280,7 @@ describe 'Problem', ->
describe 'updateMathML', ->
beforeEach ->
@problem = new Problem 1, "problem_1", "/problem/url/"
@problem = new Problem($('.xmodule_display'))
@stubbedJax.root.toMathML.andReturn '<MathML>'
describe 'when there is no exception', ->
......@@ -270,7 +300,7 @@ describe 'Problem', ->
describe 'refreshAnswers', ->
beforeEach ->
@problem = new Problem 1, "problem_1", "/problem/url/"
@problem = new Problem($('.xmodule_display'))
@problem.el.html '''
<textarea class="CodeMirror" />
<input id="input_1_1" name="input_1_1" class="schematic" value="one" />
......@@ -293,3 +323,6 @@ describe 'Problem', ->
it 'serialize all answers', ->
@problem.refreshAnswers()
expect(@problem.answers).toEqual "input_1_1=one&input_1_2=two"
jasmine.getFixtures().fixturesPath = 'xmodule/js/fixtures'
jasmine.stubbedMetadata =
slowerSpeedYoutubeId:
id: 'slowerSpeedYoutubeId'
duration: 300
normalSpeedYoutubeId:
id: 'normalSpeedYoutubeId'
duration: 200
bogus:
duration: 100
jasmine.stubbedCaption =
start: [0, 10000, 20000, 30000]
text: ['Caption at 0', 'Caption at 10000', 'Caption at 20000', 'Caption at 30000']
jasmine.stubRequests = ->
spyOn($, 'ajax').andCallFake (settings) ->
if match = settings.url.match /youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/
settings.success data: jasmine.stubbedMetadata[match[1]]
else if match = settings.url.match /static\/subs\/(.+)\.srt\.sjson/
settings.success jasmine.stubbedCaption
else if settings.url.match /.+\/problem_get$/
settings.success html: readFixtures('problem_content.html')
else if settings.url == '/calculate' ||
settings.url.match(/.+\/goto_position$/) ||
settings.url.match(/event$/) ||
settings.url.match(/.+\/problem_(check|reset|show|save)$/)
# do nothing
else
throw "External request attempted for #{settings.url}, which is not defined."
jasmine.stubYoutubePlayer = ->
YT.Player = -> jasmine.createSpyObj 'YT.Player', ['cueVideoById', 'getVideoEmbedCode',
'getCurrentTime', 'getPlayerState', 'getVolume', 'setVolume', 'loadVideoById',
'playVideo', 'pauseVideo', 'seekTo']
jasmine.stubVideoPlayer = (context, enableParts, createPlayer=true) ->
enableParts = [enableParts] unless $.isArray(enableParts)
suite = context.suite
currentPartName = suite.description while suite = suite.parentSuite
enableParts.push currentPartName
for part in ['VideoCaption', 'VideoSpeedControl', 'VideoVolumeControl', 'VideoProgressSlider']
unless $.inArray(part, enableParts) >= 0
spyOn window, part
loadFixtures 'video.html'
jasmine.stubRequests()
YT.Player = undefined
context.video = new Video 'example', '.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId'
jasmine.stubYoutubePlayer()
if createPlayer
return new VideoPlayer(video: context.video)
spyOn(window, 'onunload')
# Stub Youtube API
window.YT =
PlayerState:
UNSTARTED: -1
ENDED: 0
PLAYING: 1
PAUSED: 2
BUFFERING: 3
CUED: 5
# Stub jQuery.cookie
$.cookie = jasmine.createSpy('jQuery.cookie').andReturn '1.0'
# Stub jQuery.qtip
$.fn.qtip = jasmine.createSpy 'jQuery.qtip'
# Stub jQuery.scrollTo
$.fn.scrollTo = jasmine.createSpy 'jQuery.scrollTo'
......@@ -3,6 +3,8 @@ require 'tempfile'
require 'net/http'
require 'launchy'
require 'colorize'
require 'erb'
require 'tempfile'
# Build Constants
REPO_ROOT = File.dirname(__FILE__)
......@@ -79,6 +81,31 @@ def django_for_jasmine(system, django_reload)
end
end
def template_jasmine_runner(lib)
coffee_files = Dir["#{lib}/**/js/**/*.coffee", "common/static/coffee/src/**/*.coffee"]
if !coffee_files.empty?
sh("coffee -c #{coffee_files.join(' ')}")
end
phantom_jasmine_path = File.expand_path("common/test/phantom-jasmine")
common_js_root = File.expand_path("common/static/js")
common_coffee_root = File.expand_path("common/static/coffee/src")
# Get arrays of spec and source files, ordered by how deep they are nested below the library
# (and then alphabetically) and expanded from a relative to an absolute path
spec_glob = File.join("#{lib}", "**", "spec", "**", "*.js")
src_glob = File.join("#{lib}", "**", "src", "**", "*.js")
js_specs = Dir[spec_glob].sort_by {|p| [p.split('/').length, p]} .map {|f| File.expand_path(f)}
js_source = Dir[src_glob].sort_by {|p| [p.split('/').length, p]} .map {|f| File.expand_path(f)}
template = ERB.new(File.read("#{lib}/jasmine_test_runner.html.erb"))
template_output = "#{lib}/jasmine_test_runner.html"
File.open(template_output, 'w') do |f|
f.write(template.result(binding))
end
yield File.expand_path(template_output)
end
def report_dir_path(dir)
return File.join(REPORT_DIR, dir.to_s)
end
......@@ -126,22 +153,6 @@ end
end
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
$failed_tests = 0
......@@ -210,6 +221,23 @@ TEST_TASK_DIRS = []
end
end
end
desc "Open jasmine tests for #{system} 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 for #{system} 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
desc "Reset the relational database used by django. WARNING: this will delete all of your existing users"
......@@ -245,6 +273,22 @@ Dir["common/lib/*"].select{|lib| File.directory?(lib)}.each do |lib|
sh("nosetests #{lib}")
end
desc "Open jasmine tests for #{lib} in your default browser"
task "browse_jasmine_#{lib}" do
template_jasmine_runner(lib) do |f|
sh("python -m webbrowser -t 'file://#{f}'")
puts "Press ENTER to terminate".red
$stdin.gets
end
end
desc "Use phantomjs to run jasmine tests for #{lib} from the console"
task "phantomjs_jasmine_#{lib}" do
phantomjs = ENV['PHANTOMJS_PATH'] || 'phantomjs'
template_jasmine_runner(lib) do |f|
sh("#{phantomjs} common/test/phantom-jasmine/lib/run_jasmine_test.coffee #{f}")
end
end
end
task :report_dirs
......
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