Class: EasyPrompt::MockCommandLineUser

Inherits:
Object
  • Object
show all
Defined in:
lib/easyprompt.rb

Overview

The MockCommandLineUser can be used if you want to unit-test the command-line part of a program.

irb(main):001:0> require 'easyprompt'
=> true
irb(main):002:0> user = EasyPrompt::MockCommandLineUser.new
=> #<EasyPrompt::MockCommandLineUser:0x595818 @match_count={},
   @mock_stdout=#<StringIO:0x5949b8>, @mock_stdin=#<StringIO:0x595750>,
   @responses={}>
irb(main):003:0> prompt = EasyPrompt.new
=> #<EasyPrompt:0x57d894 @stdout=#<StringIO:0x5949b8>>
irb(main):004:0> prompt.ask( "Prepared for this one?" )
RuntimeError: Can't match "Prepared for this one? "
         from /usr/local/lib/ruby/site_ruby/1.8/easyprompt.rb:79:in `match_regexp'
         from /usr/local/lib/ruby/site_ruby/1.8/easyprompt.rb:95:in `update'
         from /usr/local/lib/ruby/1.8/observer.rb:185:in `notify_observers'
         from /usr/local/lib/ruby/1.8/observer.rb:184:in `each'
         from /usr/local/lib/ruby/1.8/observer.rb:184:in `notify_observers'
         from /usr/local/lib/ruby/site_ruby/1.8/easyprompt.rb:128:in `gets'
         from /usr/local/lib/ruby/site_ruby/1.8/easyprompt.rb:36:in `ask'
         from (irb):4
irb(main):005:0> user.set_response( /about this one/, "sure!" )
=> ["sure!", nil]
irb(main):006:0> prompt.ask( "How about this one?" )
=> "sure!"
irb(main):007:0> user.set_response( /twice/, "no", 1 )
=> ["no", 1]
irb(main):008:0> prompt.ask( "Can I ask you this twice?" )
=> "no"
irb(main):009:0> prompt.ask( "Can I ask you this twice?" )
RuntimeError: Exceeded limit of 1 for (?-mix:twice)
         from /usr/local/lib/ruby/site_ruby/1.8/easyprompt.rb:101:in `update'
         from /usr/local/lib/ruby/1.8/observer.rb:185:in `notify_observers'
         from /usr/local/lib/ruby/1.8/observer.rb:184:in `each'
         from /usr/local/lib/ruby/1.8/observer.rb:184:in `notify_observers'
         from /usr/local/lib/ruby/site_ruby/1.8/easyprompt.rb:128:in `gets'
         from /usr/local/lib/ruby/site_ruby/1.8/easyprompt.rb:36:in `ask'
         from (irb):9

Instance Method Summary collapse

Constructor Details

#initializeMockCommandLineUser

Initializes the MockCommandLineUser. Once a MockCommandLineUser has been instantiated, it will automatically intercept the calls that EasyPrompt makes to STDIN and STDOUT. Future calls to EasyPrompt#ask will check against the list of responses contained in MockCommandLineUser; if there is no match, an error will be raised. Use set_response to add a response.



102
103
104
105
106
107
108
109
110
111
# File 'lib/easyprompt.rb', line 102

def initialize
	@responses = {}
	@match_count = Hash.new( 1 )
	context = Lafcadio::Context.instance
	@mock_stdin = StringIO.new
	@mock_stdin.add_observer( self )
	context.set_resource( MockableStdin, @mock_stdin )
	@mock_stdout = StringIO.new
	context.set_resource( MockableStdout, @mock_stdout )
end

Instance Method Details

#match_regexpObject

:nodoc:



113
114
115
116
117
118
119
120
121
122
# File 'lib/easyprompt.rb', line 113

def match_regexp #:nodoc:
	arg = @mock_stdout.string
	@mock_stdout.string = ''
	matching = @responses.map { |regexp, response_pair |
		( loc = arg =~ regexp ) ? [ regexp, loc ] : nil
	}
	matching.compact!
	fail "Can't match \"#{ arg }\"" if matching.empty?
	( matching.sort_by { |regexp, loc| loc } ).last.first
end

#respond(response) ⇒ Object

:nodoc:



124
125
126
127
128
129
# File 'lib/easyprompt.rb', line 124

def respond( response ) #:nodoc:
	response = response.instance_of?( String ) ? response : response.call
	@mock_stdin.string = ''
	@mock_stdin.puts( response )
	@mock_stdin.rewind
end

#set_response(input_regexp, response, limit = nil) ⇒ Object

Adds a response to the list of responses.

input_regexp

The regexp that each EasyPrompt#ask prompt is compared to.

response

The value returned.

limit

The maximum number of times this response can be used.



135
136
137
# File 'lib/easyprompt.rb', line 135

def set_response( input_regexp, response, limit = nil )
	@responses[input_regexp] = [ response, limit ]
end

#updateObject

:nodoc:



139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/easyprompt.rb', line 139

def update #:nodoc:
	regexp = match_regexp
	if regexp && ( @responses[regexp].last.nil? ||
								 @match_count[regexp] <= @responses[regexp].last )
		respond( @responses[regexp].first )
		@match_count[regexp] += 1
	elsif regexp
		raise "Exceeded limit of #{ @responses[regexp].last } for #{ regexp }"
	else
		raise "Can't find a response for " + arg
	end
end