hammer_cli_foreman 0.10.2 → 0.11.0

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/config/foreman.yml +4 -0
  3. data/doc/release_notes.md +21 -5
  4. data/lib/hammer_cli_foreman/api/connection.rb +14 -5
  5. data/lib/hammer_cli_foreman/api/interactive_basic_auth.rb +17 -5
  6. data/lib/hammer_cli_foreman/api/session_authenticator_wrapper.rb +27 -8
  7. data/lib/hammer_cli_foreman/auth.rb +14 -10
  8. data/lib/hammer_cli_foreman/auth_source_ldap.rb +38 -34
  9. data/lib/hammer_cli_foreman/compute_resource.rb +24 -0
  10. data/lib/hammer_cli_foreman/filter.rb +6 -2
  11. data/lib/hammer_cli_foreman/host.rb +2 -7
  12. data/lib/hammer_cli_foreman/hostgroup.rb +1 -0
  13. data/lib/hammer_cli_foreman/id_resolver.rb +27 -7
  14. data/lib/hammer_cli_foreman/location.rb +1 -0
  15. data/lib/hammer_cli_foreman/organization.rb +1 -0
  16. data/lib/hammer_cli_foreman/references.rb +10 -2
  17. data/lib/hammer_cli_foreman/smart_class_parameter.rb +10 -1
  18. data/lib/hammer_cli_foreman/smart_variable.rb +24 -16
  19. data/lib/hammer_cli_foreman/subnet.rb +33 -3
  20. data/lib/hammer_cli_foreman/template.rb +1 -1
  21. data/lib/hammer_cli_foreman/testing/api_expectations.rb +3 -1
  22. data/lib/hammer_cli_foreman/user.rb +37 -3
  23. data/lib/hammer_cli_foreman/version.rb +1 -1
  24. data/locale/ca/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  25. data/locale/de/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  26. data/locale/en/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  27. data/locale/en_GB/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  28. data/locale/es/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  29. data/locale/fr/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  30. data/locale/it/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  31. data/locale/ja/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  32. data/locale/ko/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  33. data/locale/pt_BR/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  34. data/locale/ru/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  35. data/locale/zh_CN/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  36. data/locale/zh_TW/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  37. data/test/functional/filter_test.rb +146 -0
  38. data/test/functional/host_test.rb +12 -0
  39. data/test/functional/smart_variable_test.rb +4 -4
  40. data/test/functional/template_test.rb +20 -0
  41. data/test/functional/user_test.rb +13 -13
  42. data/test/unit/api/interactive_basic_auth_test.rb +18 -0
  43. data/test/unit/api/session_authenticator_wrapper_test.rb +72 -2
  44. data/test/unit/apipie_resource_mock.rb +3 -0
  45. data/test/unit/auth_source_ldap_test.rb +2 -3
  46. data/test/unit/commands_test.rb +1 -1
  47. data/test/unit/compute_resource_test.rb +24 -0
  48. data/test/unit/host_test.rb +1 -1
  49. data/test/unit/hostgroup_test.rb +1 -1
  50. data/test/unit/id_resolver_test.rb +59 -21
  51. data/test/unit/subnet_test.rb +1 -0
  52. data/test/unit/user_test.rb +7 -1
  53. metadata +35 -33
@@ -6,6 +6,18 @@ describe "host create" do
6
6
  let(:minimal_params_without_hosgroup) { ['--location-id=1', '--organization-id=1', '--name=test'] }
7
7
  let(:minimal_params) { ['--hostgroup-id=1'] + minimal_params_without_hosgroup }
8
8
 
9
+ it "accepts hostgroup title" do
10
+ api_expects_search(:hostgroups, { :title => 'test/hg1' }).returns(index_response([{ 'id' => '83' }]))
11
+ api_expects(:hosts, :create, 'Create host with interfaces params') do |par|
12
+ par['host']['hostgroup_id'] == '83'
13
+ end.returns({})
14
+
15
+ expected_result = success_result("Host created\n")
16
+
17
+ result = run_cmd(cmd + minimal_params_without_hosgroup + ['--hostgroup-title=test/hg1'])
18
+ assert_cmd(expected_result, result)
19
+ end
20
+
9
21
  it "passes interface attributes to server" do
10
22
  params = ['--interface', 'identifier=eth0,ip=10.0.0.4,primary=true,provision=true']
11
23
 
@@ -3,13 +3,13 @@ require File.join(File.dirname(__FILE__), 'test_helper')
3
3
  describe 'smart-variable update' do
4
4
  let(:cmd) { %w(smart-variable update) }
5
5
 
6
- it 'allows to save new name' do
7
- params = ['--id=1', '--new-variable=name2']
6
+ it 'allows to save new name and override value order' do
7
+ params = ['--id=1', '--new-variable=name2', '--override-value-order=\'fqdn\',\'hostgroup\',\'domain\',\'os\'']
8
8
 
9
9
  expected_result = success_result("Smart variable [name2] updated\n")
10
10
 
11
11
  api_expects(:smart_variables, :update, 'Update the variable') do |par|
12
- par['smart_variable']['variable'] == 'name2'
12
+ (par['smart_variable']['variable'] == 'name2') && (par['smart_variable']['override_value_order'] == "fqdn\nhostgroup\ndomain\nos")
13
13
  end.returns(
14
14
  'description' => '',
15
15
  'parameter_type' => 'string',
@@ -18,7 +18,7 @@ describe 'smart-variable update' do
18
18
  'hidden_value' => '*****',
19
19
  'validator_type' => '',
20
20
  'validator_rule' => nil,
21
- 'override_value_order' => 'fqdn\nhostgroup\nos\ndomain',
21
+ 'override_value_order' => 'fqdn\nhostgroup\ndomain\nos',
22
22
  'merge_overrides' => false,
23
23
  'merge_default' => false,
24
24
  'avoid_duplicates' => false,
@@ -77,4 +77,24 @@ describe 'template' do
77
77
  assert_cmd(success_result("Provisioning template cloned\n"), result)
78
78
  end
79
79
  end
80
+
81
+ describe 'update' do
82
+ before do
83
+ @cmd = %w(template update)
84
+ end
85
+
86
+ it "doesn't send snippet flag when --type is undefined" do
87
+ params = ['--id=1', '--locked=true']
88
+
89
+ api_expects(:template_kinds, :index, 'Get list of template kinds').returns(index_response([]))
90
+ api_expects(:config_templates, :update, 'Update the template') do |par|
91
+ par['config_template']['locked'] == true &&
92
+ par['config_template']['snippet'].nil?
93
+ end.returns(:name => 'A', :value => '1')
94
+
95
+ result = run_cmd(@cmd + params)
96
+
97
+ assert_cmd(success_result("Provisioning template updated\n"), result)
98
+ end
99
+ end
80
100
  end
@@ -2,17 +2,17 @@ require File.join(File.dirname(__FILE__), 'test_helper')
2
2
 
3
3
  describe "user" do
4
4
  let(:minimal_params) { ['--login', 'jane', '--mail', 'jane@test.org', '--password', 'secret', '--auth-source-id', '1'] }
5
+ let(:update_params) { ['--login', 'jane'] }
5
6
  let(:user) { { 'id' => '32', 'login' => 'jane' } }
6
7
 
7
8
  def expect_with_minimal_params(action, message, &block)
8
- api_expects(:users, action, message) do |par|
9
- user = par['user']
10
- user['login'] == 'jane' &&
11
- user['mail'] == 'jane@test.org' &&
12
- user['password'] == 'secret' &&
13
- user['auth_source_id'] == '1' &&
14
- yield(par)
15
- end
9
+ api_expects(:users, action, message).with_params({
10
+ 'user' => {'login' => 'jane', 'mail' => 'jane@test.org', 'password' => 'secret', 'auth_source_id' => '1'}})
11
+ end
12
+
13
+ def expect_with_update_params(action, message, &block)
14
+ api_expects(:users, action, message).with_params({
15
+ 'user' => {'login' => 'jane'}})
16
16
  end
17
17
 
18
18
  describe "create" do
@@ -55,14 +55,14 @@ describe "user" do
55
55
 
56
56
  api_expects_search(:users, { :login => 'jane' }).returns(index_response([user]))
57
57
  api_expects_search(:organizations, { :name => 'Org1' }).returns(index_response([{ 'id' => '3' }]))
58
- expect_with_minimal_params(:update, 'Update user with default org') do |par|
58
+ expect_with_update_params(:update, 'Update user with default org') do |par|
59
59
  par['id'] == '32' &&
60
60
  par['user']['default_organization_id'] == '3'
61
61
  end.returns(user)
62
-
63
62
  expected_result = success_result("User [jane] updated\n")
64
63
 
65
- result = run_cmd(cmd + minimal_params + params)
64
+ result = run_cmd(cmd + update_params + params)
65
+
66
66
  assert_cmd(expected_result, result)
67
67
  end
68
68
 
@@ -71,14 +71,14 @@ describe "user" do
71
71
 
72
72
  api_expects_search(:users, { :login => 'jane' }).returns(index_response([user]))
73
73
  api_expects_search(:locations, { :name => 'Loc1' }).returns(index_response([{ 'id' => '4' }]))
74
- expect_with_minimal_params(:update, 'Update user with default loc') do |par|
74
+ expect_with_update_params(:update, 'Update user with default loc') do |par|
75
75
  par['id'] == '32' &&
76
76
  par['user']['default_location_id'] == '4'
77
77
  end.returns(user)
78
78
 
79
79
  expected_result = success_result("User [jane] updated\n")
80
80
 
81
- result = run_cmd(cmd + minimal_params + params)
81
+ result = run_cmd(cmd + update_params + params)
82
82
  assert_cmd(expected_result, result)
83
83
  end
84
84
  end
@@ -83,4 +83,22 @@ describe HammerCLIForeman::Api::InteractiveBasicAuth do
83
83
  assert_nil new_ex
84
84
  end
85
85
  end
86
+
87
+ describe '#set_credentials' do
88
+ let(:auth) { HammerCLIForeman::Api::InteractiveBasicAuth.new(nil, nil) }
89
+
90
+ it 'sets username and password' do
91
+ auth.set_credentials('admin', 'password')
92
+ assert_equal 'admin', auth.user
93
+ end
94
+ end
95
+
96
+ describe '#clear' do
97
+ let(:auth) { HammerCLIForeman::Api::InteractiveBasicAuth.new('user', 'password') }
98
+
99
+ it 'clears username and password' do
100
+ auth.clear
101
+ assert_nil auth.user
102
+ end
103
+ end
86
104
  end
@@ -96,13 +96,14 @@ describe HammerCLIForeman::Api::SessionAuthenticatorWrapper do
96
96
  end
97
97
  end
98
98
 
99
- it "drops the session when usernames don't match" do
99
+ it "keeps the session and sets cuser_changed flag when usernames don't match and " do
100
100
  prepare_session_storage :session_id => 'SOME_SESSION_ID' do |auth, dir|
101
101
  wrapped_auth.expects(:authenticate).with(request, args)
102
102
  wrapped_auth.expects(:user).returns('other_user')
103
103
  auth.authenticate(request, args)
104
104
 
105
- refute File.exist?(session_file(dir))
105
+ assert File.exist?(session_file(dir))
106
+ assert auth.user_changed?
106
107
  end
107
108
  end
108
109
 
@@ -194,6 +195,28 @@ describe HammerCLIForeman::Api::SessionAuthenticatorWrapper do
194
195
  assert File.exist?(session_file(dir))
195
196
  end
196
197
  end
198
+
199
+ context 'when user has changed' do
200
+ it 'sets a special error message' do
201
+ prepare_session_storage :session_id => 'SOME_SESSION_ID' do |auth, dir|
202
+ auth.force_user_change
203
+ ex = RestClient::Unauthorized.new
204
+ new_ex = auth.error(ex)
205
+
206
+ assert_equal "Invalid username or password, continuing with session for 'admin'", new_ex.message
207
+ end
208
+ end
209
+
210
+ it 'keeps the previous session' do
211
+ prepare_session_storage :session_id => 'SOME_SESSION_ID' do |auth, dir|
212
+ auth.force_user_change
213
+ ex = RestClient::Unauthorized.new
214
+ auth.error(ex)
215
+
216
+ assert File.exist?(session_file(dir))
217
+ end
218
+ end
219
+ end
197
220
  end
198
221
 
199
222
  context 'when there is no existing session' do
@@ -284,4 +307,51 @@ describe HammerCLIForeman::Api::SessionAuthenticatorWrapper do
284
307
  end
285
308
  end
286
309
  end
310
+
311
+ describe '#user_changed?' do
312
+ it 'is false by default' do
313
+ prepare_session_storage do |auth, dir|
314
+ refute auth.user_changed?
315
+ end
316
+ end
317
+ end
318
+
319
+ describe '#force_user_change' do
320
+ it 'sets force user change flag' do
321
+ prepare_session_storage do |auth, dir|
322
+ auth.force_user_change
323
+ assert auth.user_changed?
324
+ end
325
+ end
326
+ end
327
+
328
+ describe '#set_credentials' do
329
+ it 'passes credentials to a wrapped authenticator' do
330
+ prepare_session_storage do |auth, dir|
331
+ wrapped_auth.expects(:set_credentials).with('admin', 'password')
332
+ auth.set_credentials('admin', 'password')
333
+ end
334
+ end
335
+
336
+ it "doesn't pass the credentials when a wrapped autneticator doesn't support it" do
337
+ prepare_session_storage do |auth, dir|
338
+ auth.set_credentials('admin', 'password')
339
+ end
340
+ end
341
+ end
342
+
343
+ describe '#clear' do
344
+ it 'passes clear to a wrapped authenticator' do
345
+ prepare_session_storage do |auth, dir|
346
+ wrapped_auth.expects(:clear)
347
+ auth.clear
348
+ end
349
+ end
350
+
351
+ it "doesn't pass clear when a wrapped autneticator doesn't support it" do
352
+ prepare_session_storage do |auth, dir|
353
+ auth.clear
354
+ end
355
+ end
356
+ end
287
357
  end
@@ -41,6 +41,9 @@ module ResourceMocks
41
41
  ResourceMocks.mock_action_call(:compute_resources, :available_images, [])
42
42
  end
43
43
 
44
+ def self.compute_resources_available_networks
45
+ ResourceMocks.mock_action_call(:compute_resources, :available_networks, [])
46
+ end
44
47
 
45
48
  def self.organizations_index
46
49
  ResourceMocks.mock_action_call(:organizations, :index, {
@@ -28,7 +28,7 @@ describe HammerCLIForeman::AuthSourceLdap do
28
28
  it_should_print_column "Id"
29
29
  it_should_print_column "LDAPS\\?"
30
30
  it_should_print_column "Port"
31
- it_should_print_column "Server Type"
31
+ it_should_print_column "Server"
32
32
  end
33
33
 
34
34
  end
@@ -47,8 +47,7 @@ describe HammerCLIForeman::AuthSourceLdap do
47
47
  context "output" do
48
48
  with_params ["--id=1"] do
49
49
  it_should_print_n_records 1
50
- it_should_print_column "Name"
51
- it_should_print_column "Id"
50
+ it_should_print_columns ["Server", "Account", "Attribute mappings", "Locations", "Organizations"]
52
51
  end
53
52
  end
54
53
 
@@ -160,7 +160,7 @@ describe HammerCLIForeman::Command do
160
160
  out, err = capture_io do
161
161
  com.run(['--location', 'loc']).wont_equal HammerCLI::EX_OK
162
162
  end
163
- err.must_equal "Error: Could not find location, please set one of options --location, --location-id.\n"
163
+ err.must_equal "Error: Could not find location, please set one of options --location, --location-title, --location-id.\n"
164
164
 
165
165
  end
166
166
 
@@ -94,5 +94,29 @@ describe HammerCLIForeman::ComputeResource do
94
94
 
95
95
  end
96
96
 
97
+ context "AvailableNetworksCommand" do
98
+ before do
99
+ ResourceMocks.compute_resources_available_networks
100
+ end
101
+
102
+ let(:cmd) { HammerCLIForeman::ComputeResource::AvailableNetworksCommand.new("", ctx) }
103
+
104
+ context "parameters" do
105
+ it_should_accept "id", ["--id=1"]
106
+ it_should_accept "name", ["--name=arch"]
107
+ # it_should_fail_with "no params", [] # TODO: temporarily disabled, parameters are checked in the id resolver
108
+ # it_should_fail_with "name or id missing", ["--new-name=arch2"] # TODO: temporarily disabled, parameters are checked in the id resolver
109
+ end
110
+
111
+ context "output" do
112
+ let(:expected_record_count) { count_records(cmd.resource.call(:available_networks)) }
113
+
114
+ with_params ["--name=testcr"] do
115
+ it_should_print_n_records
116
+ it_should_print_columns ["Name", "Id"]
117
+ end
118
+ end
119
+
120
+ end
97
121
 
98
122
  end
@@ -48,7 +48,7 @@ describe HammerCLIForeman::Host do
48
48
  it_should_print_columns ["Host Group", "Compute Resource", "Compute Profile", "Environment"]
49
49
  it_should_print_columns ["Puppet CA Id", "Puppet Master Id", "Cert name"]
50
50
  it_should_print_columns ["Managed", "Installed at", "Last report"]
51
- it_should_print_columns ["Network", "Network interfaces", "Operating system", "Parameters", "Additional info"]
51
+ it_should_print_columns ["Network", "Network interfaces", "Operating system", "Parameters", "All parameters", "Additional info"]
52
52
  end
53
53
  end
54
54
 
@@ -43,7 +43,7 @@ describe HammerCLIForeman::Hostgroup do
43
43
  it_should_print_n_records 1
44
44
  it_should_print_columns ["Id", "Name", "Title", "Operating System", "Subnet"]
45
45
  it_should_print_columns ["Domain", "Environment", "Puppetclasses", "Parent Id"]
46
- it_should_print_columns ["Parameters"]
46
+ it_should_print_columns ["Parameters", "Description"]
47
47
  end
48
48
  end
49
49
 
@@ -62,6 +62,10 @@ describe HammerCLIForeman::IdResolver do
62
62
 
63
63
 
64
64
  describe "resolving ids" do
65
+ let(:john_id) { 11 }
66
+ let(:john) { {"id" => john_id, "name" => "John Doe"} }
67
+ let(:jane_id) { 22 }
68
+ let(:jane) { {"id" => jane_id, "name" => "Jane Doe"} }
65
69
 
66
70
  it "must define methods for all resources" do
67
71
  expected_method_names = api.resources.map(&:singular_name).collect{|r| "#{r}_id"}
@@ -93,10 +97,7 @@ describe HammerCLIForeman::IdResolver do
93
97
  end
94
98
 
95
99
  it "raises exception when multiple resources are found" do
96
- ResourceMocks.mock_action_call(:users, :index, [
97
- {"id" => 11, "name" => "user11"},
98
- {"id" => 22, "name" => "user22"}
99
- ])
100
+ ResourceMocks.mock_action_call(:users, :index, [john, jane])
100
101
 
101
102
  err = resolver_run.must_raise HammerCLIForeman::ResolverError
102
103
  err.message.must_equal "found more than one user"
@@ -107,7 +108,7 @@ describe HammerCLIForeman::IdResolver do
107
108
  ( resource == :users &&
108
109
  action == :index &&
109
110
  params[:search] == "name = \"John Doe\"")
110
- end.returns({"id" => 1, "name" => "John Doe"})
111
+ end.returns(john)
111
112
 
112
113
  resolver_run.call
113
114
  end
@@ -119,17 +120,15 @@ describe HammerCLIForeman::IdResolver do
119
120
  end
120
121
 
121
122
  it "returns id of the resource" do
122
- ResourceMocks.mock_action_call(:users, :index, [
123
- {"id" => 11, "name" => "John Doe"}
124
- ])
123
+ ResourceMocks.mock_action_call(:users, :index, [john])
125
124
 
126
- resolver_run.call.must_equal 11
125
+ resolver_run.call.must_equal john_id
127
126
  end
128
127
 
129
128
  end
130
129
 
131
130
  describe "searching dependent resources" do
132
- let(:resolver_run) { proc { resolver.post_id({"option_name" => "Post 11", "option_user_name" => "User 22"}) } }
131
+ let(:resolver_run) { proc { resolver.post_id({"option_name" => "Post 11", "option_user_name" => "John Doe"}) } }
133
132
 
134
133
  it "raises exception when no resource is found" do
135
134
  ResourceMocks.mock_action_call(:posts, :index, [])
@@ -141,10 +140,7 @@ describe HammerCLIForeman::IdResolver do
141
140
 
142
141
  it "raises exception when multiple resources are found" do
143
142
  ResourceMocks.mock_action_call(:posts, :index, [])
144
- ResourceMocks.mock_action_call(:users, :index, [
145
- {"id" => 11, "name" => "user1"},
146
- {"id" => 22, "name" => "user2"}
147
- ])
143
+ ResourceMocks.mock_action_call(:users, :index, [john, jane])
148
144
 
149
145
  err = resolver_run.must_raise HammerCLIForeman::ResolverError
150
146
  err.message.must_equal "found more than one user"
@@ -154,8 +150,8 @@ describe HammerCLIForeman::IdResolver do
154
150
  ApipieBindings::API.any_instance.expects(:call).with() do |resource, action, params, headers, opts|
155
151
  ( resource == :users &&
156
152
  action == :index &&
157
- params[:search] == "name = \"User 22\"")
158
- end.returns({"id" => 22, "name" => "User 22"})
153
+ params[:search] == "name = \"John Doe\"")
154
+ end.returns(john)
159
155
 
160
156
  ApipieBindings::API.any_instance.expects(:call).with() do |resource, action, params, headers, opts|
161
157
  ( resource == :posts &&
@@ -178,9 +174,7 @@ describe HammerCLIForeman::IdResolver do
178
174
  end
179
175
 
180
176
  describe 'searching for puppetclasses' do
181
- let(:resolver_run) { proc { resolver.puppetclass_ids('option_names' => ['apache::mod::authnz_ldap', 'git::params', 'apache::dev']) } }
182
-
183
- it "returns ids of the classes" do
177
+ before do
184
178
  ResourceMocks.mock_action_call(:puppetclasses, :index, {
185
179
  'apache' => [
186
180
  { 'id' => 70, 'name' => 'apache::dev', 'created_at' => '2015-01-27T07:24:57.134Z', 'updated_at' => '2015-03-05T17:27:54.282Z' },
@@ -188,9 +182,53 @@ describe HammerCLIForeman::IdResolver do
188
182
  ],
189
183
  'git' => [
190
184
  { 'id' => 85, 'name' => 'git::params', 'created_at' => '2015-01-27T07:24:57.306Z', 'updated_at' => '2015-01-27T07:24:57.306Z' }
191
- ] })
185
+ ]
186
+ })
187
+ end
188
+
189
+ it "returns ids from options" do
190
+ result = resolver.user_ids({"option_ids" => [4, 5], "option_names" => ['apache::dev']})
191
+ assert_equal [4, 5], result
192
+ end
193
+
194
+ it "returns ids of the classes" do
195
+ class_names = ['apache::mod::authnz_ldap', 'git::params', 'apache::dev']
196
+ assert_equal [70, 27, 85], resolver.puppetclass_ids('option_names' => class_names)
197
+ end
198
+
199
+ it 'returns empty array for empty class array' do
200
+ assert_equal [], resolver.puppetclass_ids('option_names' => [])
201
+ end
202
+ end
203
+
204
+ describe "searching for multiple resources" do
205
+ it "returns ids from options" do
206
+ result = resolver.user_ids({"option_ids" => [4, 5], "option_names" => ["some", "names"]})
207
+ assert_equal [4, 5], result
208
+ end
209
+
210
+ it "finds multiple ids" do
211
+ ApipieBindings::API.any_instance.expects(:call).with() do |resource, action, params, headers, opts|
212
+ ( resource == :users &&
213
+ action == :index &&
214
+ params[:search] == "name = \"John Doe\" or name = \"Jane Doe\"")
215
+ end.returns([john, jane])
216
+
217
+ assert_equal [john_id, jane_id], resolver.user_ids({"option_names" => ["John Doe", "Jane Doe"]})
218
+ end
219
+
220
+ it "raises exception when wrong number of resources is found" do
221
+ ResourceMocks.mock_action_call(:users, :index, [john])
222
+
223
+ assert_raises HammerCLIForeman::ResolverError do
224
+ resolver.user_ids({"option_names" => ["John Doe", "Jane Doe"]})
225
+ end
226
+ end
227
+
228
+ it "returns empty array for empty input" do
229
+ ResourceMocks.mock_action_call(:users, :index, [john, jane])
192
230
 
193
- resolver_run.call.must_equal [70, 27, 85]
231
+ assert_equal [], resolver.user_ids({"option_names" => []})
194
232
  end
195
233
  end
196
234
  end