core: allow IO redirection of UI for testing
Use of $stdin, $stdout, and $stderr globals makes testing difficult. By exposing the IO objects as writable attributes, input/output can be more easily simulated using StringIO or doubles.
This commit is contained in:
parent
a8dcf92f14
commit
3b8bc2a433
|
@ -21,9 +21,22 @@ module Vagrant
|
|||
# specific. See the implementation for more docs.
|
||||
attr_accessor :opts
|
||||
|
||||
# @return [IO] UI input. Defaults to `$stdin`.
|
||||
attr_accessor :stdin
|
||||
|
||||
# @return [IO] UI output. Defaults to `$stdout`.
|
||||
attr_accessor :stdout
|
||||
|
||||
# @return [IO] UI error output. Defaults to `$stderr`.
|
||||
attr_accessor :stderr
|
||||
|
||||
def initialize
|
||||
@logger = Log4r::Logger.new("vagrant::ui::interface")
|
||||
@opts = {}
|
||||
|
||||
@stdin = $stdin
|
||||
@stdout = $stdout
|
||||
@stderr = $stderr
|
||||
end
|
||||
|
||||
def initialize_copy(original)
|
||||
|
@ -132,7 +145,7 @@ module Vagrant
|
|||
super(message)
|
||||
|
||||
# We can't ask questions when the output isn't a TTY.
|
||||
raise Errors::UIExpectsTTY if !$stdin.tty? && !Vagrant::Util::Platform.cygwin?
|
||||
raise Errors::UIExpectsTTY if !@stdin.tty? && !Vagrant::Util::Platform.cygwin?
|
||||
|
||||
# Setup the options so that the new line is suppressed
|
||||
opts ||= {}
|
||||
|
@ -144,11 +157,11 @@ module Vagrant
|
|||
say(:info, message, opts)
|
||||
|
||||
input = nil
|
||||
if opts[:echo]
|
||||
input = $stdin.gets
|
||||
if opts[:echo] || !@stdin.respond_to?(:noecho)
|
||||
input = @stdin.gets
|
||||
else
|
||||
begin
|
||||
input = $stdin.noecho(&:gets)
|
||||
input = @stdin.noecho(&:gets)
|
||||
|
||||
# Output a newline because without echo, the newline isn't
|
||||
# echoed either.
|
||||
|
@ -206,7 +219,7 @@ module Vagrant
|
|||
|
||||
# Determine the proper IO channel to send this message
|
||||
# to based on the type of the message
|
||||
channel = type == :error || opts[:channel] == :error ? $stderr : $stdout
|
||||
channel = type == :error || opts[:channel] == :error ? @stderr : @stdout
|
||||
|
||||
# Output! We wrap this in a lock so that it safely outputs only
|
||||
# one line at a time. We wrap this in a thread because as of Ruby 2.0
|
||||
|
|
|
@ -40,23 +40,37 @@ describe Vagrant::UI::Basic do
|
|||
subject.output("foo", new_line: false)
|
||||
end
|
||||
|
||||
it "outputs to stdout" do
|
||||
it "outputs to the assigned stdout" do
|
||||
stdout = StringIO.new
|
||||
subject.stdout = stdout
|
||||
|
||||
expect(subject).to receive(:safe_puts).with { |message, **opts|
|
||||
expect(opts[:io]).to be($stdout)
|
||||
expect(opts[:io]).to be(stdout)
|
||||
true
|
||||
}
|
||||
|
||||
subject.output("foo")
|
||||
end
|
||||
|
||||
it "outputs to stderr for errors" do
|
||||
it "outputs to stdout by default" do
|
||||
expect(subject.stdout).to be($stdout)
|
||||
end
|
||||
|
||||
it "outputs to the assigned stderr for errors" do
|
||||
stderr = StringIO.new
|
||||
subject.stderr = stderr
|
||||
|
||||
expect(subject).to receive(:safe_puts).with { |message, **opts|
|
||||
expect(opts[:io]).to be($stderr)
|
||||
expect(opts[:io]).to be(stderr)
|
||||
true
|
||||
}
|
||||
|
||||
subject.error("foo")
|
||||
end
|
||||
|
||||
it "outputs to stderr for errors by default" do
|
||||
expect(subject.stderr).to be($stderr)
|
||||
end
|
||||
end
|
||||
|
||||
context "#detail" do
|
||||
|
|
Loading…
Reference in New Issue