diff options
-rw-r--r-- | lib/chef/knife/client_bulk_delete.rb | 2 | ||||
-rw-r--r-- | lib/chef/knife/cookbook_bulk_delete.rb | 2 | ||||
-rw-r--r-- | lib/chef/knife/core/ui.rb | 53 | ||||
-rw-r--r-- | spec/unit/knife/client_bulk_delete_spec.rb | 4 | ||||
-rw-r--r-- | spec/unit/knife/core/ui_spec.rb | 161 |
5 files changed, 142 insertions, 80 deletions
diff --git a/lib/chef/knife/client_bulk_delete.rb b/lib/chef/knife/client_bulk_delete.rb index 1e1d6af190..f2be772759 100644 --- a/lib/chef/knife/client_bulk_delete.rb +++ b/lib/chef/knife/client_bulk_delete.rb @@ -71,7 +71,7 @@ class Chef else ui.msg("The following validators will be deleted:") print_clients(validators) - if ui.confirm("Are you sure you want to delete these validators", true, false) + if ui.confirm_without_exit("Are you sure you want to delete these validators") destroy_clients(validators) end end diff --git a/lib/chef/knife/cookbook_bulk_delete.rb b/lib/chef/knife/cookbook_bulk_delete.rb index f8ad74d856..65fa888486 100644 --- a/lib/chef/knife/cookbook_bulk_delete.rb +++ b/lib/chef/knife/cookbook_bulk_delete.rb @@ -49,7 +49,7 @@ class Chef ui.msg "" unless config[:yes] - ui.confirm("Do you really want to delete these cookbooks? (Y/N) ", false) + ui.confirm("Do you really want to delete these cookbooks") if config[:purge] ui.msg("Files that are common to multiple cookbooks are shared, so purging the files may break other cookbooks.") diff --git a/lib/chef/knife/core/ui.rb b/lib/chef/knife/core/ui.rb index 5b86150fee..ff2545cfed 100644 --- a/lib/chef/knife/core/ui.rb +++ b/lib/chef/knife/core/ui.rb @@ -205,38 +205,61 @@ class Chef output(format_for_display(object)) if config[:print_after] end - def confirm(question, append_instructions=true, default_choice=nil) - return true if config[:yes] - + def confirmation_instructions(default_choice) case default_choice - when 'Y', 'y' - instructions = '? (Y/n)' - when 'N', 'n' - instructions = '? (y/N)' + when true + '? (Y/n)' + when false + '? (y/N)' else - instructions = '? (Y/N)' + '? (Y/N)' end + end + + # See confirm method for argument information + def confirm_without_exit(question, append_instructions=true, default_choice=nil) + return true if config[:yes] stdout.print question - stdout.print instructions if append_instructions + stdout.print confirmation_instructions(default_choice) if append_instructions + answer = stdin.readline answer.chomp! - answer == '' ? answer = default_choice : answer + case answer when "Y", "y" true when "N", "n" self.msg("You said no, so I'm done here.") - if should_exit - exit 3 + false + when "" + unless default_choice.nil? + default_choice else - false + self.msg("I have no idea what to do with '#{answer}'") + self.msg("Just say Y or N, please.") + confirm_without_exit(question, append_instructions, default_choice) end else - self.msg("I have no idea what to do with #{answer}") + self.msg("I have no idea what to do with '#{answer}'") self.msg("Just say Y or N, please.") - confirm(question) + confirm_without_exit(question, append_instructions, default_choice) + end + end + + # + # Not the ideal signature for a function but we need to stick with this + # for now until we get a chance to break our API in Chef 12. + # + # question => Question to print before asking for confirmation + # append_instructions => Should print '? (Y/N)' as instructions + # default_choice => Set to true for 'Y', and false for 'N' as default answer + # + def confirm(question, append_instructions=true, default_choice=nil) + unless confirm_without_exit(question, append_instructions, default_choice) + exit 3 end + true end end diff --git a/spec/unit/knife/client_bulk_delete_spec.rb b/spec/unit/knife/client_bulk_delete_spec.rb index f490851cbc..7df7d02e9b 100644 --- a/spec/unit/knife/client_bulk_delete_spec.rb +++ b/spec/unit/knife/client_bulk_delete_spec.rb @@ -28,6 +28,7 @@ describe Chef::Knife::ClientBulkDelete do k.config = option_args k.ui.stub(:stdout).and_return(stdout_io) k.ui.stub(:confirm).and_return(knife_confirm) + k.ui.stub(:confirm_without_exit).and_return(knife_confirm) k } @@ -132,7 +133,8 @@ describe Chef::Knife::ClientBulkDelete do end it "should confirm twice" do - knife.ui.should_receive(:confirm).twice + knife.ui.should_receive(:confirm).once + knife.ui.should_receive(:confirm_without_exit).once knife.run end diff --git a/spec/unit/knife/core/ui_spec.rb b/spec/unit/knife/core/ui_spec.rb index 74b3906067..9044bc2f2f 100644 --- a/spec/unit/knife/core/ui_spec.rb +++ b/spec/unit/knife/core/ui_spec.rb @@ -406,95 +406,132 @@ EOM end describe "confirm" do - before(:each) do - @question = "monkeys rule" - @stdout = StringIO.new - @ui.stub(:stdout).and_return(@stdout) - @ui.stdin.stub(:readline).and_return("y") + let(:stdout) {StringIO.new} + let(:output) {stdout.string} + + let(:question) { "monkeys rule" } + let(:answer) { 'y' } + + let(:default_choice) { nil } + let(:append_instructions) { true } + + def run_confirm + @ui.stub(:stdout).and_return(stdout) + @ui.stdin.stub(:readline).and_return(answer) + @ui.confirm(question, append_instructions, default_choice) end - it "should return true if you answer Y" do - @ui.stdin.stub(:readline).and_return("Y") - @ui.confirm(@question).should == true + def run_confirm_without_exit + @ui.stub(:stdout).and_return(stdout) + @ui.stdin.stub(:readline).and_return(answer) + @ui.confirm_without_exit(question, append_instructions, default_choice) end - it "should return true if you answer y" do - @ui.stdin.stub(:readline).and_return("y") - @ui.confirm(@question).should == true + shared_examples_for "confirm with positive answer" do + it "confirm should return true" do + run_confirm.should be_true + end + + it "confirm_without_exit should return true" do + run_confirm_without_exit.should be_true + end end - it "should exit 3 if you answer N" do - @ui.stdin.stub(:readline).and_return("N") - lambda { - @ui.confirm(@question) - }.should raise_error(SystemExit) { |e| e.status.should == 3 } + shared_examples_for "confirm with negative answer" do + it "confirm should exit 3" do + lambda { + run_confirm + }.should raise_error(SystemExit) { |e| e.status.should == 3 } + end + + it "confirm_without_exit should return false" do + run_confirm_without_exit.should be_false + end end - it "should exit 3 if you answer n" do - @ui.stdin.stub(:readline).and_return("n") - lambda { - @ui.confirm(@question) - }.should raise_error(SystemExit) { |e| e.status.should == 3 } + describe "with default choice set to true" do + let(:default_choice) { true } + + it "should show 'Y/n' in the instructions" do + run_confirm + output.should include("Y/n") + end + + describe "with empty answer" do + let(:answer) { "" } + + it_behaves_like "confirm with positive answer" + end + + describe "with answer N " do + let(:answer) { "N" } + + it_behaves_like "confirm with negative answer" + end end - describe "with 'Y' as a default choice" do - it 'should return true if you answer default' do - @ui.stdin.stub(:readline).and_return("\n") - @ui.confirm(@question, false, 'Y').should == true + describe "with default choice set to false" do + let(:default_choice) { false } + + it "should show 'y/N' in the instructions" do + run_confirm + output.should include("y/N") + end + + describe "with empty answer" do + let(:answer) { "" } + + it_behaves_like "confirm with negative answer" end - it "should show 'Y' as the default in the instructions" do - out = StringIO.new - @ui.stdin.stub(:readline).and_return("\n") - @ui.stub(:stdout).and_return(out) - @ui.confirm(@question, true, 'Y').should == true - out.string.should == "#{@question}? (Y/n)" + describe "with answer N " do + let(:answer) { "Y" } + + it_behaves_like "confirm with positive answer" end end - describe "with 'N' as a default choice" do - it 'should exit 3 if you answer default' do - @ui.stdin.stub(:readline).and_return("\n") - lambda { - @ui.confirm(@question, false, 'N') - }.should raise_error(SystemExit) { |e| e.status.should == 3 } + ["Y", "y"].each do |answer| + describe "with answer #{answer}" do + let(:answer) { answer } + + it_behaves_like "confirm with positive answer" end + end - it "should show 'N' as the default in the instructions" do - out = StringIO.new - @ui.stdin.stub(:readline).and_return("\n") - @ui.stub(:stdout).and_return(out) - lambda { - @ui.confirm(@question, true, 'N') - }.should raise_error(SystemExit) { |e| e.status.should == 3 } - out.string.should == "#{@question}? (y/N)You said no, so I'm done here.\n" + ["N", "n"].each do |answer| + describe "with answer #{answer}" do + let(:answer) { answer } + + it_behaves_like "confirm with negative answer" end end describe "with --y or --yes passed" do it "should return true" do @ui.config[:yes] = true - @ui.confirm(@question).should == true + run_confirm.should be_true + output.should eq("") end end + end - describe "when asking for free-form user input" do - it "asks a question and returns the answer provided by the user" do - out = StringIO.new - @ui.stub(:stdout).and_return(out) - @ui.stub(:stdin).and_return(StringIO.new("http://mychefserver.example.com\n")) - @ui.ask_question("your chef server URL?").should == "http://mychefserver.example.com" - out.string.should == "your chef server URL?" - end - - it "suggests a default setting and returns the default when the user's response only contains whitespace" do - out = StringIO.new - @ui.stub(:stdout).and_return(out) - @ui.stub(:stdin).and_return(StringIO.new(" \n")) - @ui.ask_question("your chef server URL? ", :default => 'http://localhost:4000').should == "http://localhost:4000" - out.string.should == "your chef server URL? [http://localhost:4000] " - end + describe "when asking for free-form user input" do + it "asks a question and returns the answer provided by the user" do + out = StringIO.new + @ui.stub(:stdout).and_return(out) + @ui.stub(:stdin).and_return(StringIO.new("http://mychefserver.example.com\n")) + @ui.ask_question("your chef server URL?").should == "http://mychefserver.example.com" + out.string.should == "your chef server URL?" end + it "suggests a default setting and returns the default when the user's response only contains whitespace" do + out = StringIO.new + @ui.stub(:stdout).and_return(out) + @ui.stub(:stdin).and_return(StringIO.new(" \n")) + @ui.ask_question("your chef server URL? ", :default => 'http://localhost:4000').should == "http://localhost:4000" + out.string.should == "your chef server URL? [http://localhost:4000] " + end end + end |