command_mapper 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/spec/commnad_spec.rb CHANGED
@@ -7,10 +7,17 @@ describe CommandMapper::Command do
7
7
  command 'foo'
8
8
  end
9
9
 
10
+ class InheritedCommandName < WithCommandName
11
+ end
12
+
10
13
  class NoCommandName < CommandMapper::Command
11
14
  end
12
15
  end
13
16
 
17
+ it "must include Types" do
18
+ expect(command_class).to include(CommandMapper::Types)
19
+ end
20
+
14
21
  describe ".command_name" do
15
22
  subject { command_class }
16
23
 
@@ -47,6 +54,14 @@ describe CommandMapper::Command do
47
54
  expect(subject.command_name).to eq('foo')
48
55
  end
49
56
  end
57
+
58
+ context "when the command class inherits from another command class" do
59
+ let(:command_class) { TestCommand::InheritedCommandName }
60
+
61
+ it "must check the superclass" do
62
+ expect(subject.command_name).to eq("foo")
63
+ end
64
+ end
50
65
  end
51
66
 
52
67
  module TestCommand
@@ -54,6 +69,20 @@ describe CommandMapper::Command do
54
69
  end
55
70
  end
56
71
 
72
+ module TestCommand
73
+ class BaseClassWithOptions < CommandMapper::Command
74
+ option "--foo"
75
+ option "--bar"
76
+ end
77
+
78
+ class InheritedOptions < BaseClassWithOptions
79
+ end
80
+
81
+ class InheritsAndDefinesOptions < BaseClassWithOptions
82
+ option "--baz"
83
+ end
84
+ end
85
+
57
86
  describe ".options" do
58
87
  subject { command_class }
59
88
 
@@ -64,16 +93,6 @@ describe CommandMapper::Command do
64
93
  end
65
94
 
66
95
  context "and when the command inherits from another command class" do
67
- module TestCommand
68
- class BaseClassWithOptions < CommandMapper::Command
69
- option "--foo"
70
- option "--bar"
71
- end
72
-
73
- class InheritedOptions < BaseClassWithOptions
74
- end
75
- end
76
-
77
96
  let(:command_class) { TestCommand::InheritedOptions }
78
97
  let(:command_superclass) { TestCommand::BaseClassWithOptions }
79
98
 
@@ -82,12 +101,6 @@ describe CommandMapper::Command do
82
101
  end
83
102
 
84
103
  context "and when the class defines options of it's own" do
85
- module TestCommand
86
- class InheritsAndDefinesOptions < BaseClassWithOptions
87
- option "--baz"
88
- end
89
- end
90
-
91
104
  let(:command_class) { TestCommand::InheritsAndDefinesOptions }
92
105
 
93
106
  it "must copy the options defined in the superclass" do
@@ -105,6 +118,38 @@ describe CommandMapper::Command do
105
118
  end
106
119
  end
107
120
 
121
+ describe ".has_option?" do
122
+ subject { command_class }
123
+
124
+ let(:name) { :bar }
125
+
126
+ context "when the command has no defined options" do
127
+ let(:command_class) { TestCommand::EmptyCommand }
128
+
129
+ it "must return false" do
130
+ expect(subject.has_option?(name)).to be(false)
131
+ end
132
+ end
133
+
134
+ context "when the command does have defined options" do
135
+ let(:command_class) { TestCommand::BaseClassWithOptions }
136
+
137
+ context "and has the option with the given name" do
138
+ it "must return true" do
139
+ expect(subject.has_option?(name)).to be(true)
140
+ end
141
+ end
142
+
143
+ context "but does not have the option with the given name" do
144
+ let(:name) { :xxx }
145
+
146
+ it "must return false" do
147
+ expect(subject.has_option?(name)).to be(false)
148
+ end
149
+ end
150
+ end
151
+ end
152
+
108
153
  describe ".option" do
109
154
  module TestCommand
110
155
  class DefinesItsOwnOptions < CommandMapper::Command
@@ -227,6 +272,55 @@ describe CommandMapper::Command do
227
272
  }.to raise_error(ArgumentError,"option #{flag.inspect} maps to method name ##{name} and cannot override the internal method with same name: ##{name}")
228
273
  end
229
274
  end
275
+
276
+ context "when the option name conflicts with another defined argument" do
277
+ let(:command_class) do
278
+ Class.new(described_class) do
279
+ argument :foo
280
+ end
281
+ end
282
+
283
+ let(:flag) { "--foo" }
284
+ let(:name) { :foo }
285
+
286
+ it do
287
+ expect {
288
+ subject.option(flag)
289
+ }.to raise_error(ArgumentError,"option #{flag.inspect} with name #{name.inspect} conflicts with another argument with the same name")
290
+ end
291
+ end
292
+
293
+ context "when the option name conflicts with another defined subcommand" do
294
+ let(:command_class) do
295
+ Class.new(described_class) do
296
+ subcommand 'foo' do
297
+ end
298
+ end
299
+ end
300
+
301
+ let(:flag) { "--foo" }
302
+ let(:name) { :foo }
303
+
304
+ it do
305
+ expect {
306
+ subject.option(flag)
307
+ }.to raise_error(ArgumentError,"option #{flag.inspect} with name #{name.inspect} conflicts with another subcommand with the same name")
308
+ end
309
+ end
310
+ end
311
+
312
+ module TestCommand
313
+ class BaseClassWithArguments < CommandMapper::Command
314
+ argument :foo
315
+ argument :bar
316
+ end
317
+
318
+ class InheritedArguments < BaseClassWithArguments
319
+ end
320
+
321
+ class InheritsAndDefinesArguments < BaseClassWithArguments
322
+ argument :baz
323
+ end
230
324
  end
231
325
 
232
326
  describe ".arguments" do
@@ -239,31 +333,15 @@ describe CommandMapper::Command do
239
333
  end
240
334
 
241
335
  context "when the comand does have defined arguments" do
242
- module TestCommand
243
- class BaseClassWithOptions < CommandMapper::Command
244
- argument :foo
245
- argument :bar
246
- end
247
-
248
- class InheritedOptions < BaseClassWithOptions
249
- end
250
- end
251
-
252
- let(:command_class) { TestCommand::InheritedOptions }
253
- let(:command_superclass) { TestCommand::BaseClassWithOptions }
336
+ let(:command_class) { TestCommand::InheritedArguments }
337
+ let(:command_superclass) { TestCommand::BaseClassWithArguments }
254
338
 
255
339
  it "must copy the arguments defined in the superclass" do
256
340
  expect(subject.arguments).to eq(command_superclass.arguments)
257
341
  end
258
342
 
259
343
  context "and when the class defines arguments of it's own" do
260
- module TestCommand
261
- class InheritsAndDefinesOptions < BaseClassWithOptions
262
- argument :baz
263
- end
264
- end
265
-
266
- let(:command_class) { TestCommand::InheritsAndDefinesOptions }
344
+ let(:command_class) { TestCommand::InheritsAndDefinesArguments }
267
345
 
268
346
  it "must copy the arguments defined in the superclass" do
269
347
  expect(subject.arguments).to include(command_superclass.arguments)
@@ -280,6 +358,38 @@ describe CommandMapper::Command do
280
358
  end
281
359
  end
282
360
 
361
+ describe ".has_argument?" do
362
+ subject { command_class }
363
+
364
+ let(:name) { :bar }
365
+
366
+ context "when the command has no defined arguments" do
367
+ let(:command_class) { TestCommand::EmptyCommand }
368
+
369
+ it "must return false" do
370
+ expect(subject.has_argument?(name)).to be(false)
371
+ end
372
+ end
373
+
374
+ context "when the command does have defined arguments" do
375
+ let(:command_class) { TestCommand::BaseClassWithArguments }
376
+
377
+ context "and has the argument with the given name" do
378
+ it "must return true" do
379
+ expect(subject.has_argument?(name)).to be(true)
380
+ end
381
+ end
382
+
383
+ context "but does not have the argument with the given name" do
384
+ let(:name) { :xxx }
385
+
386
+ it "must return false" do
387
+ expect(subject.has_argument?(name)).to be(false)
388
+ end
389
+ end
390
+ end
391
+ end
392
+
283
393
  describe ".argument" do
284
394
  module TestCommand
285
395
  class DefinesArgument < CommandMapper::Command
@@ -342,6 +452,59 @@ describe CommandMapper::Command do
342
452
  }.to raise_error(ArgumentError,"argument #{name.inspect} cannot override internal method with same name: ##{name}")
343
453
  end
344
454
  end
455
+
456
+ context "when the argument name conflicts with another defined option" do
457
+ let(:command_class) do
458
+ Class.new(described_class) do
459
+ option '--foo'
460
+ end
461
+ end
462
+
463
+ let(:name) { :foo }
464
+
465
+ it do
466
+ expect {
467
+ subject.argument(name)
468
+ }.to raise_error(ArgumentError,"argument #{name.inspect} conflicts with another option with the same name")
469
+ end
470
+ end
471
+
472
+ context "when the argument name conflicts with another defined subcommand" do
473
+ let(:command_class) do
474
+ Class.new(described_class) do
475
+ subcommand 'foo' do
476
+ end
477
+ end
478
+ end
479
+
480
+ let(:name) { :foo }
481
+
482
+ it do
483
+ expect {
484
+ subject.argument(name)
485
+ }.to raise_error(ArgumentError,"argument #{name.inspect} conflicts with another subcommand with the same name")
486
+ end
487
+ end
488
+ end
489
+
490
+ module TestCommand
491
+ class BaseClassWithSubcommands < CommandMapper::Command
492
+ subcommand :foo do
493
+ end
494
+
495
+ subcommand :bar do
496
+ end
497
+ end
498
+
499
+ class InheritedSubcommands < BaseClassWithSubcommands
500
+ end
501
+
502
+ class InheritsAndDefinesSubcommands < BaseClassWithSubcommands
503
+
504
+ subcommand :baz do
505
+ end
506
+
507
+ end
345
508
  end
346
509
 
347
510
  describe ".subcommands" do
@@ -354,37 +517,15 @@ describe CommandMapper::Command do
354
517
  end
355
518
 
356
519
  context "when the comand does have defined subcommands" do
357
- module TestCommand
358
- class BaseClassWithOptions < CommandMapper::Command
359
- subcommand :foo do
360
- end
361
-
362
- subcommand :bar do
363
- end
364
- end
365
-
366
- class InheritedOptions < BaseClassWithOptions
367
- end
368
- end
369
-
370
- let(:command_class) { TestCommand::InheritedOptions }
371
- let(:command_superclass) { TestCommand::BaseClassWithOptions }
520
+ let(:command_class) { TestCommand::InheritedSubcommands }
521
+ let(:command_superclass) { TestCommand::BaseClassWithSubcommands }
372
522
 
373
523
  it "must copy the subcommands defined in the superclass" do
374
524
  expect(subject.subcommands).to eq(command_superclass.subcommands)
375
525
  end
376
526
 
377
527
  context "and when the class defines subcommands of it's own" do
378
- module TestCommand
379
- class InheritsAndDefinesOptions < BaseClassWithOptions
380
-
381
- subcommand :baz do
382
- end
383
-
384
- end
385
- end
386
-
387
- let(:command_class) { TestCommand::InheritsAndDefinesOptions }
528
+ let(:command_class) { TestCommand::InheritsAndDefinesSubcommands }
388
529
 
389
530
  it "must copy the subcommands defined in the superclass" do
390
531
  expect(subject.subcommands).to include(command_superclass.subcommands)
@@ -401,6 +542,38 @@ describe CommandMapper::Command do
401
542
  end
402
543
  end
403
544
 
545
+ describe ".has_subcommand?" do
546
+ subject { command_class }
547
+
548
+ let(:name) { :bar }
549
+
550
+ context "when the command has no defined subcommands" do
551
+ let(:command_class) { TestCommand::EmptyCommand }
552
+
553
+ it "must return false" do
554
+ expect(subject.has_subcommand?(name)).to be(false)
555
+ end
556
+ end
557
+
558
+ context "when the command does have defined subcommands" do
559
+ let(:command_class) { TestCommand::BaseClassWithSubcommands }
560
+
561
+ context "and has the subcommand with the given name" do
562
+ it "must return true" do
563
+ expect(subject.has_subcommand?(name)).to be(true)
564
+ end
565
+ end
566
+
567
+ context "but does not have the subcommand with the given name" do
568
+ let(:name) { :xxx }
569
+
570
+ it "must return false" do
571
+ expect(subject.has_subcommand?(name)).to be(false)
572
+ end
573
+ end
574
+ end
575
+ end
576
+
404
577
  describe ".subcommand" do
405
578
  module TestCommand
406
579
  class DefinesSubcommand < CommandMapper::Command
@@ -552,11 +725,45 @@ describe CommandMapper::Command do
552
725
 
553
726
  it do
554
727
  expect {
555
- command_class.subcommand(name) do
728
+ subject.subcommand(name) do
556
729
  end
557
730
  }.to raise_error(ArgumentError,"subcommand #{name.inspect} maps to method name ##{method_name} and cannot override the internal method with same name: ##{method_name}")
558
731
  end
559
732
  end
733
+
734
+ context "when the subcommand name conflicts with another defined option" do
735
+ let(:command_class) do
736
+ Class.new(described_class) do
737
+ option '--foo'
738
+ end
739
+ end
740
+
741
+ let(:name) { 'foo' }
742
+
743
+ it do
744
+ expect {
745
+ subject.subcommand(name) do
746
+ end
747
+ }.to raise_error(ArgumentError,"subcommand #{name.inspect} conflicts with another option with the same name")
748
+ end
749
+ end
750
+
751
+ context "when the subcommand name conflicts with another defined argument" do
752
+ let(:command_class) do
753
+ Class.new(described_class) do
754
+ argument :foo
755
+ end
756
+ end
757
+
758
+ let(:name) { 'foo' }
759
+
760
+ it do
761
+ expect {
762
+ subject.subcommand(name) do
763
+ end
764
+ }.to raise_error(ArgumentError,"subcommand #{name.inspect} conflicts with another argument with the same name")
765
+ end
766
+ end
560
767
  end
561
768
 
562
769
  module TestCommand
@@ -600,8 +807,8 @@ describe CommandMapper::Command do
600
807
  {opt1: opt1, arg1: arg1}
601
808
  end
602
809
 
603
- it "must initialize a new command with the Hash of params and call #run" do
604
- if RUBY_VERSION < '3.'
810
+ it "must initialize a new command with the Hash of params and call #run_command" do
811
+ if RUBY_VERSION < '3.' || RUBY_ENGINE == 'truffleruby'
605
812
  expect(subject).to receive(:new).with({},params).and_return(command_instance)
606
813
  else
607
814
  expect(subject).to receive(:new).with(params).and_return(command_instance)
@@ -618,7 +825,7 @@ describe CommandMapper::Command do
618
825
  {opt1: opt1, arg1: arg1}
619
826
  end
620
827
 
621
- it "must initialize a new command with the keyword arguments and call #run" do
828
+ it "must initialize a new command with the keyword arguments and call #run_command" do
622
829
  expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance)
623
830
  expect(command_instance).to receive(:run_command).and_return(return_value)
624
831
 
@@ -627,6 +834,44 @@ describe CommandMapper::Command do
627
834
  end
628
835
  end
629
836
 
837
+ describe ".spawn" do
838
+ let(:command_instance) { double(:command_instance) }
839
+ let(:return_value) { double(:boolean) }
840
+
841
+ subject { command_class }
842
+
843
+ context "when called with a Hash of params" do
844
+ let(:params) do
845
+ {opt1: opt1, arg1: arg1}
846
+ end
847
+
848
+ it "must initialize a new command with the Hash of params and call #spawn_command" do
849
+ if RUBY_VERSION < '3.' || RUBY_ENGINE == 'truffleruby'
850
+ expect(subject).to receive(:new).with({},params).and_return(command_instance)
851
+ else
852
+ expect(subject).to receive(:new).with(params).and_return(command_instance)
853
+ end
854
+
855
+ expect(command_instance).to receive(:spawn_command).and_return(return_value)
856
+
857
+ expect(subject.spawn(params)).to be(return_value)
858
+ end
859
+ end
860
+
861
+ context "when called with keyword aguments" do
862
+ let(:kwargs) do
863
+ {opt1: opt1, arg1: arg1}
864
+ end
865
+
866
+ it "must initialize a new command with the keyword arguments and call #spawn_command" do
867
+ expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance)
868
+ expect(command_instance).to receive(:spawn_command).and_return(return_value)
869
+
870
+ expect(subject.spawn(**kwargs)).to be(return_value)
871
+ end
872
+ end
873
+ end
874
+
630
875
  describe ".capture" do
631
876
  let(:command_instance) { double(:command_instance) }
632
877
  let(:return_value) { double(:string) }
@@ -638,8 +883,8 @@ describe CommandMapper::Command do
638
883
  {opt1: opt1, arg1: arg1}
639
884
  end
640
885
 
641
- it "must initialize a new command with the Hash of params and call #capture" do
642
- if RUBY_VERSION < '3.'
886
+ it "must initialize a new command with the Hash of params and call #capture_command" do
887
+ if RUBY_VERSION < '3.' || RUBY_ENGINE == 'truffleruby'
643
888
  expect(subject).to receive(:new).with({},params).and_return(command_instance)
644
889
  else
645
890
  expect(subject).to receive(:new).with(params).and_return(command_instance)
@@ -656,7 +901,7 @@ describe CommandMapper::Command do
656
901
  {opt1: opt1, arg1: arg1}
657
902
  end
658
903
 
659
- it "must initialize a new command with the keyword arguments and call #capture" do
904
+ it "must initialize a new command with the keyword arguments and call #capture_command" do
660
905
  expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance)
661
906
  expect(command_instance).to receive(:capture_command).and_return(return_value)
662
907
 
@@ -676,8 +921,8 @@ describe CommandMapper::Command do
676
921
  {opt1: opt1, arg1: arg1}
677
922
  end
678
923
 
679
- it "must initialize a new command with the Hash of params and call #popen" do
680
- if RUBY_VERSION < '3.'
924
+ it "must initialize a new command with the Hash of params and call #popen_command" do
925
+ if RUBY_VERSION < '3.' || RUBY_ENGINE == 'truffleruby'
681
926
  expect(subject).to receive(:new).with({},params).and_return(command_instance)
682
927
  else
683
928
  expect(subject).to receive(:new).with(params).and_return(command_instance)
@@ -694,7 +939,7 @@ describe CommandMapper::Command do
694
939
  {opt1: opt1, arg1: arg1}
695
940
  end
696
941
 
697
- it "must initialize a new command with the keyword arguments and call #popen" do
942
+ it "must initialize a new command with the keyword arguments and call #popen_command" do
698
943
  expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance)
699
944
  expect(command_instance).to receive(:popen_command).and_return(return_value)
700
945
 
@@ -714,8 +959,8 @@ describe CommandMapper::Command do
714
959
  {opt1: opt1, arg1: arg1}
715
960
  end
716
961
 
717
- it "must initialize a new command with the Hash of params and call #sudo" do
718
- if RUBY_VERSION < '3.'
962
+ it "must initialize a new command with the Hash of params and call #sudo_command" do
963
+ if RUBY_VERSION < '3.' || RUBY_ENGINE == 'truffleruby'
719
964
  expect(subject).to receive(:new).with({},params).and_return(command_instance)
720
965
  else
721
966
  expect(subject).to receive(:new).with(params).and_return(command_instance)
@@ -732,7 +977,7 @@ describe CommandMapper::Command do
732
977
  {opt1: opt1, arg1: arg1}
733
978
  end
734
979
 
735
- it "must initialize a new command with the keyword arguments and call #sudo" do
980
+ it "must initialize a new command with the keyword arguments and call #sudo_command" do
736
981
  expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance)
737
982
  expect(command_instance).to receive(:sudo_command).and_return(return_value)
738
983
 
@@ -1105,12 +1350,22 @@ describe CommandMapper::Command do
1105
1350
  subject { command_class.new({opt1: opt1, arg1: arg1}, command_env: env) }
1106
1351
 
1107
1352
  it "must pass the command's env and argv to Kenrel.system" do
1108
- expect(subject).to receive(:system).with(env,*subject.command_argv)
1353
+ expect(Kernel).to receive(:system).with(env,*subject.command_argv)
1109
1354
 
1110
1355
  subject.run_command
1111
1356
  end
1112
1357
  end
1113
1358
 
1359
+ describe "#spawn_command" do
1360
+ subject { command_class.new({opt1: opt1, arg1: arg1}, command_env: env) }
1361
+
1362
+ it "must pass the command's env and argv to Kenrel.system" do
1363
+ expect(Process).to receive(:spawn).with(env,*subject.command_argv)
1364
+
1365
+ subject.spawn_command
1366
+ end
1367
+ end
1368
+
1114
1369
  describe "#capture_command" do
1115
1370
  subject { command_class.new({opt1: opt1, arg1: arg1}, command_env: env) }
1116
1371