whoa more stuff and it works in production projects

This commit is contained in:
John Bintz 2012-03-14 13:07:13 -04:00
parent 0529359352
commit e6bdbf6313
15 changed files with 192 additions and 67 deletions

View File

@ -5,10 +5,18 @@ 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", "Run the specs found in spec dir, loading spec_helper.rb for configuration details"
method_options :pwd => :string, :runners => :string, :verbose_server => false method_options :pwd => :string, :runners => :string, :runner => :string, :verbose_server => false
def test(dir = "spec/javascripts") def test(dir = "spec/javascripts")
Dir.chdir(pwd) do Dir.chdir(pwd) do
exit Flowerbox.run(dir, options) exit Flowerbox.run(dir, options.dup)
end
end
desc "debug DIR", "Start the Flowerbox server to help debug loading issues."
method_options :pwd => :string, :runners => :string, :runner => :string, :verbose_server => false
def debug(dir = "spec/javascripts")
Dir.chdir(pwd) do
Flowerbox.debug(dir, options.dup)
end end
end end

View File

@ -4,32 +4,28 @@
# #
Flowerbox = Flowerbox =
baseUrl: '/' baseUrl: '/'
debug: false
ping: -> ping: ->
Flowerbox.contact('ping') Flowerbox.contact('ping')
pause: (time) ->
t = (new Date()).getTime()
while (t + time) > (new Date().getTime())
Flowerbox.ping()
contact: (url, data...) -> contact: (url, data...) ->
attempts = 3 if !Flowerbox.debug
attempts = 3
doContact = -> doContact = ->
attempts -= 1 attempts -= 1
try try
xhr = new XMLHttpRequest() xhr = new XMLHttpRequest()
xhr.open("POST", Flowerbox.baseUrl + url, false) xhr.open("POST", Flowerbox.baseUrl + url, false)
xhr.setRequestHeader("Accept", "application/json") xhr.setRequestHeader("Accept", "application/json")
xhr.send(JSON.stringify(data)) xhr.send(JSON.stringify(data))
catch e catch e
if attempts == 0 if attempts == 0
throw e throw e
else else
doContact() doContact()
doContact() doContact()
fail: -> fail: ->

View File

@ -1,5 +1,5 @@
class Flowerbox.Exception class Flowerbox.Exception
constructor: (@stack) -> constructor: (@source, @name, @stack) ->
toJSON: -> toJSON: ->
{ trace: { stack: @stack } } { status: Flowerbox.Result.FAILURE, source: @source, name: @name, trace: { stack: @stack } }

View File

@ -1,5 +1,8 @@
#= require flowerbox/jasmine/reporter #= require flowerbox/jasmine/reporter
# because why not?
@context = @describe
getSplitName = (parts) -> getSplitName = (parts) ->
parts.push(String(@description).replace(/[\n\r]/g, ' ')) parts.push(String(@description).replace(/[\n\r]/g, ' '))
parts parts

View File

@ -1,4 +1,16 @@
class jasmine.FlowerboxReporter class jasmine.FlowerboxReporter
buildResult: (spec, overrides = {}) ->
data =
status: Flowerbox.Result.SUCCESS
source: 'jasmine'
name: spec.getSpecSplitName()
file: 'unknown:0'
for key, value of overrides
data[key] = value
new Flowerbox.Result(data)
reportRunnerStarting: (runner) -> reportRunnerStarting: (runner) ->
@time = (new Date()).getTime() @time = (new Date()).getTime()
@ -7,17 +19,15 @@ class jasmine.FlowerboxReporter
Flowerbox.contact("start_test", spec.description) Flowerbox.contact("start_test", spec.description)
if spec.description == 'encountered a declaration exception' if spec.description == 'encountered a declaration exception'
Flowerbox.contact("finish_test", new Flowerbox.Exception([ spec.description ])) Flowerbox.contact("finish_test", this.buildResult(spec, status: Flowerbox.Result.FAILURE))
Flowerbox.contact("results", 0)
Flowerbox.fail() if Flowerbox.fail?
reportSpecResults: (spec) -> reportSpecResults: (spec) ->
result = new Flowerbox.Result(status: Flowerbox.Result.SUCCESS, source: 'jasmine', name: spec.getSpecSplitName(), file: 'unknown:0') result = this.buildResult(spec)
for item in spec.results().items_ for item in spec.results().items_
if !item.passed_ if !item.passed_
result.status = Flowerbox.Result.FAILURE result.status = Flowerbox.Result.FAILURE
failure = { runner: Flowerbox.environment, message: item.message, stack: item.trace.stack } failure = { runner: Flowerbox.environment, message: item.message, stack: (item.trace.stack || '').split("\n") }
result.failures.push(failure) result.failures.push(failure)

View File

@ -2,6 +2,10 @@ 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'
@ -35,12 +39,14 @@ module Flowerbox
class << self class << self
attr_writer :reporters attr_writer :reporters
attr_accessor :port
def reset! def reset!
@spec_patterns = nil @spec_patterns = nil
@spec_files = nil @spec_files = nil
@asset_paths = nil @asset_paths = nil
@reporters = nil @reporters = nil
@port = nil
end end
def spec_patterns def spec_patterns
@ -55,6 +61,10 @@ module Flowerbox
@reporters ||= [] @reporters ||= []
end end
def additional_files
@additional_files ||= []
end
def test_with(what) def test_with(what)
self.test_environment = Flowerbox::TestEnvironment.for(what) self.test_environment = Flowerbox::TestEnvironment.for(what)
end end
@ -90,34 +100,80 @@ module Flowerbox
@bare_coffeescript ||= true @bare_coffeescript ||= true
end end
def run(dir, options = {}) def prep(dir, options = {})
reset! reset!
load File.join(dir, 'spec_helper.rb') load File.join(dir, 'spec_helper.rb')
if options[:runners]
Flowerbox.run_with(options[:runners].split(','))
end
require 'coffee_script' require 'coffee_script'
require 'tilt/coffee' require 'tilt/coffee'
Tilt::CoffeeScriptTemplate.default_bare = Flowerbox.bare_coffeescript Tilt::CoffeeScriptTemplate.default_bare = Flowerbox.bare_coffeescript
if runners = options[:runners] || options[:runner]
Flowerbox.run_with(runners.split(','))
end
end
def debug(dir, options = {})
options[:debug] = true
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
def run(dir, options = {})
prep(dir, options)
result_set = ResultSet.new result_set = ResultSet.new
time = 0 time = 0
realtime = Time.now.to_i realtime = Time.now.to_i
Flowerbox.runner_environment.each do |env| runner_envs = Flowerbox.runner_environment.collect do |env|
env.ensure_configured! env.ensure_configured!
result_set << env.run(build_sprockets_for(dir), spec_files_for(dir), options) result_set << env.run(build_sprockets_for(dir), spec_files_for(dir), options)
time += env.time time += env.time
env
end end
result_set.print(:time => time, :realtime => Time.now.to_i - realtime) result_set.print(:time => time, :realtime => Time.now.to_i - realtime)
runner_envs.each(&:cleanup)
result_set.exitstatus result_set.exitstatus
end end
@ -136,6 +192,8 @@ module Flowerbox
Flowerbox.test_environment.inject_into(sprockets) Flowerbox.test_environment.inject_into(sprockets)
Flowerbox.additional_files.each { |file| sprockets.add(file) }
sprockets sprockets
end end

View File

@ -5,13 +5,17 @@ require 'cgi'
module Flowerbox module Flowerbox
class Rack < Sinatra::Base class Rack < Sinatra::Base
class << self class << self
attr_accessor :runner attr_accessor :runner, :sprockets
end end
def runner def runner
self.class.runner self.class.runner
end end
def sprockets
self.class.sprockets
end
def data def data
JSON.parse(request.body.string) JSON.parse(request.body.string)
end end
@ -44,11 +48,16 @@ module Flowerbox
runner.ping runner.ping
end end
get %r{^/__F__(/.*)$} do |file| get %r{^/__F__/(.*)$} do |file|
File.read(file) asset = sprockets.asset_for(file, :bundle => false)
content_type asset.content_type
asset.body
end end
get '/' do get '/' do
sprockets.expire_index!
runner.template runner.template
end end
end end

View File

@ -9,22 +9,26 @@ module Flowerbox::Reporter
end end
def report_progress(result) def report_progress(result)
result.name.each_with_index do |name, index| if result.name
if @name_stack[index] != name result.name.each_with_index do |name, index|
if name != result.name.last if @name_stack[index] != name
message = name if name != result.name.last
else message = name
message = self.send("progress_#{result.type}", result) else
if !(file_display = path_for(result)).empty? message = self.send("progress_#{result.type}", result)
message << " # #{file_display}" if !(file_display = path_for(result)).empty?
message << " # #{file_display}"
end
end end
puts indent(message, index)
end end
puts indent(message, index)
end end
end
@name_stack = result.name.dup @name_stack = result.name.dup
else
puts result.data
end
end end
def progress_skipped(result) def progress_skipped(result)

View File

@ -11,6 +11,7 @@ module Flowerbox
end end
autoload :Base, 'flowerbox/result/base' autoload :Base, 'flowerbox/result/base'
autoload :Exception, 'flowerbox/result/exception'
autoload :Failure, 'flowerbox/result/failure' autoload :Failure, 'flowerbox/result/failure'
autoload :Pending, 'flowerbox/result/pending' autoload :Pending, 'flowerbox/result/pending'
autoload :FailureMessage, 'flowerbox/result/failure_message' autoload :FailureMessage, 'flowerbox/result/failure_message'

View File

@ -18,8 +18,12 @@ module Flowerbox
end end
end end
def run(sprockets, spec_files, options) def setup(sprockets, spec_files, options)
@sprockets, @spec_files, @options = sprockets, spec_files, options @sprockets, @spec_files, @options = sprockets, spec_files, options
end
def run(*args)
setup(*args)
@count = 0 @count = 0
@ -41,6 +45,10 @@ module Flowerbox
def configure def configure
end end
def debug?
options[:debug] == true
end
def ensure_configured! def ensure_configured!
if !configured? if !configured?
puts "#{console_name} is not configured for this project, configuring now..." puts "#{console_name} is not configured for this project, configuring now..."
@ -65,9 +73,11 @@ module Flowerbox
server_options = { :app => Flowerbox::Rack } server_options = { :app => Flowerbox::Rack }
server_options[:logging] = true if options[:verbose_server] server_options[:logging] = true if options[:verbose_server]
server_options[:port] = Flowerbox.port
@server = Flowerbox::Delivery::Server.new(server_options) @server = Flowerbox::Delivery::Server.new(server_options)
Flowerbox::Rack.runner = self Flowerbox::Rack.runner = self
Flowerbox::Rack.sprockets = @sprockets
@server @server
end end

View File

@ -13,7 +13,7 @@ class Flowerbox::Runner::Chrome < Flowerbox::Runner::Selenium
end end
def browser def browser
:chrome @browser ||= ::Selenium::WebDriver.for(:chrome)
end end
end end

View File

@ -8,7 +8,7 @@ class Flowerbox::Runner::Firefox < Flowerbox::Runner::Selenium
end end
def browser def browser
:firefox @browser ||= ::Selenium::WebDriver.for(:firefox)
end end
end end

View File

@ -26,6 +26,8 @@ module Flowerbox
File.directory?(File.join(Dir.pwd, 'node_modules/cucumber')) File.directory?(File.join(Dir.pwd, 'node_modules/cucumber'))
end end
def cleanup ; end
def configure def configure
system %{bash -c "mkdir -p node_modules && npm link jsdom && npm link xmlhttprequest && npm link cucumber"} system %{bash -c "mkdir -p node_modules && npm link jsdom && npm link xmlhttprequest && npm link cucumber"}
end end
@ -73,7 +75,7 @@ jsdom.env(
var options = { var options = {
host: "localhost", host: "localhost",
port: #{server.port}, port: #{server.port},
path: "/__F__" + file, path: "/__F__/" + file,
method: "GET" method: "GET"
}; };

View File

@ -3,7 +3,6 @@ require 'selenium-webdriver'
module Flowerbox module Flowerbox
module Runner module Runner
class Selenium < Base class Selenium < Base
def name def name
raise StandardError.new("Override me") raise StandardError.new("Override me")
end end
@ -12,17 +11,19 @@ module Flowerbox
:selenium :selenium
end end
def cleanup
@browser.close if @browser
end
def browser
raise StandardError.new("Define a browser")
end
def run(sprockets, spec_files, options) def run(sprockets, spec_files, options)
super do super do
begin browser.navigate.to "http://localhost:#{server.port}/"
selenium = ::Selenium::WebDriver.for(browser)
selenium.navigate.to "http://localhost:#{server.port}/" ensure_alive
ensure_alive
ensure
selenium.quit if selenium
end
end end
end end
@ -50,13 +51,13 @@ console.log = function(msg) {
<body> <body>
<h1>Flowerbox - #{Flowerbox.test_environment.name} Runner</h1> <h1>Flowerbox - #{Flowerbox.test_environment.name} Runner</h1>
<script type="text/javascript"> <script type="text/javascript">
Flowerbox.environment = '#{browser}'; Flowerbox.environment = '#{name}';
var context = this; var context = this;
window.onload = function() { window.addEventListener('DOMContentLoaded', function() {
#{env} #{env}
}; }, false);
</script> </script>
</body> </body>
</html> </html>
@ -64,7 +65,7 @@ HTML
end end
def template_files def template_files
sprockets.files.collect { |file| %{<script type="text/javascript" src="/__F__#{file}"></script>} } sprockets.files.collect { |file| %{<script type="text/javascript" src="/__F__/#{file.logical_path}"></script>} }
end end
end end
end end

23
lib/guard/flowerbox.rb Normal file
View File

@ -0,0 +1,23 @@
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