rip out the big js parser and put in a tiny one to guess spec line numbers on failures

This commit is contained in:
John Bintz 2011-09-12 15:12:58 -04:00
parent d8d04b8638
commit 243fe526ac
11 changed files with 159 additions and 13 deletions

View File

@ -82,8 +82,15 @@ void ConsoleOutput::logSpecFilename(const QString &name) {
} }
void ConsoleOutput::logSpecResult(const QString &result) { void ConsoleOutput::logSpecResult(const QString &result) {
QStringList lines = result.split("\n");
QStringListIterator linesIterator(lines);
red(); red();
*outputIO << " " << qPrintable(result) << std::endl; while (linesIterator.hasNext()) {
*outputIO << " " << qPrintable(linesIterator.next()) << std::endl;
yellow();
}
clear(); clear();
} }

View File

@ -4,6 +4,7 @@
#include <QObject> #include <QObject>
#include <iostream> #include <iostream>
#include <QStack> #include <QStack>
#include <QStringList>
class ConsoleOutput : public QObject { class ConsoleOutput : public QObject {
public: public:

View File

@ -7,6 +7,8 @@ system %{make clean}
$: << File.expand_path("../../../lib", __FILE__) $: << File.expand_path("../../../lib", __FILE__)
require 'qt/qmake' require 'qt/qmake'
result = 0
Dir['*_test.pro'].each do |test| Dir['*_test.pro'].each do |test|
FileUtils.rm_f('jhw-test') FileUtils.rm_f('jhw-test')
@ -15,10 +17,15 @@ Dir['*_test.pro'].each do |test|
if File.file?('jhw-test') if File.file?('jhw-test')
system %{./jhw-test} system %{./jhw-test}
if $?.exitstatus != 0 if $?.exitstatus != 0
exit 1 result = 1
break
end end
else else
exit 1 result = 1
break
end end
end end
Qt::Qmake.make!('jasmine-headless-webkit', 'specrunner.pro')
exit result

View File

@ -24,6 +24,23 @@ jasmine.Spec.prototype.getJHWSpecInformation = ->
parts.push('') parts.push('')
parts.join("||") parts.join("||")
jasmine.Spec.prototype.fail = (e) ->
if e 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)
if !jasmine.WaitsBlock.prototype._execute if !jasmine.WaitsBlock.prototype._execute
jasmine.WaitsBlock.prototype._execute = jasmine.WaitsBlock.prototype.execute jasmine.WaitsBlock.prototype._execute = jasmine.WaitsBlock.prototype.execute
jasmine.WaitsForBlock.prototype._execute = jasmine.WaitsForBlock.prototype.execute jasmine.WaitsForBlock.prototype._execute = jasmine.WaitsForBlock.prototype.execute
@ -37,6 +54,24 @@ if !jasmine.WaitsBlock.prototype._execute
jasmine.WaitsBlock.prototype.execute = pauseAndRun jasmine.WaitsBlock.prototype.execute = pauseAndRun
jasmine.WaitsForBlock.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?
lineCount = 0
for line in arguments.callee.caller.caller.caller.toString().split("\n")
line = line.replace(/^\s*/, '').replace(/\s*$/, '')
if line.match(/^\s*expect/)
result.expectations.push(line)
lineCount += 1
this.addResult_(result)
}
jasmine.ExpectationResult.prototype.line = ->
if @expectations && @lineNumber then @expectations[@lineNumber] else ''
# Try to get the line number of a failed spec # Try to get the line number of a failed spec
class window.HeadlessReporterResult class window.HeadlessReporterResult
constructor: (@name, @splitName) -> constructor: (@name, @splitName) ->
@ -50,7 +85,10 @@ class window.HeadlessReporterResult
JHW.printName(output) JHW.printName(output)
for result in @results for result in @results
JHW.printResult(result) output = result.message
if result.lineNumber
output += " (line ~#{bestChoice.lineNumber + result.lineNumber})\n #{result.line()}"
JHW.printResult(output)
@findSpecLine: (splitName) -> @findSpecLine: (splitName) ->
bestChoice = { accuracy: 0, file: null, lineNumber: null } bestChoice = { accuracy: 0, file: null, lineNumber: null }
@ -104,9 +142,13 @@ class jasmine.HeadlessReporter
JHW.specFailed(spec.getJHWSpecInformation()) JHW.specFailed(spec.getJHWSpecInformation())
@failedCount++ @failedCount++
failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName()) failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName())
testCount = 1
for result in results.getItems() for result in results.getItems()
if result.type == 'expect' and !result.passed_ if result.type == 'expect' and !result.passed_
failureResult.addResult(result.message) if foundLine = result.expectations[testCount - 1]
result.lineNumber = testCount - 1
failureResult.addResult(result)
testCount += 1
@results.push(failureResult) @results.push(failureResult)
reportSpecStarting: (spec) -> reportSpecStarting: (spec) ->

View File

@ -26,6 +26,28 @@
} }
return parts.join("||"); return parts.join("||");
}; };
jasmine.Spec.prototype.fail = function(e) {
var expectationResult, filename, realFilename;
if (e && 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);
};
if (!jasmine.WaitsBlock.prototype._execute) { if (!jasmine.WaitsBlock.prototype._execute) {
jasmine.WaitsBlock.prototype._execute = jasmine.WaitsBlock.prototype.execute; jasmine.WaitsBlock.prototype._execute = jasmine.WaitsBlock.prototype.execute;
jasmine.WaitsForBlock.prototype._execute = jasmine.WaitsForBlock.prototype.execute; jasmine.WaitsForBlock.prototype._execute = jasmine.WaitsForBlock.prototype.execute;
@ -38,6 +60,29 @@
}; };
jasmine.WaitsBlock.prototype.execute = pauseAndRun; jasmine.WaitsBlock.prototype.execute = pauseAndRun;
jasmine.WaitsForBlock.prototype.execute = pauseAndRun; jasmine.WaitsForBlock.prototype.execute = pauseAndRun;
jasmine.NestedResults.prototype.addResult_ = jasmine.NestedResults.prototype.addResult;
jasmine.NestedResults.prototype.addResult = function(result) {
var line, lineCount, _i, _len, _ref;
result.expectations = [];
lineCount = 0;
_ref = arguments.callee.caller.caller.caller.toString().split("\n");
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
line = _ref[_i];
line = line.replace(/^\s*/, '').replace(/\s*$/, '');
if (line.match(/^\s*expect/)) {
result.expectations.push(line);
}
lineCount += 1;
}
return this.addResult_(result);
};
jasmine.ExpectationResult.prototype.line = function() {
if (this.expectations && this.lineNumber) {
return this.expectations[this.lineNumber];
} else {
return '';
}
};
} }
window.HeadlessReporterResult = (function() { window.HeadlessReporterResult = (function() {
function HeadlessReporterResult(name, splitName) { function HeadlessReporterResult(name, splitName) {
@ -60,7 +105,11 @@
_results = []; _results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
result = _ref[_i]; result = _ref[_i];
_results.push(JHW.printResult(result)); output = result.message;
if (result.lineNumber) {
output += " (line ~" + (bestChoice.lineNumber + result.lineNumber) + ")\n " + (result.line());
}
_results.push(JHW.printResult(output));
} }
return _results; return _results;
}; };
@ -130,7 +179,7 @@
return this.startTime = new Date(); return this.startTime = new Date();
}; };
HeadlessReporter.prototype.reportSpecResults = function(spec) { HeadlessReporter.prototype.reportSpecResults = function(spec) {
var failureResult, result, results, _i, _len, _ref; var failureResult, foundLine, result, results, testCount, _i, _len, _ref;
if (this.hasError()) { if (this.hasError()) {
return; return;
} }
@ -142,12 +191,17 @@
JHW.specFailed(spec.getJHWSpecInformation()); JHW.specFailed(spec.getJHWSpecInformation());
this.failedCount++; this.failedCount++;
failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName()); failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName());
testCount = 1;
_ref = results.getItems(); _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];
if (result.type === 'expect' && !result.passed_) { if (result.type === 'expect' && !result.passed_) {
failureResult.addResult(result.message); if (foundLine = result.expectations[testCount - 1]) {
result.lineNumber = testCount - 1;
}
failureResult.addResult(result);
} }
testCount += 1;
} }
return this.results.push(failureResult); return this.results.push(failureResult);
} }

View File

@ -1,6 +1,7 @@
require 'jasmine-core' require 'jasmine-core'
require 'iconv' require 'iconv'
require 'time' require 'time'
require 'multi_json'
module Jasmine module Jasmine
class FilesList class FilesList
@ -63,10 +64,25 @@ module Jasmine
alert_time = nil alert_time = nil
end end
case File.extname(file) function_locations = {}
source = nil
result = case File.extname(file)
when '.coffee' when '.coffee'
begin begin
%{<script type="text/javascript">#{Jasmine::Headless::CoffeeScriptCache.for(file)}</script>} cache = Jasmine::Headless::CoffeeScriptCache.new(file)
source = cache.handle
if cache.cached?
%{
<script type="text/javascript" src="#{cache.cache_file}"></script>S
<script type="text/javascript">
window.CoffeeScriptToFilename = window.CoffeeScriptToFilename || {};
window.CoffeeScriptToFilename['#{File.split(cache.cache_file).last}'] = '#{file}';
</script>
}
else
%{<script type="text/javascript">#{source}</script>}
end
rescue CoffeeScript::CompilationError => ne rescue CoffeeScript::CompilationError => ne
puts "[%s] %s: %s" % [ 'coffeescript'.color(:red), file.color(:yellow), ne.message.to_s.color(:white) ] puts "[%s] %s: %s" % [ 'coffeescript'.color(:red), file.color(:yellow), ne.message.to_s.color(:white) ]
raise ne raise ne
@ -79,6 +95,8 @@ module Jasmine
when '.css' when '.css'
%{<link rel="stylesheet" href="#{file}" type="text/css" />} %{<link rel="stylesheet" href="#{file}" type="text/css" />}
end end
result
}.flatten.compact.reject(&:empty?) }.flatten.compact.reject(&:empty?)
end end

View File

@ -58,7 +58,11 @@ module Jasmine::Headless
end end
def fresh? def fresh?
File.exist?(cache_file) && (File.mtime(file) < File.mtime(cache_file)) cached? && (File.mtime(file) < File.mtime(cache_file))
end
def cached?
File.exist?(cache_file)
end end
def action def action

View File

@ -14,7 +14,8 @@ module Jasmine
'spec_dir' => 'spec/javascripts', 'spec_dir' => 'spec/javascripts',
'src_dir' => nil, 'src_dir' => nil,
'stylesheets' => [], 'stylesheets' => [],
'src_files' => [] 'src_files' => [],
'backtrace' => []
} }
RUNNER_DIR = File.expand_path('../../../../ext/jasmine-webkit-specrunner', __FILE__) RUNNER_DIR = File.expand_path('../../../../ext/jasmine-webkit-specrunner', __FILE__)

View File

@ -170,7 +170,8 @@ describe Jasmine::FilesList do
'test.coffee' 'test.coffee'
]) ])
Jasmine::Headless::CoffeeScriptCache.stubs(:for).with('test.coffee').returns("i compiled") File.stubs(:read)
Jasmine::Headless::CoffeeScriptCache.any_instance.stubs(:handle).returns("i compiled")
end end
context '#files_to_html' do context '#files_to_html' do

View File

@ -22,6 +22,8 @@ describe Jasmine::Headless::CacheableAction do
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)) }
let(:cache_file_data) { YAML.load(File.read(cache_file)) } let(:cache_file_data) { YAML.load(File.read(cache_file)) }
let(:cache_object) { described_class.new(file) }
describe '.for' do describe '.for' do
context 'cache disabled' do context 'cache disabled' do
before do before do
@ -32,6 +34,8 @@ describe Jasmine::Headless::CacheableAction do
action_runs! action_runs!
described_class.for(file).should == compiled described_class.for(file).should == compiled
cache_file.should_not be_a_file cache_file.should_not be_a_file
cache_object.should_not be_cached
end end
end end
@ -52,6 +56,7 @@ describe Jasmine::Headless::CacheableAction do
described_class.for(file).should == compiled described_class.for(file).should == compiled
cache_file_data.should == compiled cache_file_data.should == compiled
cache_object.should be_cached
end end
end end
@ -69,6 +74,7 @@ describe Jasmine::Headless::CacheableAction do
described_class.for(file).should == compiled described_class.for(file).should == compiled
cache_file_data.should == compiled cache_file_data.should == compiled
cache_object.should be_cached
end end
end end
@ -81,6 +87,7 @@ describe Jasmine::Headless::CacheableAction do
described_class.for(file).should == compiled described_class.for(file).should == compiled
cache_file_data.should == compiled cache_file_data.should == compiled
cache_object.should be_cached
end end
end end
end end

View File

@ -6,6 +6,10 @@ describe Jasmine::TemplateWriter do
describe '.write!' do describe '.write!' do
include FakeFS::SpecHelpers include FakeFS::SpecHelpers
before do
File.stubs(:read).returns(nil)
end
let(:files_list) { Jasmine::FilesList.new } let(:files_list) { Jasmine::FilesList.new }
before do before do