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