optimist 3.0.1 → 3.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.
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Optimist
5
5
 
6
- class ParserTest < ::MiniTest::Test
6
+ class ParserTest < ::Minitest::Test
7
7
  def setup
8
8
  @p = Parser.new
9
9
  end
@@ -35,8 +35,6 @@ class ParserTest < ::MiniTest::Test
35
35
  assert_equal "synopsis string", parser.synopsis
36
36
  end
37
37
 
38
- # def test_depends
39
- # def test_conflicts
40
38
  # def test_stop_on
41
39
  # def test_stop_on_unknown
42
40
 
@@ -45,10 +43,57 @@ class ParserTest < ::MiniTest::Test
45
43
 
46
44
 
47
45
  def test_unknown_arguments
48
- assert_raises(CommandlineError) { @p.parse(%w(--arg)) }
46
+ assert_raises_errmatch(CommandlineError, /unknown argument '--arg'/) { @p.parse(%w(--arg)) }
49
47
  @p.opt "arg"
50
48
  @p.parse(%w(--arg))
51
- assert_raises(CommandlineError) { @p.parse(%w(--arg2)) }
49
+ assert_raises_errmatch(CommandlineError, /unknown argument '--arg2'/) { @p.parse(%w(--arg2)) }
50
+ end
51
+
52
+ def test_unknown_arguments_with_suggestions
53
+ unless (Module::const_defined?("DidYouMean") &&
54
+ Module::const_defined?("DidYouMean::JaroWinkler") &&
55
+ Module::const_defined?("DidYouMean::Levenshtein"))
56
+ # if we cannot
57
+ skip("Skipping because DidYouMean was not found")
58
+ return false
59
+ end
60
+ sugp = Parser.new(:suggestions => true)
61
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--bone)) }
62
+ assert_match(/unknown argument '--bone'$/, err.message)
63
+
64
+ sugp.opt "cone"
65
+ sugp.parse(%w(--cone))
66
+
67
+ # single letter mismatch
68
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--bone)) }
69
+ assert_match(/unknown argument '--bone'. Did you mean: \[--cone\] \?$/, err.message)
70
+
71
+ # transposition
72
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--ocne)) }
73
+ assert_match(/unknown argument '--ocne'. Did you mean: \[--cone\] \?$/, err.message)
74
+
75
+ # extra letter at end
76
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--cones)) }
77
+ assert_match(/unknown argument '--cones'. Did you mean: \[--cone\] \?$/, err.message)
78
+
79
+ # too big of a mismatch to suggest (extra letters in front)
80
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--snowcone)) }
81
+ assert_match(/unknown argument '--snowcone'$/, err.message)
82
+
83
+ # too big of a mismatch to suggest (nothing close)
84
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--clown-nose)) }
85
+ assert_match(/unknown argument '--clown-nose'$/, err.message)
86
+
87
+ sugp.opt "zippy"
88
+ sugp.opt "zapzy"
89
+ # single letter mismatch, matches two
90
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--zipzy)) }
91
+ assert_match(/unknown argument '--zipzy'. Did you mean: \[--zippy, --zapzy\] \?$/, err.message)
92
+
93
+ sugp.opt "big_bug"
94
+ # suggest common case of dash versus underscore in argnames
95
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--big_bug)) }
96
+ assert_match(/unknown argument '--big_bug'. Did you mean: \[--big-bug\] \?$/, err.message)
52
97
  end
53
98
 
54
99
  def test_syntax_check
@@ -56,8 +101,8 @@ class ParserTest < ::MiniTest::Test
56
101
 
57
102
  @p.parse(%w(--arg))
58
103
  @p.parse(%w(arg))
59
- assert_raises(CommandlineError) { @p.parse(%w(---arg)) }
60
- assert_raises(CommandlineError) { @p.parse(%w(-arg)) }
104
+ assert_raises_errmatch(CommandlineError, /invalid argument syntax: '---arg'/) { @p.parse(%w(---arg)) }
105
+ assert_raises_errmatch(CommandlineError, /unknown argument '-r'/) { @p.parse(%w(-arg)) }
61
106
  end
62
107
 
63
108
  def test_required_flags_are_required
@@ -67,8 +112,9 @@ class ParserTest < ::MiniTest::Test
67
112
 
68
113
  @p.parse(%w(--arg))
69
114
  @p.parse(%w(--arg --arg2))
70
- assert_raises(CommandlineError) { @p.parse(%w(--arg2)) }
71
- assert_raises(CommandlineError) { @p.parse(%w(--arg2 --arg3)) }
115
+ err_regex = %r/option --arg must be specified/
116
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--arg2)) }
117
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--arg2 --arg3)) }
72
118
  end
73
119
 
74
120
  ## flags that take an argument error unless given one
@@ -77,8 +123,9 @@ class ParserTest < ::MiniTest::Test
77
123
  @p.opt "goodarg2", "desc", :type => String
78
124
 
79
125
  @p.parse(%w(--goodarg goat))
80
- assert_raises(CommandlineError) { @p.parse(%w(--goodarg --goodarg2 goat)) }
81
- assert_raises(CommandlineError) { @p.parse(%w(--goodarg)) }
126
+ err_regex = %r/option '--goodarg' needs a parameter/
127
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--goodarg --goodarg2 goat)) }
128
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--goodarg)) }
82
129
  end
83
130
 
84
131
  ## flags that don't take arguments ignore them
@@ -95,19 +142,24 @@ class ParserTest < ::MiniTest::Test
95
142
  ## flags that require args of a specific type refuse args of other
96
143
  ## types
97
144
  def test_typed_args_refuse_args_of_other_types
98
- @p.opt "goodarg", "desc", :type => :int
99
- assert_raises(ArgumentError) { @p.opt "badarg", "desc", :type => :asdf }
145
+ @p.opt "goodarg", "desc", :type => :int
146
+ err_regex = %r/Unsupported argument type 'asdf', registry lookup 'asdf'/
147
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg", "desc", :type => :asdf }
100
148
 
101
149
  @p.parse(%w(--goodarg 3))
102
- assert_raises(CommandlineError) { @p.parse(%w(--goodarg 4.2)) }
103
- assert_raises(CommandlineError) { @p.parse(%w(--goodarg hello)) }
150
+ err_regex = %r/option 'goodarg' needs an integer/
151
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--goodarg 4.2)) }
152
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--goodarg hello)) }
104
153
  end
105
154
 
106
155
  ## type is correctly derived from :default
107
156
  def test_type_correctly_derived_from_default
108
- assert_raises(ArgumentError) { @p.opt "badarg", "desc", :default => [] }
109
- assert_raises(ArgumentError) { @p.opt "badarg3", "desc", :default => [{1 => 2}] }
110
- assert_raises(ArgumentError) { @p.opt "badarg4", "desc", :default => Hash.new }
157
+ err_regex = %r/multiple argument type cannot be deduced from an empty array/
158
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg", "desc", :default => [] }
159
+ err_regex = %r/Unsupported argument type 'hashs', registry lookup 'hashs'/
160
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg3", "desc", :default => [{1 => 2}] }
161
+ err_regex = %r/Unsupported argument type 'hash', registry lookup 'hash'/
162
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg4", "desc", :default => Hash.new }
111
163
 
112
164
  # single arg: int
113
165
  @p.opt "argsi", "desc", :default => 0
@@ -119,9 +171,9 @@ class ParserTest < ::MiniTest::Test
119
171
  assert_equal 4, opts["argsi"]
120
172
  opts = @p.parse(%w(--argsi=-4))
121
173
  assert_equal( -4, opts["argsi"])
122
-
123
- assert_raises(CommandlineError) { @p.parse(%w(--argsi 4.2)) }
124
- assert_raises(CommandlineError) { @p.parse(%w(--argsi hello)) }
174
+ err_regex = /option 'argsi' needs an integer/
175
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--argsi 4.2)) }
176
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--argsi hello)) }
125
177
 
126
178
  # single arg: float
127
179
  @p.opt "argsf", "desc", :default => 3.14
@@ -133,7 +185,8 @@ class ParserTest < ::MiniTest::Test
133
185
  assert_equal 2, opts["argsf"]
134
186
  opts = @p.parse(%w(--argsf 1.0e-2))
135
187
  assert_equal 1.0e-2, opts["argsf"]
136
- assert_raises(CommandlineError) { @p.parse(%w(--argsf hello)) }
188
+ err_regex = /option 'argsf' needs a floating-point number/
189
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--argsf hello)) }
137
190
 
138
191
  # single arg: date
139
192
  date = Date.today
@@ -142,7 +195,8 @@ class ParserTest < ::MiniTest::Test
142
195
  assert_equal Date.today, opts["argsd"]
143
196
  opts = @p.parse(['--argsd', 'Jan 4, 2007'])
144
197
  assert_equal Date.civil(2007, 1, 4), opts["argsd"]
145
- assert_raises(CommandlineError) { @p.parse(%w(--argsd hello)) }
198
+ err_regex = /option 'argsd' needs a date/
199
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--argsd hello)) }
146
200
 
147
201
  # single arg: string
148
202
  @p.opt "argss", "desc", :default => "foobar"
@@ -159,8 +213,9 @@ class ParserTest < ::MiniTest::Test
159
213
  assert_equal [3, 5], opts["argmi"]
160
214
  opts = @p.parse(%w(--argmi 4))
161
215
  assert_equal [4], opts["argmi"]
162
- assert_raises(CommandlineError) { @p.parse(%w(--argmi 4.2)) }
163
- assert_raises(CommandlineError) { @p.parse(%w(--argmi hello)) }
216
+ err_regex = /option 'argmi' needs an integer/
217
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--argmi 4.2)) }
218
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--argmi hello)) }
164
219
 
165
220
  # multi args: floats
166
221
  @p.opt "argmf", "desc", :default => [3.34, 5.21]
@@ -170,7 +225,8 @@ class ParserTest < ::MiniTest::Test
170
225
  assert_equal [2], opts["argmf"]
171
226
  opts = @p.parse(%w(--argmf 4.0))
172
227
  assert_equal [4.0], opts["argmf"]
173
- assert_raises(CommandlineError) { @p.parse(%w(--argmf hello)) }
228
+ err_regex = /option 'argmf' needs a floating-point number/
229
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--argmf hello)) }
174
230
 
175
231
  # multi args: dates
176
232
  dates = [Date.today, Date.civil(2007, 1, 4)]
@@ -179,7 +235,8 @@ class ParserTest < ::MiniTest::Test
179
235
  assert_equal dates, opts["argmd"]
180
236
  opts = @p.parse(['--argmd', 'Jan 4, 2007'])
181
237
  assert_equal [Date.civil(2007, 1, 4)], opts["argmd"]
182
- assert_raises(CommandlineError) { @p.parse(%w(--argmd hello)) }
238
+ err_regex = /option 'argmd' needs a date/
239
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse(%w(--argmd hello)) }
183
240
 
184
241
  # multi args: strings
185
242
  @p.opt "argmst", "desc", :default => %w(hello world)
@@ -193,10 +250,12 @@ class ParserTest < ::MiniTest::Test
193
250
 
194
251
  ## :type and :default must match if both are specified
195
252
  def test_type_and_default_must_match
196
- assert_raises(ArgumentError) { @p.opt "badarg", "desc", :type => :int, :default => "hello" }
197
- assert_raises(ArgumentError) { @p.opt "badarg2", "desc", :type => :String, :default => 4 }
198
- assert_raises(ArgumentError) { @p.opt "badarg2", "desc", :type => :String, :default => ["hi"] }
199
- assert_raises(ArgumentError) { @p.opt "badarg2", "desc", :type => :ints, :default => [3.14] }
253
+ # Different versions of ruby raise different error messages.
254
+ err_regex = %r/(type specification and default type don't match|Unsupported argument type)/
255
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg", "desc", :type => :int, :default => "hello" }
256
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg2", "desc", :type => :String, :default => 4 }
257
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg2", "desc", :type => :String, :default => ["hi"] }
258
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg2", "desc", :type => :ints, :default => [3.14] }
200
259
 
201
260
  @p.opt "argsi", "desc", :type => :int, :default => 4
202
261
  @p.opt "argsf", "desc", :type => :float, :default => 3.14
@@ -239,10 +298,11 @@ class ParserTest < ::MiniTest::Test
239
298
  @p.opt "argmf", "desc", :type => :floats, :default => []
240
299
  @p.opt "argmd", "desc", :type => :dates, :default => []
241
300
  @p.opt "argms", "desc", :type => :strings, :default => []
242
- assert_raises(ArgumentError) { @p.opt "badi", "desc", :type => :int, :default => [] }
243
- assert_raises(ArgumentError) { @p.opt "badf", "desc", :type => :float, :default => [] }
244
- assert_raises(ArgumentError) { @p.opt "badd", "desc", :type => :date, :default => [] }
245
- assert_raises(ArgumentError) { @p.opt "bads", "desc", :type => :string, :default => [] }
301
+ err_regex = %r/multiple argument type must be plural/
302
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badi", "desc", :type => :int, :default => [] }
303
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badf", "desc", :type => :float, :default => [] }
304
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badd", "desc", :type => :date, :default => [] }
305
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "bads", "desc", :type => :string, :default => [] }
246
306
  opts = @p.parse([])
247
307
  assert_equal(opts["argmi"], [])
248
308
  assert_equal(opts["argmf"], [])
@@ -253,18 +313,22 @@ class ParserTest < ::MiniTest::Test
253
313
  def test_long_detects_bad_names
254
314
  @p.opt "goodarg", "desc", :long => "none"
255
315
  @p.opt "goodarg2", "desc", :long => "--two"
256
- assert_raises(ArgumentError) { @p.opt "badarg", "desc", :long => "" }
257
- assert_raises(ArgumentError) { @p.opt "badarg2", "desc", :long => "--" }
258
- assert_raises(ArgumentError) { @p.opt "badarg3", "desc", :long => "-one" }
259
- assert_raises(ArgumentError) { @p.opt "badarg4", "desc", :long => "---toomany" }
316
+ @p.opt "goodarg3", "desc", :long => "arg-3"
317
+ @p.opt "goodarg4", "desc", :long => "--good-arg-four"
318
+ err_regex = /invalid long option name/
319
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg", "desc", :long => "" }
320
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg2", "desc", :long => "--" }
321
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg3", "desc", :long => "-one" }
322
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg4", "desc", :long => "---toomany" }
260
323
  end
261
324
 
262
325
  def test_short_detects_bad_names
263
326
  @p.opt "goodarg", "desc", :short => "a"
264
327
  @p.opt "goodarg2", "desc", :short => "-b"
265
- assert_raises(ArgumentError) { @p.opt "badarg", "desc", :short => "" }
266
- assert_raises(ArgumentError) { @p.opt "badarg2", "desc", :short => "-ab" }
267
- assert_raises(ArgumentError) { @p.opt "badarg3", "desc", :short => "--t" }
328
+ err_regex = /invalid short option name/
329
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg", "desc", :short => "" }
330
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg2", "desc", :short => "-ab" }
331
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg3", "desc", :short => "--t" }
268
332
  end
269
333
 
270
334
  def test_short_names_created_automatically
@@ -308,25 +372,29 @@ class ParserTest < ::MiniTest::Test
308
372
  @p.educate sio
309
373
  assert sio.string =~ /--arg\s+desc/
310
374
 
311
- assert_raises(CommandlineError) { @p.parse %w(-a) }
375
+ assert_raises_errmatch(CommandlineError, /unknown argument '-a'/) { @p.parse %w(-a) }
312
376
  end
313
377
 
314
378
  ## two args can't have the same name
315
379
  def test_conflicting_names_are_detected
316
380
  @p.opt "goodarg"
317
- assert_raises(ArgumentError) { @p.opt "goodarg" }
381
+ err_regex = /you already have an argument named 'goodarg'/
382
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "goodarg" }
318
383
  end
319
384
 
320
385
  ## two args can't have the same :long
321
386
  def test_conflicting_longs_detected
322
387
  @p.opt "goodarg", "desc", :long => "--goodarg"
323
- assert_raises(ArgumentError) { @p.opt "badarg", "desc", :long => "--goodarg" }
388
+ err_regex = /long option name \"goodarg\" is already taken/
389
+
390
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg", "desc", :long => "--goodarg" }
324
391
  end
325
392
 
326
393
  ## two args can't have the same :short
327
394
  def test_conflicting_shorts_detected
328
395
  @p.opt "goodarg", "desc", :short => "-g"
329
- assert_raises(ArgumentError) { @p.opt "badarg", "desc", :short => "-g" }
396
+ err_regex = /short option name \"g\" is already taken/
397
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt "badarg", "desc", :short => "-g" }
330
398
  end
331
399
 
332
400
  ## note: this behavior has changed in optimist 2.0!
@@ -347,6 +415,14 @@ class ParserTest < ::MiniTest::Test
347
415
  assert_equal true, opts[:defaultfalse]
348
416
  assert_equal true, opts[:defaulttrue]
349
417
 
418
+ ## using short form turns them all on, regardless of default
419
+ #
420
+ # (matches positve "non-no" long form)
421
+ opts = @p.parse %w(-d -e -f)
422
+ assert_equal true, opts[:defaultnone]
423
+ assert_equal true, opts[:defaultfalse]
424
+ assert_equal true, opts[:defaulttrue]
425
+
350
426
  ## using --no- form turns them off, regardless of default
351
427
  opts = @p.parse %w(--no-defaultfalse --no-defaulttrue --no-defaultnone)
352
428
  assert_equal false, opts[:defaultnone]
@@ -378,8 +454,16 @@ class ParserTest < ::MiniTest::Test
378
454
  assert_equal false, opts[:no_default_false]
379
455
  assert_equal false, opts[:no_default_true]
380
456
 
457
+ ## using short form turns them all off, regardless of default
458
+ #
459
+ # (matches positve "non-no" long form)
460
+ opts = @p.parse %w(-n -o -d)
461
+ assert_equal false, opts[:no_default_none]
462
+ assert_equal false, opts[:no_default_false]
463
+ assert_equal false, opts[:no_default_true]
464
+
381
465
  ## disallow double negatives for reasons of sanity preservation
382
- assert_raises(CommandlineError) { @p.parse %w(--no-no-default-true) }
466
+ assert_raises_errmatch(CommandlineError, /unknown argument '--no-default-true'/) { @p.parse %w(--no-no-default-true) }
383
467
  end
384
468
 
385
469
  def test_short_options_combine
@@ -402,8 +486,9 @@ class ParserTest < ::MiniTest::Test
402
486
  assert_equal true, opts[:arg2]
403
487
  assert_equal 4, opts[:arg3]
404
488
 
405
- assert_raises(CommandlineError) { @p.parse %w(-cab 4) }
406
- assert_raises(CommandlineError) { @p.parse %w(-cba 4) }
489
+ err_regex = /option '-c' needs a parameter/
490
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse %w(-cab 4) }
491
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse %w(-cba 4) }
407
492
  end
408
493
 
409
494
  def test_doubledash_ends_option_processing
@@ -490,13 +575,15 @@ Options:
490
575
  assert_equal(-0.1, opts[:arg])
491
576
  opts = @p.parse %w(-f -.1)
492
577
  assert_equal(-0.1, opts[:arg])
493
- assert_raises(CommandlineError) { @p.parse %w(-f a) }
494
- assert_raises(CommandlineError) { @p.parse %w(-f 1a) }
495
- assert_raises(CommandlineError) { @p.parse %w(-f 1.a) }
496
- assert_raises(CommandlineError) { @p.parse %w(-f a.1) }
497
- assert_raises(CommandlineError) { @p.parse %w(-f 1.0.0) }
498
- assert_raises(CommandlineError) { @p.parse %w(-f .) }
499
- assert_raises(CommandlineError) { @p.parse %w(-f -.) }
578
+ err_regex = %r/option 'arg' needs a floating-point number/
579
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse %w(-f a) }
580
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse %w(-f 1a) }
581
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse %w(-f 1.a) }
582
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse %w(-f a.1) }
583
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse %w(-f 1.0.0) }
584
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse %w(-f .) }
585
+ err_regex = %r/unknown argument '-.'/
586
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse %w(-f -.) }
500
587
  end
501
588
 
502
589
  def test_floating_point_formatting_default
@@ -514,23 +601,30 @@ Options:
514
601
  end
515
602
 
516
603
  def test_short_options_cant_be_numeric
517
- assert_raises(ArgumentError) { @p.opt :arg, "desc", :short => "-1" }
604
+ err_regex = %r/short option name '1' can't be a number or a dash/
605
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt :arg, "desc", :short => "-1" }
518
606
  @p.opt :a1b, "desc"
519
607
  @p.opt :a2b, "desc"
520
- assert @p.specs[:a2b].short.to_i == 0
608
+ @p.parse []
609
+ # testing private interface to ensure default
610
+ # short options did not become numeric
611
+ assert_equal @p.specs[:a1b].short.chars.first, 'a'
612
+ assert_equal @p.specs[:a2b].short.chars.first, 'b'
521
613
  end
522
614
 
523
615
  def test_short_options_can_be_weird
524
616
  @p.opt :arg1, "desc", :short => "#"
525
617
  @p.opt :arg2, "desc", :short => "."
526
- assert_raises(ArgumentError) { @p.opt :arg3, "desc", :short => "-" }
618
+ err_regex = %r/short option name '-' can't be a number or a dash/
619
+ assert_raises_errmatch(ArgumentError, err_regex) { @p.opt :arg3, "desc", :short => "-" }
527
620
  end
528
621
 
529
622
  def test_options_cant_be_set_multiple_times_if_not_specified
530
623
  @p.opt :arg, "desc", :short => "-x"
531
624
  @p.parse %w(-x)
532
- assert_raises(CommandlineError) { @p.parse %w(-x -x) }
533
- assert_raises(CommandlineError) { @p.parse %w(-xx) }
625
+ err_regex = /option '-x' specified multiple times/
626
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse %w(-x -x) }
627
+ assert_raises_errmatch(CommandlineError, err_regex) { @p.parse %w(-xx) }
534
628
  end
535
629
 
536
630
  def test_options_can_be_set_multiple_times_if_specified
@@ -614,7 +708,7 @@ Options:
614
708
  assert_equal [4, 6, 9], opts[:arg3]
615
709
  assert_equal [3.14, 2.41], opts[:arg4]
616
710
 
617
- assert_raises(CommandlineError) { opts = @p.parse %w(-abcd 3.14 2.41) }
711
+ assert_raises_errmatch(CommandlineError, /option '-c' needs a parameter/) { opts = @p.parse %w(-abcd 3.14 2.41) }
618
712
  end
619
713
 
620
714
  def test_long_options_with_multiple_options
@@ -694,7 +788,7 @@ Options:
694
788
 
695
789
  def test_auto_generated_long_names_convert_underscores_to_hyphens
696
790
  @p.opt :hello_there
697
- assert_equal "hello-there", @p.specs[:hello_there].long
791
+ assert_equal "hello-there", @p.specs[:hello_there].long.long
698
792
  end
699
793
 
700
794
  def test_arguments_passed_through_block
@@ -706,98 +800,37 @@ Options:
706
800
  assert_equal @goat, boat
707
801
  end
708
802
 
803
+ ## test-only access reader method so that we dont have to
804
+ ## expose settings in the public API.
805
+ class Optimist::Parser
806
+ def get_settings_for_testing ; return @settings ;end
807
+ end
808
+
809
+ def test_two_arguments_passed_through_block
810
+ newp = Parser.new(:abcd => 123, :efgh => "other" ) do |i|
811
+ end
812
+ assert_equal newp.get_settings_for_testing[:abcd], 123
813
+ assert_equal newp.get_settings_for_testing[:efgh], "other"
814
+ end
815
+
816
+
709
817
  def test_version_and_help_override_errors
710
818
  @p.opt :asdf, "desc", :type => String
711
819
  @p.version "version"
712
820
  @p.parse %w(--asdf goat)
713
- assert_raises(CommandlineError) { @p.parse %w(--asdf) }
821
+ assert_raises_errmatch(CommandlineError, /option '--asdf' needs a parameter/) { @p.parse %w(--asdf) }
714
822
  assert_raises(HelpNeeded) { @p.parse %w(--asdf --help) }
715
823
  assert_raises(VersionNeeded) { @p.parse %w(--asdf --version) }
716
824
  end
717
825
 
718
- def test_conflicts
719
- @p.opt :one
720
- assert_raises(ArgumentError) { @p.conflicts :one, :two }
721
- @p.opt :two
722
- @p.conflicts :one, :two
723
- @p.parse %w(--one)
724
- @p.parse %w(--two)
725
- assert_raises(CommandlineError) { @p.parse %w(--one --two) }
726
-
727
- @p.opt :hello
728
- @p.opt :yellow
729
- @p.opt :mellow
730
- @p.opt :jello
731
- @p.conflicts :hello, :yellow, :mellow, :jello
732
- assert_raises(CommandlineError) { @p.parse %w(--hello --yellow --mellow --jello) }
733
- assert_raises(CommandlineError) { @p.parse %w(--hello --mellow --jello) }
734
- assert_raises(CommandlineError) { @p.parse %w(--hello --jello) }
735
-
736
- @p.parse %w(--hello)
737
- @p.parse %w(--jello)
738
- @p.parse %w(--yellow)
739
- @p.parse %w(--mellow)
740
-
741
- @p.parse %w(--mellow --one)
742
- @p.parse %w(--mellow --two)
743
-
744
- assert_raises(CommandlineError) { @p.parse %w(--mellow --two --jello) }
745
- assert_raises(CommandlineError) { @p.parse %w(--one --mellow --two --jello) }
746
- end
747
-
748
- def test_conflict_error_messages
749
- @p.opt :one
750
- @p.opt "two"
751
- @p.conflicts :one, "two"
752
-
753
- assert_raises(CommandlineError, /--one.*--two/) { @p.parse %w(--one --two) }
754
- end
755
-
756
- def test_depends
757
- @p.opt :one
758
- assert_raises(ArgumentError) { @p.depends :one, :two }
759
- @p.opt :two
760
- @p.depends :one, :two
761
- @p.parse %w(--one --two)
762
- assert_raises(CommandlineError) { @p.parse %w(--one) }
763
- assert_raises(CommandlineError) { @p.parse %w(--two) }
764
-
765
- @p.opt :hello
766
- @p.opt :yellow
767
- @p.opt :mellow
768
- @p.opt :jello
769
- @p.depends :hello, :yellow, :mellow, :jello
770
- @p.parse %w(--hello --yellow --mellow --jello)
771
- assert_raises(CommandlineError) { @p.parse %w(--hello --mellow --jello) }
772
- assert_raises(CommandlineError) { @p.parse %w(--hello --jello) }
773
-
774
- assert_raises(CommandlineError) { @p.parse %w(--hello) }
775
- assert_raises(CommandlineError) { @p.parse %w(--mellow) }
776
-
777
- @p.parse %w(--hello --yellow --mellow --jello --one --two)
778
- @p.parse %w(--hello --yellow --mellow --jello --one --two a b c)
779
-
780
- assert_raises(CommandlineError) { @p.parse %w(--mellow --two --jello --one) }
781
- end
782
-
783
- def test_depend_error_messages
784
- @p.opt :one
785
- @p.opt "two"
786
- @p.depends :one, "two"
787
-
788
- @p.parse %w(--one --two)
789
-
790
- assert_raises(CommandlineError, /--one.*--two/) { @p.parse %w(--one) }
791
- assert_raises(CommandlineError, /--one.*--two/) { @p.parse %w(--two) }
792
- end
793
826
 
794
827
  ## courtesy neill zero
795
828
  def test_two_required_one_missing_accuses_correctly
796
829
  @p.opt "arg1", "desc1", :required => true
797
830
  @p.opt "arg2", "desc2", :required => true
798
831
 
799
- assert_raises(CommandlineError, /arg2/) { @p.parse(%w(--arg1)) }
800
- assert_raises(CommandlineError, /arg1/) { @p.parse(%w(--arg2)) }
832
+ assert_raises_errmatch(CommandlineError, /arg2/) { @p.parse(%w(--arg1)) }
833
+ assert_raises_errmatch(CommandlineError, /arg1/) { @p.parse(%w(--arg2)) }
801
834
  @p.parse(%w(--arg1 --arg2))
802
835
  end
803
836
 
@@ -958,8 +991,11 @@ Options:
958
991
 
959
992
  opts = @p.parse %w(--arg3 stdin)
960
993
  assert_equal $stdin, opts[:arg3]
961
-
962
- assert_raises(CommandlineError) { opts = @p.parse %w(--arg /fdasfasef/fessafef/asdfasdfa/fesasf) }
994
+
995
+ err_regex = %r/file or url for option 'arg' cannot be opened: No such file or directory/
996
+ assert_raises_errmatch(CommandlineError, err_regex) {
997
+ opts = @p.parse %w(--arg /fdasfasef/fessafef/asdfasdfa/fesasf)
998
+ }
963
999
  end
964
1000
 
965
1001
  def test_openstruct_style_access
@@ -1060,6 +1096,86 @@ Options:
1060
1096
  assert opts[:ccd]
1061
1097
  end
1062
1098
 
1099
+ def test_short_opts_not_implicitly_created
1100
+ newp = Parser.new(implicit_short_opts: false)
1101
+ newp.opt :user1, "user1"
1102
+ newp.opt :bag, "bag", :short => 'b'
1103
+ assert_raises_errmatch(CommandlineError, /unknown argument '-u'/) do
1104
+ newp.parse %w(-u)
1105
+ end
1106
+ opts = newp.parse %w(--user1)
1107
+ assert opts[:user1]
1108
+ opts = newp.parse %w(-b)
1109
+ assert opts[:bag]
1110
+ end
1111
+
1112
+ def test_short_opts_not_implicit_help_ver
1113
+ # When implicit_short_opts is false this implies the short options
1114
+ # for the built-in help/version are also not created.
1115
+ newp = Parser.new(implicit_short_opts: false)
1116
+ newp.opt :abc, "abc"
1117
+ newp.version "3.4.5"
1118
+ assert_raises_errmatch(CommandlineError, /unknown argument '-h'/) do
1119
+ newp.parse %w(-h)
1120
+ end
1121
+ assert_raises_errmatch(CommandlineError, /unknown argument '-v'/) do
1122
+ newp.parse %w(-v)
1123
+ end
1124
+ assert_raises(HelpNeeded) do
1125
+ newp.parse %w(--help)
1126
+ end
1127
+ assert_raises(VersionNeeded) do
1128
+ newp.parse %w(--version)
1129
+ end
1130
+ end
1131
+
1132
+ def test_inexact_match
1133
+ newp = Parser.new(exact_match: false)
1134
+ newp.opt :liberation, "liberate something", :type => :int
1135
+ newp.opt :evaluate, "evaluate something", :type => :string
1136
+ opts = newp.parse %w(--lib 5 --ev bar)
1137
+ assert_equal 5, opts[:liberation]
1138
+ assert_equal 'bar', opts[:evaluate]
1139
+ assert_nil opts[:eval]
1140
+ end
1141
+
1142
+ def test_exact_match
1143
+ newp = Parser.new()
1144
+ newp.opt :liberation, "liberate something", :type => :int
1145
+ newp.opt :evaluate, "evaluate something", :type => :string
1146
+ assert_raises_errmatch(CommandlineError, /unknown argument '--lib'/) do
1147
+ newp.parse %w(--lib 5)
1148
+ end
1149
+ assert_raises_errmatch(CommandlineError, /unknown argument '--ev'/) do
1150
+ newp.parse %w(--ev bar)
1151
+ end
1152
+ end
1153
+
1154
+ def test_inexact_collision
1155
+ newp = Parser.new(exact_match: false)
1156
+ newp.opt :bookname, "name of a book", :type => :string
1157
+ newp.opt :bookcost, "cost of the book", :type => :string
1158
+ opts = newp.parse %w(--bookn hairy_potsworth --bookc 10)
1159
+ assert_equal 'hairy_potsworth', opts[:bookname]
1160
+ assert_equal '10', opts[:bookcost]
1161
+ assert_raises_errmatch(CommandlineError, /ambiguous option '--book' matched keys \(bookname,bookcost\)/) do
1162
+ newp.parse %w(--book 5) # ambiguous
1163
+ end
1164
+ ## partial match causes 'specified multiple times' error
1165
+ assert_raises_errmatch(CommandlineError, /specified multiple times/) do
1166
+ newp.parse %w(--bookc 17 --bookcost 22)
1167
+ end
1168
+ end
1169
+
1170
+ def test_inexact_collision_with_exact
1171
+ newp = Parser.new(exact_match: false)
1172
+ newp.opt :book, "name of a book", :type => :string, :default => "ABC"
1173
+ newp.opt :bookcost, "cost of the book", :type => :int, :default => 5
1174
+ opts = newp.parse %w(--book warthog --bookc 3)
1175
+ assert_equal 'warthog', opts[:book]
1176
+ assert_equal 3, opts[:bookcost]
1177
+ end
1178
+
1063
1179
  def test_accepts_arguments_with_spaces
1064
1180
  @p.opt :arg1, "arg", :type => String
1065
1181
  @p.opt :arg2, "arg2", :type => String
@@ -1117,7 +1233,7 @@ Options:
1117
1233
  end
1118
1234
 
1119
1235
  def test_simple_interface_handles_die
1120
- assert_stderr do
1236
+ assert_stderr(/Error: argument --potato is invalid/) do
1121
1237
  ::Optimist::options(%w(--potato)) do
1122
1238
  opt :potato
1123
1239
  end
@@ -1126,7 +1242,7 @@ Options:
1126
1242
  end
1127
1243
 
1128
1244
  def test_simple_interface_handles_die_without_message
1129
- assert_stderr(/Error:/) do
1245
+ assert_stderr(/Error: potato\./) do
1130
1246
  ::Optimist::options(%w(--potato)) do
1131
1247
  opt :potato
1132
1248
  end
@@ -1135,7 +1251,7 @@ Options:
1135
1251
  end
1136
1252
 
1137
1253
  def test_invalid_option_with_simple_interface
1138
- assert_stderr do
1254
+ assert_stderr(/Error: unknown argument \'--potato\'\./) do
1139
1255
  assert_raises(SystemExit) do
1140
1256
  ::Optimist.options(%w(--potato))
1141
1257
  end
@@ -1151,7 +1267,7 @@ Options:
1151
1267
  end
1152
1268
 
1153
1269
  def test_supports_callback_inline
1154
- assert_raises(RuntimeError, "good") do
1270
+ assert_raises_errmatch(RuntimeError, "good") do
1155
1271
  @p.opt :cb1 do |vals|
1156
1272
  raise "good"
1157
1273
  end
@@ -1160,7 +1276,7 @@ Options:
1160
1276
  end
1161
1277
 
1162
1278
  def test_supports_callback_param
1163
- assert_raises(RuntimeError, "good") do
1279
+ assert_raises_errmatch(RuntimeError, "good") do
1164
1280
  @p.opt :cb1, "with callback", :callback => lambda { |vals| raise "good" }
1165
1281
  @p.parse(%w(--cb1))
1166
1282
  end
@@ -1215,6 +1331,37 @@ Options:
1215
1331
  assert opts[:arg1]
1216
1332
  assert_equal %w{-bu potato}, @p.leftovers
1217
1333
  end
1334
+
1335
+ # Due to strangeness in how the cloaker works, there were
1336
+ # cases where Optimist.parse would work, but Optimist.options
1337
+ # did not, depending on arguments given to the function.
1338
+ # These serve to validate different args given to Optimist.options
1339
+ def test_options_takes_hashy_settings
1340
+ passargs_copy = []
1341
+ settings_copy = []
1342
+ ::Optimist.options(%w(--wig --pig), :fizz=>:buzz, :bear=>:cat) do |*passargs|
1343
+ opt :wig
1344
+ opt :pig
1345
+ passargs_copy = passargs.dup
1346
+ settings_copy = @settings
1347
+ end
1348
+ assert_equal [], passargs_copy
1349
+ assert_equal settings_copy[:fizz], :buzz
1350
+ assert_equal settings_copy[:bear], :cat
1351
+ end
1352
+
1353
+ def test_options_takes_some_other_data
1354
+ passargs_copy = []
1355
+ settings_copy = []
1356
+ ::Optimist.options(%w(--nose --close), 1, 2, 3) do |*passargs|
1357
+ opt :nose
1358
+ opt :close
1359
+ passargs_copy = passargs.dup
1360
+ settings_copy = @settings
1361
+ end
1362
+ assert_equal [1,2,3], passargs_copy
1363
+ assert_equal(Optimist::Parser::DEFAULT_SETTINGS, settings_copy)
1364
+ end
1218
1365
  end
1219
1366
 
1220
1367
  end