Skip to content

Commit

Permalink
Add cross-plattform PhantomJS executable detection.
Browse files Browse the repository at this point in the history
  • Loading branch information
netzpirat committed Nov 5, 2011
1 parent bdd45a5 commit bcca7a6
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 26 deletions.
42 changes: 34 additions & 8 deletions lib/guard/jasmine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class Jasmine < Guard
:server => :auto,
:port => 8888,
:jasmine_url => 'http://localhost:8888/jasmine',
:phantomjs_bin => `which phantomjs`.chomp,
:timeout => 10000,
:notification => true,
:hide_success => false,
Expand Down Expand Up @@ -59,6 +58,7 @@ def initialize(watchers = [], options = { })
options = DEFAULT_OPTIONS.merge(options)
options[:specdoc] = :failure if ![:always, :never, :failure].include? options[:specdoc]
options[:server] = :auto if ![:auto, :none, :rack, :jasmine_gem].include? options[:server]
options[:phantomjs_bin] = Jasmine.which('phantomjs') unless options[:phantomjs_bin]

super(watchers, options)

Expand Down Expand Up @@ -175,14 +175,18 @@ def jasmine_runner_available?(url)
# @return [Boolean] when the runner is available
#
def phantomjs_bin_valid?(bin)
version = `#{ bin } --version`

if !version
notify_failure('PhantomJS binary missing', "PhantomJS binary doesn't exist at #{ bin }")
elsif version.to_version < '1.3.0'.to_version
notify_failure('Wrong PhantomJS version', "PhantomJS binary at #{ bin } must be at least version 1.3.0")
if bin && !bin.empty?
version = `#{ bin } --version`

if !version
notify_failure('PhantomJS executable missing', "PhantomJS executable doesn't exist at #{ bin }")
elsif version.to_version < '1.3.0'.to_version
notify_failure('Wrong PhantomJS version', "PhantomJS executable at #{ bin } must be at least version 1.3.0")
else
true
end
else
true
notify_failure('PhantomJS executable missing', "PhantomJS executable couldn't be auto detected.")
end
end

Expand All @@ -200,5 +204,27 @@ def notify_failure(title, message)
false
end

# Cross-platform way of finding an executable in the $PATH.
# http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
#
# @example
# which('ruby') #=> /usr/bin/ruby
#
# @param cmd [String] the executable to find
# @return [String, nil] the path to the executable
#
def self.which(cmd)
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']

ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
exts.each do |ext|
exe = "#{ path }/#{ cmd }#{ ext }"
return exe if File.executable?(exe)
end
end

nil
end

end
end
2 changes: 1 addition & 1 deletion spec/guard/jasmine/runner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
let(:runner) { Guard::Jasmine::Runner }
let(:formatter) { Guard::Jasmine::Formatter }

let(:defaults) { Guard::Jasmine::DEFAULT_OPTIONS }
let(:defaults) { Guard::Jasmine::DEFAULT_OPTIONS.merge({ :phantomjs_bin => '/usr/local/bin/phantomjs' }) }

let(:phantomjs_error_response) do
<<-JSON
Expand Down
72 changes: 55 additions & 17 deletions spec/guard/jasmine_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
formatter.stub(:notify)
server.stub(:start)
server.stub(:stop)
Guard::Jasmine.stub(:which).and_return '/usr/local/bin/phantomjs'
end

describe '#initialize' do
Expand All @@ -33,10 +34,6 @@
guard.options[:jasmine_url].should eql 'http://localhost:8888/jasmine'
end

it 'sets a default :phantomjs_bin option' do
guard.options[:phantomjs_bin].should eql `which phantomjs`.chomp
end

it 'sets a default :timeout option' do
guard.options[:timeout].should eql 10000
end
Expand Down Expand Up @@ -84,6 +81,11 @@
it 'sets last failed paths to empty' do
guard.last_failed_paths.should be_empty
end

it 'tries to auto detect the :phantomjs_bin' do
::Guard::Jasmine.should_receive(:which).and_return '/bin/phantomjs'
guard.options[:phantomjs_bin].should eql '/bin/phantomjs'
end
end

context 'with other options than the default ones' do
Expand Down Expand Up @@ -181,13 +183,41 @@
end

describe '.start' do
context 'with a missing PhantomJS binary' do
context 'when not able to detect the PhantomJS executable' do

before do
Guard::Jasmine.stub(:which).and_return nil
end

it 'shows a message that the executable is missing' do
formatter.should_receive(:error).with "PhantomJS executable couldn't be auto detected."
expect { guard.start }.to throw_symbol :task_has_failed
end

it 'throws :task_has_failed' do
expect { guard.start }.to throw_symbol :task_has_failed
end

context 'with enabled notifications' do
it 'shows a notification that the executable is missing' do
formatter.should_receive(:notify).with("PhantomJS executable couldn't be auto detected.",
:title => 'PhantomJS executable missing',
:image => :failed,
:priority => 2)
expect { guard.start }.to throw_symbol :task_has_failed
end
end
end

context 'with a missing PhantomJS executable' do
let(:guard) { Guard::Jasmine.new(nil, { :phantomjs_bin => '/tmp' }) }

before do
guard.stub(:`).and_return nil
end

it 'shows a message that the binary is missing' do
formatter.should_receive(:error).with "PhantomJS binary doesn't exist at /usr/local/bin/phantomjs"
it 'shows a message that the executable is missing' do
formatter.should_receive(:error).with "PhantomJS executable doesn't exist at /tmp"
expect { guard.start }.to throw_symbol :task_has_failed
end

Expand All @@ -196,9 +226,9 @@
end

context 'with enabled notifications' do
it 'shows a notification that the binary is missing' do
formatter.should_receive(:notify).with("PhantomJS binary doesn't exist at /usr/local/bin/phantomjs",
:title => 'PhantomJS binary missing',
it 'shows a notification that the executable is missing' do
formatter.should_receive(:notify).with("PhantomJS executable doesn't exist at /tmp",
:title => 'PhantomJS executable missing',
:image => :failed,
:priority => 2)
expect { guard.start }.to throw_symbol :task_has_failed
Expand All @@ -207,12 +237,14 @@
end

context 'with a wrong PhantomJS version' do
let(:guard) { Guard::Jasmine.new(nil, { :phantomjs_bin => '/usr/local/bin/phantomjs' }) }

before do
guard.stub(:`).and_return '1.2.0'
end

it 'shows a message that the version is wrong' do
formatter.should_receive(:error).with "PhantomJS binary at /usr/local/bin/phantomjs must be at least version 1.3.0"
formatter.should_receive(:error).with "PhantomJS executable at /usr/local/bin/phantomjs must be at least version 1.3.0"
expect { guard.start }.to throw_symbol :task_has_failed
end

Expand All @@ -222,7 +254,7 @@

context 'with enabled notifications' do
it 'shows a notification that the version is wrong' do
formatter.should_receive(:notify).with("PhantomJS binary at /usr/local/bin/phantomjs must be at least version 1.3.0",
formatter.should_receive(:notify).with("PhantomJS executable at /usr/local/bin/phantomjs must be at least version 1.3.0",
:title => 'Wrong PhantomJS version',
:image => :failed,
:priority => 2)
Expand All @@ -231,7 +263,9 @@
end
end

context 'with a valid PhantomJS binary' do
context 'with a valid PhantomJS executable' do
let(:guard) { Guard::Jasmine.new(nil, { :phantomjs_bin => '/bin/phantomjs' }) }

before do
guard.stub(:phantomjs_bin_valid?).and_return true
end
Expand Down Expand Up @@ -378,8 +412,10 @@
end

describe '.run_all' do
let(:guard) { Guard::Jasmine.new(nil, { :phantomjs_bin => '/bin/phantomjs' }) }

it 'starts the Runner with the spec dir' do
runner.should_receive(:run).with(['spec/javascripts'], defaults).and_return [['spec/javascripts/a.js.coffee'], true]
runner.should_receive(:run).with(['spec/javascripts'], defaults.merge(:phantomjs_bin => '/bin/phantomjs')).and_return [['spec/javascripts/a.js.coffee'], true]

guard.run_all
end
Expand Down Expand Up @@ -415,6 +451,8 @@
end

describe '.run_on_change' do
let(:guard) { Guard::Jasmine.new(nil, { :phantomjs_bin => '/Users/michi/.bin/phantomjs' }) }

it 'passes the paths to the Inspector for cleanup' do
inspector.should_receive(:clean).twice.with(['spec/javascripts/a.js.coffee',
'spec/javascripts/b.js.coffee'])
Expand All @@ -437,21 +475,21 @@
inspector.should_receive(:clean).twice.with(['spec/javascripts/a.js.coffee',
'spec/javascripts/b.js.coffee']).and_return ['spec/javascripts/a.js.coffee']

runner.should_receive(:run).with(['spec/javascripts/a.js.coffee'], defaults).and_return [['spec/javascripts/a.js.coffee'], true]
runner.should_receive(:run).with(['spec/javascripts/a.js.coffee'], defaults.merge({ :phantomjs_bin => '/Users/michi/.bin/phantomjs' })).and_return [['spec/javascripts/a.js.coffee'], true]

guard.run_on_change(['spec/javascripts/a.js.coffee', 'spec/javascripts/b.js.coffee'])
end

context 'with :keep_failed enabled' do
let(:guard) { Guard::Jasmine.new(nil, { :keep_failed => true }) }
let(:guard) { Guard::Jasmine.new(nil, { :keep_failed => true, :phantomjs_bin => '/usr/bin/phantomjs' }) }

before do
guard.last_failed_paths = ['spec/javascripts/b.js.coffee']
end

it 'appends the last failed paths to the current run' do
runner.should_receive(:run).with(['spec/javascripts/a.js.coffee',
'spec/javascripts/b.js.coffee'], defaults)
'spec/javascripts/b.js.coffee'], defaults.merge({ :phantomjs_bin => '/usr/bin/phantomjs' }))

guard.run_on_change(['spec/javascripts/a.js.coffee'])
end
Expand Down

0 comments on commit bcca7a6

Please sign in to comment.