Compare commits

..

No commits in common. "master" and "split-reporter" have entirely different histories.

77 changed files with 735 additions and 888 deletions

1
.gitignore vendored
View File

@ -16,4 +16,3 @@ _site/
jhw.*.html jhw.*.html
coverage/ coverage/
tmp/ tmp/
cache dir/

17
Gemfile
View File

@ -12,19 +12,16 @@ gem 'guard-shell'
gem 'guard-coffeescript' gem 'guard-coffeescript'
gem 'guard-cucumber' gem 'guard-cucumber'
require 'rbconfig' gem 'growl'
case RbConfig::CONFIG['host_os'] gem 'rake', '0.8.7'
when /darwin/ gem 'mocha', '0.9.12'
when /linux/ gem 'guard-jasmine-headless-webkit', :git => 'git://github.com/johnbintz/guard-jasmine-headless-webkit.git'
gem 'libnotify' gem 'facter'
end
gem 'mocha'
gem 'cucumber' gem 'cucumber'
gem 'jquery-rails', '~> 1.0.0' gem 'jquery-rails'
gem 'ejs' gem 'ejs'
gem 'guard-jasmine-headless-webkit', :git => 'git://github.com/johnbintz/guard-jasmine-headless-webkit.git' gem 'simplecov'

View File

@ -1,5 +1,3 @@
_This project is dead. You should use [Karma](http://karma-runner.github.io/) instead. I do._
# Jasmine Headless WebKit runner # Jasmine Headless WebKit runner
Run your specs at sonic boom speed! No pesky reload button or page rendering slowdowns! Run your specs at sonic boom speed! No pesky reload button or page rendering slowdowns!

View File

@ -14,7 +14,7 @@ require 'jasmine/headless/task'
Jasmine::Headless::Task.new Jasmine::Headless::Task.new
PLATFORMS = %w{1.9.2 1.9.3} PLATFORMS = %w{1.8.7 1.9.2 ree 1.9.3-rc1}
def rvm_bundle(command = '') def rvm_bundle(command = '')
Bundler.with_clean_env do Bundler.with_clean_env do

View File

@ -1,2 +0,0 @@
default: -r features

View File

@ -11,5 +11,6 @@ void Page::javaScriptConsoleMessage(const QString & message, int lineNumber, con
} }
void Page::javaScriptAlert(QWebFrame *, const QString &) {} void Page::javaScriptAlert(QWebFrame *, const QString &) {}
bool Page::javaScriptConfirm(QWebFrame *, const QString &) { return false; } bool Page::javaScriptConfirm(QWebFrame *, const QString &) {
bool Page::javaScriptPrompt(QWebFrame *, const QString &, const QString &, QString *) { return false; } return false;
}

View File

@ -12,7 +12,6 @@ class Page: public QWebPage {
void javaScriptConsoleMessage(const QString & message, int lineNumber, const QString & sourceID); void javaScriptConsoleMessage(const QString & message, int lineNumber, const QString & sourceID);
void javaScriptAlert(QWebFrame *, const QString &); void javaScriptAlert(QWebFrame *, const QString &);
bool javaScriptConfirm(QWebFrame *, const QString &); bool javaScriptConfirm(QWebFrame *, const QString &);
bool javaScriptPrompt(QWebFrame *, const QString &, const QString &, QString *);
signals: signals:
void handleError(const QString & message, int lineNumber, const QString & sourceID); void handleError(const QString & message, int lineNumber, const QString & sourceID);
}; };

View File

@ -18,7 +18,6 @@ Runner::Runner() : QObject()
, usedConsole(false) , usedConsole(false)
, isFinished(false) , isFinished(false)
, useColors(false) , useColors(false)
, quiet(false)
{ {
page.settings()->enablePersistentStorage(); page.settings()->enablePersistentStorage();
ticker.setInterval(TIMER_TICK); ticker.setInterval(TIMER_TICK);
@ -71,9 +70,7 @@ void Runner::loadSpec()
outputFiles.enqueue(outputFile); outputFiles.enqueue(outputFile);
} }
QString runnerFile = runnerFiles.dequeue(); page.mainFrame()->load(runnerFiles.dequeue());
page.mainFrame()->load(runnerFile);
ticker.start(); ticker.start();
} }
@ -125,18 +122,10 @@ void Runner::setSeed(QString s) {
seed = s; seed = s;
} }
void Runner::setQuiet(bool q) {
quiet = q;
}
QString Runner::getSeed() { QString Runner::getSeed() {
return seed; return seed;
} }
bool Runner::isQuiet() {
return quiet;
}
void Runner::print(const QString &fh, const QString &content) { void Runner::print(const QString &fh, const QString &content) {
if (fh == "stdout") { if (fh == "stdout") {
std::cout << qPrintable(content); std::cout << qPrintable(content);

View File

@ -7,9 +7,7 @@
#include <QTextStream> #include <QTextStream>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <sstream>
#include <QQueue> #include <QQueue>
#include <QApplication>
#include "Page.h" #include "Page.h"
@ -24,7 +22,6 @@ class Runner: public QObject {
void setColors(bool colors); void setColors(bool colors);
void setReportFiles(QStack<QString> &files); void setReportFiles(QStack<QString> &files);
void setSeed(QString s); void setSeed(QString s);
void setQuiet(bool q);
void addFile(const QString &spec); void addFile(const QString &spec);
void go(); void go();
@ -36,7 +33,6 @@ class Runner: public QObject {
void hasError(); void hasError();
void hasSpecFailure(); void hasSpecFailure();
bool isQuiet();
QString getSeed(); QString getSeed();
void print(const QString &fh, const QString &content); void print(const QString &fh, const QString &content);
@ -58,7 +54,6 @@ class Runner: public QObject {
bool usedConsole; bool usedConsole;
bool isFinished; bool isFinished;
bool useColors; bool useColors;
bool quiet;
QString seed; QString seed;

View File

@ -1,6 +1,7 @@
TEMPLATE = app TEMPLATE = app
CONFIG -= app_bundle CONFIG -= app_bundle
QMAKE_INFO_PLIST = Info.plist QMAKE_INFO_PLIST = Info.plist
QMAKESPEC = macx-g++
QT += network webkit QT += network webkit
SOURCES = Page.cpp Runner.cpp SOURCES = Page.cpp Runner.cpp

View File

@ -0,0 +1,19 @@
######################################################################
# Automatically generated by qmake (2.01a) Tue Aug 2 10:37:48 2011
######################################################################
TEMPLATE = app
TARGET =
DEPENDPATH += . HeadlessSpecRunner Test
INCLUDEPATH += . HeadlessSpecRunner Test
# Input
HEADERS += HeadlessSpecRunner/ConsoleOutput.h \
HeadlessSpecRunner/Page.h \
HeadlessSpecRunner/Runner.h \
Test/Page_test.h
SOURCES += specrunner.cpp \
HeadlessSpecRunner/ConsoleOutput.cpp \
HeadlessSpecRunner/Page.cpp \
HeadlessSpecRunner/Runner.cpp \
Test/Page_test.cpp

View File

@ -23,10 +23,6 @@
#include "Runner.h" #include "Runner.h"
#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
#include <getopt.h>
#endif
#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) #if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
#error Use Qt 4.7 or later version #error Use Qt 4.7 or later version
#endif #endif
@ -34,20 +30,17 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
bool showColors = false; bool showColors = false;
bool isQuiet = false;
QString seed; QString seed;
QStack<QString> reporterFiles; QStack<QString> reporterFiles;
int c, index; int c, index;
while ((c = getopt(argc, argv, "cr:s:q")) != -1) { while ((c = getopt(argc, argv, "cr:s:")) != -1) {
switch(c) { switch(c) {
case 'c': case 'c':
showColors = true; showColors = true;
break; break;
case 'q':
isQuiet = true;
break;
case 'r': case 'r':
reporterFiles.push(QString(optarg)); reporterFiles.push(QString(optarg));
break; break;
@ -68,7 +61,6 @@ int main(int argc, char** argv)
Runner runner; Runner runner;
runner.setColors(showColors); runner.setColors(showColors);
runner.setQuiet(isQuiet);
runner.setReportFiles(reporterFiles); runner.setReportFiles(reporterFiles);
runner.setSeed(seed); runner.setSeed(seed);

View File

@ -1,7 +0,0 @@
Feature: Bin - Help
Scenario: Display the Help
Given I have a test suite
When I run `bin/jasmine-headless-webkit -h`
Then I should get help output
And the exit status should be 0

View File

@ -1,8 +0,0 @@
Feature: Bin - Quiet Messages
Scenario: Run a test that would cause a lot of messages to be displayed and silence them all
Given I have a test suite
When I run `bin/jasmine-headless-webkit -q -j spec/jasmine/noisy/noisy.yml`
Then the exit status should be 0
And the output should not include "[Skipping File]"
And the output should not include "You should mock"

View File

@ -1,7 +0,0 @@
Feature: Bin - Two spec files with same basename
Scenario: Run both files
Given there is no existing "spec/report.txt" file
When I run `bin/jasmine-headless-webkit -j spec/jasmine/two_spec_files_same_basename/jasmine.yml -f File:spec/report.txt`
Then the exit status should be 0
And the report file "spec/report.txt" should have 2 total, 0 failures, no console usage

View File

@ -1,11 +0,0 @@
Feature: Two files from source files
Scenario: Files are ordered directly
Given I have a test suite
When I run `bin/jasmine-headless-webkit -j spec/jasmine/two_files_from_src_files/jasmine.yml -l`
Then the exit status should be 0
And the following files should be loaded in order:
| vendor/vendor-file.js |
| vendor/vendor.js |
| app/app-file.js |
| app/app.js |

View File

@ -1,7 +0,0 @@
Feature: Bin - With Server
Scenario: Run using an HTTP server
Given there is no existing "spec/report.txt" file
When I run `bin/jasmine-headless-webkit --use-server -j spec/jasmine/success/success.yml -f File:spec/report.txt`
Then the exit status should be 0
And the report file "spec/report.txt" should have 1 total, 0 failures, no console usage

View File

@ -1,7 +0,0 @@
Feature: Bin - With window.prompt()
Scenario: Alert the user that window.prompt() needs to be stubbed
Given I have a test suite
When I run `bin/jasmine-headless-webkit -j spec/jasmine/window_prompt/window_prompt.yml`
Then the exit status should be 0
And the output should include "You should mock window.prompt"

View File

@ -1,10 +0,0 @@
Then /^the following files should be loaded in order:$/ do |table|
files = table.raw.flatten
@output.lines.collect(&:strip).each do |line|
files.shift if line[files.first]
end
files.should be_empty
end

View File

@ -1,4 +0,0 @@
Then /^I should get help output$/ do
@output.should include("Usage:")
end

View File

@ -1,4 +0,0 @@
Then /^the output should not include "([^"]*)"$/ do |string|
@output.should_not include(string)
end

View File

@ -20,11 +20,9 @@ Gem::Specification.new do |s|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"] s.require_paths = ["lib"]
s.add_runtime_dependency 'jasmine-core' s.add_runtime_dependency 'jasmine-core', '~> 1.1'
s.add_runtime_dependency 'coffee-script' s.add_runtime_dependency 'coffee-script'
s.add_runtime_dependency 'rainbow' s.add_runtime_dependency 'rainbow'
s.add_runtime_dependency 'multi_json', '>= 1.2.0' s.add_runtime_dependency 'multi_json'
s.add_runtime_dependency 'sprockets' s.add_runtime_dependency 'sprockets', '~> 2'
s.add_runtime_dependency 'sprockets-vendor_gems'
end end

View File

@ -0,0 +1,20 @@
module Digest
class JasmineTest
def self.file(file)
new
end
def file(file)
self
end
def hexdigest
'test'
end
def update(prefix)
self
end
end
end

View File

@ -1,3 +1,7 @@
require 'jasmine/headless' require 'jasmine/headless'
require 'jasmine/headless/railtie' if defined?(Rails) && Rails::VERSION::MAJOR >= 3 require 'jasmine/headless/railtie' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
module Digest
autoload :JasmineTest, 'digest/jasmine_test'
end

View File

@ -35,24 +35,6 @@ module Jasmine
def root def root
@root ||= Pathname(File.expand_path('../../..', __FILE__)) @root ||= Pathname(File.expand_path('../../..', __FILE__))
end end
def warn(message)
output.puts message if show_warnings?
end
def show_warnings=(show)
@show_warnings = show
end
def show_warnings?
@show_warnings = true if @show_warnings.nil?
@show_warnings
end
def output
$stdout
end
end end
end end
end end

View File

@ -54,11 +54,7 @@ module Jasmine::Headless
end end
def cache_file def cache_file
@cache_file ||= File.expand_path(relative_cache_file) + '.js' @cache_file ||= File.expand_path(File.join(self.class.cache_dir, self.class.cache_type, file)) + '.js'
end
def relative_cache_file
File.join(self.class.cache_dir, self.class.cache_type, file.gsub(Dir.pwd + '/', ''))
end end
def fresh? def fresh?

View File

@ -1,18 +1,14 @@
module Jasmine::Headless::FileChecker module Jasmine::Headless::FileChecker
def excluded_formats
::Jasmine::Headless::EXCLUDED_FORMATS
end
def bad_format?(file) def bad_format?(file)
return if file.nil? return if file.nil?
excluded_formats.any? do |format| ::Jasmine::Headless::EXCLUDED_FORMATS.any? do |format|
file[%r{\.#{format}(\.|$)}] file[%r{\.#{format}(\.|$)}]
end end
end end
def alert_bad_format(file) def alert_bad_format(file)
Jasmine::Headless.warn("[%s] %s: %s" % [ 'Skipping File'.color(:red), file.color(:yellow), "unsupported format".color(:white) ]) puts "[%s] %s: %s" % [ 'Skipping File'.color(:red), file.color(:yellow), "unsupported format".color(:white) ]
end end
def alert_if_bad_format?(file) def alert_if_bad_format?(file)

View File

@ -4,7 +4,6 @@ require 'multi_json'
require 'set' require 'set'
require 'sprockets' require 'sprockets'
require 'sprockets/engines' require 'sprockets/engines'
require 'sprockets-vendor_gems'
module Jasmine::Headless module Jasmine::Headless
class FilesList class FilesList
@ -12,12 +11,33 @@ module Jasmine::Headless
class << self class << self
def asset_paths def asset_paths
@asset_paths ||= Sprockets.find_gem_vendor_paths(:for => 'javascripts') return @asset_paths if @asset_paths
require 'rubygems'
raise StandardError.new("A newer version of Rubygems is required to use vendored assets. Please upgrade.") if !Gem::Specification.respond_to?(:each)
@asset_paths = []
Gem::Specification.each { |gemspec| @asset_paths += get_paths_from_gemspec(gemspec) }
@asset_paths
end
def get_paths_from_gemspec(gemspec)
%w{vendor lib app}.collect do |dir|
path = File.join(gemspec.gem_dir, dir, "assets/javascripts")
if File.directory?(path) && !@asset_paths.include?(path)
path
else
nil
end
end.compact
end end
def reset! def reset!
@asset_paths = nil @asset_paths = nil
@registered_engines = {}
# register haml-sprockets and handlebars_assets if it's available... # register haml-sprockets and handlebars_assets if it's available...
%w{haml-sprockets handlebars_assets}.each do |library| %w{haml-sprockets handlebars_assets}.each do |library|
@ -36,27 +56,22 @@ module Jasmine::Headless
end end
end end
@sprockets_environment = nil # ...and unregister ones we don't want/need
end Sprockets.instance_eval do
EXCLUDED_FORMATS.each do |extension|
register_engine ".#{extension}", Jasmine::Headless::NilTemplate
end
def registered_engines register_engine '.coffee', Jasmine::Headless::CoffeeTemplate
@registered_engines ||= {} register_engine '.js', Jasmine::Headless::JSTemplate
end register_engine '.css', Jasmine::Headless::CSSTemplate
register_engine '.jst', Jasmine::Headless::JSTTemplate
def register_engine(file_extension, template_class)
registered_engines[file_extension] = template_class
end
def register_engines!
registered_engines.each do |file_extension, template_class|
Sprockets.register_engine file_extension, template_class
end end
end end
def default_files def default_files
%w{jasmine.js jasmine-html jasmine.css jasmine-extensions %w{jasmine.js jasmine-html jasmine.css jasmine-extensions
intense headless_reporter_result jasmine.HeadlessReporter intense headless_reporter_result jasmine.HeadlessReporter
jasmine.HeadlessReporter.ConsoleBase
jsDump beautify-html} jsDump beautify-html}
end end
@ -79,21 +94,11 @@ module Jasmine::Headless
@required_files = UniqueAssetList.new @required_files = UniqueAssetList.new
@potential_files_to_filter = [] @potential_files_to_filter = []
register_engines!
load_initial_assets load_initial_assets
use_config if config? use_config if config?
end end
def register_engines!
begin
require spec_helper
rescue LoadError
end
self.class.register_engines!
end
def load_initial_assets def load_initial_assets
self.class.default_files.each do |file| self.class.default_files.each do |file|
begin begin
@ -131,7 +136,6 @@ module Jasmine::Headless
@search_paths += asset_paths.collect { |dir| File.expand_path(dir) } @search_paths += asset_paths.collect { |dir| File.expand_path(dir) }
@search_paths += spec_dir.collect { |dir| File.expand_path(dir) } @search_paths += spec_dir.collect { |dir| File.expand_path(dir) }
@search_paths.uniq!
@search_paths @search_paths
end end
@ -142,19 +146,6 @@ module Jasmine::Headless
search_paths.each { |path| @sprockets_environment.append_path(path) } search_paths.each { |path| @sprockets_environment.append_path(path) }
@sprockets_environment.unregister_postprocessor('application/javascript', Sprockets::SafetyColons) @sprockets_environment.unregister_postprocessor('application/javascript', Sprockets::SafetyColons)
# ...and unregister ones we don't want/need
@sprockets_environment.instance_eval do
EXCLUDED_FORMATS.each do |extension|
register_engine ".#{extension}", Jasmine::Headless::NilTemplate
end
register_engine '.coffee', Jasmine::Headless::CoffeeTemplate
register_engine '.js', Jasmine::Headless::JSTemplate
register_engine '.css', Jasmine::Headless::CSSTemplate
register_engine '.jst', Jasmine::Headless::JSTTemplate
end
@sprockets_environment @sprockets_environment
end end
@ -235,13 +226,13 @@ module Jasmine::Headless
end end
def add_files(patterns, type, dirs) def add_files(patterns, type, dirs)
patterns.each do |pattern| dirs.product(patterns).each do |search|
dirs.collect { |dir| expanded_dir(File.join(dir, pattern)) }.each do |files| files = expanded_dir(File.join(*search))
files.sort! { |a, b| Kernel.rand(3) - 1 } if type == 'spec_files'
files.each do |path| files.sort! { |a, b| Kernel.rand(3) - 1 } if type == 'spec_files'
add_path(path, type)
end files.each do |path|
add_path(path, type)
end end
end end
@ -255,8 +246,7 @@ module Jasmine::Headless
end end
def expanded_dir(path) def expanded_dir(path)
file_list = Dir.glob(path).sort Dir[path].find_all { |file|
file_list.find_all { |file|
file[extension_filter] && !alert_if_bad_format?(file) file[extension_filter] && !alert_if_bad_format?(file)
}.collect { }.collect {
|file| File.expand_path(file) |file| File.expand_path(file)
@ -280,7 +270,7 @@ module Jasmine::Headless
end end
def src_dir def src_dir
@src_dir ||= config_dir_or_pwd('src_dir') + asset_paths @src_dir ||= config_dir_or_pwd('src_dir')
end end
def spec_dir def spec_dir
@ -288,7 +278,7 @@ module Jasmine::Headless
end end
def asset_paths def asset_paths
@asset_paths ||= config_dir('asset_paths') @asset_paths ||= config_dir_or_pwd('asset_paths')
end end
def spec_file_searches def spec_file_searches
@ -296,15 +286,9 @@ module Jasmine::Headless
end end
def config_dir_or_pwd(dir) def config_dir_or_pwd(dir)
if (found = config_dir(dir)).empty? found_dir = (@options[:config] && @options[:config][dir]) || Dir.pwd
found = [ Dir.pwd ]
end
found [ found_dir ].flatten.collect { |dir| File.expand_path(dir) }
end
def config_dir(dir)
[ @options[:config] && @options[:config][dir] ].flatten.compact.collect { |dir| File.expand_path(dir) }
end end
def filter_for_requested_specs(files) def filter_for_requested_specs(files)
@ -316,17 +300,5 @@ module Jasmine::Headless
end end
end end
end end
def spec_helper
File.join(spec_dir, "helpers", "spec_helper")
end
end
end
module Jasmine::Headless
extend self
def register_engine(file_extension, template_class)
Jasmine::Headless::FilesList.register_engine(file_extension, template_class)
end end
end end

View File

@ -17,10 +17,9 @@ module Jasmine
:full_run => true, :full_run => true,
:enable_cache => true, :enable_cache => true,
:files => [], :files => [],
:reporters => [ [ 'Console' ] ], :reporters => [
:quiet => false, [ 'Console' ]
:use_server => false, ]
:server_port => nil
} }
DEFAULTS_FILE = File.join(Dir.pwd, '.jasmine-headless-webkit') DEFAULTS_FILE = File.join(Dir.pwd, '.jasmine-headless-webkit')
@ -40,7 +39,6 @@ module Jasmine
srand srand
@options[:seed] = rand(10000) @options[:seed] = rand(10000)
read_defaults_files read_defaults_files
opts.each { |k, v| @options[k] = v if v } opts.each { |k, v| @options[k] = v if v }
end end
@ -71,22 +69,12 @@ module Jasmine
@options[:full_run] = false @options[:full_run] = false
when '--list', '-l' when '--list', '-l'
@options[:do_list] = true @options[:do_list] = true
when '--quiet', '-q'
@options[:quiet] = true
when '--seed' when '--seed'
@options[:seed] = arg.to_i @options[:seed] = arg.to_i
when '--format', '-f' when '--format', '-f'
add_reporter(arg) add_reporter(arg)
when '--use-server'
@options[:use_server] = true
when '--server-port'
@options[:server_port] = arg.to_i
when '--out' when '--out'
add_reporter_file(arg) add_reporter_file(arg)
when '-h', '--help'
print_help
exit
end end
end end
@ -112,11 +100,7 @@ module Jasmine
[ '--list', '-l', GetoptLong::NO_ARGUMENT ], [ '--list', '-l', GetoptLong::NO_ARGUMENT ],
[ '--seed', GetoptLong::REQUIRED_ARGUMENT ], [ '--seed', GetoptLong::REQUIRED_ARGUMENT ],
[ '--format', '-f', GetoptLong::REQUIRED_ARGUMENT ], [ '--format', '-f', GetoptLong::REQUIRED_ARGUMENT ],
[ '--out', GetoptLong::REQUIRED_ARGUMENT ], [ '--out', GetoptLong::REQUIRED_ARGUMENT ]
[ '--use-server', GetoptLong::NO_ARGUMENT ],
[ '--server-port', GetoptLong::REQUIRED_ARGUMENT ],
[ '-h', '--help', GetoptLong::NO_ARGUMENT ],
[ '-q', '--quiet', GetoptLong::NO_ARGUMENT ]
) )
command_line_args.each { |*args| process_option(*args) } command_line_args.each { |*args| process_option(*args) }
@ -162,44 +146,6 @@ module Jasmine
def add_reporter_file(file) def add_reporter_file(file)
@options[:reporters].last << file @options[:reporters].last << file
end end
def print_help
options = [
[ '-c, --colors', 'Enable colors (default: disabled)' ],
[ '-nc, --no-colors', 'Disable colors' ],
[ '--cache', 'Enable cache (default: enabled)' ],
[ '--no-cache', 'Disable cache' ],
[ '--keep', 'Keep runner files on failure' ],
[ '--runner-out <filename>', 'Write runner to specified filename' ],
[ '-j, --jasmine-config <config file>', 'Jasmine Yaml config to use' ],
[ '--no-full-run', 'Do not perform a full spec run after a successful targeted spec run' ],
[ '--use-server', 'Load tests from an HTTP server instead of from filesystem' ],
[ '-l, --list', 'List files in the order they will be required' ],
[ '--seed <seed>', 'Random order seed for spec file ordering' ],
[ '-f, --format <reporter<:filename>>', 'Specify an output reporter and possibly output filename' ],
[ '--out <filename>', 'Specify output filename for last defined reporter' ],
[ '-q, --quiet', "Silence most non-test related warnings" ],
[ '-h, --help', "You're looking at it" ]
]
longest_length = options.collect(&:first).collect(&:length).max
puts <<-HELP
Usage: #{$0} [ options ] [ spec files ]
Options:
#{options.collect { |option, description| " #{option.ljust(longest_length)} #{description}" }.join("\n")}
Available reporters:
Console Write out spec results to the console in a progress format (default)
Verbose Write out spec results to the console in a verbose format
File Write spec results in jasmine-headless-webkit ReportFile format
Tap Write spec results in TAP format
Add reporters to the jasmine.HeadlessReporter object to access them
(ex: jasmine.HeadlessReporter.Teamcity for the Teamcity reporter)
HELP
end
end end
end end
end end

View File

@ -7,26 +7,9 @@ require 'yaml'
require 'erb' require 'erb'
require 'sprockets' require 'sprockets'
module Jasmine module Jasmine
module Headless module Headless
class IndexHandler
class << self
attr_accessor :index
end
def initialize(app)
@app = app
end
def call(env)
if env['PATH_INFO'] == '/'
return [ 302, { 'Location' => self.class.index }, [ 'Redirecting...' ] ]
end
@app.call(env)
end
end
class Runner class Runner
JASMINE_DEFAULTS = { JASMINE_DEFAULTS = {
'spec_files' => [ '**/*[sS]pec.js' ], 'spec_files' => [ '**/*[sS]pec.js' ],
@ -43,103 +26,9 @@ module Jasmine
attr_reader :options attr_reader :options
def self.run(options = {}) class << self
new(options).run def run(options = {})
end new(options).run
def self.server_port
return @server_port if @server_port
require 'socket'
count = 100
begin
port = select_server_port
socket = TCPSocket.new(server_interface, port)
socket.close
count -= 1
raise "Could not create server port after 100 attempts!" if count == 0
rescue Errno::ECONNREFUSED
@server_port = port
break
ensure
begin
socket.close if socket
rescue IOError
end
end while true
@server_port
end
def self.server_port=(port)
@server_port = port
end
def self.select_server_port
21000 + rand(10000)
end
def self.server_interface
'127.0.0.1'
end
def self.server_uri
"http://#{server_interface}:#{server_port}"
end
def self.server_spec_path
self.server_uri + '/__JHW__/'
end
def self.ensure_server(options)
return if @server
require 'webrick'
require 'thread'
require 'rack'
require 'net/http'
port = server_port
@server = Thread.new do
Jasmine::Headless.warn "Powering up!"
app = Rack::Builder.new do
use IndexHandler
map '/__JHW__' do
run Rack::File.new(Dir.pwd)
end
map '/' do
run Rack::File.new('/')
end
end
Rack::Handler::WEBrick.run(
app,
:Port => port,
:Logger => Logger.new(StringIO.new),
:AccessLog => [
[ StringIO.new, WEBrick::AccessLog::COMMON_LOG_FORMAT ],
[ StringIO.new, WEBrick::AccessLog::REFERER_LOG_FORMAT ]
]
)
end
while true do
begin
Net::HTTP.get(URI(server_uri))
break
rescue Errno::ECONNREFUSED => e
end
sleep 0.1
end end
end end
@ -168,26 +57,23 @@ module Jasmine
command << "-s #{options[:seed]}" command << "-s #{options[:seed]}"
command << '-c' if options[:colors] command << '-c' if options[:colors]
command << '-q' if options[:quiet]
options.file_reporters.each do |reporter, identifier, file| options.file_reporters.each do |reporter, identifier, file|
command << "-r #{file}" command << "-r #{file}"
end end
command += targets command += targets
command.compact.join(' ') command.compact.join(' ')
end end
def run def run
Jasmine::Headless::CacheableAction.enabled = @options[:enable_cache] Jasmine::Headless::CacheableAction.enabled = @options[:enable_cache]
Jasmine::Headless.show_warnings = !@options[:quiet]
FilesList.reset! FilesList.reset!
self.class.server_port = options[:server_port]
@_targets = template_writer.write @_targets = template_writer.write
run_targets = absolute_run_targets(@_targets.dup) run_targets = @_targets.dup
if run_targets.length == 2 if run_targets.length == 2
if (!@options[:full_run] && files_list.filtered?) || files_list.has_spec_outside_scope? if (!@options[:full_run] && files_list.filtered?) || files_list.has_spec_outside_scope?
@ -195,13 +81,7 @@ module Jasmine
end end
end end
runner = lambda { system jasmine_command(run_targets) } system jasmine_command(run_targets)
if options[:use_server]
wrap_in_server(run_targets, &runner)
else
runner.call
end
@_status = $?.exitstatus @_status = $?.exitstatus
ensure ensure
@ -210,17 +90,6 @@ module Jasmine
end end
end end
def absolute_run_targets(targets)
targets.flatten.collect do |target|
if options[:use_server]
target = self.class.server_spec_path + target
else
target = "file://" + File.expand_path(target)
end
target
end
end
def runner_filename def runner_filename
options[:runner_output_filename] || begin options[:runner_output_filename] || begin
if (runner_output = jasmine_config['runner_output']) && !runner_output.empty? if (runner_output = jasmine_config['runner_output']) && !runner_output.empty?
@ -240,15 +109,6 @@ module Jasmine
) )
end end
def wrap_in_server(run_targets)
self.class.ensure_server(options)
IndexHandler.index = run_targets.last
Jasmine::Headless.warn "HTTP powered specs! Located at #{run_targets.join(' ')}"
yield
end
private private
def jasmine_config_data def jasmine_config_data
raise JasmineConfigNotFound.new("Jasmine config not found. I tried #{@options[:jasmine_config]}.") if !File.file?(@options[:jasmine_config]) raise JasmineConfigNotFound.new("Jasmine config not found. I tried #{@options[:jasmine_config]}.") if !File.file?(@options[:jasmine_config])

View File

@ -33,11 +33,11 @@ module Jasmine::Headless
end end
def serialize(data) def serialize(data)
MultiJson.dump(data) MultiJson.encode(data)
end end
def unserialize(data) def unserialize(data)
MultiJson.load(data) MultiJson.decode(data)
end end
end end
end end

View File

@ -14,9 +14,23 @@ module Jasmine
desc 'Run Jasmine specs headlessly' desc 'Run Jasmine specs headlessly'
task(name) { run_rake_task } task(name) { run_rake_task }
create_rails_compliant_task if defined?(Rails)
end end
private private
def create_rails_compliant_task
if Rails.respond_to?(:version) && Rails.version >= "3.1.0"
task 'assets:precompile:for_testing' => :environment do
$stderr.puts "This task is deprecated and will be removed after 2012-01-01"
Rails.application.assets.digest_class = Digest::JasmineTest
Rake::Task['assets:precompile'].invoke
end
end
end
def run_rake_task def run_rake_task
case Jasmine::Headless::Runner.run( case Jasmine::Headless::Runner.run(
:colors => colors, :colors => colors,

View File

@ -24,9 +24,7 @@ module Jasmine::Headless
output.unshift([filtered_tests_filename, files_list.filtered_files_to_html ]) if files_list.filtered? output.unshift([filtered_tests_filename, files_list.filtered_files_to_html ]) if files_list.filtered?
output.each do |name, files| output.each do |name, files|
template = template_for(files) File.open(name, 'w') { |fh| fh.print template_for(files) }
File.open(name, 'wb') { |fh| fh.print template }
end end
output.collect(&:first) output.collect(&:first)

View File

@ -3,7 +3,7 @@ module Jasmine::Headless
def <<(asset) def <<(asset)
raise InvalidUniqueAsset.new("Not an asset: #{asset.inspect}") if !asset.respond_to?(:logical_path) raise InvalidUniqueAsset.new("Not an asset: #{asset.inspect}") if !asset.respond_to?(:logical_path)
super if !self.any? { |other| asset.pathname == other.pathname } super if !self.any? { |other| asset.logical_path == other.logical_path }
end end
def flatten def flatten

View File

@ -1,5 +1,5 @@
module Jasmine module Jasmine
module Headless module Headless
VERSION = "0.9.0.rc.2" VERSION = "0.8.4"
end end
end end

View File

@ -1,4 +0,0 @@
#!/bin/bash
penchant gemfile remote --switch-back

View File

@ -2,9 +2,9 @@
OLD_GIT_DIR=$GIT_DIR OLD_GIT_DIR=$GIT_DIR
if [ "$(penchant gemfile-env)" != "remote deployment" ]; then if [ "$(penchant gemfile-env)" != "remote" ]; then
unset GIT_DIR unset GIT_DIR
penchant gemfile remote --deployment penchant gemfile remote
GIT_DIR=$OLD_GIT_DIR GIT_DIR=$OLD_GIT_DIR
git add Gemfile* git add Gemfile*
fi fi

View File

@ -5,7 +5,7 @@ if File.file?('Gemfile.erb')
Dir.chdir '..' do Dir.chdir '..' do
File.readlines(File.join(pwd, 'Gemfile.erb')).find_all { |line| line[':git'] }.each do |line| File.readlines(File.join(pwd, 'Gemfile.erb')).find_all { |line| line[':git'] }.each do |line|
repo = line[%r{:git => (['"])([^'"]+)\1}, 2] repo = line[%r{:git => (['"])(.*)\1}, 2]
puts "Installing #{repo}" puts "Installing #{repo}"
system %{git clone #{repo}} system %{git clone #{repo}}

View File

@ -6,7 +6,7 @@
<script type="text/javascript" src="<%= Jasmine::Headless.root.join('vendor/assets/javascripts/prolog.js') %>"></script> <script type="text/javascript" src="<%= Jasmine::Headless.root.join('vendor/assets/javascripts/prolog.js') %>"></script>
<%= files.join("\n") %> <%= files.join("\n") %>
<script type="text/javascript"> <script type="text/javascript">
if (window.JHW) { HeadlessReporterResult.specLineNumbers = <%= MultiJson.dump(spec_lines) %>; } if (window.JHW) { HeadlessReporterResult.specLineNumbers = <%= MultiJson.encode(spec_lines) %>; }
</script> </script>
</head> </head>
<body> <body>
@ -34,39 +34,6 @@
break; break;
} }
} }
var location = window.location.href;
var getLastModified = function(callback) {
var http = new XMLHttpRequest();
var header;
http.open('HEAD', location, true);
http.onreadystatechange = function() {
if(http.readyState === http.DONE) {
callback(http.getResponseHeader('Last-Modified'));
}
};
http.send();
}
getLastModified(function(currentLastModified) {
var checker;
checker = function() {
setTimeout(function() {
getLastModified(function(newLastModified) {
if (currentLastModified != newLastModified) {
setTimeout(function() { window.location.reload(); }, 1000);
} else {
checker();
}
});
}, 3000);
};
checker();
});
} }
jasmine.getEnv().execute(); jasmine.getEnv().execute();

View File

@ -1,8 +0,0 @@
src_dir: spec/jasmine/noisy
src_files:
- '**/*'
spec_dir: spec/jasmine/noisy
spec_files:
- '**/*'

View File

@ -1,2 +0,0 @@
window.prompt("hello");

View File

@ -1,2 +0,0 @@
//= require app-file
//

View File

@ -1,7 +0,0 @@
src_dir: spec/jasmine/two_files_from_src_files/app
asset_paths:
- "spec/jasmine/two_files_from_src_files/vendor"
src_files: [ 'vendor.js', 'app.js' ]

View File

@ -1,2 +0,0 @@
//= require vendor-file
//

View File

@ -1,6 +0,0 @@
src_dir: spec/jasmine/two_spec_files_same_basename
src_files: []
spec_dir: spec/jasmine/two_spec_files_same_basename
spec_files: [ "**/*.{js,coffee}" ]

View File

@ -1,4 +0,0 @@
describe 'two', ->
it 'should pass', ->
expect(true).toEqual(true)

View File

@ -1,6 +0,0 @@
describe("one", function() {
it('should pass', function() {
expect(true).toEqual(true);
});
});

View File

@ -1,2 +0,0 @@
window.prompt("Yes! Hi!");

View File

@ -1,4 +0,0 @@
src_dir: spec/jasmine/window_prompt
src_files:
- '**/*.js'

View File

@ -1,35 +0,0 @@
describe 'jasmine.HeadlessReporter.ConsoleBase', ->
reporter = null
beforeEach ->
reporter = new jasmine.HeadlessReporter.ConsoleBase()
describe '#formatResultLine', ->
context 'length = 1', ->
it 'should format', ->
reporter.length = 1
expect(reporter.formatResultLine(0)).toMatch(/test,/)
context 'length != 1', ->
it 'should format', ->
reporter.length = 2
expect(reporter.formatResultLine(0)).toMatch(/tests,/)
context 'failedCount = 1', ->
it 'should format', ->
reporter.failedCount = 1
expect(reporter.formatResultLine(0)).toMatch(/failure,/)
context 'failedCount != 1', ->
it 'should format', ->
reporter.failedCount = 0
expect(reporter.formatResultLine(0)).toMatch(/failures,/)
context 'runtime = 1', ->
it 'should format', ->
expect(reporter.formatResultLine(1)).toMatch(/sec./)
context 'runtime != 1', ->
it 'should format', ->
expect(reporter.formatResultLine(0)).toMatch(/secs./)

View File

@ -1,3 +1,35 @@
describe 'jasmine.HeadlessReporter.Console', -> describe 'jasmine.HeadlessReporter', ->
describe '#reportSpecResults', -> reporter = null
beforeEach ->
reporter = new jasmine.HeadlessReporter.Console()
describe '#formatResultLine', ->
context 'length = 1', ->
it 'should format', ->
reporter.length = 1
expect(reporter.formatResultLine(0)).toMatch(/test,/)
context 'length != 1', ->
it 'should format', ->
reporter.length = 2
expect(reporter.formatResultLine(0)).toMatch(/tests,/)
context 'failedCount = 1', ->
it 'should format', ->
reporter.failedCount = 1
expect(reporter.formatResultLine(0)).toMatch(/failure,/)
context 'failedCount != 1', ->
it 'should format', ->
reporter.failedCount = 0
expect(reporter.formatResultLine(0)).toMatch(/failures,/)
context 'runtime = 1', ->
it 'should format', ->
expect(reporter.formatResultLine(1)).toMatch(/sec./)
context 'runtime != 1', ->
it 'should format', ->
expect(reporter.formatResultLine(0)).toMatch(/secs./)

View File

@ -95,28 +95,5 @@ describe Jasmine::Headless::CacheableAction do
end end
end end
end end
describe '#relative_cache_file' do
context 'file is an absolute windows file' do
let(:current_path) { 'C:/path' }
let(:filename) { "file.coffee" }
let(:windows_path) { File.join(current_path, filename) }
let(:cache_dir) { 'cache dir' }
let(:cache_type) { 'cache type' }
before do
cache_object.stubs(:file).returns(windows_path)
described_class.stubs(:cache_dir).returns(cache_dir)
described_class.stubs(:cache_type).returns(cache_type)
Dir.stubs(:pwd).returns(current_path)
end
subject { cache_object.relative_cache_file }
it { should == File.join(cache_dir, cache_type, filename) }
end
end
end end

View File

@ -1,41 +1,25 @@
require 'spec_helper' require 'spec_helper'
describe Jasmine::Headless::FileChecker do describe Jasmine::Headless::FileChecker do
include FakeFS::SpecHelpers
let(:test_class) do let(:test_class) do
object = Object.new object = Object.new
object.class.send(:include, Jasmine::Headless::FileChecker) object.class.send(:include, Jasmine::Headless::FileChecker)
object object
end end
describe "#bad_format?" do context "bad_format?" do
subject { test_class.bad_format?(file) } it "should return false wth correct format" do
test_class.bad_format?('foobar.js').should be_false
before do
test_class.stubs(:excluded_formats).returns(%w{erb string})
end end
context 'nil' do it "should return false wth wrong format" do
let(:file) { nil } test_class.bad_format?('foobar.js.erb').should be_true
it { should be_nil }
end end
context 'allowed format' do it "should check for the whole extension" do
let(:file) { 'foobar.js' } test_class.bad_format?('foobar.string.js').should be_false
it { should be_false }
end
context 'unallowed format' do
let(:file) { 'foobar.erb' }
it { should be_true }
end
context 'check whole extension' do
let(:file) { 'foobar.string.js' }
it { should be_true }
end end
end end
end end

View File

@ -5,6 +5,50 @@ require 'coffee-script'
describe Jasmine::Headless::FilesList do describe Jasmine::Headless::FilesList do
let(:files_list) { described_class.new } let(:files_list) { described_class.new }
describe '.get_paths_from_gemspec' do
include FakeFS::SpecHelpers
let(:gem_dir) { "dir" }
let(:gemspec) { stub(:gem_dir => gem_dir) }
let(:paths) do
%w{vendor lib app}.collect do |dir|
File.join(gem_dir, dir, 'assets/javascripts')
end
end
before do
paths.each { |path| FileUtils.mkdir_p path }
described_class.instance_variable_set(:@asset_paths, [])
end
subject { described_class.get_paths_from_gemspec(gemspec) }
it { should =~ paths }
end
describe '.asset_paths' do
include FakeFS::SpecHelpers
let(:dir_one) { 'dir_one' }
let(:dir_two) { 'dir_two' }
let(:gem_one) { stub(:gem_dir => dir_one) }
let(:gem_two) { stub(:gem_dir => dir_two) }
before do
described_class.instance_variable_set(:@asset_paths, nil)
FileUtils.mkdir_p File.join(dir_two, 'vendor/assets/javascripts')
Gem::Specification.stubs(:_all).returns([gem_one, gem_two])
end
it 'should return all matching gems with vendor/assets/javascripts directories' do
described_class.asset_paths.should == [ File.join(dir_two, 'vendor/assets/javascripts') ]
end
end
describe '#initialize' do describe '#initialize' do
before do before do
described_class.any_instance.stubs(:load_initial_assets) described_class.any_instance.stubs(:load_initial_assets)
@ -174,21 +218,6 @@ describe Jasmine::Headless::FilesList do
files_list.files.any? { |file| file['.erb'] }.should be_false files_list.files.any? { |file| file['.erb'] }.should be_false
end end
end end
describe "#register_engine!" do
before(:each) do
Jasmine::Headless::FilesList.reset!
end
it "should register code added via configure blocks" do
template_class = mock()
described_class.register_engine ".foo", template_class
Sprockets.expects(:register_engine).with(".foo", template_class)
described_class.new
end
end
end end
end end

View File

@ -91,15 +91,6 @@ describe Jasmine::Headless::Runner do
it_should_have_basics it_should_have_basics
it { should include("-r #{file}") } it { should include("-r #{file}") }
end end
context 'quiet' do
before do
options[:quiet] = true
end
it_should_have_basics
it { should include("-q") }
end
end end
describe '#runner_filename' do describe '#runner_filename' do
@ -194,54 +185,4 @@ describe Jasmine::Headless::Runner do
subject.options[:reporters].should == reporters subject.options[:reporters].should == reporters
end end
end end
describe '.server_port' do
before do
described_class.instance_variable_set(:@server_port, nil)
end
context 'port in use' do
require 'socket'
before do
described_class.stubs(:select_server_port).returns(5000, 5001)
end
it 'should try another port' do
server = TCPServer.new(described_class.server_interface, 5000)
described_class.server_port.should == 5001
end
end
end
describe '#absolute_run_targets' do
let(:opts) { {} }
subject { runner.absolute_run_targets(targets) }
let(:targets) { [ target ] }
let(:target) { 'target' }
before do
runner.stubs(:options).returns(:use_server => use_server)
end
context 'server' do
let(:use_server) { true }
let(:server_spec_path) { 'server spec path' }
before do
described_class.stubs(:server_spec_path).returns(server_spec_path)
end
it { should == [ server_spec_path + target ] }
end
context 'no server' do
let(:use_server) { false }
it { should == [ 'file://' + File.expand_path(target) ] }
end
end
end end

View File

@ -3,9 +3,9 @@ require 'spec_helper'
describe Jasmine::Headless::UniqueAssetList do describe Jasmine::Headless::UniqueAssetList do
let(:list) { described_class.new } let(:list) { described_class.new }
let(:first) { stub(:logical_path => 'one', :pathname => 'one') } let(:first) { stub(:logical_path => 'one') }
let(:second) { stub(:logical_path => 'two', :pathname => 'two') } let(:second) { stub(:logical_path => 'two') }
let(:third) { stub(:logical_path => 'two', :pathname => 'two') } let(:third) { stub(:logical_path => 'two') }
it 'should raise an exception on a non-asset' do it 'should raise an exception on a non-asset' do
expect { list << "whatever" }.to raise_error(StandardError) expect { list << "whatever" }.to raise_error(StandardError)

View File

@ -1,38 +1,2 @@
require 'spec_helper' require 'spec_helper'
describe Jasmine::Headless do
describe '.warn' do
let(:output) { StringIO.new }
before do
described_class.stubs(:output).returns(output)
end
context 'warnings enabled' do
before do
described_class.stubs(:show_warnings?).returns(true)
end
it 'should work' do
described_class.warn("warning")
output.rewind
output.read.should == "warning\n"
end
end
context 'warnings disabled' do
before do
described_class.stubs(:show_warnings?).returns(false)
end
it 'should work' do
described_class.warn("warning")
output.rewind
output.read.should == ""
end
end
end
end

View File

@ -11,16 +11,16 @@ window.Intense = {
methods: methods:
foreground: (color) -> foreground: (color) ->
if Intense.useColors if Intense.useColors
'\x1b' + "[3#{Intense.colors[color]}m#{this}" + '\x1b' + "[0m" "\033[3#{Intense.colors[color]}m#{this}\033[0m"
else else
this this
bright: -> bright: ->
if Intense.useColors if Intense.useColors
'\x1b' + "[1m#{this}" + '\x1b' + "[0m" "\033[1m#{this}\033[0m"
else else
this this
useColors: true useColors: true
moveBack: (count = 1) -> '\x1b' + "[#{count}D" moveBack: (count = 1) -> "\033[#{count}D"
} }
for method, code of Intense.methods for method, code of Intense.methods

View File

@ -30,7 +30,15 @@ if window.JHW
this.env.reporter.reportSpecResults(this) this.env.reporter.reportSpecResults(this)
jasmine.Spec.prototype.fail = (e) -> jasmine.Spec.prototype.fail = (e) ->
e = JHW.createCoffeeScriptFileException(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({ expectationResult = new jasmine.ExpectationResult({
passed: false, passed: false,
@ -39,8 +47,6 @@ if window.JHW
}) })
@results_.addResult(expectationResult) @results_.addResult(expectationResult)
this.env.reporter.reportException(e)
jasmine.NestedResults.isValidSpecLine = (line) -> jasmine.NestedResults.isValidSpecLine = (line) ->
line.match(/^\s*expect/) != null || line.match(/^\s*return\s*expect/) != null line.match(/^\s*expect/) != null || line.match(/^\s*return\s*expect/) != null
@ -86,7 +92,7 @@ if window.JHW
this.addResult_(result) this.addResult_(result)
for method in [ "reportSpecWaiting", "reportSpecRunning", "reportException" ] for method in [ "reportSpecWaiting", "reportSpecRunning" ]
generator = (method) -> generator = (method) ->
(args...) -> (args...) ->
for reporter in @subReporters_ for reporter in @subReporters_

View File

@ -1,25 +1,12 @@
#= require jasmine.HeadlessReporter #= require jasmine.HeadlessReporter.js
#
class jasmine.HeadlessReporter.ConsoleBase extends jasmine.HeadlessReporter class jasmine.HeadlessReporter.Console extends jasmine.HeadlessReporter
constructor: (@callback = null) -> constructor: (@callback = null) ->
super(@callback) super(@callback)
@position = 0 @position = 0
@positions = "|/-\\" @positions = "|/-\\"
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(' ')
reportRunnerResults: (runner) -> reportRunnerResults: (runner) ->
super() super()
@ -41,6 +28,27 @@ class jasmine.HeadlessReporter.ConsoleBase extends jasmine.HeadlessReporter
super(runner) super(runner)
this.puts("\nRunning Jasmine specs...".bright()) if !this.hasError() this.puts("\nRunning Jasmine specs...".bright()) if !this.hasError()
reportSpecResults: (spec) ->
super(spec)
this._reportSpecResult(spec, {
success: (results) =>
this.print('.'.foreground('green'))
failure: (results) =>
this.print('F'.foreground('red'))
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)
})
reportSpecWaiting: -> reportSpecWaiting: ->
if !@timer if !@timer
@timer = true @timer = true
@ -54,28 +62,18 @@ class jasmine.HeadlessReporter.ConsoleBase extends jasmine.HeadlessReporter
@timer = null @timer = null
this.print(Intense.moveBack()) this.print(Intense.moveBack())
reportSpecResults: (spec) -> formatResultLine: (runtime) ->
super(spec) line = []
line.push(@length)
line.push((if @length == 1 then "test" else "tests") + ',')
this._reportSpecResult(spec, { line.push(@failedCount)
success: (results) => line.push((if @failedCount == 1 then "failure" else "failures") + ',')
this.displaySuccess(spec)
failure: (results) =>
this.displayFailure(spec)
this.reportFailureResult(results, new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName())) line.push(runtime)
}) line.push((if runtime == 1.0 then "sec" else "secs") + '.')
reportFailureResult: (results, failureResult) -> line.join(' ')
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)
_waitRunner: => _waitRunner: =>
@timer = setTimeout( @timer = setTimeout(
@ -89,4 +87,3 @@ class jasmine.HeadlessReporter.ConsoleBase extends jasmine.HeadlessReporter
this._waitRunner() this._waitRunner()
, 750 , 750
) )

View File

@ -1,4 +1,4 @@
#= require jasmine.HeadlessReporter #= require jasmine.HeadlessReporter.js
# #
class jasmine.HeadlessReporter.File extends jasmine.HeadlessReporter class jasmine.HeadlessReporter.File extends jasmine.HeadlessReporter
reportRunnerResults: (runner) -> reportRunnerResults: (runner) ->

View File

@ -1,4 +1,4 @@
#= require jasmine.HeadlessReporter #= require jasmine.HeadlessReporter.js
class jasmine.HeadlessReporter.Tap extends jasmine.HeadlessReporter class jasmine.HeadlessReporter.Tap extends jasmine.HeadlessReporter
constructor: (@outputTarget = null) -> constructor: (@outputTarget = null) ->

View File

@ -29,15 +29,12 @@ if window.JHW
puts = (message) -> puts = (message) ->
JHW.print('stdout', message + "\n") JHW.print('stdout', message + "\n")
warn = (message) ->
puts(message) if !JHW.isQuiet()
# handle unloading # handle unloading
window.onbeforeunload = (e) -> window.onbeforeunload = (e) ->
e = e || window.event e = e || window.event
JHW.hasError() JHW.hasError()
warn "The code tried to leave the test page. Check for unhandled form submits and link clicks." puts "The code tried to leave the test page. Check for unhandled form submits and link clicks."
e.returnValue = 'string' if e e.returnValue = 'string' if e
@ -51,18 +48,13 @@ if window.JHW
false false
# dialogs # dialogs
window.confirm = -> window.confirm = (message) ->
warn "#{"[confirm]".foreground('red')} You should mock window.confirm. Returning true." puts "#{"[confirm]".foreground('red')} jasmine-headless-webkit can't handle confirm() yet! You should mock window.confirm. Returning true."
true
window.prompt = ->
warn "#{"[prompt]".foreground('red')} You should mock window.prompt. Returning true."
true true
window.alert = (message) -> window.alert = (message) ->
warn "[alert] ".foreground('red') + message puts "[alert] ".foreground('red') + message
# color support # color support
JHW._setColors = (useColors) -> Intense.useColors = useColors JHW._setColors = (useColors) -> Intense.useColors = useColors
@ -79,22 +71,6 @@ if window.JHW
puts msg puts msg
JHW.createCoffeeScriptFileException = (e) ->
if e and e.sourceURL
filename = e.sourceURL.split('/').pop()
e =
name: e.name
message: e.message
sourceURL: e.sourceURL
lineNumber: e.line
if window.CoffeeScriptToFilename and realFilename = window.CoffeeScriptToFilename[filename]
e.sourceURL = realFilename
e.lineNumber = "~" + String(e.line)
e
window.CoffeeScriptToFilename = {} window.CoffeeScriptToFilename = {}
window.CSTF = window.CoffeeScriptToFilename window.CSTF = window.CoffeeScriptToFilename

View File

@ -1,4 +1,3 @@
(function() {
window.HeadlessReporterResult = (function() { window.HeadlessReporterResult = (function() {
@ -75,5 +74,3 @@
return HeadlessReporterResult; return HeadlessReporterResult;
})(); })();
}).call(this);

44
vendor/assets/javascripts/intense.js vendored Normal file
View File

@ -0,0 +1,44 @@
(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) {
if (Intense.useColors) {
return "\033[3" + Intense.colors[color] + "m" + this + "\033[0m";
} else {
return this;
}
},
bright: function() {
if (Intense.useColors) {
return "\033[1m" + this + "\033[0m";
} else {
return this;
}
}
},
useColors: true,
moveBack: function(count) {
if (count == null) count = 1;
return "\033[" + count + "D";
}
};
_ref = Intense.methods;
for (method in _ref) {
code = _ref[method];
String.prototype[method] = code;
}
}).call(this);

View File

@ -0,0 +1,129 @@
(function() {
var generator, getSplitName, method, pauseAndRun, _i, _len, _ref;
var __slice = Array.prototype.slice;
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.finishCallback = function() {
JHW.ping();
return this.env.reporter.reportSpecResults(this);
};
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();
jasmine.getEnv().reporter.reportSpecWaiting();
return this._execute(function() {
jasmine.getEnv().reporter.reportSpecRunning();
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);
};
_ref = ["reportSpecWaiting", "reportSpecRunning"];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
method = _ref[_i];
generator = function(method) {
return function() {
var args, reporter, _j, _len2, _ref2, _results;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
_ref2 = this.subReporters_;
_results = [];
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
reporter = _ref2[_j];
if (reporter[method] != null) {
_results.push(reporter[method].apply(reporter, args));
} else {
_results.push(void 0);
}
}
return _results;
};
};
jasmine.MultiReporter.prototype[method] = generator(method);
}
}
}
}).call(this);

View File

@ -1,8 +0,0 @@
#= require jasmine.HeadlessReporter.ConsoleBase
#
class jasmine.HeadlessReporter.Console extends jasmine.HeadlessReporter.ConsoleBase
displaySuccess: (spec) =>
this.print('.'.foreground('green'))
displayFailure: (spec) =>
this.print('F'.foreground('red'))

View File

@ -0,0 +1,115 @@
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
jasmine.HeadlessReporter.Console = (function() {
__extends(Console, jasmine.HeadlessReporter);
function Console(callback) {
this.callback = callback != null ? callback : null;
this._waitRunner = __bind(this._waitRunner, this);
Console.__super__.constructor.call(this, this.callback);
this.position = 0;
this.positions = "|/-\\";
}
Console.prototype.reportRunnerResults = function(runner) {
var result, resultLine, _i, _len, _ref;
Console.__super__.reportRunnerResults.call(this);
this.print("\n");
resultLine = this.formatResultLine(this._runtime());
if (this.failedCount === 0) {
this.puts(("PASS: " + resultLine).foreground('green'));
} else {
this.puts(("FAIL: " + resultLine).foreground('red'));
}
_ref = this.results;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
result = _ref[_i];
this.puts(result.toString());
}
return this.puts("\nTest ordering seed: --seed " + (JHW.getSeed()));
};
Console.prototype.reportRunnerStarting = function(runner) {
Console.__super__.reportRunnerStarting.call(this, runner);
if (!this.hasError()) {
return this.puts("\nRunning Jasmine specs...".bright());
}
};
Console.prototype.reportSpecResults = function(spec) {
var _this = this;
Console.__super__.reportSpecResults.call(this, spec);
return this._reportSpecResult(spec, {
success: function(results) {
return _this.print('.'.foreground('green'));
},
failure: function(results) {
var failureResult, foundLine, result, testCount, _i, _len, _ref;
_this.print('F'.foreground('red'));
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);
}
});
};
Console.prototype.reportSpecWaiting = function() {
if (!this.timer) {
this.timer = true;
this.first = true;
return this._waitRunner();
}
};
Console.prototype.reportSpecRunning = function() {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
return this.print(Intense.moveBack());
}
};
Console.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(' ');
};
Console.prototype._waitRunner = function() {
var _this = this;
return this.timer = setTimeout(function() {
if (_this.timer) {
if (!_this.first) _this.print(Intense.moveBack());
_this.print(_this.positions.substr(_this.position, 1).foreground('yellow'));
_this.position += 1;
_this.position %= _this.positions.length;
_this.first = false;
return _this._waitRunner();
}
}, 750);
};
return Console;
})();
}).call(this);

View File

@ -0,0 +1,41 @@
(function() {
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
jasmine.HeadlessReporter.File = (function() {
__extends(File, jasmine.HeadlessReporter);
function File() {
File.__super__.constructor.apply(this, arguments);
}
File.prototype.reportRunnerResults = function(runner) {
var output;
File.__super__.reportRunnerResults.call(this, runner);
output = "TOTAL||" + this.length + "||" + this.failedCount + "||" + (this._runtime()) + "||" + (JHW._hasErrors ? "T" : "F");
this.puts(output);
return this.puts("SEED||" + (JHW.getSeed()));
};
File.prototype.consoleLogUsed = function(msg) {
return this.puts("CONSOLE||" + msg);
};
File.prototype.reportSpecResults = function(spec) {
var _this = this;
File.__super__.reportSpecResults.call(this, spec);
return this._reportSpecResult(spec, {
success: function(results) {
return _this.puts("PASS||" + spec.getJHWSpecInformation());
},
failure: function(results) {
return _this.puts("FAIL||" + spec.getJHWSpecInformation());
}
});
};
return File;
})();
}).call(this);

View File

@ -0,0 +1,40 @@
(function() {
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
jasmine.HeadlessReporter.Tap = (function() {
__extends(Tap, jasmine.HeadlessReporter);
function Tap(outputTarget) {
this.outputTarget = outputTarget != null ? outputTarget : null;
Tap.__super__.constructor.call(this, this.outputTarget);
this.output = [];
}
Tap.prototype.reportRunnerResults = function(runner) {
Tap.__super__.reportRunnerResults.call(this, runner);
if (this.output.length > 0) this.output.unshift("1.." + this.output.length);
return this.puts(this.output.join("\n"));
};
Tap.prototype.reportSpecResults = function(spec) {
var description, index;
var _this = this;
Tap.__super__.reportSpecResults.call(this, spec);
index = this.output.length + 1;
description = spec.getSpecSplitName().join(' ');
return this._reportSpecResult(spec, {
success: function(results) {
return _this.output.push("ok " + index + " " + description);
},
failure: function(results) {
return _this.output.push("not ok " + index + " " + description);
}
});
};
return Tap;
})();
}).call(this);

View File

@ -1,64 +0,0 @@
#= require jasmine.HeadlessReporter.ConsoleBase
#
class jasmine.HeadlessReporter.Verbose extends jasmine.HeadlessReporter.ConsoleBase
@prereport = false
displaySuccess: (spec) =>
this.displaySpec(spec, 'green')
displayFailure: (spec) =>
this.displaySpec(spec, 'red')
displaySpec: (spec, color) =>
currentLastNames = (@lastNames || []).slice(0)
@lastNames = spec.getSpecSplitName()
for line in this.indentSpec(@lastNames, currentLastNames, color)
if line? and !_.isEmpty(line)
this.puts(line)
indentSpec: (current, last, color) =>
last = last.slice(0)
lines = []
for name in current
if last.shift() != name
lines.push(name)
else
lines.push(null)
this.indentLines(lines, color)
indentLines: (lines, color) =>
indent = ''
output = []
for line in lines
if line?
outputLine = indent
outputLine += this.colorLine(line, color)
output.push(outputLine)
indent += ' '
output
colorLine: (line, color) =>
line.foreground(color)
reportSpecStarting: (spec) =>
if jasmine.HeadlessReporter.Verbose.prereport
this.puts(spec.getSpecSplitName().join(' '))
reportException: (e) =>
e = JHW.createCoffeeScriptFileException(e)
if e.sourceURL && e.lineNumber
output = "#{e.sourceURL}:#{e.lineNumber} #{e.message}"
else
output = e.message ? e
this.puts(output.foreground('yellow'))

View File

@ -0,0 +1,77 @@
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
if (!(typeof jasmine !== "undefined" && jasmine !== null)) {
throw new Error("jasmine not loaded!");
}
jasmine.HeadlessReporter = (function() {
function HeadlessReporter(outputTarget) {
this.outputTarget = outputTarget != null ? outputTarget : null;
this.puts = __bind(this.puts, this);
this.print = __bind(this.print, this);
this.results = [];
this.failedCount = 0;
this.length = 0;
this.timer = null;
}
HeadlessReporter.prototype.hasError = function() {
return JHW._hasErrors;
};
HeadlessReporter.prototype.reportSpecStarting = function(spec) {
if (this.hasError()) {
spec.finish();
return spec.suite.finish();
}
};
HeadlessReporter.prototype.reportSuiteResults = function(suite) {};
HeadlessReporter.prototype.reportRunnerStarting = function(runner) {
return this.startTime = new Date();
};
HeadlessReporter.prototype.reportRunnerResults = function(runner) {
if (this.hasError()) return;
if (this.failedCount !== 0) JHW.hasSpecFailure();
JHW.finishSuite();
if (window.JHW) return window.onbeforeunload = null;
};
HeadlessReporter.prototype.reportSpecResults = function(spec) {
if (this.hasError()) return;
return JHW.ping();
};
HeadlessReporter.prototype._reportSpecResult = function(spec, options) {
var results;
results = spec.results();
this.length++;
if (results.passed()) {
return options.success(results, spec);
} else {
this.failedCount++;
return options.failure(results, spec);
}
};
HeadlessReporter.prototype._runtime = function() {
return (new Date() - this.startTime) / 1000.0;
};
HeadlessReporter.prototype.print = function(output) {
return JHW.print(this.outputTarget, output);
};
HeadlessReporter.prototype.puts = function(output) {
return JHW.print(this.outputTarget, output + "\n");
};
return HeadlessReporter;
})();
}).call(this);

View File

@ -1,5 +1,5 @@
(function() { (function() {
var puts, warn; var puts;
if (window.JHW) { if (window.JHW) {
window.console = { window.console = {
@ -40,13 +40,10 @@
puts = function(message) { puts = function(message) {
return JHW.print('stdout', message + "\n"); return JHW.print('stdout', message + "\n");
}; };
warn = function(message) {
if (!JHW.isQuiet()) return puts(message);
};
window.onbeforeunload = function(e) { window.onbeforeunload = function(e) {
e = e || window.event; e = e || window.event;
JHW.hasError(); JHW.hasError();
warn("The code tried to leave the test page. Check for unhandled form submits and link clicks."); puts("The code tried to leave the test page. Check for unhandled form submits and link clicks.");
if (e) e.returnValue = 'string'; if (e) e.returnValue = 'string';
return 'string'; return 'string';
}; };
@ -56,16 +53,12 @@
JHW._hasErrors = true; JHW._hasErrors = true;
return false; return false;
}; };
window.confirm = function() { window.confirm = function(message) {
warn("" + ("[confirm]".foreground('red')) + " You should mock window.confirm. Returning true."); puts("" + ("[confirm]".foreground('red')) + " jasmine-headless-webkit can't handle confirm() yet! You should mock window.confirm. Returning true.");
return true;
};
window.prompt = function() {
warn("" + ("[prompt]".foreground('red')) + " You should mock window.prompt. Returning true.");
return true; return true;
}; };
window.alert = function(message) { window.alert = function(message) {
return warn("[alert] ".foreground('red') + message); return puts("[alert] ".foreground('red') + message);
}; };
JHW._setColors = function(useColors) { JHW._setColors = function(useColors) {
return Intense.useColors = useColors; return Intense.useColors = useColors;
@ -82,23 +75,6 @@
JHW._usedConsole = true; JHW._usedConsole = true;
return puts(msg); return puts(msg);
}; };
JHW.createCoffeeScriptFileException = function(e) {
var filename, realFilename;
if (e && e.sourceURL) {
filename = e.sourceURL.split('/').pop();
e = {
name: e.name,
message: e.message,
sourceURL: e.sourceURL,
lineNumber: e.line
};
if (window.CoffeeScriptToFilename && (realFilename = window.CoffeeScriptToFilename[filename])) {
e.sourceURL = realFilename;
e.lineNumber = "~" + String(e.line);
}
}
return e;
};
} }
window.CoffeeScriptToFilename = {}; window.CoffeeScriptToFilename = {};