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.
- data/LICENSE +1277 -30
- data/Rakefile +12 -1
- data/bin/cf +0 -3
- data/lib/cf.rb +6 -0
- data/lib/cf/cli.rb +389 -190
- data/lib/cf/cli/app/app.rb +45 -0
- data/lib/cf/cli/app/apps.rb +99 -0
- data/lib/cf/cli/app/base.rb +90 -0
- data/lib/cf/cli/app/crashes.rb +42 -0
- data/lib/cf/cli/app/delete.rb +95 -0
- data/lib/cf/cli/app/deprecated.rb +11 -0
- data/lib/cf/cli/app/env.rb +78 -0
- data/lib/cf/cli/app/files.rb +137 -0
- data/lib/cf/cli/app/health.rb +26 -0
- data/lib/cf/cli/app/instances.rb +53 -0
- data/lib/cf/cli/app/logs.rb +76 -0
- data/lib/cf/cli/app/push.rb +105 -0
- data/lib/cf/cli/app/push/create.rb +149 -0
- data/lib/cf/cli/app/push/interactions.rb +94 -0
- data/lib/cf/cli/app/push/sync.rb +64 -0
- data/lib/cf/cli/app/rename.rb +35 -0
- data/lib/cf/cli/app/restart.rb +20 -0
- data/lib/cf/cli/app/scale.rb +69 -0
- data/lib/cf/cli/app/start.rb +143 -0
- data/lib/cf/cli/app/stats.rb +67 -0
- data/lib/cf/cli/app/stop.rb +27 -0
- data/lib/cf/cli/domain/base.rb +8 -0
- data/lib/cf/cli/domain/domains.rb +40 -0
- data/lib/cf/cli/domain/map.rb +55 -0
- data/lib/cf/cli/domain/unmap.rb +56 -0
- data/lib/cf/cli/help.rb +15 -0
- data/lib/cf/cli/interactive.rb +105 -0
- data/lib/cf/cli/organization/base.rb +12 -0
- data/lib/cf/cli/organization/create.rb +32 -0
- data/lib/cf/cli/organization/delete.rb +73 -0
- data/lib/cf/cli/organization/org.rb +45 -0
- data/lib/cf/cli/organization/orgs.rb +35 -0
- data/lib/cf/cli/organization/rename.rb +36 -0
- data/lib/cf/cli/route/base.rb +8 -0
- data/lib/cf/cli/route/map.rb +70 -0
- data/lib/cf/cli/route/routes.rb +26 -0
- data/lib/cf/cli/route/unmap.rb +62 -0
- data/lib/cf/cli/service/base.rb +8 -0
- data/lib/cf/cli/service/bind.rb +44 -0
- data/lib/cf/cli/service/create.rb +107 -0
- data/lib/cf/cli/service/delete.rb +82 -0
- data/lib/cf/cli/service/rename.rb +35 -0
- data/lib/cf/cli/service/service.rb +40 -0
- data/lib/cf/cli/service/services.rb +99 -0
- data/lib/cf/cli/service/unbind.rb +38 -0
- data/lib/cf/cli/space/base.rb +19 -0
- data/lib/cf/cli/space/create.rb +63 -0
- data/lib/cf/cli/space/delete.rb +95 -0
- data/lib/cf/cli/space/rename.rb +39 -0
- data/lib/cf/cli/space/space.rb +64 -0
- data/lib/cf/cli/space/spaces.rb +55 -0
- data/lib/cf/cli/space/switch.rb +16 -0
- data/lib/cf/cli/start/base.rb +93 -0
- data/lib/cf/cli/start/colors.rb +13 -0
- data/lib/cf/cli/start/info.rb +124 -0
- data/lib/cf/cli/start/login.rb +94 -0
- data/lib/cf/cli/start/logout.rb +17 -0
- data/lib/cf/cli/start/target.rb +69 -0
- data/lib/cf/cli/start/target_interactions.rb +37 -0
- data/lib/cf/cli/start/targets.rb +16 -0
- data/lib/cf/cli/user/base.rb +29 -0
- data/lib/cf/cli/user/create.rb +39 -0
- data/lib/cf/cli/user/passwd.rb +43 -0
- data/lib/cf/cli/user/register.rb +42 -0
- data/lib/cf/cli/user/users.rb +32 -0
- data/lib/cf/constants.rb +10 -7
- data/lib/cf/detect.rb +113 -48
- data/lib/cf/errors.rb +17 -0
- data/lib/cf/plugin.rb +28 -12
- data/lib/cf/spacing.rb +89 -0
- data/lib/cf/spec_helper.rb +1 -0
- data/lib/cf/test_support.rb +6 -0
- data/lib/cf/version.rb +1 -1
- data/spec/assets/hello-sinatra/Gemfile +3 -0
- data/spec/assets/hello-sinatra/Gemfile.lock +17 -0
- data/spec/assets/hello-sinatra/config.ru +3 -0
- data/spec/assets/hello-sinatra/fat-cat-makes-app-larger.png +0 -0
- data/spec/assets/hello-sinatra/main.rb +6 -0
- data/spec/assets/specker_runner/specker_runner_input.rb +6 -0
- data/spec/assets/specker_runner/specker_runner_pause.rb +5 -0
- data/spec/cf/cli/app/base_spec.rb +17 -0
- data/spec/cf/cli/app/delete_spec.rb +188 -0
- data/spec/cf/cli/app/instances_spec.rb +65 -0
- data/spec/cf/cli/app/push/create_spec.rb +661 -0
- data/spec/cf/cli/app/push_spec.rb +369 -0
- data/spec/cf/cli/app/rename_spec.rb +104 -0
- data/spec/cf/cli/app/scale_spec.rb +75 -0
- data/spec/cf/cli/app/start_spec.rb +208 -0
- data/spec/cf/cli/app/stats_spec.rb +68 -0
- data/spec/cf/cli/domain/map_spec.rb +130 -0
- data/spec/cf/cli/domain/unmap_spec.rb +69 -0
- data/spec/cf/cli/organization/orgs_spec.rb +108 -0
- data/spec/cf/cli/organization/rename_spec.rb +113 -0
- data/spec/cf/cli/route/map_spec.rb +121 -0
- data/spec/cf/cli/route/unmap_spec.rb +155 -0
- data/spec/cf/cli/service/bind_spec.rb +25 -0
- data/spec/cf/cli/service/delete_spec.rb +22 -0
- data/spec/cf/cli/service/rename_spec.rb +105 -0
- data/spec/cf/cli/service/service_spec.rb +23 -0
- data/spec/cf/cli/service/unbind_spec.rb +25 -0
- data/spec/cf/cli/space/create_spec.rb +93 -0
- data/spec/cf/cli/space/rename_spec.rb +102 -0
- data/spec/cf/cli/space/spaces_spec.rb +104 -0
- data/spec/cf/cli/space/switch_space_spec.rb +55 -0
- data/spec/cf/cli/start/info_spec.rb +160 -0
- data/spec/cf/cli/start/login_spec.rb +142 -0
- data/spec/cf/cli/start/logout_spec.rb +50 -0
- data/spec/cf/cli/start/target_spec.rb +123 -0
- data/spec/cf/cli/user/create_spec.rb +54 -0
- data/spec/cf/cli/user/passwd_spec.rb +102 -0
- data/spec/cf/cli/user/register_spec.rb +140 -0
- data/spec/cf/cli_spec.rb +442 -0
- data/spec/cf/detect_spec.rb +54 -0
- data/spec/console_app_specker/console_app_specker_matchers_spec.rb +173 -0
- data/spec/console_app_specker/specker_runner_spec.rb +167 -0
- data/spec/features/account_lifecycle_spec.rb +85 -0
- data/spec/features/login_spec.rb +66 -0
- data/spec/features/push_flow_spec.rb +125 -0
- data/spec/features/switching_targets_spec.rb +32 -0
- data/spec/spec_helper.rb +72 -0
- data/spec/support/command_helper.rb +81 -0
- data/spec/support/config_helper.rb +15 -0
- data/spec/support/console_app_specker_matchers.rb +86 -0
- data/spec/support/fake_home_dir.rb +55 -0
- data/spec/support/interact_helper.rb +29 -0
- data/spec/support/shared_examples/errors.rb +40 -0
- data/spec/support/shared_examples/input.rb +14 -0
- data/spec/support/specker_runner.rb +80 -0
- data/spec/support/tracking_expector.rb +71 -0
- metadata +427 -66
- data/lib/cf/cli/app.rb +0 -595
- data/lib/cf/cli/command.rb +0 -444
- data/lib/cf/cli/dots.rb +0 -133
- data/lib/cf/cli/service.rb +0 -112
- data/lib/cf/cli/user.rb +0 -71
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
if ENV['CF_V2_TEST_USER'] && ENV['CF_V2_TEST_PASSWORD'] && ENV['CF_V2_TEST_TARGET'] && ENV['CF_V2_OTHER_TEST_USER']
|
|
4
|
+
describe 'A user logs in and switches spaces, after a different user has logged in', :ruby19 => true do
|
|
5
|
+
include ConsoleAppSpeckerMatchers
|
|
6
|
+
|
|
7
|
+
let(:target) { ENV['CF_V2_TEST_TARGET'] }
|
|
8
|
+
let(:username) { ENV['CF_V2_TEST_USER'] }
|
|
9
|
+
let(:password) { ENV['CF_V2_TEST_PASSWORD'] }
|
|
10
|
+
|
|
11
|
+
let(:second_username) { ENV['CF_V2_OTHER_TEST_USER'] }
|
|
12
|
+
let(:second_organization) { ENV['CF_V2_OTHER_TEST_ORGANIZATION'] }
|
|
13
|
+
let(:second_space) { ENV['CF_V2_OTHER_TEST_SPACE'] }
|
|
14
|
+
let(:second_password) { ENV['CF_V2_OTHER_TEST_PASSWORD'] || ENV['CF_V2_TEST_PASSWORD'] }
|
|
15
|
+
|
|
16
|
+
before do
|
|
17
|
+
Interact::Progress::Dots.start!
|
|
18
|
+
|
|
19
|
+
run("#{cf_bin} target #{target}") do |runner|
|
|
20
|
+
expect(runner).to say "Setting target"
|
|
21
|
+
expect(runner).to say target
|
|
22
|
+
runner.wait_for_exit
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
run("#{cf_bin} logout") do |runner|
|
|
26
|
+
runner.wait_for_exit
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
after do
|
|
31
|
+
Interact::Progress::Dots.stop!
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context "when a different user is already logged in" do
|
|
35
|
+
before do
|
|
36
|
+
run("#{cf_bin} login #{username} --password #{password}") do |runner|
|
|
37
|
+
expect(runner).to say "Authenticating... OK"
|
|
38
|
+
expect(runner).to say "Organization>"
|
|
39
|
+
runner.send_keys("pivotal")
|
|
40
|
+
|
|
41
|
+
expect(runner).to say "Switching to organization"
|
|
42
|
+
expect(runner).to say "OK"
|
|
43
|
+
|
|
44
|
+
expect(runner).to say "Space"
|
|
45
|
+
runner.send_keys("1")
|
|
46
|
+
|
|
47
|
+
expect(runner).to say "Switching to space"
|
|
48
|
+
expect(runner).to say "OK"
|
|
49
|
+
|
|
50
|
+
runner.wait_for_exit
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "can switch spaces on login" do
|
|
55
|
+
run("#{cf_bin} login #{second_username} --password #{second_password} --organization #{second_organization} --space #{second_space}") do |runner|
|
|
56
|
+
expect(runner).to say "Authenticating... OK"
|
|
57
|
+
expect(runner).to say "Switching to organization #{second_organization}... OK"
|
|
58
|
+
expect(runner).to say "Switching to space #{second_space}... OK"
|
|
59
|
+
runner.wait_for_exit
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
else
|
|
65
|
+
$stderr.puts 'Skipping v2 integration specs; please provide $CF_V2_TEST_TARGET, $CF_V2_TEST_USER, $CF_V2_TEST_PASSWORD, and $CF_V2_OTHER_TEST_USER'
|
|
66
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "webmock/rspec"
|
|
3
|
+
|
|
4
|
+
if ENV['CF_V2_TEST_USER'] && ENV['CF_V2_TEST_PASSWORD'] && ENV['CF_V2_TEST_TARGET']
|
|
5
|
+
describe 'A new user tries to use CF against v2', :ruby19 => true do
|
|
6
|
+
include ConsoleAppSpeckerMatchers
|
|
7
|
+
include CF::Interactive
|
|
8
|
+
|
|
9
|
+
let(:target) { ENV['CF_V2_TEST_TARGET'] }
|
|
10
|
+
let(:username) { ENV['CF_V2_TEST_USER'] }
|
|
11
|
+
let(:password) { ENV['CF_V2_TEST_PASSWORD'] }
|
|
12
|
+
|
|
13
|
+
let(:app) do
|
|
14
|
+
fuzz = TRAVIS_BUILD_ID.to_s + Time.new.to_f.to_s.gsub(".", "_")
|
|
15
|
+
"hello-sinatra-#{fuzz}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
before do
|
|
19
|
+
FileUtils.rm_rf File.expand_path(CF::CONFIG_DIR)
|
|
20
|
+
WebMock.allow_net_connect!
|
|
21
|
+
Interact::Progress::Dots.start!
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
after do
|
|
25
|
+
cf %W(delete #{app} -f --no-script)
|
|
26
|
+
Interact::Progress::Dots.stop!
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'pushes a simple sinatra app using defaults as much as possible' do
|
|
30
|
+
run("#{cf_bin} target http://#{target}") do |runner|
|
|
31
|
+
expect(runner).to say %r{Setting target to http://#{target}... OK}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
run("#{cf_bin} login") do |runner|
|
|
35
|
+
expect(runner).to say %r{target: https?://#{target}}
|
|
36
|
+
|
|
37
|
+
expect(runner).to say "Email>"
|
|
38
|
+
runner.send_keys username
|
|
39
|
+
|
|
40
|
+
expect(runner).to say "Password>"
|
|
41
|
+
runner.send_keys password
|
|
42
|
+
|
|
43
|
+
expect(runner).to say "Authenticating... OK"
|
|
44
|
+
|
|
45
|
+
expect(runner).to say(
|
|
46
|
+
"Organization>" => proc {
|
|
47
|
+
runner.send_keys "1"
|
|
48
|
+
expect(runner).to say /Switching to organization .*\.\.\. OK/
|
|
49
|
+
},
|
|
50
|
+
"Switching to organization" => proc {}
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
expect(runner).to say(
|
|
54
|
+
"Space>" => proc {
|
|
55
|
+
runner.send_keys "1"
|
|
56
|
+
expect(runner).to say /Switching to space .*\.\.\. OK/
|
|
57
|
+
},
|
|
58
|
+
"Switching to space" => proc {}
|
|
59
|
+
)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
run("#{cf_bin} app #{app}") do |runner|
|
|
63
|
+
expect(runner).to say "Unknown app '#{app}'."
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
Dir.chdir("#{SPEC_ROOT}/assets/hello-sinatra") do
|
|
67
|
+
run("#{cf_bin} push") do |runner|
|
|
68
|
+
expect(runner).to say "Name>"
|
|
69
|
+
runner.send_keys app
|
|
70
|
+
|
|
71
|
+
expect(runner).to say "Instances> 1"
|
|
72
|
+
runner.send_keys ""
|
|
73
|
+
|
|
74
|
+
expect(runner).to say "Custom startup command> "
|
|
75
|
+
runner.send_keys "bundle exec ruby main.rb -p $PORT"
|
|
76
|
+
|
|
77
|
+
expect(runner).to say "Memory Limit>"
|
|
78
|
+
runner.send_keys "64M"
|
|
79
|
+
|
|
80
|
+
expect(runner).to say "Creating #{app}... OK"
|
|
81
|
+
|
|
82
|
+
expect(runner).to say "Subdomain> #{app}"
|
|
83
|
+
runner.send_keys ""
|
|
84
|
+
|
|
85
|
+
expect(runner).to say "1:"
|
|
86
|
+
expect(runner).to say "Domain>"
|
|
87
|
+
runner.send_keys "1"
|
|
88
|
+
|
|
89
|
+
expect(runner).to say(/Creating route #{app}\..*\.\.\. OK/)
|
|
90
|
+
expect(runner).to say(/Binding #{app}\..* to #{app}\.\.\. OK/)
|
|
91
|
+
|
|
92
|
+
expect(runner).to say "Create services for application?> n"
|
|
93
|
+
runner.send_keys ""
|
|
94
|
+
|
|
95
|
+
# skip this
|
|
96
|
+
if runner.expect "Bind other services to application?> n", 1
|
|
97
|
+
runner.send_keys ""
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
expect(runner).to say "Save configuration?> n"
|
|
101
|
+
runner.send_keys ""
|
|
102
|
+
|
|
103
|
+
expect(runner).to say "Uploading #{app}... OK"
|
|
104
|
+
expect(runner).to say "Starting #{app}... OK"
|
|
105
|
+
|
|
106
|
+
expect(runner).to say /(Using|Installing) Ruby/i, 10
|
|
107
|
+
expect(runner).to say "Your bundle is complete!", 30
|
|
108
|
+
|
|
109
|
+
expect(runner).to say "Checking #{app}..."
|
|
110
|
+
expect(runner).to say "1/1 instances"
|
|
111
|
+
expect(runner).to say "OK", 30
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
run("#{cf_bin} delete #{app}") do |runner|
|
|
116
|
+
expect(runner).to say "Really delete #{app}?>"
|
|
117
|
+
runner.send_keys "y"
|
|
118
|
+
|
|
119
|
+
expect(runner).to say "Deleting #{app}... OK"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
else
|
|
124
|
+
$stderr.puts 'Skipping v2 integration specs; please provide $CF_V2_TEST_TARGET, $CF_V2_TEST_USER, and $CF_V2_TEST_PASSWORD'
|
|
125
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
if ENV['CF_V2_TEST_TARGET']
|
|
4
|
+
describe 'A new user tries to use CF against v2 production', :ruby19 => true do
|
|
5
|
+
include ConsoleAppSpeckerMatchers
|
|
6
|
+
|
|
7
|
+
let(:target) { ENV['CF_V2_TEST_TARGET'] }
|
|
8
|
+
|
|
9
|
+
before do
|
|
10
|
+
Interact::Progress::Dots.start!
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
after do
|
|
14
|
+
Interact::Progress::Dots.stop!
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "can switch targets, even if a target is invalid" do
|
|
18
|
+
run("#{cf_bin} target invalid-target") do |runner|
|
|
19
|
+
expect(runner).to say "Target refused"
|
|
20
|
+
runner.wait_for_exit
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
run("#{cf_bin} target #{target}") do |runner|
|
|
24
|
+
expect(runner).to say "Setting target"
|
|
25
|
+
expect(runner).to say target
|
|
26
|
+
runner.wait_for_exit
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
else
|
|
31
|
+
$stderr.puts 'Skipping v2 integration specs; please provide $CF_V2_TEST_TARGET'
|
|
32
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
SPEC_ROOT = File.dirname(__FILE__).freeze
|
|
2
|
+
|
|
3
|
+
require "rspec"
|
|
4
|
+
require "cfoundry"
|
|
5
|
+
require "cfoundry/test_support"
|
|
6
|
+
require "cf"
|
|
7
|
+
require "cf/test_support"
|
|
8
|
+
require "webmock"
|
|
9
|
+
require "ostruct"
|
|
10
|
+
require "fakefs/safe"
|
|
11
|
+
|
|
12
|
+
INTEGRATE_WITH = ENV["INTEGRATE_WITH"] || "default"
|
|
13
|
+
TRAVIS_BUILD_ID = ENV["TRAVIS_BUILD_ID"]
|
|
14
|
+
|
|
15
|
+
OriginalFile = File
|
|
16
|
+
|
|
17
|
+
class FakeFS::File
|
|
18
|
+
def self.fnmatch(*args, &blk)
|
|
19
|
+
OriginalFile.fnmatch(*args, &blk)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def cf_bin
|
|
24
|
+
cf = File.expand_path("#{SPEC_ROOT}/../bin/cf.dev")
|
|
25
|
+
if INTEGRATE_WITH != 'default'
|
|
26
|
+
"rvm #{INTEGRATE_WITH}@cf do #{cf}"
|
|
27
|
+
else
|
|
28
|
+
cf
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
Dir[File.expand_path('../support/**/*.rb', __FILE__)].each do |file|
|
|
33
|
+
require file
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
RSpec.configure do |c|
|
|
37
|
+
c.include Fake::FakeMethods
|
|
38
|
+
c.include ConsoleAppSpeckerMatchers
|
|
39
|
+
|
|
40
|
+
c.mock_with :rr
|
|
41
|
+
|
|
42
|
+
if RUBY_VERSION =~ /^1\.8\.\d/
|
|
43
|
+
c.filter_run_excluding :ruby19 => true
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
c.include FakeHomeDir
|
|
47
|
+
c.include CommandHelper
|
|
48
|
+
c.include InteractHelper
|
|
49
|
+
c.include ConfigHelper
|
|
50
|
+
|
|
51
|
+
c.before(:all) do
|
|
52
|
+
WebMock.disable_net_connect!
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
c.before do
|
|
56
|
+
CF::CLI.send(:class_variable_set, :@@client, nil)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def name_list(xs)
|
|
61
|
+
if xs.empty?
|
|
62
|
+
"none"
|
|
63
|
+
else
|
|
64
|
+
xs.collect(&:name).join(", ")
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def run(command)
|
|
69
|
+
SpeckerRunner.new(command) do |runner|
|
|
70
|
+
yield runner
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
def command(klass, &specs)
|
|
2
|
+
describe klass do
|
|
3
|
+
let(:stub_precondition?) { true }
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
any_instance_of klass do |cli|
|
|
7
|
+
stub(cli).precondition if stub_precondition?
|
|
8
|
+
stub(cli).client { client }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
before(:all) do
|
|
13
|
+
klass.class_eval do
|
|
14
|
+
def wrap_errors
|
|
15
|
+
yield
|
|
16
|
+
rescue CF::UserError => e
|
|
17
|
+
err e.message
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
after(:all) do
|
|
23
|
+
klass.class_eval do
|
|
24
|
+
remove_method :wrap_errors
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class_eval(&specs)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
module CommandHelper
|
|
33
|
+
def cf(argv)
|
|
34
|
+
Mothership.new.exit_status 0
|
|
35
|
+
stub(CF::CLI).exit { |code| code }
|
|
36
|
+
capture_output { CF::CLI.start(argv + ["--debug", "--no-script"]) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def bool_flag(flag)
|
|
40
|
+
"#{'no-' unless send(flag)}#{flag.to_s.gsub('_', '-')}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
attr_reader :stdout, :stderr, :stdin, :status
|
|
44
|
+
|
|
45
|
+
def capture_output
|
|
46
|
+
$real_stdout = $stdout
|
|
47
|
+
$real_stderr = $stderr
|
|
48
|
+
$real_stdin = $stdin
|
|
49
|
+
$stdout = @stdout = StringIO.new
|
|
50
|
+
$stderr = @stderr = StringIO.new
|
|
51
|
+
$stdin = @stdin = StringIO.new
|
|
52
|
+
@status = yield
|
|
53
|
+
@stdout.rewind
|
|
54
|
+
@stderr.rewind
|
|
55
|
+
@status
|
|
56
|
+
ensure
|
|
57
|
+
$stdout = $real_stdout
|
|
58
|
+
$stderr = $real_stderr
|
|
59
|
+
$stdin = $real_stdin
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def output
|
|
63
|
+
@output ||= TrackingExpector.new(stdout)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def error_output
|
|
67
|
+
@error_output ||= TrackingExpector.new(stderr)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def mock_invoke(*args)
|
|
71
|
+
any_instance_of described_class do |cli|
|
|
72
|
+
mock(cli).invoke *args
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def dont_allow_invoke(*args)
|
|
77
|
+
any_instance_of described_class do |cli|
|
|
78
|
+
dont_allow(cli).invoke *args
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module ConfigHelper
|
|
2
|
+
def write_token_file(config={})
|
|
3
|
+
File.open(File.expand_path(tokens_file_path), 'w') do |f|
|
|
4
|
+
f.puts YAML.dump(
|
|
5
|
+
{ "https://api.some-domain.com" =>
|
|
6
|
+
{
|
|
7
|
+
:version => 2,
|
|
8
|
+
:token => 'bearer token',
|
|
9
|
+
:refresh_token => nil
|
|
10
|
+
}.merge(config)
|
|
11
|
+
}
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
module ConsoleAppSpeckerMatchers
|
|
2
|
+
class InvalidInputError < StandardError; end
|
|
3
|
+
|
|
4
|
+
class ExpectOutputMatcher
|
|
5
|
+
attr_reader :timeout
|
|
6
|
+
|
|
7
|
+
def initialize(expected_output, timeout = 30)
|
|
8
|
+
@expected_output = expected_output
|
|
9
|
+
@timeout = timeout
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def matches?(runner)
|
|
13
|
+
raise InvalidInputError unless runner.respond_to?(:expect)
|
|
14
|
+
@matched = runner.expect(@expected_output, @timeout)
|
|
15
|
+
@full_output = runner.output
|
|
16
|
+
!!@matched
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def failure_message
|
|
20
|
+
if @expected_output.is_a?(Hash)
|
|
21
|
+
expected_keys = @expected_output.keys.map{|key| "'#{key}'"}.join(', ')
|
|
22
|
+
"expected one of #{expected_keys} to be printed, but it wasn't. full output:\n#@full_output"
|
|
23
|
+
else
|
|
24
|
+
"expected '#{@expected_output}' to be printed, but it wasn't. full output:\n#@full_output"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def negative_failure_message
|
|
29
|
+
if @expected_output.is_a?(Hash)
|
|
30
|
+
match = @matched
|
|
31
|
+
else
|
|
32
|
+
match = @expected_output
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
"expected '#{match}' to not be printed, but it was. full output:\n#@full_output"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ExitCodeMatcher
|
|
41
|
+
def initialize(expected_code)
|
|
42
|
+
@expected_code = expected_code
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def matches?(runner)
|
|
46
|
+
raise InvalidInputError unless runner.respond_to?(:exit_code)
|
|
47
|
+
|
|
48
|
+
begin
|
|
49
|
+
Timeout.timeout(5) do
|
|
50
|
+
@actual_code = runner.exit_code
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
@actual_code == @expected_code
|
|
54
|
+
rescue Timeout::Error
|
|
55
|
+
@timed_out = true
|
|
56
|
+
false
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def failure_message
|
|
61
|
+
if @timed_out
|
|
62
|
+
"expected process to exit with status #@expected_code, but it did not exit within 5 seconds"
|
|
63
|
+
else
|
|
64
|
+
"expected process to exit with status #{@expected_code}, but it exited with status #{@actual_code}"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def negative_failure_message
|
|
69
|
+
if @timed_out
|
|
70
|
+
"expected process to exit with status #@expected_code, but it did not exit within 5 seconds"
|
|
71
|
+
else
|
|
72
|
+
"expected process to not exit with status #{@expected_code}, but it did"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def say(expected_output, timeout = 30)
|
|
78
|
+
ExpectOutputMatcher.new(expected_output, timeout)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def have_exited_with(expected_code)
|
|
82
|
+
ExitCodeMatcher.new(expected_code)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
alias :exit_with :have_exited_with
|
|
86
|
+
end
|