benry-cmdapp 0.2.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1219 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+
5
+ require_relative 'shared'
6
+
7
+
8
+
9
+ class ScopeTestAction < Benry::CmdApp::Action
10
+
11
+ @action.("test")
12
+ def scope9392()
13
+ end
14
+
15
+ end
16
+
17
+
18
+ class OverrideTestAction1 < Benry::CmdApp::Action
19
+ def foo1__bar1()
20
+ end
21
+ end
22
+
23
+ class OverrideTestAction2 < OverrideTestAction1
24
+ #category "foo1:"
25
+ #@action.("foo1")
26
+ #def bar1()
27
+ #end
28
+ end
29
+
30
+
31
+ Oktest.scope do
32
+
33
+
34
+ topic Benry::CmdApp::ActionScope do
35
+
36
+ before do
37
+ @config = Benry::CmdApp::Config.new("test app", "1.2.3",
38
+ app_name: "TestApp", app_command: "testapp",
39
+ option_verbose: true, option_quiet: true,
40
+ option_color: true, #option_debug: true,
41
+ option_trace: true)
42
+ end
43
+
44
+
45
+ topic '#__clear_recursive_reference()' do
46
+
47
+ spec "[!i68z0] clears instance var which refers context object." do
48
+ scope = Benry::CmdApp::ActionScope.new(@config)
49
+ ctx = scope.instance_eval { @__context__ }
50
+ ok {ctx} != nil
51
+ scope.__clear_recursive_reference()
52
+ ctx = scope.instance_eval { @__context__ }
53
+ ok {ctx} == nil
54
+ end
55
+
56
+ end
57
+
58
+
59
+ topic '.inherited()' do
60
+
61
+ spec "[!8cck9] sets Proc object to `@action` in subclass." do
62
+ x = ScopeTestAction.class_eval { @action }
63
+ ok {x}.is_a?(Proc)
64
+ ok {x}.lambda?
65
+ end
66
+
67
+ spec "[!r07i7] `@action.()` raises DefinitionError if called consectively." do
68
+ pr = proc do
69
+ ScopeTestAction.class_eval do
70
+ @action.("foo")
71
+ @action.("bar")
72
+ def dummy4922()
73
+ end
74
+ end
75
+ end
76
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
77
+ "`@action.()` called without method definition (please define method for this action).")
78
+ end
79
+
80
+ spec "[!34psw] `@action.()` stores arguments into `@__actiondef__`." do
81
+ x = nil
82
+ ScopeTestAction.class_eval do
83
+ @__actiondef__ = nil
84
+ #
85
+ @action.("test")
86
+ x = @__actiondef__
87
+ def dummy2321()
88
+ end
89
+ end
90
+ ok {x}.is_a?(Array).length(3)
91
+ ok {x[0]} == "test"
92
+ ok {x[1]}.is_a?(Benry::CmdApp::ACTION_OPTION_SCHEMA_CLASS)
93
+ ok {x[2]} == {:usage=>nil, :detail=>nil, :description=>nil, :postamble=>nil, :tag=>nil, :important=>nil, :hidden=>nil}
94
+ end
95
+
96
+ spec "[!en6n0] sets Proc object to `@option` in subclass." do
97
+ x = ScopeTestAction.class_eval { @option }
98
+ ok {x}.is_a?(Proc)
99
+ ok {x}.lambda?
100
+ end
101
+
102
+ spec "[!68hf8] raises DefinitionError if `@option.()` called without `@action.()`." do
103
+ pr = proc do
104
+ ScopeTestAction.class_eval do
105
+ @__actiondef__ = nil
106
+ @option.(:help, "-", "help")
107
+ end
108
+ end
109
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
110
+ "`@option.()` called without `@action.()`.")
111
+ end
112
+
113
+ spec "[!2p98r] `@option.()` stores arguments into option schema object." do
114
+ tuple = nil
115
+ ScopeTestAction.class_eval do
116
+ @action.("foobar")
117
+ @option.(:lang, "-l <lang>", "language", detail: "blabla", hidden: true) {|val| val }
118
+ @option.(:color, "--color[=<on|off>]", "color mode", type: TrueClass)
119
+ @option.(:ints, "-n <N>", "integers", multiple: true, type: Integer)
120
+ tuple = @__actiondef__
121
+ def s2055(help: false, lang: nil, color: nil, ints: nil)
122
+ end
123
+ end
124
+ schema = tuple[1]
125
+ ok {schema}.is_a?(Benry::CmdApp::ACTION_OPTION_SCHEMA_CLASS)
126
+ #
127
+ x = schema.get(:lang)
128
+ ok {x.key} == :lang
129
+ ok {x.short} == "l"
130
+ ok {x.long} == nil
131
+ ok {x.desc} == "language"
132
+ ok {x.type} == nil
133
+ ok {x.detail} == "blabla"
134
+ ok {x.multiple?} == false
135
+ ok {x.hidden?} == true
136
+ ok {x.callback}.is_a?(Proc)
137
+ #
138
+ x = schema.get(:color)
139
+ ok {x.key} == :color
140
+ ok {x.short} == nil
141
+ ok {x.long} == "color"
142
+ ok {x.desc} == "color mode"
143
+ ok {x.type} == TrueClass
144
+ ok {x.detail} == nil
145
+ ok {x.multiple?} == false
146
+ ok {x.hidden?} == false
147
+ ok {x.callback} == nil
148
+ #
149
+ x = schema.get(:ints)
150
+ ok {x.key} == :ints
151
+ ok {x.short} == "n"
152
+ ok {x.long} == nil
153
+ ok {x.multiple?} == true
154
+ end
155
+
156
+ spec "[!aiwns] `@copy_options.()` copies options from other action." do
157
+ MyAction.class_eval do
158
+ @action.("hello 1291")
159
+ @option.(:lang, "-l <lang>", "language")
160
+ @option.(:color, "--color[=<on|off>]", "color mode", type: TrueClass)
161
+ @option.(:debug, "-D", "debug mode")
162
+ @option.(:trace, "-T", "trace mode")
163
+ @option.(:indent, "-i[<N>]", "indent", type: Integer)
164
+ def hello1291(lang: nil, color: false, debug: false, trace: false, indent: 0)
165
+ end
166
+ #
167
+ @action.("hello 3942")
168
+ @copy_options.("hello1291", except: [:debug, :trace])
169
+ @option.(:silent, "--silent", "silent mode")
170
+ def hello3942(lang: "en", color: false, indent: 0, silent: false)
171
+ end
172
+ end
173
+ at_end { Benry::CmdApp.undef_action("hello3942") }
174
+ #
175
+ md = Benry::CmdApp::REGISTRY.metadata_get("hello3942")
176
+ ok {md.schema.option_help()} == <<"END"
177
+ -l <lang> : language
178
+ --color[=<on|off>] : color mode
179
+ -i[<N>] : indent
180
+ --silent : silent mode
181
+ END
182
+ end
183
+
184
+ spec "[!bfxye] `@copy_options.()` tries to find an action with current prefix." do
185
+ MyAction.class_eval do
186
+ category "c9588:" do
187
+ @action.("test action")
188
+ @option.(:foo, "--foo", "foo option")
189
+ def action9588(foo: nil)
190
+ end
191
+ #
192
+ @action.("test action")
193
+ @copy_options.("action9588")
194
+ @option.(:bar, "--bar", "bar option")
195
+ def action9588x(foo: nil, bar: nil)
196
+ end
197
+ end
198
+ end
199
+ at_end {
200
+ Benry::CmdApp.undef_action("c9588:action9588")
201
+ Benry::CmdApp.undef_action("c9588:action9588x")
202
+ }
203
+ #
204
+ md = Benry::CmdApp::REGISTRY.metadata_get("c9588:action9588x")
205
+ ok {md.schema.option_help()} == <<END
206
+ --foo : foo option
207
+ --bar : bar option
208
+ END
209
+ end
210
+
211
+ spec "[!mhhn2] `@copy_options.()` raises DefinitionError when action not found." do
212
+ pr = proc do
213
+ MyAction.class_eval do
214
+ @action.("hello 4691")
215
+ @copy_options.("hello469100")
216
+ def hello4691()
217
+ end
218
+ end
219
+ end
220
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
221
+ %q|@copy_options.("hello469100"): Action not found.|)
222
+ end
223
+
224
+ spec "[!0slo8] raises DefinitionError if `@copy_options.()` called without `@action.()`." do
225
+ pr = proc do
226
+ MyAction.class_eval do
227
+ @__actiondef__ = nil
228
+ @copy_options.("hello")
229
+ def hello8420()
230
+ end
231
+ end
232
+ end
233
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
234
+ %q|@copy_options.("hello"): Called without `@action.()`.|)
235
+ end
236
+
237
+ spec "[!0qz0q] `@copy_options.()` stores arguments into option schema object." do
238
+ x1 = x2 = nil
239
+ MyAction.class_eval do
240
+ @action.("hello")
241
+ x1 = @__actiondef__[1]
242
+ @copy_options.("hello")
243
+ x2 = @__actiondef__[1]
244
+ @__actiondef__ = nil
245
+ end
246
+ ok {x1} != nil
247
+ ok {x2}.same?(x1)
248
+ ok {x2}.is_a?(Benry::CmdApp::ACTION_OPTION_SCHEMA_CLASS)
249
+ ok {x2.to_s()} == <<"END"
250
+ -l, --lang=<lang> : language name (en/fr/it)
251
+ END
252
+ end
253
+
254
+ spec "[!dezh1] `@copy_options.()` ignores help option automatically." do
255
+ x = nil
256
+ MyAction.class_eval do
257
+ @action.("copy of hello")
258
+ @__actiondef__[1] = Benry::CmdApp::ACTION_OPTION_SCHEMA_CLASS.new
259
+ @__actiondef__[1].instance_eval { @items.clear() }
260
+ @copy_options.("hello")
261
+ x = @__actiondef__[1]
262
+ @__actiondef__ = nil
263
+ end
264
+ ok {x} != nil
265
+ ok {x}.is_a?(Benry::CmdApp::ACTION_OPTION_SCHEMA_CLASS)
266
+ ok {x.to_s()} == <<"END"
267
+ -l, --lang=<lang> : language name (en/fr/it)
268
+ END
269
+ end
270
+
271
+ spec "[!7g5ug] sets Proc object to `@optionset` in subclass." do
272
+ _ = self
273
+ MyAction.class_eval do
274
+ _.ok {@optionset} != nil
275
+ _.ok {@optionset}.is_a?(Proc)
276
+ end
277
+ end
278
+
279
+ spec "[!o27kt] raises DefinitionError if `@optionset.()` called without `@action.()`." do
280
+ pr = proc do
281
+ MyAction.class_eval do
282
+ @optionset.()
283
+ end
284
+ end
285
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
286
+ "`@optionset.()` called without `@action.()`.")
287
+ end
288
+
289
+ spec "[!ky6sg] copies option items from optionset into schema object." do
290
+ MyAction.class_eval do
291
+ optset1 = optionset do
292
+ @option.(:user, "-u <user>", "user name")
293
+ @option.(:email, "-e <email>", "email address")
294
+ end
295
+ optset2 = optionset do
296
+ @option.(:host, "--host=<host>", "host name")
297
+ @option.(:port, "--port=<port>", "port number", type: Integer)
298
+ end
299
+ #
300
+ @action.("sample")
301
+ @optionset.(optset1, optset2)
302
+ def dummy8173(user: nil, email: nil, host: nil, port: nil)
303
+ end
304
+ end
305
+ metadata = Benry::CmdApp::REGISTRY.metadata_get("dummy8173")
306
+ ok {metadata.schema.to_s} == <<"END"
307
+ -u <user> : user name
308
+ -e <email> : email address
309
+ --host=<host> : host name
310
+ --port=<port> : port number
311
+ END
312
+ end
313
+
314
+ end
315
+
316
+
317
+ topic '._new_option_schema()' do
318
+
319
+ spec "[!zuxmj] creates new option schema object." do
320
+ x = Benry::CmdApp::ActionScope.class_eval { _new_option_schema() }
321
+ ok {x}.is_a?(Benry::CmdApp::ACTION_OPTION_SCHEMA_CLASS)
322
+ end
323
+
324
+ spec "[!rruxi] adds '-h, --help' option as hidden automatically." do
325
+ schema = Benry::CmdApp::ActionScope.class_eval { _new_option_schema() }
326
+ item = schema.get(:help)
327
+ ok {item} != nil
328
+ ok {item.key} == :help
329
+ ok {item.optdef} == "-h, --help"
330
+ ok {item}.hidden?
331
+ end
332
+
333
+ end
334
+
335
+
336
+ topic '.method_added()' do
337
+
338
+ spec "[!6frgx] do nothing if `@action.()` is not called." do
339
+ ScopeTestAction.class_eval { @__actiondef__ = nil }
340
+ x = ScopeTestAction.__send__(:method_added, :foo)
341
+ ok {x} == false
342
+ #
343
+ ScopeTestAction.class_eval do
344
+ def s6732()
345
+ end
346
+ @__actiondef__ = ["test", Benry::CmdApp::OptionSchema.new, {}]
347
+ end
348
+ x = ScopeTestAction.__send__(:method_added, :s6732)
349
+ ok {x} == true
350
+ end
351
+
352
+ spec "[!e3yjo] clears `@__actiondef__`." do
353
+ x1 = nil
354
+ x2 = nil
355
+ ScopeTestAction.class_eval do
356
+ @action.("test")
357
+ x1 = @__actiondef__
358
+ def s4643()
359
+ end
360
+ x2 = @__actiondef__
361
+ end
362
+ ok {x1} != nil
363
+ ok {x2} == nil
364
+ end
365
+
366
+ spec "[!jq4ex] raises DefinitionError if option defined but corresponding keyword arg is missing." do
367
+ pr = proc do
368
+ ScopeTestAction.class_eval do
369
+ @action.("test")
370
+ @option.(:foo, "--foo", "foo option")
371
+ @option.(:bar, "--bar", "bar option")
372
+ def a7913(arg, foo: nil, baz: nil)
373
+ end
374
+ end
375
+ end
376
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
377
+ "def a7913(): Keyword argument `bar:` expected which corresponds to the `:bar` option, but not exist.")
378
+ end
379
+
380
+ spec "[!ejdlo] converts method name to action name." do
381
+ ScopeTestAction.class_eval do
382
+ @action.("test")
383
+ def s9321__aa_bb__cc_dd_()
384
+ end
385
+ end
386
+ md = Benry::CmdApp::REGISTRY.metadata_each.find {|x| x.name =~ /s9321/ }
387
+ ok {md} != nil
388
+ ok {md.name} == "s9321:aa-bb:cc-dd"
389
+ end
390
+
391
+ case_when "[!w9qat] when `category()` called before defining action method..." do
392
+
393
+ spec "[!3pl1r] renames method name to new name with prefix." do
394
+ ScopeTestAction.class_eval do
395
+ category "p3442:" do
396
+ category "foo:" do
397
+ category "bar:" do
398
+ @action.("test")
399
+ def s9192()
400
+ end
401
+ end
402
+ end
403
+ end
404
+ end
405
+ ok {ScopeTestAction.method_defined?(:s9192)} == false
406
+ ok {ScopeTestAction.method_defined?(:p3442__foo__bar__s9192)} == true
407
+ end
408
+
409
+ case_when "[!mil2g] when action name matched to 'action:' kwarg of `category()`..." do
410
+
411
+ spec "[!hztpp] uses pefix name as action name." do
412
+ ScopeTestAction.class_eval do
413
+ category "p9782:", action: "s3867" do
414
+ @action.("test")
415
+ def s3867()
416
+ end
417
+ end
418
+ end
419
+ ok {Benry::CmdApp::REGISTRY.metadata_get("p9782:s3867")} == nil
420
+ ok {Benry::CmdApp::REGISTRY.metadata_get("p9782")} != nil
421
+ ok {Benry::CmdApp::REGISTRY.metadata_get("p9782").meth} == :p9782__s3867
422
+ end
423
+
424
+ spec "[!cydex] clears `action:` kwarg." do
425
+ x1 = x2 = x3 = nil
426
+ ScopeTestAction.class_eval do
427
+ category "p3503:", action: "s5319" do
428
+ x1 = @__prefixdef__[1]
429
+ #
430
+ @action.("test")
431
+ def s1767()
432
+ end
433
+ x2 = @__prefixdef__[1]
434
+ #
435
+ @action.("test")
436
+ def s5319()
437
+ end
438
+ x3 = @__prefixdef__[1]
439
+ end
440
+ end
441
+ ok {x1} == "s5319"
442
+ ok {x2} == "s5319"
443
+ ok {x3} == nil
444
+ end
445
+
446
+ end
447
+
448
+ case_when "[!8xsnw] when action name matched to `alias_for:` kwarg of `category()`..." do
449
+
450
+ spec "[!iguvp] adds prefix name to action name." do
451
+ ScopeTestAction.class_eval do
452
+ category "p8134:", alias_for: "s6368" do
453
+ @action.("test")
454
+ def s6368()
455
+ end
456
+ end
457
+ end
458
+ md = Benry::CmdApp::REGISTRY.metadata_each.find {|x| x.name =~ /s6368/ }
459
+ ok {md.name} == "p8134:s6368"
460
+ ok {md}.NOT.alias?
461
+ md = Benry::CmdApp::REGISTRY.metadata_get("p8134")
462
+ ok {md.name} == "p8134"
463
+ ok {md}.alias?
464
+ end
465
+
466
+ end
467
+
468
+ case_when "[!wmevh] else..." do
469
+
470
+ spec "[!9cyc2] adds prefix name to action name." do
471
+ ScopeTestAction.class_eval do
472
+ category "p9986:", alias_for: "s4711" do
473
+ @action.("test")
474
+ def s0629()
475
+ end
476
+ @action.("test")
477
+ def s4711()
478
+ end
479
+ end
480
+ end
481
+ md = Benry::CmdApp::REGISTRY.metadata_each.find {|x| x.name =~ /s0629/ }
482
+ ok {md.name} == "p9986:s0629"
483
+ ok {md}.NOT.alias?
484
+ end
485
+
486
+ end
487
+
488
+ end
489
+
490
+ case_when "[!y8lh0] else..." do
491
+
492
+ spec "[!0ki5g] not add prefix to action name." do
493
+ ScopeTestAction.class_eval do
494
+ category "p2592:", action: "s2619" do
495
+ @action.("test")
496
+ def s4487()
497
+ end
498
+ @action.("test")
499
+ def s2619()
500
+ end
501
+ end
502
+ end
503
+ md = Benry::CmdApp::REGISTRY.metadata_get("p2592:s4487")
504
+ ok {md.name} == "p2592:s4487"
505
+ ok {md}.NOT.alias?
506
+ md = Benry::CmdApp::REGISTRY.metadata_get("p2592")
507
+ ok {md.name} == "p2592"
508
+ ok {md}.NOT.alias?
509
+ end
510
+
511
+ end
512
+
513
+ spec "[!dad1q] raises DefinitionError if action with same name already defined." do
514
+ pr = proc do
515
+ ScopeTestAction.class_eval do
516
+ @action.("duplicate")
517
+ def hello()
518
+ end
519
+ end
520
+ end
521
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
522
+ "def hello(): Action 'hello' already defined (to redefine it, delete it beforehand by `undef_action()`).")
523
+ #
524
+ pr = proc do
525
+ ScopeTestAction.class_eval do
526
+ category "git:" do
527
+ @action.("duplicate")
528
+ def stage()
529
+ end
530
+ end
531
+ end
532
+ end
533
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
534
+ "def stage(): Action 'git:stage' already defined (to redefine it, delete it beforehand by `undef_action()`).")
535
+ end
536
+
537
+ spec "[!ur8lp] raises DefinitionError if method already defined in parent or ancestor class." do
538
+ pr = proc do
539
+ ScopeTestAction.class_eval do
540
+ @action.("print")
541
+ def print()
542
+ end
543
+ end
544
+ end
545
+ at_end { ScopeTestAction.class_eval { @__actiondef__ = nil } }
546
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
547
+ "def print(): Please rename it to `print_()`, because it overrides existing method in parent or ancestor class.")
548
+ end
549
+
550
+ spec "[!dj0ql] method override check is done with new method name (= prefixed name)." do
551
+ pr = proc do
552
+ ScopeTestAction.class_eval do
553
+ category "p2946:" do
554
+ @action.("print")
555
+ def print()
556
+ end
557
+ end
558
+ end
559
+ end
560
+ ok {pr}.NOT.raise?(Exception)
561
+ metadata = Benry::CmdApp::REGISTRY.metadata_get("p2946:print")
562
+ ok {metadata} != nil
563
+ ok {metadata.meth} == :p2946__print
564
+ #
565
+ pr = proc do
566
+ OverrideTestAction2.class_eval do
567
+ category "foo1:"
568
+ @action.("foo1")
569
+ def bar1()
570
+ end
571
+ end
572
+ end
573
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
574
+ "def bar1(): Please rename it to `bar1_()`, because it overrides existing method in parent or ancestor class.")
575
+ end
576
+
577
+ spec "[!7fnh4] registers action metadata." do
578
+ ScopeTestAction.class_eval do
579
+ category "p7966:" do
580
+ @action.("test")
581
+ def s3198()
582
+ end
583
+ end
584
+ end
585
+ md = Benry::CmdApp::REGISTRY.metadata_get("p7966:s3198")
586
+ ok {md} != nil
587
+ ok {md.name} == "p7966:s3198"
588
+ ok {md}.NOT.alias?
589
+ end
590
+
591
+ spec "[!lyn0z] registers alias metadata if necessary." do
592
+ ScopeTestAction.class_eval do
593
+ category "p0692:", alias_for: "s8075" do
594
+ @action.("test")
595
+ def s8075()
596
+ end
597
+ end
598
+ end
599
+ md = Benry::CmdApp::REGISTRY.metadata_get("p0692")
600
+ ok {md} != nil
601
+ ok {md}.alias?
602
+ ok {md.action} == "p0692:s8075"
603
+ md = Benry::CmdApp::REGISTRY.metadata_get("p0692:s8075")
604
+ ok {md} != nil
605
+ ok {md}.NOT.alias?
606
+ end
607
+
608
+ spec "[!4402s] clears `alias_for:` kwarg." do
609
+ x1 = x2 = x3 = nil
610
+ ScopeTestAction.class_eval do
611
+ category "p7506:", alias_for: "s3449" do
612
+ x1 = @__prefixdef__[2]
613
+ #
614
+ @action.("test")
615
+ def s8075()
616
+ end
617
+ x2 = @__prefixdef__[2]
618
+ #
619
+ @action.("test")
620
+ def s3449()
621
+ end
622
+ x3 = @__prefixdef__[2]
623
+ end
624
+ end
625
+ x1 == "s3449"
626
+ x2 == "s3449"
627
+ x3 == nil
628
+ end
629
+
630
+ spec "[!u0td6] registers prefix of action if not registered yet." do
631
+ prefix = "p1777:foo:bar:"
632
+ ok {Benry::CmdApp::REGISTRY.category_exist?(prefix)} == false
633
+ ScopeTestAction.class_eval do
634
+ @action.("example")
635
+ def p1777__foo__bar__hello()
636
+ end
637
+ end
638
+ ok {Benry::CmdApp::REGISTRY.category_exist?(prefix)} == true
639
+ end
640
+
641
+ end
642
+
643
+
644
+ topic '.__validate_kwargs()' do
645
+
646
+ spec "[!xpg47] returns nil if `**kwargs` exist." do
647
+ errmsg = ""
648
+ ScopeTestAction.class_eval do
649
+ @action.("dummy")
650
+ @option.(:foo, "--foo", "foo option")
651
+ @option.(:bar, "--bar", "bar option")
652
+ def a5758(foo: nil, bar: nil)
653
+ end
654
+ #
655
+ def a5759(arg1, arg2=nil, foo: nil, baz: nil, **kws)
656
+ end
657
+ md = Benry::CmdApp::REGISTRY.metadata_get("a5758")
658
+ errmsg = __validate_kwargs(:a5759, md.schema)
659
+ end
660
+ ok {errmsg} == nil
661
+ end
662
+
663
+ spec "[!qowwj] returns error message if option defined but corresponding keyword arg is missing." do
664
+ errmsg = nil
665
+ ScopeTestAction.class_eval do
666
+ @action.("dummy")
667
+ @option.(:foo, "--foo", "foo option")
668
+ @option.(:bar, "--bar", "bar option")
669
+ def a5756(foo: nil, bar: nil)
670
+ end
671
+ #
672
+ def a5757(arg1, arg2=nil, foo: nil, baz: nil)
673
+ end
674
+ md = Benry::CmdApp::REGISTRY.metadata_get("a5756")
675
+ errmsg = __validate_kwargs(:a5757, md.schema)
676
+ end
677
+ ok {errmsg} == "Keyword argument `bar:` expected which corresponds to the `:bar` option, but not exist."
678
+ end
679
+
680
+ end
681
+
682
+
683
+ topic '.__validate_action_method()' do
684
+
685
+ spec "[!5a4d3] returns error message if action with same name already defined." do
686
+ x = nil
687
+ ScopeTestAction.class_eval do
688
+ x = __validate_action_method("hello", :tmp__helo, :hello)
689
+ end
690
+ ok {x} == "Action 'hello' already defined (to redefine it, delete it beforehand by `undef_action()`)."
691
+ end
692
+
693
+ spec "[!uxsx3] returns error message if method already defined in parent or ancestor class." do
694
+ x = nil
695
+ ScopeTestAction.class_eval do
696
+ x = __validate_action_method("print", :print, :print)
697
+ end
698
+ ok {x} == "Please rename it to `print_()`, because it overrides existing method in parent or ancestor class."
699
+ end
700
+
701
+ spec "[!3fmpo] method override check is done with new method name (= prefixed name)." do
702
+ x = nil
703
+ ScopeTestAction.class_eval do
704
+ x = __validate_action_method("p3159:print", :print, :xprint)
705
+ end
706
+ ok {x} == "Please rename it to `xprint_()`, because it overrides existing method in parent or ancestor class."
707
+ end
708
+
709
+ end
710
+
711
+
712
+ topic '.current_prefix()' do
713
+
714
+ spec "[!2zt0f] returns current prefix name such as 'foo:bar:'." do
715
+ x1 = x2 = x3 = x4 = x5 = nil
716
+ ScopeTestAction.class_eval do
717
+ x1 = current_prefix()
718
+ category "p9912:" do
719
+ x2 = current_prefix()
720
+ category "p3138:" do
721
+ x3 = current_prefix()
722
+ end
723
+ x4 = current_prefix()
724
+ end
725
+ x5 = current_prefix()
726
+ end
727
+ ok {x1} == nil
728
+ ok {x2} == "p9912:"
729
+ ok {x3} == "p9912:p3138:"
730
+ ok {x4} == "p9912:"
731
+ ok {x5} == nil
732
+ end
733
+
734
+ end
735
+
736
+
737
+ topic '.category()' do
738
+
739
+ spec "[!mp1p5] raises DefinitionError if prefix is invalid." do
740
+ at_end { ScopeTestAction.class_eval { @__prefixdef__ = nil } }
741
+ pr = proc do
742
+ ScopeTestAction.class_eval do
743
+ category "p2737"
744
+ @action.("test")
745
+ def s4393()
746
+ end
747
+ end
748
+ end
749
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
750
+ "category(\"p2737\"): Prefix name should end with ':'.")
751
+ end
752
+
753
+ spec "[!q01ma] raises DefinitionError if action or alias name is invalid." do
754
+ pr = proc do
755
+ ScopeTestAction.class_eval { category "p0936:", action: :foo }
756
+ end
757
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
758
+ %q|`category("p0936:", action: :foo)`: Action name should be a string, but got Symbol object.|)
759
+ #
760
+ pr = proc do
761
+ ScopeTestAction.class_eval { category "p0936:", alias_for: :bar }
762
+ end
763
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
764
+ %q|`category("p0936:", alias_for: :bar)`: Alias name should be a string, but got Symbol object.|)
765
+ #
766
+ pr = proc do
767
+ ScopeTestAction.class_eval { category "p0936:", action: "foo", alias_for: "bar" }
768
+ end
769
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
770
+ %q|`category("p0936:", action: "foo", alias_for: "bar")`: `action:` and `alias_for:` are exclusive.|)
771
+ end
772
+
773
+ case_when "[!kwst6] if block given..." do
774
+
775
+ spec "[!t8wwm] saves previous prefix data and restore them at end of block." do
776
+ x1 = x2 = x3 = nil
777
+ ScopeTestAction.class_eval do
778
+ x1 = @__prefixdef__
779
+ category "p4929:" do
780
+ x2 = @__prefixdef__
781
+ @action.("test")
782
+ def s0997()
783
+ end
784
+ end
785
+ x3 = @__prefixdef__
786
+ end
787
+ ok {x1} == nil
788
+ ok {x2} != nil
789
+ ok {x3} == nil
790
+ end
791
+
792
+ spec "[!j00pk] registers prefix and description, even if no actions defined." do
793
+ ScopeTestAction.class_eval do
794
+ category "p0516:", "bla bla" do
795
+ category "git:", "boom boom" do
796
+ end
797
+ end
798
+ end
799
+ ok {Benry::CmdApp::REGISTRY.category_get_desc("p0516:")} == "bla bla"
800
+ ok {Benry::CmdApp::REGISTRY.category_get_desc("p0516:git:")} == "boom boom"
801
+ #
802
+ ScopeTestAction.class_eval do
803
+ category "p3893:", "guu guu", action: "a1" do
804
+ category "git:", "gii gii", alias_for: "a2" do
805
+ @action.("x")
806
+ def a2(); end
807
+ end
808
+ @action.("x")
809
+ def a1(); end
810
+ end
811
+ end
812
+ ok {Benry::CmdApp::REGISTRY.category_get_desc("p3893:")} == "guu guu"
813
+ ok {Benry::CmdApp::REGISTRY.category_get_desc("p3893:git:")} == "gii gii"
814
+ #
815
+ ScopeTestAction.class_eval do
816
+ category "p2358:" do
817
+ end
818
+ end
819
+ ok {Benry::CmdApp::REGISTRY.category_exist?("p2358:")} == true
820
+ end
821
+
822
+ spec "[!w52y5] raises DefinitionError if `action:` specified but target action not defined." do
823
+ at_end { ScopeTestAction.class_eval { @__prefixdef__ = nil } }
824
+ pr = proc do
825
+ ScopeTestAction.class_eval do
826
+ category "p4929:", action: "s7832" do
827
+ @action.("test")
828
+ def s2649()
829
+ end
830
+ end
831
+ end
832
+ end
833
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
834
+ %q|category("p4929:", action: "s7832"): Target action not defined.|)
835
+ end
836
+
837
+ spec "[!zs3b5] raises DefinitionError if `alias_for:` specified but target action not defined." do
838
+ at_end { ScopeTestAction.class_eval { @__prefixdef__ = nil } }
839
+ pr = proc do
840
+ ScopeTestAction.class_eval do
841
+ category "p2476:", alias_for: "s6678" do
842
+ @action.("test")
843
+ def s1452()
844
+ end
845
+ end
846
+ end
847
+ end
848
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
849
+ %q|category("p2476:", alias_for: "s6678"): Target action of alias not defined.|)
850
+ end
851
+
852
+ end
853
+
854
+ case_when "[!yqhm8] else..." do
855
+
856
+ spec "[!tgux9] just stores arguments into class." do
857
+ ScopeTestAction.class_eval do
858
+ @__prefixdef__ = nil
859
+ category "p6062:"
860
+ end
861
+ x = ScopeTestAction.class_eval { @__prefixdef__ }
862
+ ok {x} == ["p6062:", nil, nil]
863
+ end
864
+
865
+ spec "[!ncskq] registers prefix and description, even if no actions defined." do
866
+ ScopeTestAction.class_eval do
867
+ category "p6712:", "bowow"
868
+ end
869
+ ok {Benry::CmdApp::REGISTRY.category_get_desc("p6712:")} == "bowow"
870
+ #
871
+ ScopeTestAction.class_eval do
872
+ category "p9461:", "hoo hoo", action: "homhom"
873
+ category "p0438:", "yaa yaa", alias_for: "homhom"
874
+ @__prefixdef__ = nil
875
+ end
876
+ ok {Benry::CmdApp::REGISTRY.category_get_desc("p9461:")} == "hoo hoo"
877
+ ok {Benry::CmdApp::REGISTRY.category_get_desc("p0438:")} == "yaa yaa"
878
+ #
879
+ ScopeTestAction.class_eval do
880
+ category "p7217:"
881
+ end
882
+ ok {Benry::CmdApp::REGISTRY.category_exist?("p7217:")} == true
883
+ end
884
+
885
+ end
886
+
887
+ end
888
+
889
+
890
+ topic '.__validate_prefix()' do
891
+
892
+ spec "[!bac19] returns error message if prefix is not a string." do
893
+ errmsg = ScopeTestAction.class_eval { __validate_prefix(:foo) }
894
+ ok {errmsg} == "String expected, but got Symbol."
895
+ end
896
+
897
+ spec "[!608fc] returns error message if prefix doesn't end with ':'." do
898
+ errmsg = ScopeTestAction.class_eval { __validate_prefix("foo") }
899
+ ok {errmsg} == "Prefix name should end with ':'."
900
+ end
901
+
902
+ spec "[!vupza] returns error message if prefix contains '_'." do
903
+ errmsg = ScopeTestAction.class_eval { __validate_prefix("foo_bar:") }
904
+ ok {errmsg} == "Prefix name should not contain '_' (use '-' instead)."
905
+ end
906
+
907
+ spec "[!5vgn3] returns error message if prefix is invalid." do
908
+ errmsg = ScopeTestAction.class_eval { __validate_prefix("123:") }
909
+ ok {errmsg} == "Invalid prefix name."
910
+ end
911
+
912
+ spec "[!7rphu] returns nil if prefix is valid." do
913
+ errmsg = ScopeTestAction.class_eval { __validate_prefix("foo-bar:") }
914
+ ok {errmsg} == nil
915
+ end
916
+
917
+ end
918
+
919
+
920
+ topic '.__validate_action_and_alias()' do
921
+
922
+ spec "[!38ji9] returns error message if action name is not a string." do
923
+ pr = proc do
924
+ ScopeTestAction.class_eval do
925
+ category "p1871:", action: :foo
926
+ end
927
+ end
928
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
929
+ %q|`category("p1871:", action: :foo)`: Action name should be a string, but got Symbol object.|)
930
+ end
931
+
932
+ spec "[!qge3m] returns error message if alias name is not a string." do
933
+ pr = proc do
934
+ ScopeTestAction.class_eval do
935
+ category "p7328:", alias_for: :foo
936
+ end
937
+ end
938
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
939
+ %q|`category("p7328:", alias_for: :foo)`: Alias name should be a string, but got Symbol object.|)
940
+ end
941
+
942
+ spec "[!ermv8] returns error message if both `action:` and `alias_for:` kwargs are specified." do
943
+ at_end { ScopeTestAction.class_eval { @__prefixdef__ = nil } }
944
+ pr = proc do
945
+ ScopeTestAction.class_eval do
946
+ category "p7549:", action: "s0573", alias_for: "s0573"
947
+ @action.("test")
948
+ def s0573()
949
+ end
950
+ end
951
+ end
952
+ ok {pr}.raise?(Benry::CmdApp::DefinitionError,
953
+ %q|`category("p7549:", action: "s0573", alias_for: "s0573")`: `action:` and `alias_for:` are exclusive.|)
954
+ end
955
+
956
+ end
957
+
958
+
959
+ topic '.define_alias()' do
960
+
961
+ spec "[!tcpuz] just defines an alias when current prefix is nil." do
962
+ ScopeTestAction.class_eval do
963
+ @action.("sample")
964
+ def a7033()
965
+ end
966
+ define_alias "x7033", "a7033"
967
+ end
968
+ md = Benry::CmdApp::REGISTRY.metadata_get("x7033")
969
+ ok {md.action} == "a7033"
970
+ end
971
+
972
+ spec "[!c6duw] defines an alias with prefix when current prefix exist." do
973
+ ScopeTestAction.class_eval do
974
+ category "p8866:" do
975
+ @action.("sample")
976
+ def a5073()
977
+ end
978
+ define_alias "x5073", "a5073"
979
+ end
980
+ end
981
+ md = Benry::CmdApp::REGISTRY.metadata_get("x5073")
982
+ ok {md.action} == "p8866:a5073"
983
+ end
984
+
985
+ spec "[!b8ly2] supports array argument." do
986
+ ScopeTestAction.class_eval do
987
+ category "p2433:" do
988
+ @action.("sample")
989
+ def a9940(arg)
990
+ end
991
+ define_alias "x2433", ["a9940", "abc"]
992
+ end
993
+ end
994
+ md = Benry::CmdApp::REGISTRY.metadata_get("x2433")
995
+ ok {md.action} == "p2433:a9940"
996
+ ok {md.args} == ["abc"]
997
+ end
998
+
999
+ spec "[!0dkrj] keyword arguments are passed to higher function." do
1000
+ ScopeTestAction.class_eval do
1001
+ category "p5582:"
1002
+ @action.("sample")
1003
+ def a1017(arg)
1004
+ end
1005
+ define_alias "x5582", ["a1017", "abc"], hidden: true, important: true, tag: "experimental"
1006
+ @__prefixdef__ = nil
1007
+ end
1008
+ md = Benry::CmdApp::REGISTRY.metadata_get("x5582")
1009
+ ok {md.action} == "p5582:a1017"
1010
+ ok {md.hidden?} == true
1011
+ ok {md.important?} == true
1012
+ ok {md.tag} == "experimental"
1013
+ end
1014
+
1015
+ end
1016
+
1017
+
1018
+ topic '.optionset()' do
1019
+
1020
+ spec "[!us0g4] yields block with dummy action." do
1021
+ _ = self
1022
+ called = false
1023
+ ScopeTestAction.class_eval do
1024
+ optset1 = optionset() do
1025
+ called = true
1026
+ _.ok {@__actiondef__} != nil
1027
+ _.ok {@__actiondef__[0]} == "dummy action by optionset()"
1028
+ end
1029
+ end
1030
+ ok {called} == true
1031
+ end
1032
+
1033
+ spec "[!1idwv] clears default option items." do
1034
+ _ = self
1035
+ ScopeTestAction.class_eval do
1036
+ optset1 = optionset() do
1037
+ schema = @__actiondef__[1]
1038
+ _.ok {schema.each.to_a}.length(0)
1039
+ end
1040
+ end
1041
+ end
1042
+
1043
+ spec "[!sp3hk] clears `@__actiondef__` to make `@action.()` available." do
1044
+ _ = self
1045
+ ScopeTestAction.class_eval do
1046
+ _.ok {@__actiondef__} == nil
1047
+ optset1 = optionset() do
1048
+ _.ok {@__actiondef__} != nil
1049
+ end
1050
+ _.ok {@__actiondef__} == nil
1051
+ end
1052
+ end
1053
+
1054
+ spec "[!mwbyc] returns new OptionSet object which contains option items." do
1055
+ optset1 = nil
1056
+ ScopeTestAction.class_eval do
1057
+ optset1 = optionset() do
1058
+ @option.(:user, "-u, --user=<user>", "user name")
1059
+ @option.(:email, "-e, --email=<email>", "email address")
1060
+ end
1061
+ end
1062
+ ok {optset1}.is_a?(Benry::CmdApp::OptionSet)
1063
+ items = optset1.instance_variable_get(:@items)
1064
+ ok {items[0].key} == :user
1065
+ ok {items[1].key} == :email
1066
+ end
1067
+
1068
+ end
1069
+
1070
+
1071
+ topic '#run_once()' do
1072
+
1073
+ spec "[!nqjxk] runs action and returns true if not runned ever." do
1074
+ scope = MyAction.new(@config)
1075
+ capture_sio do
1076
+ ok {scope.run_once("hello")} == true
1077
+ end
1078
+ end
1079
+
1080
+ spec "[!wcyut] not run action and returns false if already runned." do
1081
+ scope = MyAction.new(@config)
1082
+ sout, serr = capture_sio do
1083
+ ok {scope.run_once("hello")} == true
1084
+ ok {scope.run_once("hello")} == false
1085
+ ok {scope.run_once("hello")} == false
1086
+ end
1087
+ ok {sout} == "Hello, world!\n"
1088
+ end
1089
+
1090
+ end
1091
+
1092
+
1093
+ topic '#run_action()' do
1094
+
1095
+ spec "[!uwi68] runs action and returns true." do
1096
+ scope = MyAction.new(@config)
1097
+ sout, serr = capture_sio do
1098
+ ok {scope.run_action("hello")} == true
1099
+ ok {scope.run_action("hello")} == true
1100
+ ok {scope.run_action("hello")} == true
1101
+ end
1102
+ ok {sout} == "Hello, world!\n" * 3
1103
+ end
1104
+
1105
+ end
1106
+
1107
+
1108
+ topic '#at_end()' do
1109
+
1110
+ spec "[!3mqcz] registers proc object to context object." do
1111
+ context = Benry::CmdApp::ApplicationContext.new(@config)
1112
+ scope = MyAction.new(@config, context)
1113
+ ok {context.instance_variable_get(:@end_blocks)}.length(0)
1114
+ scope.at_end { puts "A" }
1115
+ scope.at_end { puts "B" }
1116
+ ok {context.instance_variable_get(:@end_blocks)}.length(2)
1117
+ ok {context.instance_variable_get(:@end_blocks)}.all? {|x| x.is_a?(Proc) }
1118
+ end
1119
+ end
1120
+
1121
+
1122
+ topic '#option_error()' do
1123
+
1124
+ spec "[!engp2] returns OptionError object." do
1125
+ x = ScopeTestAction.new(nil).instance_eval {
1126
+ option_error("error message e2038")
1127
+ }
1128
+ ok {x}.is_a?(Benry::CmdApp::OptionError)
1129
+ ok {x.message} == "error message e2038"
1130
+ end
1131
+
1132
+ end
1133
+
1134
+
1135
+ topic '#action_error()' do
1136
+
1137
+ spec "[!2m7d6] returns ActionError object." do
1138
+ x = ScopeTestAction.new(nil).instance_eval {
1139
+ action_error("error message e4417")
1140
+ }
1141
+ ok {x}.is_a?(Benry::CmdApp::ActionError)
1142
+ ok {x.message} == "error message e4417"
1143
+ end
1144
+
1145
+ end
1146
+
1147
+
1148
+ end
1149
+
1150
+
1151
+ topic Benry::CmdApp::BuiltInAction do
1152
+
1153
+ before do
1154
+ @config = Benry::CmdApp::Config.new("test app", "1.2.3",
1155
+ app_name: "TestApp", app_command: "testapp",
1156
+ option_verbose: true, option_quiet: true,
1157
+ option_color: true, #option_debug: true,
1158
+ option_trace: true)
1159
+ end
1160
+
1161
+ topic '#help()' do
1162
+
1163
+ spec "[!2n99u] raises ActionError if current application is not nil." do
1164
+ scope = Benry::CmdApp::BuiltInAction.new(@config)
1165
+ pr = proc { scope.help() }
1166
+ ok {pr}.raise?(Benry::CmdApp::ActionError,
1167
+ "'help' action is available only when invoked from application.")
1168
+ end
1169
+
1170
+ spec "[!g0n06] prints application help message if action name not specified." do
1171
+ app = Benry::CmdApp::Application.new(@config)
1172
+ Benry::CmdApp._set_current_app(app)
1173
+ at_end { Benry::CmdApp._set_current_app(nil) }
1174
+ scope = Benry::CmdApp::BuiltInAction.new(@config)
1175
+ sout, serr = capture_sio(tty: true) { scope.help() }
1176
+ ok {sout} =~ /\A\e\[1mTestApp\e\[0m \e\[2m\(1\.2\.3\)\e\[0m --- test app$/
1177
+ ok {sout} =~ /^\e\[1;34mUsage:\e\[0m$/
1178
+ ok {sout} =~ /^\e\[1;34mOptions:\e\[0m$/
1179
+ ok {sout} =~ /^\e\[1;34mActions:\e\[0m$/
1180
+ end
1181
+
1182
+ spec "[!epj74] prints action help message if action name specified." do
1183
+ app = Benry::CmdApp::Application.new(@config)
1184
+ Benry::CmdApp._set_current_app(app)
1185
+ at_end { Benry::CmdApp._set_current_app(nil) }
1186
+ scope = Benry::CmdApp::BuiltInAction.new(@config)
1187
+ sout, serr = capture_sio(tty: true) { scope.help("hello") }
1188
+ ok {sout} =~ /\A\e\[1mtestapp hello\e\[0m --- greeting message$/
1189
+ ok {sout} =~ /^\e\[1;34mUsage:\e\[0m$/
1190
+ ok {sout} =~ /^\e\[1;34mOptions:\e\[0m$/
1191
+ ok {sout} !~ /^\e\[1;34mActions:\e\[0m$/
1192
+ end
1193
+
1194
+ spec "[!2t43b] deletes escape characters from help message when non-color mode." do
1195
+ app = Benry::CmdApp::Application.new(@config)
1196
+ Benry::CmdApp._set_current_app(app)
1197
+ at_end { Benry::CmdApp._set_current_app(nil) }
1198
+ scope = Benry::CmdApp::BuiltInAction.new(@config)
1199
+ #
1200
+ sout, serr = capture_sio(tty: false) { scope.help() }
1201
+ ok {sout} =~ /\ATestApp \(1\.2\.3\) --- test app$/
1202
+ ok {sout} =~ /^Usage:$/
1203
+ ok {sout} =~ /^Options:$/
1204
+ ok {sout} =~ /^Actions:$/
1205
+ #
1206
+ sout, serr = capture_sio(tty: false) { scope.help("hello") }
1207
+ ok {sout} =~ /\Atestapp hello --- greeting message$/
1208
+ ok {sout} =~ /^Usage:$/
1209
+ ok {sout} =~ /^Options:$/
1210
+ ok {sout} !~ /^Actions:$/
1211
+ end
1212
+
1213
+ end
1214
+
1215
+
1216
+ end
1217
+
1218
+
1219
+ end