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

193 lines
6.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# Unit tests for lib/output.sh
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/output.sh"
TMPDIR_SELF="$(mktemp -d)"
trap 'rm -rf "$TMPDIR_SELF"' EXIT
# ---------------------------------------------------------------------------
suite "output: basic file creation"
# ---------------------------------------------------------------------------
ENV_VARS=("FOO" "BAR")
ENV_DESC_FOO=""
ENV_DESC_BAR=""
ENV_VALUE_FOO="hello"
ENV_VALUE_BAR="world"
OUT="$TMPDIR_SELF/basic.env"
write_env_file "$OUT" 2>/dev/null
assert_file_exists "$OUT" "output file created"
assert_file_contains "FOO=hello" "$OUT" "FOO written correctly"
assert_file_contains "BAR=world" "$OUT" "BAR written correctly"
assert_file_contains "# Generated by generate-env" "$OUT" "header present"
# ---------------------------------------------------------------------------
suite "output: variable order matches ENV_VARS"
# ---------------------------------------------------------------------------
ENV_VARS=("ALPHA" "BETA" "GAMMA")
ENV_VALUE_ALPHA="1"
ENV_VALUE_BETA="2"
ENV_VALUE_GAMMA="3"
OUT="$TMPDIR_SELF/order.env"
write_env_file "$OUT" 2>/dev/null
# grep -n returns the line number; verify order
alpha_line=$(grep -n "ALPHA=" "$OUT" | cut -d: -f1)
beta_line=$(grep -n "BETA=" "$OUT" | cut -d: -f1)
gamma_line=$(grep -n "GAMMA=" "$OUT" | cut -d: -f1)
if (( alpha_line < beta_line && beta_line < gamma_line )); then
pass "variable order preserved"
else
fail "variable order preserved" "ALPHA < BETA < GAMMA" "lines $alpha_line, $beta_line, $gamma_line"
fi
# ---------------------------------------------------------------------------
suite "output: empty values written as KEY="
# ---------------------------------------------------------------------------
ENV_VARS=("WITH_VALUE" "NO_VALUE")
ENV_VALUE_WITH_VALUE="set"
ENV_VALUE_NO_VALUE=""
OUT="$TMPDIR_SELF/empty.env"
write_env_file "$OUT" 2>/dev/null
assert_file_contains "WITH_VALUE=set" "$OUT" "non-empty value written"
assert_file_contains "NO_VALUE=" "$OUT" "empty value written as KEY="
assert_file_not_contains "NO_VALUE=x" "$OUT" "no stray value for empty var"
# ---------------------------------------------------------------------------
suite "output: values containing special characters"
# ---------------------------------------------------------------------------
ENV_VARS=("SPECIAL")
ENV_VALUE_SPECIAL='postgres://user:p@ss!#$@host:5432/db?ssl=true'
OUT="$TMPDIR_SELF/special.env"
write_env_file "$OUT" 2>/dev/null
assert_file_contains "SPECIAL=postgres://user:p@ss" "$OUT" "special chars in value preserved"
# ---------------------------------------------------------------------------
suite "output: values containing equals signs"
# ---------------------------------------------------------------------------
ENV_VARS=("DB_URL")
ENV_VALUE_DB_URL="postgres://host/db?sslmode=require&timeout=10"
OUT="$TMPDIR_SELF/equals.env"
write_env_file "$OUT" 2>/dev/null
assert_file_contains "DB_URL=postgres://host/db?sslmode=require&timeout=10" \
"$OUT" "equals signs in value preserved"
# ---------------------------------------------------------------------------
suite "output: header contains ISO-8601 timestamp"
# ---------------------------------------------------------------------------
ENV_VARS=("X")
ENV_VALUE_X="1"
OUT="$TMPDIR_SELF/ts.env"
write_env_file "$OUT" 2>/dev/null
# Header should contain a UTC timestamp in the form YYYY-MM-DDTHH:MM:SSZ
if grep -qE '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z' "$OUT"; then
pass "header contains ISO-8601 UTC timestamp"
else
fail "header contains ISO-8601 UTC timestamp" \
"YYYY-MM-DDTHH:MM:SSZ" "(not found in header)"
fi
# ---------------------------------------------------------------------------
suite "output: single variable"
# ---------------------------------------------------------------------------
ENV_VARS=("SOLO")
ENV_VALUE_SOLO="only"
OUT="$TMPDIR_SELF/solo.env"
write_env_file "$OUT" 2>/dev/null
assert_file_exists "$OUT" "file created for single var"
assert_file_contains "SOLO=only" "$OUT" "single var written"
# ---------------------------------------------------------------------------
suite "output: description written as comment before KEY=VALUE"
# ---------------------------------------------------------------------------
ENV_VARS=("DESCRIBED" "NODESC")
ENV_DESC_DESCRIBED="Explains this variable"
ENV_DESC_NODESC=""
ENV_VALUE_DESCRIBED="val1"
ENV_VALUE_NODESC="val2"
OUT="$TMPDIR_SELF/desc.env"
write_env_file "$OUT" 2>/dev/null
assert_file_contains "# Explains this variable" "$OUT" "description written as comment"
assert_file_contains "DESCRIBED=val1" "$OUT" "KEY=VALUE follows comment"
# The comment line should immediately precede the variable line
desc_line=$(grep -n "# Explains this variable" "$OUT" | cut -d: -f1)
var_line=$(grep -n "^DESCRIBED=" "$OUT" | cut -d: -f1)
if (( var_line == desc_line + 1 )); then
pass "comment is on the line directly before KEY=VALUE"
else
fail "comment is on the line directly before KEY=VALUE" \
"$((desc_line + 1))" "$var_line"
fi
# Variable with no description should have no comment line immediately before it
nodesc_line=$(grep -n "^NODESC=" "$OUT" | cut -d: -f1)
prev_line_content=$(sed -n "$((nodesc_line - 1))p" "$OUT")
if [[ -z "$prev_line_content" ]]; then
pass "variable with no description has blank line before it (no comment)"
else
fail "variable with no description has blank line before it (no comment)" \
"" "$prev_line_content"
fi
# ---------------------------------------------------------------------------
suite "output: blank line separates each variable block"
# ---------------------------------------------------------------------------
ENV_VARS=("A" "B" "C")
ENV_DESC_A="First"
ENV_DESC_B=""
ENV_DESC_C="Third"
ENV_VALUE_A="1"
ENV_VALUE_B="2"
ENV_VALUE_C="3"
OUT="$TMPDIR_SELF/spacing.env"
write_env_file "$OUT" 2>/dev/null
# Each variable block ends with a blank line; verify A and C have their comments
assert_file_contains "# First" "$OUT" "first var description present"
assert_file_contains "# Third" "$OUT" "third var description present"
a_line=$(grep -n "^A=" "$OUT" | cut -d: -f1)
b_line=$(grep -n "^B=" "$OUT" | cut -d: -f1)
# There must be a blank line between A= and B=
between=$(sed -n "$((a_line + 1)),$((b_line - 1))p" "$OUT")
if [[ -z "$between" || "$between" =~ ^[[:space:]]*$ ]]; then
pass "blank line between variable blocks"
else
fail "blank line between variable blocks" "(blank)" "$between"
fi
print_summary