optimist 3.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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"], [])
@@ -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
@@ -310,25 +372,29 @@ class ParserTest < ::MiniTest::Test
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
 
@@ -1004,8 +991,11 @@ Options:
1004
991
 
1005
992
  opts = @p.parse %w(--arg3 stdin)
1006
993
  assert_equal $stdin, opts[:arg3]
1007
-
1008
- 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
+ }
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