diff --git a/bin/flowerbox b/bin/flowerbox index d87996b..bbc3d0d 100755 --- a/bin/flowerbox +++ b/bin/flowerbox @@ -5,7 +5,7 @@ require 'flowerbox-delivery' require 'thor' class Flowerbox::CLI < Thor - desc "test DIR SPEC_PATTERN", "Run the specs found in spec dir" + desc "test DIR", "Run the specs found in spec dir, loading spec_helper.rb for configuration details" method_options :pwd => :string def test(dir) Dir.chdir(pwd) do @@ -15,18 +15,17 @@ class Flowerbox::CLI < Thor Tilt::CoffeeScriptTemplate.default_bare = Flowerbox.bare_coffeescript - sprockets = Flowerbox::Delivery::SprocketsHandler.new(:asset_paths => [ dir, Flowerbox.asset_paths ].flatten) + sprockets = Flowerbox::Delivery::SprocketsHandler.new(:asset_paths => [ Flowerbox.path.join("lib/assets/javascripts"), dir, Flowerbox.asset_paths ].flatten) - Flowerbox.load_test_environment(sprockets) + Flowerbox.test_environment.inject_into(sprockets) Flowerbox.spec_patterns.each do |pattern| Dir[File.join(dir, pattern)].each do |file| - sprockets.add(file.gsub(dir + '/', '')) end end - exit Flowerbox::Runner::Node.run(sprockets.files) + exit Flowerbox.runner_environment.run(sprockets) end end diff --git a/features/basic_run.feature b/features/basic_run.feature index bc0b921..4f6f8a5 100644 --- a/features/basic_run.feature +++ b/features/basic_run.feature @@ -1,14 +1,5 @@ Feature: Basic Run - Scenario: Use the Node runner using Jasmine - Given I have the file "spec/javascripts/spec_helper.rb" with the content: - """ - Flowerbox.configure do |c| - c.test_with :jasmine - c.spec_patterns << "**/*_spec.*" - c.asset_paths << "lib" - c.bare_coffeescript = true - end - """ + Background: Given I have the file "spec/javascripts/cat_spec.js.coffee" with the content: """ #= require cat @@ -25,6 +16,39 @@ Feature: Basic Run class Cat meow: -> "meow" """ + + Scenario: Use the Node runner using Jasmine + Given I have the file "spec/javascripts/spec_helper.rb" with the content: + """ + Flowerbox.configure do |c| + c.test_with :jasmine + c.run_with :node + + c.spec_patterns << "**/*_spec.*" + c.asset_paths << "lib" + c.bare_coffeescript = true + + c.test_environment.reporters << "SimpleNodeReporter" + end + """ + When I run Flowerbox with "spec/javascripts" + Then I should have 1 test and 0 failures + + Scenario: Use the Selenium runner using Jasmine + Given I have the file "spec/javascripts/spec_helper.rb" with the content: + """ + Flowerbox.configure do |c| + c.test_with :jasmine + c.run_with :selenium + c.runner_environment.browser = :firefox + + c.spec_patterns << "**/*_spec.*" + c.asset_paths << "lib" + c.bare_coffeescript = true + + c.test_environment.reporters << "SimpleSeleniumReporter" + end + """ When I run Flowerbox with "spec/javascripts" Then I should have 1 test and 0 failures diff --git a/flowerbox.gemspec b/flowerbox.gemspec index 42ef5e9..336d370 100644 --- a/flowerbox.gemspec +++ b/flowerbox.gemspec @@ -21,4 +21,6 @@ Gem::Specification.new do |gem| gem.add_dependency 'flowerbox-delivery' gem.add_dependency 'thor' + gem.add_dependency 'capybara' + gem.add_dependency 'sinatra' end diff --git a/lib/assets/javascripts/flowerbox/jasmine/node.js.coffee b/lib/assets/javascripts/flowerbox/jasmine/node.js.coffee new file mode 100644 index 0000000..6f30198 --- /dev/null +++ b/lib/assets/javascripts/flowerbox/jasmine/node.js.coffee @@ -0,0 +1,9 @@ +class jasmine.SimpleNodeReporter + reportRunnerResults: (runner) -> + console.log(runner.results().totalCount + '/' + runner.results().failedCount) + + if runner.results().failedCount == 0 + process.exit(0) + else + process.exit(1) + diff --git a/lib/assets/javascripts/flowerbox/jasmine/selenium.js.coffee b/lib/assets/javascripts/flowerbox/jasmine/selenium.js.coffee new file mode 100644 index 0000000..f20777a --- /dev/null +++ b/lib/assets/javascripts/flowerbox/jasmine/selenium.js.coffee @@ -0,0 +1,6 @@ +class jasmine.SimpleSeleniumReporter + reportRunnerResults: (runner) -> + xhr = new XMLHttpRequest() + xhr.open("POST", "/results") + xhr.send(runner.results().totalCount + '/' + runner.results().failedCount) + diff --git a/lib/flowerbox.rb b/lib/flowerbox.rb index c564218..5d4ce74 100644 --- a/lib/flowerbox.rb +++ b/lib/flowerbox.rb @@ -3,6 +3,8 @@ require "flowerbox/version" module Flowerbox module Runner autoload :Node, 'flowerbox/runner/node' + autoload :Selenium, 'flowerbox/runner/selenium' + autoload :Base, 'flowerbox/runner/base' end class << self @@ -15,16 +17,18 @@ module Flowerbox end def test_with(what) - @test_with = what + require "flowerbox/test_environment/#{what}" end - def load_test_environment(sprockets) - require "flowerbox/test_environment/#{@test_with}" - - Flowerbox.test_environment.inject_into(sprockets) + def run_with(what) + require "flowerbox/runner/#{what}" end - attr_accessor :test_environment, :bare_coffeescript + def path + Pathname(File.expand_path('../..', __FILE__)) + end + + attr_accessor :test_environment, :runner_environment, :bare_coffeescript def configure yield self diff --git a/lib/flowerbox/jasmine.rb b/lib/flowerbox/jasmine.rb deleted file mode 100644 index e69de29..0000000 diff --git a/lib/flowerbox/runner/base.rb b/lib/flowerbox/runner/base.rb new file mode 100644 index 0000000..aee0f26 --- /dev/null +++ b/lib/flowerbox/runner/base.rb @@ -0,0 +1,20 @@ +module Flowerbox + module Runner + class Base + attr_reader :sprockets + + def run(sprockets) + @sprockets = sprockets + end + + def type + self.class.name.to_s.split('::').last.downcase.to_sym + end + + def start_test_environment + Flowerbox.test_environment.start_for(type) + end + end + end +end + diff --git a/lib/flowerbox/runner/node.rb b/lib/flowerbox/runner/node.rb index e27c041..91ba023 100644 --- a/lib/flowerbox/runner/node.rb +++ b/lib/flowerbox/runner/node.rb @@ -2,16 +2,10 @@ require 'tempfile' module Flowerbox module Runner - class Node - def self.run(files) - new(files).run - end + class Node < Base + def run(sprockets) + super - def initialize(files) - @files = files - end - - def run file = Tempfile.new("node") file.print template file.close @@ -22,23 +16,28 @@ module Flowerbox end def template + env = start_test_environment + <<-JS -var fs = require('fs'); -var window = this; +var fs = require('fs'), + vm = require('vm'); + +// expand the sandbox a bit +var context = function() {}; +context.window = true; +for (method in global) { context[method] = global[method]; } #{template_files.join("\n")} -#{start_test_environment} +#{env} JS end def template_files - @files.collect { |file| %{eval(fs.readFileSync('#{file}', 'utf-8'));} } - end - - def start_test_environment - Flowerbox.test_environment.start_for(:node) + sprockets.files.collect { |file| %{vm.runInNewContext(fs.readFileSync('#{file}', 'utf-8'), context, '#{file}');} } end end end end +Flowerbox.runner_environment = Flowerbox::Runner::Node.new + diff --git a/lib/flowerbox/runner/selenium.rb b/lib/flowerbox/runner/selenium.rb new file mode 100644 index 0000000..a6d0e32 --- /dev/null +++ b/lib/flowerbox/runner/selenium.rb @@ -0,0 +1,92 @@ +require 'capybara' +require 'capybara/dsl' +require 'sinatra' +require 'thread' + +module Flowerbox + module Runner + class Selenium < Base + include Capybara::DSL + + class Rack < Sinatra::Base + class << self + attr_accessor :runner + end + + def runner + self.class.runner + end + + post '/results' do + runner.results = request.env['rack.input'].read + end + + get %r{^/__F__(/.*)$} do |file| + File.read(file) + end + + get '/' do + runner.template + end + end + + attr_accessor :browser, :results + + def run(sprockets) + super + + Capybara.register_driver :firefox do |app| + Capybara::Selenium::Driver.new(app, :browser => :firefox) + end + + Capybara.default_driver = :firefox + + Rack.runner = self + Capybara.app = Rack + + visit '/' + + 1.upto(30) do + if results + break + else + sleep 1 + end + end + + if results + puts results + + exit (results.split('/').last.to_i == 0) ? 0 : 1 + else + exit 1 + end + end + + def template + env = start_test_environment + + <<-HTML + + + Flowerbox - Selenium Runner + #{template_files.join("\n")} + + +

Flowerbox - Selenium Runner

+ + + +HTML + end + + def template_files + sprockets.files.collect { |file| %{} } + end + end + end +end + +Flowerbox.runner_environment = Flowerbox::Runner::Selenium.new diff --git a/lib/flowerbox/test_environment/jasmine.rb b/lib/flowerbox/test_environment/jasmine.rb index 57cec70..349140c 100644 --- a/lib/flowerbox/test_environment/jasmine.rb +++ b/lib/flowerbox/test_environment/jasmine.rb @@ -3,37 +3,45 @@ require 'jasmine-core' module Flowerbox module TestEnvironment class Jasmine - def self.inject_into(sprockets) - sprockets.append_path(::Jasmine::Core.path) + def inject_into(sprockets) + @sprockets = sprockets - sprockets.add('jasmine.js') - sprockets.add('jasmine-html.js') + @sprockets.append_path(::Jasmine::Core.path) + + @sprockets.add('jasmine.js') + @sprockets.add('jasmine-html.js') end - def self.start_for(runner) - <<-JS -jasmine.NodeReporter = function() {} + def start_for(runner) + @sprockets.add("flowerbox/jasmine/#{runner}") -jasmine.NodeReporter.prototype.reportSpecResults = function(spec) { - console.log(spec.results().totalCount + '/' + spec.results().failedCount); + case runner + when :node + <<-JS +var jasmine = context.jasmine; - if (spec.results().failedCount == 0) { - process.exit(0); - } else { - process.exit(1); - } -} - -jasmine.NodeReporter.prototype.reportRunnerResults = function(runner) { -} - -jasmine.getEnv().addReporter(new jasmine.NodeReporter()); +#{jasmine_reporters.join("\n")} jasmine.getEnv().execute(); JS + when :selenium + <<-JS +jasmine.getEnv().addReporter(new jasmine.TrivialReporter()); +jasmine.getEnv().addReporter(new jasmine.SimpleSeleniumReporter()); +jasmine.getEnv().execute(); +JS + end + end + + def jasmine_reporters + reporters.collect { |reporter| %{jasmine.getEnv().addReporter(new jasmine.#{reporter}());} } + end + + def reporters + @reporters ||= [] end end end end -Flowerbox.test_environment = Flowerbox::TestEnvironment::Jasmine +Flowerbox.test_environment = Flowerbox::TestEnvironment::Jasmine.new