cf 0.1.5 → 0.6.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. data/LICENSE +1277 -30
  2. data/Rakefile +12 -1
  3. data/bin/cf +0 -3
  4. data/lib/cf.rb +6 -0
  5. data/lib/cf/cli.rb +389 -190
  6. data/lib/cf/cli/app/app.rb +45 -0
  7. data/lib/cf/cli/app/apps.rb +99 -0
  8. data/lib/cf/cli/app/base.rb +90 -0
  9. data/lib/cf/cli/app/crashes.rb +42 -0
  10. data/lib/cf/cli/app/delete.rb +95 -0
  11. data/lib/cf/cli/app/deprecated.rb +11 -0
  12. data/lib/cf/cli/app/env.rb +78 -0
  13. data/lib/cf/cli/app/files.rb +137 -0
  14. data/lib/cf/cli/app/health.rb +26 -0
  15. data/lib/cf/cli/app/instances.rb +53 -0
  16. data/lib/cf/cli/app/logs.rb +76 -0
  17. data/lib/cf/cli/app/push.rb +105 -0
  18. data/lib/cf/cli/app/push/create.rb +149 -0
  19. data/lib/cf/cli/app/push/interactions.rb +94 -0
  20. data/lib/cf/cli/app/push/sync.rb +64 -0
  21. data/lib/cf/cli/app/rename.rb +35 -0
  22. data/lib/cf/cli/app/restart.rb +20 -0
  23. data/lib/cf/cli/app/scale.rb +69 -0
  24. data/lib/cf/cli/app/start.rb +143 -0
  25. data/lib/cf/cli/app/stats.rb +67 -0
  26. data/lib/cf/cli/app/stop.rb +27 -0
  27. data/lib/cf/cli/domain/base.rb +8 -0
  28. data/lib/cf/cli/domain/domains.rb +40 -0
  29. data/lib/cf/cli/domain/map.rb +55 -0
  30. data/lib/cf/cli/domain/unmap.rb +56 -0
  31. data/lib/cf/cli/help.rb +15 -0
  32. data/lib/cf/cli/interactive.rb +105 -0
  33. data/lib/cf/cli/organization/base.rb +12 -0
  34. data/lib/cf/cli/organization/create.rb +32 -0
  35. data/lib/cf/cli/organization/delete.rb +73 -0
  36. data/lib/cf/cli/organization/org.rb +45 -0
  37. data/lib/cf/cli/organization/orgs.rb +35 -0
  38. data/lib/cf/cli/organization/rename.rb +36 -0
  39. data/lib/cf/cli/route/base.rb +8 -0
  40. data/lib/cf/cli/route/map.rb +70 -0
  41. data/lib/cf/cli/route/routes.rb +26 -0
  42. data/lib/cf/cli/route/unmap.rb +62 -0
  43. data/lib/cf/cli/service/base.rb +8 -0
  44. data/lib/cf/cli/service/bind.rb +44 -0
  45. data/lib/cf/cli/service/create.rb +107 -0
  46. data/lib/cf/cli/service/delete.rb +82 -0
  47. data/lib/cf/cli/service/rename.rb +35 -0
  48. data/lib/cf/cli/service/service.rb +40 -0
  49. data/lib/cf/cli/service/services.rb +99 -0
  50. data/lib/cf/cli/service/unbind.rb +38 -0
  51. data/lib/cf/cli/space/base.rb +19 -0
  52. data/lib/cf/cli/space/create.rb +63 -0
  53. data/lib/cf/cli/space/delete.rb +95 -0
  54. data/lib/cf/cli/space/rename.rb +39 -0
  55. data/lib/cf/cli/space/space.rb +64 -0
  56. data/lib/cf/cli/space/spaces.rb +55 -0
  57. data/lib/cf/cli/space/switch.rb +16 -0
  58. data/lib/cf/cli/start/base.rb +93 -0
  59. data/lib/cf/cli/start/colors.rb +13 -0
  60. data/lib/cf/cli/start/info.rb +124 -0
  61. data/lib/cf/cli/start/login.rb +94 -0
  62. data/lib/cf/cli/start/logout.rb +17 -0
  63. data/lib/cf/cli/start/target.rb +69 -0
  64. data/lib/cf/cli/start/target_interactions.rb +37 -0
  65. data/lib/cf/cli/start/targets.rb +16 -0
  66. data/lib/cf/cli/user/base.rb +29 -0
  67. data/lib/cf/cli/user/create.rb +39 -0
  68. data/lib/cf/cli/user/passwd.rb +43 -0
  69. data/lib/cf/cli/user/register.rb +42 -0
  70. data/lib/cf/cli/user/users.rb +32 -0
  71. data/lib/cf/constants.rb +10 -7
  72. data/lib/cf/detect.rb +113 -48
  73. data/lib/cf/errors.rb +17 -0
  74. data/lib/cf/plugin.rb +28 -12
  75. data/lib/cf/spacing.rb +89 -0
  76. data/lib/cf/spec_helper.rb +1 -0
  77. data/lib/cf/test_support.rb +6 -0
  78. data/lib/cf/version.rb +1 -1
  79. data/spec/assets/hello-sinatra/Gemfile +3 -0
  80. data/spec/assets/hello-sinatra/Gemfile.lock +17 -0
  81. data/spec/assets/hello-sinatra/config.ru +3 -0
  82. data/spec/assets/hello-sinatra/fat-cat-makes-app-larger.png +0 -0
  83. data/spec/assets/hello-sinatra/main.rb +6 -0
  84. data/spec/assets/specker_runner/specker_runner_input.rb +6 -0
  85. data/spec/assets/specker_runner/specker_runner_pause.rb +5 -0
  86. data/spec/cf/cli/app/base_spec.rb +17 -0
  87. data/spec/cf/cli/app/delete_spec.rb +188 -0
  88. data/spec/cf/cli/app/instances_spec.rb +65 -0
  89. data/spec/cf/cli/app/push/create_spec.rb +661 -0
  90. data/spec/cf/cli/app/push_spec.rb +369 -0
  91. data/spec/cf/cli/app/rename_spec.rb +104 -0
  92. data/spec/cf/cli/app/scale_spec.rb +75 -0
  93. data/spec/cf/cli/app/start_spec.rb +208 -0
  94. data/spec/cf/cli/app/stats_spec.rb +68 -0
  95. data/spec/cf/cli/domain/map_spec.rb +130 -0
  96. data/spec/cf/cli/domain/unmap_spec.rb +69 -0
  97. data/spec/cf/cli/organization/orgs_spec.rb +108 -0
  98. data/spec/cf/cli/organization/rename_spec.rb +113 -0
  99. data/spec/cf/cli/route/map_spec.rb +121 -0
  100. data/spec/cf/cli/route/unmap_spec.rb +155 -0
  101. data/spec/cf/cli/service/bind_spec.rb +25 -0
  102. data/spec/cf/cli/service/delete_spec.rb +22 -0
  103. data/spec/cf/cli/service/rename_spec.rb +105 -0
  104. data/spec/cf/cli/service/service_spec.rb +23 -0
  105. data/spec/cf/cli/service/unbind_spec.rb +25 -0
  106. data/spec/cf/cli/space/create_spec.rb +93 -0
  107. data/spec/cf/cli/space/rename_spec.rb +102 -0
  108. data/spec/cf/cli/space/spaces_spec.rb +104 -0
  109. data/spec/cf/cli/space/switch_space_spec.rb +55 -0
  110. data/spec/cf/cli/start/info_spec.rb +160 -0
  111. data/spec/cf/cli/start/login_spec.rb +142 -0
  112. data/spec/cf/cli/start/logout_spec.rb +50 -0
  113. data/spec/cf/cli/start/target_spec.rb +123 -0
  114. data/spec/cf/cli/user/create_spec.rb +54 -0
  115. data/spec/cf/cli/user/passwd_spec.rb +102 -0
  116. data/spec/cf/cli/user/register_spec.rb +140 -0
  117. data/spec/cf/cli_spec.rb +442 -0
  118. data/spec/cf/detect_spec.rb +54 -0
  119. data/spec/console_app_specker/console_app_specker_matchers_spec.rb +173 -0
  120. data/spec/console_app_specker/specker_runner_spec.rb +167 -0
  121. data/spec/features/account_lifecycle_spec.rb +85 -0
  122. data/spec/features/login_spec.rb +66 -0
  123. data/spec/features/push_flow_spec.rb +125 -0
  124. data/spec/features/switching_targets_spec.rb +32 -0
  125. data/spec/spec_helper.rb +72 -0
  126. data/spec/support/command_helper.rb +81 -0
  127. data/spec/support/config_helper.rb +15 -0
  128. data/spec/support/console_app_specker_matchers.rb +86 -0
  129. data/spec/support/fake_home_dir.rb +55 -0
  130. data/spec/support/interact_helper.rb +29 -0
  131. data/spec/support/shared_examples/errors.rb +40 -0
  132. data/spec/support/shared_examples/input.rb +14 -0
  133. data/spec/support/specker_runner.rb +80 -0
  134. data/spec/support/tracking_expector.rb +71 -0
  135. metadata +427 -66
  136. data/lib/cf/cli/app.rb +0 -595
  137. data/lib/cf/cli/command.rb +0 -444
  138. data/lib/cf/cli/dots.rb +0 -133
  139. data/lib/cf/cli/service.rb +0 -112
  140. data/lib/cf/cli/user.rb +0 -71
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+ require "cf/cli/space/switch"
3
+
4
+ describe CF::Space::Switch do
5
+ let(:space_to_switch_to) { spaces.last }
6
+ let(:spaces) { fake_list(:space, 3) }
7
+ let(:organization) { fake(:organization, :spaces => spaces) }
8
+ let(:client) { fake_client(:current_organization => organization, :spaces => spaces) }
9
+
10
+ before do
11
+ any_instance_of described_class do |cli|
12
+ stub(cli).client { client }
13
+ stub(cli).precondition { nil }
14
+ end
15
+ end
16
+
17
+ describe 'metadata' do
18
+ let(:command) { Mothership.commands[:switch_space] }
19
+
20
+ describe 'command' do
21
+ subject { command }
22
+ its(:description) { should eq "Switch to a space" }
23
+ it { expect(Mothership::Help.group(:spaces)).to include(subject) }
24
+ end
25
+
26
+ include_examples 'inputs must have descriptions'
27
+
28
+ describe 'arguments' do
29
+ subject { command.arguments }
30
+ it 'has the correct argument order' do
31
+ should eq([{ :type => :normal, :value => nil, :name => :name }])
32
+ end
33
+ end
34
+ end
35
+
36
+ subject { cf %W[--no-quiet switch-space #{space_to_switch_to.name} --no-color] }
37
+
38
+ context "when the space exists" do
39
+ it "switches to that space" do
40
+ any_instance_of(Mothership) do |m|
41
+ mock(m).invoke(:target, {:space => space_to_switch_to})
42
+ end
43
+
44
+ subject
45
+ end
46
+ end
47
+
48
+ context "when the space does not exist" do
49
+ let(:space_to_switch_to) { fake(:space, :name => "unique-name") }
50
+
51
+ it_behaves_like "an error that gets passed through",
52
+ :with_exception => CF::UserError,
53
+ :with_message => "The space unique-name does not exist, please create the space first."
54
+ end
55
+ end
@@ -0,0 +1,160 @@
1
+ require 'spec_helper'
2
+
3
+ describe CF::Start::Info do
4
+ let(:frameworks) { false }
5
+ let(:runtimes) { false }
6
+ let(:services) { false }
7
+ let(:all) { false }
8
+
9
+ let(:client) do
10
+ fake_client :frameworks => fake_list(:framework, 3),
11
+ :runtimes => fake_list(:runtime, 3),
12
+ :services => fake_list(:service, 3),
13
+ :token => CFoundry::AuthToken.new("bearer some-access-token")
14
+ end
15
+
16
+ let(:target_info) do
17
+ { :description => "Some description",
18
+ :version => 2,
19
+ :support => "http://example.com"
20
+ }
21
+ end
22
+
23
+ before do
24
+ any_instance_of described_class do |cli|
25
+ stub(cli).client { client }
26
+ end
27
+ end
28
+
29
+ describe 'metadata' do
30
+ let(:command) { Mothership.commands[:info] }
31
+
32
+ describe 'command' do
33
+ subject { command }
34
+ its(:description) { should eq "Display information on the current target, user, etc." }
35
+ it { expect(Mothership::Help.group(:start)).to include(subject) }
36
+ end
37
+
38
+ include_examples 'inputs must have descriptions'
39
+
40
+ describe 'flags' do
41
+ subject { command.flags }
42
+
43
+ its(["-f"]) { should eq :frameworks }
44
+ its(["-r"]) { should eq :runtimes }
45
+ its(["-s"]) { should eq :services }
46
+ its(["-a"]) { should eq :all }
47
+ end
48
+
49
+ describe 'arguments' do
50
+ subject { command.arguments }
51
+ it { should be_empty }
52
+ end
53
+ end
54
+
55
+
56
+ subject { cf %W[info --#{bool_flag(:frameworks)} --#{bool_flag(:runtimes)} --#{bool_flag(:services)} --#{bool_flag(:all)} --no-force --no-quiet] }
57
+
58
+ context 'when given no flags' do
59
+ it "displays target information" do
60
+ mock(client).info { target_info }
61
+
62
+ subject
63
+
64
+ stdout.rewind
65
+ expect(stdout.readline).to eq "Some description\n"
66
+ expect(stdout.readline).to eq "\n"
67
+ expect(stdout.readline).to eq "target: #{client.target}\n"
68
+ expect(stdout.readline).to eq " version: 2\n"
69
+ expect(stdout.readline).to eq " support: http://example.com\n"
70
+ end
71
+ end
72
+
73
+ context 'when given --frameworks' do
74
+ let(:frameworks) { true }
75
+
76
+ it 'does not grab /info' do
77
+ dont_allow(client).info
78
+ subject
79
+ end
80
+
81
+ it 'lists frameworks on the target' do
82
+ subject
83
+
84
+ stdout.rewind
85
+ expect(stdout.readline).to match /Getting frameworks.*OK/
86
+ expect(stdout.readline).to eq "\n"
87
+ expect(stdout.readline).to match /framework\s+description/
88
+
89
+ client.frameworks.sort_by(&:name).each do |f|
90
+ expect(stdout.readline).to match /#{f.name}\s+#{f.description}/
91
+ end
92
+ end
93
+ end
94
+
95
+ context 'when given --runtimes' do
96
+ let(:runtimes) { true }
97
+
98
+ it 'does not grab /info' do
99
+ dont_allow(client).info
100
+ subject
101
+ end
102
+
103
+ it 'lists runtimes on the target' do
104
+ subject
105
+
106
+ stdout.rewind
107
+ expect(stdout.readline).to match /Getting runtimes.*OK/
108
+ expect(stdout.readline).to eq "\n"
109
+ expect(stdout.readline).to match /runtime\s+description/
110
+
111
+ client.runtimes.sort_by(&:name).each do |r|
112
+ expect(stdout.readline).to match /#{r.name}\s+#{r.description}/
113
+ end
114
+ end
115
+ end
116
+
117
+ context 'when given --services' do
118
+ let(:services) { true }
119
+
120
+ it 'does not grab /info' do
121
+ dont_allow(client).info
122
+ subject
123
+ end
124
+
125
+ it 'lists services on the target' do
126
+ subject
127
+
128
+ stdout.rewind
129
+ expect(stdout.readline).to match /Getting services.*OK/
130
+ expect(stdout.readline).to eq "\n"
131
+ expect(stdout.readline).to match /service\s+version\s+provider\s+plans\s+description/
132
+
133
+ client.services.sort_by(&:label).each do |s|
134
+ expect(stdout.readline).to match /#{s.label}\s+#{s.version}\s+#{s.provider}.+#{s.description}/
135
+ end
136
+ end
137
+ end
138
+
139
+ context 'when given --all' do
140
+ let(:all) { true }
141
+
142
+ it 'combines --frameworks --runtimes and --services' do
143
+ mock(client).info { target_info }
144
+
145
+ subject
146
+
147
+ stdout.rewind
148
+ expect(stdout.readline).to match /Getting runtimes.*OK/
149
+ expect(stdout.readline).to match /Getting frameworks.*OK/
150
+ expect(stdout.readline).to match /Getting services.*OK/
151
+ end
152
+ end
153
+
154
+ context 'when there is no target' do
155
+ let(:client) { nil }
156
+ it_behaves_like "an error that gets passed through",
157
+ :with_exception => CF::UserError,
158
+ :with_message => "Please select a target with 'cf target'."
159
+ end
160
+ end
@@ -0,0 +1,142 @@
1
+ require 'spec_helper'
2
+
3
+ command CF::Start::Login do
4
+ let(:client) { fake_client :organizations => [] }
5
+
6
+ describe 'metadata' do
7
+ let(:command) { Mothership.commands[:login] }
8
+
9
+ describe 'command' do
10
+ subject { command }
11
+ its(:description) { should eq "Authenticate with the target" }
12
+ specify { expect(Mothership::Help.group(:start)).to include(subject) }
13
+ end
14
+
15
+ include_examples 'inputs must have descriptions'
16
+
17
+ describe 'flags' do
18
+ subject { command.flags }
19
+
20
+ its(["-o"]) { should eq :organization }
21
+ its(["--org"]) { should eq :organization }
22
+ its(["--email"]) { should eq :username }
23
+ its(["-s"]) { should eq :space }
24
+ end
25
+
26
+ describe 'arguments' do
27
+ subject(:arguments) { command.arguments }
28
+ it 'have the correct commands' do
29
+ expect(arguments).to eq [{:type => :optional, :value => :email, :name => :username}]
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "running the command" do
35
+ stub_home_dir_with { "#{SPEC_ROOT}/fixtures/fake_home_dirs/new" }
36
+
37
+ let(:auth_token) { CFoundry::AuthToken.new("bearer some-new-access-token", "some-new-refresh-token") }
38
+ let(:tokens_yaml) { YAML.load_file(File.expand_path(tokens_file_path)) }
39
+ let(:tokens_file_path) { '~/.cf/tokens.yml' }
40
+ let(:organizations) { [] }
41
+
42
+ before do
43
+ stub(client).login("my-username", "my-password") { auth_token }
44
+ stub(client).login_prompts do
45
+ {
46
+ :username => ["text", "Username"],
47
+ :password => ["password", "8-digit PIN"]
48
+ }
49
+ end
50
+ end
51
+
52
+ subject { cf ["login"] }
53
+
54
+ it "logs in with the provided credentials and saves the token data to the YAML file" do
55
+ stub_ask("Username", {}) { "my-username" }
56
+ stub_ask("8-digit PIN", {:echo => "*", :forget => true}) { "my-password" }
57
+
58
+ subject
59
+
60
+ expect(tokens_yaml["https://api.some-domain.com"][:token]).to eq("bearer some-new-access-token")
61
+ expect(tokens_yaml["https://api.some-domain.com"][:refresh_token]).to eq("some-new-refresh-token")
62
+ end
63
+
64
+ context "with space and org in the token file" do
65
+ before do
66
+ write_token_file(:space => "space-id-1", :organization => "organization-id-1")
67
+ stub_ask("Username", {}) { "my-username" }
68
+ stub_ask("8-digit PIN", {:echo => "*", :forget => true}) { "my-password" }
69
+ end
70
+
71
+ context "when the user has no organizations" do
72
+ it "clears the org and space param from the token file" do
73
+ subject
74
+
75
+ expect(tokens_yaml["https://api.some-domain.com"][:space]).to be_nil
76
+ expect(tokens_yaml["https://api.some-domain.com"][:organization]).to be_nil
77
+ end
78
+ end
79
+
80
+ context "when the user has an organization, but no spaces" do
81
+ let(:client) {
82
+ fake_client :organizations => organizations,
83
+ :token => CFoundry::AuthToken.new("bearer some-access-token")
84
+ }
85
+ let(:organization) { fake :organization, :users => [user] }
86
+ let(:user) { fake :user }
87
+
88
+ shared_examples_for :method_clearing_the_token_file do
89
+ it "sets the new organization in the token file" do
90
+ subject
91
+ expect(tokens_yaml["https://api.some-domain.com"][:organization]).to eq(organizations.first.guid)
92
+ end
93
+
94
+ it "clears the space param from the token file" do
95
+ subject
96
+ expect(tokens_yaml["https://api.some-domain.com"][:space]).to be_nil
97
+ end
98
+ end
99
+
100
+ context "with one organization" do
101
+ let(:organizations) {
102
+ [ organization ]
103
+ }
104
+
105
+ it "does not prompt for an organization" do
106
+ dont_allow_ask("Organization", anything)
107
+ subject
108
+ end
109
+
110
+ it_behaves_like :method_clearing_the_token_file
111
+ end
112
+
113
+ context "with multiple organizations" do
114
+ let(:organizations) {
115
+ [ organization, OpenStruct.new(:name => 'My Org 2', :guid => 'organization-id-2') ]
116
+ }
117
+
118
+ before do
119
+ stub_ask("Organization", anything) { organizations.first }
120
+ end
121
+
122
+ it "prompts for organization" do
123
+ mock_ask("Organization", anything) { organizations.first }
124
+ subject
125
+ end
126
+
127
+ it_behaves_like :method_clearing_the_token_file
128
+ end
129
+ end
130
+ end
131
+
132
+ context 'when there is no target' do
133
+ let(:client) { nil }
134
+ let(:stub_precondition?) { false }
135
+
136
+ it "tells the user to select a target" do
137
+ subject
138
+ expect(error_output).to say("Please select a target with 'cf target'.")
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe CF::Start::Logout do
4
+ let(:client) { fake_client }
5
+
6
+ before do
7
+ any_instance_of described_class do |cli|
8
+ stub(cli).client { client }
9
+ end
10
+ end
11
+
12
+ describe 'metadata' do
13
+ let(:command) { Mothership.commands[:logout] }
14
+
15
+ describe 'command' do
16
+ subject { command }
17
+ its(:description) { should eq "Log out from the target" }
18
+ it { expect(Mothership::Help.group(:start)).to include(subject) }
19
+ end
20
+ end
21
+
22
+ describe "running the command" do
23
+ subject { cf ["logout"] }
24
+
25
+ context "when there is a target" do
26
+ let(:info) { { client.target => "x", "abc" => "x" } }
27
+
28
+ before do
29
+ any_instance_of CF::CLI do |cli|
30
+ stub(cli).targets_info { info }
31
+ stub(cli).client_target { client.target }
32
+ end
33
+ end
34
+
35
+ it "removes the target info from the tokens file" do
36
+ expect {
37
+ subject
38
+ }.to change { info }.to("abc" => "x")
39
+ end
40
+ end
41
+
42
+ context "when there is no target" do
43
+ let(:client) { nil }
44
+ it_behaves_like "an error that gets passed through",
45
+ :with_exception => CF::UserError,
46
+ :with_message => "Please select a target with 'cf target'."
47
+ end
48
+ end
49
+ end
50
+
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+ require "webmock/rspec"
3
+
4
+ command CF::Start::Target do
5
+ let(:client) { fake_client :apps => [app] }
6
+ let(:app) { fake :app }
7
+
8
+ describe 'metadata' do
9
+ let(:command) { Mothership.commands[:target] }
10
+
11
+ describe 'command' do
12
+ subject { command }
13
+ its(:description) { should eq "Set or display the target cloud, organization, and space" }
14
+ specify { expect(Mothership::Help.group(:start)).to include(subject) }
15
+ end
16
+
17
+ include_examples 'inputs must have descriptions'
18
+
19
+ describe 'flags' do
20
+ subject { command.flags }
21
+
22
+ its(["-o"]) { should eq :organization }
23
+ its(["--org"]) { should eq :organization }
24
+ its(["-s"]) { should eq :space }
25
+ end
26
+
27
+ describe 'arguments' do
28
+ subject(:arguments) { command.arguments }
29
+ it 'have the correct commands' do
30
+ expect(arguments).to eq [{:type => :optional, :value => nil, :name => :url}]
31
+ end
32
+ end
33
+ end
34
+
35
+ describe 'running the command' do
36
+ stub_home_dir_with { "#{SPEC_ROOT}/fixtures/fake_home_dirs/new" }
37
+
38
+ context "when the user is authenticated and has an organization" do
39
+ let(:tokens_file_path) { '~/.cf/tokens.yml' }
40
+ let(:organizations) {
41
+ [ fake(:organization, :name => 'My Org', :guid => 'organization-id-1', :users => [user], :spaces => spaces),
42
+ fake(:organization, :name => 'My Org 2', :guid => 'organization-id-2') ]
43
+ }
44
+ let(:spaces) {
45
+ [ fake(:space, :name => 'Development', :guid => 'space-id-1'),
46
+ fake(:space, :name => 'Staging', :guid => 'space-id-2') ]
47
+ }
48
+
49
+ let(:user) { stub! }
50
+ let(:organization) { organizations.first }
51
+ let(:client) do
52
+ fake_client :frameworks => fake_list(:framework, 3),
53
+ :organizations => organizations,
54
+ :token => CFoundry::AuthToken.new("bearer some-access-token")
55
+ end
56
+
57
+ before do
58
+ write_token_file({:space => "space-id-1", :organization => "organization-id-1"})
59
+ stub(client).current_user { user }
60
+ stub(client).organization { organization }
61
+ stub(client).current_organization { organization }
62
+ any_instance_of(described_class) do |instance|
63
+ stub(instance).client { client }
64
+ end
65
+ end
66
+
67
+ describe "switching the target" do
68
+ let(:target) { "some-valid-target.com" }
69
+ subject { cf ["target", target] }
70
+
71
+ context "when the target is not valid" do
72
+ before { WebMock.stub_request(:get, "http://#{target}/info").to_return(:body => "{}") }
73
+
74
+ it "should still be able to switch to a valid target after that" do
75
+ subject
76
+ end
77
+ end
78
+
79
+ context "when the target is valid but the connection is refused" do
80
+ it "shows a pretty error message" do
81
+ any_instance_of(CFoundry::Client) do |cli|
82
+ stub(cli).info { raise CFoundry::TargetRefused, "foo" }
83
+ end
84
+
85
+ subject
86
+ expect(error_output).to say("Target refused connection.")
87
+ end
88
+ end
89
+
90
+ context "when the uri is malformed" do
91
+ it "shows a pretty error message" do
92
+ any_instance_of(CFoundry::Client) do |cli|
93
+ stub(cli).info { raise CFoundry::InvalidTarget.new(target) }
94
+ end
95
+
96
+ subject
97
+ expect(error_output).to say("Invalid target URI.")
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "switching the space" do
103
+ let(:space) { spaces.last }
104
+ let(:tokens_yaml) { YAML.load_file(File.expand_path(tokens_file_path)) }
105
+ let(:tokens_file_path) { '~/.cf/tokens.yml' }
106
+
107
+ def run_command
108
+ cf %W[target -s #{space.name}]
109
+ end
110
+
111
+ it "should not reprompt for organization" do
112
+ dont_allow_ask("Organization", anything)
113
+ run_command
114
+ end
115
+
116
+ it "sets the space param in the token file" do
117
+ run_command
118
+ expect(tokens_yaml["https://api.some-domain.com"][:space]).to be == 'space-id-2'
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end