Merge in new HTML runner. Tests green, regression on focused running.

This commit is contained in:
ragaskar 2009-08-19 07:42:47 -07:00
commit 0a3358f249
20 changed files with 462 additions and 164 deletions

View File

@ -19,15 +19,39 @@ module Jasmine
port port
end end
class RunAdapter def self.server_is_listening_on(hostname, port)
def initialize(spec_files) require 'socket'
p "spec_files: #{spec_files}" begin
socket = TCPSocket.open(hostname, port)
rescue Errno::ECONNREFUSED
return false
end
socket.close
true
end
@spec_files = spec_files def self.wait_for_listener(port, name = "required process", seconds_to_wait = 10)
time_out_at = Time.now + seconds_to_wait
until server_is_listening_on "localhost", port
sleep 0.1
puts "Waiting for #{name} on #{port}..."
raise "#{name} didn't show up on port #{port} after #{seconds_to_wait} seconds." if Time.now > time_out_at
end
end
def self.kill_process_group(process_group_id, signal="TERM")
Process.kill signal, -process_group_id # negative pid means kill process group. (see man 2 kill)
end
class RunAdapter
def initialize(spec_files_or_proc)
@spec_files_or_proc = spec_files_or_proc
end end
def call(env) def call(env)
spec_files = @spec_files spec_files = @spec_files_or_proc
spec_files = spec_files.call if spec_files.respond_to?(:call)
body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html"))).result(binding) body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html"))).result(binding)
[ [
200, 200,
@ -38,11 +62,11 @@ module Jasmine
end end
class SimpleServer class SimpleServer
def self.start(port, spec_dir, mappings) def self.start(port, spec_files_or_proc, mappings)
require 'thin' require 'thin'
config = { config = {
'/run.html' => Jasmine::RunAdapter.new(spec_dir) '/run.html' => Jasmine::RunAdapter.new(spec_files_or_proc)
} }
mappings.each do |from, to| mappings.each do |from, to|
config[from] = Rack::File.new(to) config[from] = Rack::File.new(to)
@ -50,7 +74,6 @@ module Jasmine
app = Rack::URLMap.new(config) app = Rack::URLMap.new(config)
server_port = Jasmine::find_unused_port
Thin::Server.start('0.0.0.0', port, app) Thin::Server.start('0.0.0.0', port, app)
end end
end end
@ -119,26 +142,6 @@ module Jasmine
stop_servers stop_servers
end end
def server_is_listening_on(hostname, port)
require 'socket'
begin
socket = TCPSocket.open(hostname, port)
rescue Errno::ECONNREFUSED
return false
end
socket.close
true
end
def wait_for_listener(port, name = "required process", seconds_to_wait = 10)
seconds_waited = 0
until server_is_listening_on "localhost", port
sleep 1
puts "Waiting for #{name} on #{port}..."
raise "#{name} didn't show up on port #{port} after #{seconds_to_wait} seconds." if (seconds_waited += 1) >= seconds_to_wait
end
end
def start_servers def start_servers
@jasmine_server_port = Jasmine::find_unused_port @jasmine_server_port = Jasmine::find_unused_port
@selenium_server_port = Jasmine::find_unused_port @selenium_server_port = Jasmine::find_unused_port
@ -156,18 +159,14 @@ module Jasmine
end end
puts "jasmine server started. pid is #{@jasmine_server_pid}" puts "jasmine server started. pid is #{@jasmine_server_pid}"
wait_for_listener(@selenium_server_port, "selenium server") Jasmine::wait_for_listener(@selenium_server_port, "selenium server")
wait_for_listener(@jasmine_server_port, "jasmine server") Jasmine::wait_for_listener(@jasmine_server_port, "jasmine server")
end
def kill_process_group(process_group_id, signal="TERM")
Process.kill signal, -process_group_id # negative pid means kill process group. (see man 2 kill)
end end
def stop_servers def stop_servers
puts "shutting down the servers..." puts "shutting down the servers..."
kill_process_group(@selenium_pid) if @selenium_pid Jasmine::kill_process_group(@selenium_pid) if @selenium_pid
kill_process_group(@jasmine_server_pid) if @jasmine_server_pid Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_pid
end end
def run def run

View File

@ -0,0 +1,51 @@
require 'spec'
require 'open-uri'
require File.dirname(__FILE__) + '/jasmine_runner'
describe Jasmine::SimpleServer do
before do
@port = Jasmine::find_unused_port
end
after do
Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_pid
end
it "should start and print script tags" do
@jasmine_server_pid = fork do
Process.setpgrp
Jasmine::SimpleServer.start(@port, ["file1", "file2"], {})
exit! 0
end
Jasmine::wait_for_listener(@port)
run_html = open("http://localhost:#{@port}/run.html").read
run_html.should =~ /<script src="file1"/
run_html.should =~ /<script src="file2"/
end
it "should take a proc that returns a list of spec files" do
spec_fileses = [["file1", "file2"], ["file1", "file2", "file3"]]
spec_files_proc = lambda do
spec_fileses.shift
end
@jasmine_server_pid = fork do
Process.setpgrp
Jasmine::SimpleServer.start(@port, spec_files_proc, {})
exit! 0
end
Jasmine::wait_for_listener(@port)
run_html = open("http://localhost:#{@port}/run.html").read
run_html.should =~ /<script src="file1"/
run_html.should =~ /<script src="file2"/
run_html = open("http://localhost:#{@port}/run.html").read
run_html.should =~ /<script src="file1"/
run_html.should =~ /<script src="file2"/
run_html.should =~ /<script src="file3"/
end
end

View File

@ -121,7 +121,7 @@ module Jasmine
out << "\n" out << "\n"
unless message["passed"] unless message["passed"]
stack_trace = message["trace"]["stack"] stack_trace = message["trace"]["stack"].gsub(/<br \/>/, "\n").gsub(/<\/?b>/, " ")
STDERR << stack_trace.gsub(/\(.*\)@http:\/\/localhost:[0-9]+\/specs\//, "/spec/") STDERR << stack_trace.gsub(/\(.*\)@http:\/\/localhost:[0-9]+\/specs\//, "/spec/")
STDERR << "\n" STDERR << "\n"
end end

View File

@ -3,20 +3,32 @@
<head> <head>
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type"/> <meta content="text/html;charset=UTF-8" http-equiv="Content-Type"/>
<title>Jasmine suite</title> <title>Jasmine suite</title>
<script src="/specs/javascripts/jasmine/lib/jasmine.js"></script> <script src="/jasmine/lib/jasmine.js"></script>
<script src="/specs/javascripts/jasmine/lib/json2.js"></script><!-- todo: don't load JSON in the test runner! [20090710 xw] --> <script src="/jasmine/lib/json2.js"></script><!-- todo: don't load JSON in the test runner! [20090710 xw] -->
<script src="/specs/javascripts/jasmine/lib/TrivialReporter.js"></script> <script src="/jasmine/lib/TrivialReporter.js"></script>
<script src="/specs/javascripts/screw-jasmine-compat.js"></script> <script src="/specs/javascripts/screw-jasmine-compat.js"></script>
<script type="text/javascript"></script> <script type="text/javascript"></script>
<link href="/core/jasmine.css" rel="stylesheet"/> <link href="/jasmine/lib/jasmine.css" rel="stylesheet"/>
<script type="text/javascript"> <script type="text/javascript">
var jsApiReporter;
(function() {
var jasmineEnv = jasmine.getEnv(); var jasmineEnv = jasmine.getEnv();
var jsApiReporter = new jasmine.JsApiReporter(); jasmineEnv.updateInterval = 1000;
jsApiReporter = new jasmine.JsApiReporter();
var trivialReporter = new jasmine.TrivialReporter();
jasmineEnv.addReporter(jsApiReporter); jasmineEnv.addReporter(jsApiReporter);
jasmineEnv.addReporter(new jasmine.TrivialReporter()); jasmineEnv.addReporter(trivialReporter);
jasmineEnv.specFilter = function(spec) {
return trivialReporter.specFilter(spec);
};
window.onload = function() { window.onload = function() {
jasmineEnv.execute(); jasmineEnv.execute();
}; };
})();
</script> </script>
<% spec_files.each do |spec_file| %> <% spec_files.each do |spec_file| %>

View File

@ -1,4 +1,6 @@
jasmine.TrivialReporter = function() { jasmine.TrivialReporter = function(doc) {
this.document = doc || document;
this.suiteDivs = {};
}; };
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
@ -25,37 +27,88 @@ jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarA
return el; return el;
}; };
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
var suites = runner.getAllSuites();
this.runnerDiv = this.createDom('div', { className: 'runner running' }, "Running...");
this.document.body.appendChild(this.runnerDiv);
for (var i = 0; i < suites.length; i++) {
var suite = suites[i];
var suiteDiv = this.createDom('div', { className: 'suite' },
this.createDom('a', { className: 'runSpec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
suite.description);
this.suiteDivs[suite.getFullName()] = suiteDiv;
var parentDiv = this.document.body;
if (suite.parentSuite) {
parentDiv = this.suiteDivs[suite.parentSuite.getFullName()];
}
parentDiv.appendChild(suiteDiv);
}
};
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
console.log(runner); var results = runner.getResults();
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
this.runnerDiv.setAttribute("class", className);
var message = results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
this.runnerDiv.replaceChild(this.document.createTextNode(message), this.runnerDiv.firstChild);
}; };
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
console.log(suite); var results = suite.getResults();
var status = results.passed() ? 'passed' : 'failed';
if (results.totalCount == 0) { // todo: change this to check results.skipped
status = 'skipped';
}
this.suiteDivs[suite.getFullName()].className += " " + status;
}; };
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
var specDiv = this.createDom('div', { var results = spec.getResults();
className: spec.getResults().passed() ? 'spec passed' : 'spec failed' var status = results.passed() ? 'passed' : 'failed';
}, spec.getFullName()); if (results.skipped) {
status = 'skipped';
}
var specDiv = this.createDom('div', { className: 'spec ' + status },
this.createDom('a', { className: 'runSpec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
spec.getFullName());
var resultItems = spec.getResults().getItems();
var resultItems = results.getItems();
for (var i = 0; i < resultItems.length; i++) { for (var i = 0; i < resultItems.length; i++) {
var result = resultItems[i]; var result = resultItems[i];
if (!result.passed) { if (!result.passed()) {
var resultMessageDiv = this.createDom('div', {className: 'resultMessage'}); var resultMessageDiv = this.createDom('div', {className: 'resultMessage fail'});
resultMessageDiv.innerHTML = result.message; // todo: lame; mend resultMessageDiv.innerHTML = result.message; // todo: lame; mend
specDiv.appendChild(resultMessageDiv); specDiv.appendChild(resultMessageDiv);
specDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); specDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
} }
} }
document.body.appendChild(specDiv); this.suiteDivs[spec.suite.getFullName()].appendChild(specDiv);
}; };
jasmine.TrivialReporter.prototype.log = function() { jasmine.TrivialReporter.prototype.log = function() {
console.log.apply(console, arguments); console.log.apply(console, arguments);
}; };
jasmine.TrivialReporter.prototype.getLocation = function() {
return this.document.location;
};
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
var paramMap = {};
var params = this.getLocation().search.substring(1).split('&');
for (var i = 0; i < params.length; i++) {
var p = params[i].split('=');
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
}
if (!paramMap["spec"]) return true;
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
};
//protect against console.log incidents //protect against console.log incidents
if (!("console" in window) || !("firebug" in console)) { if (!("console" in window) || !("firebug" in console)) {
var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];

View File

@ -1,6 +1,5 @@
body { body {
font: 14px "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; font: 14px "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
padding-left: 40px;
} }
h1 { h1 {
@ -14,11 +13,74 @@ p {
padding-left: 20px; padding-left: 20px;
} }
p.fail { .fail {
background: url( ../images/fail-16.png ) no-repeat; background: url( ../images/fail-16.png ) no-repeat;
padding-left: 20px;
color: red; color: red;
} }
p.fail_in_summary { .failInSummary {
color: red; color: red;
} }
.runner {
border: 1px outset gray;
margin: 5px;
padding-left: 1em;
}
.runner.running {
background-color: yellow;
}
.suite {
border: 1px outset gray;
margin: 5px;
padding-left: 1em;
}
.suite.passed {
background-color: #cfc;
}
.suite.failed {
background-color: #fdd;
}
.spec {
margin: 5px;
clear: both;
}
.passed {
background-color: lightgreen;
}
.failed {
background-color: pink;
}
.skipped {
color: #777;
background-color: #eee;
}
.resultMessage {
white-space: pre;
}
.stackTrace {
white-space: pre;
font-size: .8em;
margin-left: 10px;
height: 5em;
overflow: auto;
border: 1px inset red;
padding: 1em;
background: #eef;
}
.runSpec {
margin-left: 5px;
float: right;
}

View File

@ -1084,6 +1084,16 @@ jasmine.Matchers.prototype.toNotContain = function(item) {
'Expected ' + jasmine.Matchers.pp(this.actual) + ' not to contain ' + jasmine.Matchers.pp(item) + ', but it does.'); 'Expected ' + jasmine.Matchers.pp(this.actual) + ' not to contain ' + jasmine.Matchers.pp(item) + ', but it does.');
}; };
jasmine.Matchers.prototype.toBeLessThan = function(expected) {
return this.report(this.actual < expected,
'Expected ' + jasmine.Matchers.pp(this.actual) + ' to be less than ' + jasmine.Matchers.pp(expected) + ', but it was not.');
};
jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
return this.report(this.actual > expected,
'Expected ' + jasmine.Matchers.pp(this.actual) + ' to be greater than ' + jasmine.Matchers.pp(expected) + ', but it was not.');
};
/** /**
* Matcher that checks that the expected exception was thrown by the actual. * Matcher that checks that the expected exception was thrown by the actual.
* *
@ -1366,7 +1376,8 @@ jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
jasmine.StringPrettyPrinter.prototype.append = function(value) { jasmine.StringPrettyPrinter.prototype.append = function(value) {
this.string += value; this.string += value;
}; };
jasmine.Queue = function() { jasmine.Queue = function(env) {
this.env = env;
this.blocks = []; this.blocks = [];
this.running = false; this.running = false;
this.index = 0; this.index = 0;
@ -1405,13 +1416,17 @@ jasmine.Queue.prototype.isRunning = function () {
jasmine.Queue.prototype._next = function () { jasmine.Queue.prototype._next = function () {
var self = this; var self = this;
self.env.setTimeout(function () {
self.offset = 0; self.offset = 0;
self.index++; self.index++;
if (self.index < self.blocks.length) { if (self.index < self.blocks.length) {
self.blocks[self.index].execute(function () {self._next();}); self.blocks[self.index].execute(function () {
self._next();
});
} else { } else {
self.finish(); self.finish();
} }
}, 0);
}; };
jasmine.Queue.prototype.finish = function () { jasmine.Queue.prototype.finish = function () {
@ -1472,7 +1487,7 @@ jasmine.Reporters.reporter = function(callbacks) {
jasmine.Runner = function(env) { jasmine.Runner = function(env) {
var self = this; var self = this;
self.env = env; self.env = env;
self.queue = new jasmine.Queue(); self.queue = new jasmine.Queue(env);
}; };
jasmine.Runner.prototype.execute = function() { jasmine.Runner.prototype.execute = function() {
@ -1487,10 +1502,34 @@ jasmine.Runner.prototype.finishCallback = function() {
this.env.reporter.reportRunnerResults(this); this.env.reporter.reportRunnerResults(this);
}; };
jasmine.Runner.prototype.add = function(block) { jasmine.Runner.prototype.add = function(block) {
this.queue.add(block); this.queue.add(block);
}; };
jasmine.Runner.prototype.getAllSuites = function() {
var suitesToReturn = [];
function addSuite(suite) {
suitesToReturn.push(suite);
for (var j = 0; j < suite.specs.length; j++) {
var spec = suite.specs[j];
if (spec instanceof jasmine.Suite) {
addSuite(spec);
}
}
}
for (var i = 0; i < this.suites.length; i++) {
var suite = this.suites[i];
addSuite(suite);
}
return suitesToReturn;
};
jasmine.Runner.prototype.getResults = function() { jasmine.Runner.prototype.getResults = function() {
var results = new jasmine.NestedResults(); var results = new jasmine.NestedResults();
var runnerResults = this.queue.getResults(); var runnerResults = this.queue.getResults();
@ -1516,7 +1555,7 @@ jasmine.Spec = function(env, suite, description) {
spec.env = env; spec.env = env;
spec.suite = suite; spec.suite = suite;
spec.description = description; spec.description = description;
spec.queue = new jasmine.Queue(); spec.queue = new jasmine.Queue(env);
spec.finished = false; spec.finished = false;
spec.afterCallbacks = []; spec.afterCallbacks = [];
@ -1705,7 +1744,7 @@ jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
var self = this; var self = this;
self.id = env.nextSuiteId_++; self.id = env.nextSuiteId_++;
self.description = description; self.description = description;
self.queue = new jasmine.Queue(); self.queue = new jasmine.Queue(env);
self.parentSuite = parentSuite; self.parentSuite = parentSuite;
self.env = env; self.env = env;
self.beforeQueue = []; self.beforeQueue = [];

View File

@ -3,6 +3,7 @@
<html> <html>
<head> <head>
<title>Jasmine Test Runner</title> <title>Jasmine Test Runner</title>
<script type="text/javascript" src="../src/base.js"></script> <script type="text/javascript" src="../src/base.js"></script>
<script type="text/javascript" src="../src/util.js"></script> <script type="text/javascript" src="../src/util.js"></script>
<script type="text/javascript" src="../src/Env.js"></script> <script type="text/javascript" src="../src/Env.js"></script>
@ -35,31 +36,10 @@
jasmine.include('suites/RunnerTest.js', true); jasmine.include('suites/RunnerTest.js', true);
jasmine.include('suites/SpecRunningTest.js', true); jasmine.include('suites/SpecRunningTest.js', true);
jasmine.include('suites/SpyTest.js', true); jasmine.include('suites/SpyTest.js', true);
jasmine.include('suites/TrivialReporterTest.js', true);
</script> </script>
<style type="text/css"> <link href="../lib/jasmine.css" rel="stylesheet"/>
.spec {
margin: 5px;
}
.passed {
background-color: lightgreen;
}
.failed {
background-color: pink;
}
.resultMessage {
white-space: pre;
}
.stackTrace {
white-space: pre;
font-size: .8em;
margin-left: 10px;
}
</style>
</head> </head>
<body> <body>

View File

@ -77,20 +77,29 @@ describe('Exceptions:', function() {
fakeTimer.tick(2500); fakeTimer.tick(2500);
var suiteResults = suite.getResults(); var suiteResults = suite.getResults();
expect(suiteResults.length).toEqual(5); var specResults = suiteResults.getItems();
expect(suiteResults[0].passed()).toEqual(false);
expect(suiteResults[0].items_[0].message).toMatch(/fake error 1/);
expect(suiteResults[1].passed()).toEqual(false), expect(suiteResults.passed()).toEqual(false);
expect(suiteResults[1].items_[0].message).toMatch(/fake error 2/),
expect(suiteResults[1].items_[1].passed).toEqual(true);
expect(suiteResults[2].passed()).toEqual(true); expect(specResults.length).toEqual(5);
expect(specResults[0].passed()).toMatch(false);
var blockResults = specResults[0].getItems();
expect(blockResults[0].passed()).toEqual(false);
expect(blockResults[0].message).toMatch(/fake error 1/);
expect(suiteResults[3].passed()).toEqual(false); expect(specResults[1].passed()).toEqual(false);
expect(suiteResults[3].items_[0].message).toMatch(/fake error 3/); var blockResults = specResults[1].getItems();
expect(blockResults[0].passed()).toEqual(false);
expect(blockResults[0].message).toMatch(/fake error 2/),
expect(blockResults[1].passed()).toEqual(true);
expect(suiteResults[4].passed()).toEqual(true); expect(specResults[2].passed()).toEqual(true);
expect(specResults[3].passed()).toEqual(false);
blockResults = specResults[3].getItems();
expect(blockResults[0].message).toMatch(/fake error 3/);
expect(specResults[4].passed()).toEqual(true);
}); });

View File

@ -167,6 +167,18 @@ describe("jasmine.Matchers", function() {
}); });
}); });
it("toBeLessThan should pass if actual is less than expected", function() {
expect(match(37).toBeLessThan(42)).toEqual(true);
expect(match(37).toBeLessThan(-42)).toEqual(false);
expect(match(37).toBeLessThan(37)).toEqual(false);
});
it("toBeGreaterThan should pass if actual is greater than expected", function() {
expect(match(37).toBeGreaterThan(42)).toEqual(false);
expect(match(37).toBeGreaterThan(-42)).toEqual(true);
expect(match(37).toBeGreaterThan(37)).toEqual(false);
});
it("toThrow", function() { it("toThrow", function() {
var expected = new jasmine.Matchers(env, function() { var expected = new jasmine.Matchers(env, function() {
throw new Error("Fake Error"); throw new Error("Fake Error");
@ -210,7 +222,7 @@ describe("jasmine.Matchers", function() {
expected = match(TestClass.someFunction); expected = match(TestClass.someFunction);
expect(expected.wasCalledWith('c', 'b', 'a')).toEqual(false); expect(expected.wasCalledWith('c', 'b', 'a')).toEqual(false);
expect(expected.getResults().getItems()[0].passed).toEqual(false); expect(expected.getResults().getItems()[0].passed()).toEqual(false);
TestClass.someFunction.reset(); TestClass.someFunction.reset();
TestClass.someFunction('a', 'b', 'c'); TestClass.someFunction('a', 'b', 'c');
@ -233,9 +245,9 @@ describe("jasmine.Matchers", function() {
expect(results.getItems().length).toEqual(2); expect(results.getItems().length).toEqual(2);
expect(results.getItems()[0].passed).toEqual(true); expect(results.getItems()[0].passed()).toEqual(true);
expect(results.getItems()[1].passed).toEqual(false); expect(results.getItems()[1].passed()).toEqual(false);
results = new jasmine.NestedResults(); results = new jasmine.NestedResults();
expected = new jasmine.Matchers(env, false, results); expected = new jasmine.Matchers(env, false, results);
@ -285,17 +297,17 @@ describe("jasmine.Matchers", function() {
expected = new jasmine.Matchers(env, [1, 2, 3], results); expected = new jasmine.Matchers(env, [1, 2, 3], results);
results.getItems().length = 0; results.getItems().length = 0;
expected.toEqual([1, 2, 3]); expected.toEqual([1, 2, 3]);
expect(results.getItems()[0].passed).toEqual(true); expect(results.getItems()[0].passed()).toEqual(true);
expected = new jasmine.Matchers(env, [1, 2, 3], results); expected = new jasmine.Matchers(env, [1, 2, 3], results);
results.getItems().length = 0; results.getItems().length = 0;
expected.toEqual([{}, {}, {}]); expected.toEqual([{}, {}, {}]);
expect(results.getItems()[0].passed).toEqual(false); expect(results.getItems()[0].passed()).toEqual(false);
expected = new jasmine.Matchers(env, [{}, {}, {}], results); expected = new jasmine.Matchers(env, [{}, {}, {}], results);
results.getItems().length = 0; results.getItems().length = 0;
expected.toEqual([1, 2, 3]); expected.toEqual([1, 2, 3]);
expect(results.getItems()[0].passed).toEqual(false); expect(results.getItems()[0].passed()).toEqual(false);
}); });
}); });

View File

@ -3,14 +3,14 @@ describe('jasmine.NestedResults', function() {
// Leaf case // Leaf case
var results = new jasmine.NestedResults(); var results = new jasmine.NestedResults();
results.addResult({passed: true, message: 'Passed.'}); results.addResult(new jasmine.ExpectationResult(true,'Passed.'));
expect(results.getItems().length).toEqual(1); expect(results.getItems().length).toEqual(1);
expect(results.totalCount).toEqual(1); expect(results.totalCount).toEqual(1);
expect(results.passedCount).toEqual(1); expect(results.passedCount).toEqual(1);
expect(results.failedCount).toEqual(0); expect(results.failedCount).toEqual(0);
results.addResult({passed: false, message: 'FAIL.'}); results.addResult(new jasmine.ExpectationResult(false, 'FAIL.'));
expect(results.getItems().length).toEqual(2); expect(results.getItems().length).toEqual(2);
expect(results.totalCount).toEqual(2); expect(results.totalCount).toEqual(2);
@ -21,12 +21,12 @@ describe('jasmine.NestedResults', function() {
it('should roll up counts for nested results', function() { it('should roll up counts for nested results', function() {
// Branch case // Branch case
var leafResultsOne = new jasmine.NestedResults(); var leafResultsOne = new jasmine.NestedResults();
leafResultsOne.addResult({passed: true, message: ''}); leafResultsOne.addResult(new jasmine.ExpectationResult( true, ''));
leafResultsOne.addResult({passed: false, message: ''}); leafResultsOne.addResult(new jasmine.ExpectationResult( false, ''));
var leafResultsTwo = new jasmine.NestedResults(); var leafResultsTwo = new jasmine.NestedResults();
leafResultsTwo.addResult({passed: true, message: ''}); leafResultsTwo.addResult(new jasmine.ExpectationResult( true, ''));
leafResultsTwo.addResult({passed: false, message: ''}); leafResultsTwo.addResult(new jasmine.ExpectationResult( false, ''));
var branchResults = new jasmine.NestedResults(); var branchResults = new jasmine.NestedResults();
branchResults.addResult(leafResultsOne); branchResults.addResult(leafResultsOne);

View File

@ -122,11 +122,32 @@ describe('RunnerTest', function() {
expect(fakeReporter.reportRunnerResults).wasCalledWith(env.currentRunner); expect(fakeReporter.reportRunnerResults).wasCalledWith(env.currentRunner);
}); });
});
it("should report when the tests start running", function() { it("should report when the tests start running", function() {
expect(fakeReporter.reportRunnerStarting).wasNotCalled(); var fakeReporter = jasmine.createSpyObj("fakeReporter", ["log", "reportRunnerStarting"]);
env.currentRunner.execute(); env.addReporter(fakeReporter);
expect(fakeReporter.reportRunnerStarting).wasCalledWith(env.currentRunner);
var runner = new jasmine.Runner(env);
spyOn(runner.queue, 'start');
runner.execute();
expect(fakeReporter.reportRunnerStarting).wasCalledWith(runner);
expect(runner.queue.start).wasCalled();
});
it("should return a flat array of all suites, including nested suites", function() {
var suite1, suite2;
suite1 = env.describe("spec 1", function() {
suite2 = env.describe("nested spec", function() {});
});
document.runner = env.currentRunner;
var suites = env.currentRunner.getAllSuites();
expect(suites).toEqual([suite1, suite2]);
}); });
}); });
});

View File

@ -69,10 +69,10 @@ describe("jasmine spec running", function () {
expect(specWithNoBody.description).toEqual('new spec'); expect(specWithNoBody.description).toEqual('new spec');
expect(specWithExpectation.results.getItems().length).toEqual(1); // "Results aren't there after a spec was executed" expect(specWithExpectation.results.getItems().length).toEqual(1); // "Results aren't there after a spec was executed"
expect(specWithExpectation.results.getItems()[0].passed).toEqual(true); // "Results has a result, but it's true" expect(specWithExpectation.results.getItems()[0].passed()).toEqual(true); // "Results has a result, but it's true"
expect(specWithExpectation.results.description).toEqual('spec with an expectation'); // "Spec's results did not get the spec's description" expect(specWithExpectation.results.description).toEqual('spec with an expectation'); // "Spec's results did not get the spec's description"
expect(specWithFailingExpectations.results.getItems()[0].passed).toEqual(false); // "Expectation that failed, passed" expect(specWithFailingExpectations.results.getItems()[0].passed()).toEqual(false); // "Expectation that failed, passed"
expect(specWithMultipleExpectations.results.getItems().length).toEqual(2); // "Spec doesn't support multiple expectations" expect(specWithMultipleExpectations.results.getItems().length).toEqual(2); // "Spec doesn't support multiple expectations"
}); });
@ -91,8 +91,8 @@ describe("jasmine spec running", function () {
another_spec.done = true; another_spec.done = true;
expect(another_spec.results.getItems().length).toEqual(2); expect(another_spec.results.getItems().length).toEqual(2);
expect(another_spec.results.getItems()[0].passed).toEqual(true); // "In a spec without a run block, expected first expectation result to be true but was false" expect(another_spec.results.getItems()[0].passed()).toEqual(true); // "In a spec without a run block, expected first expectation result to be true but was false"
expect(another_spec.results.getItems()[1].passed).toEqual(false); // "In a spec without a run block, expected second expectation result to be false but was true"; expect(another_spec.results.getItems()[1].passed()).toEqual(false); // "In a spec without a run block, expected second expectation result to be false but was true";
expect(another_spec.results.description).toEqual('spec with an expectation'); // "In a spec without a run block, results did not include the spec's description"; expect(another_spec.results.description).toEqual('spec with an expectation'); // "In a spec without a run block, results did not include the spec's description";
}); });
@ -145,7 +145,7 @@ describe("jasmine spec running", function () {
fakeTimer.tick(0); fakeTimer.tick(0);
expect(a_spec.results.getItems().length).toEqual(1); // 'No call to waits(): Spec queue did not run all functions'; expect(a_spec.results.getItems().length).toEqual(1); // 'No call to waits(): Spec queue did not run all functions';
expect(a_spec.results.getItems()[0].passed).toEqual(true); // 'No call to waits(): Queued expectation failed'; expect(a_spec.results.getItems()[0].passed()).toEqual(true); // 'No call to waits(): Queued expectation failed';
foo = 0; foo = 0;
env.describe('test async spec', function() { env.describe('test async spec', function() {
@ -173,7 +173,7 @@ describe("jasmine spec running", function () {
fakeTimer.tick(500); fakeTimer.tick(500);
expect(a_spec.results.getItems().length).toEqual(1); // 'Calling waits(): Spec queue did not run all functions'; expect(a_spec.results.getItems().length).toEqual(1); // 'Calling waits(): Spec queue did not run all functions';
expect(a_spec.results.getItems()[0].passed).toEqual(true); // 'Calling waits(): Queued expectation failed'; expect(a_spec.results.getItems()[0].passed()).toEqual(true); // 'Calling waits(): Queued expectation failed';
var bar = 0; var bar = 0;
var another_spec; var another_spec;
@ -204,7 +204,7 @@ describe("jasmine spec running", function () {
fakeTimer.tick(1000); fakeTimer.tick(1000);
expect(another_spec.results.getItems().length).toEqual(1); expect(another_spec.results.getItems().length).toEqual(1);
expect(another_spec.results.getItems()[0].passed).toEqual(true); expect(another_spec.results.getItems()[0].passed()).toEqual(true);
var baz = 0; var baz = 0;
var yet_another_spec; var yet_another_spec;
@ -230,7 +230,7 @@ describe("jasmine spec running", function () {
expect(yet_another_spec.results.getItems().length).toEqual(1); expect(yet_another_spec.results.getItems().length).toEqual(1);
expect(yet_another_spec.results.getItems()[0].passed).toEqual(false); expect(yet_another_spec.results.getItems()[0].passed()).toEqual(false);
}); });
it("testAsyncSpecsWithMockSuite", function () { it("testAsyncSpecsWithMockSuite", function () {
@ -259,7 +259,7 @@ describe("jasmine spec running", function () {
another_spec.execute(); another_spec.execute();
fakeTimer.tick(2000); fakeTimer.tick(2000);
expect(another_spec.results.getItems().length).toEqual(1); expect(another_spec.results.getItems().length).toEqual(1);
expect(another_spec.results.getItems()[0].passed).toEqual(true); expect(another_spec.results.getItems()[0].passed()).toEqual(true);
}); });
it("testWaitsFor", function() { it("testWaitsFor", function() {
@ -431,9 +431,9 @@ describe("jasmine spec running", function () {
fakeTimer.tick(0); fakeTimer.tick(0);
var suite = suiteWithBefore; var suite = suiteWithBefore;
expect(suite.beforeEachFunction); // "testBeforeAndAfterCallbacks: Suite's beforeEach was not defined");
expect(suite.getResults()[0].passed()).toEqual(true); // "testBeforeAndAfterCallbacks: the first spec's foo should have been 2"); expect(suite.getResults().getItems()[0].passed()).toEqual(true); // "testBeforeAndAfterCallbacks: the first spec's foo should have been 2");
expect(suite.getResults()[1].passed()).toEqual(true); // "testBeforeAndAfterCallbacks: the second spec's this.foo should have been 2"); expect(suite.getResults().getItems()[1].passed()).toEqual(true); // "testBeforeAndAfterCallbacks: the second spec's this.foo should have been 2");
var foo = 1; var foo = 1;
@ -461,8 +461,8 @@ describe("jasmine spec running", function () {
suite = suiteWithAfter; suite = suiteWithAfter;
expect(suite.afterEach.length).toEqual(1); expect(suite.afterEach.length).toEqual(1);
expect(suite.getResults()[0].passed()).toEqual(true); expect(suite.getResults().getItems()[0].passed()).toEqual(true);
expect(suite.getResults()[1].passed()).toEqual(true); expect(suite.getResults().getItems()[1].passed()).toEqual(true);
expect(foo).toEqual(0); expect(foo).toEqual(0);
}); });
@ -822,8 +822,8 @@ describe("jasmine spec running", function () {
expect(report).toEqual("firstsecond"); expect(report).toEqual("firstsecond");
var suiteResults = suite.getResults(); var suiteResults = suite.getResults();
expect(suiteResults[0].getItems()[0].passed).toEqual(false); expect(suiteResults.getItems()[0].getItems()[0].passed()).toEqual(false);
expect(suiteResults[1].getItems()[0].passed).toEqual(true); expect(suiteResults.getItems()[1].getItems()[0].passed()).toEqual(true);
}); });
it("testAfterExecutesSafely", function() { it("testAfterExecutesSafely", function() {
@ -862,16 +862,16 @@ describe("jasmine spec running", function () {
expect(report).toEqual("firstsecondthird"); // "all tests should run"); expect(report).toEqual("firstsecondthird"); // "all tests should run");
//After each errors should not go in spec results because it confuses the count. //After each errors should not go in spec results because it confuses the count.
var suiteResults = suite.getResults(); var suiteResults = suite.getResults();
expect(suiteResults.length).toEqual(3, 'testAfterExecutesSafely should have results for three specs'); expect(suiteResults.getItems().length).toEqual(3, 'testAfterExecutesSafely should have results for three specs');
expect(suiteResults[0].getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 1st spec should pass"); expect(suiteResults.getItems()[0].getItems()[0].passed()).toEqual(true, "testAfterExecutesSafely 1st spec should pass");
expect(suiteResults[1].getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 2nd spec should pass"); expect(suiteResults.getItems()[1].getItems()[0].passed()).toEqual(true, "testAfterExecutesSafely 2nd spec should pass");
expect(suiteResults[2].getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 3rd spec should pass"); expect(suiteResults.getItems()[2].getItems()[0].passed()).toEqual(true, "testAfterExecutesSafely 3rd spec should pass");
expect(suiteResults[0].getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 1st result for 1st suite spec should pass"); expect(suiteResults.getItems()[0].getItems()[0].passed()).toEqual(true, "testAfterExecutesSafely 1st result for 1st suite spec should pass");
expect(suiteResults[0].getItems()[1].passed).toEqual(false, "testAfterExecutesSafely 2nd result for 1st suite spec should fail because afterEach failed"); expect(suiteResults.getItems()[0].getItems()[1].passed()).toEqual(false, "testAfterExecutesSafely 2nd result for 1st suite spec should fail because afterEach failed");
expect(suiteResults[1].getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 2nd suite spec should pass"); expect(suiteResults.getItems()[1].getItems()[0].passed()).toEqual(true, "testAfterExecutesSafely 2nd suite spec should pass");
expect(suiteResults[2].getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 3rd suite spec should pass"); expect(suiteResults.getItems()[2].getItems()[0].passed()).toEqual(true, "testAfterExecutesSafely 3rd suite spec should pass");
}); });
it("testNestedDescribes", function() { it("testNestedDescribes", function() {
@ -998,9 +998,9 @@ describe("jasmine spec running", function () {
fakeTimer.tick(600); fakeTimer.tick(600);
expect(spec.foo).toEqual(2); expect(spec.foo).toEqual(2);
var suiteResults = suite.getResults(); var suiteResults = suite.getResults();
expect(suiteResults[0].getItems().length).toEqual(2); expect(suiteResults.getItems()[0].getItems().length).toEqual(2);
expect(suiteResults[0].getItems()[0].passed).toEqual(false); expect(suiteResults.getItems()[0].getItems()[0].passed()).toEqual(false);
expect(suiteResults[0].getItems()[1].passed).toEqual(true); expect(suiteResults.getItems()[0].getItems()[1].passed()).toEqual(true);
}); });
it("shouldn't run disabled tests", function() { it("shouldn't run disabled tests", function() {

View File

@ -0,0 +1,34 @@
describe("TrivialReporter", function() {
var trivialReporter;
var body;
beforeEach(function() {
body = document.createElement("body");
});
function fakeSpec(name) {
return {
getFullName: function() { return name; }
};
}
it("should run only specs beginning with spec parameter", function() {
trivialReporter = new jasmine.TrivialReporter({ location: {search: "?spec=run%20this"} });
expect(trivialReporter.specFilter(fakeSpec("run this"))).toBeTruthy();
expect(trivialReporter.specFilter(fakeSpec("not the right spec"))).toBeFalsy();
expect(trivialReporter.specFilter(fakeSpec("not run this"))).toBeFalsy();
});
it("should display empty divs for every suite when the runner is starting", function() {
trivialReporter = new jasmine.TrivialReporter({ body: body });
trivialReporter.reportRunnerStarting({
getAllSuites: function() {
return [ new jasmine.Suite({}, "suite 1", null, null) ];
}
});
var divs = body.getElementsByTagName("div");
expect(divs.length).toEqual(2);
expect(divs[1].innerHTML).toContain("suite 1");
});
});

View File

@ -216,6 +216,16 @@ jasmine.Matchers.prototype.toNotContain = function(item) {
'Expected ' + jasmine.Matchers.pp(this.actual) + ' not to contain ' + jasmine.Matchers.pp(item) + ', but it does.'); 'Expected ' + jasmine.Matchers.pp(this.actual) + ' not to contain ' + jasmine.Matchers.pp(item) + ', but it does.');
}; };
jasmine.Matchers.prototype.toBeLessThan = function(expected) {
return this.report(this.actual < expected,
'Expected ' + jasmine.Matchers.pp(this.actual) + ' to be less than ' + jasmine.Matchers.pp(expected) + ', but it was not.');
};
jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
return this.report(this.actual > expected,
'Expected ' + jasmine.Matchers.pp(this.actual) + ' to be greater than ' + jasmine.Matchers.pp(expected) + ', but it was not.');
};
/** /**
* Matcher that checks that the expected exception was thrown by the actual. * Matcher that checks that the expected exception was thrown by the actual.
* *

View File

@ -62,7 +62,7 @@ jasmine.NestedResults.prototype.addResult = function(result) {
this.rollupCounts(result); this.rollupCounts(result);
} else { } else {
this.totalCount++; this.totalCount++;
if (result.passed) { if (result.passed()) {
this.passedCount++; this.passedCount++;
} else { } else {
this.failedCount++; this.failedCount++;

View File

@ -59,9 +59,11 @@ jasmine.Queue.prototype.finish = function () {
}; };
jasmine.Queue.prototype.getResults = function () { jasmine.Queue.prototype.getResults = function () {
var results = []; var results = new jasmine.NestedResults();
for (var i = 0; i < this.blocks.length; i++) { for (var i = 0; i < this.blocks.length; i++) {
results.push(this.blocks[i].getResults()); if (this.blocks[i].getResults) {
results.addResult(this.blocks[i].getResults());
}
} }
return results; return results;
}; };

View File

@ -8,6 +8,7 @@ jasmine.Runner = function(env) {
var self = this; var self = this;
self.env = env; self.env = env;
self.queue = new jasmine.Queue(env); self.queue = new jasmine.Queue(env);
self.suites = [];
}; };
jasmine.Runner.prototype.execute = function() { jasmine.Runner.prototype.execute = function() {
@ -15,25 +16,31 @@ jasmine.Runner.prototype.execute = function() {
if (self.env.reporter.reportRunnerStarting) { if (self.env.reporter.reportRunnerStarting) {
self.env.reporter.reportRunnerStarting(this); self.env.reporter.reportRunnerStarting(this);
} }
self.queue.start(function () { self.finishCallback(); }); self.queue.start(function () {
self.finishCallback();
});
}; };
jasmine.Runner.prototype.finishCallback = function() { jasmine.Runner.prototype.finishCallback = function() {
this.env.reporter.reportRunnerResults(this); this.env.reporter.reportRunnerResults(this);
}; };
jasmine.Runner.prototype.addSuite = function(suite) {
this.suites.push(suite);
};
jasmine.Runner.prototype.add = function(block) { jasmine.Runner.prototype.add = function(block) {
if (block instanceof jasmine.Suite) {
this.addSuite(block);
}
this.queue.add(block); this.queue.add(block);
}; };
jasmine.Runner.prototype.getResults = function() {
var results = new jasmine.NestedResults(); jasmine.Runner.prototype.getAllSuites = function() {
var runnerResults = this.queue.getResults(); return this.suites;
for (var i=0; i < runnerResults.length; i++) { };
var suiteResults = runnerResults[i];
for (var j=0; j < suiteResults.length; j++) { jasmine.Runner.prototype.getResults = function() {
results.rollupCounts(suiteResults[j]); return this.queue.getResults();
}
}
return results;
}; };

View File

@ -50,6 +50,9 @@ jasmine.Suite.prototype.getResults = function() {
}; };
jasmine.Suite.prototype.add = function(block) { jasmine.Suite.prototype.add = function(block) {
if (block instanceof jasmine.Suite) {
this.env.currentRunner.addSuite(block);
}
this.queue.add(block); this.queue.add(block);
}; };

View File

@ -40,12 +40,16 @@ jasmine.MessageResult = function(text) {
jasmine.ExpectationResult = function(passed, message, details) { jasmine.ExpectationResult = function(passed, message, details) {
this.type = 'ExpectationResult'; this.type = 'ExpectationResult';
this.passed = passed; this.passed_ = passed;
this.message = message; this.message = message;
this.details = details; this.details = details;
this.trace = new Error(message); // todo: test better this.trace = new Error(message); // todo: test better
}; };
jasmine.ExpectationResult.prototype.passed = function () {
return this.passed_;
};
/** /**
* Getter for the Jasmine environment. Ensures one gets created * Getter for the Jasmine environment. Ensures one gets created
*/ */