command_kit 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +6 -0
  3. data/README.md +3 -0
  4. data/command_kit.gemspec +7 -2
  5. data/lib/command_kit/completion/install.rb +276 -0
  6. data/lib/command_kit/env/prefix.rb +41 -0
  7. data/lib/command_kit/env/shell.rb +58 -0
  8. data/lib/command_kit/version.rb +1 -1
  9. metadata +4 -64
  10. data/spec/arguments/argument_spec.rb +0 -133
  11. data/spec/arguments/argument_value_spec.rb +0 -66
  12. data/spec/arguments_spec.rb +0 -279
  13. data/spec/bug_report_spec.rb +0 -266
  14. data/spec/colors_spec.rb +0 -771
  15. data/spec/command_kit_spec.rb +0 -8
  16. data/spec/command_name_spec.rb +0 -130
  17. data/spec/command_spec.rb +0 -123
  18. data/spec/commands/auto_load/subcommand_spec.rb +0 -82
  19. data/spec/commands/auto_load_spec.rb +0 -159
  20. data/spec/commands/auto_require_spec.rb +0 -142
  21. data/spec/commands/fixtures/test_auto_load/cli/commands/test1.rb +0 -10
  22. data/spec/commands/fixtures/test_auto_load/cli/commands/test2.rb +0 -10
  23. data/spec/commands/fixtures/test_auto_require/lib/test_auto_require/cli/commands/test1.rb +0 -10
  24. data/spec/commands/help_spec.rb +0 -66
  25. data/spec/commands/parent_command_spec.rb +0 -40
  26. data/spec/commands/subcommand_spec.rb +0 -99
  27. data/spec/commands_spec.rb +0 -865
  28. data/spec/description_spec.rb +0 -179
  29. data/spec/edit_spec.rb +0 -72
  30. data/spec/env/home_spec.rb +0 -46
  31. data/spec/env/path_spec.rb +0 -84
  32. data/spec/env_spec.rb +0 -123
  33. data/spec/examples_spec.rb +0 -211
  34. data/spec/exception_handler_spec.rb +0 -103
  35. data/spec/file_utils_spec.rb +0 -59
  36. data/spec/fixtures/template.erb +0 -5
  37. data/spec/help/man_spec.rb +0 -345
  38. data/spec/help_spec.rb +0 -94
  39. data/spec/inflector_spec.rb +0 -166
  40. data/spec/interactive_spec.rb +0 -415
  41. data/spec/main_spec.rb +0 -179
  42. data/spec/man_spec.rb +0 -46
  43. data/spec/open_app_spec.rb +0 -85
  44. data/spec/options/option_spec.rb +0 -343
  45. data/spec/options/option_value_spec.rb +0 -171
  46. data/spec/options/parser_spec.rb +0 -274
  47. data/spec/options/quiet_spec.rb +0 -51
  48. data/spec/options/verbose_spec.rb +0 -51
  49. data/spec/options/version_spec.rb +0 -146
  50. data/spec/options_spec.rb +0 -465
  51. data/spec/os/linux_spec.rb +0 -164
  52. data/spec/os_spec.rb +0 -233
  53. data/spec/package_manager_spec.rb +0 -806
  54. data/spec/pager_spec.rb +0 -217
  55. data/spec/printing/fields_spec.rb +0 -167
  56. data/spec/printing/indent_spec.rb +0 -132
  57. data/spec/printing/lists_spec.rb +0 -99
  58. data/spec/printing/tables/border_style.rb +0 -43
  59. data/spec/printing/tables/cell_builer_spec.rb +0 -135
  60. data/spec/printing/tables/row_builder_spec.rb +0 -165
  61. data/spec/printing/tables/style_spec.rb +0 -377
  62. data/spec/printing/tables/table_builder_spec.rb +0 -252
  63. data/spec/printing/tables/table_formatter_spec.rb +0 -1190
  64. data/spec/printing/tables_spec.rb +0 -1069
  65. data/spec/printing_spec.rb +0 -106
  66. data/spec/program_name_spec.rb +0 -70
  67. data/spec/spec_helper.rb +0 -3
  68. data/spec/stdio_spec.rb +0 -264
  69. data/spec/sudo_spec.rb +0 -51
  70. data/spec/terminal_spec.rb +0 -231
  71. data/spec/usage_spec.rb +0 -237
  72. data/spec/xdg_spec.rb +0 -191
@@ -1,865 +0,0 @@
1
- require 'spec_helper'
2
- require 'command_kit/commands'
3
-
4
- describe CommandKit::Commands do
5
- module TestCommands
6
- class TestEmptyCommands
7
-
8
- include CommandKit::Commands
9
-
10
- end
11
-
12
- class TestCommands
13
-
14
- include CommandKit::Commands
15
-
16
- class Test1 < CommandKit::Command
17
- end
18
-
19
- class Test2 < CommandKit::Command
20
- end
21
-
22
- command Test1
23
- command Test2
24
-
25
- end
26
-
27
- class TestCommandsWithAliases
28
-
29
- include CommandKit::Commands
30
-
31
- class Test1 < CommandKit::Command
32
- end
33
-
34
- class Test2 < CommandKit::Command
35
- end
36
-
37
- command Test1, aliases: %w[t1]
38
- command Test2, aliases: %w[t2]
39
-
40
- end
41
-
42
- class TestCommandsWithExplicitNames
43
-
44
- include CommandKit::Commands
45
-
46
- class Test1 < CommandKit::Command
47
- end
48
-
49
- class Test2 < CommandKit::Command
50
- end
51
-
52
- command 'command-name-1', Test1
53
- command 'command-name-2', Test2
54
-
55
- end
56
-
57
- class TestCommandsWithExplicitNamesAndAliases
58
-
59
- include CommandKit::Commands
60
-
61
- class Test1 < CommandKit::Command
62
- end
63
-
64
- class Test2 < CommandKit::Command
65
- end
66
-
67
- command 'command-name-1', Test1, aliases: %w[t1]
68
- command 'command-name-2', Test2, aliases: %w[t2]
69
-
70
- end
71
-
72
- class TestCommandsWithExplicitSummaries
73
-
74
- include CommandKit::Commands
75
-
76
- class Test1 < CommandKit::Command
77
- end
78
-
79
- class Test2 < CommandKit::Command
80
- end
81
-
82
- command Test1, summary: 'Explicit summary 1'
83
- command Test2, summary: 'Explicit summary 2'
84
-
85
- end
86
-
87
- class TestCommandsWithCustomExitStatus
88
-
89
- include CommandKit::Commands
90
-
91
- class Test < CommandKit::Command
92
-
93
- def run(*argv)
94
- exit(2)
95
- end
96
-
97
- end
98
-
99
- command Test
100
-
101
- end
102
-
103
- class TestCommandsWithGlobalOptions
104
-
105
- include CommandKit::Commands
106
-
107
- class Test1 < CommandKit::Command
108
- end
109
-
110
- class Test2 < CommandKit::Command
111
- end
112
-
113
- option :foo, short: '-f',
114
- desc: "Global --foo option"
115
-
116
- option :bar, short: '-b',
117
- value: {
118
- required: true,
119
- type: String,
120
- usage: 'BAR'
121
- },
122
- desc: "Global --bar option"
123
-
124
- command Test1
125
- command Test2
126
-
127
- end
128
-
129
- class TestCommandsWithCommandArguments
130
-
131
- include CommandKit::Commands
132
-
133
- class Test1 < CommandKit::Command
134
- argument :arg1, required: false,
135
- desc: 'Argument 1'
136
-
137
- argument :arg2, required: false,
138
- desc: 'Argument 2'
139
- end
140
-
141
- class Test2 < CommandKit::Command
142
- argument :arg1, required: false,
143
- desc: 'Argument 1'
144
-
145
- argument :arg2, required: false,
146
- desc: 'Argument 2'
147
- end
148
-
149
- command Test1
150
- command Test2
151
-
152
- end
153
-
154
- end
155
-
156
- let(:command_class) { TestCommands::TestCommands }
157
-
158
- describe ".included" do
159
- subject { command_class }
160
-
161
- it "must set .usage to '[options] [COMMAND [ARGS...]]'" do
162
- expect(subject.usage).to eq('[options] [COMMAND [ARGS...]]')
163
- end
164
-
165
- it "must add a 'command' argument" do
166
- expect(subject.arguments[:command]).to_not be_nil
167
- expect(subject.arguments[:command].required?).to be(false)
168
- expect(subject.arguments[:command].desc).to eq('The command name to run')
169
- end
170
-
171
- it "must add a 'args' argument" do
172
- expect(subject.arguments[:args]).to_not be_nil
173
- expect(subject.arguments[:args].required?).to be(false)
174
- expect(subject.arguments[:args].repeats?).to be(true)
175
- expect(subject.arguments[:args].desc).to eq('Additional arguments for the command')
176
- end
177
-
178
- it "must add a 'help' command" do
179
- expect(subject.commands['help']).to_not be(nil)
180
- expect(subject.commands['help'].command).to be(described_class::Help)
181
- end
182
- end
183
-
184
- describe ".commands" do
185
- subject { command_class }
186
-
187
- it "must return a Hash" do
188
- expect(subject.commands).to be_kind_of(Hash)
189
- end
190
-
191
- it "must provide a default 'help' command" do
192
- expect(subject.commands['help']).to_not be_nil
193
- expect(subject.commands['help'].command).to eq(CommandKit::Commands::Help)
194
- end
195
-
196
- context "when additional commands are defined in a superclass" do
197
- module TestCommands
198
- class TestInheritedCommands < TestCommands
199
-
200
- class Test3 < CommandKit::Command
201
-
202
- def run
203
- puts 'test command three'
204
- end
205
-
206
- end
207
-
208
- command :test3, Test3
209
-
210
- end
211
- end
212
-
213
- let(:command_superclass) { TestCommands::TestCommands }
214
- let(:command_class) { TestCommands::TestInheritedCommands }
215
-
216
- it "must inherit the superclass'es commands" do
217
- expect(subject.commands['test1']).to eq(command_superclass.commands['test1'])
218
- expect(subject.commands['test2']).to eq(command_superclass.commands['test2'])
219
- end
220
-
221
- it "must allow defining additional commands in the subclass" do
222
- expect(subject.commands['test3']).to_not be_nil
223
- expect(subject.commands['test3'].command).to eq(command_class::Test3)
224
- end
225
-
226
- it "must not change the superclass'es commands" do
227
- expect(command_superclass.commands['test3']).to be(nil)
228
- end
229
- end
230
- end
231
-
232
- describe ".command_aliases" do
233
- subject { command_class }
234
-
235
- it "must return an empty Hash by default" do
236
- expect(subject.command_aliases).to eq({})
237
- end
238
-
239
- context "when commands have aliases" do
240
- let(:command_class) { TestCommands::TestCommandsWithAliases }
241
-
242
- it "must contain the mapping of aliases to command names" do
243
- expect(subject.command_aliases).to eq({
244
- 't1' => 'test1',
245
- 't2' => 'test2'
246
- })
247
- end
248
- end
249
-
250
- context "when additional command aliases are defined in a superclass" do
251
- module TestCommands
252
- class TestInheritedCommandsWithAliases < TestCommandsWithAliases
253
-
254
- class Test3 < CommandKit::Command
255
-
256
- def run
257
- puts 'test command three'
258
- end
259
-
260
- end
261
-
262
- command :test3, Test3, aliases: %w[t3]
263
-
264
- end
265
- end
266
-
267
- let(:command_superclass) { TestCommands::TestCommandsWithAliases }
268
- let(:command_class) { TestCommands::TestInheritedCommandsWithAliases }
269
-
270
- it "must inherit the superclass'es command aliases" do
271
- expect(subject.command_aliases['t1']).to eq(command_superclass.command_aliases['t1'])
272
- expect(subject.command_aliases['t2']).to eq(command_superclass.command_aliases['t2'])
273
- end
274
-
275
- it "must allow defining additional command aliases in the subclass" do
276
- expect(subject.command_aliases['t3']).to eq('test3')
277
- end
278
-
279
- it "must not change the superclass'es command aliases" do
280
- expect(command_superclass.command_aliases['test3']).to be(nil)
281
- end
282
- end
283
- end
284
-
285
- describe ".command" do
286
- subject { command_class }
287
-
288
- context "when given only a command class" do
289
- module TestCommands
290
- class TestCommandWithOnlyACommandClass
291
- include CommandKit::Commands
292
-
293
- class Test < CommandKit::Command
294
- end
295
-
296
- command Test
297
- end
298
- end
299
-
300
- let(:command_class) { TestCommands::TestCommandWithOnlyACommandClass }
301
-
302
- it "must default the command name to the command class'es command_name" do
303
- expect(subject.commands['test']).to_not be_nil
304
- expect(subject.commands['test'].command).to eq(command_class::Test)
305
- end
306
-
307
- context "and aliases:" do
308
- let(:command_class) { TestCommands::TestCommandsWithAliases }
309
-
310
- it "must populate aliases with the aliases and the command names" do
311
- expect(subject.command_aliases['t1']).to eq(command_class::Test1.command_name)
312
- expect(subject.command_aliases['t2']).to eq(command_class::Test2.command_name)
313
- end
314
- end
315
- end
316
-
317
- context "when given a command name and a command class" do
318
- let(:command_class) { TestCommands::TestCommandsWithExplicitNames }
319
-
320
- it "must not add an entry for the command class'es command_name" do
321
- expect(subject.commands['test1']).to be_nil
322
- expect(subject.commands['test2']).to be_nil
323
- end
324
-
325
- it "must add an entry for the command name" do
326
- expect(subject.commands['command-name-1']).to_not be_nil
327
- expect(subject.commands['command-name-1'].command).to eq(command_class::Test1)
328
-
329
- expect(subject.commands['command-name-2']).to_not be_nil
330
- expect(subject.commands['command-name-2'].command).to eq(command_class::Test2)
331
- end
332
-
333
- context "and aliases:" do
334
- let(:command_class) { TestCommands::TestCommandsWithExplicitNamesAndAliases }
335
-
336
- it "must populate aliases with the aliases and the explicit command names" do
337
- expect(subject.command_aliases['t1']).to eq('command-name-1')
338
- expect(subject.command_aliases['t2']).to eq('command-name-2')
339
- end
340
- end
341
-
342
- context "when the command name is a Symbol" do
343
- module TestCommands
344
- class TestCommandWithASymbolCommandName
345
- include CommandKit::Commands
346
-
347
- class Test < CommandKit::Command
348
- end
349
-
350
- command :test_sym, Test
351
- end
352
- end
353
-
354
- let(:command_class) { TestCommands::TestCommandWithASymbolCommandName }
355
-
356
- it "must not add an entry for the command class'es command_name" do
357
- expect(subject.commands['test']).to be_nil
358
- end
359
-
360
- it "must not add entries with Symbol keys" do
361
- expect(subject.commands.keys).to all(be_kind_of(String))
362
- end
363
-
364
- it "must convert the command name to a String" do
365
- expect(subject.commands['test_sym']).to_not be_nil
366
- expect(subject.commands['test_sym'].command).to eq(command_class::Test)
367
- end
368
- end
369
- end
370
-
371
- context "when given an explicit summary: keyword argument" do
372
- let(:command_class) { TestCommands::TestCommandsWithExplicitSummaries }
373
-
374
- it "must initialize the Subcommand#summary" do
375
- expect(subject.commands['test1'].summary).to eq('Explicit summary 1')
376
- expect(subject.commands['test2'].summary).to eq('Explicit summary 2')
377
- end
378
- end
379
- end
380
-
381
- describe ".get_command" do
382
- subject { command_class }
383
-
384
- context "when given a command name" do
385
- let(:command_class) { TestCommands::TestCommands }
386
-
387
- it "must return the command's class" do
388
- expect(subject.get_command('test1')).to eq(command_class::Test1)
389
- expect(subject.get_command('test2')).to eq(command_class::Test2)
390
- end
391
- end
392
-
393
- context "when given a command's alias name" do
394
- let(:command_class) { TestCommands::TestCommandsWithAliases }
395
-
396
- it "must return the command's class associated with the alias" do
397
- expect(subject.get_command('t1')).to eq(command_class::Test1)
398
- expect(subject.get_command('t2')).to eq(command_class::Test2)
399
- end
400
- end
401
-
402
- context "when given an unknown command name" do
403
- it "must return nil" do
404
- expect(subject.get_command('foo')).to be(nil)
405
- end
406
- end
407
- end
408
-
409
- subject { command_class.new }
410
-
411
- describe "#command" do
412
- module TestCommands
413
- class TestSubCommandInitialization
414
- include CommandKit::Commands
415
-
416
- class Test < CommandKit::Command
417
- end
418
-
419
- command 'test', Test
420
- end
421
- end
422
-
423
- let(:command_class) { TestCommands::TestSubCommandInitialization }
424
- let(:subcommand_class) { command_class::Test }
425
-
426
- context "when given a valid command name" do
427
- it "must lookup the command and initialize it" do
428
- expect(subject.command(subcommand_class.command_name)).to be_kind_of(subcommand_class)
429
- end
430
- end
431
-
432
- context "when given a command alias" do
433
- let(:command_class) { TestCommands::TestCommandsWithAliases }
434
-
435
- it "must lookup the command and initialize it" do
436
- expect(subject.command('t1')).to be_kind_of(command_class::Test1)
437
- expect(subject.command('t2')).to be_kind_of(command_class::Test2)
438
- end
439
- end
440
-
441
- context "when given an unknown command name" do
442
- it "must return nil" do
443
- expect(subject.command('foo')).to be_nil
444
- end
445
- end
446
-
447
- context "when the command includes CommandKit::Commands::ParentCommand" do
448
- module TestCommands
449
- class TestSubCommandInitializationWithParentCommand
450
- include CommandKit::Commands
451
-
452
- class Test
453
- include CommandKit::Commands::ParentCommand
454
- end
455
-
456
- command 'test', Test
457
- end
458
- end
459
-
460
- let(:command_class) { TestCommands::TestSubCommandInitializationWithParentCommand }
461
- let(:subcommand_class) { command_class::Test }
462
-
463
- it "must initialize the sub-command with a parent_command value" do
464
- subcommand = subject.command('test')
465
-
466
- expect(subcommand.parent_command).to be(subject)
467
- end
468
- end
469
-
470
- context "when the command includes CommandKit::CommandName" do
471
- module TestCommands
472
- class TestSubCommandInitializationWithCommandName
473
- include CommandKit::Commands
474
-
475
- class Test
476
- include CommandKit::CommandName
477
- end
478
-
479
- command 'test', Test
480
- end
481
- end
482
-
483
- let(:command_class) { TestCommands::TestSubCommandInitializationWithCommandName }
484
- let(:subcommand_class) { command_class::Test }
485
- let(:expected_subcommand_name) do
486
- "#{command_class.command_name} #{subcommand_class.command_name}"
487
- end
488
-
489
- it "must initialize the sub-command with the command and subcommand name" do
490
- subcommand = subject.command('test')
491
-
492
- expect(subcommand.command_name).to eq(expected_subcommand_name)
493
- end
494
- end
495
-
496
- context "when the command includes CommandKit::Stdio" do
497
- module TestCommands
498
- class TestSubCommandInitializationWithStdio
499
- include CommandKit::Commands
500
-
501
- class Test
502
- include CommandKit::Stdio
503
- end
504
-
505
- command 'test', Test
506
- end
507
- end
508
-
509
- let(:command_class) { TestCommands::TestSubCommandInitializationWithStdio }
510
- let(:subcommand_class) { command_class::Test }
511
-
512
- let(:stdin) { StringIO.new }
513
- let(:stdout) { StringIO.new }
514
- let(:stderr) { StringIO.new }
515
-
516
- subject do
517
- command_class.new(stdin: stdin, stdout: stdout, stderr: stderr)
518
- end
519
-
520
- it "must initialize the sub-command with the command's #stdin, #stdout, #stderr" do
521
- subcommand = subject.command('test')
522
-
523
- expect(subcommand.stdin).to be(stdin)
524
- expect(subcommand.stdout).to be(stdout)
525
- expect(subcommand.stderr).to be(stderr)
526
- end
527
- end
528
-
529
- context "when the command includes CommandKit::Env" do
530
- module TestCommands
531
- class TestSubCommandInitializationWithEnv
532
- include CommandKit::Commands
533
-
534
- class Test
535
- include CommandKit::Env
536
- end
537
-
538
- command 'test', Test
539
- end
540
- end
541
-
542
- let(:command_class) { TestCommands::TestSubCommandInitializationWithEnv }
543
- let(:subcommand_class) { command_class::Test }
544
-
545
- let(:env) { {'FOO' => 'bar'} }
546
- subject { command_class.new(env: env) }
547
-
548
- it "must initialize the sub-command with a copy of the command's #env" do
549
- subcommand = subject.command('test')
550
-
551
- expect(subcommand.env).to eq(env)
552
- expect(subcommand.env).to_not be(env)
553
- end
554
- end
555
-
556
- context "when the command includes CommandKit::Options" do
557
- module TestCommands
558
- class TestSubCommandInitializationWithOptions
559
- include CommandKit::Commands
560
-
561
- class Test
562
- include CommandKit::Options
563
- end
564
-
565
- command 'test', Test
566
- end
567
- end
568
-
569
- let(:command_class) { TestCommands::TestSubCommandInitializationWithOptions }
570
- let(:subcommand_class) { command_class::Test }
571
-
572
- let(:options) { {foo: 'bar'} }
573
- subject { command_class.new(options: options) }
574
-
575
- it "must initialize the sub-command with a copy of the command's #options Hash" do
576
- subcommand = subject.command('test')
577
-
578
- expect(subcommand.options).to eq(options)
579
- expect(subcommand.options).to_not be(options)
580
- end
581
- end
582
- end
583
-
584
- describe "#invoke" do
585
- context "when given a valid command name" do
586
- let(:command_name) { 'test2' }
587
- let(:argv) { %w[--opt arg1 arg2] }
588
-
589
- it "must call the command's #main method with the given argv" do
590
- expect_any_instance_of(command_class::Test2).to receive(:main).with(argv)
591
-
592
- subject.invoke(command_name,*argv)
593
- end
594
-
595
- context "when the command returns a custom exit code" do
596
- let(:command_class) { TestCommands::TestCommandsWithCustomExitStatus }
597
-
598
- it "must return the exit code" do
599
- expect(subject.invoke('test')).to eq(2)
600
- end
601
- end
602
- end
603
-
604
- context "when given an unknown command name" do
605
- let(:command_name) { 'xxx' }
606
- let(:argv) { %w[--opt arg1 arg2] }
607
-
608
- it "must call #on_unknown_command with the given name and argv" do
609
- expect(subject).to receive(:on_unknown_command).with(command_name,argv)
610
-
611
- subject.invoke(command_name,*argv)
612
- end
613
- end
614
- end
615
-
616
- let(:unknown_command) { 'xxx' }
617
-
618
- describe "#command_not_found" do
619
- it "must print an error message to stderr and exit with 1" do
620
- expect(subject).to receive(:exit).with(1)
621
-
622
- expect { subject.command_not_found(unknown_command) }.to output(
623
- "#{subject.command_name}: '#{unknown_command}' is not a #{subject.command_name} command. See `#{subject.command_name} help`" + $/
624
- ).to_stderr
625
- end
626
- end
627
-
628
- describe "#on_unknown_command" do
629
- it "must call #command_not_found with the given command name by default" do
630
- expect(subject).to receive(:command_not_found).with(unknown_command)
631
-
632
- subject.on_unknown_command(unknown_command)
633
- end
634
- end
635
-
636
- describe "#option_parser" do
637
- let(:command_name) { 'test1' }
638
- let(:command_argv) { %w[foo bar baz] }
639
- let(:argv) { [command_name, *command_argv] }
640
-
641
- it "must stop before the first non-option argument" do
642
- expect(subject.option_parser.parse(argv)).to eq(
643
- [command_name, *command_argv]
644
- )
645
- end
646
-
647
- context "when an unknown command name is given" do
648
- let(:command_argv) { %w[bar baz] }
649
- let(:argv) { ['foo', command_name, *command_argv] }
650
-
651
- it "must stop before the first non-option argument" do
652
- expect(subject.option_parser.parse(argv)).to eq(argv)
653
- end
654
- end
655
-
656
- context "when additional global options are defined" do
657
- let(:command_class) { TestCommands::TestCommandsWithGlobalOptions }
658
- let(:bar) { '2' }
659
- let(:argv) do
660
- ['--foo', '--bar', bar.to_s, command_name, *command_argv]
661
- end
662
-
663
- it "must parse the global options, but stop before the first non-option associated argument" do
664
- expect(subject.option_parser.parse(argv)).to eq(
665
- [command_name, *command_argv]
666
- )
667
-
668
- expect(subject.options[:foo]).to be(true)
669
- expect(subject.options[:bar]).to eq(bar)
670
- end
671
- end
672
- end
673
-
674
- describe "#run" do
675
- context "when a command name is the first argument" do
676
- let(:command) { 'test1' }
677
- let(:exit_status) { 2 }
678
-
679
- it "must invoke the command and exit with it's status" do
680
- expect(subject).to receive(:invoke).with(command).and_return(exit_status)
681
- expect(subject).to receive(:exit).with(exit_status)
682
-
683
- subject.run(command)
684
- end
685
-
686
- context "when additional argv is given after the command name" do
687
- let(:argv) { %w[--opt arg1 arg2] }
688
-
689
- it "must pass the additional argv to the command" do
690
- expect(subject).to receive(:invoke).with(command,*argv).and_return(exit_status)
691
- expect(subject).to receive(:exit).with(exit_status)
692
-
693
- subject.run(command,*argv)
694
- end
695
- end
696
- end
697
-
698
- context "when given no arguments" do
699
- let(:exit_status) { 1 }
700
-
701
- it "must default to calling #help and exit with 1" do
702
- expect(subject).to receive(:help)
703
- expect(subject).to receive(:exit).with(exit_status)
704
-
705
- subject.run()
706
- end
707
- end
708
- end
709
-
710
- describe "#main" do
711
- let(:command_class) { TestCommands::TestCommandsWithCommandArguments }
712
-
713
- context "when a command name is the first argument" do
714
- let(:command) { 'test1' }
715
- let(:argv) { [command] }
716
-
717
- it "must return 0" do
718
- expect(subject.main(argv)).to eq(0)
719
- end
720
- end
721
-
722
- context "when given additional command arguments" do
723
- let(:argv) { %w[test1 arg1 arg2] }
724
-
725
- it "must pass them to the command" do
726
- expect(subject.main(argv)).to eq(0)
727
- end
728
- end
729
-
730
- context "when given no arguments" do
731
- let(:exit_status) { 1 }
732
- let(:argv) { %w[] }
733
-
734
- it "must call #help and return 1" do
735
- expect(subject).to receive(:help)
736
-
737
- expect(subject.main(argv)).to eq(exit_status)
738
- end
739
- end
740
- end
741
-
742
- describe "#help_commands" do
743
- it "must print usage and the list of available commands" do
744
- expect { subject.help_commands }.to output(
745
- [
746
- "",
747
- "Commands:",
748
- " help",
749
- " test1",
750
- " test2",
751
- ""
752
- ].join($/)
753
- ).to_stdout
754
- end
755
-
756
- context "when the commands have custom names" do
757
- let(:command_class) { TestCommands::TestCommandsWithExplicitNames }
758
-
759
- it "must print the command names, not the command class'es #command_name" do
760
- expect { subject.help_commands }.to output(
761
- [
762
- "",
763
- "Commands:",
764
- " command-name-1",
765
- " command-name-2",
766
- " help",
767
- ""
768
- ].join($/)
769
- ).to_stdout
770
- end
771
- end
772
-
773
- context "when the commands have summaries" do
774
- let(:command_class) { TestCommands::TestCommandsWithExplicitSummaries }
775
-
776
- it "must print the command names and their summaries" do
777
- expect { subject.help_commands }.to output(
778
- [
779
- "",
780
- "Commands:",
781
- " help",
782
- " test1\t#{command_class.commands['test1'].summary}",
783
- " test2\t#{command_class.commands['test2'].summary}",
784
- ""
785
- ].join($/)
786
- ).to_stdout
787
- end
788
- end
789
- end
790
-
791
- describe "#help" do
792
- it "must print the list of available commands after other help output" do
793
- expect { subject.help }.to output(
794
- [
795
- "Usage: #{subject.command_name} [options] [COMMAND [ARGS...]]",
796
- "",
797
- "Options:",
798
- " -h, --help Print help information",
799
- "",
800
- "Arguments:",
801
- " [COMMAND] The command name to run",
802
- " [ARGS ...] Additional arguments for the command",
803
- "",
804
- "Commands:",
805
- " help",
806
- " test1",
807
- " test2",
808
- ""
809
- ].join($/)
810
- ).to_stdout
811
- end
812
-
813
- context "when the command has command alises" do
814
- let(:command_class) { TestCommands::TestCommandsWithAliases }
815
-
816
- it "must print the command names, along with their command aliases" do
817
- expect { subject.help }.to output(
818
- [
819
- "Usage: #{subject.command_name} [options] [COMMAND [ARGS...]]",
820
- "",
821
- "Options:",
822
- " -h, --help Print help information",
823
- "",
824
- "Arguments:",
825
- " [COMMAND] The command name to run",
826
- " [ARGS ...] Additional arguments for the command",
827
- "",
828
- "Commands:",
829
- " help",
830
- " test1, t1",
831
- " test2, t2",
832
- ""
833
- ].join($/)
834
- ).to_stdout
835
- end
836
- end
837
-
838
- context "when the command defines additional global options" do
839
- let(:command_class) { TestCommands::TestCommandsWithGlobalOptions }
840
-
841
- it "must print any global options" do
842
- expect { subject.help }.to output(
843
- [
844
- "Usage: #{subject.command_name} [options] [COMMAND [ARGS...]]",
845
- "",
846
- "Options:",
847
- " -f, --foo Global --foo option",
848
- " -b, --bar BAR Global --bar option",
849
- " -h, --help Print help information",
850
- "",
851
- "Arguments:",
852
- " [COMMAND] The command name to run",
853
- " [ARGS ...] Additional arguments for the command",
854
- "",
855
- "Commands:",
856
- " help",
857
- " test1",
858
- " test2",
859
- ""
860
- ].join($/)
861
- ).to_stdout
862
- end
863
- end
864
- end
865
- end