rhc 1.22.5 → 1.23.7

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.
@@ -13,7 +13,7 @@ module RHC::Commands
13
13
  cartridge) by default.
14
14
 
15
15
  Examples:
16
- Uploading a file from your workding directory to your app-root/data directory
16
+ Uploading a file from your working directory to your app-root/data directory
17
17
  rhc scp myapp upload somefile.txt app-root/data
18
18
 
19
19
  Downloading a file from your app-root/data directory to your working directory
@@ -67,6 +67,24 @@ module RHC
67
67
  end
68
68
  end
69
69
 
70
+ class TeamsNotSupportedException < Exception
71
+ def initialize(message="Server does not support teams")
72
+ super message, 161
73
+ end
74
+ end
75
+
76
+ class TeamNotFoundException < Exception
77
+ def initialize(message="Team not found")
78
+ super message, 162
79
+ end
80
+ end
81
+
82
+ class MemberNotFoundException < Exception
83
+ def initialize(message="Member not found")
84
+ super message, 163
85
+ end
86
+ end
87
+
70
88
  class GitPermissionDenied < GitException; end
71
89
  class GitDirectoryExists < GitException; end
72
90
 
data/lib/rhc/helpers.rb CHANGED
@@ -437,7 +437,7 @@ module RHC
437
437
  def run_with_tee(cmd)
438
438
  status, stdout, stderr = nil
439
439
 
440
- if windows?
440
+ if windows? || jruby?
441
441
  #:nocov: TODO: Test block
442
442
  system(cmd)
443
443
  status = $?.exitstatus
data/lib/rhc/rest.rb CHANGED
@@ -18,6 +18,7 @@ module RHC
18
18
  autoload :GearGroup, 'rhc/rest/gear_group'
19
19
  autoload :Key, 'rhc/rest/key'
20
20
  autoload :Membership, 'rhc/rest/membership'
21
+ autoload :Team, 'rhc/rest/team'
21
22
  autoload :User, 'rhc/rest/user'
22
23
 
23
24
  class Exception < RuntimeError
@@ -64,6 +64,38 @@ module RHC
64
64
  @user ||= api.rest_method "GET_USER"
65
65
  end
66
66
 
67
+ def teams
68
+ debug "Getting all teams"
69
+ if link = api.link_href(:LIST_TEAMS)
70
+ @teams ||= api.rest_method "LIST_TEAMS"
71
+ else
72
+ raise RHC::TeamsNotSupportedException
73
+ end
74
+ end
75
+
76
+ def owned_teams
77
+ debug "Getting owned teams"
78
+ if link = api.link_href(:LIST_TEAMS_BY_OWNER)
79
+ @owned_teams ||= api.rest_method "LIST_TEAMS_BY_OWNER", :owner => '@self'
80
+ else
81
+ raise RHC::TeamsNotSupportedException
82
+ end
83
+ end
84
+
85
+ def search_teams(search, global=false)
86
+ debug "Searching teams"
87
+ if link = api.link_href(:SEARCH_TEAMS)
88
+ api.rest_method "SEARCH_TEAMS", :search => search, :global => global
89
+ else
90
+ raise RHC::TeamsNotSupportedException
91
+ end
92
+ end
93
+
94
+ def search_owned_teams(search)
95
+ debug "Searching owned teams"
96
+ owned_teams.select{|team| team.name.downcase =~ /#{Regexp.escape(search)}/i}
97
+ end
98
+
67
99
  #Find Domain by namespace
68
100
  def find_domain(id)
69
101
  debug "Finding domain #{id}"
@@ -550,6 +582,12 @@ module RHC
550
582
  data.map{ |json| EnvironmentVariable.new(json, self) }
551
583
  when 'deployments'
552
584
  data.map{ |json| Deployment.new(json, self) }
585
+ when 'teams'
586
+ data.map{ |json| Team.new(json, self) }
587
+ when 'member'
588
+ RHC::Rest::Membership::Member.new(data, self)
589
+ when 'members'
590
+ data.map{ |json| RHC::Rest::Membership::Member.new(json, self) }
553
591
  else
554
592
  data
555
593
  end
@@ -1,22 +1,54 @@
1
1
  module RHC::Rest
2
2
  module Membership
3
3
  class Member < Base
4
+
4
5
  define_attr :name, :login, :id, :type, :from, :role, :owner, :explicit_role
6
+
5
7
  def owner?
6
8
  !!owner
7
9
  end
10
+
8
11
  def admin?
9
12
  role == 'admin'
10
13
  end
14
+
11
15
  def editor?
12
16
  role == 'edit'
13
17
  end
18
+
14
19
  def viewer?
15
20
  role == 'view'
16
21
  end
22
+
23
+ def team?
24
+ type == 'team'
25
+ end
26
+
17
27
  def name
18
28
  attributes['name'] || login
19
29
  end
30
+
31
+ def type
32
+ attributes['type'] || 'user'
33
+ end
34
+
35
+ def explicit_role?
36
+ explicit_role.present?
37
+ end
38
+
39
+ def from
40
+ Array(attributes['from'])
41
+ end
42
+
43
+ def grant_from?(type, id)
44
+ from.detect {|f| f['type'] == type && f['id'] == id}
45
+ end
46
+
47
+ def teams(members)
48
+ team_ids = from.inject([]) {|ids, f| ids << f['id'] if f['type'] == 'team'; ids }
49
+ members.select {|m| m.team? && team_ids.include?(m.id) }
50
+ end
51
+
20
52
  def to_s
21
53
  if name == login
22
54
  "#{login} (#{role})"
@@ -26,12 +58,21 @@ module RHC::Rest
26
58
  "#{name} (#{role})"
27
59
  end
28
60
  end
61
+
62
+ def <=>(other)
63
+ [role_weight, type, name, id] <=> [other.role_weight, other.type, other.name, other.id]
64
+ end
65
+
29
66
  def role_weight
30
- case role
31
- when 'admin' then 0
32
- when 'edit' then 1
33
- when 'view' then 2
34
- else 3
67
+ if owner?
68
+ 0
69
+ else
70
+ case role
71
+ when 'admin' then 1
72
+ when 'edit' then 2
73
+ when 'view' then 3
74
+ else 4
75
+ end
35
76
  end
36
77
  end
37
78
  end
data/lib/rhc/rest/mock.rb CHANGED
@@ -428,11 +428,18 @@ module RHC::Rest::Mock
428
428
  end
429
429
 
430
430
  def mock_real_client_links
431
- [['GET_USER', "broker/rest/user", 'GET'],
432
- ['LIST_DOMAINS', "broker/rest/domains", 'GET'],
433
- ['ADD_DOMAIN', "broker/rest/domains", 'POST', ({'optional_params' => [{'name' => 'allowed_gear_sizes'}]} if example_allows_gear_sizes?)].compact,
434
- ['LIST_CARTRIDGES', "broker/rest/cartridges", 'GET'],
435
- ]
431
+ mock_teams_links.concat([
432
+ ['GET_USER', "broker/rest/user", 'GET'],
433
+ ['LIST_DOMAINS', "broker/rest/domains", 'GET'],
434
+ ['ADD_DOMAIN', "broker/rest/domains", 'POST', ({'optional_params' => [{'name' => 'allowed_gear_sizes'}]} if example_allows_gear_sizes?)].compact,
435
+ ['LIST_CARTRIDGES', "broker/rest/cartridges", 'GET'],
436
+ ])
437
+ end
438
+
439
+ def mock_teams_links
440
+ [['SEARCH_TEAMS', "broker/rest/teams", 'GET'],
441
+ ['LIST_TEAMS', "broker/rest/teams", 'GET'],
442
+ ['LIST_TEAMS_BY_OWNER', "broker/rest/teams", 'GET']]
436
443
  end
437
444
 
438
445
  def mock_api_with_authorizations
@@ -696,6 +703,12 @@ module RHC::Rest::Mock
696
703
  @applications
697
704
  end
698
705
 
706
+ def init_members
707
+ @members ||= []
708
+ attributes['members'] ||= []
709
+ self
710
+ end
711
+
699
712
  def add_member(member)
700
713
  (@members ||= []) << member
701
714
  (attributes['members'] ||= []) << member.attributes
@@ -902,6 +915,12 @@ module RHC::Rest::Mock
902
915
  end
903
916
  end
904
917
 
918
+ def init_members
919
+ @members ||= []
920
+ attributes['members'] ||= []
921
+ self
922
+ end
923
+
905
924
  def add_member(member)
906
925
  (@members ||= []) << member
907
926
  (attributes['members'] ||= []) << member.attributes
@@ -0,0 +1,20 @@
1
+ module RHC
2
+ module Rest
3
+ class Team < Base
4
+
5
+ define_attr :id, :name, :global
6
+
7
+ def global?
8
+ global
9
+ end
10
+
11
+ def <=>(team)
12
+ return self.name <=> team.name
13
+ end
14
+
15
+ def to_s
16
+ self.name
17
+ end
18
+ end
19
+ end
20
+ end
@@ -334,7 +334,7 @@ describe RHC::Commands::Domain do
334
334
  let(:arguments) { ['domain', 'leave', '-n', 'deleteme'] }
335
335
 
336
336
  it "should leave the domain" do
337
- rest_client.domains.first.should_receive(:leave)
337
+ rest_client.domains.first.should_receive(:leave).and_return(RHC::Rest::Membership::Member.new)
338
338
  expect { run }.to exit_with_code(0)
339
339
  end
340
340
  end
@@ -13,7 +13,7 @@ describe RHC::Commands::Member do
13
13
  expect { run }.to exit_with_code(0)
14
14
  end
15
15
  it('should output usage') { run_output.should match "Usage: rhc member" }
16
- it('should output info about roles') { run_output.should match "Teams of developers can collaborate" }
16
+ it('should output info about roles') { run_output.should match "Developers can collaborate" }
17
17
  end
18
18
 
19
19
  let(:username){ 'test_user' }
@@ -35,13 +35,23 @@ describe RHC::Commands::Member do
35
35
  end
36
36
  end
37
37
 
38
- let(:owner){ RHC::Rest::Membership::Member.new(:id => '1', :role => 'admin', :owner => true, :login => 'alice') }
39
- let(:other_admin){ RHC::Rest::Membership::Member.new(:id => '2', :role => 'admin', :login => 'Bob') }
40
- let(:other_editor){ RHC::Rest::Membership::Member.new(:id => '3', :role => 'edit', :name => 'Carol', :login => 'carol') }
41
- let(:other_viewer){ RHC::Rest::Membership::Member.new(:id => '4', :role => 'view', :name => 'Doug', :login => 'doug@doug.com') }
42
- let(:other_viewer2){ RHC::Rest::Membership::Member.new(:id => '5', :role => 'view', :name => 'ViewerC', :login => 'viewerc@viewer.com') }
43
- let(:other_viewer3){ RHC::Rest::Membership::Member.new(:id => '6', :role => 'view', :name => 'ViewerB', :login => 'viewerb@viewer.com') }
44
- let(:other_viewer4){ RHC::Rest::Membership::Member.new(:id => '7', :role => 'view', :name => 'ViewerA', :login => 'viewera@viewer.com') }
38
+ let(:owner){ RHC::Rest::Membership::Member.new(:id => '1', :role => 'admin', :explicit_role => 'admin', :owner => true, :login => 'alice', :type => 'user') }
39
+ let(:other_admin){ RHC::Rest::Membership::Member.new(:id => '2', :role => 'admin', :explicit_role => 'admin', :login => 'Bob', :type => 'user') }
40
+ let(:other_editor){ RHC::Rest::Membership::Member.new(:id => '3', :role => 'edit', :explicit_role => 'edit', :name => 'Carol', :login => 'carol', :type => 'user') }
41
+ let(:other_viewer){ RHC::Rest::Membership::Member.new(:id => '4', :role => 'view', :explicit_role => 'view', :name => 'Doug', :login => 'doug@doug.com', :type => 'user') }
42
+ let(:other_viewer2){ RHC::Rest::Membership::Member.new(:id => '5', :role => 'view', :explicit_role => 'view', :name => 'ViewerC', :login => 'viewerc@viewer.com', :type => 'user') }
43
+ let(:other_viewer3){ RHC::Rest::Membership::Member.new(:id => '6', :role => 'view', :explicit_role => 'view', :name => 'ViewerB', :login => 'viewerb@viewer.com', :type => 'user') }
44
+ let(:other_viewer4){ RHC::Rest::Membership::Member.new(:id => '7', :role => 'view', :explicit_role => 'view', :name => 'ViewerA', :login => 'viewera@viewer.com', :type => 'user') }
45
+ let(:team_admin){ RHC::Rest::Membership::Member.new(:id => '11', :role => 'admin', :explicit_role => 'admin', :name => 'team1', :type => 'team') }
46
+ let(:team_editor){ RHC::Rest::Membership::Member.new(:id => '12', :role => 'edit', :explicit_role => 'edit', :name => 'team2', :type => 'team') }
47
+ let(:team_viewer){ RHC::Rest::Membership::Member.new(:id => '13', :role => 'view', :explicit_role => 'view', :name => 'team3', :type => 'team') }
48
+ let(:team_admin_member){ RHC::Rest::Membership::Member.new(:id => '21', :role => 'admin', :login => 'memberadmin', :type => 'user', :from => [{'id' => '11', 'type' => 'team'}]) }
49
+ let(:team_editor_member){ RHC::Rest::Membership::Member.new(:id => '22', :role => 'edit', :login => 'membereditor', :type => 'user', :from => [{'id' => '12', 'type' => 'team'}]) }
50
+ let(:team_viewer_member){ RHC::Rest::Membership::Member.new(:id => '23', :role => 'view', :login => 'memberviewer', :type => 'user', :from => [{'id' => '13', 'type' => 'team'}]) }
51
+ let(:team_viewer_member2){ RHC::Rest::Membership::Member.new(:id => '24', :role => 'view', :login => 'memberviewer2', :type => 'user', :from => [{'id' => '13', 'type' => 'team'}]) }
52
+ let(:team_viewer_member3){ RHC::Rest::Membership::Member.new(:id => '25', :role => 'view', :login => 'memberviewer3', :type => 'user', :from => [{'id' => '13', 'type' => 'team'}]) }
53
+ let(:team_viewer_and_explicit_member){ RHC::Rest::Membership::Member.new(:id => '26', :role => 'view', :explicit_role => 'view', :login => 'memberviewerexplicitedit', :type => 'user', :from => [{'id' => '13', 'type' => 'team'}]) }
54
+ let(:app_member_via_domain) { RHC::Rest::Membership::Member.new(:id => '27', :role => 'view', :login => 'app_member_via_domain', :type => 'user', :from => [{'type' => 'domain'}]) }
45
55
 
46
56
  describe 'show-domain' do
47
57
  context 'with members' do
@@ -57,16 +67,52 @@ describe RHC::Commands::Member do
57
67
  it("should order the members by role then by name") { run_output.should =~ /Bob.*admin.*Admins.*Carol.*Editors.*ViewerA.*ViewerB.*ViewerC.*Viewers/m }
58
68
  it("should include the login value") { run_output.should =~ /alice.*Bob.*carol.*doug@doug\.com/m }
59
69
  end
70
+
60
71
  end
61
72
 
62
73
  describe 'list-member' do
74
+ context 'on a domain with no members' do
75
+ let(:arguments) { ['members', '-n', 'mock-domain-0'] }
76
+ let(:supports_members){ true }
77
+ before{ with_mock_domain.init_members }
78
+ it { expect { run }.to exit_with_code(0) }
79
+ it { run_output.should =~ /does not have any members/ }
80
+ end
81
+
63
82
  context 'on a domain' do
64
83
  let(:arguments) { ['members', '-n', 'mock-domain-0'] }
65
84
  let(:supports_members){ true }
66
85
  before{ with_mock_domain.add_member(owner) }
67
86
  it { expect { run }.to exit_with_code(0) }
68
87
  it { run_output.should =~ /alice\s+admin \(owner\)/ }
69
- it("should not show the name column") { run_output.should =~ /^Login\s+Role$/ }
88
+ it("should not show the name column") { run_output.should =~ /^Login\s+Role\s+Type$/ }
89
+ end
90
+
91
+ context 'on a domain with teams not showing all members' do
92
+ let(:arguments) { ['members', '-n', 'mock-domain-0'] }
93
+ let(:supports_members){ true }
94
+ before{ with_mock_domain.add_member(owner).add_member(team_admin).add_member(team_editor).add_member(team_admin_member).add_member(team_editor_member).add_member(team_viewer).add_member(team_viewer_and_explicit_member) }
95
+ it { expect { run }.to exit_with_code(0) }
96
+ it { run_output.should =~ /alice\s+alice\s+admin \(owner\)\s+user/ }
97
+ it { run_output.should =~ /team1\s+admin\s+team/ }
98
+ it { run_output.should_not =~ /memberadmin\s+memberadmin\s+admin \(via team1\)\s+user/ }
99
+ it { run_output.should =~ /team2\s+edit\s+team/ }
100
+ it { run_output.should_not =~ /membereditor\s+membereditor\s+edit \(via team2\)\s+user/ }
101
+ it("should show the name column") { run_output.should =~ /^Name\s+Login\s+Role\s+Type$/ }
102
+ it("should prompt to use the --all parameter") { run_output.should =~ /--all to display all members/ }
103
+ end
104
+
105
+ context 'on a domain with teams showing all members' do
106
+ let(:arguments) { ['members', '-n', 'mock-domain-0', '--all'] }
107
+ let(:supports_members){ true }
108
+ before{ with_mock_domain.add_member(owner).add_member(team_admin).add_member(team_editor).add_member(team_admin_member).add_member(team_editor_member).add_member(team_viewer).add_member(team_viewer_and_explicit_member) }
109
+ it { expect { run }.to exit_with_code(0) }
110
+ it { run_output.should =~ /alice\s+alice\s+admin \(owner\)\s+user/ }
111
+ it { run_output.should =~ /team1\s+admin\s+team/ }
112
+ it { run_output.should =~ /memberadmin\s+memberadmin\s+admin \(via team1\)\s+user/ }
113
+ it { run_output.should =~ /team2\s+edit\s+team/ }
114
+ it { run_output.should =~ /membereditor\s+membereditor\s+edit \(via team2\)\s+user/ }
115
+ it("should show the name column") { run_output.should =~ /^Name\s+Login\s+Role\s+Type$/ }
70
116
  end
71
117
 
72
118
  context 'on an application' do
@@ -77,18 +123,27 @@ describe RHC::Commands::Member do
77
123
  it { expect { run }.to exit_with_code(1) }
78
124
  it { run_output.should =~ /The server does not support adding or removing members/ }
79
125
 
126
+ context "with only implicit members via domain" do
127
+ let(:supports_members){ true }
128
+ before{ with_mock_app.add_member(app_member_via_domain) }
129
+ it { expect { run }.to exit_with_code(0) }
130
+ it { run_output.should =~ /app_member_via_domain\s+view \(via domain\)/ }
131
+ it("should not show the name column") { run_output.should =~ /^Login\s+Role\s+Type$/ }
132
+ it("should not show the --all message") { run_output.should_not =~ /--all/ }
133
+ end
134
+
80
135
  context "with only owner" do
81
136
  let(:supports_members){ true }
82
137
  before{ with_mock_app.add_member(owner) }
83
138
  it { expect { run }.to exit_with_code(0) }
84
139
  it { run_output.should =~ /alice\s+admin \(owner\)/ }
85
- it("should not show the name column") { run_output.should =~ /^Login\s+Role$/ }
140
+ it("should not show the name column") { run_output.should =~ /^Login\s+Role\s+Type$/ }
86
141
 
87
142
  context "with ids" do
88
143
  let(:arguments) { ['members', 'mock-domain-0/mock-app-0', '--ids'] }
89
144
  it { expect { run }.to exit_with_code(0) }
90
145
  it { run_output.should =~ /alice\s+admin \(owner\) 1/ }
91
- it("should not show the name column") { run_output.should =~ /^Login\s+Role\s+ID$/ }
146
+ it("should not show the name column") { run_output.should =~ /^Login\s+Role\s+ID\s+Type$/ }
92
147
  end
93
148
  end
94
149
 
@@ -102,7 +157,7 @@ describe RHC::Commands::Member do
102
157
  it { run_output.should =~ /doug\.com\s+view/ }
103
158
  it("should order the members by role") { run_output.should =~ /admin.*owner.*admin.*edit.*view/m }
104
159
  it("should include the login value") { run_output.should =~ /alice.*Bob.*carol.*doug@doug\.com/m }
105
- it("should show the name column") { run_output.should =~ /^Name\s+Login\s+Role$/ }
160
+ it("should show the name column") { run_output.should =~ /^Name\s+Login\s+Role\s+Type$/ }
106
161
  end
107
162
  end
108
163
  end
@@ -119,6 +174,13 @@ describe RHC::Commands::Member do
119
174
  it { run_output.should =~ /Adding 1 editor to domain .*The server does not support adding or removing members/ }
120
175
  end
121
176
 
177
+ context "when the client doesn't support teams" do
178
+ let(:mock_teams_links){ [] }
179
+ let(:arguments) { ['add-member', 'testteam', '-n', 'test', '--type', 'team'] }
180
+ it { expect { run }.to exit_with_code(161) }
181
+ it { run_output.should =~ /Adding 1 editor to domain .*Server does not support teams/ }
182
+ end
183
+
122
184
  context "with supported membership" do
123
185
  let(:supports_members?){ true }
124
186
 
@@ -126,13 +188,154 @@ describe RHC::Commands::Member do
126
188
  let(:arguments) { ['add-member', 'testuser', '-n', 'test'] }
127
189
  before do
128
190
  stub_api_request(:patch, "broker/rest/domains/test/members").
129
- with(:body => {:members => [{'login' => 'testuser', 'role' => 'edit'}]}).
191
+ with(:body => {:members => [{'login' => 'testuser', 'role' => 'edit', 'type' => 'user'}]}).
130
192
  to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'login', :index => 0, :severity => 'info', :text => 'Added 1 member'},]}.to_json, :status => 200})
131
193
  end
132
194
  it { expect { run }.to exit_with_code(0) }
133
195
  it { run_output.should =~ /Adding 1 editor to domain .*done/ }
134
196
  end
135
197
 
198
+ context 'with a valid team' do
199
+ let(:arguments) { ['add-member', 'testteam', '-n', 'test', '--type', 'team'] }
200
+ before do
201
+ challenge do
202
+ stub_api_request(:get, "broker/rest/teams?owner=@self").
203
+ to_return({:body => {:type => 'teams', :data => [{:id => 111, :global => false, :name => 'testteam'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing teams'},]}.to_json, :status => 200})
204
+ end
205
+ stub_api_request(:patch, "broker/rest/domains/test/members").
206
+ with(:body => {:members => [{:role => 'edit', :type => 'team', :id => 111, }]}).
207
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'id', :index => 0, :severity => 'info', :text => 'Added 1 member'},]}.to_json, :status => 200})
208
+ end
209
+ it { expect { run }.to exit_with_code(0) }
210
+ it { run_output.should =~ /Adding 1 editor to domain .*done/ }
211
+ end
212
+
213
+ context 'with an invalid type' do
214
+ let(:arguments) { ['add-member', 'invalidteam', '-n', 'test', '--type', 'foo'] }
215
+ it { expect { run }.to exit_with_code(1) }
216
+ it { run_output.should =~ /Type must be/ }
217
+ end
218
+
219
+ context 'with an invalid team' do
220
+ let(:arguments) { ['add-member', 'invalidteam', '-n', 'test', '--type', 'team'] }
221
+ before do
222
+ challenge do
223
+ stub_api_request(:get, "broker/rest/teams?owner=@self").
224
+ to_return({:body => {:type => 'teams', :data => [{:id => 111, :global => false, :name => 'testteam'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing teams'},]}.to_json, :status => 200})
225
+ end
226
+ end
227
+ it { expect { run }.to exit_with_code(162) }
228
+ it { run_output.should =~ /Adding 1 editor to domain .*You do not have a team named 'invalidteam'/ }
229
+ end
230
+
231
+ context 'with multiple partial team matches but one exact match' do
232
+ let(:arguments) { ['add-member', 'testteam', '-n', 'test', '--type', 'team'] }
233
+ before do
234
+ challenge do
235
+ stub_api_request(:get, "broker/rest/teams?owner=@self").
236
+ to_return({:body => {:type => 'teams', :data => [{:id => 111, :global => false, :name => 'testteam'}, {:id => 222, :global => false, :name => 'testteam1'}, {:id => 333, :global => false, :name => 'testteam11'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing teams'},]}.to_json, :status => 200})
237
+ end
238
+ stub_api_request(:patch, "broker/rest/domains/test/members").
239
+ with(:body => {:members => [{:role => 'edit', :type => 'team', :id => 111, }]}).
240
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'id', :index => 0, :severity => 'info', :text => 'Added 1 member'},]}.to_json, :status => 200})
241
+ end
242
+ it { expect { run }.to exit_with_code(0) }
243
+ it { run_output.should =~ /Adding 1 editor to domain .*done/ }
244
+ end
245
+
246
+ context 'without an exact team match' do
247
+ let(:arguments) { ['add-member', 'team', '-n', 'test', '--type', 'team'] }
248
+ before do
249
+ challenge do
250
+ stub_api_request(:get, "broker/rest/teams?owner=@self").
251
+ to_return({:body => {:type => 'teams', :data => [{:id => 111, :global => false, :name => 'team1'}, {:id => 111, :global => false, :name => 'team2'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing teams'},]}.to_json, :status => 200})
252
+ end
253
+ end
254
+ it { expect { run }.to exit_with_code(162) }
255
+ it { run_output.should =~ /Adding 1 editor to domain .*You do not have a team named 'team'. Did you mean one of the following\?\nteam1, team2/ }
256
+ end
257
+
258
+ context 'with a single exact case insensitive match' do
259
+ let(:arguments) { ['add-member', 'testteam', '-n', 'test', '--type', 'team'] }
260
+ before do
261
+ challenge do
262
+ stub_api_request(:get, "broker/rest/teams?owner=@self").
263
+ to_return({:body => {:type => 'teams', :data => [{:id => 111, :global => false, :name => 'TESTTEAM'}, {:id => 222, :global => false, :name => 'TESTTEAM1'}, {:id => 333, :global => false, :name => 'TESTTEAM2'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing teams'},]}.to_json, :status => 200})
264
+ end
265
+ stub_api_request(:patch, "broker/rest/domains/test/members").
266
+ with(:body => {:members => [{:role => 'edit', :type => 'team', :id => 111, }]}).
267
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'id', :index => 0, :severity => 'info', :text => 'Added 1 member'},]}.to_json, :status => 200})
268
+ end
269
+ it { expect { run }.to exit_with_code(0) }
270
+ it { run_output.should =~ /Adding 1 editor to domain .*done/ }
271
+ end
272
+
273
+ context 'with an exact case sensitive match and some exact case insensitive matches' do
274
+ let(:arguments) { ['add-member', 'testteam', '-n', 'test', '--type', 'team'] }
275
+ before do
276
+ challenge do
277
+ stub_api_request(:get, "broker/rest/teams?owner=@self").
278
+ to_return({:body => {:type => 'teams', :data => [{:id => 111, :global => false, :name => 'testteam'}, {:id => 222, :global => false, :name => 'TESTTEAM'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing teams'},]}.to_json, :status => 200})
279
+ end
280
+ stub_api_request(:patch, "broker/rest/domains/test/members").
281
+ with(:body => {:members => [{:role => 'edit', :type => 'team', :id => 111, }]}).
282
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'id', :index => 0, :severity => 'info', :text => 'Added 1 member'},]}.to_json, :status => 200})
283
+ end
284
+ it { expect { run }.to exit_with_code(0) }
285
+ it { run_output.should =~ /Adding 1 editor to domain .*done/ }
286
+ end
287
+
288
+ context 'with a team name containing special characters' do
289
+ let(:arguments) { ['add-member', '*1()', '-n', 'test', '--type', 'team'] }
290
+ before do
291
+ challenge do
292
+ stub_api_request(:get, "broker/rest/teams?owner=@self").
293
+ to_return({:body => {:type => 'teams', :data => [{:id => 111, :global => false, :name => '*1()'}, {:id => 222, :global => false, :name => 'another team'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing teams'},]}.to_json, :status => 200})
294
+ end
295
+ stub_api_request(:patch, "broker/rest/domains/test/members").
296
+ with(:body => {:members => [{:role => 'edit', :type => 'team', :id => 111, }]}).
297
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'id', :index => 0, :severity => 'info', :text => 'Added 1 member'},]}.to_json, :status => 200})
298
+ end
299
+ it { expect { run }.to exit_with_code(0) }
300
+ it { run_output.should =~ /Adding 1 editor to domain .*done/ }
301
+ end
302
+
303
+ context 'with multiple exact team matches' do
304
+ let(:arguments) { ['add-member', 'someteam', '-n', 'test', '--type', 'team'] }
305
+ before do
306
+ challenge do
307
+ stub_api_request(:get, "broker/rest/teams?owner=@self").
308
+ to_return({:body => {:type => 'teams', :data => [{:id => 111, :global => false, :name => 'someteam'}, {:id => 222, :global => false, :name => 'someteam'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing teams'},]}.to_json, :status => 200})
309
+ end
310
+ end
311
+ it { expect { run }.to exit_with_code(162) }
312
+ it { run_output.should =~ /Adding 1 editor to domain .*There is more than one team named 'someteam'\. Please use the --ids flag and specify the exact id of the team you want to manage\./ }
313
+ end
314
+
315
+ context 'with multiple case-insensitive team matches' do
316
+ let(:arguments) { ['add-member', 'someteam', '-n', 'test', '--type', 'team'] }
317
+ before do
318
+ challenge do
319
+ stub_api_request(:get, "broker/rest/teams?owner=@self").
320
+ to_return({:body => {:type => 'teams', :data => [{:id => 111, :global => false, :name => 'SOMETEAM'}, {:id => 222, :global => false, :name => 'SomeTeam'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing teams'},]}.to_json, :status => 200})
321
+ end
322
+ end
323
+ it { expect { run }.to exit_with_code(162) }
324
+ it { run_output.should =~ /Adding 1 editor to domain .*You do not have a team named 'someteam'. Did you mean one of the following\?\nSOMETEAM, SomeTeam/ }
325
+ end
326
+
327
+ context 'without a global team' do
328
+ let(:arguments) { ['add-member', 'testteam', '-n', 'test', '--type', 'team', '--global'] }
329
+ before do
330
+ challenge do
331
+ stub_api_request(:get, "broker/rest/teams?global&search=testteam").
332
+ to_return({:body => {:type => 'teams', :data => [], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing teams'},]}.to_json, :status => 200})
333
+ end
334
+ end
335
+ it { expect { run }.to exit_with_code(162) }
336
+ it { run_output.should =~ /Adding 1 editor to domain .*No global team found with the name 'testteam'\./ }
337
+ end
338
+
136
339
  context 'with an invalid role' do
137
340
  let(:arguments) { ['add-member', 'testuser', '-n', 'test', '--role', 'missing'] }
138
341
  it { expect { run }.to exit_with_code(1) }
@@ -140,10 +343,10 @@ describe RHC::Commands::Member do
140
343
  end
141
344
 
142
345
  context 'with a missing user' do
143
- let(:arguments) { ['add-member', 'testuser', '-n', 'test'] }
346
+ let(:arguments) { ['add-member', 'testuser', '-n', 'test', '--type', 'user'] }
144
347
  before do
145
348
  stub_api_request(:patch, "broker/rest/domains/test/members").
146
- with(:body => {:members => [{'login' => 'testuser', 'role' => 'edit'}]}).
349
+ with(:body => {:members => [{'login' => 'testuser', 'role' => 'edit', 'type' => 'user'}]}).
147
350
  to_return({:body => {:messages => [{:exit_code => 132, :field => 'login', :index => 0, :severity => 'error', :text => 'There is no user with a login testuser'},]}.to_json, :status => 422})
148
351
  end
149
352
  it { expect { run }.to exit_with_code(1) }
@@ -154,7 +357,7 @@ describe RHC::Commands::Member do
154
357
  let(:arguments) { ['add-member', '123', '-n', 'test', '--ids', '--role', 'admin'] }
155
358
  before do
156
359
  stub_api_request(:patch, "broker/rest/domains/test/members").
157
- with(:body => {:members => [{'id' => '123', 'role' => 'admin'}]}).
360
+ with(:body => {:members => [{'id' => '123', 'role' => 'admin', 'type' => 'user'}]}).
158
361
  to_return({:body => {:messages => [{:exit_code => 132, :field => 'id', :index => 0, :severity => 'error', :text => 'There is no user with the id 123'},]}.to_json, :status => 422})
159
362
  end
160
363
  it { expect { run }.to exit_with_code(1) }
@@ -163,6 +366,166 @@ describe RHC::Commands::Member do
163
366
  end
164
367
  end
165
368
 
369
+ describe 'update-member' do
370
+ context "when the resource doesn't support membership changes" do
371
+ before{ stub_api }
372
+
373
+ context "when updating a domain" do
374
+ let(:arguments) { ['update-member', 'testuser', '-n', 'test'] }
375
+ before{ challenge{ stub_one_domain('test', nil, mock_user_auth) } }
376
+ it { expect { run }.to exit_with_code(1) }
377
+ it { run_output.should =~ /Updating 1 editor to domain .*The server does not support adding or removing members/ }
378
+ end
379
+ end
380
+
381
+ context "with supported membership" do
382
+ let(:supports_members?){ true }
383
+ before do
384
+ stub_api
385
+ challenge{ stub_one_domain('test', nil, mock_user_auth) }
386
+ end
387
+
388
+ context 'with a valid user' do
389
+ let(:arguments) { ['update-member', 'testuser', '-n', 'test', '-r', 'view'] }
390
+ before do
391
+ stub_api_request(:patch, "broker/rest/domains/test/members").
392
+ with(:body => {:members => [{'login' => 'testuser', 'role' => 'view', 'type' => 'user'}]}).
393
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'login', :index => 0, :severity => 'info', :text => 'Updated 1 member'},]}.to_json, :status => 200})
394
+ end
395
+ it { expect { run }.to exit_with_code(0) }
396
+ it { run_output.should =~ /Updating 1 viewer to domain .*done/ }
397
+ end
398
+
399
+ context 'with a valid team' do
400
+ let(:arguments) { ['update-member', 'testteam', '-n', 'test', '-r', 'view', '--type', 'team'] }
401
+ before do
402
+ stub_api_request(:get, "broker/rest/domains/test/members").
403
+ to_return({:body => {:type => 'members', :data => [{:id => 1, :name => 'testteam', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'team'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing members'},]}.to_json, :status => 200})
404
+ stub_api_request(:patch, "broker/rest/domains/test/members").
405
+ with(:body => {:members => [{'id' => 1, 'role' => 'view', 'type' => 'team'}]}).
406
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'login', :index => 0, :severity => 'info', :text => 'Updated 1 member'},]}.to_json, :status => 200})
407
+ end
408
+ it { expect { run }.to exit_with_code(0) }
409
+ it { run_output.should =~ /Updating 1 viewer to domain .*done/ }
410
+ end
411
+
412
+ context 'with multiple team exact matches' do
413
+ let(:arguments) { ['update-member', 'testteam', '-n', 'test', '-r', 'view', '--type', 'team'] }
414
+ before do
415
+ stub_api_request(:get, "broker/rest/domains/test/members").
416
+ to_return({:body => {:type => 'members', :data => [{:id => 1, :name => 'testteam', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'team'}, {:id => 12, :name => 'testteam', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'team'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing members'},]}.to_json, :status => 200})
417
+ stub_api_request(:patch, "broker/rest/domains/test/members").
418
+ with(:body => {:members => [{'id' => 1, 'role' => 'view', 'type' => 'team'}]}).
419
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'login', :index => 0, :severity => 'info', :text => 'Updated 1 member'},]}.to_json, :status => 200})
420
+ end
421
+ it { expect { run }.to exit_with_code(163) }
422
+ it { run_output.should =~ /Updating 1 viewer to domain .*There is more than one member team named 'testteam'/ }
423
+ end
424
+
425
+ context 'with multiple team case-insensitive matches' do
426
+ let(:arguments) { ['update-member', 'testteam', '-n', 'test', '-r', 'view', '--type', 'team'] }
427
+ before do
428
+ stub_api_request(:get, "broker/rest/domains/test/members").
429
+ to_return({:body => {:type => 'members', :data => [{:id => 1, :name => 'TESTTEAM', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'team'}, {:id => 12, :name => 'TestTeam', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'team'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing members'},]}.to_json, :status => 200})
430
+ end
431
+ it { expect { run }.to exit_with_code(163) }
432
+ it { run_output.should =~ /Updating 1 viewer to domain .*No member team found with the name 'testteam'. Did you mean one of the following\?\nTESTTEAM, TestTeam/ }
433
+ end
434
+
435
+ context 'with a single exact case insensitive match' do
436
+ let(:arguments) { ['update-member', 'testteam', '-n', 'test', '-r', 'view', '--type', 'team'] }
437
+ before do
438
+ stub_api_request(:get, "broker/rest/domains/test/members").
439
+ to_return({:body => {:type => 'members', :data => [{:id => 1, :name => 'TESTTEAM', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'team'}, {:id => 2, :name => 'TESTTEAM2', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'team'}, {:id => 3, :name => 'TESTTEAM3', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'team'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing members'},]}.to_json, :status => 200})
440
+ stub_api_request(:patch, "broker/rest/domains/test/members").
441
+ with(:body => {:members => [{'id' => 1, 'role' => 'view', 'type' => 'team'}]}).
442
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'login', :index => 0, :severity => 'info', :text => 'Updated 1 member'},]}.to_json, :status => 200})
443
+ end
444
+ it { expect { run }.to exit_with_code(0) }
445
+ it { run_output.should =~ /Updating 1 viewer to domain .*done/ }
446
+ end
447
+
448
+ context 'with an exact case sensitive match and some exact case insensitive matches' do
449
+ let(:arguments) { ['update-member', 'testteam', '-n', 'test', '-r', 'view', '--type', 'team'] }
450
+ before do
451
+ stub_api_request(:get, "broker/rest/domains/test/members").
452
+ to_return({:body => {:type => 'members', :data => [{:id => 1, :name => 'testteam', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'team'}, {:id => 2, :name => 'TESTTEAM', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'team'}, {:id => 3, :name => 'TeStTeAm', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'team'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing members'},]}.to_json, :status => 200})
453
+ stub_api_request(:patch, "broker/rest/domains/test/members").
454
+ with(:body => {:members => [{'id' => 1, 'role' => 'view', 'type' => 'team'}]}).
455
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'login', :index => 0, :severity => 'info', :text => 'Updated 1 member'},]}.to_json, :status => 200})
456
+ end
457
+ it { expect { run }.to exit_with_code(0) }
458
+ it { run_output.should =~ /Updating 1 viewer to domain .*done/ }
459
+ end
460
+
461
+ context 'with a team name containing special characters' do
462
+ let(:arguments) { ['update-member', '*1()', '-n', 'test', '-r', 'view', '--type', 'team'] }
463
+ before do
464
+ stub_api_request(:get, "broker/rest/domains/test/members").
465
+ to_return({:body => {:type => 'members', :data => [{:id => 1, :name => '*1()', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'team'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing members'},]}.to_json, :status => 200})
466
+ stub_api_request(:patch, "broker/rest/domains/test/members").
467
+ with(:body => {:members => [{'id' => 1, 'role' => 'view', 'type' => 'team'}]}).
468
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'login', :index => 0, :severity => 'info', :text => 'Updated 1 member'},]}.to_json, :status => 200})
469
+ end
470
+ it { expect { run }.to exit_with_code(0) }
471
+ it { run_output.should =~ /Updating 1 viewer to domain .*done/ }
472
+ end
473
+
474
+ context 'with a missing user' do
475
+ let(:arguments) { ['update-member', 'testuser', '-n', 'test', '-r', 'view'] }
476
+ before do
477
+ stub_api_request(:patch, "broker/rest/domains/test/members").
478
+ with(:body => {:members => [{'login' => 'testuser', 'role' => 'view', 'type' => 'user'}]}).
479
+ to_return({:body => {:messages => [{:exit_code => 132, :field => 'login', :index => 0, :severity => 'error', :text => 'There is no user with a login testuser'},]}.to_json, :status => 422})
480
+ end
481
+ it { expect { run }.to exit_with_code(1) }
482
+ it { run_output.should =~ /Updating 1 viewer to domain.*There is no user with a login testuser/ }
483
+ end
484
+
485
+ context 'with a missing team' do
486
+ let(:arguments) { ['update-member', 'testteam', '-n', 'test', '-r', 'view', '--type', 'team'] }
487
+ before do
488
+ stub_api_request(:get, "broker/rest/domains/test/members").
489
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing teams'},]}.to_json, :status => 200})
490
+ end
491
+ it { expect { run }.to exit_with_code(163) }
492
+ it { run_output.should =~ /Updating 1 viewer to domain.*No member team found with the name 'testteam'/ }
493
+ end
494
+
495
+ context 'with a missing team with an identical user name' do
496
+ let(:arguments) { ['update-member', 'testteam', '-n', 'test', '-r', 'view', '--type', 'team'] }
497
+ before do
498
+ stub_api_request(:get, "broker/rest/domains/test/members").
499
+ to_return({:body => {:type => 'members', :data => [{:id => 1, :name => 'testteam', :login => 'testteam', :owner => false, :role => 'edit', :explicit_role => 'edit', :type => 'user'}], :messages => [{:exit_code => 0, :field => nil, :index => nil, :severity => 'info', :text => 'Listing members'},]}.to_json, :status => 200})
500
+ end
501
+ it { expect { run }.to exit_with_code(163) }
502
+ it { run_output.should =~ /Updating 1 viewer to domain.*No member team found with the name 'testteam'/ }
503
+ end
504
+
505
+ context 'with a missing user id and role' do
506
+ let(:arguments) { ['update-member', '123', '-n', 'test', '--ids', '-r', 'view'] }
507
+ before do
508
+ stub_api_request(:patch, "broker/rest/domains/test/members").
509
+ with(:body => {:members => [{'id' => '123', 'role' => 'view', 'type' => 'user'}]}).
510
+ to_return({:body => {:messages => [{:exit_code => 132, :field => 'id', :index => 0, :severity => 'error', :text => 'There is no user with the id 123'},]}.to_json, :status => 422})
511
+ end
512
+ it { expect { run }.to exit_with_code(1) }
513
+ it { run_output.should =~ /Updating 1 viewer to domain.*There is no user with the id 123/ }
514
+ end
515
+
516
+ context 'when the user is not a member' do
517
+ let(:arguments) { ['update-member', 'testuser', '-n', 'test', '-r', 'view'] }
518
+ before do
519
+ stub_api_request(:patch, "broker/rest/domains/test/members").
520
+ with(:body => {:members => [{'login' => 'testuser', 'role' => 'view', 'type' => 'user'}]}).
521
+ to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'login', :index => 0, :severity => 'warning', :text => 'testuser is not a member of this domain.'},]}.to_json, :status => 200})
522
+ end
523
+ it { expect { run }.to exit_with_code(0) }
524
+ it { run_output.should =~ /Updating 1 viewer to domain.*testuser is not a member of this domain.*done/m }
525
+ end
526
+ end
527
+ end
528
+
166
529
  describe 'remove-member' do
167
530
  context "when the resource doesn't support membership changes" do
168
531
  before{ stub_api }
@@ -193,7 +556,7 @@ describe RHC::Commands::Member do
193
556
  let(:arguments) { ['remove-member', 'testuser', '-n', 'test'] }
194
557
  before do
195
558
  stub_api_request(:patch, "broker/rest/domains/test/members").
196
- with(:body => {:members => [{'login' => 'testuser', 'role' => 'none'}]}).
559
+ with(:body => {:members => [{'login' => 'testuser', 'role' => 'none', 'type' => 'user'}]}).
197
560
  to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'login', :index => 0, :severity => 'info', :text => 'Removed 1 member'},]}.to_json, :status => 200})
198
561
  end
199
562
  it { expect { run }.to exit_with_code(0) }
@@ -214,7 +577,7 @@ describe RHC::Commands::Member do
214
577
  let(:arguments) { ['remove-member', 'testuser', '-n', 'test'] }
215
578
  before do
216
579
  stub_api_request(:patch, "broker/rest/domains/test/members").
217
- with(:body => {:members => [{'login' => 'testuser', 'role' => 'none'}]}).
580
+ with(:body => {:members => [{'login' => 'testuser', 'role' => 'none', 'type' => 'user'}]}).
218
581
  to_return({:body => {:messages => [{:exit_code => 132, :field => 'login', :index => 0, :severity => 'error', :text => 'There is no user with a login testuser'},]}.to_json, :status => 422})
219
582
  end
220
583
  it { expect { run }.to exit_with_code(1) }
@@ -225,18 +588,18 @@ describe RHC::Commands::Member do
225
588
  let(:arguments) { ['remove-member', '123', '-n', 'test', '--ids'] }
226
589
  before do
227
590
  stub_api_request(:patch, "broker/rest/domains/test/members").
228
- with(:body => {:members => [{'id' => '123', 'role' => 'none'}]}).
591
+ with(:body => {:members => [{'id' => '123', 'role' => 'none', 'type' => 'user'}]}).
229
592
  to_return({:body => {:messages => [{:exit_code => 132, :field => 'id', :index => 0, :severity => 'error', :text => 'There is no user with the id 123'},]}.to_json, :status => 422})
230
593
  end
231
594
  it { expect { run }.to exit_with_code(1) }
232
595
  it { run_output.should =~ /Removing 1 member from domain.*There is no user with the id 123/ }
233
596
  end
234
597
 
235
- context 'when the user isn''t a member' do
598
+ context 'when the user is not a member' do
236
599
  let(:arguments) { ['remove-member', 'testuser', '-n', 'test'] }
237
600
  before do
238
601
  stub_api_request(:patch, "broker/rest/domains/test/members").
239
- with(:body => {:members => [{'login' => 'testuser', 'role' => 'none'}]}).
602
+ with(:body => {:members => [{'login' => 'testuser', 'role' => 'none', 'type' => 'user'}]}).
240
603
  to_return({:body => {:type => 'members', :data => [], :messages => [{:exit_code => 0, :field => 'login', :index => 0, :severity => 'warning', :text => 'testuser is not a member of this domain.'},]}.to_json, :status => 200})
241
604
  end
242
605
  it { expect { run }.to exit_with_code(0) }