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,69 @@
1
+ require 'spec_helper'
2
+
3
+ command CF::Domain::Unmap do
4
+ let(:client) do
5
+ fake_client(
6
+ :current_organization => organization,
7
+ :current_space => space,
8
+ :spaces => [space],
9
+ :organizations => [organization],
10
+ :domains => [domain])
11
+ end
12
+
13
+ let(:organization) { fake(:organization, :spaces => [space]) }
14
+ let(:space) { fake(:space) }
15
+ let(:domain) { fake(:domain, :name => "some.domain.com") }
16
+
17
+ context "when the --delete flag is given" do
18
+ subject { cf %W[unmap-domain #{domain.name} --delete] }
19
+
20
+ it "asks for a confirmation" do
21
+ mock_ask("Really delete #{domain.name}?", :default => false) { false }
22
+ stub(domain).delete!
23
+ subject
24
+ end
25
+
26
+ context "and the user answers 'no' to the confirmation" do
27
+ it "does NOT delete the domain" do
28
+ stub_ask("Really delete #{domain.name}?", anything) { false }
29
+ dont_allow(domain).delete!
30
+ subject
31
+ end
32
+ end
33
+
34
+ context "and the user answers 'yes' to the confirmation" do
35
+ it "deletes the domain" do
36
+ stub_ask("Really delete #{domain.name}?", anything) { true }
37
+ mock(domain).delete!
38
+ subject
39
+ end
40
+ end
41
+ end
42
+
43
+ context "when a space is given" do
44
+ subject { cf %W[unmap-domain #{domain.name} --space #{space.name}] }
45
+
46
+ it "unmaps the domain from the space" do
47
+ mock(space).remove_domain(domain)
48
+ subject
49
+ end
50
+ end
51
+
52
+ context "when an organization is given" do
53
+ subject { cf %W[unmap-domain #{domain.name} --organization #{organization.name}] }
54
+
55
+ it "unmaps the domain from the organization" do
56
+ mock(organization).remove_domain(domain)
57
+ subject
58
+ end
59
+ end
60
+
61
+ context "when only the domain is given" do
62
+ subject { cf %W[unmap-domain #{domain.name}] }
63
+
64
+ it "unmaps the domain from the current space" do
65
+ mock(client.current_space).remove_domain(domain)
66
+ subject
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+ require 'stringio'
3
+
4
+ describe CF::Organization::Orgs do
5
+ let(:global) { { :color => false } }
6
+ let(:inputs) { {} }
7
+ let(:given) { {} }
8
+ let(:output) { StringIO.new }
9
+
10
+ let(:client) { fake_client(:organizations => organizations) }
11
+ let!(:org_1) { fake(:organization, :name => "bb_second", :spaces => fake_list(:space, 2), :domains => [fake(:domain)]) }
12
+ let!(:org_2) { fake(:organization, :name => "aa_first", :spaces => [fake(:space)], :domains => fake_list(:domain, 3)) }
13
+ let!(:org_3) { fake(:organization, :name => "cc_last", :spaces => fake_list(:space, 2), :domains => fake_list(:domain, 2)) }
14
+ let(:organizations) { [org_1, org_2, org_3]}
15
+
16
+ before do
17
+ any_instance_of(CF::CLI) do |cli|
18
+ stub(cli).client { client }
19
+ stub(cli).precondition { nil }
20
+ end
21
+ end
22
+
23
+ subject do
24
+ capture_output { Mothership.new.invoke(:orgs, inputs, given, global) }
25
+ end
26
+
27
+ describe 'metadata' do
28
+ let(:command) { Mothership.commands[:orgs] }
29
+
30
+ describe 'command' do
31
+ subject { command }
32
+ its(:description) { should eq "List available organizations" }
33
+ it { expect(Mothership::Help.group(:organizations)).to include(subject) }
34
+ end
35
+
36
+ include_examples 'inputs must have descriptions'
37
+
38
+ describe 'arguments' do
39
+ subject { command.arguments }
40
+ it 'has no arguments' do
41
+ should be_empty
42
+ end
43
+ end
44
+ end
45
+
46
+ it 'should have the correct first two lines' do
47
+ subject
48
+ stdout.rewind
49
+ expect(stdout.readline).to match /Getting organizations.*OK/
50
+ expect(stdout.readline).to eq "\n"
51
+ end
52
+
53
+ context 'when there are no orgnaizations' do
54
+ let(:organizations) { [] }
55
+
56
+ context 'and the full flag is given' do
57
+ let(:inputs) { {:full => true} }
58
+
59
+ it 'displays yaml-style output with all organization details' do
60
+ any_instance_of CF::Organization::Orgs do |orgs|
61
+ dont_allow(orgs).invoke
62
+ end
63
+ subject
64
+ end
65
+ end
66
+
67
+ context 'and the full flag is not given (default is false)' do
68
+ it 'should show only the progress' do
69
+ subject
70
+
71
+ stdout.rewind
72
+ expect(stdout.readline).to match /Getting organizations.*OK/
73
+ expect(stdout).to be_eof
74
+ end
75
+ end
76
+ end
77
+
78
+ context 'when there are organizations' do
79
+ context 'and the full flag is given' do
80
+ let(:inputs) { {:full => true} }
81
+
82
+ it 'displays yaml-style output with all organization details' do
83
+ any_instance_of CF::Organization::Orgs do |orgs|
84
+ mock(orgs).invoke(:org, :organization => org_2, :full => true).ordered
85
+ mock(orgs).invoke(:org, :organization => org_1, :full => true).ordered
86
+ mock(orgs).invoke(:org, :organization => org_3, :full => true).ordered
87
+ end
88
+ subject
89
+ end
90
+ end
91
+
92
+ context 'and the full flag is not given (default is false)' do
93
+ it 'displays tabular output with names, spaces and domains' do
94
+ subject
95
+
96
+ stdout.rewind
97
+ stdout.readline
98
+ stdout.readline
99
+
100
+ expect(stdout.readline).to match /name\s+spaces\s+domains/
101
+ organizations.sort_by(&:name).each do |org|
102
+ expect(stdout.readline).to match /#{org.name}\s+#{name_list(org.spaces)}\s+#{name_list(org.domains)}/
103
+ end
104
+ expect(stdout).to be_eof
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+ require "cf/cli/organization/rename"
3
+
4
+ describe CF::Organization::Rename do
5
+ let(:global) { { :color => false, :quiet => true } }
6
+ let(:inputs) { {} }
7
+ let(:given) { {} }
8
+ let(:organizations) { fake_list(:organization, 3) }
9
+ let(:client) { fake_client(:organizations => organizations) }
10
+ let(:new_name) { "some-new-name" }
11
+
12
+ before do
13
+ any_instance_of(CF::CLI) do |cli|
14
+ stub(cli).client { client }
15
+ stub(cli).precondition { nil }
16
+ end
17
+ end
18
+
19
+ subject { Mothership.new.invoke(:rename_org, inputs, given, global) }
20
+
21
+ describe 'metadata' do
22
+ let(:command) { Mothership.commands[:rename_org] }
23
+
24
+ describe 'command' do
25
+ subject { command }
26
+ its(:description) { should eq "Rename an organization" }
27
+ it { expect(Mothership::Help.group(:organizations)).to include(subject) }
28
+ end
29
+
30
+ describe 'inputs' do
31
+ subject { command.inputs }
32
+
33
+ it "is not missing any descriptions" do
34
+ subject.each do |input, attrs|
35
+ expect(attrs[:description]).to be
36
+ expect(attrs[:description].strip).to_not be_empty
37
+ end
38
+ end
39
+ end
40
+
41
+ describe 'arguments' do
42
+ subject { command.arguments }
43
+ it 'has the correct argument order' do
44
+ should eq([
45
+ { :type => :optional, :value => nil, :name => :organization },
46
+ { :type => :optional, :value => nil, :name => :name }
47
+ ])
48
+ end
49
+ end
50
+ end
51
+
52
+ context 'when there are no organizations' do
53
+ let(:organizations) { [] }
54
+
55
+ context 'and an organization is given' do
56
+ let(:given) { { :organization => "some-invalid-organization" } }
57
+ it { expect { subject }.to raise_error(CF::UserError, "Unknown organization 'some-invalid-organization'.") }
58
+ end
59
+
60
+ context 'and an organization is not given' do
61
+ it { expect { subject }.to raise_error(CF::UserError, "No organizations.") }
62
+ end
63
+ end
64
+
65
+ context 'when there are organizations' do
66
+ let(:renamed_organization) { organizations.first }
67
+
68
+ context 'when the defaults are used' do
69
+ it 'asks for the organization and new name and renames' do
70
+ mock_ask("Rename which organization?", anything) { renamed_organization }
71
+ mock_ask("New name") { new_name }
72
+ mock(renamed_organization).name=(new_name)
73
+ mock(renamed_organization).update!
74
+ subject
75
+ end
76
+ end
77
+
78
+ context 'when no name is provided, but an organization is' do
79
+ let(:given) { { :organization => renamed_organization.name } }
80
+
81
+ it 'asks for the new name and renames' do
82
+ dont_allow_ask("Rename which organization?", anything)
83
+ mock_ask("New name") { new_name }
84
+ mock(renamed_organization).name=(new_name)
85
+ mock(renamed_organization).update!
86
+ subject
87
+ end
88
+ end
89
+
90
+ context 'when an organization is provided and a name' do
91
+ let(:inputs) { { :organization => renamed_organization, :name => new_name } }
92
+
93
+ it 'renames the organization' do
94
+ mock(renamed_organization).update!
95
+ subject
96
+ end
97
+
98
+ it 'displays the progress' do
99
+ mock_with_progress("Renaming to #{new_name}")
100
+ mock(renamed_organization).update!
101
+
102
+ subject
103
+ end
104
+
105
+ context 'and the name already exists' do
106
+ it 'fails' do
107
+ mock(renamed_organization).update! { raise CFoundry::OrganizationNameTaken.new("Bad error", 200) }
108
+ expect { subject }.to raise_error(CFoundry::OrganizationNameTaken)
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ command CF::Route::Map do
4
+ let(:client) { fake_client(:apps => apps, :routes => routes) }
5
+
6
+ let(:app) { fake(:app, :space => space, :name => "app-name") }
7
+ let(:space) { fake(:space, :domains => space_domains) }
8
+ let(:domain) { fake(:domain) }
9
+
10
+ let(:apps) { [app] }
11
+ let(:routes) { [] }
12
+ let(:domains) { [domain] }
13
+
14
+ let(:space_domains) { domains }
15
+
16
+ let(:host_name) { "some-host" }
17
+
18
+ shared_examples "mapping the route to the app" do
19
+ context 'and the domain is mapped to the space' do
20
+ let(:space_domains) { [domain] }
21
+
22
+ context 'and the route is mapped to the space' do
23
+ let(:routes) { [route] }
24
+ let(:route) do
25
+ fake(:route, :space => space, :host => host_name,
26
+ :domain => domain)
27
+ end
28
+
29
+ it 'binds the route to the app' do
30
+ mock(app).add_route(route)
31
+ subject
32
+ end
33
+ end
34
+
35
+ context 'and the route is not mapped to the space' do
36
+ let(:new_route) { fake(:route) }
37
+
38
+ before do
39
+ stub(client).route { new_route }
40
+ stub(app).add_route
41
+ stub(new_route).create!
42
+ end
43
+
44
+ it 'indicates that it is creating a route' do
45
+ subject
46
+ expect(output).to say("Creating route #{host_name}.#{domain.name}")
47
+ end
48
+
49
+ it "creates the route in the app's space" do
50
+ mock(new_route).create!
51
+ subject
52
+ expect(new_route.host).to eq host_name
53
+ expect(new_route.domain).to eq domain
54
+ expect(new_route.space).to eq space
55
+ end
56
+
57
+ it 'indicates that it is binding the route' do
58
+ subject
59
+ expect(output).to say("Binding #{host_name}.#{domain.name} to #{app.name}")
60
+ end
61
+
62
+ it 'binds the route to the app' do
63
+ mock(app).add_route(new_route)
64
+ subject
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ context 'when an app is specified' do
71
+ subject { cf %W[map #{app.name} #{host_name} #{domain.name}] }
72
+
73
+ context 'and the domain is not already mapped to the space' do
74
+ let(:space_domains) { [] }
75
+
76
+ it 'indicates that the domain is invalid' do
77
+ subject
78
+ expect(error_output).to say("Unknown domain")
79
+ end
80
+ end
81
+
82
+ include_examples "mapping the route to the app"
83
+ end
84
+
85
+ context 'when an app is not specified' do
86
+ let(:space_domains) { [domain] }
87
+ let(:new_route) { fake(:route) }
88
+
89
+ subject { cf %W[map --host #{host_name} #{domain.name}] }
90
+
91
+ before { stub_ask("Which application?", anything) { app } }
92
+
93
+ it 'asks for an app' do
94
+ stub(client).route { new_route }
95
+ stub(app).add_route
96
+ stub(new_route).create!
97
+ mock_ask("Which application?", anything) { app }
98
+ subject
99
+ end
100
+
101
+ include_examples "mapping the route to the app"
102
+ end
103
+
104
+ context "when a host is not specified" do
105
+ let(:new_route) { fake(:route) }
106
+
107
+ subject { cf %W[map #{app.name} #{domain.name}] }
108
+
109
+ before do
110
+ stub(client).route { new_route }
111
+ stub(app).add_route
112
+ stub(new_route).create!
113
+ end
114
+
115
+ it "creates a route with an empty string as its host" do
116
+ mock(new_route).create!
117
+ subject
118
+ expect(new_route.host).to eq ""
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+
3
+ command CF::Route::Unmap do
4
+ let(:client) { fake_client :apps => [app] }
5
+
6
+ let(:app){ fake(:app, :space => space, :name => "app-name") }
7
+ let(:space) { fake(:space, :name => "space-name", :domains => space_domains) }
8
+ let(:domain) { fake(:domain, :name => domain_name ) }
9
+ let(:domain_name) { "some-domain.com" }
10
+ let(:host_name) { "some-host" }
11
+ let(:url) { "#{host_name}.#{domain_name}" }
12
+ let(:space_domains) { [domain] }
13
+
14
+ describe 'metadata' do
15
+ let(:command) { Mothership.commands[:delete_service] }
16
+
17
+ describe 'command' do
18
+ subject { command }
19
+ its(:description) { should eq "Delete a service" }
20
+ it { expect(Mothership::Help.group(:services, :manage)).to include(subject) }
21
+ end
22
+
23
+ include_examples 'inputs must have descriptions'
24
+
25
+ describe 'arguments' do
26
+ subject { command.arguments }
27
+ it 'has the correct argument order' do
28
+ should eq([{:type => :optional, :value => nil, :name => :service }])
29
+ end
30
+ end
31
+ end
32
+
33
+ context "when an app and a url are specified" do
34
+ subject { cf %W[unmap #{url} #{app.name}] }
35
+
36
+ context "when the given route is mapped to the given app" do
37
+ let(:app) { fake(:app, :space => space, :name => "app-name", :routes => [route]) }
38
+ let(:route) { fake(:route, :space => space, :host => host_name, :domain => domain) }
39
+
40
+ it "unmaps the url from the app" do
41
+ mock(app).remove_route(route)
42
+ subject
43
+ end
44
+ end
45
+
46
+ context "when the given route is NOT mapped to the given app" do
47
+ it "displays an error" do
48
+ subject
49
+ expect(error_output).to say("Unknown route")
50
+ end
51
+ end
52
+ end
53
+
54
+ context "when only an app is specified" do
55
+ let(:other_route) { fake(:route, :host => "abcd", :domain => domain) }
56
+ let(:route) { fake(:route, :host => "efgh", :domain => domain) }
57
+ let(:app) { fake(:app, :space => space, :routes => [route, other_route] )}
58
+
59
+ subject { cf %W[unmap --app #{app.name}] }
60
+
61
+ it "asks the user to select from the app's urls" do
62
+ mock_ask("Which URL?", anything) do |_, opts|
63
+ expect(opts[:choices]).to eq [other_route, route]
64
+ route
65
+ end
66
+
67
+ stub(app).remove_route(anything)
68
+
69
+ subject
70
+ end
71
+
72
+ it "unmaps the selected url from the app" do
73
+ stub_ask("Which URL?", anything) { route }
74
+ mock(app).remove_route(route)
75
+ subject
76
+ end
77
+ end
78
+
79
+ context "when an app is specified and the --all option is given" do
80
+ let(:other_route) { fake(:route, :host => "abcd", :domain => domain) }
81
+ let(:route) { fake(:route, :host => "efgh", :domain => domain) }
82
+ let(:app) { fake(:app, :routes => [route, other_route]) }
83
+
84
+ subject { cf %W[unmap --all --app #{app.name}] }
85
+
86
+ it "unmaps all routes from the given app" do
87
+ mock(app).remove_route(route)
88
+ mock(app).remove_route(other_route)
89
+ subject
90
+ end
91
+ end
92
+
93
+ context "when a url is specified and the --delete option is given" do
94
+ let(:route) { fake(:route, :host => host_name, :domain => domain) }
95
+ let(:client) { fake_client :routes => [route] }
96
+
97
+ subject { cf %W[unmap #{url} --delete] }
98
+
99
+ it "deletes the route" do
100
+ mock(route).delete!
101
+ subject
102
+ end
103
+ end
104
+
105
+ context "when the --delete and --all options are both passed" do
106
+ let(:other_route) { fake(:route, :host => "abcd", :domain => domain) }
107
+ let(:route) { fake(:route, :host => "efgh", :domain => domain) }
108
+ let(:client) { fake_client :routes => [route, other_route] }
109
+
110
+ subject { cf %W[unmap --delete --all] }
111
+
112
+ before do
113
+ any_instance_of(route.class) do |route|
114
+ stub(route).delete!
115
+ end
116
+ end
117
+
118
+ it "asks if the user really wants to unmap all urls" do
119
+ mock_ask("Really delete ALL URLS?", :default => false) { false }
120
+ subject
121
+ end
122
+
123
+ context "when the user responds with a yes" do
124
+ before { stub_ask("Really delete ALL URLS?", anything) { true } }
125
+
126
+ it "deletes all the user's routes" do
127
+ client.routes.each { |r| mock(r).delete! }
128
+ subject
129
+ end
130
+ end
131
+
132
+ context "when the user responds with a no" do
133
+ before { stub_ask("Really delete ALL URLS?", anything) { false } }
134
+
135
+ it "does not delete any routes" do
136
+ any_instance_of(route.class) do |route|
137
+ dont_allow(route).delete!
138
+ end
139
+ subject
140
+ end
141
+ end
142
+ end
143
+
144
+ context "when only a url is passed" do
145
+ let(:route) { fake(:route, :host => host_name, :domain => domain) }
146
+ let(:client) { fake_client :routes => [route] }
147
+
148
+ subject { cf %W[unmap #{url}] }
149
+
150
+ it "displays an error message" do
151
+ subject
152
+ expect(error_output).to say("Missing either --delete or --app.")
153
+ end
154
+ end
155
+ end