first big switch to javascript doing all the work

This commit is contained in:
John Bintz 2011-10-24 16:40:08 -04:00
parent 894b979674
commit dda84fdcb9
14 changed files with 544 additions and 447 deletions

View File

@ -18,7 +18,6 @@ begin
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 } files_list.files.each { |file| puts file }
else else
puts "Running Jasmine specs...".color(:white)
exit runner.run exit runner.run
end end
rescue CoffeeScript::CompilationError rescue CoffeeScript::CompilationError

View File

@ -35,6 +35,7 @@ void Runner::go()
m_ticker.stop(); m_ticker.stop();
m_page.setPreferredContentsSize(QSize(1024, 600)); m_page.setPreferredContentsSize(QSize(1024, 600));
addJHW(); addJHW();
loadSpec(); loadSpec();
m_ticker.start(); m_ticker.start();
@ -46,6 +47,13 @@ void Runner::addJHW()
void Runner::loadSpec() void Runner::loadSpec()
{ {
if (!reportFileName.isEmpty()) {
outputFile = new QFile(reportFileName);
outputFile->open(QIODevice::WriteOnly);
ts = new QTextStream(outputFile);
}
m_page.mainFrame()->load(runnerFiles.dequeue()); m_page.mainFrame()->load(runnerFiles.dequeue());
m_ticker.start(); m_ticker.start();
} }
@ -59,11 +67,9 @@ void Runner::watch(bool ok)
QApplication::instance()->exit(1); QApplication::instance()->exit(1);
return; return;
} }
} }
bool Runner::hasElement(const char *select) bool Runner::hasElement(const char *select) {
{
return !m_page.mainFrame()->findFirstElement(select).isNull(); return !m_page.mainFrame()->findFirstElement(select).isNull();
} }
@ -75,10 +81,6 @@ void Runner::reportFile(const QString &file) {
reportFileName = file; reportFileName = file;
} }
bool Runner::hasError() {
return hasErrors;
}
void Runner::timerPause() { void Runner::timerPause() {
m_ticker.stop(); m_ticker.stop();
} }
@ -87,17 +89,21 @@ void Runner::timerDone() {
m_ticker.start(); m_ticker.start();
} }
void Runner::specPassed(const QString &specDetail) { void Runner::print(const QString &fh, const QString &content) {
consoleOutput.passed(specDetail); if (fh == "stdout") {
reportFileOutput.passed(specDetail); std::cout << qPrintable(content);
} std::cout.flush();
}
void Runner::specFailed(const QString &specDetail) { if (fh == "stderr") {
consoleOutput.failed(specDetail); std::cerr << qPrintable(content);
reportFileOutput.failed(specDetail); std::cerr.flush();
}
didFail = true; if (fh == "report") {
failedSpecs.push(specDetail); *ts << qPrintable(content);
ts->flush();
}
} }
void Runner::errorLog(const QString &msg, int lineNumber, const QString &sourceID) void Runner::errorLog(const QString &msg, int lineNumber, const QString &sourceID)
@ -115,11 +121,9 @@ void Runner::internalLog(const QString &note, const QString &msg) {
reportFileOutput.internalLog(note, msg); reportFileOutput.internalLog(note, msg);
} }
void Runner::log(const QString &msg) void Runner::usedConsole()
{ {
usedConsole = true; usedConsole = true;
consoleOutput.consoleLog(msg);
reportFileOutput.consoleLog(msg);
} }
void Runner::leavePageAttempt(const QString &msg) void Runner::leavePageAttempt(const QString &msg)
@ -129,53 +133,19 @@ void Runner::leavePageAttempt(const QString &msg)
hasErrors = true; hasErrors = true;
} }
void Runner::printName(const QString &name) void Runner::finishSuite() {
{
consoleOutput.logSpecFilename(name);
}
void Runner::printResult(const QString &result)
{
consoleOutput.logSpecResult(result);
}
void Runner::finishSuite(const QString &duration, const QString &total, const QString& failed)
{
if (didFail) {
consoleOutput.reportFailure(total, failed, duration);
reportFileOutput.reportFailure(total, failed, duration);
} else {
if (hasErrors) {
consoleOutput.reportSuccessWithJSErrors(total, failed, duration);
reportFileOutput.reportSuccessWithJSErrors(total, failed, duration);
} else {
consoleOutput.reportSuccess(total, failed, duration);
reportFileOutput.reportSuccess(total, failed, duration);
}
}
if (!reportFileName.isEmpty()) {
QFile outputFile(reportFileName);
outputFile.open(QIODevice::WriteOnly);
QTextStream ts(&outputFile);
ts << reportFileOutput.outputIO->str().c_str();
outputFile.close();
}
isFinished = true; isFinished = true;
} }
void Runner::timerEvent() void Runner::timerEvent() {
{
++m_runs; ++m_runs;
if (hasErrors && m_runs > 2) if (hasErrors && m_runs > 2)
QApplication::instance()->exit(1); QApplication::instance()->exit(1);
if (isFinished) { if (isFinished) {
outputFile->close();
int exitCode = 0; int exitCode = 0;
if (didFail || hasErrors) { if (didFail || hasErrors) {
exitCode = 1; exitCode = 1;

View File

@ -31,11 +31,10 @@ class Runner: public QObject {
void leavePageAttempt(const QString &msg); void leavePageAttempt(const QString &msg);
void timerPause(); void timerPause();
void timerDone(); void timerDone();
void specPassed(const QString &specDetail);
void specFailed(const QString &specDetail); void print(const QString &fh, const QString &content);
void printName(const QString &name);
void printResult(const QString &result); void finishSuite();
void finishSuite(const QString &duration, const QString &total, const QString& failed);
private slots: private slots:
void watch(bool ok); void watch(bool ok);
void errorLog(const QString &msg, int lineNumber, const QString &sourceID); void errorLog(const QString &msg, int lineNumber, const QString &sourceID);
@ -55,12 +54,14 @@ class Runner: public QObject {
QQueue<QString> runnerFiles; QQueue<QString> runnerFiles;
QStack<QString> failedSpecs; QStack<QString> failedSpecs;
ConsoleOutput consoleOutput;
ReportFileOutput reportFileOutput; ReportFileOutput reportFileOutput;
QString reportFileName; QString reportFileName;
void loadSpec(); void loadSpec();
QFile *outputFile;
QTextStream *ts;
}; };
#endif #endif

View File

@ -0,0 +1,41 @@
# 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.foreground('red')
bestChoice = HeadlessReporterResult.findSpecLine(@splitName)
output += " (#{bestChoice.file}:#{bestChoice.lineNumber})".foreground('blue') if bestChoice.file
JHW.stdout.puts "\n\n#{output}"
for result in @results
output = result.message.foreground('red')
if result.lineNumber
output += " (line ~#{bestChoice.lineNumber + result.lineNumber})".foreground('red').bright()
JHW.stdout.puts(" " + output)
JHW.stdout.puts(" #{result.line}".foreground('yellow'))
@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
lineNumber = lastLine
index++
if index > bestChoice.accuracy
bestChoice = { accuracy: index, file: file, lineNumber: lineNumber }
bestChoice

View File

@ -0,0 +1,72 @@
(function() {
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.foreground('red');
bestChoice = HeadlessReporterResult.findSpecLine(this.splitName);
if (bestChoice.file) {
output += (" (" + bestChoice.file + ":" + bestChoice.lineNumber + ")").foreground('blue');
}
JHW.stdout.puts("\n\n" + output);
_ref = this.results;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
result = _ref[_i];
output = result.message.foreground('red');
if (result.lineNumber) {
output += (" (line ~" + (bestChoice.lineNumber + result.lineNumber) + ")").foreground('red').bright();
}
JHW.stdout.puts(" " + output);
_results.push(JHW.stdout.puts((" " + result.line).foreground('yellow')));
}
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;
})();
}).call(this);

20
jasmine/intense.coffee Normal file
View File

@ -0,0 +1,20 @@
window.Intense = {
colors:
black: 0
red: 1
green: 2
yellow: 3
blue: 4
magenta: 5
cyan: 6
white: 7
methods:
foreground: (color) ->
"\033[3#{Intense.colors[color]}m#{this}\033[0m"
bright: ->
"\033[1m#{this}\033[0m"
}
for method, code of Intense.methods
String.prototype[method] = code

28
jasmine/intense.js Normal file
View File

@ -0,0 +1,28 @@
(function() {
var code, method, _ref;
window.Intense = {
colors: {
black: 0,
red: 1,
green: 2,
yellow: 3,
blue: 4,
magenta: 5,
cyan: 6,
white: 7
},
methods: {
foreground: function(color) {
return "\033[3" + Intense.colors[color] + "m" + this + "\033[0m";
},
bright: function() {
return "\033[1m" + this + "\033[0m";
}
}
};
_ref = Intense.methods;
for (method in _ref) {
code = _ref[method];
String.prototype[method] = code;
}
}).call(this);

View File

@ -0,0 +1,86 @@
if !jasmine?
throw new Error("jasmine not laoded!")
if window.JHW
# Jasmine extensions
getSplitName = (parts) ->
parts.push(String(@description).replace(/[\n\r]/g, ' '))
parts
jasmine.Suite.prototype.getSuiteSplitName = ->
this.getSplitName(if @parentSuite then @parentSuite.getSuiteSplitName() else [])
jasmine.Spec.prototype.getSpecSplitName = ->
this.getSplitName(@suite.getSuiteSplitName())
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.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)
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.parseAndStore = (func) ->
if !jasmine.NestedResults.ParsedFunctions[func]
jasmine.NestedResults.ParsedFunctions[func] = jasmine.NestedResults.parseFunction(func)
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 = (onComplete) ->
JHW.timerPause()
this._execute ->
JHW.timerDone()
onComplete()
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?
result.expectations = jasmine.NestedResults.parseAndStore(arguments.callee.caller.caller.caller.toString())
this.addResult_(result)

View File

@ -0,0 +1,97 @@
(function() {
var getSplitName, pauseAndRun;
if (!(typeof jasmine !== "undefined" && jasmine !== null)) {
throw new Error("jasmine not laoded!");
}
if (window.JHW) {
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();
});
};
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);
};
}
}
}).call(this);

View File

@ -1,175 +1,78 @@
if !jasmine? if !jasmine?
throw new Error("jasmine not laoded!") throw new Error("jasmine not laoded!")
if window.JHW
# Jasmine extensions
getSplitName = (parts) ->
parts.push(String(@description).replace(/[\n\r]/g, ' '))
parts
jasmine.Suite.prototype.getSuiteSplitName = ->
this.getSplitName(if @parentSuite then @parentSuite.getSuiteSplitName() else [])
jasmine.Spec.prototype.getSpecSplitName = ->
this.getSplitName(@suite.getSuiteSplitName())
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.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)
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.parseAndStore = (func) ->
if !jasmine.NestedResults.ParsedFunctions[func]
jasmine.NestedResults.ParsedFunctions[func] = jasmine.NestedResults.parseFunction(func)
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 = (onComplete) ->
JHW.timerPause()
this._execute ->
JHW.timerDone()
onComplete()
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?
result.expectations = jasmine.NestedResults.parseAndStore(arguments.callee.caller.caller.caller.toString())
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
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
lineNumber = lastLine
index++
if index > bestChoice.accuracy
bestChoice = { accuracy: index, file: file, lineNumber: lineNumber }
bestChoice
# The reporter itself. # The reporter itself.
class jasmine.HeadlessReporter class jasmine.HeadlessReporter
constructor: (@callback = null) -> constructor: (@callback = null) ->
@results = [] @results = []
@failedCount = 0 @failedCount = 0
@length = 0 @length = 0
reportRunnerResults: (runner) -> @_hasError = false
return if this.hasError() reportRunnerResults: (runner) ->
return if this.hasError()
for result in @results this.callback() if @callback
result.print()
this.callback() if @callback runtime = (new Date() - @startTime) / 1000.0
JHW.finishSuite((new Date() - @startTime) / 1000.0, @length, @failedCount)
reportRunnerStarting: (runner) -> JHW.stdout.print("\n")
@startTime = new Date()
reportSpecResults: (spec) -> resultLine = this._formatResultLine(runtime)
return if this.hasError()
results = spec.results() if @failedCount == 0
@length++ JHW.stdout.puts("PASS: #{resultLine}".foreground('green'))
if results.passed() else
JHW.specPassed(spec.getJHWSpecInformation()) JHW.stdout.puts("FAIL: #{resultLine}".foreground('red'))
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) -> result.print() for result in @results
if this.hasError()
spec.finish()
spec.suite.finish()
reportSuiteResults: (suite) -> JHW.finishSuite()
hasError: ->
JHW.hasError() reportRunnerStarting: (runner) ->
@startTime = new Date()
JHW.stdout.puts("Running Jasmine specs...")
reportSpecResults: (spec) ->
return if this.hasError()
results = spec.results()
@length++
if results.passed()
JHW.stdout.print('.'.foreground('green'))
JHW.report.puts("PASS||" + spec.getJHWSpecInformation())
else
JHW.stdout.print('F'.foreground('red'))
JHW.report.puts("FAIL||" + 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()
reportSuiteResults: (suite) ->
hasError: ->
@_hasError == true
_formatResultLine: (runtime) ->
line = []
line.push(@length)
line.push((if @length == 1 then "test" else "tests") + ',')
line.push(@failedCount)
line.push((if @failedCount == 1 then "failure" else "failures") + ',')
line.push(runtime)
line.push((if runtime == 1.0 then "sec" else "secs") + '.')
line.join(' ')

View File

@ -1,231 +1,93 @@
(function() { (function() {
var getSplitName, pauseAndRun;
if (!(typeof jasmine !== "undefined" && jasmine !== null)) { if (!(typeof jasmine !== "undefined" && jasmine !== null)) {
throw new Error("jasmine not laoded!"); throw new Error("jasmine not laoded!");
} }
if (window.JHW) { jasmine.HeadlessReporter = (function() {
getSplitName = function(parts) { function HeadlessReporter(callback) {
parts.push(String(this.description).replace(/[\n\r]/g, ' ')); this.callback = callback != null ? callback : null;
return parts; this.results = [];
}; this.failedCount = 0;
jasmine.Suite.prototype.getSuiteSplitName = function() { this.length = 0;
return this.getSplitName(this.parentSuite ? this.parentSuite.getSuiteSplitName() : []); this._hasError = false;
};
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();
});
};
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() { HeadlessReporter.prototype.reportRunnerResults = function(runner) {
function HeadlessReporterResult(name, splitName) { var result, resultLine, runtime, _i, _len, _ref;
this.name = name; if (this.hasError()) {
this.splitName = splitName; return;
this.results = [];
} }
HeadlessReporterResult.prototype.addResult = function(message) { if (this.callback) {
return this.results.push(message); this.callback();
}; }
HeadlessReporterResult.prototype.print = function() { runtime = (new Date() - this.startTime) / 1000.0;
var bestChoice, output, result, _i, _len, _ref, _results; JHW.stdout.print("\n");
output = this.name; resultLine = this._formatResultLine(runtime);
bestChoice = HeadlessReporterResult.findSpecLine(this.splitName); if (this.failedCount === 0) {
if (bestChoice.file) { JHW.stdout.puts(("PASS: " + resultLine).foreground('green'));
output += " (" + bestChoice.file + ":" + bestChoice.lineNumber + ")"; } else {
} JHW.stdout.puts(("FAIL: " + resultLine).foreground('red'));
JHW.printName(output); }
_ref = this.results; _ref = this.results;
_results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) {
result = _ref[_i];
result.print();
}
return JHW.finishSuite();
};
HeadlessReporter.prototype.reportRunnerStarting = function(runner) {
this.startTime = new Date();
return JHW.stdout.puts("Running Jasmine specs...");
};
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()) {
JHW.stdout.print('.'.foreground('green'));
return JHW.report.puts("PASS||" + spec.getJHWSpecInformation());
} else {
JHW.stdout.print('F'.foreground('red'));
JHW.report.puts("FAIL||" + 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++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
result = _ref[_i]; result = _ref[_i];
output = result.message; if (result.type === 'expect' && !result.passed_) {
if (result.lineNumber) { if (foundLine = result.expectations[testCount - 1]) {
output += " (line ~" + (bestChoice.lineNumber + result.lineNumber) + ")\n " + result.line; result.line = foundLine[0], result.lineNumber = foundLine[1];
}
_results.push(JHW.printResult(output));
}
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++; failureResult.addResult(result);
}
if (index > bestChoice.accuracy) {
bestChoice = {
accuracy: index,
file: file,
lineNumber: lineNumber
};
} }
testCount += 1;
} }
return bestChoice; return this.results.push(failureResult);
};
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; HeadlessReporter.prototype.reportSpecStarting = function(spec) {
if (this.hasError()) { if (this.hasError()) {
return; spec.finish();
} return spec.suite.finish();
_ref = this.results; }
for (_i = 0, _len = _ref.length; _i < _len; _i++) { };
result = _ref[_i]; HeadlessReporter.prototype.reportSuiteResults = function(suite) {};
result.print(); HeadlessReporter.prototype.hasError = function() {
} return this._hasError === true;
if (this.callback) { };
this.callback(); HeadlessReporter.prototype._formatResultLine = function(runtime) {
} var line;
return JHW.finishSuite((new Date() - this.startTime) / 1000.0, this.length, this.failedCount); line = [];
}; line.push(this.length);
HeadlessReporter.prototype.reportRunnerStarting = function(runner) { line.push((this.length === 1 ? "test" : "tests") + ',');
return this.startTime = new Date(); line.push(this.failedCount);
}; line.push((this.failedCount === 1 ? "failure" : "failures") + ',');
HeadlessReporter.prototype.reportSpecResults = function(spec) { line.push(runtime);
var failureResult, foundLine, result, results, testCount, _i, _len, _ref; line.push((runtime === 1.0 ? "sec" : "secs") + '.');
if (this.hasError()) { return line.join(' ');
return; };
} return HeadlessReporter;
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); }).call(this);

View File

@ -10,6 +10,9 @@ module Jasmine
File.join(Jasmine::Core.path, "jasmine.js"), File.join(Jasmine::Core.path, "jasmine.js"),
File.join(Jasmine::Core.path, "jasmine-html.js"), File.join(Jasmine::Core.path, "jasmine-html.js"),
File.join(Jasmine::Core.path, "jasmine.css"), File.join(Jasmine::Core.path, "jasmine.css"),
Jasmine::Headless.root.join('jasmine/jasmine-extensions.js').to_s,
Jasmine::Headless.root.join('jasmine/intense.js').to_s,
Jasmine::Headless.root.join('jasmine/headless_reporter_result.js').to_s,
Jasmine::Headless.root.join('jasmine/jasmine.headless-reporter.js').to_s, 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/jsDump.js').to_s,
Jasmine::Headless.root.join('js-lib/beautify-html.js').to_s Jasmine::Headless.root.join('js-lib/beautify-html.js').to_s

View File

@ -3,7 +3,7 @@
<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 Test Runner - Generated by jasmine-headless-webkit</title> <title>Jasmine Test Runner - Generated by jasmine-headless-webkit</title>
<script type="text/javascript"> <script type="text/javascript"><%= File.read('
if (window.JHW) { if (window.JHW) {
window.console = { log: function(data) { window.console = { log: function(data) {
if (typeof(jQuery) !== 'undefined' && data instanceof jQuery) { if (typeof(jQuery) !== 'undefined' && data instanceof jQuery) {
@ -42,6 +42,21 @@
return "leaving"; return "leaving";
}; };
JHW.stdout = {
print: function(content) { JHW.print('stdout', content); },
puts: function(content) { JHW.print('stdout', content + "\n"); }
};
JHW.report = {
print: function(content) { JHW.print('report', content); },
puts: function(content) { JHW.print('report', content + "\n"); }
};
JHW.log = function(msg) {
JHW.usedConsole();
JHW.stdout.puts(msg);
}
} }
</script> </script>
<%= files.join("\n") %> <%= files.join("\n") %>

View File

@ -30,7 +30,7 @@ describe 'jasmine.HeadlessReporter', ->
reporter.reportSpecStarting(spec) reporter.reportSpecStarting(spec)
expect(spec.finish).toHaveBeenCalled() expect(spec.finish).not.toHaveBeenCalled()
expect(suite.finish).toHaveBeenCalled() expect(suite.finish).toHaveBeenCalled()
describe 'jasmine.Suite.prototype.getSuiteSplitName', -> describe 'jasmine.Suite.prototype.getSuiteSplitName', ->