command_kit 0.1.0.pre2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +15 -0
  3. data/.rubocop.yml +141 -0
  4. data/ChangeLog.md +98 -2
  5. data/Gemfile +3 -0
  6. data/README.md +189 -117
  7. data/Rakefile +3 -2
  8. data/command_kit.gemspec +4 -4
  9. data/examples/command.rb +1 -1
  10. data/gemspec.yml +10 -2
  11. data/lib/command_kit/arguments/argument.rb +2 -0
  12. data/lib/command_kit/arguments/argument_value.rb +2 -0
  13. data/lib/command_kit/arguments.rb +23 -4
  14. data/lib/command_kit/colors.rb +253 -45
  15. data/lib/command_kit/command.rb +6 -1
  16. data/lib/command_kit/command_name.rb +9 -0
  17. data/lib/command_kit/commands/auto_load.rb +24 -1
  18. data/lib/command_kit/commands/auto_require.rb +16 -0
  19. data/lib/command_kit/commands/command.rb +3 -0
  20. data/lib/command_kit/commands/help.rb +5 -2
  21. data/lib/command_kit/commands/parent_command.rb +7 -0
  22. data/lib/command_kit/commands/subcommand.rb +13 -1
  23. data/lib/command_kit/commands.rb +54 -9
  24. data/lib/command_kit/description.rb +12 -1
  25. data/lib/command_kit/env/home.rb +9 -0
  26. data/lib/command_kit/env/path.rb +16 -1
  27. data/lib/command_kit/env.rb +4 -0
  28. data/lib/command_kit/examples.rb +12 -1
  29. data/lib/command_kit/exception_handler.rb +4 -0
  30. data/lib/command_kit/help/man.rb +26 -30
  31. data/lib/command_kit/help.rb +7 -1
  32. data/lib/command_kit/inflector.rb +49 -17
  33. data/lib/command_kit/interactive.rb +248 -0
  34. data/lib/command_kit/main.rb +18 -9
  35. data/lib/command_kit/man.rb +44 -0
  36. data/lib/command_kit/open_app.rb +69 -0
  37. data/lib/command_kit/options/option.rb +3 -6
  38. data/lib/command_kit/options/option_value.rb +5 -2
  39. data/lib/command_kit/options/parser.rb +46 -19
  40. data/lib/command_kit/options/quiet.rb +3 -0
  41. data/lib/command_kit/options/verbose.rb +5 -0
  42. data/lib/command_kit/options/version.rb +6 -0
  43. data/lib/command_kit/options.rb +32 -7
  44. data/lib/command_kit/os/linux.rb +157 -0
  45. data/lib/command_kit/os.rb +165 -11
  46. data/lib/command_kit/package_manager.rb +200 -0
  47. data/lib/command_kit/pager.rb +80 -11
  48. data/lib/command_kit/printing/indent.rb +27 -4
  49. data/lib/command_kit/printing.rb +35 -1
  50. data/lib/command_kit/program_name.rb +7 -0
  51. data/lib/command_kit/stdio.rb +24 -0
  52. data/lib/command_kit/sudo.rb +40 -0
  53. data/lib/command_kit/terminal.rb +159 -0
  54. data/lib/command_kit/usage.rb +14 -0
  55. data/lib/command_kit/version.rb +1 -1
  56. data/lib/command_kit/xdg.rb +13 -0
  57. data/lib/command_kit.rb +1 -0
  58. data/spec/arguments/argument_spec.rb +2 -2
  59. data/spec/arguments_spec.rb +53 -27
  60. data/spec/colors_spec.rb +277 -13
  61. data/spec/command_name_spec.rb +1 -1
  62. data/spec/command_spec.rb +79 -5
  63. data/spec/commands/auto_load/subcommand_spec.rb +1 -1
  64. data/spec/commands/auto_load_spec.rb +34 -3
  65. data/spec/commands/auto_require_spec.rb +2 -2
  66. data/spec/commands/help_spec.rb +1 -1
  67. data/spec/commands/parent_command_spec.rb +1 -1
  68. data/spec/commands/subcommand_spec.rb +1 -1
  69. data/spec/commands_spec.rb +103 -29
  70. data/spec/description_spec.rb +1 -25
  71. data/spec/env/home_spec.rb +1 -1
  72. data/spec/env/path_spec.rb +7 -1
  73. data/spec/examples_spec.rb +1 -25
  74. data/spec/exception_handler_spec.rb +1 -1
  75. data/spec/help/man_spec.rb +45 -58
  76. data/spec/help_spec.rb +0 -25
  77. data/spec/inflector_spec.rb +71 -9
  78. data/spec/interactive_spec.rb +415 -0
  79. data/spec/main_spec.rb +7 -7
  80. data/spec/man_spec.rb +46 -0
  81. data/spec/open_app_spec.rb +85 -0
  82. data/spec/options/option_spec.rb +5 -5
  83. data/spec/options/option_value_spec.rb +56 -1
  84. data/spec/options_spec.rb +283 -1
  85. data/spec/os/linux_spec.rb +164 -0
  86. data/spec/os_spec.rb +201 -14
  87. data/spec/package_manager_spec.rb +806 -0
  88. data/spec/pager_spec.rb +76 -11
  89. data/spec/printing/indent_spec.rb +8 -6
  90. data/spec/printing_spec.rb +33 -3
  91. data/spec/program_name_spec.rb +1 -1
  92. data/spec/spec_helper.rb +0 -3
  93. data/spec/sudo_spec.rb +51 -0
  94. data/spec/{console_spec.rb → terminal_spec.rb} +65 -35
  95. data/spec/usage_spec.rb +2 -2
  96. data/spec/xdg_spec.rb +1 -1
  97. metadata +26 -8
  98. data/lib/command_kit/console.rb +0 -141
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'command_kit/commands'
3
3
 
4
- describe Commands do
4
+ describe CommandKit::Commands do
5
5
  module TestCommands
6
6
  class TestEmptyCommands
7
7
 
@@ -126,6 +126,33 @@ describe Commands do
126
126
  command Test2
127
127
 
128
128
  end
129
+
130
+ class TestCommandsWithCommandArguments
131
+
132
+ include CommandKit::Commands
133
+
134
+ class Test1 < CommandKit::Command
135
+ argument :arg1, required: false,
136
+ desc: 'Argument 1'
137
+
138
+ argument :arg2, required: false,
139
+ desc: 'Argument 2'
140
+ end
141
+
142
+ class Test2 < CommandKit::Command
143
+ argument :arg1, required: false,
144
+ desc: 'Argument 1'
145
+
146
+ argument :arg2, required: false,
147
+ desc: 'Argument 2'
148
+ end
149
+
150
+ p method(:command).source_location
151
+ command Test1
152
+ command Test2
153
+
154
+ end
155
+
129
156
  end
130
157
 
131
158
  let(:command_class) { TestCommands::TestCommands }
@@ -191,7 +218,7 @@ describe Commands do
191
218
  it "must contain the mapping of aliases to command names" do
192
219
  expect(subject.command_aliases).to eq({
193
220
  't1' => 'test1',
194
- 't2' => 'test2',
221
+ 't2' => 'test2'
195
222
  })
196
223
  end
197
224
  end
@@ -569,7 +596,7 @@ describe Commands do
569
596
  expect(subject).to receive(:exit).with(1)
570
597
 
571
598
  expect { subject.command_not_found(unknown_command) }.to output(
572
- "'#{unknown_command}' is not a #{subject.command_name} command. See `#{subject.command_name} help`" + $/
599
+ "#{subject.command_name}: '#{unknown_command}' is not a #{subject.command_name} command. See `#{subject.command_name} help`" + $/
573
600
  ).to_stderr
574
601
  end
575
602
  end
@@ -582,6 +609,44 @@ describe Commands do
582
609
  end
583
610
  end
584
611
 
612
+ describe "#option_parser" do
613
+ let(:command_name) { 'test1' }
614
+ let(:command_argv) { %w[foo bar baz] }
615
+ let(:argv) { [command_name, *command_argv] }
616
+
617
+ it "must stop before the first non-option argument" do
618
+ expect(subject.option_parser.parse(argv)).to eq(
619
+ [command_name, *command_argv]
620
+ )
621
+ end
622
+
623
+ context "when an unknown command name is given" do
624
+ let(:command_argv) { %w[bar baz] }
625
+ let(:argv) { ['foo', command_name, *command_argv] }
626
+
627
+ it "must stop before the first non-option argument" do
628
+ expect(subject.option_parser.parse(argv)).to eq(argv)
629
+ end
630
+ end
631
+
632
+ context "when additional global options are defined" do
633
+ let(:command_class) { TestCommands::TestCommandsWithGlobalOptions }
634
+ let(:bar) { '2' }
635
+ let(:argv) do
636
+ ['--foo', '--bar', bar.to_s, command_name, *command_argv]
637
+ end
638
+
639
+ it "must parse the global options, but stop before the first non-option associated argument" do
640
+ expect(subject.option_parser.parse(argv)).to eq(
641
+ [command_name, *command_argv]
642
+ )
643
+
644
+ expect(subject.options[:foo]).to be(true)
645
+ expect(subject.options[:bar]).to eq(bar)
646
+ end
647
+ end
648
+ end
649
+
585
650
  describe "#run" do
586
651
  context "when a command name is the first argument" do
587
652
  let(:command) { 'test1' }
@@ -607,48 +672,45 @@ describe Commands do
607
672
  end
608
673
 
609
674
  context "when given no arguments" do
610
- it "must default to calling #help" do
675
+ let(:exit_status) { 1 }
676
+
677
+ it "must default to calling #help and exit with 1" do
611
678
  expect(subject).to receive(:help)
679
+ expect(subject).to receive(:exit).with(exit_status)
612
680
 
613
681
  subject.run()
614
682
  end
615
683
  end
616
684
  end
617
685
 
618
- describe "#option_parser" do
619
- let(:command_name) { 'test1' }
620
- let(:command_argv) { %w[foo bar baz] }
621
- let(:argv) { [command_name, *command_argv] }
686
+ describe "#main" do
687
+ let(:command_class) { TestCommands::TestCommandsWithCommandArguments }
622
688
 
623
- it "must stop before the first non-option argument" do
624
- expect(subject.option_parser.parse(argv)).to eq(
625
- [command_name, *command_argv]
626
- )
689
+ context "when a command name is the first argument" do
690
+ let(:command) { 'test1' }
691
+ let(:argv) { [command] }
692
+
693
+ it "must return 0" do
694
+ expect(subject.main(argv)).to eq(0)
695
+ end
627
696
  end
628
697
 
629
- context "when an unknown command name is given" do
630
- let(:command_argv) { %w[bar baz] }
631
- let(:argv) { ['foo', command_name, *command_argv] }
698
+ context "when given additional command arguments" do
699
+ let(:argv) { %w[test1 arg1 arg2] }
632
700
 
633
- it "must stop before the first non-option argument" do
634
- expect(subject.option_parser.parse(argv)).to eq(argv)
701
+ it "must pass them to the command" do
702
+ expect(subject.main(argv)).to eq(0)
635
703
  end
636
704
  end
637
705
 
638
- context "when additional global options are defined" do
639
- let(:command_class) { TestCommands::TestCommandsWithGlobalOptions }
640
- let(:bar) { '2' }
641
- let(:argv) do
642
- ['--foo', '--bar', bar.to_s, command_name, *command_argv]
643
- end
706
+ context "when given no arguments" do
707
+ let(:exit_status) { 1 }
708
+ let(:argv) { %w[] }
644
709
 
645
- it "must parse the global options, but stop before the first non-option associated argument" do
646
- expect(subject.option_parser.parse(argv)).to eq(
647
- [command_name, *command_argv]
648
- )
710
+ it "must call #help and return 1" do
711
+ expect(subject).to receive(:help)
649
712
 
650
- expect(subject.options[:foo]).to be(true)
651
- expect(subject.options[:bar]).to eq(bar)
713
+ expect(subject.main(argv)).to eq(exit_status)
652
714
  end
653
715
  end
654
716
  end
@@ -711,6 +773,10 @@ describe Commands do
711
773
  "Options:",
712
774
  " -h, --help Print help information",
713
775
  "",
776
+ "Arguments:",
777
+ " [COMMAND] The command name to run",
778
+ " [ARGS ...] Additional arguments for the command",
779
+ "",
714
780
  "Commands:",
715
781
  " help",
716
782
  " test1",
@@ -731,6 +797,10 @@ describe Commands do
731
797
  "Options:",
732
798
  " -h, --help Print help information",
733
799
  "",
800
+ "Arguments:",
801
+ " [COMMAND] The command name to run",
802
+ " [ARGS ...] Additional arguments for the command",
803
+ "",
734
804
  "Commands:",
735
805
  " help",
736
806
  " test1, t1",
@@ -754,6 +824,10 @@ describe Commands do
754
824
  " -b, --bar BAR Global --bar option",
755
825
  " -h, --help Print help information",
756
826
  "",
827
+ "Arguments:",
828
+ " [COMMAND] The command name to run",
829
+ " [ARGS ...] Additional arguments for the command",
830
+ "",
757
831
  "Commands:",
758
832
  " help",
759
833
  " test1",
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'command_kit/description'
3
3
 
4
- describe Description do
4
+ describe CommandKit::Description do
5
5
  module TestDescription
6
6
  class ImplicitCmd
7
7
  include CommandKit::Description
@@ -175,29 +175,5 @@ describe Description do
175
175
 
176
176
  subject.help
177
177
  end
178
-
179
- context "when the superclass defines it's own #help method" do
180
- module TestDescription
181
- class SuperclassHelpMethod
182
- def help
183
- puts 'superclass'
184
- end
185
- end
186
-
187
- class InheritedHelpMethod < SuperclassHelpMethod
188
- include CommandKit::Description
189
- end
190
- end
191
-
192
- let(:super_command_class) { TestDescription::SuperclassHelpMethod }
193
- let(:command_class) { TestDescription::InheritedHelpMethod }
194
-
195
- it "must call the superclass'es #help method first" do
196
- expect_any_instance_of(super_command_class).to receive(:help)
197
- expect(subject).to receive(:help_description)
198
-
199
- subject.help
200
- end
201
- end
202
178
  end
203
179
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'command_kit/env/home'
3
3
 
4
- describe Env::Home do
4
+ describe CommandKit::Env::Home do
5
5
  module TestEnvHome
6
6
  class TestCommand
7
7
  include CommandKit::Env::Home
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'command_kit/env/path'
3
3
 
4
- describe Env::Path do
4
+ describe CommandKit::Env::Path do
5
5
  module TestEnvPath
6
6
  class TestCommand
7
7
 
@@ -13,6 +13,12 @@ describe Env::Path do
13
13
  let(:command_class) { TestEnvPath::TestCommand }
14
14
  subject { command_class.new }
15
15
 
16
+ describe ".included" do
17
+ it "must include CommandKit::Env" do
18
+ expect(command_class).to be_include(CommandKit::Env)
19
+ end
20
+ end
21
+
16
22
  describe "#initialize" do
17
23
  it "must split ENV['PATH'] into an Array of directories" do
18
24
  expect(subject.path_dirs).to eq(ENV['PATH'].split(File::PATH_SEPARATOR))
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'command_kit/examples'
3
3
 
4
- describe Examples do
4
+ describe CommandKit::Examples do
5
5
  module TestExamples
6
6
  class ImplicitCmd
7
7
  include CommandKit::Examples
@@ -207,29 +207,5 @@ describe Examples do
207
207
 
208
208
  subject.help
209
209
  end
210
-
211
- context "when the superclass defines it's own #help method" do
212
- module TestDescription
213
- class SuperclassHelpMethod
214
- def help
215
- puts 'superclass'
216
- end
217
- end
218
-
219
- class InheritedHelpMethod < SuperclassHelpMethod
220
- include CommandKit::Examples
221
- end
222
- end
223
-
224
- let(:super_command_class) { TestDescription::SuperclassHelpMethod }
225
- let(:command_class) { TestDescription::InheritedHelpMethod }
226
-
227
- it "must call the superclass'es #help method first" do
228
- expect_any_instance_of(super_command_class).to receive(:help)
229
- expect(subject).to receive(:help_examples)
230
-
231
- subject.help
232
- end
233
- end
234
210
  end
235
211
  end
@@ -73,7 +73,7 @@ describe CommandKit::ExceptionHandler do
73
73
  include CommandKit::ExceptionHandler
74
74
 
75
75
  def run
76
- raise(RuntimeError.new("error"))
76
+ raise("error")
77
77
  end
78
78
 
79
79
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'command_kit/help/man'
3
3
 
4
- describe Help::Man do
4
+ describe CommandKit::Help::Man do
5
5
  module TestHelpMan
6
6
  class TestCommand
7
7
  include CommandKit::Help::Man
@@ -16,7 +16,13 @@ describe Help::Man do
16
16
  man_page 'foo.1'
17
17
  end
18
18
 
19
- class EmptyCommand
19
+ class TestCommandWithRelativeManDir
20
+ include CommandKit::Help::Man
21
+
22
+ man_dir File.join(__dir__,'..','..','..','man')
23
+ end
24
+
25
+ class TestCommandWithManDirNotSet
20
26
  include CommandKit::Help::Man
21
27
  end
22
28
  end
@@ -41,7 +47,7 @@ describe Help::Man do
41
47
 
42
48
  describe ".man_dir" do
43
49
  context "when no man_dir have been set" do
44
- subject { TestHelpMan::EmptyCommand }
50
+ subject { TestHelpMan::TestCommandWithManDirNotSet }
45
51
 
46
52
  it "should default to nil" do
47
53
  expect(subject.man_dir).to be_nil
@@ -52,7 +58,17 @@ describe Help::Man do
52
58
  subject { TestHelpMan::TestCommand }
53
59
 
54
60
  it "must return the explicitly set man_dir" do
55
- expect(subject.man_dir).to eq(File.expand_path('../fixtures/man',__FILE__))
61
+ expect(subject.man_dir).to eq(File.join(__dir__,'fixtures','man'))
62
+ end
63
+
64
+ context "but it's a relative path" do
65
+ subject { TestHelpMan::TestCommandWithRelativeManDir }
66
+
67
+ it "must expand the given man_dir path" do
68
+ expect(subject.man_dir).to eq(
69
+ File.expand_path(File.join(__dir__,'..','..','..','man'))
70
+ )
71
+ end
56
72
  end
57
73
  end
58
74
 
@@ -96,7 +112,7 @@ describe Help::Man do
96
112
  end
97
113
 
98
114
  it "must not change the superclass'es man_dir" do
99
- expect(super_subject.man_dir).to eq('set/in/baseclass')
115
+ expect(super_subject.man_dir).to eq(File.expand_path('set/in/baseclass'))
100
116
  end
101
117
  end
102
118
 
@@ -115,7 +131,7 @@ describe Help::Man do
115
131
  subject { TestHelpMan::ExplicitInheritedCmd }
116
132
 
117
133
  it "must return the subclass'es man_dir" do
118
- expect(subject.man_dir).to eq('set/in/subclass')
134
+ expect(subject.man_dir).to eq(File.expand_path('set/in/subclass'))
119
135
  end
120
136
 
121
137
  it "must not change the superclass'es man_dir" do
@@ -134,11 +150,11 @@ describe Help::Man do
134
150
  subject { TestHelpMan::ExplicitOverridingInheritedCmd }
135
151
 
136
152
  it "must return the subclass'es man_dir" do
137
- expect(subject.man_dir).to eq('set/in/subclass')
153
+ expect(subject.man_dir).to eq(File.expand_path('set/in/subclass'))
138
154
  end
139
155
 
140
156
  it "must not change the superclass'es man_dir" do
141
- expect(super_subject.man_dir).to eq('set/in/baseclass')
157
+ expect(super_subject.man_dir).to eq(File.expand_path('set/in/baseclass'))
142
158
  end
143
159
  end
144
160
  end
@@ -234,48 +250,7 @@ describe Help::Man do
234
250
 
235
251
  subject { command_class.new }
236
252
 
237
- describe "#man" do
238
- let(:man_page) { 'foo' }
239
-
240
- it "must call system() with the given man page" do
241
- expect(subject).to receive(:system).with('man',man_page)
242
-
243
- subject.man(man_page)
244
- end
245
-
246
- context "when given a non-String man-page argument" do
247
- let(:man_page_arg) { double(:non_string_arg) }
248
-
249
- it "must call #to_s on the man-page argument" do
250
- expect(man_page_arg).to receive(:to_s).and_return(man_page)
251
-
252
- expect(subject).to receive(:system).with('man',man_page)
253
-
254
- subject.man(man_page_arg)
255
- end
256
- end
257
-
258
- context "when given the section: keyword argument" do
259
- let(:section) { 7 }
260
-
261
- it "must call system() with the given section number and man page" do
262
- expect(subject).to receive(:system).with('man',section.to_s,man_page)
263
-
264
- subject.man(man_page, section: section)
265
- end
266
- end
267
- end
268
-
269
253
  describe "#help_man" do
270
- context "when .man_dir is not set" do
271
- let(:command_class) { TestHelpMan::EmptyCommand }
272
- subject { command_class.new }
273
-
274
- it do
275
- expect { subject.help_man }.to raise_error(NotImplementedError)
276
- end
277
- end
278
-
279
254
  let(:man_page_path) do
280
255
  File.join(subject.class.man_dir,subject.class.man_page)
281
256
  end
@@ -318,21 +293,33 @@ describe Help::Man do
318
293
  expect(subject.stdout).to receive(:tty?).and_return(true)
319
294
  end
320
295
 
321
- it "must open the command's man-page" do
322
- expect(subject).to receive(:help_man).and_return(true)
296
+ context "and man_dir is set" do
297
+ it "must open the command's man-page" do
298
+ expect(subject).to receive(:help_man).and_return(true)
323
299
 
324
- subject.help
325
- end
300
+ subject.help
301
+ end
302
+
303
+ context "but when the man command is not installed" do
304
+ before do
305
+ expect(subject).to receive(:help_man).and_return(nil)
306
+ end
326
307
 
327
- context "but when the man command is not installed" do
328
- before do
329
- expect(subject).to receive(:help_man).and_return(nil)
308
+ it "must call the super help() method" do
309
+ subject.help
310
+
311
+ expect(subject.stdout.string).to eq(normal_help_output)
312
+ end
330
313
  end
314
+ end
315
+
316
+ context "but the man_dir is not set" do
317
+ let(:command_class) { TestHelpMan::TestCommandWithManDirNotSet }
331
318
 
332
- it "must call the super help() method" do
319
+ it "must call the super help() mehtod" do
333
320
  subject.help
334
321
 
335
- expect(subject.stdout.string).to eq(normal_help_output)
322
+ expect(stdout.string).to eq(normal_help_output)
336
323
  end
337
324
  end
338
325
  end
data/spec/help_spec.rb CHANGED
@@ -90,30 +90,5 @@ describe CommandKit::Help do
90
90
  subject.help()
91
91
  end
92
92
  end
93
-
94
- context "when the superclass defines it's own #help method" do
95
- module TestHelp
96
- class SuperclassWithHelp
97
-
98
- def help
99
- puts 'superclass'
100
- end
101
-
102
- end
103
-
104
- class SubclassOfSuperclassWithHelp < SuperclassWithHelp
105
- include CommandKit::Help
106
- end
107
- end
108
-
109
- let(:command_superclass) { TestHelp::SuperclassWithHelp }
110
- let(:command_class) { TestHelp::SubclassOfSuperclassWithHelp }
111
-
112
- it "must call the superclass'es #help" do
113
- expect_any_instance_of(command_superclass).to receive(:help)
114
-
115
- subject.help()
116
- end
117
- end
118
93
  end
119
94
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'command_kit/inflector'
3
3
 
4
- describe Inflector do
4
+ describe CommandKit::Inflector do
5
5
  describe ".demodularize" do
6
6
  context "when given a single class or module name" do
7
7
  let(:name) { 'Foo' }
@@ -28,6 +28,10 @@ describe Inflector do
28
28
  end
29
29
  end
30
30
 
31
+ ascii = (0..255).map(&:chr)
32
+ alpha = ('a'..'z').to_a + ('A'..'Z').to_a
33
+ numeric = ('0'..'9').to_a
34
+
31
35
  describe ".underscore" do
32
36
  it "must convert CamelCase to camel_case" do
33
37
  expect(subject.underscore('CamelCase')).to eq('camel_case')
@@ -37,18 +41,48 @@ describe Inflector do
37
41
  expect(subject.underscore('camelCase')).to eq('camel_case')
38
42
  end
39
43
 
40
- it "must convert Camel to camel" do
41
- expect(subject.underscore('Camel')).to eq('camel')
44
+ it "must convert Camelcase to camelcase" do
45
+ expect(subject.underscore('Camelcase')).to eq('camelcase')
42
46
  end
43
47
 
44
- it "must convert CAMEL to camel" do
45
- expect(subject.underscore('CAMEL')).to eq('camel')
48
+ it "must convert CAMELCASE to camelcase" do
49
+ expect(subject.underscore('CAMELCASE')).to eq('camelcase')
46
50
  end
47
51
 
48
- context "when given a String containing '/' characters" do
49
- it "must replace dashes with underscores" do
50
- expect(subject.underscore('foo-bar')).to eq('foo_bar')
51
- end
52
+ it "must convert CAMELCase to camel_case" do
53
+ expect(subject.underscore('CAMELCase')).to eq('camel_case')
54
+ end
55
+
56
+ it "must convert CamelCASE to camel_case" do
57
+ expect(subject.underscore('CAMELCase')).to eq('camel_case')
58
+ end
59
+
60
+ it "must convert FooBARBaz to foo_bar_baz" do
61
+ expect(subject.underscore('FooBARBaz')).to eq('foo_bar_baz')
62
+ end
63
+
64
+ it "must convert foo_bar_baz to foo_bar_baz" do
65
+ expect(subject.underscore('foo_bar_baz')).to eq('foo_bar_baz')
66
+ end
67
+
68
+ it "must convert foo___bar___baz to foo___bar___baz" do
69
+ expect(subject.underscore('foo___bar___baz')).to eq('foo___bar___baz')
70
+ end
71
+
72
+ it "must convert foo-bar-baz to foo_bar_baz" do
73
+ expect(subject.underscore('foo-bar-baz')).to eq('foo_bar_baz')
74
+ end
75
+
76
+ it "must convert foo---bar---baz to foo___bar___baz" do
77
+ expect(subject.underscore('foo---bar---baz')).to eq('foo___bar___baz')
78
+ end
79
+
80
+ it "must convert foo_BAR_baz to foo_bar_baz" do
81
+ expect(subject.underscore('foo_BAR_baz')).to eq('foo_bar_baz')
82
+ end
83
+
84
+ it "must convert foo-BAR-baz to foo_bar_baz" do
85
+ expect(subject.underscore('foo-BAR-baz')).to eq('foo_bar_baz')
52
86
  end
53
87
 
54
88
  context "when given a non-String" do
@@ -56,6 +90,20 @@ describe Inflector do
56
90
  expect(subject.underscore(:CamelCase)).to eq('camel_case')
57
91
  end
58
92
  end
93
+
94
+ separators = %w[_ -]
95
+
96
+ (ascii - alpha - numeric - separators).each do |char|
97
+ context "when the given String contains a #{char.inspect} character" do
98
+ let(:string) { "Foo#{char}Bar" }
99
+
100
+ it do
101
+ expect {
102
+ subject.underscore(string)
103
+ }.to raise_error(ArgumentError,"cannot convert string to underscored: #{string.inspect}")
104
+ end
105
+ end
106
+ end
59
107
  end
60
108
 
61
109
  describe ".dasherize" do
@@ -100,5 +148,19 @@ describe Inflector do
100
148
  expect(subject.camelize(:foo_bar)).to eq('FooBar')
101
149
  end
102
150
  end
151
+
152
+ separators = %w[_ - /]
153
+
154
+ (ascii - alpha - numeric - separators).each do |char|
155
+ context "when the given String contains a #{char.inspect} character" do
156
+ let(:string) { "foo#{char}bar" }
157
+
158
+ it do
159
+ expect {
160
+ subject.camelize(string)
161
+ }.to raise_error(ArgumentError,"cannot convert string to CamelCase: #{string.inspect}")
162
+ end
163
+ end
164
+ end
103
165
  end
104
166
  end