Files
interactive-env/tests/test_prompt.sh
2026-03-10 00:14:14 -05:00

191 lines
8.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# Unit tests for prompt helper functions in lib/prompt.sh.
#
# All interactive functions write prompts to stderr and read from stdin.
# Tests pipe input via stdin and capture stdout, suppressing stderr.
TESTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(dirname "$TESTS_DIR")"
source "$TESTS_DIR/framework.sh"
source "$ROOT_DIR/lib/colors.sh"
source "$ROOT_DIR/lib/validate.sh"
source "$ROOT_DIR/lib/prompt.sh"
# Helpers: feed stdin to a function and capture its stdout
feed() {
# feed <input_string> <function> [args...]
local input="$1"; shift
printf "%s" "$input" | "$@" 2>/dev/null
}
# ---------------------------------------------------------------------------
suite "_prompt_enum: numeric selection"
# ---------------------------------------------------------------------------
assert_eq "a" "$(feed "1"$'\n' _prompt_enum "V" "a,b,c" "a")" "choice 1 -> first option"
assert_eq "b" "$(feed "2"$'\n' _prompt_enum "V" "a,b,c" "a")" "choice 2 -> second option"
assert_eq "c" "$(feed "3"$'\n' _prompt_enum "V" "a,b,c" "a")" "choice 3 -> third option"
# ---------------------------------------------------------------------------
suite "_prompt_enum: string selection"
# ---------------------------------------------------------------------------
assert_eq "a" "$(feed "a"$'\n' _prompt_enum "V" "a,b,c" "")" "string 'a' selects a"
assert_eq "b" "$(feed "b"$'\n' _prompt_enum "V" "a,b,c" "")" "string 'b' selects b"
assert_eq "c" "$(feed "c"$'\n' _prompt_enum "V" "a,b,c" "")" "string 'c' selects c"
# ---------------------------------------------------------------------------
suite "_prompt_enum: empty input uses default"
# ---------------------------------------------------------------------------
assert_eq "a" "$(feed $'\n' _prompt_enum "V" "a,b,c" "a")" "empty -> first default"
assert_eq "b" "$(feed $'\n' _prompt_enum "V" "a,b,c" "b")" "empty -> middle default"
assert_eq "c" "$(feed $'\n' _prompt_enum "V" "a,b,c" "c")" "empty -> last default"
# ---------------------------------------------------------------------------
suite "_prompt_enum: invalid choice then valid"
# ---------------------------------------------------------------------------
# Send out-of-range number, then a valid number
assert_eq "b" "$(printf "99\n2\n" | _prompt_enum "V" "a,b,c" "a" 2>/dev/null)" \
"invalid index followed by valid index"
# Send unknown string, then valid string
assert_eq "c" "$(printf "zzz\nc\n" | _prompt_enum "V" "a,b,c" "a" 2>/dev/null)" \
"invalid string followed by valid string"
# ---------------------------------------------------------------------------
suite "_prompt_enum: real-world APP_ENV"
# ---------------------------------------------------------------------------
assert_eq "development" \
"$(feed $'\n' _prompt_enum "APP_ENV" "development,staging,production" "development")" \
"empty -> development (default)"
assert_eq "production" \
"$(feed "3"$'\n' _prompt_enum "APP_ENV" "development,staging,production" "development")" \
"choice 3 -> production"
assert_eq "staging" \
"$(feed "staging"$'\n' _prompt_enum "APP_ENV" "development,staging,production" "development")" \
"string 'staging' -> staging"
# ---------------------------------------------------------------------------
suite "_prompt_bool: explicit inputs"
# ---------------------------------------------------------------------------
assert_eq "true" "$(feed "y"$'\n' _prompt_bool "")" "y -> true"
assert_eq "true" "$(feed "yes"$'\n' _prompt_bool "")" "yes -> true"
assert_eq "true" "$(feed "true"$'\n' _prompt_bool "")" "true -> true"
assert_eq "true" "$(feed "1"$'\n' _prompt_bool "")" "1 -> true"
assert_eq "false" "$(feed "n"$'\n' _prompt_bool "")" "n -> false"
assert_eq "false" "$(feed "no"$'\n' _prompt_bool "")" "no -> false"
assert_eq "false" "$(feed "false"$'\n' _prompt_bool "")" "false -> false"
assert_eq "false" "$(feed "0"$'\n' _prompt_bool "")" "0 -> false"
# ---------------------------------------------------------------------------
suite "_prompt_bool: empty input uses default"
# ---------------------------------------------------------------------------
assert_eq "true" "$(feed $'\n' _prompt_bool "true")" "empty -> true default"
assert_eq "true" "$(feed $'\n' _prompt_bool "yes")" "empty -> yes default normalizes to true"
assert_eq "false" "$(feed $'\n' _prompt_bool "false")" "empty -> false default"
assert_eq "false" "$(feed $'\n' _prompt_bool "no")" "empty -> no default normalizes to false"
# ---------------------------------------------------------------------------
suite "_prompt_bool: invalid then valid"
# ---------------------------------------------------------------------------
assert_eq "true" "$(printf "banana\ny\n" | _prompt_bool "" 2>/dev/null)" \
"invalid input followed by y"
assert_eq "false" "$(printf "maybe\nn\n" | _prompt_bool "" 2>/dev/null)" \
"invalid input followed by n"
# ---------------------------------------------------------------------------
suite "_prompt_secret: matching values accepted"
# ---------------------------------------------------------------------------
assert_eq "mysecret" \
"$(printf "mysecret\nmysecret\n" | _prompt_secret "V" "" 2>/dev/null)" \
"matching entries return value"
assert_eq "p@ss!#\$word" \
"$(printf 'p@ss!#$word\np@ss!#$word\n' | _prompt_secret "V" "" 2>/dev/null)" \
"special characters in secret preserved"
# ---------------------------------------------------------------------------
suite "_prompt_secret: empty input uses default"
# ---------------------------------------------------------------------------
assert_eq "defaultsecret" \
"$(printf "\n" | _prompt_secret "V" "defaultsecret" 2>/dev/null)" \
"empty input returns default"
# ---------------------------------------------------------------------------
suite "_prompt_secret: mismatch retries"
# ---------------------------------------------------------------------------
# First pair mismatches, second pair matches
assert_eq "correct" \
"$(printf "wrong\nmismatch\ncorrect\ncorrect\n" | _prompt_secret "V" "" 2>/dev/null)" \
"mismatch retries until match"
# ---------------------------------------------------------------------------
suite "prompt_variable: string type stores value"
# ---------------------------------------------------------------------------
# Use process substitution (<(...)) so prompt_variable runs in the current
# shell and its variable assignments (ENV_VALUE_*) persist.
ENV_VARS=("MYVAR")
ENV_DESC_MYVAR="A test variable"
ENV_TYPE_MYVAR="string"
ENV_REQUIRED_MYVAR="false"
ENV_DEFAULT_MYVAR="default_val"
# Accept default
prompt_variable "MYVAR" < <(printf "\n") 2>/dev/null
assert_eq "default_val" "$ENV_VALUE_MYVAR" "empty input stores default"
# Provide a value
prompt_variable "MYVAR" < <(printf "custom\n") 2>/dev/null
assert_eq "custom" "$ENV_VALUE_MYVAR" "typed value stored"
# ---------------------------------------------------------------------------
suite "prompt_variable: number type re-prompts on invalid input"
# ---------------------------------------------------------------------------
ENV_TYPE_MYVAR="number"
ENV_DEFAULT_MYVAR="42"
prompt_variable "MYVAR" < <(printf "abc\n99\n") 2>/dev/null
assert_eq "99" "$ENV_VALUE_MYVAR" "invalid number re-prompts, then stores valid"
# ---------------------------------------------------------------------------
suite "prompt_variable: bool type"
# ---------------------------------------------------------------------------
ENV_TYPE_MYVAR="bool"
ENV_DEFAULT_MYVAR="false"
prompt_variable "MYVAR" < <(printf "y\n") 2>/dev/null
assert_eq "true" "$ENV_VALUE_MYVAR" "bool y stored as true"
prompt_variable "MYVAR" < <(printf "\n") 2>/dev/null
assert_eq "false" "$ENV_VALUE_MYVAR" "bool empty uses false default"
# ---------------------------------------------------------------------------
suite "prompt_variable: enum type"
# ---------------------------------------------------------------------------
ENV_TYPE_MYVAR="enum:x,y,z"
ENV_DEFAULT_MYVAR="x"
prompt_variable "MYVAR" < <(printf "2\n") 2>/dev/null
assert_eq "y" "$ENV_VALUE_MYVAR" "enum choice 2 stores y"
prompt_variable "MYVAR" < <(printf "\n") 2>/dev/null
assert_eq "x" "$ENV_VALUE_MYVAR" "enum empty uses default x"
print_summary