start work on writing out report files usable by other things

This commit is contained in:
John Bintz 2011-10-10 14:11:13 -04:00
parent b04bb49879
commit 0be7b9e20c
19 changed files with 619 additions and 500 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ hydra-runner.log
jhw-test
.jhw-cache/
_site/
jhw.*.html

View File

@ -10,19 +10,12 @@ end
$:.unshift(File.join(gem_dir, 'lib'))
require 'jasmine-headless-webkit'
require 'jasmine/headless/errors'
require 'jasmine/headless/runner'
require 'jasmine/headless/options'
begin
options = Jasmine::Headless::Options.from_command_line
runner = Jasmine::Headless::Runner.new(options)
if options[:do_list]
files_list = Jasmine::FilesList.new(
:config => runner.jasmine_config
)
files_list = Jasmine::FilesList.new(:config => runner.jasmine_config)
files_list.files.each { |file| puts file }
else
puts "Running Jasmine specs...".color(:white)

View File

@ -1,174 +1,175 @@
if !jasmine?
throw new Error("jasmine not laoded!")
if window.JHW
# Jasmine extensions
getSplitName = (parts) ->
parts.push(String(@description).replace(/[\n\r]/g, ' '))
parts
getSplitName = (parts) ->
parts.push(String(@description).replace(/[\n\r]/g, ' '))
parts
jasmine.Suite.prototype.getSuiteSplitName = ->
this.getSplitName(if @parentSuite then @parentSuite.getSuiteSplitName() else [])
jasmine.Suite.prototype.getSuiteSplitName = ->
this.getSplitName(if @parentSuite then @parentSuite.getSuiteSplitName() else [])
jasmine.Spec.prototype.getSpecSplitName = ->
this.getSplitName(@suite.getSuiteSplitName())
jasmine.Spec.prototype.getSpecSplitName = ->
this.getSplitName(@suite.getSuiteSplitName())
jasmine.Suite.prototype.getSplitName = getSplitName
jasmine.Spec.prototype.getSplitName = getSplitName
jasmine.Suite.prototype.getSplitName = getSplitName
jasmine.Spec.prototype.getSplitName = getSplitName
jasmine.Spec.prototype.getJHWSpecInformation = ->
parts = this.getSpecSplitName()
specLineInfo = HeadlessReporterResult.findSpecLine(parts)
if specLineInfo.file
parts.push("#{specLineInfo.file}:#{specLineInfo.lineNumber}")
else
parts.push('')
parts.join("||")
jasmine.Spec.prototype.getJHWSpecInformation = ->
parts = this.getSpecSplitName()
specLineInfo = HeadlessReporterResult.findSpecLine(parts)
if specLineInfo.file
parts.push("#{specLineInfo.file}:#{specLineInfo.lineNumber}")
else
parts.push('')
parts.join("||")
jasmine.Spec.prototype.fail = (e) ->
if e and e.sourceURL and window.CoffeeScriptToFilename
filename = e.sourceURL.split('/').pop()
if realFilename = window.CoffeeScriptToFilename[filename]
e = {
name: e.name,
message: e.message,
lineNumber: "~" + String(e.line),
sourceURL: realFilename
}
jasmine.Spec.prototype.fail = (e) ->
if e and e.sourceURL and window.CoffeeScriptToFilename
filename = e.sourceURL.split('/').pop()
if realFilename = window.CoffeeScriptToFilename[filename]
e = {
name: e.name,
message: e.message,
lineNumber: "~" + String(e.line),
sourceURL: realFilename
}
expectationResult = new jasmine.ExpectationResult({
passed: false,
message: if e then jasmine.util.formatException(e) else 'Exception',
trace: { stack: e.stack }
})
@results_.addResult(expectationResult)
expectationResult = new jasmine.ExpectationResult({
passed: false,
message: if e then jasmine.util.formatException(e) else 'Exception',
trace: { stack: e.stack }
})
@results_.addResult(expectationResult)
jasmine.NestedResults.isValidSpecLine = (line) ->
line.match(/^\s*expect/) != null || line.match(/^\s*return\s*expect/) != null
jasmine.NestedResults.isValidSpecLine = (line) ->
line.match(/^\s*expect/) != null || line.match(/^\s*return\s*expect/) != null
jasmine.NestedResults.parseFunction = (func) ->
lines = []
lineCount = 0
for line in func.split("\n")
if jasmine.NestedResults.isValidSpecLine(line)
line = line.replace(/^\s*/, '').replace(/\s*$/, '').replace(/^return\s*/, '')
lines.push([line, lineCount])
lineCount += 1
lines
jasmine.NestedResults.parseFunction = (func) ->
lines = []
lineCount = 0
for line in func.split("\n")
if jasmine.NestedResults.isValidSpecLine(line)
line = line.replace(/^\s*/, '').replace(/\s*$/, '').replace(/^return\s*/, '')
lines.push([line, lineCount])
lineCount += 1
lines
jasmine.NestedResults.parseAndStore = (func) ->
if !jasmine.NestedResults.ParsedFunctions[func]
jasmine.NestedResults.ParsedFunctions[func] = jasmine.NestedResults.parseFunction(func)
jasmine.NestedResults.ParsedFunctions[func]
jasmine.NestedResults.parseAndStore = (func) ->
if !jasmine.NestedResults.ParsedFunctions[func]
jasmine.NestedResults.ParsedFunctions[func] = jasmine.NestedResults.parseFunction(func)
jasmine.NestedResults.ParsedFunctions[func]
jasmine.NestedResults.ParsedFunctions = []
jasmine.NestedResults.ParsedFunctions = []
if !jasmine.WaitsBlock.prototype._execute
jasmine.WaitsBlock.prototype._execute = jasmine.WaitsBlock.prototype.execute
jasmine.WaitsForBlock.prototype._execute = jasmine.WaitsForBlock.prototype.execute
if !jasmine.WaitsBlock.prototype._execute
jasmine.WaitsBlock.prototype._execute = jasmine.WaitsBlock.prototype.execute
jasmine.WaitsForBlock.prototype._execute = jasmine.WaitsForBlock.prototype.execute
pauseAndRun = (onComplete) ->
JHW.timerPause()
this._execute ->
JHW.timerDone()
onComplete()
pauseAndRun = (onComplete) ->
JHW.timerPause()
this._execute ->
JHW.timerDone()
onComplete()
jasmine.WaitsBlock.prototype.execute = pauseAndRun
jasmine.WaitsForBlock.prototype.execute = pauseAndRun
jasmine.WaitsBlock.prototype.execute = pauseAndRun
jasmine.WaitsForBlock.prototype.execute = pauseAndRun
jasmine.NestedResults.prototype.addResult_ = jasmine.NestedResults.prototype.addResult
jasmine.NestedResults.prototype.addResult = (result) ->
result.expectations = []
# always three up?
jasmine.NestedResults.prototype.addResult_ = jasmine.NestedResults.prototype.addResult
jasmine.NestedResults.prototype.addResult = (result) ->
result.expectations = []
# always three up?
result.expectations = jasmine.NestedResults.parseAndStore(arguments.callee.caller.caller.caller.toString())
result.expectations = jasmine.NestedResults.parseAndStore(arguments.callee.caller.caller.caller.toString())
this.addResult_(result)
this.addResult_(result)
# Try to get the line number of a failed spec
class window.HeadlessReporterResult
constructor: (@name, @splitName) ->
@results = []
addResult: (message) ->
@results.push(message)
print: ->
output = @name
bestChoice = HeadlessReporterResult.findSpecLine(@splitName)
output += " (#{bestChoice.file}:#{bestChoice.lineNumber})" if bestChoice.file
class window.HeadlessReporterResult
constructor: (@name, @splitName) ->
@results = []
addResult: (message) ->
@results.push(message)
print: ->
output = @name
bestChoice = HeadlessReporterResult.findSpecLine(@splitName)
output += " (#{bestChoice.file}:#{bestChoice.lineNumber})" if bestChoice.file
JHW.printName(output)
for result in @results
output = result.message
if result.lineNumber
output += " (line ~#{bestChoice.lineNumber + result.lineNumber})\n #{result.line}"
JHW.printResult(output)
@findSpecLine: (splitName) ->
bestChoice = { accuracy: 0, file: null, lineNumber: null }
JHW.printName(output)
for result in @results
output = result.message
if result.lineNumber
output += " (line ~#{bestChoice.lineNumber + result.lineNumber})\n #{result.line}"
JHW.printResult(output)
@findSpecLine: (splitName) ->
bestChoice = { accuracy: 0, file: null, lineNumber: null }
for file, lines of HeadlessReporterResult.specLineNumbers
index = 0
lineNumber = 0
while newLineNumberInfo = lines[splitName[index]]
if newLineNumberInfo.length == 0
lineNumber = newLineNumberInfo[0]
else
lastLine = null
for line in newLineNumberInfo
lastLine = line
break if line > lineNumber
for file, lines of HeadlessReporterResult.specLineNumbers
index = 0
lineNumber = 0
while newLineNumberInfo = lines[splitName[index]]
if newLineNumberInfo.length == 0
lineNumber = newLineNumberInfo[0]
else
lastLine = null
for line in newLineNumberInfo
lastLine = line
break if line > lineNumber
lineNumber = lastLine
lineNumber = lastLine
index++
index++
if index > bestChoice.accuracy
bestChoice = { accuracy: index, file: file, lineNumber: lineNumber }
bestChoice
if index > bestChoice.accuracy
bestChoice = { accuracy: index, file: file, lineNumber: lineNumber }
bestChoice
# The reporter itself.
class jasmine.HeadlessReporter
constructor: (@callback = null) ->
@results = []
@failedCount = 0
@length = 0
reportRunnerResults: (runner) ->
return if this.hasError()
class jasmine.HeadlessReporter
constructor: (@callback = null) ->
@results = []
@failedCount = 0
@length = 0
reportRunnerResults: (runner) ->
return if this.hasError()
for result in @results
result.print()
for result in @results
result.print()
this.callback() if @callback
JHW.finishSuite((new Date() - @startTime) / 1000.0, @length, @failedCount)
this.callback() if @callback
JHW.finishSuite((new Date() - @startTime) / 1000.0, @length, @failedCount)
reportRunnerStarting: (runner) ->
@startTime = new Date()
reportRunnerStarting: (runner) ->
@startTime = new Date()
reportSpecResults: (spec) ->
return if this.hasError()
reportSpecResults: (spec) ->
return if this.hasError()
results = spec.results()
@length++
if results.passed()
JHW.specPassed(spec.getJHWSpecInformation())
else
JHW.specFailed(spec.getJHWSpecInformation())
@failedCount++
failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName())
testCount = 1
for result in results.getItems()
if result.type == 'expect' and !result.passed_
if foundLine = result.expectations[testCount - 1]
[ result.line, result.lineNumber ] = foundLine
failureResult.addResult(result)
testCount += 1
@results.push(failureResult)
results = spec.results()
@length++
if results.passed()
JHW.specPassed(spec.getJHWSpecInformation())
else
JHW.specFailed(spec.getJHWSpecInformation())
@failedCount++
failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName())
testCount = 1
for result in results.getItems()
if result.type == 'expect' and !result.passed_
if foundLine = result.expectations[testCount - 1]
[ result.line, result.lineNumber ] = foundLine
failureResult.addResult(result)
testCount += 1
@results.push(failureResult)
reportSpecStarting: (spec) ->
if this.hasError()
spec.finish()
spec.suite.finish()
reportSpecStarting: (spec) ->
if this.hasError()
spec.finish()
spec.suite.finish()
reportSuiteResults: (suite) ->
hasError: ->
JHW.hasError()
reportSuiteResults: (suite) ->
hasError: ->
JHW.hasError()

View File

@ -3,227 +3,229 @@
if (!(typeof jasmine !== "undefined" && jasmine !== null)) {
throw new Error("jasmine not laoded!");
}
getSplitName = function(parts) {
parts.push(String(this.description).replace(/[\n\r]/g, ' '));
return parts;
};
jasmine.Suite.prototype.getSuiteSplitName = function() {
return this.getSplitName(this.parentSuite ? this.parentSuite.getSuiteSplitName() : []);
};
jasmine.Spec.prototype.getSpecSplitName = function() {
return this.getSplitName(this.suite.getSuiteSplitName());
};
jasmine.Suite.prototype.getSplitName = getSplitName;
jasmine.Spec.prototype.getSplitName = getSplitName;
jasmine.Spec.prototype.getJHWSpecInformation = function() {
var parts, specLineInfo;
parts = this.getSpecSplitName();
specLineInfo = HeadlessReporterResult.findSpecLine(parts);
if (specLineInfo.file) {
parts.push("" + specLineInfo.file + ":" + specLineInfo.lineNumber);
} else {
parts.push('');
}
return parts.join("||");
};
jasmine.Spec.prototype.fail = function(e) {
var expectationResult, filename, realFilename;
if (e && e.sourceURL && window.CoffeeScriptToFilename) {
filename = e.sourceURL.split('/').pop();
if (realFilename = window.CoffeeScriptToFilename[filename]) {
e = {
name: e.name,
message: e.message,
lineNumber: "~" + String(e.line),
sourceURL: realFilename
};
}
}
expectationResult = new jasmine.ExpectationResult({
passed: false,
message: e ? jasmine.util.formatException(e) : 'Exception',
trace: {
stack: e.stack
}
});
return this.results_.addResult(expectationResult);
};
jasmine.NestedResults.isValidSpecLine = function(line) {
return line.match(/^\s*expect/) !== null || line.match(/^\s*return\s*expect/) !== null;
};
jasmine.NestedResults.parseFunction = function(func) {
var line, lineCount, lines, _i, _len, _ref;
lines = [];
lineCount = 0;
_ref = func.split("\n");
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
line = _ref[_i];
if (jasmine.NestedResults.isValidSpecLine(line)) {
line = line.replace(/^\s*/, '').replace(/\s*$/, '').replace(/^return\s*/, '');
lines.push([line, lineCount]);
}
lineCount += 1;
}
return lines;
};
jasmine.NestedResults.parseAndStore = function(func) {
if (!jasmine.NestedResults.ParsedFunctions[func]) {
jasmine.NestedResults.ParsedFunctions[func] = jasmine.NestedResults.parseFunction(func);
}
return jasmine.NestedResults.ParsedFunctions[func];
};
jasmine.NestedResults.ParsedFunctions = [];
if (!jasmine.WaitsBlock.prototype._execute) {
jasmine.WaitsBlock.prototype._execute = jasmine.WaitsBlock.prototype.execute;
jasmine.WaitsForBlock.prototype._execute = jasmine.WaitsForBlock.prototype.execute;
pauseAndRun = function(onComplete) {
JHW.timerPause();
return this._execute(function() {
JHW.timerDone();
return onComplete();
});
if (window.JHW) {
getSplitName = function(parts) {
parts.push(String(this.description).replace(/[\n\r]/g, ' '));
return parts;
};
jasmine.WaitsBlock.prototype.execute = pauseAndRun;
jasmine.WaitsForBlock.prototype.execute = pauseAndRun;
jasmine.NestedResults.prototype.addResult_ = jasmine.NestedResults.prototype.addResult;
jasmine.NestedResults.prototype.addResult = function(result) {
result.expectations = [];
result.expectations = jasmine.NestedResults.parseAndStore(arguments.callee.caller.caller.caller.toString());
return this.addResult_(result);
jasmine.Suite.prototype.getSuiteSplitName = function() {
return this.getSplitName(this.parentSuite ? this.parentSuite.getSuiteSplitName() : []);
};
}
window.HeadlessReporterResult = (function() {
function HeadlessReporterResult(name, splitName) {
this.name = name;
this.splitName = splitName;
this.results = [];
}
HeadlessReporterResult.prototype.addResult = function(message) {
return this.results.push(message);
jasmine.Spec.prototype.getSpecSplitName = function() {
return this.getSplitName(this.suite.getSuiteSplitName());
};
HeadlessReporterResult.prototype.print = function() {
var bestChoice, output, result, _i, _len, _ref, _results;
output = this.name;
bestChoice = HeadlessReporterResult.findSpecLine(this.splitName);
if (bestChoice.file) {
output += " (" + bestChoice.file + ":" + bestChoice.lineNumber + ")";
jasmine.Suite.prototype.getSplitName = getSplitName;
jasmine.Spec.prototype.getSplitName = getSplitName;
jasmine.Spec.prototype.getJHWSpecInformation = function() {
var parts, specLineInfo;
parts = this.getSpecSplitName();
specLineInfo = HeadlessReporterResult.findSpecLine(parts);
if (specLineInfo.file) {
parts.push("" + specLineInfo.file + ":" + specLineInfo.lineNumber);
} else {
parts.push('');
}
JHW.printName(output);
_ref = this.results;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
result = _ref[_i];
output = result.message;
if (result.lineNumber) {
output += " (line ~" + (bestChoice.lineNumber + result.lineNumber) + ")\n " + result.line;
}
_results.push(JHW.printResult(output));
}
return _results;
return parts.join("||");
};
HeadlessReporterResult.findSpecLine = function(splitName) {
var bestChoice, file, index, lastLine, line, lineNumber, lines, newLineNumberInfo, _i, _len, _ref;
bestChoice = {
accuracy: 0,
file: null,
lineNumber: null
};
_ref = HeadlessReporterResult.specLineNumbers;
for (file in _ref) {
lines = _ref[file];
index = 0;
lineNumber = 0;
while (newLineNumberInfo = lines[splitName[index]]) {
if (newLineNumberInfo.length === 0) {
lineNumber = newLineNumberInfo[0];
} else {
lastLine = null;
for (_i = 0, _len = newLineNumberInfo.length; _i < _len; _i++) {
line = newLineNumberInfo[_i];
lastLine = line;
if (line > lineNumber) {
break;
}
}
lineNumber = lastLine;
}
index++;
}
if (index > bestChoice.accuracy) {
bestChoice = {
accuracy: index,
file: file,
lineNumber: lineNumber
jasmine.Spec.prototype.fail = function(e) {
var expectationResult, filename, realFilename;
if (e && e.sourceURL && window.CoffeeScriptToFilename) {
filename = e.sourceURL.split('/').pop();
if (realFilename = window.CoffeeScriptToFilename[filename]) {
e = {
name: e.name,
message: e.message,
lineNumber: "~" + String(e.line),
sourceURL: realFilename
};
}
}
return bestChoice;
expectationResult = new jasmine.ExpectationResult({
passed: false,
message: e ? jasmine.util.formatException(e) : 'Exception',
trace: {
stack: e.stack
}
});
return this.results_.addResult(expectationResult);
};
return HeadlessReporterResult;
})();
jasmine.HeadlessReporter = (function() {
function HeadlessReporter(callback) {
this.callback = callback != null ? callback : null;
this.results = [];
this.failedCount = 0;
this.length = 0;
}
HeadlessReporter.prototype.reportRunnerResults = function(runner) {
var result, _i, _len, _ref;
if (this.hasError()) {
return;
}
_ref = this.results;
jasmine.NestedResults.isValidSpecLine = function(line) {
return line.match(/^\s*expect/) !== null || line.match(/^\s*return\s*expect/) !== null;
};
jasmine.NestedResults.parseFunction = function(func) {
var line, lineCount, lines, _i, _len, _ref;
lines = [];
lineCount = 0;
_ref = func.split("\n");
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
result = _ref[_i];
result.print();
line = _ref[_i];
if (jasmine.NestedResults.isValidSpecLine(line)) {
line = line.replace(/^\s*/, '').replace(/\s*$/, '').replace(/^return\s*/, '');
lines.push([line, lineCount]);
}
lineCount += 1;
}
if (this.callback) {
this.callback();
}
return JHW.finishSuite((new Date() - this.startTime) / 1000.0, this.length, this.failedCount);
return lines;
};
HeadlessReporter.prototype.reportRunnerStarting = function(runner) {
return this.startTime = new Date();
};
HeadlessReporter.prototype.reportSpecResults = function(spec) {
var failureResult, foundLine, result, results, testCount, _i, _len, _ref;
if (this.hasError()) {
return;
jasmine.NestedResults.parseAndStore = function(func) {
if (!jasmine.NestedResults.ParsedFunctions[func]) {
jasmine.NestedResults.ParsedFunctions[func] = jasmine.NestedResults.parseFunction(func);
}
results = spec.results();
this.length++;
if (results.passed()) {
return JHW.specPassed(spec.getJHWSpecInformation());
} else {
JHW.specFailed(spec.getJHWSpecInformation());
this.failedCount++;
failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName());
testCount = 1;
_ref = results.getItems();
return jasmine.NestedResults.ParsedFunctions[func];
};
jasmine.NestedResults.ParsedFunctions = [];
if (!jasmine.WaitsBlock.prototype._execute) {
jasmine.WaitsBlock.prototype._execute = jasmine.WaitsBlock.prototype.execute;
jasmine.WaitsForBlock.prototype._execute = jasmine.WaitsForBlock.prototype.execute;
pauseAndRun = function(onComplete) {
JHW.timerPause();
return this._execute(function() {
JHW.timerDone();
return onComplete();
});
};
jasmine.WaitsBlock.prototype.execute = pauseAndRun;
jasmine.WaitsForBlock.prototype.execute = pauseAndRun;
jasmine.NestedResults.prototype.addResult_ = jasmine.NestedResults.prototype.addResult;
jasmine.NestedResults.prototype.addResult = function(result) {
result.expectations = [];
result.expectations = jasmine.NestedResults.parseAndStore(arguments.callee.caller.caller.caller.toString());
return this.addResult_(result);
};
}
window.HeadlessReporterResult = (function() {
function HeadlessReporterResult(name, splitName) {
this.name = name;
this.splitName = splitName;
this.results = [];
}
HeadlessReporterResult.prototype.addResult = function(message) {
return this.results.push(message);
};
HeadlessReporterResult.prototype.print = function() {
var bestChoice, output, result, _i, _len, _ref, _results;
output = this.name;
bestChoice = HeadlessReporterResult.findSpecLine(this.splitName);
if (bestChoice.file) {
output += " (" + bestChoice.file + ":" + bestChoice.lineNumber + ")";
}
JHW.printName(output);
_ref = this.results;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
result = _ref[_i];
if (result.type === 'expect' && !result.passed_) {
if (foundLine = result.expectations[testCount - 1]) {
result.line = foundLine[0], result.lineNumber = foundLine[1];
}
failureResult.addResult(result);
output = result.message;
if (result.lineNumber) {
output += " (line ~" + (bestChoice.lineNumber + result.lineNumber) + ")\n " + result.line;
}
testCount += 1;
_results.push(JHW.printResult(output));
}
return this.results.push(failureResult);
return _results;
};
HeadlessReporterResult.findSpecLine = function(splitName) {
var bestChoice, file, index, lastLine, line, lineNumber, lines, newLineNumberInfo, _i, _len, _ref;
bestChoice = {
accuracy: 0,
file: null,
lineNumber: null
};
_ref = HeadlessReporterResult.specLineNumbers;
for (file in _ref) {
lines = _ref[file];
index = 0;
lineNumber = 0;
while (newLineNumberInfo = lines[splitName[index]]) {
if (newLineNumberInfo.length === 0) {
lineNumber = newLineNumberInfo[0];
} else {
lastLine = null;
for (_i = 0, _len = newLineNumberInfo.length; _i < _len; _i++) {
line = newLineNumberInfo[_i];
lastLine = line;
if (line > lineNumber) {
break;
}
}
lineNumber = lastLine;
}
index++;
}
if (index > bestChoice.accuracy) {
bestChoice = {
accuracy: index,
file: file,
lineNumber: lineNumber
};
}
}
return bestChoice;
};
return HeadlessReporterResult;
})();
jasmine.HeadlessReporter = (function() {
function HeadlessReporter(callback) {
this.callback = callback != null ? callback : null;
this.results = [];
this.failedCount = 0;
this.length = 0;
}
};
HeadlessReporter.prototype.reportSpecStarting = function(spec) {
if (this.hasError()) {
spec.finish();
return spec.suite.finish();
}
};
HeadlessReporter.prototype.reportSuiteResults = function(suite) {};
HeadlessReporter.prototype.hasError = function() {
return JHW.hasError();
};
return HeadlessReporter;
})();
HeadlessReporter.prototype.reportRunnerResults = function(runner) {
var result, _i, _len, _ref;
if (this.hasError()) {
return;
}
_ref = this.results;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
result = _ref[_i];
result.print();
}
if (this.callback) {
this.callback();
}
return JHW.finishSuite((new Date() - this.startTime) / 1000.0, this.length, this.failedCount);
};
HeadlessReporter.prototype.reportRunnerStarting = function(runner) {
return this.startTime = new Date();
};
HeadlessReporter.prototype.reportSpecResults = function(spec) {
var failureResult, foundLine, result, results, testCount, _i, _len, _ref;
if (this.hasError()) {
return;
}
results = spec.results();
this.length++;
if (results.passed()) {
return JHW.specPassed(spec.getJHWSpecInformation());
} else {
JHW.specFailed(spec.getJHWSpecInformation());
this.failedCount++;
failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName());
testCount = 1;
_ref = results.getItems();
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
result = _ref[_i];
if (result.type === 'expect' && !result.passed_) {
if (foundLine = result.expectations[testCount - 1]) {
result.line = foundLine[0], result.lineNumber = foundLine[1];
}
failureResult.addResult(result);
}
testCount += 1;
}
return this.results.push(failureResult);
}
};
HeadlessReporter.prototype.reportSpecStarting = function(spec) {
if (this.hasError()) {
spec.finish();
return spec.suite.finish();
}
};
HeadlessReporter.prototype.reportSuiteResults = function(suite) {};
HeadlessReporter.prototype.hasError = function() {
return JHW.hasError();
};
return HeadlessReporter;
})();
}
}).call(this);

View File

@ -1,22 +1,7 @@
module Jasmine
autoload :FilesList, 'jasmine/files_list'
autoload :TemplateWriter, 'jasmine/template_writer'
module Headless
autoload :CoffeeScriptCache, 'jasmine/headless/coffee_script_cache'
autoload :SpecFileAnalyzer, 'jasmine/headless/spec_file_analyzer'
autoload :CacheableAction, 'jasmine/headless/cacheable_action'
autoload :VERSION, 'jasmine/headless/version'
autoload :Runner, 'jasmine/headless/runner'
autoload :Options, 'jasmine/headless/options'
autoload :Task, 'jasmine/headless/task'
autoload :Report, 'jasmine/headless/report'
autoload :ReportMessage, 'jasmine/headless/report_message'
end
end
require 'jasmine/headless/errors'
require 'jasmine/headless'
require 'jasmine/headless/railtie' if defined?(Rails) && Rails::VERSION::MAJOR >= 3

View File

@ -9,9 +9,10 @@ module Jasmine
DEFAULT_FILES = [
File.join(Jasmine::Core.path, "jasmine.js"),
File.join(Jasmine::Core.path, "jasmine-html.js"),
File.expand_path('../../../jasmine/jasmine.headless-reporter.js', __FILE__),
File.expand_path('../../../js-lib/jsDump.js', __FILE__),
File.expand_path('../../../js-lib/beautify-html.js', __FILE__)
File.join(Jasmine::Core.path, "jasmine.css"),
Jasmine::Headless.root.join('jasmine/jasmine.headless-reporter.js').to_s,
Jasmine::Headless.root.join('js-lib/jsDump.js').to_s,
Jasmine::Headless.root.join('js-lib/beautify-html.js').to_s
]
PLEASE_WAIT_IM_WORKING_TIME = 2

22
lib/jasmine/headless.rb Normal file
View File

@ -0,0 +1,22 @@
module Jasmine::Headless
autoload :CoffeeScriptCache, 'jasmine/headless/coffee_script_cache'
autoload :SpecFileAnalyzer, 'jasmine/headless/spec_file_analyzer'
autoload :CacheableAction, 'jasmine/headless/cacheable_action'
autoload :VERSION, 'jasmine/headless/version'
autoload :Runner, 'jasmine/headless/runner'
autoload :Options, 'jasmine/headless/options'
autoload :Task, 'jasmine/headless/task'
autoload :TemplateWriter, 'jasmine/headless/template_writer'
autoload :Report, 'jasmine/headless/report'
autoload :ReportMessage, 'jasmine/headless/report_message'
class << self
def root
@root ||= Pathname.new(File.expand_path('../../..', __FILE__))
end
end
end
require 'jasmine/headless/errors'

View File

@ -56,7 +56,7 @@ module Jasmine::Headless
end
def cache_file
@cache_file ||= File.join(self.class.cache_dir, self.class.cache_type, Digest::SHA1.hexdigest(file))
@cache_file ||= File.join(self.class.cache_dir, self.class.cache_type, Digest::SHA1.hexdigest(file)) + '.js'
end
def fresh?

View File

@ -11,6 +11,7 @@ module Jasmine
DEFAULT_OPTIONS = {
:colors => false,
:remove_html_file => true,
:runner_output_filename => false,
:jasmine_config => 'spec/javascripts/support/jasmine.yml',
:report => false,
:do_list => false,
@ -51,6 +52,8 @@ module Jasmine
@options[:remove_html_file] = false
when '--report'
@options[:report] = arg
when '--runner-out'
@options[:runner_output_filename] = arg
when '--jasmine-config', '-j'
@options[:jasmine_config] = arg
when '--no-full-run'
@ -75,6 +78,7 @@ module Jasmine
[ '--cache', GetoptLong::NO_ARGUMENT ],
[ '--no-t stcache', GetoptLong::NO_ARGUMENT ],
[ '--keep', GetoptLong::NO_ARGUMENT ],
[ '--runner-out', GetoptLong::REQUIRED_ARGUMENT ],
[ '--report', GetoptLong::REQUIRED_ARGUMENT ],
[ '--jasmine-config', '-j', GetoptLong::REQUIRED_ARGUMENT ],
[ '--no-full-run', GetoptLong::NO_ARGUMENT ],

View File

@ -40,6 +40,10 @@ module Jasmine
@options = options
end
def template_writer
@template_writer ||= TemplateWriter.new(self)
end
def jasmine_config
raise JasmineConfigNotFound.new("Jasmine config not found. I tried #{@options[:jasmine_config]}.") if !File.file?(@options[:jasmine_config])
@ -63,19 +67,23 @@ module Jasmine
:only => @options[:files]
)
targets = Jasmine::TemplateWriter.write!(files_list)
targets = template_writer.write!(files_list)
run_targets = targets.dup
run_targets.pop if (!@options[:full_run] && files_list.filtered?) || files_list.has_spec_outside_scope?
system jasmine_command(run_targets)
status = $?.exitstatus
if @options[:remove_html_file] || (status == 0)
if !(runner_filename || (@options[:remove_html_file] && status != 0))
targets.each { |target| FileUtils.rm_f target }
end
status
end
def runner_filename
options[:runner_output_filename]
end
end
end
end

View File

@ -0,0 +1,41 @@
require 'multi_json'
require 'erb'
require 'tempfile'
module Jasmine::Headless
class TemplateWriter
attr_reader :runner
def initialize(runner)
@runner = runner
end
def write!(files_list)
output = [
[ all_tests_filename, files_list.files_to_html ]
]
output.unshift([filtered_tests_filename , files_list.filtered_files_to_html ]) if files_list.filtered?
output.each do |name, files|
File.open(name, 'w') { |fh| fh.print template_for(files, files_list.spec_file_line_numbers) }
end
output.collect(&:first)
end
def all_tests_filename
runner.runner_filename || "jhw.#{$$}.html"
end
def filtered_tests_filename
all_tests_filename.gsub(%r{\.html$}, '.filter.html')
end
private
def template_for(files, spec_lines)
ERB.new(Jasmine::Headless.root.join('skel/template.html.erb').read).result(binding)
end
end
end

View File

@ -1,86 +0,0 @@
require 'jasmine/files_list'
require 'multi_json'
module Jasmine
class TemplateWriter
class << self
def write!(files_list)
output = [
[ "specrunner.#{$$}.html", files_list.files_to_html ]
]
output.unshift([ "specrunner.#{$$}.filter.html", files_list.filtered_files_to_html ]) if files_list.filtered?
output.each do |name, files|
File.open(name, 'w') { |fh| fh.print template_for(files, files_list.spec_file_line_numbers) }
end
output.collect(&:first)
end
private
def template_for(files, spec_lines)
<<-HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type"/>
<title>Jasmine Test Runner</title>
<script type="text/javascript">
window.console = { log: function(data) {
if (typeof(jQuery) !== 'undefined' && data instanceof jQuery) {
JHW.log(style_html($("<div />").append(data).html(), { indent_size: 2 }));
} else {
var usejsDump = true;
try {
if (typeof data.toJSON == 'function') {
JHW.log("JSON: " + JSON.stringify(data, null, 2));
usejsDump = false;
}
} catch (e) {}
if (usejsDump) {
var dump = jsDump.doParse(data);
if (dump.indexOf("\\n") == -1) {
JHW.log(dump);
} else {
JHW.log("jsDump: " + dump);
}
}
}
}, pp: function(data) {
JHW.log(jasmine ? jasmine.pp(data) : JSON.stringify(data));
} };
window.onbeforeunload = function(e) {
JHW.leavePageAttempt('The code tried to leave the test page. Check for unhandled form submits and link clicks.');
if (e = e || window.event) {
e.returnValue = "leaving";
}
return "leaving";
};
</script>
#{files.join("\n")}
<script type="text/javascript">
HeadlessReporterResult.specLineNumbers = #{MultiJson.encode(spec_lines)};
</script>
</head>
<body>
<script type="text/javascript">
jasmine.getEnv().addReporter(new jasmine.HeadlessReporter(function() {
window.onbeforeunload = null;
}));
jasmine.getEnv().execute();
</script>
</body>
</html>
HTML
end
end
end
end

68
skel/template.html.erb Normal file
View File

@ -0,0 +1,68 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type"/>
<title>Jasmine Test Runner - Generated by jasmine-headless-webkit</title>
<script type="text/javascript">
if (window.JHW) {
window.console = { log: function(data) {
if (typeof(jQuery) !== 'undefined' && data instanceof jQuery) {
JHW.log(style_html($("<div />").append(data).html(), { indent_size: 2 }));
} else {
var usejsDump = true;
try {
if (typeof data.toJSON == 'function') {
JHW.log("JSON: " + JSON.stringify(data, null, 2));
usejsDump = false;
}
} catch (e) {}
if (usejsDump) {
var dump = jsDump.doParse(data);
if (dump.indexOf("\\n") == -1) {
JHW.log(dump);
} else {
JHW.log("jsDump: " + dump);
}
}
}
}, pp: function(data) {
JHW.log(jasmine ? jasmine.pp(data) : JSON.stringify(data));
} };
window.onbeforeunload = function(e) {
JHW.leavePageAttempt('The code tried to leave the test page. Check for unhandled form submits and link clicks.');
if (e = e || window.event) {
e.returnValue = "leaving";
}
return "leaving";
};
}
</script>
<%= files.join("\n") %>
<script type="text/javascript">
if (window.JHW) { HeadlessReporterResult.specLineNumbers = <%= MultiJson.encode(spec_lines) %>; }
</script>
</head>
<body>
<script type="text/javascript">
window._onload = window.onload
window.onload = function() {
if (window._onload) { window._onload() }
if (window.JHW) {
jasmine.getEnv().addReporter(new jasmine.HeadlessReporter(function() {
window.onbeforeunload = null;
}));
} else {
jasmine.getEnv().addReporter(new jasmine.HtmlReporter());
}
jasmine.getEnv().execute();
}
</script>
</body>
</html>

View File

@ -126,5 +126,16 @@ describe "jasmine-headless-webkit" do
files.lines.to_a.should include("./spec/jasmine/success/success_spec.js\n")
end
end
describe 'runner-out' do
it 'should write out the runner HTML to the specified path and not run the test' do
runner_path = Tempfile.new('jhw')
runner_path.close
system %{bin/jasmine-headless-webkit -j spec/jasmine/success/success.yml --runner-out #{runner_path.path}}
File.size(runner_path.path).should_not == 0
end
end
end

View File

@ -13,6 +13,7 @@ describe Jasmine::FilesList do
files_list.files.should == [
File.join(Jasmine::Core.path, "jasmine.js"),
File.join(Jasmine::Core.path, "jasmine-html.js"),
File.join(Jasmine::Core.path, "jasmine.css"),
File.expand_path('jasmine/jasmine.headless-reporter.js'),
File.expand_path('js-lib/jsDump.js'),
File.expand_path('js-lib/beautify-html.js'),

View File

@ -19,7 +19,7 @@ describe Jasmine::Headless::CacheableAction do
let(:cache_type) { 'action' }
let(:cache_dir) { 'cache' }
let(:cache_file) { File.join(cache_dir, cache_type, Digest::SHA1.hexdigest(file)) }
let(:cache_file) { File.join(cache_dir, cache_type, Digest::SHA1.hexdigest(file)) + '.js' }
let(:cache_file_data) { YAML.load(File.read(cache_file)) }
let(:cache_object) { described_class.new(file) }

View File

@ -13,6 +13,11 @@ describe Jasmine::Headless::Runner do
runner.options[:test].should == 'test'
runner.options[:jasmine_config].should == 'spec/javascripts/support/jasmine.yml'
end
it 'should have a template writer' do
runner.template_writer.should be_a_kind_of(Jasmine::Headless::TemplateWriter)
runner.template_writer.runner.should == runner
end
end
describe '#load_config' do
@ -96,4 +101,23 @@ describe Jasmine::Headless::Runner do
report.should contain_a_failing_spec(['failure', 'should fail with error code of 1'])
end
end
describe '#runner_filename' do
context 'not provided' do
let(:opts) { { :runner_output_filename => false } }
it 'should reverse the remove_html_file option' do
runner.runner_filename.should == false
end
end
context 'provided' do
let(:filename) { 'filename.html' }
let(:opts) { { :runner_output_filename => filename } }
it 'should reverse the remove_html_file option' do
runner.runner_filename.should == filename
end
end
end
end

View File

@ -0,0 +1,84 @@
require 'spec_helper'
require 'fakefs/spec_helpers'
describe Jasmine::Headless::TemplateWriter do
let(:runner) { stub }
let(:template_writer) { described_class.new(runner) }
describe '#all_tests_filename' do
let(:all_tests_filename) { template_writer.all_tests_filename }
context 'runner does not care about filename' do
before do
runner.stubs(:runner_filename).returns(false)
end
it 'should use a specrunner.html file' do
all_tests_filename.should_not include('tmp')
all_tests_filename.should include('jhw')
all_tests_filename.should include('.html')
end
end
context 'runner cares about filename' do
let(:filename) { 'filename.html' }
before do
runner.stubs(:runner_filename).returns(filename)
end
it 'should use a specrunner.html file' do
all_tests_filename.should == filename
end
end
end
describe '#filtered_tests_filename' do
before do
template_writer.stubs(:all_tests_filename).returns("test.html")
end
it 'should filter the filename for all tests' do
template_writer.filtered_tests_filename.should == 'test.filter.html'
end
end
describe '#write!' do
include FakeFS::SpecHelpers
before do
File.stubs(:read).returns(nil)
runner.stubs(:keep_runner).returns(true)
runner.stubs(:runner_filename).returns(false)
end
let(:files_list) { Jasmine::FilesList.new }
before do
files_list.files << 'file.js'
files_list.filtered_files << 'file.js'
end
context 'no filter' do
it 'should write one file' do
template_writer.write!(files_list).should == [
"jhw.#{$$}.html"
]
end
end
context 'filtered files' do
before do
files_list.files << 'file2.js'
end
it 'should write two files' do
template_writer.write!(files_list).should == [
"jhw.#{$$}.filter.html", "jhw.#{$$}.html"
]
end
end
end
end

View File

@ -1,41 +0,0 @@
require 'spec_helper'
require 'jasmine/template_writer'
require 'fakefs/spec_helpers'
describe Jasmine::TemplateWriter do
describe '.write!' do
include FakeFS::SpecHelpers
before do
File.stubs(:read).returns(nil)
end
let(:files_list) { Jasmine::FilesList.new }
before do
files_list.files << 'file.js'
files_list.filtered_files << 'file.js'
end
context 'no filter' do
it 'should write one file' do
Jasmine::TemplateWriter.write!(files_list).should == [
"specrunner.#{$$}.html"
]
end
end
context 'filtered files' do
before do
files_list.files << 'file2.js'
end
it 'should write two files' do
Jasmine::TemplateWriter.write!(files_list).should == [
"specrunner.#{$$}.filter.html", "specrunner.#{$$}.html"
]
end
end
end
end