Created
September 15, 2011 18:58
-
-
Save ef4/1220137 to your computer and use it in GitHub Desktop.
Minimal Jasmine Setup for Browser & Console with Rails 3.1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Jasmine Reporter for theubyracer on the console | |
// | |
// Originally adapted from https://github.com/mhevery/jasmine-node | |
// | |
// Helpers | |
// | |
(function(){ | |
function noop() {} | |
printRunnerResults = function(runner){ | |
var results = runner.results(); | |
var suites = runner.suites(); | |
var msg = ''; | |
msg += suites.length + ' test' + ((suites.length === 1) ? '' : 's') + ', '; | |
msg += results.totalCount + ' assertion' + ((results.totalCount === 1) ? '' : 's') + ', '; | |
msg += results.failedCount + ' failure' + ((results.failedCount === 1) ? '' : 's') + '\n'; | |
return msg; | |
}; | |
ANSIColors = { | |
pass: function() { return '\033[32m'; }, // Green | |
fail: function() { return '\033[31m'; }, // Red | |
neutral: function() { return '\033[0m'; } // Normal | |
}; | |
NoColors = { | |
pass: function() { return ''; }, | |
fail: function() { return ''; }, | |
neutral: function() { return ''; } | |
}; | |
// | |
// Reporter implementation | |
// | |
TerminalReporter = function(config) { | |
this.print_ = config.print; | |
this.isVerbose_ = config.verbose || false; | |
this.onComplete_ = config.onComplete || noop; | |
this.color_ = config.color? ANSIColors: NoColors; | |
this.stackFilter = config.stackFilter || function(t) { return t; } | |
this.columnCounter_ = 0; | |
this.log_ = []; | |
this.start_ = 0; | |
}; | |
TerminalReporter.prototype = { | |
// Public Methods // | |
log: noop, | |
reportSpecStarting: noop, | |
reportRunnerStarting: function(runner) { | |
this.printLine_('Started'); | |
this.start_ = Number(new Date); | |
}, | |
reportSuiteResults: function(suite) { | |
var specResults = suite.results(); | |
var path = []; | |
while(suite) { | |
path.unshift(suite.description); | |
suite = suite.parentSuite; | |
} | |
var description = path.join(' '); | |
if (this.isVerbose_) | |
this.log_.push('Spec ' + description); | |
outerThis = this; | |
specResults.items_.forEach(function(spec){ | |
if (spec.failedCount > 0 && spec.description) { | |
if (!outerThis.isVerbose_) | |
outerThis.log_.push(description); | |
outerThis.log_.push(' it ' + spec.description); | |
spec.items_.forEach(function(result){ | |
if (!result.passed_) | |
outerThis.log_.push(' ' + outerThis.stackFilter(result.trace.stack) + '\n'); | |
}); | |
} else { | |
if (outerThis.isVerbose_) | |
outerThis.log_.push(' it ' + spec.description); | |
} | |
}); | |
}, | |
reportSpecResults: function(spec) { | |
var result = spec.results(); | |
var msg = ''; | |
if (result.passed()) { | |
msg = this.stringWithColor_('.', this.color_.pass()); | |
// } else if (result.skipped) { TODO: Research why "result.skipped" returns false when "xit" is called on a spec? | |
// msg = (colors) ? (ansi.yellow + '*' + ansi.none) : '*'; | |
} else { | |
msg = this.stringWithColor_('F', this.color_.fail()); | |
} | |
this.print_(msg); | |
if (this.columnCounter_++ < 50) return; | |
this.columnCounter_ = 0; | |
this.print_('\n'); | |
}, | |
reportRunnerResults: function(runner) { | |
var elapsed = (Number(new Date) - this.start_) / 1000; | |
var owner = this; | |
this.printLine_('\n'); | |
this.log_.forEach(function(entry) { | |
owner.printLine_(entry); | |
}); | |
this.printLine_('Finished in ' + elapsed + ' seconds'); | |
var summary = printRunnerResults(runner); | |
if(runner.results().failedCount === 0 ) { | |
this.printLine_(this.stringWithColor_(summary, this.color_.pass())); | |
} | |
else { | |
this.printLine_(this.stringWithColor_(summary, this.color_.fail())); | |
} | |
this.onComplete_(runner, this.log_); | |
}, | |
// Helper Methods // | |
stringWithColor_: function(str, color) { | |
return (color || this.color_.neutral()) + str + this.color_.neutral(); | |
}, | |
printLine_: function(str) { | |
this.print_(str); | |
this.print_('\n'); | |
} | |
}; | |
window.TerminalReporter = TerminalReporter; | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
"http://www.w3.org/TR/html4/loose.dtd"> | |
<html> | |
<head> | |
<title>Jasmine Spec Runner</title> | |
<link rel="shortcut icon" type="image/png" href="/assets/jasmine-1.1.0/jasmine_favicon.png"> | |
<link rel="stylesheet" type="text/css" href="/assets/jasmine-1.1.0/jasmine.css"> | |
<script type="text/javascript" src="/assets/jasmine-1.1.0/jasmine.js"></script> | |
<script type="text/javascript" src="/assets/jasmine-1.1.0/jasmine-html.js"></script> | |
<script type="text/javascript" src="/assets/test"></script> | |
<script type="text/javascript"> | |
(function() { | |
var jasmineEnv = jasmine.getEnv(); | |
jasmineEnv.updateInterval = 1000; | |
var trivialReporter = new jasmine.TrivialReporter(); | |
jasmineEnv.addReporter(trivialReporter); | |
jasmineEnv.specFilter = function(spec) { | |
return trivialReporter.specFilter(spec); | |
}; | |
var currentWindowOnload = window.onload; | |
window.onload = function() { | |
if (currentWindowOnload) { | |
currentWindowOnload(); | |
} | |
execJasmine(); | |
}; | |
function execJasmine() { | |
jasmineEnv.execute(); | |
} | |
})(); | |
</script> | |
</head> | |
<body> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'v8' | |
class JasmineContext | |
attr_reader :failed_count | |
def initialize | |
@waiting = [] | |
@ctxt = V8::Context.new | |
# Jasmine just looks for this to exist, it doesn't need to do anything | |
@ctxt['window'] = @ctxt | |
# Expose methods to v8 | |
@ctxt['setTimeout'] = method(:setTimeout) | |
@ctxt['puts'] = method(:puts) | |
@ctxt['exitStatus'] = method(:exitStatus) | |
# Jasmine tries to hook these, but doesn't really need them unless | |
# your code-under-test uses them. | |
@ctxt['clearTimeout'] = proc { raise Exception, 'unimplemented' } | |
@ctxt['setInterval'] = proc { raise Exception, 'unimplemented' } | |
@ctxt['clearInterval'] = proc { raise Exception, 'unimplemented' } | |
end | |
def load_asset(name) | |
@ctxt.eval(Rails.application.assets.find_asset(name).to_s) | |
end | |
def setTimeout(f, ms) | |
@waiting.push([Time.now + ms/1000.0, f]) | |
# Re-sorting from scratch every time is wasteful, but doesn't | |
# really matter for a small number of pending timeouts. We could | |
# replace with a priority queue for much better efficiency. | |
@waiting.sort_by! {|time, func| time } | |
end | |
def runUntilDone | |
until @waiting.empty? | |
time, func = @waiting.shift | |
while time > Time.now | |
sleep(time - Time.now) | |
end | |
func.call() | |
end | |
end | |
def method_missing(name, *args) | |
@ctxt.send(name, *args) | |
end | |
def exitStatus(runner, log) | |
@failed_count = runner.results()['failedCount'] | |
end | |
end | |
namespace :test do | |
task :javascript => ['environment'] do | |
context = JasmineContext.new | |
context.load_asset('jasmine-1.1.0/jasmine.js') | |
context.load_asset('jasmine-reporter.js') | |
context.load_asset('test') | |
context.eval <<-JS | |
jasmineEnv = jasmine.getEnv(); | |
jasmineEnv.addReporter(new TerminalReporter({print: puts, color: true, onComplete: exitStatus})); | |
jasmineEnv.execute(); | |
JS | |
context.runUntilDone | |
unless context.failed_count == 0 | |
raise Exception, "#{context.failed_count} javascript tests failed" | |
end | |
end | |
end | |
task :test => ['test:javascript'] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment