syntaxai/tdd.md · main · tools / sama-cli / src / c14_graph.test.sh

c14_graph.test.sh 110 lines · 3180 bytes raw
#!/usr/bin/env bash
# Sibling test for c14_graph.sh. Verifies emit_dot produces a
# well-formed graphviz file with the expected node + edge content,
# and that render_graph falls back gracefully when `dot` is absent.

SAMA_SRC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
# shellcheck disable=SC1091
. "$SAMA_SRC_DIR/a31_constants.sh"
# shellcheck disable=SC1091
. "$SAMA_SRC_DIR/b32_utils.sh"
# shellcheck disable=SC1091
. "$SAMA_SRC_DIR/b32_checks.sh"
# shellcheck disable=SC1091
. "$SAMA_SRC_DIR/c14_graph.sh"

TESTS_RUN=0
TESTS_FAILED=0

assert_eq() {
  local expected="$1" actual="$2" label="$3"
  TESTS_RUN=$((TESTS_RUN + 1))
  if [ "$expected" = "$actual" ]; then
    printf "  ok  %s\n" "$label"
  else
    TESTS_FAILED=$((TESTS_FAILED + 1))
    printf "  FAIL %s\n    expected: %s\n    actual:   %s\n" "$label" "$expected" "$actual"
  fi
}

assert_contains() {
  local haystack="$1" needle="$2" label="$3"
  TESTS_RUN=$((TESTS_RUN + 1))
  case "$haystack" in
    *"$needle"*) printf "  ok  %s\n" "$label" ;;
    *)
      TESTS_FAILED=$((TESTS_FAILED + 1))
      printf "  FAIL %s — needle \`%s\` not found\n" "$label" "$needle"
      ;;
  esac
}

TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT

# Build a tiny fixture repo.
mkdir -p "$TMP_DIR/repo/src"
cat > "$TMP_DIR/repo/sama.profile.toml" <<'EOF'
sama_version = "2.0"
profile = "graph-fixture"
extension = ".ts"

[layers.0]
prefixes = ["a_"]

[layers.1]
prefixes = ["b_"]

[layers.2]
prefixes = ["c_"]

[layers.3]
prefixes = ["d_"]
EOF

cat > "$TMP_DIR/repo/src/a_pure.ts" <<'EOF'
export const X = 1;
EOF

cat > "$TMP_DIR/repo/src/b_logic.ts" <<'EOF'
import { X } from "./a_pure.ts";
export const Y = X + 1;
EOF

parse_profile "$TMP_DIR/repo/sama.profile.toml"
collect_input "$TMP_DIR/repo" "$TMP_DIR/repo/src"

# — emit_dot ------------------------------------------------------
dot_output="$(emit_dot "$TMP_DIR/repo" "$TMP_DIR/repo/src")"

assert_contains "$dot_output" "digraph sama {" "emit_dot: opens with digraph block"
assert_contains "$dot_output" "src/a_pure.ts" "emit_dot: includes a_pure node"
assert_contains "$dot_output" "src/b_logic.ts" "emit_dot: includes b_logic node"
assert_contains "$dot_output" "L0" "emit_dot: labels Layer 0"
assert_contains "$dot_output" "L1" "emit_dot: labels Layer 1"
assert_contains "$dot_output" "\"src/b_logic.ts\" -> \"src/a_pure.ts\"" "emit_dot: emits b → a edge"

# — render_graph: writes .dot regardless of `dot` availability ----
out_dot="$TMP_DIR/graph.dot"
out_png="$TMP_DIR/graph.png"
render_graph "$TMP_DIR/repo" "$TMP_DIR/repo/src" "$out_dot" "$out_png" >/dev/null 2>&1
if [ -f "$out_dot" ]; then
  TESTS_RUN=$((TESTS_RUN + 1))
  printf "  ok  render_graph: writes .dot file\n"
else
  TESTS_RUN=$((TESTS_RUN + 1))
  TESTS_FAILED=$((TESTS_FAILED + 1))
  printf "  FAIL render_graph: did not write .dot file\n"
fi

# — Summary -------------------------------------------------------
echo
if [ "$TESTS_FAILED" -eq 0 ]; then
  printf "c14_graph.test.sh: %d/%d passed ✓\n" "$TESTS_RUN" "$TESTS_RUN"
  exit 0
else
  printf "c14_graph.test.sh: %d/%d passed, %d FAILED ✗\n" \
    "$((TESTS_RUN - TESTS_FAILED))" "$TESTS_RUN" "$TESTS_FAILED"
  exit 1
fi