Skip to content

Commit

Permalink
Added --engine option to 'lotus console' command. Lotus::Console clea…
Browse files Browse the repository at this point in the history
…nup. Don't require 'irb' while testing Lotus::Console.
  • Loading branch information
jodosha committed Jul 4, 2014
1 parent 26faa11 commit 19cd078
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 57 deletions.
3 changes: 2 additions & 1 deletion lib/lotus/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ def server
end

desc "console", "starts a lotus console"
method_option :applications, desc: 'path to your applications.rb file (config/applications.rb)'
method_option :applications, desc: 'path to your applications file (config/applications.rb)'
method_option :engine, desc: 'choose a specific console engine: irb/pry/ripl (irb)'
method_option :help, aliases: '-h', desc: 'displays the usage method'

def console
Expand Down
38 changes: 26 additions & 12 deletions lib/lotus/commands/console.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,48 @@
module Lotus
module Commands
class Console
ENGINES = {
'pry' => 'Pry',
'ripl' => 'Ripl',
'irb' => 'IRB'
}.freeze

attr_reader :options

def initialize(env)
@options = _extract_options(env)
@options = env.to_options
end

def start
# Clear out ARGV so Pry/IRB don't attempt to parse the rest
ARGV.shift until ARGV.empty?

require File.expand_path(options[:applications], Dir.pwd)

if defined?(Pry)
Pry.start
else
require 'irb'
IRB.start
end
engine.start
end

def engine
load_engine options.fetch(:engine) { engine_lookup }
end

private
def engine_lookup
(ENGINES.find {|_, klass| Object.const_defined?(klass) } || default_engine).first
end

def _extract_options(env)
default_options.merge(env.to_options)
def default_engine
ENGINES.to_a.last
end

def default_options
{ applications: 'config/applications.rb' }
def load_engine(engine)
require engine
rescue LoadError
ensure
return Object.const_get(
ENGINES.fetch(engine) {
raise ArgumentError.new("Unknown console engine: #{ engine }")
}
)
end
end
end
Expand Down
16 changes: 11 additions & 5 deletions lib/lotus/environment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ class Environment
LOTUS_PORT = 'LOTUS_PORT'.freeze
DEFAULT_PORT = 2300

DEFAULT_CONFIG = 'config.ru'.freeze
DEFAULT_CONFIG = 'config.ru'.freeze
DEFAULT_APPLICATIONS = 'config/applications'.freeze

def initialize(options = {})
@options = Utils::Hash.new(options).symbolize!.freeze
Expand All @@ -40,12 +41,17 @@ def config
@options.fetch(:config) { DEFAULT_CONFIG }
end

def applications
@options.fetch(:applications) { DEFAULT_APPLICATIONS }
end

def to_options
@options.merge(
environment: environment,
config: config,
host: host,
port: port
environment: environment,
applications: applications,
config: config,
host: host,
port: port
)
end

Expand Down
202 changes: 163 additions & 39 deletions test/commands/console_test.rb
Original file line number Diff line number Diff line change
@@ -1,82 +1,206 @@
require 'test_helper'
require 'lotus/commands/console'
require 'irb'

describe Lotus::Commands::Console do
let(:opts) { Hash.new }
let(:env) { Lotus::Environment.new(opts) }
let(:console) { Lotus::Commands::Console.new(env) }

def stub_engine(engine)
begin
@engine = Object.const_get(engine)
rescue NameError
@remove_const = true
end

Lotus::Utils::IO.silence_warnings do
Object.const_set(engine, Module.new { def self.start; end })
end
end

def remove_engine(engine)
Lotus::Utils::IO.silence_warnings do
Object.const_set(engine, @engine)
end if @engine

Object.send(:remove_const, engine.to_sym) if @remove_const
end

describe '#options' do
it 'merges in default values' do
console.options[:applications].must_equal 'config/applications.rb'
describe "when no options are specified" do
it 'returns a default' do
console.options.fetch(:applications).must_equal 'config/applications'
end
end

describe "when :applications option is specified" do
let(:opts) { Hash[applications: 'path/to/applications'] }

it 'returns that value' do
console.options.fetch(:applications).must_equal 'path/to/applications'
end
end
end

describe '#start' do
describe 'with no config/applications.rb file' do
it 'raises a LoadError' do
proc { console.start }.must_raise(LoadError)
describe '#engine' do
describe 'when all the supported engines are loaded' do
before do
stub_engine 'Pry'
stub_engine 'Ripl'
stub_engine 'IRB'
end

after do
remove_engine 'Pry'
remove_engine 'Ripl'
remove_engine 'IRB'
end

it 'prefers Pry' do
console.engine.must_equal(Pry)
end
end

describe 'manually setting the config/applications.rb file' do
it 'requires applications.rb and starts an IRB session' do
opts[:applications] = 'test/fixtures/microservices/config/applications.rb'
describe 'when Ripl and IRB are loaded' do
before do
stub_engine 'Ripl'
stub_engine 'IRB'
end

IRB.stub :start, -> { @started = true } do
console.start
@started.must_equal true
after do
remove_engine 'Ripl'
remove_engine 'IRB'
end

$LOADED_FEATURES.must_include "#{Dir.pwd}/#{opts[:applications]}"
end
it 'prefers Ripl' do
console.engine.must_equal(Ripl)
end
end

describe 'with the default config/applications.rb file' do
describe 'when nothing is loaded' do
before do
@old_pwd = Dir.pwd
Dir.chdir 'test/fixtures/microservices'
$LOAD_PATH.unshift Dir.pwd
stub_engine 'IRB'
end

describe 'using IRB' do
it 'requires applications.rb and starts an IRB session' do
IRB.stub :start, -> { @started = true } do
console.start
@started.must_equal true
after do
remove_engine 'IRB'
end

$LOADED_FEATURES.must_include "#{Dir.pwd}/config/applications.rb"
end
it 'uses IRB' do
console.engine.must_equal(IRB)
end
end

describe 'when an option forces to use a specific engine' do
describe 'IRB' do
let(:opts) { Hash[engine: 'irb'] }

before do
stub_engine 'IRB'
end

after do
remove_engine 'IRB'
end

it 'uses IRB' do
console.engine.must_equal(IRB)
end
end

describe 'using Pry' do
describe 'Pry' do
before do
unless defined?(::Pry)
@remove_pry_const = true
module Pry; def self.start() end; end
end
stub_engine 'Pry'
end

it 'requires applications.rb and starts a Pry session' do
Pry.stub :start, -> { @started = true } do
console.start
@started.must_equal true
after do
remove_engine 'Pry'
end

$LOADED_FEATURES.must_include "#{Dir.pwd}/config/applications.rb"
end
let(:opts) { Hash[engine: 'pry'] }

it 'uses Pry' do
console.engine.must_equal(Pry)
end
end

describe 'Ripl' do
before do
stub_engine 'Ripl'
end

after do
Object.send(:remove_const, :Pry) if @remove_pry_const
remove_engine 'Ripl'
end

let(:opts) { Hash[engine: 'ripl'] }

it 'uses Ripl' do
console.engine.must_equal(Ripl)
end
end

describe 'Unknown engine' do
let(:opts) { Hash[engine: 'unknown'] }

it 'raises error' do
begin
console.engine
rescue ArgumentError => e
e.message.must_equal 'Unknown console engine: unknown'
end
end
end
end
end

describe '#start' do
before do
@engine = Minitest::Mock.new
@engine.expect(:start, nil)
end

describe 'with the default config/applications.rb file' do
before do
@old_pwd = Dir.pwd
Dir.chdir 'test/fixtures/microservices'
end

after do
$LOAD_PATH.shift
Dir.chdir @old_pwd
end

it 'requires that file and starts a console session' do
console.stub :engine, @engine do
console.start

@engine.verify
$LOADED_FEATURES.must_include "#{Dir.pwd}/config/applications.rb"
end
end
end

describe 'when manually setting the applications file' do
let(:opts) {
Hash[applications: 'test/fixtures/microservices/config/applications']
}

it 'requires that file and starts a console session' do
console.stub :engine, @engine do
console.start

@engine.verify
$LOADED_FEATURES.must_include "#{Dir.pwd}/#{opts[:applications]}.rb"
end
end
end

describe 'when applications file is missing' do
it 'raises a LoadError' do
console.stub :engine, @engine do
proc { console.start }.must_raise(LoadError)
end
end
end
end
end

0 comments on commit 19cd078

Please sign in to comment.