command_mapper 0.1.2 → 0.2.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.
data/spec/commnad_spec.rb CHANGED
@@ -69,6 +69,20 @@ describe CommandMapper::Command do
69
69
  end
70
70
  end
71
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
+
72
86
  describe ".options" do
73
87
  subject { command_class }
74
88
 
@@ -79,16 +93,6 @@ describe CommandMapper::Command do
79
93
  end
80
94
 
81
95
  context "and when the command inherits from another command class" do
82
- module TestCommand
83
- class BaseClassWithOptions < CommandMapper::Command
84
- option "--foo"
85
- option "--bar"
86
- end
87
-
88
- class InheritedOptions < BaseClassWithOptions
89
- end
90
- end
91
-
92
96
  let(:command_class) { TestCommand::InheritedOptions }
93
97
  let(:command_superclass) { TestCommand::BaseClassWithOptions }
94
98
 
@@ -97,12 +101,6 @@ describe CommandMapper::Command do
97
101
  end
98
102
 
99
103
  context "and when the class defines options of it's own" do
100
- module TestCommand
101
- class InheritsAndDefinesOptions < BaseClassWithOptions
102
- option "--baz"
103
- end
104
- end
105
-
106
104
  let(:command_class) { TestCommand::InheritsAndDefinesOptions }
107
105
 
108
106
  it "must copy the options defined in the superclass" do
@@ -120,6 +118,38 @@ describe CommandMapper::Command do
120
118
  end
121
119
  end
122
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
+
123
153
  describe ".option" do
124
154
  module TestCommand
125
155
  class DefinesItsOwnOptions < CommandMapper::Command
@@ -242,6 +272,55 @@ describe CommandMapper::Command do
242
272
  }.to raise_error(ArgumentError,"option #{flag.inspect} maps to method name ##{name} and cannot override the internal method with same name: ##{name}")
243
273
  end
244
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
245
324
  end
246
325
 
247
326
  describe ".arguments" do
@@ -254,31 +333,15 @@ describe CommandMapper::Command do
254
333
  end
255
334
 
256
335
  context "when the comand does have defined arguments" do
257
- module TestCommand
258
- class BaseClassWithOptions < CommandMapper::Command
259
- argument :foo
260
- argument :bar
261
- end
262
-
263
- class InheritedOptions < BaseClassWithOptions
264
- end
265
- end
266
-
267
- let(:command_class) { TestCommand::InheritedOptions }
268
- let(:command_superclass) { TestCommand::BaseClassWithOptions }
336
+ let(:command_class) { TestCommand::InheritedArguments }
337
+ let(:command_superclass) { TestCommand::BaseClassWithArguments }
269
338
 
270
339
  it "must copy the arguments defined in the superclass" do
271
340
  expect(subject.arguments).to eq(command_superclass.arguments)
272
341
  end
273
342
 
274
343
  context "and when the class defines arguments of it's own" do
275
- module TestCommand
276
- class InheritsAndDefinesOptions < BaseClassWithOptions
277
- argument :baz
278
- end
279
- end
280
-
281
- let(:command_class) { TestCommand::InheritsAndDefinesOptions }
344
+ let(:command_class) { TestCommand::InheritsAndDefinesArguments }
282
345
 
283
346
  it "must copy the arguments defined in the superclass" do
284
347
  expect(subject.arguments).to include(command_superclass.arguments)
@@ -295,6 +358,38 @@ describe CommandMapper::Command do
295
358
  end
296
359
  end
297
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
+
298
393
  describe ".argument" do
299
394
  module TestCommand
300
395
  class DefinesArgument < CommandMapper::Command
@@ -357,6 +452,59 @@ describe CommandMapper::Command do
357
452
  }.to raise_error(ArgumentError,"argument #{name.inspect} cannot override internal method with same name: ##{name}")
358
453
  end
359
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
360
508
  end
361
509
 
362
510
  describe ".subcommands" do
@@ -369,37 +517,15 @@ describe CommandMapper::Command do
369
517
  end
370
518
 
371
519
  context "when the comand does have defined subcommands" do
372
- module TestCommand
373
- class BaseClassWithOptions < CommandMapper::Command
374
- subcommand :foo do
375
- end
376
-
377
- subcommand :bar do
378
- end
379
- end
380
-
381
- class InheritedOptions < BaseClassWithOptions
382
- end
383
- end
384
-
385
- let(:command_class) { TestCommand::InheritedOptions }
386
- let(:command_superclass) { TestCommand::BaseClassWithOptions }
520
+ let(:command_class) { TestCommand::InheritedSubcommands }
521
+ let(:command_superclass) { TestCommand::BaseClassWithSubcommands }
387
522
 
388
523
  it "must copy the subcommands defined in the superclass" do
389
524
  expect(subject.subcommands).to eq(command_superclass.subcommands)
390
525
  end
391
526
 
392
527
  context "and when the class defines subcommands of it's own" do
393
- module TestCommand
394
- class InheritsAndDefinesOptions < BaseClassWithOptions
395
-
396
- subcommand :baz do
397
- end
398
-
399
- end
400
- end
401
-
402
- let(:command_class) { TestCommand::InheritsAndDefinesOptions }
528
+ let(:command_class) { TestCommand::InheritsAndDefinesSubcommands }
403
529
 
404
530
  it "must copy the subcommands defined in the superclass" do
405
531
  expect(subject.subcommands).to include(command_superclass.subcommands)
@@ -416,6 +542,38 @@ describe CommandMapper::Command do
416
542
  end
417
543
  end
418
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
+
419
577
  describe ".subcommand" do
420
578
  module TestCommand
421
579
  class DefinesSubcommand < CommandMapper::Command
@@ -567,11 +725,45 @@ describe CommandMapper::Command do
567
725
 
568
726
  it do
569
727
  expect {
570
- command_class.subcommand(name) do
728
+ subject.subcommand(name) do
571
729
  end
572
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}")
573
731
  end
574
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
575
767
  end
576
768
 
577
769
  module TestCommand
@@ -615,8 +807,8 @@ describe CommandMapper::Command do
615
807
  {opt1: opt1, arg1: arg1}
616
808
  end
617
809
 
618
- it "must initialize a new command with the Hash of params and call #run" do
619
- 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'
620
812
  expect(subject).to receive(:new).with({},params).and_return(command_instance)
621
813
  else
622
814
  expect(subject).to receive(:new).with(params).and_return(command_instance)
@@ -633,7 +825,7 @@ describe CommandMapper::Command do
633
825
  {opt1: opt1, arg1: arg1}
634
826
  end
635
827
 
636
- 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
637
829
  expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance)
638
830
  expect(command_instance).to receive(:run_command).and_return(return_value)
639
831
 
@@ -642,6 +834,44 @@ describe CommandMapper::Command do
642
834
  end
643
835
  end
644
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
+
645
875
  describe ".capture" do
646
876
  let(:command_instance) { double(:command_instance) }
647
877
  let(:return_value) { double(:string) }
@@ -653,8 +883,8 @@ describe CommandMapper::Command do
653
883
  {opt1: opt1, arg1: arg1}
654
884
  end
655
885
 
656
- it "must initialize a new command with the Hash of params and call #capture" do
657
- 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'
658
888
  expect(subject).to receive(:new).with({},params).and_return(command_instance)
659
889
  else
660
890
  expect(subject).to receive(:new).with(params).and_return(command_instance)
@@ -671,7 +901,7 @@ describe CommandMapper::Command do
671
901
  {opt1: opt1, arg1: arg1}
672
902
  end
673
903
 
674
- 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
675
905
  expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance)
676
906
  expect(command_instance).to receive(:capture_command).and_return(return_value)
677
907
 
@@ -691,8 +921,8 @@ describe CommandMapper::Command do
691
921
  {opt1: opt1, arg1: arg1}
692
922
  end
693
923
 
694
- it "must initialize a new command with the Hash of params and call #popen" do
695
- 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'
696
926
  expect(subject).to receive(:new).with({},params).and_return(command_instance)
697
927
  else
698
928
  expect(subject).to receive(:new).with(params).and_return(command_instance)
@@ -709,7 +939,7 @@ describe CommandMapper::Command do
709
939
  {opt1: opt1, arg1: arg1}
710
940
  end
711
941
 
712
- 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
713
943
  expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance)
714
944
  expect(command_instance).to receive(:popen_command).and_return(return_value)
715
945
 
@@ -729,8 +959,8 @@ describe CommandMapper::Command do
729
959
  {opt1: opt1, arg1: arg1}
730
960
  end
731
961
 
732
- it "must initialize a new command with the Hash of params and call #sudo" do
733
- 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'
734
964
  expect(subject).to receive(:new).with({},params).and_return(command_instance)
735
965
  else
736
966
  expect(subject).to receive(:new).with(params).and_return(command_instance)
@@ -747,7 +977,7 @@ describe CommandMapper::Command do
747
977
  {opt1: opt1, arg1: arg1}
748
978
  end
749
979
 
750
- 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
751
981
  expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance)
752
982
  expect(command_instance).to receive(:sudo_command).and_return(return_value)
753
983
 
@@ -1120,12 +1350,22 @@ describe CommandMapper::Command do
1120
1350
  subject { command_class.new({opt1: opt1, arg1: arg1}, command_env: env) }
1121
1351
 
1122
1352
  it "must pass the command's env and argv to Kenrel.system" do
1123
- expect(subject).to receive(:system).with(env,*subject.command_argv)
1353
+ expect(Kernel).to receive(:system).with(env,*subject.command_argv)
1124
1354
 
1125
1355
  subject.run_command
1126
1356
  end
1127
1357
  end
1128
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
+
1129
1369
  describe "#capture_command" do
1130
1370
  subject { command_class.new({opt1: opt1, arg1: arg1}, command_env: env) }
1131
1371