user-choices 1.1.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.
Files changed (41) hide show
  1. data/History.txt +17 -0
  2. data/LICENSE.txt +34 -0
  3. data/Manifest.txt +40 -0
  4. data/README.txt +1 -0
  5. data/Rakefile +19 -0
  6. data/Rakefile.hoe +24 -0
  7. data/examples/older/README.txt +133 -0
  8. data/examples/older/command-line.rb +51 -0
  9. data/examples/older/default-values.rb +47 -0
  10. data/examples/older/multiple-sources.rb +63 -0
  11. data/examples/older/postprocess.rb +45 -0
  12. data/examples/older/switches.rb +50 -0
  13. data/examples/older/two-args.rb +37 -0
  14. data/examples/older/types.rb +67 -0
  15. data/examples/tutorial/index.html +648 -0
  16. data/examples/tutorial/tutorial1.rb +48 -0
  17. data/examples/tutorial/tutorial2.rb +52 -0
  18. data/examples/tutorial/tutorial3.rb +55 -0
  19. data/examples/tutorial/tutorial4.rb +55 -0
  20. data/examples/tutorial/tutorial5.rb +42 -0
  21. data/examples/tutorial/tutorial6.rb +42 -0
  22. data/examples/tutorial/tutorial7.rb +48 -0
  23. data/lib/user-choices/arglist-strategies.rb +178 -0
  24. data/lib/user-choices/builder.rb +89 -0
  25. data/lib/user-choices/command-line-source.rb +220 -0
  26. data/lib/user-choices/command.rb +42 -0
  27. data/lib/user-choices/conversions.rb +154 -0
  28. data/lib/user-choices/ruby-extensions.rb +20 -0
  29. data/lib/user-choices/sources.rb +269 -0
  30. data/lib/user-choices/version.rb +3 -0
  31. data/lib/user-choices.rb +131 -0
  32. data/setup.rb +1585 -0
  33. data/test/arglist-strategy-tests.rb +42 -0
  34. data/test/builder-tests.rb +569 -0
  35. data/test/command-line-source-tests.rb +443 -0
  36. data/test/conversion-tests.rb +157 -0
  37. data/test/set-standalone-test-paths.rb +5 -0
  38. data/test/source-tests.rb +442 -0
  39. data/test/user-choices-slowtests.rb +274 -0
  40. data/user-choices.tmproj +575 -0
  41. metadata +138 -0
@@ -0,0 +1,443 @@
1
+ load "set-standalone-test-paths.rb" unless $started_from_rakefile
2
+ require 'test/unit'
3
+ require 's4t-utils'
4
+ require 'builder'
5
+ require 'user-choices'
6
+ include S4tUtils
7
+
8
+ ### Handling of options with arguments ###
9
+
10
+ class CommandLineTestCase < Test::Unit::TestCase
11
+ include UserChoices
12
+
13
+ def setup
14
+ @cmd_line = CommandLineSource.new
15
+ end
16
+
17
+ def default_test
18
+ end
19
+ end
20
+
21
+ class OPTIONS_CommandLineTests < CommandLineTestCase
22
+ def test_options_can_be_given_in_the_command_line
23
+ with_command_args('--given-option value') {
24
+ @cmd_line.uses_option(:given_option, "--given-option VALUE")
25
+ @cmd_line.fill
26
+
27
+ assert_true(@cmd_line.has_key?(:given_option))
28
+ assert_equal("value", @cmd_line[:given_option])
29
+
30
+ assert_false(@cmd_line.has_key?(:unspecified_option))
31
+ assert_equal(nil, @cmd_line[:unspecified_option])
32
+ }
33
+ end
34
+
35
+ def test_the_specification_can_describe_options_that_are_not_given
36
+ # They're really /optional/.
37
+ with_command_args('') {
38
+ @cmd_line.uses_option(:unused_option, "--unused-option VALUE")
39
+ @cmd_line.fill
40
+
41
+ assert_false(@cmd_line.has_key?(:unused_option))
42
+ assert_equal(nil, @cmd_line[:unused_option])
43
+ }
44
+ end
45
+
46
+ def test_options_can_have_one_letter_abbreviations
47
+ with_command_args('-s s-value --option=option-value') {
48
+ @cmd_line.uses_option(:option, "-o", "--option=VALUE")
49
+ @cmd_line.uses_option(:something, "-s", "--something=VALUE")
50
+ @cmd_line.fill
51
+
52
+ assert_equal("s-value", @cmd_line[:something])
53
+ assert_equal("option-value", @cmd_line[:option])
54
+ }
55
+ end
56
+
57
+
58
+
59
+ def test_command_line_list_of_possible_values_checking
60
+ with_command_args("-n true") do
61
+ @cmd_line.uses_option(:north_west, "-n", "--north-west=VALUE")
62
+ @cmd_line.fill
63
+ output = capturing_stderr do
64
+ assert_wants_to_exit do
65
+ @cmd_line.apply({:north_west => [Conversion.for(['low', 'high'])]})
66
+ end
67
+ end
68
+ assert_match(%r{Error in the command line: --north-west's value}, output)
69
+ end
70
+ end
71
+
72
+ def test_command_line_integer_value_checking
73
+ with_command_args("--day-count-max=2d3") do
74
+ @cmd_line.uses_option(:day_count_max, "--day-count-max=VALUE")
75
+ @cmd_line.fill
76
+ output = capturing_stderr do
77
+ assert_wants_to_exit do
78
+ @cmd_line.apply({:day_count_max => [Conversion.for(:integer)]})
79
+ end
80
+ end
81
+ assert_match(/^Error in the command line: --day-count-max's value/, output)
82
+ end
83
+ end
84
+
85
+
86
+ def test_integer_conversion
87
+ with_command_args("--day-count-max 23") do
88
+ @cmd_line.uses_option(:day_count_max, "--day-count-max=VALUE")
89
+ @cmd_line.fill
90
+ @cmd_line.apply({:day_count_max => [Conversion.for(:integer)]})
91
+ assert_equal(23, @cmd_line[:day_count_max])
92
+ end
93
+ end
94
+
95
+ def test_array_value_conversion_with_proper_multivalue_declaration
96
+ with_command_args("--hosts localhost,foo.com") do
97
+ @cmd_line.uses_option(:hosts, "--hosts HOST,HOST")
98
+ @cmd_line.fill
99
+ @cmd_line.apply({:hosts => [Conversion.for([:string])]})
100
+ assert_equal(['localhost', 'foo.com'],
101
+ @cmd_line[:hosts])
102
+ end
103
+ end
104
+
105
+ def test_array_value_conversion_without_proper_multivalue_declaration_still_works
106
+ with_command_args("--hosts localhost,foo.com") do
107
+ @cmd_line.uses_option(:hosts, "--hosts HOSTS...")
108
+ @cmd_line.fill
109
+ @cmd_line.apply({:hosts => [Conversion.for([:string])]})
110
+ assert_equal(['localhost', 'foo.com'],
111
+ @cmd_line[:hosts])
112
+ end
113
+ end
114
+
115
+ end
116
+
117
+
118
+
119
+ ### Boolean switches ###
120
+
121
+ # Note that switches are string-valued for consistency with
122
+ # other sources (like environment variables).
123
+ class SWITCHES_CommandLineTest < CommandLineTestCase
124
+
125
+ def test_boolean_switches_are_accepted
126
+ with_command_args("--c") do
127
+ @cmd_line.uses_switch(:csv, "-c", "--csv")
128
+ @cmd_line.fill
129
+ assert_equal("true", @cmd_line[:csv])
130
+
131
+ # ... but they can be converted into booleans
132
+ @cmd_line.apply({:csv => [Conversion.for(:boolean)]})
133
+ assert_equal(true, @cmd_line[:csv])
134
+ end
135
+ end
136
+
137
+ def test_unmentioned_switches_have_no_value
138
+ with_command_args("") do
139
+ @cmd_line.uses_switch(:csv, "-c", "--csv")
140
+ @cmd_line.fill
141
+ assert_false(@cmd_line.has_key?(:csv))
142
+ end
143
+ end
144
+
145
+ def test_switches_can_be_explicitly_false
146
+ with_command_args("--no-csv") do
147
+ @cmd_line.uses_switch(:csv, "-c", "--csv")
148
+ @cmd_line.fill
149
+ assert_equal("false", @cmd_line[:csv])
150
+ end
151
+ end
152
+ end
153
+
154
+
155
+ ### Argument Lists ###
156
+
157
+ # Arguments lists are treated as another option.
158
+ class ARGLISTS_CommandLineTest < CommandLineTestCase
159
+
160
+ def test_by_default_arglists_are_not_allowed
161
+ # Note that the error check is done at fill time, not apply time.
162
+ with_command_args("one") {
163
+ output = capturing_stderr do
164
+ assert_wants_to_exit do
165
+ @cmd_line.fill
166
+ end
167
+ end
168
+
169
+ assert_match(/^Error in the command line: No arguments are allowed./, output)
170
+ }
171
+ end
172
+
173
+ def test_empty_arglists_are_OK_if_arglist_not_described
174
+ with_command_args("") {
175
+ output = capturing_stderr do
176
+ @cmd_line.fill
177
+ end
178
+ assert_equal("", output) # No error message
179
+ }
180
+ end
181
+
182
+ def test_arglist_after_options_can_turned_into_an_option
183
+ with_command_args("--unused unused arg1 arg2") {
184
+ @cmd_line.uses_option(:unused, "--unused VALUE") # just for grins
185
+ @cmd_line.uses_arglist(:args)
186
+ @cmd_line.fill
187
+ assert_true(@cmd_line.has_key?(:args))
188
+ assert_equal(["arg1", "arg2"], @cmd_line[:args])
189
+ }
190
+ end
191
+
192
+ def test_arglist_can_check_allowable_number_of_arguments
193
+ with_command_args("--unused unused arg1 arg2") {
194
+ @cmd_line.uses_option(:unused, "--unused VALUE") # just for grins
195
+ @cmd_line.uses_arglist(:args)
196
+ @cmd_line.fill
197
+ @cmd_line.apply({:args => [Conversion.for({:length => 2})]})
198
+ assert_true(@cmd_line.has_key?(:args))
199
+ assert_equal(["arg1", "arg2"], @cmd_line[:args])
200
+ }
201
+ end
202
+
203
+ def test_error_if_exact_arglist_number_is_wrong
204
+ with_command_args("arg1 arg2") {
205
+ @cmd_line.uses_arglist(:args)
206
+ @cmd_line.fill
207
+ output = capturing_stderr do
208
+ assert_wants_to_exit do
209
+ @cmd_line.apply({:args => [Conversion.for({:length => 3})]})
210
+ end
211
+ end
212
+ assert_match(/^Error in the command line:.*2 arguments given, 3 expected./, output)
213
+ }
214
+ end
215
+
216
+ def test_arglist_arity_can_be_a_range
217
+ with_command_args("arg1 arg2") {
218
+ @cmd_line.uses_arglist(:args)
219
+ @cmd_line.fill
220
+ @cmd_line.apply({:args => [Conversion.for({:length => 1..2})]})
221
+ assert_true(@cmd_line.has_key?(:args))
222
+ assert_equal(["arg1", "arg2"], @cmd_line[:args])
223
+ }
224
+ end
225
+
226
+
227
+ def test_error_if_arglist_does_not_match_range
228
+ with_command_args("arg1 arg2") {
229
+ @cmd_line.uses_arglist(:args)
230
+ @cmd_line.fill
231
+ output = capturing_stderr do
232
+ assert_wants_to_exit do
233
+ @cmd_line.apply({:args => [Conversion.for({:length => 3..6})]})
234
+ end
235
+ end
236
+ assert_match(/^Error in the command line:.*2 arguments given, 3 to 6 expected./, output)
237
+ }
238
+ end
239
+
240
+ def test_arglist_external_name_is_friendly
241
+ @cmd_line.uses_arglist(:fred)
242
+ assert_equal("the argument list", @cmd_line.external_names[:fred])
243
+ end
244
+
245
+ def test_deep_copy_of_conversion_map
246
+ map = { :choice => [Conversion.for([:string]), Conversion.for(:length => 3)]}
247
+ copy = @cmd_line.deep_copy(map)
248
+ assert_not_equal(map[:choice].collect { |c| c.object_id },
249
+ copy[:choice].collect { |c| c.object_id })
250
+ assert_true(copy[:choice][0].class.described_by?([:string]))
251
+ assert_true(copy[:choice][1].class.described_by?(:length => 3))
252
+
253
+ map.delete(:choice)
254
+ assert_false(map.has_key?(:choice))
255
+ assert_true(copy.has_key?(:choice))
256
+ end
257
+ end
258
+
259
+ class ARG_CommandLineTest < CommandLineTestCase
260
+ include UserChoices
261
+
262
+
263
+ def test_a_singleton_arg_will_not_be_in_a_list
264
+ with_command_args("arg-only") {
265
+ @cmd_line.uses_option(:unused, "--unused VALUE") # just for grins
266
+ @cmd_line.uses_arg(:arg)
267
+ @cmd_line.fill
268
+ assert_true(@cmd_line.has_key?(:arg))
269
+ assert_equal("arg-only", @cmd_line[:arg])
270
+ }
271
+ end
272
+
273
+ def test_singleton_args_are_incompatible_with_length_checks
274
+ # Because the missing argument might be filled in by other chained sources.
275
+ with_command_args("1") {
276
+ @cmd_line.uses_arg(:arg)
277
+ @cmd_line.fill
278
+ assert_raises_with_matching_message(StandardError, "Don't specify the length of an argument list when it's not treated as an array.") {
279
+ @cmd_line.apply({:arg => [Conversion.for(:length => 1)]})
280
+ }
281
+ }
282
+ end
283
+
284
+
285
+
286
+ def test_extra_singleton_args_generate_errors
287
+ # Note that it's caught in the 'fill' step.
288
+ with_command_args("1 2") {
289
+ @cmd_line.uses_arg(:arg)
290
+ output = capturing_stderr do
291
+ assert_wants_to_exit do
292
+ @cmd_line.fill
293
+ end
294
+ end
295
+ assert_match(/^Error in the command line: .*2 arguments given, 1 expected/, output)
296
+ }
297
+ end
298
+
299
+ def test_singleton_arguments_can_be_optional
300
+ with_command_args("") {
301
+ @cmd_line.uses_optional_arg(:arg)
302
+ @cmd_line.fill
303
+ assert_false(@cmd_line.has_key?(:arg))
304
+ assert_equal(nil, @cmd_line[:arg])
305
+ }
306
+ end
307
+
308
+ def test_optional_arguments_can_be_given
309
+ with_command_args("only") {
310
+ @cmd_line.uses_optional_arg(:arg)
311
+ @cmd_line.fill
312
+ assert_equal('only', @cmd_line[:arg])
313
+ }
314
+ end
315
+
316
+
317
+ def test_that_optional_singleton_arguments_still_precludes_two
318
+ # Note that the error check is done at fill time, not apply time.
319
+ with_command_args("one two") {
320
+ @cmd_line.uses_optional_arg(:arg)
321
+ output = capturing_stderr do
322
+ assert_wants_to_exit do
323
+ @cmd_line.fill
324
+ end
325
+ end
326
+ assert_match(/^Error in the command line:.*2 arguments given, 0 or 1 expected./, output)
327
+ }
328
+ end
329
+
330
+ def test_arg_external_name_is_friendly
331
+ @cmd_line.uses_arg(:fred)
332
+ assert_equal("the argument list", @cmd_line.external_names[:fred])
333
+ end
334
+
335
+
336
+ def test_optional_arg_external_name_is_friendly
337
+ @cmd_line.uses_optional_arg(:fred)
338
+ assert_equal("the argument list", @cmd_line.external_names[:fred])
339
+ end
340
+
341
+ end
342
+
343
+ ### Option-Handling Style ###
344
+
345
+ class OPTION_STYLE_CommandLineTest < CommandLineTestCase
346
+ include UserChoices
347
+
348
+ def define(klass)
349
+ @cmd_line = klass.new
350
+ @cmd_line.uses_switch(:switch, "--switch")
351
+ @cmd_line.uses_arglist(:args)
352
+ @cmd_line.fill
353
+ end
354
+
355
+ def test_default_style_is_permutation
356
+ with_command_args('3 --switch 5') {
357
+ define(CommandLineSource)
358
+ assert_equal('true', @cmd_line[:switch])
359
+ assert_equal(['3', '5'], @cmd_line[:args])
360
+ }
361
+ end
362
+
363
+ def test_subclass_allows_all_options_before_arguments
364
+ with_command_args('3 --switch 5') {
365
+ define(PosixCommandLineSource)
366
+ assert_equal(nil, @cmd_line[:switch])
367
+ assert_equal(['3', '--switch', '5'], @cmd_line[:args])
368
+ }
369
+ end
370
+
371
+ def test_choosing_posix_parsing_does_not_override_environment_variable
372
+ with_environment_vars('POSIXLY_CORRECT' => 'hello') do
373
+ with_command_args('3 --switch 5') {
374
+ define(PosixCommandLineSource)
375
+ assert_equal('hello', ENV['POSIXLY_CORRECT'])
376
+ }
377
+ end
378
+ end
379
+
380
+ end
381
+
382
+ ### Error Handling ###
383
+
384
+ # Additional commandline-specific error checking.
385
+ class ERROR_CommandLineTest < CommandLineTestCase
386
+ include UserChoices
387
+
388
+ def test_invalid_option_produces_error_message_and_exit
389
+ with_command_args('--doofus 3') {
390
+ output = capturing_stderr do
391
+ assert_wants_to_exit do
392
+ @cmd_line.uses_option(:doofus, "--option VALUE")
393
+ @cmd_line.fill
394
+ end
395
+ end
396
+
397
+ assert_match(/invalid option.*doofus/, output)
398
+ }
399
+ end
400
+
401
+ def test_error_is_identified_as_coming_from_the_command_line
402
+ with_command_args('--doofus') {
403
+ output = capturing_stderr do
404
+ assert_wants_to_exit do
405
+ @cmd_line.uses_option(:doofus, "--doofus VALUE")
406
+ @cmd_line.fill
407
+ end
408
+ end
409
+
410
+ assert_match(/^Error in the command line:.*missing argument.*doofus/, output)
411
+ }
412
+ end
413
+
414
+ def test_errors_cause_usage_style_output
415
+ with_command_args('wanted --wanted') {
416
+ output = capturing_stderr do
417
+ assert_wants_to_exit do
418
+ default_isbn = "343"
419
+ @cmd_line.help_banner("Usage: ruby prog [options] [isbn]",
420
+ "This and further strings are optional.")
421
+ @cmd_line.uses_option(:option, "-o", "--option=VALUE",
422
+ "Message about option",
423
+ "More about option")
424
+ @cmd_line.fill
425
+ end
426
+ end
427
+
428
+ lines = output.split($/)
429
+ # puts output
430
+ assert_match(/^Error in the command line: /, lines[0])
431
+ assert_equal("Usage: ruby prog [options] [isbn]", lines[1])
432
+ assert_match(/This and further/, lines[2])
433
+ assert_match(/\s*/, lines[3])
434
+ assert_match(/Options:/, lines[4])
435
+ assert_match(/-o.*--option=VALUE.*Message about option/, lines[5])
436
+ assert_match(/More about option/, lines[6])
437
+ assert_match(/--help.*Show this message/, lines.last)
438
+ }
439
+ end
440
+
441
+ end
442
+
443
+
@@ -0,0 +1,157 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created by Brian Marick on 2007-08-06.
4
+ # Copyright (c) 2007. All rights reserved.
5
+
6
+ load "set-standalone-test-paths.rb" unless $started_from_rakefile
7
+ require 'test/unit'
8
+ require 's4t-utils'
9
+ require 'user-choices'
10
+ include S4tUtils
11
+
12
+
13
+ class TestDefaultsAndTypes < Test::Unit::TestCase
14
+ include UserChoices
15
+
16
+ def test_correct_conversion_objects_are_chosen
17
+ start = []
18
+ Conversion.record_for(:integer, start)
19
+ Conversion.record_for(:boolean, start)
20
+ Conversion.record_for([:string], start)
21
+ Conversion.record_for(["one", "two"], start)
22
+ Conversion.record_for({:length => 1}, start)
23
+ Conversion.record_for({:length => 1..2}, start)
24
+
25
+ assert_equal([ConversionToInteger, ConversionToBoolean,
26
+ SplittingConversion, ChoiceCheckingConversion,
27
+ ExactLengthConversion, RangeLengthConversion],
28
+ start.collect { |c| c.class })
29
+ end
30
+
31
+ def test_nil_conversion_tags_do_nothing
32
+ start = []
33
+ Conversion.record_for(nil, start)
34
+ assert_equal([], start)
35
+ end
36
+
37
+ def test_integer_conversion_checking
38
+ c2i = Conversion.for(:integer)
39
+ assert_true(c2i.suitable?("034"))
40
+ assert_false(c2i.suitable?("0x1d"))
41
+ assert_false(c2i.suitable?(["0x1d"]))
42
+ assert_equal('an integer', c2i.description)
43
+ end
44
+
45
+ def test_integer_conversion
46
+ c2i = Conversion.for(:integer)
47
+ assert_equal(12, c2i.convert("12"))
48
+ end
49
+
50
+ def test_it_is_ok_for_integers_already_to_be_converted
51
+ c2i = Conversion.for(:integer)
52
+ assert_true(c2i.suitable?(12))
53
+ assert_equal(12, c2i.convert(12))
54
+ end
55
+
56
+
57
+
58
+ def test_boolean_conversion_checking
59
+ c2b = Conversion.for(:boolean)
60
+ assert_true(c2b.suitable?("true"))
61
+ assert_true(c2b.suitable?("false"))
62
+ # Case insensitive
63
+ assert_true(c2b.suitable?("False"))
64
+ assert_true(c2b.suitable?("TRUE"))
65
+
66
+ assert_false(c2b.suitable?("tru"))
67
+ assert_false(c2b.suitable?(1))
68
+ assert_equal('a boolean', c2b.description)
69
+ end
70
+
71
+ def test_boolean_conversion
72
+ c = Conversion.for(:boolean)
73
+ assert_equal(false, c.convert("FalsE"))
74
+ assert_equal(true, c.convert("true"))
75
+ end
76
+
77
+ def test_it_is_ok_for_booleans_already_to_be_converted
78
+ c = Conversion.for(:boolean)
79
+ assert_true(c.suitable?(true))
80
+ assert_equal(false, c.convert(false))
81
+ end
82
+
83
+
84
+
85
+
86
+
87
+ def test_any_string_is_accepted_for_splitting_conversion
88
+ s = Conversion.for([:string])
89
+ assert_true(s.suitable?("tru calling"))
90
+ assert_true(s.suitable?("fa,se"))
91
+ assert_false(s.suitable?(1))
92
+ end
93
+
94
+ def test_splitting
95
+ c = Conversion.for([:string])
96
+ assert_equal(["one"], c.convert("one"))
97
+ assert_equal(["one", "two"], c.convert("one,two"))
98
+ # Whitespace NOT ignored
99
+ assert_equal(["one", " two"], c.convert("one, two"))
100
+ end
101
+
102
+ def test_it_is_ok_for_values_already_to_be_split
103
+ c = Conversion.for([:string])
104
+ assert_true(c.suitable?(["one", "two"]))
105
+ assert_equal(["one", "two"], c.convert(["one", "two"]))
106
+ end
107
+
108
+
109
+
110
+
111
+ def test_choice_checking_conversion
112
+ cc = Conversion.for(["foo", "bar"])
113
+ assert_true(cc.suitable?("foo"))
114
+ assert_true(cc.suitable?("bar"))
115
+
116
+ assert_false(cc.suitable?("fred"))
117
+ # Case sensitive
118
+ assert_false(cc.suitable?("FOO"))
119
+ assert_equal("one of 'foo' or 'bar'", cc.description)
120
+ end
121
+
122
+ def test_choice_checking_does_no_conversion
123
+ cc = Conversion.for(["foo", "bar"])
124
+ assert_equal("foo", cc.convert("foo"))
125
+ end
126
+
127
+
128
+ def test_length_conversion_with_exact_length
129
+ c = Conversion.for(:length => 1)
130
+ assert_true(c.suitable?([1]))
131
+ assert_false(c.suitable?([]))
132
+ assert_false(c.suitable?([1, 2]))
133
+ assert_false(c.suitable?("not array"))
134
+
135
+ assert_equal("of length 1", c.description)
136
+ end
137
+
138
+ def test_length_conversion_with_exact_length_does_no_conversion
139
+ c = Conversion.for(:length => 1)
140
+ assert_equal(["foo"], c.convert(["foo"]))
141
+ end
142
+
143
+ def test_length_conversion_with_range
144
+ c = Conversion.for(:length => 0..1)
145
+ assert_true(c.suitable?([1]))
146
+ assert_true(c.suitable?([]))
147
+ assert_false(c.suitable?([1, 2]))
148
+
149
+ assert_equal("a list whose length is in this range: 0..1", c.description)
150
+ end
151
+
152
+ def test_length_conversion_with_range_does_no_conversion
153
+ c = Conversion.for(:length => 0..1)
154
+ assert_equal(["foo"], c.convert(["foo"]))
155
+ end
156
+
157
+ end
@@ -0,0 +1,5 @@
1
+ require 'pathname'
2
+
3
+ PACKAGE_ROOT = Pathname.new(__FILE__).parent.parent.to_s
4
+ $:.unshift("#{PACKAGE_ROOT}/lib")
5
+ require 's4t-utils/load-path-auto-adjuster'