cf 0.1.5 → 0.6.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|