rhc 1.22.5 → 1.23.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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) }