diff --git a/bin/jasmine-headless-webkit b/bin/jasmine-headless-webkit index 711de51..5495d33 100755 --- a/bin/jasmine-headless-webkit +++ b/bin/jasmine-headless-webkit @@ -18,7 +18,6 @@ begin files_list = Jasmine::FilesList.new(:config => runner.jasmine_config) files_list.files.each { |file| puts file } else - puts "Running Jasmine specs...".color(:white) exit runner.run end rescue CoffeeScript::CompilationError diff --git a/ext/jasmine-webkit-specrunner/Runner.cpp b/ext/jasmine-webkit-specrunner/Runner.cpp index 6c64ad3..19a8a74 100644 --- a/ext/jasmine-webkit-specrunner/Runner.cpp +++ b/ext/jasmine-webkit-specrunner/Runner.cpp @@ -35,6 +35,7 @@ void Runner::go() m_ticker.stop(); m_page.setPreferredContentsSize(QSize(1024, 600)); addJHW(); + loadSpec(); m_ticker.start(); @@ -46,6 +47,13 @@ void Runner::addJHW() 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_ticker.start(); } @@ -59,11 +67,9 @@ void Runner::watch(bool ok) QApplication::instance()->exit(1); return; } - } -bool Runner::hasElement(const char *select) -{ +bool Runner::hasElement(const char *select) { return !m_page.mainFrame()->findFirstElement(select).isNull(); } @@ -75,10 +81,6 @@ void Runner::reportFile(const QString &file) { reportFileName = file; } -bool Runner::hasError() { - return hasErrors; -} - void Runner::timerPause() { m_ticker.stop(); } @@ -87,17 +89,21 @@ void Runner::timerDone() { m_ticker.start(); } -void Runner::specPassed(const QString &specDetail) { - consoleOutput.passed(specDetail); - reportFileOutput.passed(specDetail); -} +void Runner::print(const QString &fh, const QString &content) { + if (fh == "stdout") { + std::cout << qPrintable(content); + std::cout.flush(); + } -void Runner::specFailed(const QString &specDetail) { - consoleOutput.failed(specDetail); - reportFileOutput.failed(specDetail); + if (fh == "stderr") { + std::cerr << qPrintable(content); + std::cerr.flush(); + } - didFail = true; - failedSpecs.push(specDetail); + if (fh == "report") { + *ts << qPrintable(content); + ts->flush(); + } } void Runner::errorLog(const QString &msg, int lineNumber, const QString &sourceID) @@ -115,11 +121,9 @@ void Runner::internalLog(const QString ¬e, const QString &msg) { reportFileOutput.internalLog(note, msg); } -void Runner::log(const QString &msg) +void Runner::usedConsole() { usedConsole = true; - consoleOutput.consoleLog(msg); - reportFileOutput.consoleLog(msg); } void Runner::leavePageAttempt(const QString &msg) @@ -129,53 +133,19 @@ void Runner::leavePageAttempt(const QString &msg) hasErrors = true; } -void Runner::printName(const QString &name) -{ - 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(); - } - +void Runner::finishSuite() { isFinished = true; } -void Runner::timerEvent() -{ +void Runner::timerEvent() { ++m_runs; if (hasErrors && m_runs > 2) QApplication::instance()->exit(1); if (isFinished) { + outputFile->close(); + int exitCode = 0; if (didFail || hasErrors) { exitCode = 1; diff --git a/ext/jasmine-webkit-specrunner/Runner.h b/ext/jasmine-webkit-specrunner/Runner.h index 96170b9..fdc9cc2 100644 --- a/ext/jasmine-webkit-specrunner/Runner.h +++ b/ext/jasmine-webkit-specrunner/Runner.h @@ -31,11 +31,10 @@ class Runner: public QObject { void leavePageAttempt(const QString &msg); void timerPause(); void timerDone(); - void specPassed(const QString &specDetail); - void specFailed(const QString &specDetail); - void printName(const QString &name); - void printResult(const QString &result); - void finishSuite(const QString &duration, const QString &total, const QString& failed); + + void print(const QString &fh, const QString &content); + + void finishSuite(); private slots: void watch(bool ok); void errorLog(const QString &msg, int lineNumber, const QString &sourceID); @@ -55,12 +54,14 @@ class Runner: public QObject { QQueue runnerFiles; QStack failedSpecs; - ConsoleOutput consoleOutput; ReportFileOutput reportFileOutput; QString reportFileName; void loadSpec(); + + QFile *outputFile; + QTextStream *ts; }; #endif diff --git a/jasmine/headless_reporter_result.coffee b/jasmine/headless_reporter_result.coffee new file mode 100644 index 0000000..fbf296f --- /dev/null +++ b/jasmine/headless_reporter_result.coffee @@ -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 diff --git a/jasmine/headless_reporter_result.js b/jasmine/headless_reporter_result.js new file mode 100644 index 0000000..9848308 --- /dev/null +++ b/jasmine/headless_reporter_result.js @@ -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); diff --git a/jasmine/intense.coffee b/jasmine/intense.coffee new file mode 100644 index 0000000..ddbcff0 --- /dev/null +++ b/jasmine/intense.coffee @@ -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 + diff --git a/jasmine/intense.js b/jasmine/intense.js new file mode 100644 index 0000000..a393ca1 --- /dev/null +++ b/jasmine/intense.js @@ -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); diff --git a/jasmine/jasmine-extensions.coffee b/jasmine/jasmine-extensions.coffee new file mode 100644 index 0000000..f7e8ce6 --- /dev/null +++ b/jasmine/jasmine-extensions.coffee @@ -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) diff --git a/jasmine/jasmine-extensions.js b/jasmine/jasmine-extensions.js new file mode 100644 index 0000000..d7a64e0 --- /dev/null +++ b/jasmine/jasmine-extensions.js @@ -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); diff --git a/jasmine/jasmine.headless-reporter.coffee b/jasmine/jasmine.headless-reporter.coffee index 8db83f4..d0a86be 100644 --- a/jasmine/jasmine.headless-reporter.coffee +++ b/jasmine/jasmine.headless-reporter.coffee @@ -1,175 +1,78 @@ 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) - -# 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. - 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 + @_hasError = false + reportRunnerResults: (runner) -> + return if this.hasError() - for result in @results - result.print() + this.callback() if @callback - this.callback() if @callback - JHW.finishSuite((new Date() - @startTime) / 1000.0, @length, @failedCount) + runtime = (new Date() - @startTime) / 1000.0 - reportRunnerStarting: (runner) -> - @startTime = new Date() + JHW.stdout.print("\n") - reportSpecResults: (spec) -> - return if this.hasError() + resultLine = this._formatResultLine(runtime) - 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) + if @failedCount == 0 + JHW.stdout.puts("PASS: #{resultLine}".foreground('green')) + else + JHW.stdout.puts("FAIL: #{resultLine}".foreground('red')) - reportSpecStarting: (spec) -> - if this.hasError() - spec.finish() - spec.suite.finish() + result.print() for result in @results - reportSuiteResults: (suite) -> - hasError: -> - JHW.hasError() + JHW.finishSuite() + + 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(' ') diff --git a/jasmine/jasmine.headless-reporter.js b/jasmine/jasmine.headless-reporter.js index 1a994f2..5209696 100644 --- a/jasmine/jasmine.headless-reporter.js +++ b/jasmine/jasmine.headless-reporter.js @@ -1,231 +1,93 @@ (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); - }; + jasmine.HeadlessReporter = (function() { + function HeadlessReporter(callback) { + this.callback = callback != null ? callback : null; + this.results = []; + this.failedCount = 0; + this.length = 0; + this._hasError = false; } - window.HeadlessReporterResult = (function() { - function HeadlessReporterResult(name, splitName) { - this.name = name; - this.splitName = splitName; - this.results = []; + HeadlessReporter.prototype.reportRunnerResults = function(runner) { + var result, resultLine, runtime, _i, _len, _ref; + if (this.hasError()) { + return; } - 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 = []; + if (this.callback) { + this.callback(); + } + runtime = (new Date() - this.startTime) / 1000.0; + JHW.stdout.print("\n"); + resultLine = this._formatResultLine(runtime); + if (this.failedCount === 0) { + JHW.stdout.puts(("PASS: " + resultLine).foreground('green')); + } else { + JHW.stdout.puts(("FAIL: " + resultLine).foreground('red')); + } + _ref = this.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++) { 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; - }; - 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; + if (result.type === 'expect' && !result.passed_) { + if (foundLine = result.expectations[testCount - 1]) { + result.line = foundLine[0], result.lineNumber = foundLine[1]; } - index++; - } - if (index > bestChoice.accuracy) { - bestChoice = { - accuracy: index, - file: file, - lineNumber: lineNumber - }; + failureResult.addResult(result); } + testCount += 1; } - return bestChoice; - }; - return HeadlessReporterResult; - })(); - jasmine.HeadlessReporter = (function() { - function HeadlessReporter(callback) { - this.callback = callback != null ? callback : null; - this.results = []; - this.failedCount = 0; - this.length = 0; + return this.results.push(failureResult); } - 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; - })(); - } + }; + HeadlessReporter.prototype.reportSpecStarting = function(spec) { + if (this.hasError()) { + spec.finish(); + return spec.suite.finish(); + } + }; + HeadlessReporter.prototype.reportSuiteResults = function(suite) {}; + HeadlessReporter.prototype.hasError = function() { + return this._hasError === true; + }; + HeadlessReporter.prototype._formatResultLine = function(runtime) { + var line; + line = []; + line.push(this.length); + line.push((this.length === 1 ? "test" : "tests") + ','); + line.push(this.failedCount); + line.push((this.failedCount === 1 ? "failure" : "failures") + ','); + line.push(runtime); + line.push((runtime === 1.0 ? "sec" : "secs") + '.'); + return line.join(' '); + }; + return HeadlessReporter; + })(); }).call(this); diff --git a/lib/jasmine/files_list.rb b/lib/jasmine/files_list.rb index 72757cd..bbd8ace 100644 --- a/lib/jasmine/files_list.rb +++ b/lib/jasmine/files_list.rb @@ -10,6 +10,9 @@ module Jasmine File.join(Jasmine::Core.path, "jasmine.js"), File.join(Jasmine::Core.path, "jasmine-html.js"), 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('js-lib/jsDump.js').to_s, Jasmine::Headless.root.join('js-lib/beautify-html.js').to_s diff --git a/skel/template.html.erb b/skel/template.html.erb index d44a535..ef8c453 100644 --- a/skel/template.html.erb +++ b/skel/template.html.erb @@ -3,7 +3,7 @@ Jasmine Test Runner - Generated by jasmine-headless-webkit - <%= files.join("\n") %> diff --git a/spec/javascripts/jasmine.headless-reporter_spec.coffee b/spec/javascripts/jasmine.headless-reporter_spec.coffee index f70203e..edc5099 100644 --- a/spec/javascripts/jasmine.headless-reporter_spec.coffee +++ b/spec/javascripts/jasmine.headless-reporter_spec.coffee @@ -30,7 +30,7 @@ describe 'jasmine.HeadlessReporter', -> reporter.reportSpecStarting(spec) - expect(spec.finish).toHaveBeenCalled() + expect(spec.finish).not.toHaveBeenCalled() expect(suite.finish).toHaveBeenCalled() describe 'jasmine.Suite.prototype.getSuiteSplitName', ->