-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlib_cli.bats
More file actions
176 lines (137 loc) · 6.2 KB
/
Copy pathlib_cli.bats
File metadata and controls
176 lines (137 loc) · 6.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/usr/bin/env bats
load ../../tests/test_helper.sh
setup() {
setup_test_tmpdir
source "$BASE_BASH_DIR/std/lib_std.sh"
# shellcheck disable=SC2034 # base_init receives the caller-owned argv array by name.
declare -a setup_args=()
base_init setup_args --source "$BASE_BASH_DIR/cli/tests/lib_cli.bats" --
source "$BASE_BASH_DIR/cli/lib_cli.sh"
}
valid_target() {
[[ "$1" =~ ^[a-z][a-z0-9-]*$ ]]
}
declare_demo_model() {
base_cli_model_init demo name=demo version=2.0.0 description="Demo CLI"
base_cli_command demo admin "Administration" aliases=manage
base_cli_command demo admin/user "Show a user" aliases=u
base_cli_option demo admin/user verbose flag --verbose -v help="Verbose output"
base_cli_option demo admin/user color value --color default=blue enum=blue,green metavar=COLOR help="Output color"
base_cli_option demo admin/user tag repeatable --tag -t help="A tag"
base_cli_positional demo admin/user target required=true validator=valid_target help="Target name"
}
@test "lib_cli can be sourced more than once" {
source "$BASE_BASH_DIR/cli/lib_cli.sh"
[ "$(type -t base_cli_model_init)" = "function" ]
}
@test "lib_cli fails clearly when sourced without stdlib" {
bats_run bash -c 'source "$1"; rc=$?; printf "source-rc=%s\n" "$rc"; exit "$rc"' bash "$BASE_BASH_DIR/cli/lib_cli.sh"
[ "$status" -eq 1 ]
[[ "$output" == *"lib_cli.sh requires lib_std.sh to be sourced first"* ]]
[[ "$output" == *"source-rc=1"* ]]
}
@test "declarative model parses nested aliases and preserves result boundaries" {
declare_demo_model
base_cli_parse demo -- manage u target-name --color green --tag one --tag "two words" --verbose
[ "$BASE_BASH_LIBS_CLI_RESULT_COMMAND" = "admin/user" ]
[ "${BASE_BASH_LIBS_CLI_RESULT_OPTIONS[color]}" = "green" ]
[ "${BASE_BASH_LIBS_CLI_RESULT_OPTIONS[verbose]}" = "1" ]
[ "${BASE_BASH_LIBS_CLI_RESULT_REPEATABLE_COUNTS[tag]}" -eq 2 ]
[ "${BASE_BASH_LIBS_CLI_RESULT_REPEATED[tag\|0]}" = "one" ]
[ "${BASE_BASH_LIBS_CLI_RESULT_REPEATED[tag\|1]}" = "two words" ]
local target color count
base_cli_result_get_positional 0 target
base_cli_result_get color color
base_cli_result_count tag count
[ "$target" = "target-name" ]
[ "$color" = "green" ]
[ "$count" -eq 2 ]
}
@test "help is deterministic and includes aliases, defaults, and nested usage" {
declare_demo_model
bats_run base_cli_help demo admin/user
[ "$status" -eq 0 ]
[[ "$output" == *"Usage: demo admin/user [options] <target>"* ]]
[[ "$output" == *"--color <COLOR>"* ]]
[[ "$output" == *"(default: blue)"* ]]
[[ "$output" == *"--tag, -t"* ]]
bats_run base_cli_help demo
[ "$status" -eq 0 ]
[[ "$output" == *"admin (manage)"* ]]
}
@test "help redacts sensitive defaults and aligns long option labels" {
base_cli_model_init secrets name=secrets version=2.0.0
base_cli_command secrets run "Run"
base_cli_option secrets run api_token value --api-token default='top-secret' sensitive=true help='Authentication token'
base_cli_option secrets run extraordinarily_long_option value --extraordinarily-long-option default=visible help='Long option'
bats_run base_cli_help secrets run
[ "$status" -eq 0 ]
[[ "$output" == *"--api-token <api_token> Authentication token (default: <redacted>)"* ]]
[[ "$output" != *"top-secret"* ]]
[[ "$output" == *"--extraordinarily-long-option <extraordinarily_long_option> Long option (default: visible)"* ]]
}
@test "conflicts must reference an already declared option" {
base_cli_model_init invalid name=invalid
base_cli_command invalid run "Run"
bats_run base_cli_option invalid run mode flag --mode conflicts=missing
[ "$status" -eq 2 ]
[[ "$output" == *"conflict option 'missing' is not declared"* ]]
}
@test "usage errors return status 2 with diagnostics" {
declare_demo_model
bats_run base_cli_parse demo -- admin user --color purple target-name
[ "$status" -eq 2 ]
[[ "$output" == *"invalid value for option 'color'"* ]]
[[ "$output" == *"Usage: demo admin/user"* ]]
bats_run base_cli_parse demo -- admin user target-name --unknown
[ "$status" -eq 2 ]
[[ "$output" == *"unknown option '--unknown'"* ]]
}
@test "double dash preserves empty and option-looking positionals" {
base_cli_model_init dash name=dash
base_cli_command dash run "Run"
base_cli_positional dash run first required=true
base_cli_positional dash run rest repeatable=true
base_cli_parse dash -- run "" -- --looks-like-option
[ "${#BASE_BASH_LIBS_CLI_RESULT_POSITIONALS[@]}" -eq 2 ]
[ "${BASE_BASH_LIBS_CLI_RESULT_POSITIONALS[0]}" = "" ]
[ "${BASE_BASH_LIBS_CLI_RESULT_POSITIONALS[1]}" = "--looks-like-option" ]
}
@test "run invokes handlers but help and version do not" {
local handler_calls=0
demo_handler() {
handler_calls=$((handler_calls + 1))
}
base_cli_model_init runme name=runme version=2.0.0 handler=demo_handler
base_cli_run runme -- --help
[ "$handler_calls" -eq 0 ]
base_cli_run runme -- --version
[ "$handler_calls" -eq 0 ]
base_cli_run runme --
[ "$handler_calls" -eq 1 ]
}
@test "explicit model validation catches undeclared handlers" {
base_cli_model_init validate name=validate handler=missing_root
base_cli_command validate run "Run" handler=missing_run
bats_run base_cli_validate_model validate
[ "$status" -eq 2 ]
[[ "$output" == *"<root>:missing_root"* ]]
[[ "$output" == *"run:missing_run"* ]]
missing_root() { :; }
missing_run() { :; }
base_cli_validate_model validate
}
@test "completion emits aliases and a self-contained completion adapter" {
declare_demo_model
bats_run base_cli_complete demo -- admin u
[ "$status" -eq 0 ]
[[ "$output" == *$'user\n'* || "$output" == user ]]
[[ "$output" == *$'u'* ]]
bats_run base_cli_completion_script demo _demo_complete
[ "$status" -eq 0 ]
[[ "$output" == *"_demo_complete()"* ]]
[[ "$output" == *"complete -F _demo_complete demo"* ]]
}
@test "the declarative runtime contains no eval dependency" {
! grep -Ev '^[[:space:]]*#' "$BASE_BASH_DIR/cli/lib_cli.sh" | grep -Eq '(^|[[:space:];])eval([[:space:];]|$)'
}