optimist 3.1.0 → 3.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.
@@ -1,9 +1,9 @@
1
1
  require 'stringio'
2
- require 'test_helper'
2
+ require_relative '../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
@@ -96,18 +143,23 @@ class ParserTest < ::MiniTest::Test
96
143
  ## types
97
144
  def test_typed_args_refuse_args_of_other_types
98
145
  @p.opt "goodarg", "desc", :type => :int
99
- assert_raises(ArgumentError) { @p.opt "badarg", "desc", :type => :asdf }
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"], [])
@@ -255,18 +315,20 @@ class ParserTest < ::MiniTest::Test
255
315
  @p.opt "goodarg2", "desc", :long => "--two"
256
316
  @p.opt "goodarg3", "desc", :long => "arg-3"
257
317
  @p.opt "goodarg4", "desc", :long => "--good-arg-four"
258
- assert_raises(ArgumentError) { @p.opt "badarg", "desc", :long => "" }
259
- assert_raises(ArgumentError) { @p.opt "badarg2", "desc", :long => "--" }
260
- assert_raises(ArgumentError) { @p.opt "badarg3", "desc", :long => "-one" }
261
- assert_raises(ArgumentError) { @p.opt "badarg4", "desc", :long => "---toomany" }
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" }
262
323
  end
263
324
 
264
325
  def test_short_detects_bad_names
265
326
  @p.opt "goodarg", "desc", :short => "a"
266
327
  @p.opt "goodarg2", "desc", :short => "-b"
267
- assert_raises(ArgumentError) { @p.opt "badarg", "desc", :short => "" }
268
- assert_raises(ArgumentError) { @p.opt "badarg2", "desc", :short => "-ab" }
269
- 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" }
270
332
  end
271
333
 
272
334
  def test_short_names_created_automatically
@@ -306,29 +368,33 @@ class ParserTest < ::MiniTest::Test
306
368
  @p.opt "arg", "desc", :short => :none
307
369
  @p.parse []
308
370
 
309
- sio = StringIO.new "w"
371
+ sio = StringIO.new
310
372
  @p.educate sio
311
373
  assert sio.string =~ /--arg\s+desc/
312
374
 
313
- assert_raises(CommandlineError) { @p.parse %w(-a) }
375
+ assert_raises_errmatch(CommandlineError, /unknown argument '-a'/) { @p.parse %w(-a) }
314
376
  end
315
377
 
316
378
  ## two args can't have the same name
317
379
  def test_conflicting_names_are_detected
318
380
  @p.opt "goodarg"
319
- 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" }
320
383
  end
321
384
 
322
385
  ## two args can't have the same :long
323
386
  def test_conflicting_longs_detected
324
387
  @p.opt "goodarg", "desc", :long => "--goodarg"
325
- 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" }
326
391
  end
327
392
 
328
393
  ## two args can't have the same :short
329
394
  def test_conflicting_shorts_detected
330
395
  @p.opt "goodarg", "desc", :short => "-g"
331
- 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" }
332
398
  end
333
399
 
334
400
  ## note: this behavior has changed in optimist 2.0!
@@ -397,7 +463,7 @@ class ParserTest < ::MiniTest::Test
397
463
  assert_equal false, opts[:no_default_true]
398
464
 
399
465
  ## disallow double negatives for reasons of sanity preservation
400
- 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) }
401
467
  end
402
468
 
403
469
  def test_short_options_combine
@@ -420,8 +486,9 @@ class ParserTest < ::MiniTest::Test
420
486
  assert_equal true, opts[:arg2]
421
487
  assert_equal 4, opts[:arg3]
422
488
 
423
- assert_raises(CommandlineError) { @p.parse %w(-cab 4) }
424
- 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) }
425
492
  end
426
493
 
427
494
  def test_doubledash_ends_option_processing
@@ -508,13 +575,15 @@ Options:
508
575
  assert_equal(-0.1, opts[:arg])
509
576
  opts = @p.parse %w(-f -.1)
510
577
  assert_equal(-0.1, opts[:arg])
511
- assert_raises(CommandlineError) { @p.parse %w(-f a) }
512
- assert_raises(CommandlineError) { @p.parse %w(-f 1a) }
513
- assert_raises(CommandlineError) { @p.parse %w(-f 1.a) }
514
- assert_raises(CommandlineError) { @p.parse %w(-f a.1) }
515
- assert_raises(CommandlineError) { @p.parse %w(-f 1.0.0) }
516
- assert_raises(CommandlineError) { @p.parse %w(-f .) }
517
- 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 -.) }
518
587
  end
519
588
 
520
589
  def test_floating_point_formatting_default
@@ -532,23 +601,30 @@ Options:
532
601
  end
533
602
 
534
603
  def test_short_options_cant_be_numeric
535
- 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" }
536
606
  @p.opt :a1b, "desc"
537
607
  @p.opt :a2b, "desc"
538
- 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'
539
613
  end
540
614
 
541
615
  def test_short_options_can_be_weird
542
616
  @p.opt :arg1, "desc", :short => "#"
543
617
  @p.opt :arg2, "desc", :short => "."
544
- 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 => "-" }
545
620
  end
546
621
 
547
622
  def test_options_cant_be_set_multiple_times_if_not_specified
548
623
  @p.opt :arg, "desc", :short => "-x"
549
624
  @p.parse %w(-x)
550
- assert_raises(CommandlineError) { @p.parse %w(-x -x) }
551
- 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) }
552
628
  end
553
629
 
554
630
  def test_options_can_be_set_multiple_times_if_specified
@@ -632,7 +708,7 @@ Options:
632
708
  assert_equal [4, 6, 9], opts[:arg3]
633
709
  assert_equal [3.14, 2.41], opts[:arg4]
634
710
 
635
- 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) }
636
712
  end
637
713
 
638
714
  def test_long_options_with_multiple_options
@@ -712,7 +788,7 @@ Options:
712
788
 
713
789
  def test_auto_generated_long_names_convert_underscores_to_hyphens
714
790
  @p.opt :hello_there
715
- assert_equal "hello-there", @p.specs[:hello_there].long
791
+ assert_equal "hello-there", @p.specs[:hello_there].long.long
716
792
  end
717
793
 
718
794
  def test_arguments_passed_through_block
@@ -724,126 +800,37 @@ Options:
724
800
  assert_equal @goat, boat
725
801
  end
726
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
+
727
817
  def test_version_and_help_override_errors
728
818
  @p.opt :asdf, "desc", :type => String
729
819
  @p.version "version"
730
820
  @p.parse %w(--asdf goat)
731
- assert_raises(CommandlineError) { @p.parse %w(--asdf) }
821
+ assert_raises_errmatch(CommandlineError, /option '--asdf' needs a parameter/) { @p.parse %w(--asdf) }
732
822
  assert_raises(HelpNeeded) { @p.parse %w(--asdf --help) }
733
823
  assert_raises(VersionNeeded) { @p.parse %w(--asdf --version) }
734
824
  end
735
825
 
736
- def test_conflicts
737
- @p.opt :one
738
- assert_raises(ArgumentError) { @p.conflicts :one, :two }
739
- @p.opt :two
740
- @p.conflicts :one, :two
741
- @p.parse %w(--one)
742
- @p.parse %w(--two)
743
- assert_raises(CommandlineError) { @p.parse %w(--one --two) }
744
-
745
- @p.opt :hello
746
- @p.opt :yellow
747
- @p.opt :mellow
748
- @p.opt :jello
749
- @p.conflicts :hello, :yellow, :mellow, :jello
750
- assert_raises(CommandlineError) { @p.parse %w(--hello --yellow --mellow --jello) }
751
- assert_raises(CommandlineError) { @p.parse %w(--hello --mellow --jello) }
752
- assert_raises(CommandlineError) { @p.parse %w(--hello --jello) }
753
-
754
- @p.parse %w(--hello)
755
- @p.parse %w(--jello)
756
- @p.parse %w(--yellow)
757
- @p.parse %w(--mellow)
758
-
759
- @p.parse %w(--mellow --one)
760
- @p.parse %w(--mellow --two)
761
-
762
- assert_raises(CommandlineError) { @p.parse %w(--mellow --two --jello) }
763
- assert_raises(CommandlineError) { @p.parse %w(--one --mellow --two --jello) }
764
- end
765
-
766
- def test_either
767
- @p.opt :one
768
- assert_raises(ArgumentError) { @p.either :one, :two }
769
- @p.opt :two
770
- @p.either :one, :two
771
- @p.parse %w(--one)
772
- @p.parse %w(--two)
773
- assert_raises(CommandlineError) { @p.parse %w(--one --two) }
774
- assert_raises(CommandlineError) { @p.parse %w() }
775
-
776
- @p.opt :hello
777
- @p.opt :yellow
778
- @p.opt :mellow
779
- @p.opt :jello
780
- @p.either :hello, :yellow, :mellow, :jello
781
- assert_raises(CommandlineError) { @p.parse %w(--hello --yellow --mellow --jello) }
782
- assert_raises(CommandlineError) { @p.parse %w(--hello --mellow --jello) }
783
- assert_raises(CommandlineError) { @p.parse %w(--hello --jello) }
784
-
785
- @p.parse %w(--hello --one)
786
- @p.parse %w(--jello --two)
787
- @p.parse %w(--mellow --one)
788
- @p.parse %w(--mellow --two)
789
-
790
- assert_raises(CommandlineError) { @p.parse %w(--mellow --two --jello) }
791
- assert_raises(CommandlineError) { @p.parse %w(--one --mellow --two --jello) }
792
- end
793
-
794
- def test_conflict_error_messages
795
- @p.opt :one
796
- @p.opt "two"
797
- @p.conflicts :one, "two"
798
-
799
- assert_raises(CommandlineError, /--one.*--two/) { @p.parse %w(--one --two) }
800
- end
801
-
802
- def test_depends
803
- @p.opt :one
804
- assert_raises(ArgumentError) { @p.depends :one, :two }
805
- @p.opt :two
806
- @p.depends :one, :two
807
- @p.parse %w(--one --two)
808
- assert_raises(CommandlineError) { @p.parse %w(--one) }
809
- assert_raises(CommandlineError) { @p.parse %w(--two) }
810
-
811
- @p.opt :hello
812
- @p.opt :yellow
813
- @p.opt :mellow
814
- @p.opt :jello
815
- @p.depends :hello, :yellow, :mellow, :jello
816
- @p.parse %w(--hello --yellow --mellow --jello)
817
- assert_raises(CommandlineError) { @p.parse %w(--hello --mellow --jello) }
818
- assert_raises(CommandlineError) { @p.parse %w(--hello --jello) }
819
-
820
- assert_raises(CommandlineError) { @p.parse %w(--hello) }
821
- assert_raises(CommandlineError) { @p.parse %w(--mellow) }
822
-
823
- @p.parse %w(--hello --yellow --mellow --jello --one --two)
824
- @p.parse %w(--hello --yellow --mellow --jello --one --two a b c)
825
-
826
- assert_raises(CommandlineError) { @p.parse %w(--mellow --two --jello --one) }
827
- end
828
-
829
- def test_depend_error_messages
830
- @p.opt :one
831
- @p.opt "two"
832
- @p.depends :one, "two"
833
-
834
- @p.parse %w(--one --two)
835
-
836
- assert_raises(CommandlineError, /--one.*--two/) { @p.parse %w(--one) }
837
- assert_raises(CommandlineError, /--one.*--two/) { @p.parse %w(--two) }
838
- end
839
826
 
840
827
  ## courtesy neill zero
841
828
  def test_two_required_one_missing_accuses_correctly
842
829
  @p.opt "arg1", "desc1", :required => true
843
830
  @p.opt "arg2", "desc2", :required => true
844
831
 
845
- assert_raises(CommandlineError, /arg2/) { @p.parse(%w(--arg1)) }
846
- 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)) }
847
834
  @p.parse(%w(--arg1 --arg2))
848
835
  end
849
836
 
@@ -1005,7 +992,10 @@ Options:
1005
992
  opts = @p.parse %w(--arg3 stdin)
1006
993
  assert_equal $stdin, opts[:arg3]
1007
994
 
1008
- assert_raises(CommandlineError) { opts = @p.parse %w(--arg /fdasfasef/fessafef/asdfasdfa/fesasf) }
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
+ }
1009
999
  end
1010
1000
 
1011
1001
  def test_openstruct_style_access
@@ -1106,6 +1096,86 @@ Options:
1106
1096
  assert opts[:ccd]
1107
1097
  end
1108
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
+
1109
1179
  def test_accepts_arguments_with_spaces
1110
1180
  @p.opt :arg1, "arg", :type => String
1111
1181
  @p.opt :arg2, "arg2", :type => String
@@ -1163,7 +1233,7 @@ Options:
1163
1233
  end
1164
1234
 
1165
1235
  def test_simple_interface_handles_die
1166
- assert_stderr do
1236
+ assert_stderr(/Error: argument --potato is invalid/) do
1167
1237
  ::Optimist::options(%w(--potato)) do
1168
1238
  opt :potato
1169
1239
  end
@@ -1172,7 +1242,7 @@ Options:
1172
1242
  end
1173
1243
 
1174
1244
  def test_simple_interface_handles_die_without_message
1175
- assert_stderr(/Error:/) do
1245
+ assert_stderr(/Error: potato\./) do
1176
1246
  ::Optimist::options(%w(--potato)) do
1177
1247
  opt :potato
1178
1248
  end
@@ -1181,7 +1251,7 @@ Options:
1181
1251
  end
1182
1252
 
1183
1253
  def test_invalid_option_with_simple_interface
1184
- assert_stderr do
1254
+ assert_stderr(/Error: unknown argument \'--potato\'\./) do
1185
1255
  assert_raises(SystemExit) do
1186
1256
  ::Optimist.options(%w(--potato))
1187
1257
  end
@@ -1197,7 +1267,7 @@ Options:
1197
1267
  end
1198
1268
 
1199
1269
  def test_supports_callback_inline
1200
- assert_raises(RuntimeError, "good") do
1270
+ assert_raises_errmatch(RuntimeError, "good") do
1201
1271
  @p.opt :cb1 do |vals|
1202
1272
  raise "good"
1203
1273
  end
@@ -1206,7 +1276,7 @@ Options:
1206
1276
  end
1207
1277
 
1208
1278
  def test_supports_callback_param
1209
- assert_raises(RuntimeError, "good") do
1279
+ assert_raises_errmatch(RuntimeError, "good") do
1210
1280
  @p.opt :cb1, "with callback", :callback => lambda { |vals| raise "good" }
1211
1281
  @p.parse(%w(--cb1))
1212
1282
  end
@@ -1261,6 +1331,37 @@ Options:
1261
1331
  assert opts[:arg1]
1262
1332
  assert_equal %w{-bu potato}, @p.leftovers
1263
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
1264
1365
  end
1265
1366
 
1266
1367
  end