even more flowerbox fun

This commit is contained in:
John Bintz 2012-03-14 19:53:04 -04:00
parent e6bdbf6313
commit d8ef63be6a
15 changed files with 265 additions and 148 deletions

View File

@ -4,16 +4,16 @@ require 'flowerbox'
require 'thor' require 'thor'
class Flowerbox::CLI < Thor class Flowerbox::CLI < Thor
desc "test DIR", "Run the specs found in spec dir, loading spec_helper.rb for configuration details" desc "test DIR FILES...", "Run the specs found in spec dir, loading spec_helper.rb for configuration details"
method_options :pwd => :string, :runners => :string, :runner => :string, :verbose_server => false method_options :pwd => :string, :env_options => nil, :runners => :string, :runner => :string, :verbose_server => false
def test(dir = "spec/javascripts") def test(dir = "spec/javascripts", *files)
Dir.chdir(pwd) do Dir.chdir(pwd) do
exit Flowerbox.run(dir, options.dup) exit Flowerbox.run(dir, options.dup.merge(:files => files))
end end
end end
desc "debug DIR", "Start the Flowerbox server to help debug loading issues." desc "debug DIR", "Start the Flowerbox server to help debug loading issues."
method_options :pwd => :string, :runners => :string, :runner => :string, :verbose_server => false method_options :pwd => :string, :env_options => nil, :runners => :string, :runner => :string, :verbose_server => false
def debug(dir = "spec/javascripts") def debug(dir = "spec/javascripts")
Dir.chdir(pwd) do Dir.chdir(pwd) do
Flowerbox.debug(dir, options.dup) Flowerbox.debug(dir, options.dup)

View File

@ -17,15 +17,21 @@ Flowerbox.World = (code = null) ->
Flowerbox.Matchers = Flowerbox.Matchers =
toEqual: (expected) -> toEqual: (expected) ->
@message = "Expected #{@actual} #{@notMessage} equal #{expected}" @message = "Expected #{@actual} #{@notMessage} equal #{expected}"
@actual == expected if typeof @actual == 'object'
for key, value of @actual
return false if expected[key] != value
for key, value of expected
return false if @actual[key] != value
true
else
@actual == expected
Flowerbox.World -> Flowerbox.World ->
@assert = (what, message = 'failed') -> @assert = (what, message = 'failed') ->
throw new Error(message) if !what throw new Error(message) if !what
@_pending = false
@pending = -> @_pending = true
@expect = (what) -> new Flowerbox.Matcher(what) @expect = (what) -> new Flowerbox.Matcher(what)
@addMatchers = (data) -> Flowerbox.Matcher.addMatchers(data) @addMatchers = (data) -> Flowerbox.Matcher.addMatchers(data)
@ -33,6 +39,20 @@ Flowerbox.World ->
Flowerbox.Matcher.matchers = {} Flowerbox.Matcher.matchers = {}
@addMatchers(Flowerbox.Matchers) @addMatchers(Flowerbox.Matchers)
if Flowerbox.Cucumber.tags
negatedTags = []
for tagSet in Flowerbox.Cucumber.tags
tags = for tag in tagSet.split(',')
if tag.substr(0, 1) == '@'
"~" + tag
else
tag.substr(1)
negatedTags.push(tags)
@around (negatedTags..., runScenario) ->
class Flowerbox.Matcher class Flowerbox.Matcher
@addMatchers: (data) -> @addMatchers: (data) ->
for method, code of data for method, code of data
@ -62,12 +82,15 @@ Flowerbox.Step = (type, match, code) ->
Flowerbox.World.Code ||= [] Flowerbox.World.Code ||= []
Flowerbox.World.Code.push (args..., callback) -> Flowerbox.World.Code.push (args..., callback) ->
this[type] match, (args..., callback) => this[type] match, (args..., callback) =>
_pending = false
@pending = -> _pending = true
result = code.apply(this, args) result = code.apply(this, args)
if result? and result.__prototype__ == Error if result? and result.__prototype__ == Error
callback.fail(result) callback.fail(result)
else else
if @_pending then callback.pending("pending") else callback() if _pending then callback.pending("pending") else callback()
null null

View File

@ -5,7 +5,7 @@ jasmine.Spec.beforeAddMatcherResult().push ->
errorInfo = new Error().stack[3] errorInfo = new Error().stack[3]
@trace = { stack: [ "#{errorInfo.getFileName()}:#{errorInfo.getLineNumber()}" ] } @trace = { stack: "#{errorInfo.getFileName()}:#{errorInfo.getLineNumber()}" }
Error.prepareStackTrace = Error.prepareStackTrace_ Error.prepareStackTrace = Error.prepareStackTrace_

View File

@ -2,16 +2,19 @@ require "flowerbox/version"
require 'flowerbox-delivery' require 'flowerbox-delivery'
require 'rainbow' require 'rainbow'
module Guard
autoload :Flowerbox, 'guard/flowerbox'
end
module Flowerbox module Flowerbox
module CoreExt module CoreExt
autoload :Module, 'flowerbox/core_ext/module' autoload :Module, 'flowerbox/core_ext/module'
end end
autoload :Runner, 'flowerbox/runner' autoload :Runner, 'flowerbox/runner'
autoload :Task, 'flowerbox/task'
module Run
autoload :Base, 'flowerbox/run/base'
autoload :Test, 'flowerbox/run/test'
autoload :Debug, 'flowerbox/run/debug'
end
module Runner module Runner
autoload :Node, 'flowerbox/runner/node' autoload :Node, 'flowerbox/runner/node'
@ -100,115 +103,12 @@ module Flowerbox
@bare_coffeescript ||= true @bare_coffeescript ||= true
end end
def prep(dir, options = {})
reset!
load File.join(dir, 'spec_helper.rb')
require 'coffee_script'
require 'tilt/coffee'
Tilt::CoffeeScriptTemplate.default_bare = Flowerbox.bare_coffeescript
if runners = options[:runners] || options[:runner]
Flowerbox.run_with(runners.split(','))
end
end
def debug(dir, options = {}) def debug(dir, options = {})
options[:debug] = true Flowerbox::Run::Debug.execute(dir, options)
prep(dir, options)
env = Flowerbox.runner_environment.first
env.setup(build_sprockets_for(dir), spec_files_for(dir), options)
Flowerbox.reporters.replace([])
puts "Flowerbox debug server running test prepared for #{env.console_name} on #{env.server.address}"
env.server.start
trap('INT') do
env.server.stop
end
@restart = false
trap('QUIT') do
puts "Restarting Flowerbox server..."
@restart = true
env.server.stop
end
while env.server.alive?
sleep 0.25
end
if @restart
debug(dir, options)
else
puts "Flowerbox finished."
end
end end
def run(dir, options = {}) def run(dir, options = {})
prep(dir, options) Flowerbox::Run::Test.execute(dir, options)
result_set = ResultSet.new
time = 0
realtime = Time.now.to_i
runner_envs = Flowerbox.runner_environment.collect do |env|
env.ensure_configured!
result_set << env.run(build_sprockets_for(dir), spec_files_for(dir), options)
time += env.time
env
end
result_set.print(:time => time, :realtime => Time.now.to_i - realtime)
runner_envs.each(&:cleanup)
result_set.exitstatus
end
def build_sprockets_for(dir)
sprockets = Flowerbox::Delivery::SprocketsHandler.new(
:asset_paths => [
Flowerbox.path.join("lib/assets/javascripts"),
Flowerbox.path.join("vendor/assets/javascripts"),
dir,
Flowerbox.asset_paths
].flatten
)
sprockets.add('flowerbox')
sprockets.add('json2')
Flowerbox.test_environment.inject_into(sprockets)
Flowerbox.additional_files.each { |file| sprockets.add(file) }
sprockets
end
def spec_files_for(dir)
return @spec_files if @spec_files
@spec_files = []
Flowerbox.spec_patterns.each do |pattern|
Dir[File.join(dir, pattern)].each do |file|
@spec_files << File.expand_path(file)
end
end
@spec_files
end end
end end
end end

View File

@ -60,6 +60,12 @@ module Flowerbox
runner.template runner.template
end end
class << self
private
def setup_protetion(builder)
end
end
end end
end end

View File

@ -13,7 +13,7 @@ module Flowerbox::Result
end end
def file def file
first_local_stack[%r{(#{Dir.pwd}.*$)}, 1] first_local_stack[%r{__F__/(.*)$}, 1]
end end
def runner def runner
@ -25,7 +25,7 @@ module Flowerbox::Result
end end
def first_local_stack def first_local_stack
@data['stack'].find { |line| line[File.join(".tmp/sprockets", Dir.pwd)] } || @data['stack'][1] @data['stack'].find { |line| line['__F__'] } || @data['stack'][1]
end end
end end
end end

View File

@ -26,7 +26,7 @@ module Flowerbox::Result::FileInfo
alias :line :line_number alias :line :line_number
def translated_file_and_line def translated_file_and_line
"#{translated_file.gsub(Dir.pwd + '/', '')}:#{line_number}" "#{translated_file.gsub(%r{^/}, '')}:#{line_number}"
end end
end end

View File

@ -41,7 +41,7 @@ module Flowerbox
end end
def exitstatus def exitstatus
@results.empty? ? 0 : 1 results.any?(&:failure?) ? 1 : 0
end end
def print(data = {}) def print(data = {})

79
lib/flowerbox/run/base.rb Normal file
View File

@ -0,0 +1,79 @@
module Flowerbox::Run
class Base
attr_reader :dir, :options
def self.execute(dir, options)
new(dir, options).execute
end
def initialize(dir, options)
@dir, @options = dir, options
end
def execute
raise StandardError.new("override in subclass")
end
def prep!
Flowerbox.reset!
load File.join(dir, 'spec_helper.rb')
require 'coffee_script'
require 'tilt/coffee'
Tilt::CoffeeScriptTemplate.default_bare = Flowerbox.bare_coffeescript
if runners = options[:runners] || options[:runner]
Flowerbox.run_with(runners.split(','))
end
Flowerbox.test_environment.set_additional_options(options[:env_options])
end
def sprockets
sprockets = Flowerbox::Delivery::SprocketsHandler.new(
:asset_paths => [
Flowerbox.path.join("lib/assets/javascripts"),
Flowerbox.path.join("vendor/assets/javascripts"),
@dir,
Flowerbox.asset_paths
].flatten
)
sprockets.add('flowerbox')
sprockets.add('json2')
Flowerbox.test_environment.inject_into(sprockets)
Flowerbox.additional_files.each { |file| sprockets.add(file) }
sprockets
end
def spec_files
return @spec_files if @spec_files
@spec_files = []
Flowerbox.spec_patterns.each do |pattern|
Dir[File.join(dir, pattern)].each do |file|
if !only || only.find { |match| file[%r{^#{match}}] }
@spec_files << File.expand_path(file)
end
end
end
@spec_files
end
def only
return @only if @only
@only = options[:files] || []
@only = nil if only.empty?
@only
end
end
end

View File

@ -0,0 +1,43 @@
module Flowerbox::Run
class Debug < Base
def execute
prep!
env = Flowerbox.runner_environment.first
env.setup(sprockets, spec_files, options)
Flowerbox.reporters.replace([])
puts "Flowerbox debug server running test prepared for #{env.console_name} on #{env.server.address}"
env.server.start
trap('INT') do
env.server.stop
end
@restart = false
trap('QUIT') do
puts "Restarting Flowerbox server..."
@restart = true
env.server.stop
end
while env.server.alive?
sleep 0.25
end
if @restart
debug(dir, options)
else
puts "Flowerbox finished."
end
end
def options
@options.dup.merge(:debug => true)
end
end
end

29
lib/flowerbox/run/test.rb Normal file
View File

@ -0,0 +1,29 @@
module Flowerbox::Run
class Test < Base
def execute
prep!
result_set = Flowerbox::ResultSet.new
time = 0
realtime = Time.now.to_i
runner_envs = Flowerbox.runner_environment.collect do |env|
env.ensure_configured!
result_set << env.run(sprockets, spec_files, options)
time += env.time
env
end
result_set.print(:time => time, :realtime => Time.now.to_i - realtime)
runner_envs.each(&:cleanup)
result_set.exitstatus
end
end
end

26
lib/flowerbox/task.rb Normal file
View File

@ -0,0 +1,26 @@
module Flowerbox
class Task
include Rake::DSL if defined?(Rake::DSL)
def self.create(*args)
new(*args).add
end
attr_reader :name, :options
def initialize(name = "flowerbox", options = nil)
@name = name
@options = options || {}
@options = { :dir => 'spec/javascripts' }.merge(@options)
end
def add
desc "Run Flowerbox for the tests in #{options[:dir]}"
task(name) do
raise StandardError.new("Flowerbox tests failed") if Flowerbox.run(@options[:dir], @options) != 0
end
end
end
end

View File

@ -1,3 +1,5 @@
require 'yaml'
module Flowerbox module Flowerbox
module TestEnvironment module TestEnvironment
class Base class Base
@ -8,6 +10,21 @@ module Flowerbox
def reporters def reporters
@reporters ||= [] @reporters ||= []
end end
def set_additional_options(opts = nil)
@options = {}
if opts
case opts
when String
@options = Hash[YAML.load(opts).collect { |k, v| [ k.to_sym, v ] }]
when Hash
@options = opts
end
@options[:tags] = [ @options[:tags] ].flatten(1) if @options[:tags]
end
end
end end
end end
end end

View File

@ -1,6 +1,14 @@
module Flowerbox module Flowerbox
module TestEnvironment module TestEnvironment
class Cucumber < Base class Cucumber < Base
def initialize
@step_language = nil
end
def prefer_step_language(language)
@step_language = language
end
def inject_into(sprockets) def inject_into(sprockets)
@sprockets = sprockets @sprockets = sprockets
@ -20,12 +28,19 @@ module Flowerbox
<<-JS <<-JS
context.Cucumber = context.require('./cucumber'); context.Cucumber = context.require('./cucumber');
context.cucumber = context.Cucumber(context.Flowerbox.Cucumber.features(), context.Flowerbox.World()); options = {}
#{maybe_tags}
context.cucumber = context.Cucumber(context.Flowerbox.Cucumber.features(), context.Flowerbox.World(), options);
context.cucumber.attachListener(new context.Flowerbox.Cucumber.Reporter()); context.cucumber.attachListener(new context.Flowerbox.Cucumber.Reporter());
context.cucumber.start(function() {}); context.cucumber.start(function() {});
JS JS
end end
def maybe_tags
"options.tags = #{@options[:tags].to_json};" if @options[:tags]
end
def obtain_test_definition_for(result) def obtain_test_definition_for(result)
matcher = result.original_name matcher = result.original_name
args = [] args = []
@ -57,6 +72,8 @@ JS
end end
def primarily_coffeescript? def primarily_coffeescript?
return true if @step_language == :coffeescript
coffee_count = @runner.spec_files.inject(0) { |s, n| s += 1 if n[%r{.coffee$}]; s } coffee_count = @runner.spec_files.inject(0) { |s, n| s += 1 if n[%r{.coffee$}]; s }
js_count = @runner.spec_files.inject(0) { |s, n| s += 1 if n[%r{.js$}]; s } js_count = @runner.spec_files.inject(0) { |s, n| s += 1 if n[%r{.js$}]; s }

View File

@ -1,23 +0,0 @@
require 'guard'
require 'guard/guard'
module Guard
class Flowerbox < ::Guard::Guard
def initialize(watchers = [], options = {})
@options = options
end
def start
puts "Starting Guard::Flowerbox..."
end
def run_all
::Flowerbox.run(@options[:dir], @options)
end
def run_on_change(files = [])
::Flowerbox.run(@options[:dir], @options.merge(:files => files))
end
end
end