cliqr 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +128 -1
  3. data/README.md +97 -71
  4. data/examples/README.md +12 -0
  5. data/examples/hbase +58 -0
  6. data/examples/my-command +63 -0
  7. data/examples/numbers +55 -0
  8. data/examples/vagrant +90 -0
  9. data/lib/cliqr.rb +17 -2
  10. data/lib/cliqr/argument_validation/argument_type_validator.rb +2 -2
  11. data/lib/cliqr/argument_validation/validator.rb +1 -1
  12. data/lib/cliqr/cli/argument_operator.rb +44 -0
  13. data/lib/cliqr/cli/argument_operator_context.rb +20 -0
  14. data/lib/cliqr/cli/command.rb +1 -1
  15. data/lib/cliqr/cli/command_context.rb +93 -12
  16. data/lib/cliqr/cli/command_runner_factory.rb +2 -2
  17. data/lib/cliqr/cli/config.rb +301 -33
  18. data/lib/cliqr/cli/executor.rb +14 -9
  19. data/lib/cliqr/cli/interface.rb +22 -7
  20. data/lib/cliqr/cli/router.rb +6 -2
  21. data/lib/cliqr/cli/shell_command.rb +69 -0
  22. data/lib/cliqr/cli/usage_builder.rb +185 -0
  23. data/lib/cliqr/config_validation/validator_factory.rb +59 -5
  24. data/lib/cliqr/error.rb +10 -4
  25. data/lib/cliqr/parser/action_token.rb +23 -0
  26. data/lib/cliqr/parser/argument_parser.rb +1 -1
  27. data/lib/cliqr/parser/argument_token.rb +1 -4
  28. data/lib/cliqr/parser/argument_tree_walker.rb +40 -8
  29. data/lib/cliqr/parser/option_token.rb +2 -1
  30. data/lib/cliqr/parser/parsed_input.rb +21 -2
  31. data/lib/cliqr/parser/parsed_input_builder.rb +11 -7
  32. data/lib/cliqr/parser/token.rb +3 -9
  33. data/lib/cliqr/parser/token_factory.rb +1 -1
  34. data/lib/cliqr/util.rb +135 -0
  35. data/lib/cliqr/version.rb +1 -1
  36. data/spec/argument_parser_spec_helper.rb +15 -0
  37. data/spec/config/action_config_validator_spec.rb +146 -0
  38. data/spec/config/config_finalize_spec.rb +1 -1
  39. data/spec/config/config_validator_spec.rb +29 -19
  40. data/spec/config/option_config_validator_spec.rb +13 -13
  41. data/spec/dsl/interface_spec.rb +1 -168
  42. data/spec/dsl/usage_spec.rb +705 -0
  43. data/spec/executor/action_executor_spec.rb +205 -0
  44. data/spec/executor/executor_spec.rb +405 -17
  45. data/spec/executor/help_executor_spec.rb +424 -0
  46. data/spec/executor/shell_executor_spec.rb +233 -0
  47. data/spec/fixtures/action_reader_command.rb +12 -0
  48. data/spec/fixtures/csv_argument_operator.rb +8 -0
  49. data/spec/fixtures/test_option_type_checker_command.rb +8 -0
  50. data/spec/parser/action_argument_parser_spec.rb +113 -0
  51. data/spec/parser/argument_parser_spec.rb +37 -44
  52. data/spec/spec_helper.rb +1 -0
  53. data/spec/validation/action_argument_validator_spec.rb +50 -0
  54. data/spec/validation/{argument_validation_spec.rb → command_argument_validation_spec.rb} +36 -18
  55. data/spec/validation/error_spec.rb +1 -1
  56. data/tasks/rdoc.rake +16 -0
  57. data/tasks/rubucop.rake +14 -0
  58. data/tasks/yard.rake +21 -0
  59. data/templates/usage.erb +39 -0
  60. metadata +48 -11
@@ -0,0 +1,205 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ require 'fixtures/test_command'
6
+ require 'fixtures/always_error_command'
7
+ require 'fixtures/action_reader_command'
8
+ require 'fixtures/test_option_reader_command'
9
+ require 'fixtures/test_option_checker_command'
10
+ require 'fixtures/argument_reader_command'
11
+
12
+ describe Cliqr::CLI::Executor do
13
+ it 'routes to action command with no arguments' do
14
+ cli = Cliqr.interface do
15
+ name 'my-command'
16
+ handler TestCommand
17
+
18
+ action 'my-action' do
19
+ handler TestCommand
20
+ end
21
+ end
22
+ result = cli.execute_internal ['my-action'], output: :buffer
23
+ expect(result[:stdout]).to eq "test command executed\n"
24
+ end
25
+
26
+ it 'handles error appropriately for an action' do
27
+ cli = Cliqr.interface do
28
+ name 'my-command'
29
+ handler AlwaysErrorCommand
30
+
31
+ action 'my-action-1' do
32
+ handler AlwaysErrorCommand
33
+
34
+ action 'my-action-2' do
35
+ handler AlwaysErrorCommand
36
+ end
37
+ end
38
+ end
39
+ expect { cli.execute_internal %w(my-action-1 my-action-2) }.to raise_error(Cliqr::Error::CommandRuntimeError,
40
+ "command 'my-command my-action-1 my-action-2' failed\n\nCause: StandardError - I always throw an error\n")
41
+ end
42
+
43
+ it 'routes to a action with option values' do
44
+ cli = Cliqr.interface do
45
+ name 'my-command'
46
+ handler TestCommand
47
+
48
+ action 'my-action' do
49
+ handler TestCommand
50
+
51
+ option 'test-option'
52
+ end
53
+ end
54
+ result = cli.execute_internal %w(my-action --test-option some-value), output: :buffer
55
+ expect(result[:stdout]).to eq "test command executed\n"
56
+ end
57
+
58
+ it 'lets a action command get all option values' do
59
+ cli = Cliqr.interface do
60
+ name 'my-command'
61
+ handler TestCommand
62
+
63
+ action 'my-action' do
64
+ handler ActionReaderCommand
65
+
66
+ option 'test-option-1'
67
+ option 'test-option-2'
68
+ end
69
+ end
70
+ result = cli.execute_internal %w(my-action --test-option-1 some-value --test-option-2 v2), output: :buffer
71
+ expect(result[:stdout]).to eq <<-EOS
72
+ command = my-command my-action
73
+
74
+ executing action = my-action
75
+ [option] test-option-1 => some-value
76
+ [option] test-option-2 => v2
77
+ EOS
78
+ end
79
+
80
+ it 'lets a deeply nested action command get all option values' do
81
+ cli = Cliqr.interface do
82
+ name 'my-command'
83
+ handler ActionReaderCommand
84
+
85
+ action 'my-action-1' do
86
+ handler ActionReaderCommand
87
+
88
+ action 'my-action-2' do
89
+ handler ActionReaderCommand
90
+
91
+ action 'my-action-3' do
92
+ handler ActionReaderCommand
93
+
94
+ option 'test-option-1'
95
+ option 'test-option-2'
96
+ end
97
+ end
98
+ end
99
+ end
100
+ result = cli.execute_internal %w(my-action-1 --test-option-1 some-value my-action-2 --test-option-2 v2 my-action-3), output: :buffer
101
+ expect(result[:stdout]).to eq <<-EOS
102
+ command = my-command my-action-1 my-action-2 my-action-3
103
+
104
+ executing action = my-action-3
105
+ [option] test-option-1 => some-value
106
+ [option] test-option-2 => v2
107
+ EOS
108
+ end
109
+
110
+ it 'does not depend on the order of action and option' do
111
+ cli = Cliqr.interface do
112
+ name 'my-command'
113
+ handler ActionReaderCommand
114
+
115
+ action 'my-action' do
116
+ handler ActionReaderCommand
117
+
118
+ option 'test-option'
119
+ end
120
+ end
121
+ result = cli.execute_internal %w(--test-option some-value my-action), output: :buffer
122
+ expect(result[:stdout]).to eq <<-EOS
123
+ command = my-command my-action
124
+
125
+ executing action = my-action
126
+ [option] test-option => some-value
127
+ EOS
128
+ end
129
+
130
+ it 'lets a action command get single option value' do
131
+ cli = Cliqr.interface do
132
+ name 'my-command'
133
+ handler TestOptionReaderCommand
134
+
135
+ action 'my-action' do
136
+ handler TestOptionReaderCommand
137
+ option 'test-option'
138
+ end
139
+ end
140
+ result = cli.execute_internal %w(my-action --test-option some-value), output: :buffer
141
+ expect(result[:stdout]).to eq <<-EOS
142
+ some-value
143
+ EOS
144
+ end
145
+
146
+ it 'lets different action commands get their own option values' do
147
+ cli = Cliqr.interface do
148
+ name 'my-command'
149
+ handler TestOptionReaderCommand
150
+
151
+ action 'my-action' do
152
+ handler TestOptionReaderCommand
153
+ option 'test-option'
154
+ end
155
+
156
+ action 'another-action' do
157
+ handler TestOptionReaderCommand
158
+ option 'test-option'
159
+ end
160
+
161
+ action 'third-action' do
162
+ handler ActionReaderCommand
163
+ option 'third-option'
164
+ end
165
+ end
166
+ result = cli.execute_internal %w(my-action --test-option some-value), output: :buffer
167
+ expect(result[:stdout]).to eq <<-EOS
168
+ some-value
169
+ EOS
170
+
171
+ result = cli.execute_internal %w(another-action --test-option another), output: :buffer
172
+ expect(result[:stdout]).to eq <<-EOS
173
+ another
174
+ EOS
175
+
176
+ result = cli.execute_internal %w(third-action --third-option 3), output: :buffer
177
+ expect(result[:stdout]).to eq <<-EOS
178
+ command = my-command third-action
179
+
180
+ executing action = third-action
181
+ [option] third-option => 3
182
+ EOS
183
+ end
184
+
185
+ it 'allows action command to access argument list' do
186
+ cli = Cliqr.interface do
187
+ name 'my-command'
188
+ handler TestOptionCheckerCommand
189
+
190
+ action 'my-action' do
191
+ handler ArgumentReaderCommand
192
+ arguments :enable
193
+
194
+ option 'test-option'
195
+ end
196
+ end
197
+
198
+ result = cli.execute_internal %w(my-action value1 --test-option qwerty value2 value3), output: :buffer
199
+ expect(result[:stdout]).to eq <<-EOS
200
+ value1
201
+ value2
202
+ value3
203
+ EOS
204
+ end
205
+ end
@@ -10,48 +10,61 @@ require 'fixtures/option_reader_command'
10
10
  require 'fixtures/test_option_reader_command'
11
11
  require 'fixtures/test_option_checker_command'
12
12
  require 'fixtures/argument_reader_command'
13
+ require 'fixtures/test_option_type_checker_command'
14
+ require 'fixtures/csv_argument_operator'
13
15
 
14
16
  describe Cliqr::CLI::Executor do
15
17
  it 'returns code 0 for default command runner' do
16
- expect(Cliqr.command.new.execute).to eq(0)
18
+ expect(Cliqr.command.new.execute(nil)).to eq(0)
17
19
  end
18
20
 
19
- it 'routes base command with no arguments' do
21
+ it 'routes base command with no arguments to command class' do
20
22
  cli = Cliqr.interface do
21
- basename 'my-command'
23
+ name 'my-command'
22
24
  handler TestCommand
23
25
  end
24
- result = cli.execute [], output: :buffer
26
+ result = cli.execute_internal [], output: :buffer
27
+ expect(result[:stdout]).to eq "test command executed\n"
28
+ end
29
+
30
+ it 'routes base command with no arguments to command instance' do
31
+ cli = Cliqr.interface do
32
+ name 'my-command'
33
+ handler TestCommand.new
34
+ end
35
+ result = cli.execute_internal [], output: :buffer
25
36
  expect(result[:stdout]).to eq "test command executed\n"
26
37
  end
27
38
 
28
39
  it 'handles error appropriately' do
29
40
  cli = Cliqr.interface do
30
- basename 'my-command'
41
+ name 'my-command'
31
42
  handler AlwaysErrorCommand
32
43
  end
33
- expect { cli.execute [] }.to raise_error(Cliqr::Error::CommandRuntimeException)
44
+ expect { cli.execute_internal [] }.to(
45
+ raise_error(Cliqr::Error::CommandRuntimeError,
46
+ "command 'my-command' failed\n\nCause: StandardError - I always throw an error\n"))
34
47
  end
35
48
 
36
49
  it 'routes a command with option values' do
37
50
  cli = Cliqr.interface do
38
- basename 'my-command'
51
+ name 'my-command'
39
52
  handler TestCommand
40
53
 
41
54
  option 'test-option'
42
55
  end
43
- result = cli.execute %w(--test-option some-value), output: :buffer
56
+ result = cli.execute_internal %w(--test-option some-value), output: :buffer
44
57
  expect(result[:stdout]).to eq "test command executed\n"
45
58
  end
46
59
 
47
60
  it 'lets a command get all option values' do
48
61
  cli = Cliqr.interface do
49
- basename 'my-command'
62
+ name 'my-command'
50
63
  handler OptionReaderCommand
51
64
 
52
65
  option 'test-option'
53
66
  end
54
- result = cli.execute %w(--test-option some-value), output: :buffer
67
+ result = cli.execute_internal %w(--test-option some-value), output: :buffer
55
68
  expect(result[:stdout]).to eq <<-EOS
56
69
  my-command
57
70
 
@@ -61,12 +74,12 @@ my-command
61
74
 
62
75
  it 'lets a command get single option value' do
63
76
  cli = Cliqr.interface do
64
- basename 'my-command'
77
+ name 'my-command'
65
78
  handler TestOptionReaderCommand
66
79
 
67
80
  option 'test-option'
68
81
  end
69
- result = cli.execute %w(--test-option some-value), output: :buffer
82
+ result = cli.execute_internal %w(--test-option some-value), output: :buffer
70
83
  expect(result[:stdout]).to eq <<-EOS
71
84
  some-value
72
85
  EOS
@@ -74,7 +87,7 @@ some-value
74
87
 
75
88
  it 'handles executor error cause properly' do
76
89
  cli = Cliqr.interface do
77
- basename 'my-command'
90
+ name 'my-command'
78
91
  handler AlwaysErrorCommand
79
92
  end
80
93
  begin
@@ -87,7 +100,7 @@ some-value
87
100
 
88
101
  it 'allows command to check if an option exists or not' do
89
102
  cli = Cliqr.interface do
90
- basename 'my-command'
103
+ name 'my-command'
91
104
  description 'a command used to test cliqr'
92
105
  handler TestOptionCheckerCommand
93
106
 
@@ -96,7 +109,7 @@ some-value
96
109
  end
97
110
  end
98
111
 
99
- result = cli.execute %w(--test-option), output: :buffer
112
+ result = cli.execute_internal %w(--test-option), output: :buffer
100
113
  expect(result[:stdout]).to eq <<-EOS
101
114
  test-option is defined
102
115
  EOS
@@ -104,18 +117,393 @@ test-option is defined
104
117
 
105
118
  it 'allows command to access argument list' do
106
119
  cli = Cliqr.interface do
107
- basename 'my-command'
120
+ name 'my-command'
108
121
  handler ArgumentReaderCommand
109
122
  arguments :enable
110
123
 
111
124
  option 'test-option'
112
125
  end
113
126
 
114
- result = cli.execute %w(value1 --test-option qwerty value2 value3), output: :buffer
127
+ result = cli.execute_internal %w(value1 --test-option qwerty value2 value3), output: :buffer
115
128
  expect(result[:stdout]).to eq <<-EOS
116
129
  value1
117
130
  value2
118
131
  value3
119
132
  EOS
120
133
  end
134
+
135
+ it 'properly handles string type arguments' do
136
+ cli = Cliqr.interface do
137
+ name 'my-command'
138
+ handler TestOptionTypeCheckerCommand
139
+
140
+ option 'test-option'
141
+ end
142
+
143
+ result = cli.execute_internal %w(--test-option qwerty), output: :buffer
144
+ expect(result[:stdout]).to eq <<-EOS
145
+ test-option is of type String
146
+ EOS
147
+ end
148
+
149
+ it 'properly handles boolean type arguments' do
150
+ cli = Cliqr.interface do
151
+ name 'my-command'
152
+ handler TestOptionTypeCheckerCommand
153
+
154
+ option 'test-option' do
155
+ type :boolean
156
+ end
157
+ end
158
+
159
+ result = cli.execute_internal %w(--test-option), output: :buffer
160
+ expect(result[:stdout]).to eq <<-EOS
161
+ test-option is of type TrueClass
162
+ EOS
163
+
164
+ result = cli.execute_internal %w(--no-test-option), output: :buffer
165
+ expect(result[:stdout]).to eq <<-EOS
166
+ test-option is of type FalseClass
167
+ EOS
168
+ end
169
+
170
+ it 'properly handles integer type arguments' do
171
+ cli = Cliqr.interface do
172
+ name 'my-command'
173
+ handler TestOptionTypeCheckerCommand
174
+
175
+ option 'test-option' do
176
+ type :numeric
177
+ end
178
+ end
179
+
180
+ result = cli.execute_internal %w(--test-option 123), output: :buffer
181
+ expect(result[:stdout]).to eq <<-EOS
182
+ test-option is of type Fixnum
183
+ EOS
184
+ end
185
+
186
+ it 'allows custom argument operators' do
187
+ cli = Cliqr.interface do
188
+ name 'my-command'
189
+ handler TestOptionReaderCommand
190
+
191
+ option 'test-option' do
192
+ operator CSVArgumentOperator
193
+ end
194
+ end
195
+
196
+ result = cli.execute_internal %w(--test-option a,b,c,d), output: :buffer
197
+ expect(result[:stdout]).to eq <<-EOS
198
+ a
199
+ b
200
+ c
201
+ d
202
+ EOS
203
+ end
204
+
205
+ it 'allows inline executor' do
206
+ cli = Cliqr.interface do
207
+ name 'my-command'
208
+
209
+ handler do
210
+ puts "value = #{option('test-option').value}"
211
+ end
212
+
213
+ option 'test-option'
214
+ end
215
+
216
+ result = cli.execute_internal %w(--test-option executor-inline), output: :buffer
217
+ expect(result[:stdout]).to eq <<-EOS
218
+ value = executor-inline
219
+ EOS
220
+ end
221
+
222
+ it 'allows inline argument operator' do
223
+ cli = Cliqr.interface do
224
+ name 'my-command'
225
+ handler TestOptionReaderCommand
226
+
227
+ option 'test-option' do
228
+ operator do
229
+ "value = #{value}"
230
+ end
231
+ end
232
+ end
233
+
234
+ result = cli.execute_internal %w(--test-option operator-inline), output: :buffer
235
+ expect(result[:stdout]).to eq <<-EOS
236
+ value = operator-inline
237
+ EOS
238
+ end
239
+
240
+ it 'allows inline executor to access all context methods directly' do
241
+ cli = Cliqr.interface do
242
+ name 'my-command'
243
+
244
+ handler do
245
+ puts 'in my-command'
246
+ puts options.map { |option| "#{option.name} => #{option.value}" }
247
+ puts action?
248
+ puts option?('option-1')
249
+ puts option?('option-2')
250
+ puts option?('option-3')
251
+ end
252
+
253
+ option 'option-1'
254
+ option 'option-2'
255
+
256
+ action 'my-action' do
257
+ handler do
258
+ puts 'in my-action'
259
+ puts options.map { |option| "#{option.name} => #{option.value}" }
260
+ puts option('option-3').value
261
+ puts action?
262
+ puts option?('option-1')
263
+ puts option?('option-2')
264
+ puts option?('option-3')
265
+ end
266
+
267
+ option 'option-3'
268
+ end
269
+ end
270
+
271
+ result = cli.execute_internal %w(--option-1 val1 --option-2 val2), output: :buffer
272
+ expect(result[:stdout]).to eq <<-EOS
273
+ in my-command
274
+ option-1 => val1
275
+ option-2 => val2
276
+ false
277
+ true
278
+ true
279
+ false
280
+ EOS
281
+
282
+ result = cli.execute_internal %w(my-action --option-3 val3), output: :buffer
283
+ expect(result[:stdout]).to eq <<-EOS
284
+ in my-action
285
+ option-3 => val3
286
+ val3
287
+ true
288
+ false
289
+ false
290
+ true
291
+ EOS
292
+ end
293
+
294
+ it 'allows inline executor to get option value by calling method' do
295
+ cli = Cliqr.interface do
296
+ name 'my-command'
297
+
298
+ handler do
299
+ puts test_option
300
+ puts test_option?
301
+ puts second_option
302
+ end
303
+
304
+ option 'test_option'
305
+
306
+ option 'second_option' do
307
+ type :boolean
308
+ end
309
+ end
310
+
311
+ result = cli.execute_internal %w(--test_option executor-inline --second_option), output: :buffer
312
+ expect(result[:stdout]).to eq <<-EOS
313
+ executor-inline
314
+ true
315
+ true
316
+ EOS
317
+
318
+ result = cli.execute_internal [], output: :buffer
319
+ expect(result[:stdout]).to eq <<-EOS
320
+
321
+ false
322
+ false
323
+ EOS
324
+ end
325
+
326
+ it 'makes false the default for boolean options' do
327
+ cli = Cliqr.interface do
328
+ name 'my-command'
329
+
330
+ handler do
331
+ puts test_option
332
+ puts test_option?
333
+ end
334
+
335
+ option 'test_option' do
336
+ type :boolean
337
+ end
338
+ end
339
+
340
+ result = cli.execute_internal [], output: :buffer
341
+ expect(result[:stdout]).to eq <<-EOS
342
+ false
343
+ false
344
+ EOS
345
+ end
346
+
347
+ it 'can override default to true' do
348
+ cli = Cliqr.interface do
349
+ name 'my-command'
350
+
351
+ handler do
352
+ puts test_option
353
+ puts test_option?
354
+ end
355
+
356
+ option 'test_option' do
357
+ type :boolean
358
+ default true
359
+ end
360
+ end
361
+
362
+ result = cli.execute_internal [], output: :buffer
363
+ expect(result[:stdout]).to eq <<-EOS
364
+ true
365
+ false
366
+ EOS
367
+ end
368
+
369
+ it 'makes 0 as default for numerical' do
370
+ cli = Cliqr.interface do
371
+ name 'my-command'
372
+
373
+ handler do
374
+ puts test_option
375
+ puts test_option?
376
+ end
377
+
378
+ option 'test_option' do
379
+ type :numeric
380
+ end
381
+ end
382
+
383
+ result = cli.execute_internal [], output: :buffer
384
+ expect(result[:stdout]).to eq <<-EOS
385
+ 0
386
+ false
387
+ EOS
388
+ end
389
+
390
+ it 'allows non-zero default for numerical option' do
391
+ cli = Cliqr.interface do
392
+ name 'my-command'
393
+
394
+ handler do
395
+ puts test_option
396
+ puts test_option?
397
+ end
398
+
399
+ option :test_option do
400
+ type :numeric
401
+ default 123
402
+ end
403
+ end
404
+
405
+ result = cli.execute_internal [], output: :buffer
406
+ expect(result[:stdout]).to eq <<-EOS
407
+ 123
408
+ false
409
+ EOS
410
+ end
411
+
412
+ it 'can use version action on base command' do
413
+ cli = Cliqr.interface do
414
+ name 'my-command'
415
+ version '1234'
416
+ end
417
+
418
+ result = cli.execute_internal ['version'], output: :buffer
419
+ expect(result[:stdout]).to eq <<-EOS
420
+ 1234
421
+ EOS
422
+ end
423
+
424
+ it 'can get version by option on base command' do
425
+ cli = Cliqr.interface do
426
+ name 'my-command'
427
+ version '1234'
428
+ end
429
+
430
+ result = cli.execute_internal ['--version'], output: :buffer
431
+ expect(result[:stdout]).to eq <<-EOS
432
+ 1234
433
+ EOS
434
+
435
+ result = cli.execute_internal ['-v'], output: :buffer
436
+ expect(result[:stdout]).to eq <<-EOS
437
+ 1234
438
+ EOS
439
+ end
440
+
441
+ it 'can use version action on action command' do
442
+ cli = Cliqr.interface do
443
+ name 'my-command'
444
+
445
+ action :bla do
446
+ version '1234'
447
+ end
448
+ end
449
+
450
+ result = cli.execute_internal ['bla version'], output: :buffer
451
+ expect(result[:stdout]).to eq <<-EOS
452
+ 1234
453
+ EOS
454
+ end
455
+
456
+ describe 'error handling' do
457
+ it 'returns 0 if no error' do
458
+ cli = Cliqr.interface do
459
+ name 'my-command'
460
+ handler do
461
+ puts 'I am happy!'
462
+ end
463
+ end
464
+
465
+ old_stdout = $stdout
466
+ $stdout = old_stdout.is_a?(StringIO) ? old_stdout : StringIO.new('', 'w')
467
+ begin
468
+ expect(cli.execute).to(eq(0))
469
+ expect($stdout.string).to(eq("I am happy!\n"))
470
+ ensure
471
+ $stdout = old_stdout
472
+ end
473
+ end
474
+
475
+ it 'can handle errors in command handler' do
476
+ cli = Cliqr.interface do
477
+ name 'my-command'
478
+ handler do
479
+ fail StandardError, 'I am not a happy handler!'
480
+ end
481
+ end
482
+
483
+ old_stdout = $stdout
484
+ $stdout = old_stdout.is_a?(StringIO) ? old_stdout : StringIO.new('', 'w')
485
+ begin
486
+ expect(cli.execute(['abcd'])).to(eq(1))
487
+ expect($stdout.string).to(eq("command 'my-command' failed\n\nCause: StandardError - I am not a happy handler!\n"))
488
+ ensure
489
+ $stdout = old_stdout
490
+ end
491
+ end
492
+
493
+ it 'can handle errors in command arguments' do
494
+ cli = Cliqr.interface do
495
+ name 'my-command'
496
+ arguments :disable
497
+ end
498
+
499
+ old_stdout = $stdout
500
+ $stdout = old_stdout.is_a?(StringIO) ? old_stdout : StringIO.new('', 'w')
501
+ begin
502
+ expect(cli.execute(['abcd'])).to(eq(2))
503
+ expect($stdout.string).to(eq("invalid command argument \"abcd\"\n"))
504
+ ensure
505
+ $stdout = old_stdout
506
+ end
507
+ end
508
+ end
121
509
  end