Merge in Pivotal changes

This commit is contained in:
ragaskar 2009-07-29 22:41:38 -07:00
commit f84c67b98a
14 changed files with 538 additions and 242 deletions

View File

@ -0,0 +1,188 @@
require 'socket'
require 'erb'
module Jasmine
# this seemingly-over-complex method is necessary to get an open port on at least some of our Macs
def self.open_socket_on_unused_port
infos = Socket::getaddrinfo("localhost", nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten]
return TCPServer.open('0.0.0.0', 0) if families.has_key?('AF_INET')
return TCPServer.open('::', 0) if families.has_key?('AF_INET6')
return TCPServer.open(0)
end
def self.find_unused_port
socket = open_socket_on_unused_port
port = socket.addr[1]
socket.close
port
end
class RunAdapter
def initialize(spec_files)
p "spec_files: #{spec_files}"
@spec_files = spec_files
end
def call(env)
spec_files = @spec_files
body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html"))).result(binding)
[
200,
{ 'Content-Type' => 'text/html' },
body
]
end
end
class SimpleServer
def self.start(port, spec_dir, mappings)
require 'thin'
config = {
'/run.html' => Jasmine::RunAdapter.new(spec_dir)
}
mappings.each do |from, to|
config[from] = Rack::File.new(to)
end
app = Rack::URLMap.new(config)
server_port = Jasmine::find_unused_port
Thin::Server.start('0.0.0.0', port, app)
end
end
class SimpleClient
def initialize(selenium_host, selenium_port, selenium_browser_start_command, http_address)
require 'selenium'
@driver = Selenium::Client::Driver.new(
selenium_host,
selenium_port,
selenium_browser_start_command,
http_address
)
@http_address = http_address
end
def tests_have_finished?
@driver.get_eval("window.jasmine.getEnv().currentRunner.finished") == "true"
end
def connect
@driver.start
@driver.open("/run.html")
end
def disconnect
@driver.stop
end
def run
until tests_have_finished? do
sleep 0.1
end
puts @driver.get_eval("window.getResults()")
failed_count = @driver.get_eval("window.jasmine.getEnv().currentRunner.getResults().failedCount").to_i
failed_count == 0
end
def eval_js(script)
escaped_script = "'" + script.gsub(/(['\\])/) { '\\' + $1 } + "'"
result = @driver.get_eval("window.eval(#{escaped_script})")
JSON.parse("[#{result}]")[0]
end
end
class Runner
def initialize(selenium_jar_path, spec_files, dir_mappings)
@selenium_jar_path = selenium_jar_path
@spec_files = spec_files
@dir_mappings = dir_mappings
@selenium_pid = nil
@jasmine_server_pid = nil
end
def start
start_servers
@client = Jasmine::SimpleClient.new("localhost", @selenium_server_port, "*firefox", "http://localhost:#{@jasmine_server_port}/")
@client.connect
end
def stop
@client.disconnect
stop_servers
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
@jasmine_server_port = Jasmine::find_unused_port
@selenium_server_port = Jasmine::find_unused_port
@selenium_pid = fork do
Process.setpgrp
exec "java -jar #{@selenium_jar_path} -port #{@selenium_server_port} > /dev/null 2>&1"
end
puts "selenium started. pid is #{@selenium_pid}"
@jasmine_server_pid = fork do
Process.setpgrp
Jasmine::SimpleServer.start(@jasmine_server_port, @spec_files, @dir_mappings)
exit! 0
end
puts "jasmine server started. pid is #{@jasmine_server_pid}"
wait_for_listener(@selenium_server_port, "selenium server")
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
def stop_servers
puts "shutting down the servers..."
kill_process_group(@selenium_pid) if @selenium_pid
kill_process_group(@jasmine_server_pid) if @jasmine_server_pid
end
def run
begin
start
puts "servers are listening on their ports -- running the test script..."
tests_passed = @client.run
ensure
stop
end
return tests_passed
end
def eval_js(script)
@client.eval_js(script)
end
end
end

View File

@ -0,0 +1,142 @@
require File.expand_path(File.join(File.dirname(__FILE__), "jasmine_runner.rb"))
module Jasmine
class SpecBuilder
attr_accessor :suites
def initialize(spec_files, runner)
@spec_files = spec_files
@runner = runner
end
def start
guess_example_locations
@runner.start
load_suite_info
@spec_results = {}
end
def stop
@runner.stop
end
def script_path
File.expand_path(__FILE__)
end
def guess_example_locations
@example_locations = {}
example_name_parts = []
previous_indent_level = 0
@spec_files.each do |filename|
line_number = 1
File.open(filename, "r") do |file|
file.readlines.each do |line|
match = /^(\s*)(describe|it)\s*\(\s*["'](.*)["']\s*,\s*function/.match(line)
if (match)
indent_level = match[1].length / 2
example_name = match[3]
example_name_parts[indent_level] = example_name
full_example_name = example_name_parts.slice(0, indent_level + 1).join(" ")
@example_locations[full_example_name] = "#{filename}:#{line_number}: in `it'"
end
line_number += 1
end
end
end
end
def load_suite_info
while !eval_js('jsApiReporter.started') do
sleep 0.1
end
@suites = eval_js('JSON.stringify(jsApiReporter.suites)')
end
def results_for(spec_id)
spec_id = spec_id.to_s
return @spec_results[spec_id] if @spec_results[spec_id]
@spec_results[spec_id] = eval_js("JSON.stringify(jsApiReporter.results[#{spec_id}])")
while @spec_results[spec_id].nil? do
sleep 0.1
@spec_results[spec_id] = eval_js("JSON.stringify(jsApiReporter.results[#{spec_id}])")
end
@spec_results[spec_id]
end
def declare_suites
me = self
suites.each do |suite|
declare_suite(self, suite)
end
end
def declare_suite(parent, suite)
me = self
parent.describe suite["name"] do
suite["children"].each do |suite_or_spec|
type = suite_or_spec["type"]
if type == "suite"
me.declare_suite(self, suite_or_spec)
elsif type == "spec"
me.declare_spec(self, suite_or_spec)
else
raise "unknown type #{type} for #{suite_or_spec.inspect}"
end
end
end
end
def declare_spec(parent, spec)
me = self
example_name = spec["name"]
backtrace = @example_locations[parent.description + " " + example_name]
parent.it example_name, {}, backtrace do
me.report_spec(spec["id"])
end
end
def report_spec(spec_id)
spec_results = results_for(spec_id)
out = ""
messages = spec_results['messages'].each do |message|
case
when message["type"] == "MessageResult"
puts message["text"]
puts "\n"
else
STDERR << message["message"]
STDERR << "\n"
out << message["message"]
out << "\n"
unless message["passed"]
stack_trace = message["trace"]["stack"]
STDERR << stack_trace.gsub(/\(.*\)@http:\/\/localhost:[0-9]+\/specs\//, "/spec/")
STDERR << "\n"
end
end
end
fail out unless spec_results['result'] == 'passed'
puts out
end
private
def eval_js(js)
@runner.eval_js(js)
end
end
end

29
contrib/ruby/run.html Normal file
View File

@ -0,0 +1,29 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type"/>
<title>Jasmine suite</title>
<script src="/specs/javascripts/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="/specs/javascripts/jasmine/lib/TrivialReporter.js"></script>
<script src="/specs/javascripts/screw-jasmine-compat.js"></script>
<script type="text/javascript"></script>
<link href="/core/jasmine.css" rel="stylesheet"/>
<script type="text/javascript">
var jasmineEnv = jasmine.getEnv();
var jsApiReporter = new jasmine.JsApiReporter();
jasmineEnv.addReporter(jsApiReporter);
jasmineEnv.addReporter(new jasmine.TrivialReporter());
window.onload = function() {
jasmineEnv.execute();
};
</script>
<% spec_files.each do |spec_file| %>
<script src="<%= spec_file %>" type="text/javascript"></script>
<% end %>
</head>
<body>
<div id="jasmine_content"></div>
</body>
</html>

View File

@ -35,7 +35,7 @@ jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
var specDiv = this.createDom('div', {
className: spec.getResults().passed() ? 'spec passed' : 'spec failed'
className: spec.getResults().passed ? 'spec passed' : 'spec failed'
}, spec.getFullName());
var resultItems = spec.getResults().getItems();

View File

@ -587,6 +587,7 @@ jasmine.Env = function() {
};
this.nextSpecId_ = 0;
this.nextSuiteId_ = 0;
this.equalityTesters_ = [];
};
@ -869,7 +870,7 @@ jasmine.Reporter.prototype.reportSpecResults = function(spec) {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.log = function (str) {
jasmine.Reporter.prototype.log = function(str) {
};
/**
@ -914,7 +915,8 @@ jasmine.Block.prototype.fail = function(e) {
*/
jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
jasmine.ActionCollection.call(this, env);
this.id = env.nextSuiteId_++;
this.description = description;
this.specs = this.actions;
this.parentSuite = parentSuite;
@ -948,6 +950,9 @@ jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
jasmine.Suite.prototype.getResults = function() {
var results = new jasmine.NestedResults();
results.description = this.description;
results.id = this.id;
for (var i = 0; i < this.specs.length; i++) {
results.rollupCounts(this.specs[i].getResults());
}
@ -984,7 +989,7 @@ jasmine.PrettyPrinter.prototype.format = function(value) {
} else if (value instanceof jasmine.Matchers.Any) {
this.emitScalar(value.toString());
} else if (typeof value === 'string') {
this.emitScalar("'" + value + "'");
this.emitString(value);
} else if (typeof value === 'function') {
this.emitScalar('Function');
} else if (typeof value.nodeType === 'number') {
@ -1019,6 +1024,7 @@ jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
jasmine.StringPrettyPrinter = function() {
jasmine.PrettyPrinter.call(this);
@ -1031,6 +1037,10 @@ jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
this.append(value);
};
jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
this.append("'" + value + "'");
};
jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
this.append('[ ');
for (var i = 0; i < array.length; i++) {
@ -1097,6 +1107,64 @@ jasmine.MultiReporter.prototype.addReporter = function(reporter) {
})(functionName);
}
})();
/** JavaScript API reporter.
*
* @constructor
*/
jasmine.JsApiReporter = function() {
this.started = false;
this.finished = false;
this.suites = [];
this.results = {};
};
jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
this.started = true;
for (var i = 0; i < runner.suites.length; i++) {
var suite = runner.suites[i];
this.suites.push(this.summarize_(suite));
}
};
jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
var summary = {
id: suiteOrSpec.id,
name: suiteOrSpec.description,
type: suiteOrSpec instanceof jasmine.Suite ? 'suite' : 'spec',
children: []
};
if (suiteOrSpec.specs) {
for (var i = 0; i < suiteOrSpec.specs.length; i++) {
summary.children.push(this.summarize_(suiteOrSpec.specs[i]));
}
}
return summary;
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
this.finished = true;
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
this.results[spec.id] = {
messages: spec.results.getItems(),
result: spec.results.failedCount > 0 ? "failed" : "passed"
};
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.log = function(str) {
};
/**
* Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
*
@ -1174,9 +1242,9 @@ jasmine.NestedResults.prototype.addResult = function(result) {
/**
* @returns {Boolean} True if <b>everything</b> below passed
*/
jasmine.NestedResults.prototype.passed = function() {
jasmine.NestedResults.prototype.__defineGetter__('passed', function() {
return this.passedCount === this.totalCount;
};
});
/**
* Runner
*

View File

@ -1,52 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Tests</title>
<script type="text/javascript" src="lib/json2.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/Env.js"></script>
<script type="text/javascript" src="../src/ActionCollection.js"></script>
<script type="text/javascript" src="../src/Matchers.js"></script>
<script type="text/javascript" src="../src/NestedResults.js"></script>
<script type="text/javascript" src="../src/PrettyPrinter.js"></script>
<script type="text/javascript" src="../src/Block.js"></script>
<script type="text/javascript" src="../src/WaitsBlock.js"></script>
<script type="text/javascript" src="../src/WaitsForBlock.js"></script>
<script type="text/javascript" src="../src/Reporters.js"></script>
<script type="text/javascript" src="../src/Runner.js"></script>
<script type="text/javascript" src="../src/Spec.js"></script>
<script type="text/javascript" src="../src/Suite.js"></script>
<script type="text/javascript" src="../src/mock-timeout.js"></script>
<script type="text/javascript" src="bootstrap.js"></script>
<link type="text/css" rel="stylesheet" href="../lib/jasmine.css"/>
</head>
<body onLoad="runTests();">
<h1>
Running all Jasmine Test Suites
</h1>
<div id="icon_wrapper">
<span id="icons"></span>
<img id="spinner" src="../images/spinner.gif" alt="" />
</div>
<div id="report">
<div id="results_summary" style="display:none;">
<h2>Summary</h2>
</div>
<div id="fails" style="display:none;">
<h2 id="fails_header">Failure Messages</h2>
<div id="fail_messages"></div>
</div>
</div>
<div style="display:none" id="json_reporter_results"></div>
<div style="display:none" id="json_reporter_results_incremental"></div>
</body>
</html>

146
spec/bootstrap.js vendored
View File

@ -1,146 +0,0 @@
var createElement = function(tag, attrs) {
var element = document.createElement(tag);
for (var attr in attrs) {
element[attr] = attrs[attr];
}
return element;
};
// Bootstrap Test Reporter function
var Reporter = function () {
this.total = 0;
this.passes = 0;
this.fails = 0;
this.start = new Date();
};
Reporter.prototype.toJSON = function(object) {
return JSON.stringify(object);
};
Reporter.prototype.test = function (result, message) {
this.total++;
if (result) {
this.passes++;
iconElement = document.getElementById('icons');
iconElement.appendChild(createElement('img', {src: '../images/go-16.png'}));
}
else {
this.fails++;
var fails_report = document.getElementById('fails');
fails_report.style.display = "";
var iconElement = document.getElementById('icons');
iconElement.appendChild(createElement('img', {src: '../images/fail-16.png'}));
var failMessages = document.getElementById('fail_messages');
var newFail = createElement('p', {'class': 'fail'});
newFail.innerHTML = message;
failMessages.appendChild(newFail);
}
};
Reporter.prototype.summary = function () {
var el = createElement('p', {'class': ((this.fails > 0) ? 'fail_in_summary' : '') });
el.innerHTML = this.total + ' expectations, ' + this.passes + ' passing, ' + this.fails + ' failed in ' + (new Date().getTime() - this.start.getTime()) + "ms.";
var summaryElement = document.getElementById('results_summary');
summaryElement.appendChild(el);
summaryElement.style.display = "";
};
var reporter = new Reporter();
function runSuite(filename) {
console.log(filename);
var suite = jasmine.include(filename);
suite.execute();
emitSuiteResults(filename, suite);
}
function emitSpecResults(testName, spec) {
var results = spec.results.getItems();
reporter.test(results.length > 0, testName + ": should have results, got " + results.length);
for (var i = 0; i < results.length; i++) {
reporter.test(results[i].passed === true, testName + ':' + spec.getFullName() + ": expectation number " + i + " failed: " + results[i].message);
}
}
function emitSuiteResults(testName, suite) {
for (var j = 0; j < suite.specs.length; j++) {
var specOrSuite = suite.specs[j];
if (specOrSuite instanceof jasmine.Suite) {
emitSuiteResults(testName, specOrSuite);
} else {
emitSpecResults(testName, specOrSuite);
}
}
}
var testExplodes = function () {
var suite = describe('exploding', function () {
it('should throw an exception when this.explodes is called inside a spec', function() {
var exceptionMessage = false;
try {
this.explodes();
}
catch (e) {
exceptionMessage = e;
}
expect(exceptionMessage).toEqual('explodes function should not have been called');
});
});
suite.execute();
emitSuiteResults('testExplodes', suite);
};
function newJasmineEnv() {
return new jasmine.Env();
}
var testRunner = function() {
};
var testRunnerFinishCallback = function () {
var env = newJasmineEnv();
var foo = 0;
env.currentRunner.finish();
reporter.test((env.currentRunner.finished === true),
"Runner finished flag was not set.");
env.currentRunner.finishCallback = function () {
foo++;
};
env.currentRunner.finish();
reporter.test((env.currentRunner.finished === true),
"Runner finished flag was not set.");
reporter.test((foo === 1),
"Runner finish callback was not called");
};
var runTests = function () {
document.getElementById('spinner').style.display = "";
runSuite('suites/PrettyPrintTest.js');
runSuite('suites/MatchersTest.js');
runSuite('suites/SpecRunningTest.js');
runSuite('suites/NestedResultsTest.js');
runSuite('suites/ReporterTest.js');
runSuite('suites/RunnerTest.js');
runSuite('suites/SpyTest.js');
runSuite('suites/ExceptionsTest.js');
reporter.summary();
document.getElementById('spinner').style.display = "none";
};

View File

@ -3,7 +3,6 @@
<html>
<head>
<title>Jasmine Test Runner</title>
</head>
<script type="text/javascript" src="../src/base.js"></script>
<script type="text/javascript" src="../src/util.js"></script>
<script type="text/javascript" src="../src/Env.js"></script>
@ -25,43 +24,43 @@
<script type="text/javascript" src="../lib/TrivialReporter.js"></script>
<script type="text/javascript">
jasmine.include('suites/ExceptionsTest.js', true);
jasmine.include('suites/EnvTest.js', true);
jasmine.include('suites/JsonReporterTest.js', true);
jasmine.include('suites/MatchersTest.js', true);
jasmine.include('suites/MultiReporterTest.js', true);
jasmine.include('suites/NestedResultsTest.js', true);
jasmine.include('suites/PrettyPrintTest.js', true);
jasmine.include('suites/ReporterTest.js', true);
jasmine.include('suites/RunnerTest.js', true);
jasmine.include('suites/SpecRunningTest.js', true);
jasmine.include('suites/SpyTest.js', true);
</script>
<script type="text/javascript">
jasmine.include('suites/EnvTest.js', true);
jasmine.include('suites/ExceptionsTest.js', true);
jasmine.include('suites/MatchersTest.js', true);
jasmine.include('suites/MultiReporterTest.js', true);
jasmine.include('suites/NestedResultsTest.js', true);
jasmine.include('suites/PrettyPrintTest.js', true);
jasmine.include('suites/ReporterTest.js', true);
jasmine.include('suites/RunnerTest.js', true);
jasmine.include('suites/SpecRunningTest.js', true);
jasmine.include('suites/SpyTest.js', true);
</script>
<style type="text/css">
.spec {
margin: 5px;
}
<style type="text/css">
.spec {
margin: 5px;
}
.passed {
background-color: lightgreen;
}
.passed {
background-color: lightgreen;
}
.failed {
background-color: pink;
}
.failed {
background-color: pink;
}
.resultMessage {
white-space: pre;
}
.resultMessage {
white-space: pre;
}
.stackTrace {
white-space: pre;
font-size: .8em;
margin-left: 10px;
}
</style>
.stackTrace {
white-space: pre;
font-size: .8em;
margin-left: 10px;
}
</style>
</head>
<body>

View File

@ -18,6 +18,7 @@ jasmine.Env = function() {
};
this.nextSpecId_ = 0;
this.nextSuiteId_ = 0;
this.equalityTesters_ = [];
};

58
src/JsApiReporter.js Normal file
View File

@ -0,0 +1,58 @@
/** JavaScript API reporter.
*
* @constructor
*/
jasmine.JsApiReporter = function() {
this.started = false;
this.finished = false;
this.suites = [];
this.results = {};
};
jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
this.started = true;
for (var i = 0; i < runner.suites.length; i++) {
var suite = runner.suites[i];
this.suites.push(this.summarize_(suite));
}
};
jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
var summary = {
id: suiteOrSpec.id,
name: suiteOrSpec.description,
type: suiteOrSpec instanceof jasmine.Suite ? 'suite' : 'spec',
children: []
};
if (suiteOrSpec.specs) {
for (var i = 0; i < suiteOrSpec.specs.length; i++) {
summary.children.push(this.summarize_(suiteOrSpec.specs[i]));
}
}
return summary;
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
this.finished = true;
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
this.results[spec.id] = {
messages: spec.results.getItems(),
result: spec.results.failedCount > 0 ? "failed" : "passed"
};
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.log = function(str) {
};

View File

@ -75,6 +75,6 @@ jasmine.NestedResults.prototype.addResult = function(result) {
/**
* @returns {Boolean} True if <b>everything</b> below passed
*/
jasmine.NestedResults.prototype.passed = function() {
jasmine.NestedResults.prototype.__defineGetter__('passed', function() {
return this.passedCount === this.totalCount;
};
});

View File

@ -28,7 +28,7 @@ jasmine.PrettyPrinter.prototype.format = function(value) {
} else if (value instanceof jasmine.Matchers.Any) {
this.emitScalar(value.toString());
} else if (typeof value === 'string') {
this.emitScalar("'" + value + "'");
this.emitString(value);
} else if (typeof value === 'function') {
this.emitScalar('Function');
} else if (typeof value.nodeType === 'number') {
@ -63,6 +63,7 @@ jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
jasmine.StringPrettyPrinter = function() {
jasmine.PrettyPrinter.call(this);
@ -75,6 +76,10 @@ jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
this.append(value);
};
jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
this.append("'" + value + "'");
};
jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
this.append('[ ');
for (var i = 0; i < array.length; i++) {

View File

@ -22,6 +22,6 @@ jasmine.Reporter.prototype.reportSpecResults = function(spec) {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.log = function (str) {
jasmine.Reporter.prototype.log = function(str) {
};

View File

@ -9,7 +9,8 @@
*/
jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
jasmine.ActionCollection.call(this, env);
this.id = env.nextSuiteId_++;
this.description = description;
this.specs = this.actions;
this.parentSuite = parentSuite;
@ -43,6 +44,9 @@ jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
jasmine.Suite.prototype.getResults = function() {
var results = new jasmine.NestedResults();
results.description = this.description;
results.id = this.id;
for (var i = 0; i < this.specs.length; i++) {
results.rollupCounts(this.specs[i].getResults());
}