require "spec_helper" require "shelly/cli/main" describe Shelly::CLI::Main do before do FileUtils.stub(:chmod) @main = Shelly::CLI::Main.new @client = mock Shelly::Client.stub(:new).and_return(@client) Shelly::User.stub(:guess_email).and_return("") $stdout.stub(:puts) $stdout.stub(:print) end describe "#version" do it "should return shelly's version" do $stdout.should_receive(:puts).with("shelly version #{Shelly::VERSION}") @main.version end end describe "#help" do it "should display available commands" do expected = <<-OUT Tasks: shelly add # Adds new cloud to Shelly Cloud shelly delete CODE-NAME # Delete cloud from Shelly Cloud shelly deploys # View cloud deploy logs shelly help [TASK] # Describe available tasks or one specific task shelly ip # Lists clouds IP's shelly list # Lists all your clouds shelly login [EMAIL] # Logs user in to Shelly Cloud shelly register [EMAIL] # Registers new user account on Shelly Cloud shelly start [CODE-NAME] # Starts specific cloud shelly stop [CODE-NAME] # Stops specific cloud shelly user # Manages users using this cloud shelly version # Displays shelly version Options: [--debug] # Show debug information OUT out = IO.popen("bin/shelly").read.strip out.should == expected.strip end end describe "#register" do before do @client.stub(:register_user) @key_path = File.expand_path("~/.ssh/id_rsa.pub") @user = Shelly::User.new FileUtils.mkdir_p("~/.ssh") File.open("~/.ssh/id_rsa.pub", "w") { |f| f << "ssh-key AAbbcc" } @client.stub(:ssh_key_available?) Shelly::User.stub(:new).and_return(@user) end it "should return false if ssh key don't exist on local hard drive" do FileUtils.rm_rf(@key_path) File.exists?(@key_path).should be_false $stdout.should_receive(:puts).with("\e[31mNo such file or directory - " + @key_path + "\e[0m") $stdout.should_receive(:puts).with("\e[31mUse ssh-keygen to generate ssh key pair\e[0m") lambda { @main.register }.should raise_error(SystemExit) end it "should check ssh key in database" do @user.stub(:ssh_key_registered?).and_raise(RestClient::Conflict) $stdout.should_receive(:puts).with("\e[31mUser with your ssh key already exists.\e[0m") $stdout.should_receive(:puts).with("\e[31mYou can login using: shelly login [EMAIL]\e[0m") lambda { @main.register }.should raise_error(SystemExit) end it "should ask for email, password and password confirmation" do $stdout.should_receive(:print).with("Email: ") $stdout.should_receive(:print).with("Password: ") $stdout.should_receive(:print).with("Password confirmation: ") fake_stdin(["better@example.com", "secret", "secret"]) do @main.register end end it "should suggest email and use it if user enters blank email" do Shelly::User.stub(:guess_email).and_return("kate@example.com") $stdout.should_receive(:print).with("Email (kate@example.com - default): ") @client.should_receive(:register_user).with("kate@example.com", "secret", "ssh-key AAbbcc") fake_stdin(["", "secret", "secret"]) do @main.register end end it "should use email provided by user" do @client.should_receive(:register_user).with("better@example.com", "secret", "ssh-key AAbbcc") fake_stdin(["better@example.com", "secret", "secret"]) do @main.register end end it "should not ask about email if it's provided as argument" do $stdout.should_receive(:puts).with("Registering with email: kate@example.com") fake_stdin(["secret", "secret"]) do @main.register("kate@example.com") end end context "when user enters blank email" do it "should show error message and exit with 1" do Shelly::User.stub(:guess_email).and_return("") $stdout.should_receive(:puts).with("\e[31mEmail can't be blank, please try again\e[0m") lambda { fake_stdin(["", "bob@example.com", "only-pass", "only-pass"]) do @main.register end }.should raise_error(SystemExit) end end context "public SSH key exists" do it "should register with the public SSH key" do FileUtils.mkdir_p("~/.ssh") File.open(@key_path, "w") { |f| f << "key" } $stdout.should_receive(:puts).with("Uploading your public SSH key from #{@key_path}") fake_stdin(["kate@example.com", "secret", "secret"]) do @main.register end end end context "public SSH key doesn't exist" do it "should register user without the public SSH key" do @user.stub(:ssh_key_registered?) FileUtils.rm_rf(@key_path) $stdout.should_not_receive(:puts).with("Uploading your public SSH key from #{@key_path}") fake_stdin(["kate@example.com", "secret", "secret"]) do @main.register end end end context "on successful registration" do it "should display message about registration and email address confirmation" do @client.stub(:register_user).and_return(true) $stdout.should_receive(:puts).with("Successfully registered!") $stdout.should_receive(:puts).with("Check you mailbox for email address confirmation") fake_stdin(["kate@example.com", "pass", "pass"]) do @main.register end end end context "on unsuccessful registration" do it "should display errors and exit with 1" do response = {"message" => "Validation Failed", "errors" => [["email", "has been already taken"]]} exception = Shelly::Client::APIError.new(response.to_json) @client.stub(:register_user).and_raise(exception) $stdout.should_receive(:puts).with("\e[31mEmail has been already taken\e[0m") lambda { fake_stdin(["kate@example.com", "pass", "pass"]) do @main.register end }.should raise_error(SystemExit) end end end describe "#login" do before do @user = Shelly::User.new @key_path = File.expand_path("~/.ssh/id_rsa.pub") FileUtils.mkdir_p("~/.ssh") File.open("~/.ssh/id_rsa.pub", "w") { |f| f << "ssh-key AAbbcc" } @user.stub(:upload_ssh_key) @client.stub(:token).and_return("abc") @client.stub(:apps).and_return([{"code_name" => "abc", "state" => "running"}, {"code_name" => "fooo", "state" => "no_code"},]) Shelly::User.stub(:new).and_return(@user) end it "should ask about email and password" do fake_stdin(["megan@example.com", "secret"]) do @main.login end end context "on successful login" do it "should display message about successful login" do $stdout.should_receive(:puts).with("Login successful") fake_stdin(["megan@example.com", "secret"]) do @main.login end end it "should accept email as parameter" do $stdout.should_receive(:puts).with("Login successful") fake_stdin(["secret"]) do @main.login("megan@example.com") end end it "should upload user's public SSH key" do @user.should_receive(:upload_ssh_key) $stdout.should_receive(:puts).with("Uploading your public SSH key") fake_stdin(["megan@example.com", "secret"]) do @main.login end end it "should upload user's public SSH key and raise HTTP status 409 Conflict when SSH key exists in database" do @user.should_receive(:upload_ssh_key).and_raise(RestClient::Conflict) $stdout.should_receive(:puts).with("\e[32mYou have following clouds available:\e[0m") fake_stdin(["megan@example.com", "secret"]) do @main.login end end it "should display list of applications to which user has access" do $stdout.should_receive(:puts).with("\e[32mYou have following clouds available:\e[0m") $stdout.should_receive(:puts).with(/ abc\s+\| running/) $stdout.should_receive(:puts).with(/ fooo\s+\| no code/) fake_stdin(["megan@example.com", "secret"]) do @main.login end end end context "when local ssh key doesn't exists" do it "should display error message and return exit with 1" do FileUtils.rm_rf(@key_path) File.exists?(@key_path).should be_false $stdout.should_receive(:puts).with("\e[31mNo such file or directory - " + @key_path + "\e[0m") $stdout.should_receive(:puts).with("\e[31mUse ssh-keygen to generate ssh key pair\e[0m") lambda { @main.login }.should raise_error(SystemExit) end end context "on unauthorized user" do it "should exit with 1 and display error message" do response = {"message" => "Unauthorized", "url" => "https://admin.winniecloud.com/users/password/new"} exception = Shelly::Client::APIError.new(response.to_json) @client.stub(:token).and_raise(exception) $stdout.should_receive(:puts).with("\e[31mWrong email or password\e[0m") $stdout.should_receive(:puts).with("\e[31mYou can reset password by using link:\e[0m") $stdout.should_receive(:puts).with("\e[31mhttps://admin.winniecloud.com/users/password/new\e[0m") lambda { fake_stdin(["megan@example.com", "secret"]) do @main.login end }.should raise_error(SystemExit) end end end describe "#add" do before do FileUtils.mkdir_p("/projects/foo") Dir.chdir("/projects/foo") @app = Shelly::App.new @app.stub(:add_git_remote) @app.stub(:create) @app.stub(:generate_cloudfile).and_return("Example Cloudfile") @app.stub(:open_billing_page) @app.stub(:git_url).and_return("git@git.shellycloud.com:foooo.git") Shelly::App.stub(:inside_git_repository?).and_return(true) Shelly::App.stub(:new).and_return(@app) end it "should exit with message if command run outside git repository" do Shelly::App.stub(:inside_git_repository?).and_return(false) $stdout.should_receive(:puts).with("\e[31mMust be run inside your project git repository\e[0m") lambda { fake_stdin(["", ""]) do @main.add end }.should raise_error(SystemExit) end context "command line options" do context "invalid params" do it "should show help and exit if not all options are passed" do $stdout.should_receive(:puts).with("\e[31mTry 'shelly help add' for more information\e[0m") @main.options = {"code-name" => "foo"} lambda { @main.add }.should raise_error(SystemExit) end it "should exit if databases are not valid" do $stdout.should_receive(:puts).with("\e[31mTry 'shelly help add' for more information\e[0m") @main.options = {"code-name" => "foo", "databases" => ["not existing"], "domains" => ["foo.example.com"]} lambda { @main.add }.should raise_error(SystemExit) end it "should display which parameter was wrong" do expected = "shelly: unrecognized option '--unknown=param'\n" + "Usage: shelly [COMMAND]... [OPTIONS]\n" + "Try 'shelly --help' for more information" Open3.popen3("bin/shelly add --unknown=param") do |stdin, stdout, stderr, wait_thr| out = stderr.read.strip out.should == expected end end end context "valid params" do it "should create app on shelly cloud" do @app.should_receive(:create) @main.options = {"code-name" => "foo", "databases" => ["postgresql"], "domains" => ["foo.example.com"]} @main.add end end end it "should use code name provided by user" do $stdout.should_receive(:print).with("Cloud code name (foo-production - default): ") @app.should_receive(:code_name=).with("mycodename") fake_stdin(["mycodename", ""]) do @main.add end end context "when user provided empty code name" do it "should use 'current_dirname-purpose' as default" do $stdout.should_receive(:print).with("Cloud code name (foo-production - default): ") @app.should_receive(:code_name=).with("foo-production") fake_stdin(["", ""]) do @main.add end end end it "should use database provided by user (separated by comma or space)" do $stdout.should_receive(:print).with("Which database do you want to use postgresql, mongodb, redis, none (postgresql - default): ") @app.should_receive(:databases=).with(["postgresql", "mongodb", "redis"]) fake_stdin(["", "postgresql ,mongodb redis"]) do @main.add end end it "should ask again for databases if unsupported kind typed" do $stdout.should_receive(:print).with("Which database do you want to use postgresql, mongodb, redis, none (postgresql - default): ") $stdout.should_receive(:print).with("Unknown database kind. Supported are: postgresql, mongodb, redis, none: ") fake_stdin(["", "postgresql,doesnt-exist", "none"]) do @main.add end end context "when user provided empty database" do it "should use 'postgresql' database as default" do @app.should_receive(:databases=).with(["postgresql"]) fake_stdin(["", ""]) do @main.add end end end it "should create the app on shelly cloud" do @app.should_receive(:create) fake_stdin(["", ""]) do @main.add end end it "should display validation errors if they are any" do response = {"message" => "Validation Failed", "errors" => [["code_name", "has been already taken"]]} exception = Shelly::Client::APIError.new(response.to_json) @app.should_receive(:create).and_raise(exception) $stdout.should_receive(:puts).with("\e[31mCode name has been already taken\e[0m") $stdout.should_receive(:puts).with("\e[31mFix erros in the below command and type it again to create your cloud\e[0m") $stdout.should_receive(:puts).with("\e[31mshelly add --code-name=foo-production --databases=postgresql --domains=foo-production.shellyapp.com\e[0m") lambda { fake_stdin(["", ""]) do @main.add end }.should raise_error(SystemExit) end it "should add git remote" do $stdout.should_receive(:puts).with("\e[32mAdding remote production git@git.shellycloud.com:foooo.git\e[0m") @app.should_receive(:add_git_remote) fake_stdin(["foooo", ""]) do @main.add end end it "should create Cloudfile" do File.exists?("/projects/foo/Cloudfile").should be_false fake_stdin(["foooo", ""]) do @main.add end File.read("/projects/foo/Cloudfile").should == "Example Cloudfile" end it "should browser window with link to edit billing information" do $stdout.should_receive(:puts).with("\e[32mProvide billing details. Opening browser...\e[0m") @app.should_receive(:open_billing_page) fake_stdin(["foooo", ""]) do @main.add end end it "should display info about adding Cloudfile to repository" do $stdout.should_receive(:puts).with("\e[32mProject is now configured for use with Shell Cloud:\e[0m") $stdout.should_receive(:puts).with("\e[32mYou can review changes using\e[0m") $stdout.should_receive(:puts).with(" git status") fake_stdin(["foooo", "none"]) do @main.add end end it "should display info on how to deploy to ShellyCloud" do $stdout.should_receive(:puts).with("\e[32mWhen you make sure all settings are correct please issue following commands:\e[0m") $stdout.should_receive(:puts).with(" git add .") $stdout.should_receive(:puts).with(' git commit -m "Application added to Shelly Cloud"') $stdout.should_receive(:puts).with(" git push") $stdout.should_receive(:puts).with("\e[32mDeploy to production using:\e[0m") $stdout.should_receive(:puts).with(" git push production master") fake_stdin(["foooo", "none"]) do @main.add end end end describe "#list" do before do @user = Shelly::User.new @client.stub(:token).and_return("abc") @client.stub(:apps).and_return([{"code_name" => "abc", "state" => "running"}, {"code_name" => "fooo", "state" => "deploy_failed"}]) Shelly::User.stub(:new).and_return(@user) end it "should display user's clouds" do $stdout.should_receive(:puts).with("\e[32mYou have following clouds available:\e[0m") $stdout.should_receive(:puts).with(/abc\s+\| running/) $stdout.should_receive(:puts).with(/fooo\s+\| deploy failed \(Support has been notified\)/) @main.list end it "should display info that user has no clouds" do @client.stub(:apps).and_return([]) $stdout.should_receive(:puts).with("\e[32mYou have no clouds yet\e[0m") @main.list end it "should have a 'status' alias" do @client.stub(:apps).and_return([]) $stdout.should_receive(:puts).with("\e[32mYou have no clouds yet\e[0m") Shelly::CLI::Main.start(["status"]) end context "on failure" do it "should display info that user is not logged in" do body = {"message" => "Unauthorized"} error = Shelly::Client::APIError.new(body.to_json) @client.stub(:token).and_raise(error) $stdout.should_receive(:puts).with("\e[31mYou are not logged in, use `shelly login`\e[0m") lambda { @main.list }.should raise_error(SystemExit) end end end describe "#start" do before do @user = Shelly::User.new @client.stub(:token).and_return("abc") FileUtils.mkdir_p("/projects/foo") Dir.chdir("/projects/foo") File.open("Cloudfile", 'w') {|f| f.write("foo-production:\n") } Shelly::User.stub(:new).and_return(@user) @client.stub(:apps).and_return([{"code_name" => "foo-production"}, {"code_name" => "foo-staging"}]) @app = Shelly::App.new Shelly::App.stub(:new).and_return(@app) end it "should exit if there is no Cloudfile" do File.delete("Cloudfile") $stdout.should_receive(:puts).with("\e[31mNo Cloudfile found\e[0m") lambda { @main.start }.should raise_error(SystemExit) end it "should exit if user doesn't have access to clouds in Cloudfile" do response = {"message" => "Cloud foo-production not found"} exception = Shelly::Client::APIError.new(response.to_json) @client.stub(:start_cloud).and_raise(exception) $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile") lambda { @main.start }.should raise_error(SystemExit) end it "should exit if user is not logged in" do response = {"message" => "Unauthorized"} exception = Shelly::Client::APIError.new(response.to_json) @client.stub(:token).and_raise(exception) $stdout.should_receive(:puts).with(red "You are not logged in. To log in use:") $stdout.should_receive(:puts).with(" shelly login") lambda { @main.start }.should raise_error(SystemExit) end context "single cloud in Cloudfile" do it "should start the cloud" do @client.stub(:start_cloud) $stdout.should_receive(:puts).with(green "Starting cloud foo-production. Check status with:") $stdout.should_receive(:puts).with(" shelly list") @main.start end end context "multiple clouds in Cloudfile" do before do File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") } end it "should show information to start specific cloud and exit" do $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Select which to start using:") $stdout.should_receive(:puts).with(" shelly start foo-production") $stdout.should_receive(:puts).with("Available clouds:") $stdout.should_receive(:puts).with(" * foo-production") $stdout.should_receive(:puts).with(" * foo-staging") lambda { @main.start }.should raise_error(SystemExit) end it "should fetch from command line which cloud to start" do @client.should_receive(:start_cloud).with("foo-staging") $stdout.should_receive(:puts).with(green "Starting cloud foo-staging. Check status with:") $stdout.should_receive(:puts).with(" shelly list") @main.start("foo-staging") end end context "on failure" do it "should show information that cloud is running" do raise_conflict(:state => "running") $stdout.should_receive(:puts).with(red "Not starting: cloud 'foo-production' is already running") lambda { @main.start }.should raise_error(SystemExit) end %w{deploying configuring}.each do |state| it "should show information that cloud is #{state}" do raise_conflict(:state => state) $stdout.should_receive(:puts).with(red "Not starting: cloud 'foo-production' is currently deploying") lambda { @main.start }.should raise_error(SystemExit) end end it "should show information that cloud has no code" do raise_conflict(:state => "no_code") $stdout.should_receive(:puts).with(red "Not starting: no source code provided") $stdout.should_receive(:puts).with(red "Push source code using:") $stdout.should_receive(:puts).with(" git push production master") lambda { @main.start }.should raise_error(SystemExit) end %w{deploy_failed configuration_failed}.each do |state| it "should show information that cloud #{state}" do raise_conflict(:state => state, :link => "http://example.com/logs") $stdout.should_receive(:puts).with(red "Not starting: deployment failed") $stdout.should_receive(:puts).with(red "Support has been notified") $stdout.should_receive(:puts).with(red "See http://example.com/logs for reasons of failure") lambda { @main.start }.should raise_error(SystemExit) end end it "should open billing page" do raise_conflict(:state => "no_billing") $stdout.should_receive(:puts).with(red "Please fill in billing details to start foo-production. Opening browser.") @app.should_receive(:open_billing_page) lambda { @main.start }.should raise_error(SystemExit) end def raise_conflict(options = {}) options = {:state => "no_code"}.merge(options) exception = RestClient::Conflict.new exception.stub(:response).and_return(options.to_json) @client.stub(:start_cloud).and_raise(exception) end end end describe "#stop" do before do @user = Shelly::User.new @client.stub(:token).and_return("abc") FileUtils.mkdir_p("/projects/foo") Dir.chdir("/projects/foo") File.open("Cloudfile", 'w') {|f| f.write("foo-production:\n") } Shelly::User.stub(:new).and_return(@user) @client.stub(:apps).and_return([{"code_name" => "foo-production"}, {"code_name" => "foo-staging"}]) @app = Shelly::App.new Shelly::App.stub(:new).and_return(@app) end it "should exit if there is no Cloudfile" do File.delete("Cloudfile") $stdout.should_receive(:puts).with("\e[31mNo Cloudfile found\e[0m") lambda { @main.stop }.should raise_error(SystemExit) end it "should exit if user doesn't have access to clouds in Cloudfile" do response = {"message" => "Cloud foo-production not found"} exception = Shelly::Client::APIError.new(response.to_json) @client.stub(:stop_cloud).and_raise(exception) $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile") lambda { @main.stop }.should raise_error(SystemExit) end it "should exit if user is not logged in" do response = {"message" => "Unauthorized"} exception = Shelly::Client::APIError.new(response.to_json) @client.stub(:token).and_raise(exception) $stdout.should_receive(:puts).with(red "You are not logged in. To log in use:") $stdout.should_receive(:puts).with(" shelly login") lambda { @main.stop }.should raise_error(SystemExit) end context "single cloud in Cloudfile" do it "should start the cloud" do @client.stub(:stop_cloud) $stdout.should_receive(:puts).with("Cloud 'foo-production' stopped") @main.stop end end context "multiple clouds in Cloudfile" do before do File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") } end it "should show information to start specific cloud and exit" do $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Select which to stop using:") $stdout.should_receive(:puts).with(" shelly stop foo-production") $stdout.should_receive(:puts).with("Available clouds:") $stdout.should_receive(:puts).with(" * foo-production") $stdout.should_receive(:puts).with(" * foo-staging") lambda { @main.stop }.should raise_error(SystemExit) end it "should fetch from command line which cloud to start" do @client.should_receive(:stop_cloud).with("foo-staging") $stdout.should_receive(:puts).with("Cloud 'foo-staging' stopped") @main.stop("foo-staging") end end end describe "#ips" do before do File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") } Shelly::App.stub(:inside_git_repository?).and_return(true) end it "should exit with message if command run outside git repository" do Shelly::App.stub(:inside_git_repository?).and_return(false) $stdout.should_receive(:puts).with("\e[31mMust be run inside your project git repository\e[0m") lambda { @main.ip }.should raise_error(SystemExit) end it "should exit with message if there is no Cloudfile" do File.delete("Cloudfile") $stdout.should_receive(:puts).with("\e[31mNo Cloudfile found\e[0m") lambda { @main.ip }.should raise_error(SystemExit) end context "on success" do it "should display mail and web server ip's" do @client.stub(:app_ips).and_return(response) $stdout.should_receive(:puts).with("\e[32mCloud foo-production:\e[0m") $stdout.should_receive(:puts).with(" Web server IP: 22.22.22.22") $stdout.should_receive(:puts).with(" Mail server IP: 11.11.11.11") @main.ip end end def response {'mail_server_ip' => '11.11.11.11', 'web_server_ip' => '22.22.22.22'} end context "on failure" do it "should raise an error if user is not in git repository" do Shelly::App.stub(:inside_git_repository?).and_return(false) $stdout.should_receive(:puts).with("\e[31mMust be run inside your project git repository\e[0m") lambda { @main.ip }.should raise_error(SystemExit) end it "should raise an error if user does not have access to cloud" do response = {"message" => "Cloud foo-staging not found"} exception = Shelly::Client::APIError.new(response.to_json) @client.stub(:app_ips).and_raise(exception) $stdout.should_receive(:puts).with(red "You have no access to 'foo-staging' cloud defined in Cloudfile") @main.ip end end end describe "#delete" do before do Shelly::App.stub(:inside_git_repository?).and_return(true) @user = Shelly::User.new @app = Shelly::App.new @client.stub(:token).and_return("abc") @app.stub(:delete) Shelly::User.stub(:new).and_return(@user) Shelly::App.stub(:new).and_return(@app) end context "when code_name is not nil" do it "should ask about delete application parts" do $stdout.should_receive(:puts).with("You are about to delete application: foo-bar.") $stdout.should_receive(:puts).with("Press Control-C at any moment to cancel.") $stdout.should_receive(:puts).with("Please confirm each question by typing yes and pressing Enter.") $stdout.should_receive(:puts).with("\n") $stdout.should_receive(:print).with("I want to delete all files stored on Shelly Cloud (yes/no): ") $stdout.should_receive(:print).with("I want to delete all database data stored on Shelly Cloud (yes/no): ") $stdout.should_receive(:print).with("I want to delete the application (yes/no): ") $stdout.should_receive(:puts).with("\n") $stdout.should_receive(:puts).with("Scheduling application delete - done") $stdout.should_receive(:puts).with("Removing git remote - done") fake_stdin(["yes", "yes", "yes"]) do @main.delete("foo-bar") end end it "should return exit 1 when user doesn't type 'yes'" do lambda{ fake_stdin(["yes", "yes", "no"]) do @main.delete("foo-bar") end }.should raise_error(SystemExit) end end context "when git repository doesn't exist" do it "should say that Git remote missing" do Shelly::App.stub(:inside_git_repository?).and_return(false) $stdout.should_receive(:puts).with("Missing git remote") fake_stdin(["yes", "yes", "yes"]) do @main.delete("foo-bar") end end end context "when application with CODE-NAME doesn't exist" do it "should raise Client::APIError" do response = {:message => "Application not found"} exception = Shelly::Client::APIError.new(response.to_json) @app.stub(:delete).and_raise(exception) $stdout.should_receive(:puts).with("\e[31mApplication not found\e[0m") lambda{ fake_stdin(["yes", "yes", "yes"]) do @main.delete("foo-bar") end }.should raise_error(SystemExit) end end context "when code_name is nil" do it "should display error when no code_name" do $stdout.should_receive(:puts).with("\e[31mMissing CODE-NAME\e[0m") $stdout.should_receive(:puts).with("\e[31mUse: shelly delete CODE-NAME\e[0m") lambda{ @main.delete }.should raise_error(SystemExit) end end end end