2011-06-16 13:51:49 +00:00
require 'fileutils'
require 'coffee-script'
require 'rainbow'
2011-07-20 22:27:20 +00:00
require 'yaml'
2011-12-16 12:21:06 +00:00
require 'erb'
2011-11-20 18:35:30 +00:00
require 'sprockets'
2011-06-16 13:51:49 +00:00
module Jasmine
module Headless
2012-01-18 23:04:36 +00:00
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
2011-06-16 13:51:49 +00:00
class Runner
JASMINE_DEFAULTS = {
'spec_files' = > [ '**/*[sS]pec.js' ] ,
'helpers' = > [ 'helpers/**/*.js' ] ,
'spec_dir' = > 'spec/javascripts' ,
'src_dir' = > nil ,
'stylesheets' = > [ ] ,
2011-09-12 19:12:58 +00:00
'src_files' = > [ ] ,
'backtrace' = > [ ]
2011-06-16 13:51:49 +00:00
}
2011-07-14 20:23:29 +00:00
RUNNER_DIR = File . expand_path ( '../../../../ext/jasmine-webkit-specrunner' , __FILE__ )
RUNNER = File . join ( RUNNER_DIR , 'jasmine-webkit-specrunner' )
2011-06-16 13:51:49 +00:00
2011-06-16 14:11:37 +00:00
attr_reader :options
2012-01-17 18:32:57 +00:00
def self . run ( options = { } )
new ( options ) . run
end
def self . server_port
return @server_port if @server_port
2012-01-18 23:04:36 +00:00
require 'socket'
2012-01-17 18:32:57 +00:00
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
2012-01-18 23:04:36 +00:00
def self . server_port = ( port )
@server_port = port
end
2012-01-17 18:32:57 +00:00
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
2012-01-18 23:04:36 +00:00
def self . server_spec_path
self . server_uri + '/__JHW__/'
end
def self . ensure_server ( options )
2012-01-17 18:32:57 +00:00
return if @server
require 'webrick'
require 'thread'
require 'rack'
require 'net/http'
port = server_port
@server = Thread . new do
Jasmine :: Headless . warn " Powering up! "
2012-01-18 23:04:36 +00:00
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
2012-01-17 18:32:57 +00:00
Rack :: Handler :: WEBrick . run (
2012-01-18 23:04:36 +00:00
app ,
2012-01-17 18:32:57 +00:00
: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
2011-11-20 18:35:30 +00:00
end
2011-06-16 13:51:49 +00:00
end
def initialize ( options )
2011-12-30 15:47:08 +00:00
options = Options . new ( options ) if ! options . kind_of? ( Options )
2011-06-16 13:51:49 +00:00
@options = options
end
2011-10-10 18:11:13 +00:00
def template_writer
@template_writer || = TemplateWriter . new ( self )
end
2011-06-16 13:51:49 +00:00
def jasmine_config
2011-10-24 15:48:41 +00:00
return @jasmine_config if @jasmine_config
2011-08-10 17:11:05 +00:00
2011-10-24 15:48:41 +00:00
@jasmine_config = JASMINE_DEFAULTS . dup
jasmine_config_data . each do | key , value |
@jasmine_config [ key ] = value if value
end
@jasmine_config
2011-06-16 13:51:49 +00:00
end
def jasmine_command ( * targets )
2011-12-29 23:37:23 +00:00
command = [ RUNNER ]
command << " -s #{ options [ :seed ] } "
command << '-c' if options [ :colors ]
2012-01-11 13:44:28 +00:00
command << '-q' if options [ :quiet ]
2011-12-29 23:37:23 +00:00
options . file_reporters . each do | reporter , identifier , file |
command << " -r #{ file } "
end
2012-01-18 23:04:36 +00:00
command += targets
2011-12-29 23:37:23 +00:00
command . compact . join ( ' ' )
2011-06-16 13:51:49 +00:00
end
def run
2011-09-01 14:39:29 +00:00
Jasmine :: Headless :: CacheableAction . enabled = @options [ :enable_cache ]
2012-01-11 13:44:28 +00:00
Jasmine :: Headless . show_warnings = ! @options [ :quiet ]
2011-11-21 15:55:37 +00:00
FilesList . reset!
2011-09-01 13:38:53 +00:00
2012-01-18 23:04:36 +00:00
self . class . server_port = options [ :server_port ]
2011-12-29 23:37:23 +00:00
@_targets = template_writer . write
2011-12-02 23:37:14 +00:00
2012-01-18 23:04:36 +00:00
run_targets = absolute_run_targets ( @_targets . dup )
2011-12-02 23:37:14 +00:00
if run_targets . length == 2
if ( ! @options [ :full_run ] && files_list . filtered? ) || files_list . has_spec_outside_scope?
run_targets . pop
end
end
2011-06-16 13:51:49 +00:00
2012-05-23 01:11:18 +00:00
runner = lambda {
raise " Error #{ $? } while attempting to run ' #{ jasmine_command ( run_targets ) } ', probably because jasmine-webkit-specrunner hasn't been compiled. " if system ( jasmine_command ( run_targets ) ) == 127
}
2012-01-12 20:02:32 +00:00
if options [ :use_server ]
2012-01-18 23:04:36 +00:00
wrap_in_server ( run_targets , & runner )
2012-01-12 20:02:32 +00:00
else
runner . call
end
2011-11-28 16:47:05 +00:00
2011-10-17 15:10:00 +00:00
@_status = $? . exitstatus
ensure
2012-05-24 22:42:20 +00:00
if @_targets && ! runner_filename && ( @options [ :remove_html_file ] || ( @_status == 0 ) )
@_targets . each { | target | FileUtils . rm_f target }
end
2011-06-16 13:51:49 +00:00
end
2011-10-10 18:11:13 +00:00
2012-01-18 23:04:36 +00:00
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
2011-10-10 18:11:13 +00:00
def runner_filename
2011-10-11 12:55:43 +00:00
options [ :runner_output_filename ] || begin
if ( runner_output = jasmine_config [ 'runner_output' ] ) && ! runner_output . empty?
runner_output
else
false
end
end
2011-10-10 18:11:13 +00:00
end
2011-10-24 15:48:41 +00:00
2011-12-29 23:37:23 +00:00
def files_list
@files_list || = Jasmine :: Headless :: FilesList . new (
:config = > jasmine_config ,
2011-12-30 16:34:30 +00:00
:only = > options [ :files ] ,
:seed = > options [ :seed ] ,
:reporters = > options . reporters
2011-12-29 23:37:23 +00:00
)
end
2012-01-18 23:04:36 +00:00
def wrap_in_server ( run_targets )
self . class . ensure_server ( options )
IndexHandler . index = run_targets . last
2012-01-12 20:02:32 +00:00
2012-01-18 23:04:36 +00:00
Jasmine :: Headless . warn " HTTP powered specs! Located at #{ run_targets . join ( ' ' ) } "
2012-01-12 21:47:36 +00:00
2012-01-12 20:02:32 +00:00
yield
end
2011-10-24 15:48:41 +00:00
private
def jasmine_config_data
raise JasmineConfigNotFound . new ( " Jasmine config not found. I tried #{ @options [ :jasmine_config ] } . " ) if ! File . file? ( @options [ :jasmine_config ] )
2011-12-16 12:21:06 +00:00
YAML . load ( ERB . new ( File . read ( @options [ :jasmine_config ] ) ) . result ( binding ) )
2011-10-24 15:48:41 +00:00
end
2011-06-16 13:51:49 +00:00
end
end
end