benry-cmdopt 2.3.0 → 2.4.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.
@@ -0,0 +1,197 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ require_relative './shared'
5
+
6
+
7
+ Oktest.scope do
8
+
9
+
10
+ topic Benry::CmdOpt::Facade do
11
+
12
+
13
+ topic '#add()' do
14
+
15
+ spec "[!vmb3r] defines command option." do
16
+ cmdopt = Benry::CmdOpt.new()
17
+ cmdopt.add(:help, "-h, --help", "show help message", detail: "(text)", tag: :important)
18
+ items = cmdopt.instance_eval { @schema.instance_variable_get('@items') }
19
+ ok {items}.is_a?(Array)
20
+ ok {items.length} == 1
21
+ ok {items[0].key} == :help
22
+ ok {items[0].short} == 'h'
23
+ ok {items[0].long} == 'help'
24
+ ok {items[0].desc} == 'show help message'
25
+ ok {items[0].detail} == '(text)'
26
+ ok {items[0].tag} == :important
27
+ end
28
+
29
+ spec "[!71cvg] type, rexp, enum, and range are can be passed as positional args as well as keyword args." do
30
+ cmdopt = Benry::CmdOpt.new()
31
+ cmdopt.add(:key, "--optdef[=xx]", "desc", Integer, /\A\d+\z/, [2,4,8], (2..8), value: 4)
32
+ items = cmdopt.instance_eval { @schema.instance_variable_get('@items') }
33
+ item = items.first
34
+ ok {item.type} == Integer
35
+ ok {item.rexp} == /\A\d+\z/
36
+ ok {item.enum} == [2,4,8]
37
+ ok {item.range} == (2..8)
38
+ ok {item.value} == 4
39
+ end
40
+
41
+ spec "[!tu4k3] returns self." do
42
+ cmdopt = Benry::CmdOpt.new()
43
+ x = cmdopt.add(:version, "-v, --version", "version")
44
+ ok {x}.same?(cmdopt)
45
+ end
46
+
47
+ end
48
+
49
+
50
+ topic '#option_help()' do
51
+
52
+ before do
53
+ @cmdopt = Benry::CmdOpt.new
54
+ @cmdopt.add(:help , "-h, --help" , "show help message")
55
+ @cmdopt.add(:version, " --version" , "print version")
56
+ @cmdopt.add(:file , "-f, --file=<FILE>" , "filename")
57
+ end
58
+
59
+ spec "[!dm4p8] returns option help message." do
60
+ helpmsg = @cmdopt.option_help()
61
+ ok {helpmsg} == <<END
62
+ -h, --help : show help message
63
+ --version : print version
64
+ -f, --file=<FILE> : filename
65
+ END
66
+ end
67
+
68
+ end
69
+
70
+
71
+ topic '#to_s()' do
72
+
73
+ spec "[!s61vo] '#to_s' is an alias to '#option_help()'." do
74
+ cmdopt = Benry::CmdOpt.new
75
+ cmdopt.add(:help , "-h, --help" , "show help message")
76
+ cmdopt.add(:version, " --version" , "print version")
77
+ ok {cmdopt.to_s} == cmdopt.option_help()
78
+ end
79
+
80
+ end
81
+
82
+
83
+ topic '#each_option_and_desc()' do
84
+
85
+ before do
86
+ @cmdopt = Benry::CmdOpt.new
87
+ @cmdopt.add(:help , "-h, --help" , "show help message")
88
+ @cmdopt.add(:version, " --version" , "print version")
89
+ @cmdopt.add(:debug , "-D" , nil) # hidden option
90
+ @cmdopt.add(:trace , "-T" , "trace", hidden: true) # hidden option
91
+ end
92
+
93
+ spec "[!bw9qx] yields each option definition string and help message." do
94
+ pairs = []
95
+ @cmdopt.each_option_and_desc {|opt, desc| pairs << [opt, desc] }
96
+ ok {pairs} == [
97
+ ["-h, --help" , "show help message"],
98
+ [" --version", "print version"],
99
+ ]
100
+ end
101
+
102
+ spec "[!kunfw] yields all items (including hidden items) if `all: true` specified." do
103
+ ## when 'all: true'
104
+ pairs = []
105
+ @cmdopt.each_option_and_desc(all: true) {|opt, desc| pairs << [opt, desc] }
106
+ ok {pairs} == [
107
+ ["-h, --help" , "show help message"],
108
+ [" --version", "print version"],
109
+ ["-D" , nil],
110
+ ["-T" , "trace"],
111
+ ]
112
+ ## when 'all: false'
113
+ pairs = []
114
+ @cmdopt.each_option_and_desc(all: false) {|opt, desc| pairs << [opt, desc] }
115
+ ok {pairs} == [
116
+ ["-h, --help" , "show help message"],
117
+ [" --version", "print version"],
118
+ ]
119
+ end
120
+
121
+ spec "[!wght5] returns enumerator object if block not given." do
122
+ ## when 'all: true'
123
+ xs = @cmdopt.each_option_and_desc(all: true)
124
+ ok {xs}.is_a?(Enumerator)
125
+ ok {xs.collect {|x, _| x }} == ["-h, --help", " --version", "-D", "-T"]
126
+ ## when 'all: false'
127
+ xs = @cmdopt.each_option_and_desc(all: false)
128
+ ok {xs}.is_a?(Enumerator)
129
+ ok {xs.collect {|x, _| x }} == ["-h, --help", " --version"]
130
+ end
131
+
132
+ end
133
+
134
+
135
+ topic '#parse()' do
136
+
137
+ before do
138
+ @cmdopt = Benry::CmdOpt.new()
139
+ @cmdopt.add(:file, "-f, --file=<FILE>", "file") do |val|
140
+ File.open(val) {|f| f.read }
141
+ end
142
+ @cmdopt.add(:debug, "-d, --debug[=<LEVEL>]", "debug", type: Integer)
143
+ end
144
+
145
+ spec "[!7gc2m] parses command options." do
146
+ args = ["-d", "x", "y"]
147
+ @cmdopt.parse(args)
148
+ ok {args} == ["x", "y"]
149
+ end
150
+
151
+ spec "[!no4xu] returns option values as dict." do
152
+ args = ["-d", "x"]
153
+ ok {@cmdopt.parse(args)} == {:debug=>true}
154
+ end
155
+
156
+ spec "[!areof] handles only OptionError when block given." do
157
+ errmsg = nil
158
+ errcls = nil
159
+ @cmdopt.parse(["-dx"]) {|err|
160
+ errmsg = err.message
161
+ errcls = err.class
162
+ }
163
+ ok {errmsg} == "-dx: Integer expected."
164
+ ok {errcls} == Benry::CmdOpt::OptionError
165
+ #
166
+ pr = proc do
167
+ @cmdopt.parse(["-f", "/foo/bar/baz.png"])
168
+ end
169
+ ok {pr}.raise?(Errno::ENOENT, /No such file or directory/)
170
+ end
171
+
172
+ spec "[!peuva] returns nil when OptionError handled." do
173
+ ret = @cmdopt.parse(["-dx"]) {|err| 1 }
174
+ ok {ret} == nil
175
+ end
176
+
177
+ spec "[!za9at] parses options only before args when `all: false`." do
178
+ argv = ["aaa", "-d3", "bbb"]
179
+ #
180
+ argv1 = argv.dup
181
+ opts1 = @cmdopt.parse(argv1)
182
+ ok {opts1} == {:debug=>3}
183
+ ok {argv1} == ["aaa", "bbb"]
184
+ #
185
+ argv2 = argv.dup
186
+ opts2 = @cmdopt.parse(argv2, all: false)
187
+ ok {opts2} == {}
188
+ ok {argv2} == ["aaa", "-d3", "bbb"]
189
+ end
190
+
191
+ end
192
+
193
+
194
+ end
195
+
196
+
197
+ end
data/test/item_test.rb ADDED
@@ -0,0 +1,463 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ require_relative './shared'
5
+
6
+
7
+ Oktest.scope do
8
+
9
+
10
+ topic Benry::CmdOpt::SchemaItem do
11
+
12
+ ITEMS = [
13
+ Benry::CmdOpt::SchemaItem.new(:help, "-h, --help", "help msg",
14
+ "h", "help", nil, nil),
15
+ Benry::CmdOpt::SchemaItem.new(:file, "-f, --file=<file>", "filename",
16
+ "f", "file", "<file>", true),
17
+ Benry::CmdOpt::SchemaItem.new(:indent, "-i, --indent[=<N>]", "indent width",
18
+ "i", "indent", "<N>", false),
19
+ ]
20
+
21
+
22
+ topic '#initialize()' do
23
+
24
+ before do
25
+ @schema = Benry::CmdOpt::Schema.new
26
+ end
27
+
28
+ spec "[!nn4cp] freezes enum object." do
29
+ item = Benry::CmdOpt::SchemaItem.new(:foo, "--foo", "desc", nil, "foo", "<val>",
30
+ true, enum: ["x", "y", "z"])
31
+ ok {item.enum} == ["x", "y", "z"]
32
+ ok {item.enum}.frozen?
33
+ end
34
+
35
+ case_when "[!wy2iv] when 'type:' specified..." do
36
+
37
+ spec "[!7xmr5] raises SchemaError when type is not registered." do
38
+ sc = @schema
39
+ pr = proc {
40
+ sc.add(:indent, "-i, --indent[=<WIDTH>]", "indent width", type: Array)
41
+ }
42
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
43
+ "Array: Unregistered type.")
44
+ end
45
+
46
+ spec "[!s2aaj] raises SchemaError when option has no params but type specified." do
47
+ sc = @schema
48
+ pr = proc {
49
+ sc.add(:indent, "-i, --indent", "indent width", type: Integer)
50
+ }
51
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
52
+ "Integer: Type specified in spite of option has no params.")
53
+ end
54
+
55
+ spec "[!sz8x2] not raise error when no params but value specified." do
56
+ sc = @schema
57
+ pr = proc {
58
+ sc.add(:indent, "-i, --indent", "indent width", type: Integer, value: 0)
59
+ }
60
+ ok {pr}.NOT.raise?(Exception)
61
+ end
62
+
63
+ spec "[!70ogf] not raise error when no params but TrueClass specified." do
64
+ sc = @schema
65
+ pr = proc {
66
+ sc.add(:indent, "-i, --indent", "indent width", type: TrueClass)
67
+ }
68
+ ok {pr}.NOT.raise?(Exception)
69
+ end
70
+
71
+ end
72
+
73
+ case_when "[!6y8s2] when 'rexp:' specified..." do
74
+
75
+ spec "[!bi2fh] raises SchemaError when pattern is not a regexp." do
76
+ sc = @schema
77
+ pr = proc {
78
+ sc.add(:indent, "-x, --indent[=<WIDTH>]", "indent width", rexp: '\A\d+\z')
79
+ }
80
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
81
+ '"\\\\A\\\\d+\\\\z": Regexp pattern expected.')
82
+ end
83
+
84
+ spec "[!01fmt] raises SchmeaError when option has no params but pattern specified." do
85
+ sc = @schema
86
+ pr = proc {
87
+ sc.add(:indent, "-i, --indent", "indent width", rexp: /\A\d+\z/)
88
+ }
89
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
90
+ '/\A\d+\z/: Regexp pattern specified in spite of option has no params.')
91
+ end
92
+
93
+ end
94
+
95
+ case_when "[!5nrvq] when 'enum:' specified..." do
96
+
97
+ spec "[!melyd] raises SchemaError when enum is not an Array nor Set." do
98
+ sc = @schema
99
+ sc.add(:indent1, "-i <N>", "indent width", enum: ["2", "4", "8"])
100
+ sc.add(:indent2, "-j <N>", "indent width", enum: Set.new(["2", "4", "8"]))
101
+ pr = proc {
102
+ sc.add(:indent3, "-k <N>", "indent width", enum: "2,4,8")
103
+ }
104
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
105
+ '"2,4,8": Array or set expected.')
106
+ end
107
+
108
+ spec "[!xqed8] raises SchemaError when enum specified for no param option." do
109
+ sc = @schema
110
+ pr = proc {
111
+ sc.add(:indent, "-i", "enable indent", enum: [2, 4, 8])
112
+ }
113
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
114
+ "[2, 4, 8]: Enum specified in spite of option has no params.")
115
+ end
116
+
117
+ spec "[!zuthh] raises SchemaError when enum element value is not instance of type class." do
118
+ sc = @schema
119
+ pr = proc {
120
+ sc.add(:indent, "-i <N>", "enable indent", type: Integer, enum: ['2', '4', '8'])
121
+ }
122
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
123
+ '["2", "4", "8"]: Enum element value should be instance of Integer, but "2" is not.')
124
+ end
125
+
126
+ end
127
+
128
+ case_when "[!hk4nw] when 'range:' specified..." do
129
+
130
+ spec "[!z20ky] raises SchemaError when range is not a Range object." do
131
+ pr = proc {
132
+ @schema.add(:indent, "-i <N>", "indent", type: Integer, range: [1,8])
133
+ }
134
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
135
+ "[1, 8]: Range object expected.")
136
+ end
137
+
138
+ spec "[!gp025] raises SchemaError when range specified with `type: TrueClass`." do
139
+ pr = proc {
140
+ @schema.add(:indent, "-i <N>", "indent", type: TrueClass, range: 0..1)
141
+ }
142
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
143
+ "0..1: Range is not available with `type: TrueClass`.")
144
+ end
145
+
146
+ spec "[!7njd5] range beginning/end value should be expected type." do
147
+ pr = proc {
148
+ @schema.add(:indent, "-i <N>", "indent", range: (1..8))
149
+ }
150
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
151
+ "1..8: Range value should be String, but not.")
152
+ pr = proc {
153
+ @schema.add(:indent, "-i <N>", "indent", type: Date, range: (1..8))
154
+ }
155
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
156
+ "1..8: Range value should be Date, but not.")
157
+ end
158
+
159
+ spec "[!uymig] range object can be endless." do
160
+ begin
161
+ range1 = eval "(1..)" # Ruby >= 2.6
162
+ range2 = eval "(..3)" # Ruby >= 2.6
163
+ rescue SyntaxError
164
+ range1 = nil # Ruby < 2.6
165
+ range2 = nil # Ruby < 2.6
166
+ end
167
+ if range1
168
+ pr = proc {
169
+ @schema.add(:indent1, "-i <N>", "indent", type: Integer, range: range1)
170
+ @schema.add(:indent2, "-j <N>", "indent", type: Integer, range: range2)
171
+ }
172
+ ok {pr}.NOT.raise?(Exception)
173
+ end
174
+ end
175
+
176
+ end
177
+
178
+ case_when "[!a0g52] when 'value:' specified..." do
179
+
180
+ spec "[!435t6] raises SchemaError when 'value:' is specified on argument-required option." do
181
+ sc = @schema
182
+ pr = proc {
183
+ sc.add(:flag, "--flag=<on|off>", "flag", type: TrueClass, value: true)
184
+ }
185
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
186
+ "true: 'value:' is meaningless when option has required argument (hint: change to optional argument instead).")
187
+ end
188
+
189
+ spec "[!6vwqv] raises SchemaError when type is TrueClass but value is not true nor false." do
190
+ sc = @schema
191
+ pr = proc {
192
+ sc.add(:flag, "--flag[=<on|off>]", "flag", type: TrueClass, value: 0)
193
+ }
194
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
195
+ "0: Value should be true or false when `type: TrueClass` specified.")
196
+ end
197
+
198
+ spec "[!c6i2o] raises SchemaError when value is not a kind of type." do
199
+ sc = @schema
200
+ pr = proc {
201
+ sc.add(:flag, "--flag[=<on|off>]", "flag", type: Integer, value: false)
202
+ }
203
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
204
+ "Type mismatched between `type: Integer` and `value: false`.")
205
+ end
206
+
207
+ spec "[!lnhp6] not raise error when type is not specified." do
208
+ sc = @schema
209
+ pr = proc {
210
+ sc.add(:flag, "--flag[=<on|off>]", "flag", value: false)
211
+ }
212
+ ok {pr}.NOT.raise?(Exception)
213
+ end
214
+
215
+ spec "[!6xb8o] value should be included in enum values." do
216
+ sc = @schema
217
+ pr = proc {
218
+ sc.add(:lang, "--lang[=<en|fr|it>]", "language", enum: ["en", "fr", "it"], value: "ja")
219
+ }
220
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
221
+ "ja: Value should be included in enum values, but not.")
222
+ end
223
+
224
+ end
225
+
226
+ end
227
+
228
+
229
+ topic '#required?' do
230
+
231
+ spec "[!svxny] returns nil if option takes no arguments." do
232
+ item, _, _ = ITEMS
233
+ ok {item.required?} == nil
234
+ end
235
+
236
+ spec "[!togcx] returns true if argument is required." do
237
+ _, item, _ = ITEMS
238
+ ok {item.required?} == true
239
+ end
240
+
241
+ spec "[!uwbgc] returns false if argument is optional." do
242
+ _, _, item = ITEMS
243
+ ok {item.required?} == false
244
+ end
245
+
246
+ end
247
+
248
+
249
+ topic '#arg_requireness()' do
250
+
251
+ spec "[!kmo28] returns :none if option takes no arguments." do
252
+ item, _, _ = ITEMS
253
+ ok {item.arg_requireness()} == :none
254
+ end
255
+
256
+ spec "[!s8gxl] returns :required if argument is required." do
257
+ _, item, _ = ITEMS
258
+ ok {item.arg_requireness()} == :required
259
+ end
260
+
261
+ spec "[!owpba] returns :optional if argument is optional." do
262
+ _, _, item = ITEMS
263
+ ok {item.arg_requireness()} == :optional
264
+ end
265
+
266
+ end
267
+
268
+
269
+ topic '#multiple?()' do
270
+
271
+ spec "[!1lj8v] returns true if @multiple is truthy." do
272
+ item = Benry::CmdOpt::SchemaItem.new(:includes, "-I <path>", "include path", "I", nil, nil, nil, multiple: true)
273
+ ok {item.multiple?} == true
274
+ item = Benry::CmdOpt::SchemaItem.new(:includes, "-I <path>", "include path", "I", nil, nil, nil, multiple: 123)
275
+ ok {item.multiple?} == true
276
+ end
277
+
278
+ spec "[!cun23] returns false if @multiple is falthy." do
279
+ item = Benry::CmdOpt::SchemaItem.new(:includes, "-I <path>", "include path", "I", nil, nil, nil, multiple: false)
280
+ ok {item.multiple?} == false
281
+ item = Benry::CmdOpt::SchemaItem.new(:includes, "-I <path>", "include path", "I", nil, nil, nil, multiple: nil)
282
+ ok {item.multiple?} == false
283
+ end
284
+
285
+ end
286
+
287
+
288
+ topic '#hidden?()' do
289
+
290
+ spec "[!no6ov] returns true if @hidden is true." do
291
+ item = Benry::CmdOpt::SchemaItem.new(:debug, "-D", "debug mode", "D", nil, nil, nil, hidden: true)
292
+ ok {item.hidden?} == true
293
+ end
294
+
295
+ spec "[!ej8ot] returns false if @hidden is false." do
296
+ item = Benry::CmdOpt::SchemaItem.new(:debug, "-D", "debug mode", "D", nil, nil, nil, hidden: false)
297
+ ok {item.hidden?} == false
298
+ end
299
+
300
+ spec "[!h0uxs] returns true if desc is nil." do
301
+ desc = nil
302
+ item = Benry::CmdOpt::SchemaItem.new(:debug, "-D", desc, "D", nil, nil, nil)
303
+ ok {item.hidden?} == true
304
+ end
305
+
306
+ spec "[!28vzx] returns false if else." do
307
+ desc = "debug mode"
308
+ item = Benry::CmdOpt::SchemaItem.new(:debug, "-D", desc, "D", nil, nil, nil)
309
+ ok {item.hidden?} == false
310
+ end
311
+
312
+ end
313
+
314
+
315
+ topic '#important?()' do
316
+
317
+ spec "[!ua8kt] returns true/false if `important:` kwarg passed to constructor." do
318
+ item1 = Benry::CmdOpt::SchemaItem.new(:debug, "-D", "debug mode", "D", nil, nil, nil, important: true)
319
+ ok {item1.important?} == true
320
+ item2 = Benry::CmdOpt::SchemaItem.new(:debug, "-D", "debug mode", "D", nil, nil, nil, important: false)
321
+ ok {item2.important?} == false
322
+ end
323
+
324
+ spec "[!hz9sx] returns nil if `important:` kwarg not passed to constructor." do
325
+ item3 = Benry::CmdOpt::SchemaItem.new(:debug, "-D", "debug mode", "D", nil, nil, nil)
326
+ ok {item3.important?} == nil
327
+ end
328
+
329
+ end
330
+
331
+
332
+ topic '#validate_and_convert()' do
333
+
334
+ def new_item(key, optstr, desc, short, long, param, required,
335
+ type: nil, rexp: nil, enum: nil, range: nil, value: nil, &callback)
336
+ return Benry::CmdOpt::SchemaItem.new(key, optstr, desc, short, long, param, required,
337
+ type: type, rexp: rexp, enum: enum, range: range, value: value, &callback)
338
+ end
339
+
340
+ spec "[!h0s0o] raises RuntimeError when value not matched to pattern." do
341
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, rexp: /\A\d+\z/)
342
+ optdict = {}
343
+ pr = proc { x.validate_and_convert("abc", optdict) }
344
+ ok {pr}.raise?(RuntimeError, "Pattern unmatched.")
345
+ end
346
+
347
+ spec "[!5jrdf] raises RuntimeError when value not in enum." do
348
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, enum: ['2', '4', '8'])
349
+ optdict = {}
350
+ pr = proc { x.validate_and_convert("10", optdict) }
351
+ ok {pr}.raise?(RuntimeError, "Expected one of 2/4/8.")
352
+ end
353
+
354
+ spec "[!5falp] raise RuntimeError when value not in range." do
355
+ x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
356
+ type: Integer, range: 2..8)
357
+ optdict = {}
358
+ pr = proc { x.validate_and_convert("1", optdict) }
359
+ ok {pr}.raise?(RuntimeError, "Too small (min: 2)")
360
+ pr = proc { x.validate_and_convert("9", optdict) }
361
+ ok {pr}.raise?(RuntimeError, "Too large (max: 8)")
362
+ ## when min==0
363
+ x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
364
+ type: Integer, range: 0..8)
365
+ optdict = {}
366
+ pr = proc { x.validate_and_convert("-1", optdict) }
367
+ ok {pr}.raise?(RuntimeError, "Positive value (>= 0) expected.")
368
+ ## when min==1
369
+ x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
370
+ type: Integer, range: 1..8)
371
+ optdict = {}
372
+ pr = proc { x.validate_and_convert("0", optdict) }
373
+ ok {pr}.raise?(RuntimeError, "Positive value (>= 1) expected.")
374
+ end
375
+
376
+ spec "[!a0rej] supports endless range." do
377
+ begin
378
+ range1 = eval "(2..)" # Ruby >= 2.6
379
+ range2 = eval "(..8)"
380
+ rescue SyntaxError
381
+ range1 = nil # Ruby < 2.6
382
+ range2 = nil
383
+ end
384
+ if range1
385
+ x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
386
+ type: Integer, range: range1)
387
+ optdict = {}
388
+ pr = proc { x.validate_and_convert("1", optdict) }
389
+ ok {pr}.raise?(RuntimeError, "Too small (min: 2)")
390
+ pr = proc { x.validate_and_convert("9", optdict) }
391
+ ok {pr}.NOT.raise?(RuntimeError)
392
+ end
393
+ if range2
394
+ x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
395
+ type: Integer, range: range2)
396
+ optdict = {}
397
+ pr = proc { x.validate_and_convert("1", optdict) }
398
+ ok {pr}.NOT.raise?(RuntimeError)
399
+ pr = proc { x.validate_and_convert("9", optdict) }
400
+ ok {pr}.raise?(RuntimeError, "Too large (max: 8)")
401
+ end
402
+ end
403
+
404
+ spec "[!j4fuz] calls type-specific callback when type specified." do
405
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, type: Integer)
406
+ optdict = {}
407
+ pr = proc { x.validate_and_convert("abc", optdict) }
408
+ ok {pr}.raise?(RuntimeError, "Integer expected.")
409
+ end
410
+
411
+ spec "[!jn9z3] calls callback when callback specified." do
412
+ called = false
413
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false) {|va|
414
+ called = true
415
+ }
416
+ optdict = {}
417
+ x.validate_and_convert("abc", optdict)
418
+ ok {called} == true
419
+ end
420
+
421
+ spec "[!iqalh] calls callback with different number of args according to arity." do
422
+ args1 = nil
423
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false) {|val|
424
+ args1 = val
425
+ }
426
+ optdict = {}
427
+ x.validate_and_convert("123", optdict)
428
+ ok {args1} == "123"
429
+ #
430
+ args2 = nil
431
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false) {|optdict, key, val|
432
+ args2 = [optdict, key, val]
433
+ }
434
+ optdict = {}
435
+ x.validate_and_convert("123", optdict)
436
+ ok {args2} == [optdict, :indent, "123"]
437
+ end
438
+
439
+ spec "[!x066l] returns new value." do
440
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, type: Integer)
441
+ ok {x.validate_and_convert("123", {})} == 123
442
+ #
443
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, type: Integer) {|val|
444
+ val * 2
445
+ }
446
+ ok {x.validate_and_convert("123", {})} == 246
447
+ end
448
+
449
+ spec "[!eafem] returns default value (if specified) instead of true value." do
450
+ x1 = new_item(:flag, "", "desc", "f", "flag", nil, false, value: nil)
451
+ ok {x1.validate_and_convert(true, {})} == true
452
+ x2 = new_item(:flag, "", "desc", "f", "flag", nil, false, value: "blabla")
453
+ ok {x2.validate_and_convert(true, {})} == "blabla"
454
+ x3 = new_item(:flag, "", "desc", "f", "flag", nil, false, value: false)
455
+ ok {x3.validate_and_convert(true, {})} == false
456
+ end
457
+
458
+ end
459
+
460
+ end
461
+
462
+
463
+ end