command_kit 0.4.1 → 0.5.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 (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