command_kit 0.1.0.pre2 → 0.2.1

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 (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