remove the need for the separate delivey gem, there was so little left in it anyway that was necessary
This commit is contained in:
parent
9a905a862f
commit
5832151ac5
@ -4,8 +4,8 @@ require File.expand_path('../lib/flowerbox/version', __FILE__)
|
||||
Gem::Specification.new do |gem|
|
||||
gem.authors = ["John Bintz"]
|
||||
gem.email = ["john@coswellproductions.com"]
|
||||
gem.description = %q{TODO: Write a gem description}
|
||||
gem.summary = %q{TODO: Write a gem summary}
|
||||
gem.description = %q{No-nonsense JavaScript testing solution.}
|
||||
gem.summary = %q{No-nonsense JavaScript testing solution.}
|
||||
gem.homepage = ""
|
||||
|
||||
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
||||
@ -19,9 +19,9 @@ Gem::Specification.new do |gem|
|
||||
gem.add_development_dependency 'rspec'
|
||||
|
||||
gem.add_dependency 'jasmine-core'
|
||||
gem.add_dependency 'flowerbox-delivery'
|
||||
gem.add_dependency 'thor'
|
||||
gem.add_dependency 'selenium-webdriver'
|
||||
gem.add_dependency 'sinatra'
|
||||
gem.add_dependency 'rainbow'
|
||||
gem.add_dependency 'sprockets-vendor_gems'
|
||||
end
|
||||
|
@ -1,5 +1,4 @@
|
||||
require "flowerbox/version"
|
||||
require 'flowerbox-delivery'
|
||||
require 'rainbow'
|
||||
|
||||
module Flowerbox
|
||||
@ -40,6 +39,10 @@ module Flowerbox
|
||||
|
||||
autoload :Reporter, 'flowerbox/reporter'
|
||||
|
||||
autoload :Server, 'flowerbox/server'
|
||||
autoload :UniqueAssetList, 'flowerbox/unique_asset_list'
|
||||
autoload :SprocketsHandler, 'flowerbox/sprockets_handler'
|
||||
|
||||
class << self
|
||||
attr_writer :reporters
|
||||
attr_accessor :port
|
||||
|
@ -33,7 +33,7 @@ module Flowerbox::Run
|
||||
end
|
||||
|
||||
def sprockets
|
||||
Flowerbox::Delivery::SprocketsHandler.new(
|
||||
Flowerbox::SprocketsHandler.new(
|
||||
:asset_paths => [
|
||||
Flowerbox.path.join("lib/assets/javascripts"),
|
||||
Flowerbox.path.join("vendor/assets/javascripts"),
|
||||
|
@ -106,7 +106,7 @@ module Flowerbox
|
||||
server_options[:logging] = true if options[:verbose_server]
|
||||
server_options[:port] = Flowerbox.port
|
||||
|
||||
@server = Flowerbox::Delivery::Server.new(server_options)
|
||||
@server = Flowerbox::Server.new(server_options)
|
||||
Flowerbox::Rack.runner = self
|
||||
Flowerbox::Rack.sprockets = @sprockets
|
||||
|
||||
|
123
lib/flowerbox/server.rb
Normal file
123
lib/flowerbox/server.rb
Normal file
@ -0,0 +1,123 @@
|
||||
require 'rack'
|
||||
require 'net/http'
|
||||
require 'socket'
|
||||
require 'rack/builder'
|
||||
require 'thin'
|
||||
|
||||
module Flowerbox
|
||||
class Server
|
||||
attr_reader :options
|
||||
|
||||
def initialize(options = {})
|
||||
@options = { :logging => false }.merge(options || {})
|
||||
end
|
||||
|
||||
def start
|
||||
@server_thread = Thread.new do
|
||||
server_options = { :Port => port, :Host => interface }
|
||||
|
||||
app = options[:app]
|
||||
|
||||
Thin::Logging.silent = !options[:logging]
|
||||
|
||||
if options[:logging]
|
||||
real_app = app
|
||||
app = ::Rack::Builder.new do
|
||||
use ::Rack::CommonLogger, STDOUT
|
||||
run real_app
|
||||
end
|
||||
end
|
||||
|
||||
::Rack::Handler::Thin.run(app, server_options) do |server|
|
||||
Thread.current[:server] = server
|
||||
|
||||
trap('QUIT') { server.stop }
|
||||
end
|
||||
end
|
||||
|
||||
while !@server_thread[:server] && @server_thread.alive?
|
||||
sleep 0.1
|
||||
end
|
||||
|
||||
raise StandardError.new("Server died") if !@server_thread[:server].running?
|
||||
end
|
||||
|
||||
def stop
|
||||
if @server_thread
|
||||
@server_thread[:server].stop
|
||||
|
||||
wait_for_server_to_stop
|
||||
end
|
||||
end
|
||||
|
||||
def interface
|
||||
options[:interface] || '0.0.0.0'
|
||||
end
|
||||
|
||||
def port
|
||||
return @port if @port ||= options[:port]
|
||||
|
||||
attempts = 20
|
||||
|
||||
begin
|
||||
attempts -= 1
|
||||
|
||||
current_port = random_port
|
||||
|
||||
begin
|
||||
socket = TCPSocket.new(interface, current_port)
|
||||
socket.close
|
||||
rescue Errno::ECONNREFUSED => e
|
||||
@port = current_port
|
||||
end
|
||||
end while !@port and attempts > 0
|
||||
|
||||
raise StandardError.new("can't start server") if attempts == 0
|
||||
|
||||
@port
|
||||
end
|
||||
|
||||
def address
|
||||
"http://#{interface}:#{port}/"
|
||||
end
|
||||
|
||||
def alive?
|
||||
@server_thread.alive?
|
||||
end
|
||||
|
||||
private
|
||||
def wait_for_server_to_start
|
||||
while true do
|
||||
begin
|
||||
connect_interface = '127.0.0.1' if interface == '0.0.0.0'
|
||||
|
||||
TCPSocket.new(connect_interface, port)
|
||||
break
|
||||
rescue Errno::ECONNREFUSED => e
|
||||
end
|
||||
|
||||
sleep 0.1
|
||||
end
|
||||
end
|
||||
|
||||
def wait_for_server_to_stop
|
||||
while alive? do
|
||||
begin
|
||||
connect_interface = '127.0.0.1' if interface == '0.0.0.0'
|
||||
|
||||
socket = TCPSocket.new(connect_interface, port)
|
||||
socket.close
|
||||
rescue Errno::ECONNREFUSED => e
|
||||
return
|
||||
end
|
||||
|
||||
sleep 0.1
|
||||
end
|
||||
end
|
||||
|
||||
def random_port
|
||||
25000 + Kernel.rand(1000)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
57
lib/flowerbox/sprockets_handler.rb
Normal file
57
lib/flowerbox/sprockets_handler.rb
Normal file
@ -0,0 +1,57 @@
|
||||
require 'sprockets'
|
||||
require 'sprockets/engines'
|
||||
require 'forwardable'
|
||||
require 'sprockets-vendor_gems'
|
||||
|
||||
module Flowerbox
|
||||
class SprocketsHandler
|
||||
extend Forwardable
|
||||
|
||||
attr_reader :files, :options
|
||||
|
||||
def_delegators :environment, :append_path, :register_engine, :[]
|
||||
|
||||
def self.gem_asset_paths
|
||||
@gem_asset_paths ||= Sprockets.find_gem_vendor_paths
|
||||
end
|
||||
|
||||
def initialize(options)
|
||||
@options = options
|
||||
|
||||
@files = Flowerbox::UniqueAssetList.new
|
||||
end
|
||||
|
||||
def add(asset)
|
||||
paths_for(asset).each { |path| add_paths_for_compiled_asset(path) }
|
||||
end
|
||||
|
||||
def paths_for(asset)
|
||||
environment.find_asset(asset).to_a.collect(&:pathname)
|
||||
end
|
||||
|
||||
def expire_index!
|
||||
@environment.send(:expire_index!)
|
||||
end
|
||||
|
||||
def environment
|
||||
return @environment if @environment
|
||||
|
||||
@environment = Sprockets::Environment.new
|
||||
@environment.cache = Sprockets::Cache::FileStore.new(".tmp")
|
||||
|
||||
self.class.gem_asset_paths.each { |path| append_path(path) }
|
||||
options[:asset_paths].each { |path| append_path(path) }
|
||||
|
||||
@environment
|
||||
end
|
||||
|
||||
def asset_for(*args)
|
||||
environment.find_asset(*args)
|
||||
end
|
||||
|
||||
def add_paths_for_compiled_asset(path)
|
||||
asset_for(path, :bundle => false).to_a.each { |file_path| @files.add(file_path) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
17
lib/flowerbox/unique_asset_list.rb
Normal file
17
lib/flowerbox/unique_asset_list.rb
Normal file
@ -0,0 +1,17 @@
|
||||
module Flowerbox
|
||||
class UniqueAssetList < ::Array
|
||||
def add(files)
|
||||
[ files ].flatten.each { |file| self << file if !include?(file) }
|
||||
end
|
||||
|
||||
def to_json
|
||||
collect(&:logical_path)
|
||||
end
|
||||
|
||||
private
|
||||
def include?(file)
|
||||
any? { |other_file| other_file.pathname.to_s == file.pathname.to_s }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
59
spec/flowerbox/delivery/template_renderer_spec.rb
Normal file
59
spec/flowerbox/delivery/template_renderer_spec.rb
Normal file
@ -0,0 +1,59 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Flowerbox::Delivery::TemplateRenderer do
|
||||
let(:template_renderer) { described_class.new(:template => template, :files => files) }
|
||||
let(:template) { 'template' }
|
||||
let(:files) { 'files' }
|
||||
|
||||
let(:rendered_template) { 'rendered template' }
|
||||
let(:erb_template) { "#{rendered_template} <%= resource_tags %>" }
|
||||
|
||||
describe '#render' do
|
||||
subject { template_renderer.render }
|
||||
|
||||
let(:rendered_files) { 'with files' }
|
||||
let(:result) { "#{rendered_template} #{rendered_files}" }
|
||||
|
||||
before do
|
||||
template_renderer.expects(:resource_tags).returns(rendered_files)
|
||||
template_renderer.expects(:template).returns(erb_template)
|
||||
end
|
||||
|
||||
it { should == result }
|
||||
end
|
||||
|
||||
describe '#template' do
|
||||
include FakeFS::SpecHelpers
|
||||
|
||||
before do
|
||||
File.open(template, 'wb') { |fh| fh.print erb_template }
|
||||
end
|
||||
|
||||
subject { template_renderer.template }
|
||||
|
||||
it { should == erb_template }
|
||||
end
|
||||
|
||||
describe '#resource_tags' do
|
||||
subject { template_renderer.resource_tags }
|
||||
|
||||
context 'success' do
|
||||
let(:files) { [ js, css ] }
|
||||
let(:js) { 'file.js' }
|
||||
let(:css) { 'file.css' }
|
||||
|
||||
it { should == [
|
||||
%{<script src="#{js}" type="text/javascript"></script>},
|
||||
%{<link rel="stylesheet" href="#{css}" type="text/css" />}
|
||||
].join }
|
||||
end
|
||||
|
||||
context 'failure' do
|
||||
let(:files) { [ 'what.ever' ] }
|
||||
|
||||
it 'should raise error' do
|
||||
expect { subject }.to raise_error(Flowerbox::Delivery::TemplateRenderer::FileTypeError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
62
spec/flowerbox/delivery/tilt/js_template_spec.rb
Normal file
62
spec/flowerbox/delivery/tilt/js_template_spec.rb
Normal file
@ -0,0 +1,62 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Flowerbox::Delivery::Tilt::JSTemplate do
|
||||
let(:js_template) { described_class.new { '' } }
|
||||
|
||||
describe '#evaluate' do
|
||||
subject { js_template.evaluate(Object.new, {}) }
|
||||
|
||||
before do
|
||||
js_template.stubs(:file).returns(file)
|
||||
end
|
||||
|
||||
context '.js' do
|
||||
let(:file) { 'file.js' }
|
||||
|
||||
it { should == file }
|
||||
end
|
||||
|
||||
context 'other extension' do
|
||||
let(:file) { 'file.coffee' }
|
||||
let(:temp_file) { 'temp file' }
|
||||
|
||||
before do
|
||||
js_template.expects(:save).returns(temp_file)
|
||||
end
|
||||
|
||||
it { should == temp_file }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#save' do
|
||||
include FakeFS::SpecHelpers
|
||||
|
||||
let(:temp_file) { 'dir/temp file' }
|
||||
let(:data) { 'data' }
|
||||
|
||||
before do
|
||||
js_template.stubs(:temp_file).returns(temp_file)
|
||||
js_template.stubs(:data).returns(data)
|
||||
end
|
||||
|
||||
it 'should save the file to disk and return the temp path' do
|
||||
js_template.save.should == temp_file
|
||||
|
||||
File.read(temp_file).should == data
|
||||
end
|
||||
end
|
||||
|
||||
describe '#temp_file' do
|
||||
subject { js_template.temp_file }
|
||||
|
||||
let(:filename) { "#{root_filename}.ext" }
|
||||
let(:root_filename) { "dir/file.js" }
|
||||
|
||||
before do
|
||||
js_template.stubs(:file).returns(filename)
|
||||
end
|
||||
|
||||
it { should == File.join(Dir.pwd, '.tmp/sprockets', root_filename) }
|
||||
end
|
||||
end
|
||||
|
100
spec/flowerbox/server_spec.rb
Normal file
100
spec/flowerbox/server_spec.rb
Normal file
@ -0,0 +1,100 @@
|
||||
require 'spec_helper'
|
||||
require 'socket'
|
||||
require 'thread'
|
||||
|
||||
describe Flowerbox::Delivery::Server do
|
||||
let(:server) { described_class.new(options) }
|
||||
let(:options) { nil }
|
||||
|
||||
subject { server }
|
||||
|
||||
describe '#initialize' do
|
||||
let(:options) { { :port => port, :interface => interface } }
|
||||
let(:port) { 'port' }
|
||||
let(:interface) { 'interface' }
|
||||
|
||||
its(:port) { should == port }
|
||||
its(:interface) { should == interface }
|
||||
end
|
||||
|
||||
describe '#start' do
|
||||
let(:port) { 12345 }
|
||||
let(:interface) { '127.0.0.1' }
|
||||
|
||||
before do
|
||||
server.stubs(:port).returns(port)
|
||||
server.stubs(:interface).returns(interface)
|
||||
end
|
||||
|
||||
it 'should start a Rack server' do
|
||||
server.start
|
||||
|
||||
TCPSocket.new(server.interface, server.port)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#interface' do
|
||||
subject { server.interface }
|
||||
|
||||
it { should == '0.0.0.0' }
|
||||
end
|
||||
|
||||
describe '#port' do
|
||||
let(:interface) { '127.0.0.1' }
|
||||
let(:base) { 25000 }
|
||||
let(:initial) { base + @offset }
|
||||
|
||||
before do
|
||||
server.stubs(:interface).returns(interface)
|
||||
|
||||
@offset = 0
|
||||
ok = true
|
||||
|
||||
begin
|
||||
[ 0, 1 ].each do |index|
|
||||
begin
|
||||
TCPSocket.new(interface, base + @offset + index)
|
||||
@offset += 1
|
||||
ok = false
|
||||
rescue Errno::ECONNREFUSED => e
|
||||
end
|
||||
end
|
||||
end while !ok
|
||||
end
|
||||
|
||||
subject { server.port }
|
||||
|
||||
context 'no running service' do
|
||||
before do
|
||||
Kernel.stubs(:rand).returns(@offset)
|
||||
end
|
||||
|
||||
it { should == initial }
|
||||
end
|
||||
|
||||
context 'running service' do
|
||||
before do
|
||||
@server = Thread.new do
|
||||
TCPServer.new(interface, initial)
|
||||
end
|
||||
|
||||
server.stubs(:random_port).returns(initial, initial + 1)
|
||||
|
||||
while true
|
||||
begin
|
||||
TCPSocket.new(interface, initial)
|
||||
break
|
||||
rescue Errno::ECONNREFUSED
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it { should == initial + 1 }
|
||||
|
||||
after do
|
||||
@server.kill
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
52
spec/flowerbox/sprockets_handler_spec.rb
Normal file
52
spec/flowerbox/sprockets_handler_spec.rb
Normal file
@ -0,0 +1,52 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Flowerbox::Delivery::SprocketsHandler do
|
||||
let(:sprockets_handler) { described_class.new(options) }
|
||||
let(:options) { { :asset_paths => asset_paths } }
|
||||
let(:asset_paths) { [ File.expand_path('asset path') ] }
|
||||
|
||||
describe '#add' do
|
||||
let(:asset) { 'asset' }
|
||||
let(:path) { 'path' }
|
||||
let(:paths) { [ path ] }
|
||||
|
||||
let(:pathname_path) { 'pathname path' }
|
||||
|
||||
before do
|
||||
sprockets_handler.expects(:paths_for).with(asset).returns(paths)
|
||||
sprockets_handler.expects(:path_for_compiled_asset).with(path).returns(pathname_path)
|
||||
end
|
||||
|
||||
it 'should add the asset to the list of ones to work with' do
|
||||
sprockets_handler.add(asset)
|
||||
|
||||
sprockets_handler.files.should == [ pathname_path ]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#paths_for' do
|
||||
subject { sprockets_handler.paths_for(asset) }
|
||||
|
||||
let(:asset) { 'asset' }
|
||||
let(:environment) { stub }
|
||||
let(:bundled_asset) { stub(:to_a => [ processed_asset ]) }
|
||||
let(:processed_asset) { stub(:pathname => path) }
|
||||
|
||||
let(:path) { 'path' }
|
||||
|
||||
before do
|
||||
sprockets_handler.stubs(:environment).returns(environment)
|
||||
environment.expects(:find_asset).with(asset).returns(bundled_asset)
|
||||
end
|
||||
|
||||
it { should == [ path ] }
|
||||
end
|
||||
|
||||
describe '#environment' do
|
||||
subject { sprockets_handler.environment }
|
||||
|
||||
it { should be_a_kind_of(Sprockets::Environment) }
|
||||
its(:paths) { should == asset_paths }
|
||||
end
|
||||
end
|
||||
|
18
spec/flowerbox/unique_asset_list_spec.rb
Normal file
18
spec/flowerbox/unique_asset_list_spec.rb
Normal file
@ -0,0 +1,18 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Flowerbox::Delivery::UniqueAssetList do
|
||||
let(:unique_asset_list) { described_class.new }
|
||||
|
||||
describe "#add" do
|
||||
let(:first) { Pathname.new('one') }
|
||||
let(:second) { Pathname.new('one') }
|
||||
let(:third) { Pathname.new('two') }
|
||||
|
||||
it 'should not add assets already added' do
|
||||
unique_asset_list.add(first)
|
||||
unique_asset_list.add([ second, third ])
|
||||
|
||||
unique_asset_list.should == [ first, third ]
|
||||
end
|
||||
end
|
||||
end
|
7
spec/spec_helper.rb
Normal file
7
spec/spec_helper.rb
Normal file
@ -0,0 +1,7 @@
|
||||
require 'flowerbox-delivery'
|
||||
require 'mocha'
|
||||
require 'fakefs/spec_helpers'
|
||||
|
||||
RSpec.configure do |c|
|
||||
c.mock_with :mocha
|
||||
end
|
Loading…
Reference in New Issue
Block a user