rhc 1.6.8 → 1.7.8
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/autocomplete/rhc_bash +1167 -0
- data/features/README.md +1 -1
- data/features/domain.feature +1 -1
- data/features/lib/rhc_helper/persistable.rb +4 -1
- data/features/multiple_cartridge.feature +4 -3
- data/features/sshkey.feature +3 -3
- data/features/support/assumptions.rb +3 -3
- data/features/support/env.rb +10 -0
- data/features/support/platform_support.rb +2 -2
- data/lib/rhc.rb +6 -0
- data/lib/rhc/auth/token.rb +4 -0
- data/lib/rhc/autocomplete.rb +50 -52
- data/lib/rhc/autocomplete_templates/{rhc.erb → bash.erb} +8 -2
- data/lib/rhc/cartridge_helpers.rb +1 -1
- data/lib/rhc/cli.rb +1 -7
- data/lib/rhc/command_runner.rb +45 -16
- data/lib/rhc/commands.rb +75 -55
- data/lib/rhc/commands/account.rb +7 -51
- data/lib/rhc/commands/alias.rb +26 -17
- data/lib/rhc/commands/app.rb +75 -39
- data/lib/rhc/commands/authorization.rb +4 -2
- data/lib/rhc/commands/base.rb +31 -29
- data/lib/rhc/commands/cartridge.rb +66 -44
- data/lib/rhc/commands/domain.rb +20 -8
- data/lib/rhc/commands/git_clone.rb +3 -3
- data/lib/rhc/commands/logout.rb +51 -0
- data/lib/rhc/commands/port_forward.rb +15 -11
- data/lib/rhc/commands/setup.rb +25 -0
- data/lib/rhc/commands/snapshot.rb +20 -10
- data/lib/rhc/commands/sshkey.rb +21 -7
- data/lib/rhc/commands/tail.rb +2 -2
- data/lib/rhc/commands/threaddump.rb +2 -2
- data/lib/rhc/context_helper.rb +0 -4
- data/lib/rhc/core_ext.rb +96 -76
- data/lib/rhc/exceptions.rb +6 -0
- data/lib/rhc/help_formatter.rb +19 -2
- data/lib/rhc/helpers.rb +32 -194
- data/lib/rhc/highline_extensions.rb +412 -0
- data/lib/rhc/output_helpers.rb +31 -67
- data/lib/rhc/rest.rb +4 -2
- data/lib/rhc/rest/alias.rb +0 -2
- data/lib/rhc/rest/application.rb +9 -4
- data/lib/rhc/rest/authorization.rb +0 -2
- data/lib/rhc/rest/base.rb +1 -1
- data/lib/rhc/rest/client.rb +11 -9
- data/lib/rhc/rest/domain.rb +5 -1
- data/lib/rhc/rest/gear_group.rb +0 -2
- data/lib/rhc/rest/key.rb +0 -2
- data/lib/rhc/rest/mock.rb +32 -10
- data/lib/rhc/ssh_helpers.rb +2 -2
- data/lib/rhc/usage_templates/command_help.erb +20 -13
- data/lib/rhc/usage_templates/command_syntax_help.erb +1 -3
- data/lib/rhc/usage_templates/help.erb +15 -16
- data/lib/rhc/usage_templates/options_help.erb +7 -9
- data/lib/rhc/wizard.rb +193 -159
- data/spec/rest_spec_helper.rb +2 -2
- data/spec/rhc/cli_spec.rb +36 -5
- data/spec/rhc/command_spec.rb +94 -42
- data/spec/rhc/commands/account_spec.rb +1 -75
- data/spec/rhc/commands/alias_spec.rb +28 -28
- data/spec/rhc/commands/app_spec.rb +141 -33
- data/spec/rhc/commands/apps_spec.rb +4 -4
- data/spec/rhc/commands/authorization_spec.rb +8 -8
- data/spec/rhc/commands/cartridge_spec.rb +18 -9
- data/spec/rhc/commands/domain_spec.rb +16 -16
- data/spec/rhc/commands/git_clone_spec.rb +3 -3
- data/spec/rhc/commands/logout_spec.rb +86 -0
- data/spec/rhc/commands/port_forward_spec.rb +9 -9
- data/spec/rhc/commands/server_spec.rb +5 -5
- data/spec/rhc/commands/setup_spec.rb +19 -5
- data/spec/rhc/commands/snapshot_spec.rb +12 -12
- data/spec/rhc/commands/sshkey_spec.rb +11 -11
- data/spec/rhc/commands/tail_spec.rb +5 -5
- data/spec/rhc/commands/threaddump_spec.rb +3 -3
- data/spec/rhc/config_spec.rb +6 -6
- data/spec/rhc/helpers_spec.rb +72 -219
- data/spec/rhc/highline_extensions_spec.rb +269 -0
- data/spec/rhc/rest_application_spec.rb +28 -1
- data/spec/rhc/rest_client_spec.rb +20 -21
- data/spec/rhc/rest_spec.rb +10 -0
- data/spec/rhc/wizard_spec.rb +72 -32
- data/spec/spec_helper.rb +86 -56
- data/spec/wizard_spec_helper.rb +7 -4
- metadata +165 -160
- data/spec/spec.opts +0 -1
data/spec/rhc/rest_spec.rb
CHANGED
@@ -43,6 +43,7 @@ describe RHC::Rest::Domain do
|
|
43
43
|
|
44
44
|
it{ domain.add_application('foo', :cartridges => ['bar']).should be_true }
|
45
45
|
it{ expect{ domain.add_application('foo', :cartridges => ['bar', 'other']) }.to raise_error(RHC::Rest::MultipleCartridgeCreationNotSupported) }
|
46
|
+
it{ expect{ domain.add_application('foo', :initial_git_url => 'a_url') }.to raise_error(RHC::Rest::InitialGitUrlNotSupported) }
|
46
47
|
it{ domain.add_application('foo', :cartridges => 'bar').should be_true }
|
47
48
|
it{ domain.add_application('foo', :cartridge => 'bar').should be_true }
|
48
49
|
it{ domain.add_application('foo', :cartridge => ['bar']).should be_true }
|
@@ -66,6 +67,15 @@ describe RHC::Rest::Domain do
|
|
66
67
|
it{ domain.add_application('foo', :cartridges => cartridges).should be_true }
|
67
68
|
it{ domain.add_application('foo', :cartridge => cartridges).should be_true }
|
68
69
|
end
|
70
|
+
|
71
|
+
context "with a url" do
|
72
|
+
before do
|
73
|
+
stub_api_request(:post, 'broker/rest/domains/bar/applications', false).
|
74
|
+
with(:body => {:name => 'foo', :initial_git_url => 'a_url', :cartridges => []}.to_json).
|
75
|
+
to_return(:status => 201, :body => {:type => 'application', :data => {:id => '1'}}.to_json)
|
76
|
+
end
|
77
|
+
it{ domain.add_application('foo', :initial_git_url => 'a_url').should be_true }
|
78
|
+
end
|
69
79
|
end
|
70
80
|
end
|
71
81
|
|
data/spec/rhc/wizard_spec.rb
CHANGED
@@ -53,7 +53,7 @@ describe RHC::Wizard do
|
|
53
53
|
mock_config
|
54
54
|
FileUtils.mkdir_p(RHC::Config.ssh_dir)
|
55
55
|
File.open(RHC::Config.ssh_priv_key_file_path, 'w'){}
|
56
|
-
File.
|
56
|
+
File.expect_mode(RHC::Config.ssh_priv_key_file_path, 0666)
|
57
57
|
expect{ subject.send(:test_private_key_mode) }.to raise_error(StandardError)
|
58
58
|
end
|
59
59
|
end
|
@@ -97,13 +97,14 @@ describe RHC::Wizard do
|
|
97
97
|
let(:password){ 'test pass' }
|
98
98
|
let(:rest_client){ stub }
|
99
99
|
let(:auth){ subject.send(:auth) }
|
100
|
+
let(:user_obj){ stub(:login => user) }
|
100
101
|
|
101
102
|
subject{ described_class.new(config, options) }
|
102
103
|
|
103
104
|
def expect_client_test(with_sessions=false)
|
104
105
|
subject.should_receive(:new_client_for_options).ordered.and_return(rest_client)
|
105
106
|
rest_client.should_receive(:api).ordered
|
106
|
-
rest_client.should_receive(:user).ordered.and_return(
|
107
|
+
rest_client.should_receive(:user).ordered.and_return(user_obj)
|
107
108
|
rest_client.should_receive(:supports_sessions?).ordered.and_return(with_sessions)
|
108
109
|
end
|
109
110
|
def expect_raise_from_api(error)
|
@@ -114,6 +115,7 @@ describe RHC::Wizard do
|
|
114
115
|
it "should prompt for user and password" do
|
115
116
|
expect_client_test
|
116
117
|
subject.send(:login_stage).should be_true
|
118
|
+
subject.send(:options).rhlogin.should == user
|
117
119
|
end
|
118
120
|
|
119
121
|
context "with token" do
|
@@ -181,6 +183,7 @@ describe RHC::Wizard do
|
|
181
183
|
before{ RHC::Auth::TokenStore.should_receive(:new).any_number_of_times.and_return(store) }
|
182
184
|
|
183
185
|
it "should not generate a token if the user does not request it" do
|
186
|
+
store.should_receive(:get).and_return(nil)
|
184
187
|
subject.should_receive(:info).with(/OpenShift can create and store a token on disk/).ordered
|
185
188
|
subject.should_receive(:agree).with(/Generate a token now?/).ordered.and_return(false)
|
186
189
|
|
@@ -189,6 +192,7 @@ describe RHC::Wizard do
|
|
189
192
|
end
|
190
193
|
|
191
194
|
it "should generate a token if the user requests it" do
|
195
|
+
store.should_receive(:get).and_return(nil)
|
192
196
|
subject.should_receive(:info).with(/OpenShift can create and store a token on disk/).ordered
|
193
197
|
subject.should_receive(:agree).with(/Generate a token now?/).ordered.and_return(true)
|
194
198
|
subject.should_receive(:say).with(/Generating an authorization token for this client /).ordered
|
@@ -278,7 +282,7 @@ describe RHC::Wizard do
|
|
278
282
|
|
279
283
|
context "when the user enters a domain and uploads a key" do
|
280
284
|
before do
|
281
|
-
|
285
|
+
stub_add_key
|
282
286
|
stub_api_request(:post, 'broker/rest/domains', user_auth).
|
283
287
|
with(:body => /(thisnamespaceistoobig|invalidnamespace)/).
|
284
288
|
to_return({
|
@@ -340,6 +344,33 @@ describe RHC::Wizard do
|
|
340
344
|
end
|
341
345
|
end
|
342
346
|
|
347
|
+
context "when a multiple keys exist but is not the same" do
|
348
|
+
before{ setup_mock_ssh(true) }
|
349
|
+
before do
|
350
|
+
stub_one_key('a_key')
|
351
|
+
stub_add_key_error('invalid```--', 'Invalid key name')
|
352
|
+
stub_add_key('another_key')
|
353
|
+
end
|
354
|
+
it "should give the user a name the key" do
|
355
|
+
should_greet_user
|
356
|
+
should_challenge_for(username, password)
|
357
|
+
should_write_config
|
358
|
+
should_not_create_an_ssh_keypair
|
359
|
+
|
360
|
+
input_line 'yes'
|
361
|
+
input_line 'invalid```--'
|
362
|
+
input_line 'another_key'
|
363
|
+
next_stage
|
364
|
+
|
365
|
+
last_output do |s|
|
366
|
+
s.should match(/a_key \(type: ssh-rsa\)/)
|
367
|
+
s.should match("Fingerprint: #{rsa_key_fingerprint_public}")
|
368
|
+
s.should match(" name |a_key|")
|
369
|
+
s.should match("Invalid key name")
|
370
|
+
s.should match("Uploading key 'another_key'")
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
343
374
|
context "when the default key already exists on the server" do
|
344
375
|
before{ setup_mock_ssh(true) }
|
345
376
|
before{ stub_mock_ssh_keys }
|
@@ -362,7 +393,7 @@ describe RHC::Wizard do
|
|
362
393
|
stub_api(:user => username)
|
363
394
|
stub_user
|
364
395
|
stub_no_keys
|
365
|
-
|
396
|
+
stub_add_key
|
366
397
|
stub_api_request(:post, 'broker/rest/domains', user_auth).
|
367
398
|
with(:body => /(thisnamespaceistoobig|invalidnamespace)/).
|
368
399
|
to_return({
|
@@ -414,7 +445,7 @@ describe RHC::Wizard do
|
|
414
445
|
|
415
446
|
context "with no server keys" do
|
416
447
|
before{ stub_no_keys }
|
417
|
-
before{
|
448
|
+
before{ stub_add_key }
|
418
449
|
|
419
450
|
it "should generate and upload keys since the user does not have them" do
|
420
451
|
input_line "yes"
|
@@ -451,44 +482,45 @@ describe RHC::Wizard do
|
|
451
482
|
let(:wizard){ RerunWizardDriver.new }
|
452
483
|
|
453
484
|
it "should cause ssh_key_upload? to catch NoMethodError and call the fallback to get the fingerprint" do
|
454
|
-
Net::SSH::KeyFactory.
|
455
|
-
|
456
|
-
wizard.
|
457
|
-
key_data = wizard.get_mock_key_data
|
458
|
-
@rest_client.stub(:sshkeys) { key_data }
|
485
|
+
Net::SSH::KeyFactory.should_receive(:load_public_key).exactly(4).times.and_raise(NoMethodError)
|
486
|
+
wizard.should_receive(:ssh_keygen_fallback).exactly(4).times
|
487
|
+
wizard.should_receive(:ssh_keys).at_least(1).times.and_return(wizard.get_mock_key_data)
|
459
488
|
|
460
489
|
wizard.send(:ssh_key_uploaded?)
|
461
|
-
|
462
|
-
@fallback_run.should be_true
|
463
490
|
end
|
464
491
|
|
465
492
|
it "should cause upload_ssh_key to catch NoMethodError and call the fallback to get the fingerprint" do
|
466
|
-
|
467
|
-
|
468
|
-
wizard.
|
469
|
-
@fallback_run = true
|
470
|
-
[OpenStruct.new( :name => 'default', :fingerprint => 'AA:BB:CC:DD:EE:FF', :type => 'ssh-rsa' )]
|
471
|
-
end
|
472
|
-
$?.stub(:exitstatus) { 255 }
|
473
|
-
Net::SSH::KeyFactory.stub(:load_public_key) { raise NoMethodError }
|
493
|
+
Net::SSH::KeyFactory.should_receive(:load_public_key).exactly(5).times.and_raise(NoMethodError)
|
494
|
+
wizard.stub(:ssh_keys).at_least(1).times.and_return(wizard.get_mock_key_data)
|
495
|
+
wizard.should_receive(:ssh_keygen_fallback).exactly(5).times.and_return(stub(:name => 'default', :fingerprint => 'AA:BB:CC:DD:EE:FF', :type => 'ssh-rsa' ))
|
474
496
|
|
475
|
-
|
497
|
+
input_line 'y'
|
476
498
|
|
477
|
-
|
478
|
-
|
479
|
-
|
499
|
+
wizard.send(:upload_ssh_key_stage).should be_false
|
500
|
+
|
501
|
+
last_output.should match("Your ssh public key at .* is invalid or unreadable\.")
|
480
502
|
end
|
481
503
|
|
482
504
|
it "should cause upload_ssh_key to catch NotImplementedError and return false" do
|
483
|
-
|
484
|
-
|
505
|
+
Net::SSH::KeyFactory.should_receive(:load_public_key).exactly(5).times.and_raise(NoMethodError)
|
506
|
+
wizard.should_receive(:ssh_keys).at_least(1).times.and_return(wizard.get_mock_key_data)
|
507
|
+
|
508
|
+
input_line 'y'
|
485
509
|
|
486
|
-
wizard.send(:
|
510
|
+
wizard.send(:upload_ssh_key_stage).should be_false
|
487
511
|
|
488
512
|
output = last_output
|
489
513
|
output.should match("Your ssh public key at .* is invalid or unreadable\.")
|
490
514
|
end
|
491
515
|
|
516
|
+
it "should find a unique name" do
|
517
|
+
wizard.should_receive(:ssh_keys).at_least(1).times.and_return(wizard.get_mock_key_data)
|
518
|
+
|
519
|
+
wizard.send(:find_unique_key_name, 'cb490595').should == 'cb4905951'
|
520
|
+
wizard.send(:find_unique_key_name, 'default').should == 'default1'
|
521
|
+
wizard.send(:find_unique_key_name, 'abc').should == 'abc'
|
522
|
+
end
|
523
|
+
|
492
524
|
it "should match ssh key fallback fingerprint to net::ssh fingerprint" do
|
493
525
|
# we need to write to a live file system so ssh-keygen can find it
|
494
526
|
FakeFS.deactivate!
|
@@ -521,12 +553,11 @@ describe RHC::Wizard do
|
|
521
553
|
key_name = 'default'
|
522
554
|
key_data = wizard.get_mock_key_data
|
523
555
|
wizard.ssh_keys = key_data
|
524
|
-
wizard.stub(:get_preferred_key_name) { key_name }
|
525
556
|
wizard.stub(:ssh_key_triple_for_default_key) { pub_key.chomp.split }
|
526
557
|
wizard.stub(:fingerprint_for_default_key) { "" } # this value is irrelevant
|
527
|
-
wizard.rest_client.stub(:find_key) { key_data.detect { |k| k.name == key_name } }
|
558
|
+
wizard.rest_client = stub('RestClient').tap{ |o| o.stub(:find_key) { key_data.detect { |k| k.name == key_name } } }
|
528
559
|
|
529
|
-
wizard.send(:upload_ssh_key)
|
560
|
+
wizard.send(:upload_ssh_key, key_name)
|
530
561
|
output = last_output
|
531
562
|
output.should match 'Updating'
|
532
563
|
end
|
@@ -540,9 +571,9 @@ describe RHC::Wizard do
|
|
540
571
|
wizard.ssh_keys = key_data
|
541
572
|
wizard.stub(:ssh_key_triple_for_default_key) { pub_key.chomp.split }
|
542
573
|
wizard.stub(:fingerprint_for_default_key) { "" } # this value is irrelevant
|
543
|
-
wizard.rest_client.stub(:add_key) { true }
|
574
|
+
wizard.rest_client = stub('RestClient').tap{ |o| o.stub(:add_key) { true } }
|
544
575
|
|
545
|
-
wizard.send(:upload_ssh_key)
|
576
|
+
wizard.send(:upload_ssh_key, "other")
|
546
577
|
output = last_output
|
547
578
|
# since the clashing key name is short, we expect to present
|
548
579
|
# a key name with "1" attached to it.
|
@@ -689,3 +720,12 @@ EOF
|
|
689
720
|
end
|
690
721
|
end
|
691
722
|
end
|
723
|
+
|
724
|
+
describe RHC::DomainWizard do
|
725
|
+
context "with a rest client" do
|
726
|
+
let(:rest_client){ stub }
|
727
|
+
it{ described_class.new(nil, nil, rest_client).rest_client.should == rest_client }
|
728
|
+
it{ subject.stages == [:config_namespace_stage] }
|
729
|
+
it{ expect{ described_class.new(nil, nil, rest_client).send(:config_namespace, '') }.to call(:add_domain).on(rest_client).and_stop }
|
730
|
+
end
|
731
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -75,6 +75,50 @@ end
|
|
75
75
|
|
76
76
|
require 'rhc/cli'
|
77
77
|
|
78
|
+
class MockHighLineTerminal < HighLineExtension
|
79
|
+
def self.use_color?
|
80
|
+
true
|
81
|
+
end
|
82
|
+
|
83
|
+
def initialize(input=StringIO.new, output=StringIO.new)
|
84
|
+
super
|
85
|
+
@last_read_pos = 0
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# read
|
90
|
+
#
|
91
|
+
# seeks to the last read in the IO stream and reads
|
92
|
+
# the data from that position so we don't repeat
|
93
|
+
# reads or get empty data due to writes moving
|
94
|
+
# the caret to the end of the stream
|
95
|
+
def read
|
96
|
+
@output.seek(@last_read_pos)
|
97
|
+
result = @output.read
|
98
|
+
@last_read_pos = @output.pos
|
99
|
+
result
|
100
|
+
end
|
101
|
+
|
102
|
+
##
|
103
|
+
# write_line
|
104
|
+
#
|
105
|
+
# writes a line of data to the end of the
|
106
|
+
# input stream appending a newline so
|
107
|
+
# highline knows to stop processing and then
|
108
|
+
# resets the caret position to the last read
|
109
|
+
def write_line(str)
|
110
|
+
reset_pos = @input.pos
|
111
|
+
# seek end so we don't overwrite anything
|
112
|
+
@input.seek(0, IO::SEEK_END)
|
113
|
+
result = @input.write "#{str}\n"
|
114
|
+
@input.seek(reset_pos)
|
115
|
+
result
|
116
|
+
end
|
117
|
+
def close_write
|
118
|
+
@input.close_write
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
78
122
|
include WebMock::API
|
79
123
|
|
80
124
|
def stderr
|
@@ -134,14 +178,14 @@ module CommandHelpers
|
|
134
178
|
# let(:arguments){ [<arguments>] }
|
135
179
|
#
|
136
180
|
|
137
|
-
def run_command
|
181
|
+
def run_command(args=arguments)
|
138
182
|
mock_terminal
|
139
183
|
input.each { |i| $terminal.write_line(i) } if respond_to?(:input)
|
140
184
|
$terminal.close_write
|
141
|
-
run!(*
|
185
|
+
run!(*args)
|
142
186
|
end
|
143
|
-
def command_output
|
144
|
-
run_command
|
187
|
+
def command_output(args=arguments)
|
188
|
+
run_command(args)
|
145
189
|
rescue SystemExit => e
|
146
190
|
"#{@output.string}\n#{$stderr.string}#{e}"
|
147
191
|
else
|
@@ -178,7 +222,7 @@ module ClassSpecHelpers
|
|
178
222
|
if obj
|
179
223
|
Object.const_set(const_for, obj)
|
180
224
|
else
|
181
|
-
"#{
|
225
|
+
"#{example.full_description}".split(" ").map{|word| word.capitalize}.join.gsub(/[^\w]/, '')
|
182
226
|
end
|
183
227
|
end
|
184
228
|
|
@@ -206,51 +250,6 @@ module ClassSpecHelpers
|
|
206
250
|
Commander::Runner.instance
|
207
251
|
end
|
208
252
|
|
209
|
-
class MockHighLineTerminal < HighLine
|
210
|
-
|
211
|
-
def self.use_color?
|
212
|
-
true
|
213
|
-
end
|
214
|
-
|
215
|
-
def initialize(input, output)
|
216
|
-
super
|
217
|
-
@last_read_pos = 0
|
218
|
-
end
|
219
|
-
|
220
|
-
##
|
221
|
-
# read
|
222
|
-
#
|
223
|
-
# seeks to the last read in the IO stream and reads
|
224
|
-
# the data from that position so we don't repeat
|
225
|
-
# reads or get empty data due to writes moving
|
226
|
-
# the caret to the end of the stream
|
227
|
-
def read
|
228
|
-
@output.seek(@last_read_pos)
|
229
|
-
result = @output.read
|
230
|
-
@last_read_pos = @output.pos
|
231
|
-
result
|
232
|
-
end
|
233
|
-
|
234
|
-
##
|
235
|
-
# write_line
|
236
|
-
#
|
237
|
-
# writes a line of data to the end of the
|
238
|
-
# input stream appending a newline so
|
239
|
-
# highline knows to stop processing and then
|
240
|
-
# resets the caret position to the last read
|
241
|
-
def write_line(str)
|
242
|
-
reset_pos = @input.pos
|
243
|
-
# seek end so we don't overwrite anything
|
244
|
-
@input.seek(0, IO::SEEK_END)
|
245
|
-
result = @input.write "#{str}\n"
|
246
|
-
@input.seek(reset_pos)
|
247
|
-
result
|
248
|
-
end
|
249
|
-
def close_write
|
250
|
-
@input.close_write
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
253
|
def mock_terminal
|
255
254
|
@input = StringIO.new
|
256
255
|
@output = StringIO.new
|
@@ -342,7 +341,7 @@ module ClassSpecHelpers
|
|
342
341
|
end
|
343
342
|
|
344
343
|
module ExitCodeMatchers
|
345
|
-
|
344
|
+
RSpec::Matchers.define :exit_with_code do |code|
|
346
345
|
actual = nil
|
347
346
|
match do |block|
|
348
347
|
begin
|
@@ -366,20 +365,28 @@ module ExitCodeMatchers
|
|
366
365
|
end
|
367
366
|
|
368
367
|
module CommanderInvocationMatchers
|
369
|
-
|
368
|
+
InvocationMatch = Class.new(RuntimeError)
|
369
|
+
|
370
|
+
RSpec::Matchers.define :call do |method|
|
370
371
|
chain :on do |object|
|
371
372
|
@object = object
|
372
373
|
end
|
373
|
-
chain :with do
|
374
|
+
chain :with do |*args|
|
374
375
|
@args = args
|
375
376
|
end
|
377
|
+
chain :and_stop do
|
378
|
+
@stop = true
|
379
|
+
end
|
376
380
|
|
377
381
|
match do |block|
|
378
382
|
e = @object.should_receive(method)
|
379
|
-
e.
|
383
|
+
e.and_raise(InvocationMatch) if @stop
|
384
|
+
e.with(*@args) if @args
|
380
385
|
begin
|
381
386
|
block.call
|
382
387
|
true
|
388
|
+
rescue InvocationMatch => e
|
389
|
+
true
|
383
390
|
rescue SystemExit => e
|
384
391
|
false
|
385
392
|
end
|
@@ -388,6 +395,29 @@ module CommanderInvocationMatchers
|
|
388
395
|
"expect block to invoke '#{method}' on #{@object} with #{@args}"
|
389
396
|
end
|
390
397
|
end
|
398
|
+
|
399
|
+
RSpec::Matchers.define :not_call do |method|
|
400
|
+
chain :on do |object|
|
401
|
+
@object = object
|
402
|
+
end
|
403
|
+
chain :with do |*args|
|
404
|
+
@args = args
|
405
|
+
end
|
406
|
+
|
407
|
+
match do |block|
|
408
|
+
e = @object.should_not_receive(method)
|
409
|
+
e.with(*@args) if @args
|
410
|
+
begin
|
411
|
+
block.call
|
412
|
+
true
|
413
|
+
rescue SystemExit => e
|
414
|
+
false
|
415
|
+
end
|
416
|
+
end
|
417
|
+
description do
|
418
|
+
"expect block to invoke '#{method}' on #{@object} with #{@args}"
|
419
|
+
end
|
420
|
+
end
|
391
421
|
end
|
392
422
|
|
393
423
|
module ColorMatchers
|
@@ -399,7 +429,7 @@ module ColorMatchers
|
|
399
429
|
:clear => 0
|
400
430
|
}
|
401
431
|
|
402
|
-
|
432
|
+
RSpec::Matchers.define :be_colorized do |msg,color|
|
403
433
|
match do |actual|
|
404
434
|
actual == colorized_message(msg,color)
|
405
435
|
end
|
@@ -436,7 +466,7 @@ def mac?
|
|
436
466
|
RbConfig::CONFIG['host_os'] =~ /^darwin/
|
437
467
|
end
|
438
468
|
|
439
|
-
|
469
|
+
RSpec.configure do |config|
|
440
470
|
config.include(ExitCodeMatchers)
|
441
471
|
config.include(CommanderInvocationMatchers)
|
442
472
|
config.include(ColorMatchers)
|