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

#initialize ⇒ MockCommandLineUser

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.



147
148
149
150
151
152
153
154
155
156
# File 'lib/easyprompt.rb', line 147

def initialize
	@responses = {}
	flush
	context = ContextualService::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

#flush ⇒ Object

Clears out the running count of how many times each response has been used.



160
# File 'lib/easyprompt.rb', line 160

def flush; @match_count = Hash.new( 1 ); end

#match_regexp ⇒ Object

:nodoc:



162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/easyprompt.rb', line 162

def match_regexp #:nodoc:
	arg = @mock_stdout.string
	if arg != ''
		@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
	else
		nil
	end
end

#respond(response) ⇒ Object

:nodoc:



177
178
179
180
181
182
# File 'lib/easyprompt.rb', line 177

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.



188
189
190
# File 'lib/easyprompt.rb', line 188

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

#update ⇒ Object

:nodoc:



192
193
194
195
196
197
198
199
200
201
# File 'lib/easyprompt.rb', line 192

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 }"
	end
end