spec/shelly/cli/main_spec.rb in shelly-0.0.10 vs spec/shelly/cli/main_spec.rb in shelly-0.0.11
- old
+ new
@@ -1,45 +1,379 @@
require "spec_helper"
require "shelly/cli/main"
describe Shelly::CLI::Main do
before do
+ ENV['SHELLY_GIT_HOST'] = nil
+ 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 "#register" do
- it "should invoke account:register command" do
- @main.should_receive(:invoke).with("account:register", "kate@example.com")
- @main.register("kate@example.com")
- end
- end
-
- describe "#add" do
- it "should invoke apps:add command" do
- @main.should_receive(:invoke).with("apps:add")
- @main.add
- end
- end
-
describe "#help" do
it "should display available commands" do
expected = <<-OUT
Tasks:
- shelly account <command> # Manages your account
- shelly add # Adds new application to Shelly Cloud
- shelly apps <command> # Manages your applications
- shelly help [TASK] # Describe available tasks or one specific task
- shelly register [EMAIL] # Registers new user account on Shelly Cloud
- shelly version # Displays shelly version
+ shelly add # Adds new application to Shelly Cloud
+ shelly help [TASK] # Describe available tasks or one specific task
+ shelly login [EMAIL] # Logins user to Shelly Cloud
+ shelly register [EMAIL] # Registers new user account on Shelly Cloud
+ shelly version # Displays shelly version
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")
+ 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", nil)
+ 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", nil)
+ 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("Email can't be blank, please try again")
+ lambda {
+ fake_stdin(["", "bob@example.com", "only-pass", "only-pass"]) do
+ @main.register
+ end
+ }.should raise_error(SystemExit)
+ end
+ end
+
+ context "when user enters blank password" do
+ it "should ask for it again" do
+ $stdout.should_receive(:puts).with("Password can't be blank")
+ fake_stdin(["better@example.com", "", "", "secret", "secret"]) do
+ @main.register
+ end
+ end
+ end
+
+ context "when user enters password and password confirmation which don't match each other" do
+ it "should ask for them again" do
+ $stdout.should_receive(:puts).with("Password and password confirmation don't match, please type them again")
+ fake_stdin(["better@example.com", "secret", "sec-TYPO-ret", "secret", "secret"]) do
+ @main.register
+ end
+ 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
+ $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)
+ @client.stub(:register_user).and_raise(exception)
+ $stdout.should_receive(:puts).with("email has been already taken")
+ 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
+ @user.stub(:upload_ssh_key)
+ @client.stub(:token).and_return("abc")
+ 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 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 display list of applications to which user has access"
+ end
+
+ context "on unauthorized user" do
+ it "should exit with 1 and display error message" do
+ exception = RestClient::Unauthorized.new
+ @client.stub(:token).and_raise(exception)
+ $stdout.should_receive(:puts).with("Wrong email or password or your email is unconfirmend")
+ 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(:remote_exists?).and_return(false)
+ 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("Must be run inside your project git repository")
+ lambda {
+ fake_stdin(["staging", "", ""]) do
+ @main.add
+ end
+ }.should raise_error(SystemExit)
+ end
+
+ it "should ask user how he will use application" do
+ $stdout.should_receive(:print).with("How will you use this system (production - default,staging): ")
+ @app.should_receive(:purpose=).with("staging")
+ fake_stdin(["staging", "", ""]) do
+ @main.add
+ end
+ end
+
+ context "when user provided empty purpose" do
+ it "should use 'production' as default" do
+ $stdout.should_receive(:print).with("How will you use this system (production - default,staging): ")
+ @app.should_receive(:purpose=).with("production")
+ fake_stdin(["", "", ""]) do
+ @main.add
+ end
+ end
+ end
+
+ it "should use code name provided by user" do
+ $stdout.should_receive(:print).with("How will you use this system (production - default,staging): ")
+ $stdout.should_receive(:print).with("Application code name (foo-staging - default): ")
+ @app.should_receive(:code_name=).with("mycodename")
+ fake_stdin(["staging", "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("How will you use this system (production - default,staging): ")
+ $stdout.should_receive(:print).with("Application code name (foo-staging - default): ")
+ fake_stdin(["staging", "", ""]) 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(["staging", "", "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(["staging", "", "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(["staging", "", ""]) 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)
+ @app.should_receive(:create).and_raise(exception)
+ $stdout.should_receive(:puts).with("code_name has been already taken")
+ lambda {
+ fake_stdin(["", "", ""]) do
+ @main.add
+ end
+ }.should raise_error(SystemExit)
+ end
+
+ context "git remote doesn't exist" do
+ it "should add git remote" do
+ $stdout.should_receive(:puts).with("\e[32mAdding remote staging git@git.shellycloud.com:foooo.git\e[0m")
+ @app.should_receive(:add_git_remote)
+ fake_stdin(["staging", "foooo", ""]) do
+ @main.add
+ end
+ end
+ end
+
+ context "git remote exist" do
+ before do
+ @app.stub(:remote_exists?).and_return(true)
+ end
+
+ it "should ask user if he wants to overwrite existing git remote" do
+ $stdout.should_receive(:puts).with("Remote staging already exists")
+ $stdout.should_receive(:print).with("Would you like to overwrite remote staging with git@git.shellycloud.com:foooo.git (Y/N)?: ")
+ fake_stdin(["staging", "foooo", "", "y"]) do
+ @main.add
+ end
+ end
+
+ it "should overwrite existing git remote on 'yes' from user" do
+ @app.should_receive(:add_git_remote).with(true)
+ fake_stdin(["staging", "foooo", "", "y"]) do
+ @main.add
+ end
+ end
+
+ it "should not overwrite existing git remote on 'no' from user" do
+ @app.should_not_receive(:add_git_remote).with(true)
+ fake_stdin(["staging", "foooo", "", "n"]) do
+ @main.add
+ end
+ end
+ end
+
+ it "should create Cloudfile" do
+ File.exists?("/projects/foo/Cloudfile").should be_false
+ fake_stdin(["staging", "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(["staging", "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(["staging", "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 staging using:\e[0m")
+ $stdout.should_receive(:puts).with(" git push staging master")
+ fake_stdin(["staging", "foooo", "none"]) do
+ @main.add
+ end
end
end
end