mirror of
https://github.com/saymrwulf/JupyterManager.git
synced 2026-05-14 20:38:00 +00:00
CLI tool that discovers and manages JupyterLab instances across multiple projects. Prevents port conflicts, finds orphan processes, provides unified status and stop-all functionality. Includes: - bin/jupyter-hub: the CLI (status, ports, stop-all, orphans, which, config) - config/defaults.sh: default scan dirs and port range - docs/LIFECYCLE_SPEC.md: client project requirements - docs/AGENT_PROMPT.md: prompt for coding agents to align projects - install.sh: symlink installer to ~/bin - tests/test_jupyter_hub.sh: 15 functional tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
95 lines
4 KiB
Bash
Executable file
95 lines
4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
# test_jupyter_hub.sh — Tests for jupyter-hub
|
|
#
|
|
# Usage: bash tests/test_jupyter_hub.sh
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
JHUB="$SCRIPT_DIR/bin/jupyter-hub"
|
|
|
|
passed=0
|
|
failed=0
|
|
|
|
pass() { echo " ✓ $1"; passed=$((passed + 1)); }
|
|
fail() { echo " ✗ $1: $2"; failed=$((failed + 1)); }
|
|
|
|
assert_exit_0() {
|
|
local desc="$1"; shift
|
|
if "$@" >/dev/null 2>&1; then
|
|
pass "$desc"
|
|
else
|
|
fail "$desc" "exited with $?"
|
|
fi
|
|
}
|
|
|
|
assert_output_contains() {
|
|
local desc="$1"
|
|
local expected="$2"
|
|
shift 2
|
|
local output
|
|
output=$("$@" 2>&1) || true
|
|
if echo "$output" | grep -q "$expected"; then
|
|
pass "$desc"
|
|
else
|
|
fail "$desc" "output did not contain '$expected'"
|
|
fi
|
|
}
|
|
|
|
echo ""
|
|
echo "Testing jupyter-hub"
|
|
echo ""
|
|
|
|
# ── Basic invocation ──────────────────────────────────────────────────
|
|
echo "Basic invocation:"
|
|
assert_exit_0 "help exits 0" "$JHUB" help
|
|
assert_exit_0 "version exits 0" "$JHUB" version
|
|
assert_exit_0 "config exits 0" "$JHUB" config
|
|
assert_output_contains "version shows version string" "jupyter-hub v" "$JHUB" version
|
|
assert_output_contains "help shows Commands section" "Commands:" "$JHUB" help
|
|
|
|
# ── Status command ────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "Status command:"
|
|
assert_exit_0 "status exits 0" "$JHUB" status
|
|
assert_output_contains "status shows header" "Jupyter Hub" "$JHUB" status
|
|
|
|
# ── Ports command ─────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "Ports command:"
|
|
assert_exit_0 "ports exits 0" "$JHUB" ports
|
|
assert_output_contains "ports shows 8888" "8888" "$JHUB" ports
|
|
|
|
# ── Config command ────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "Config command:"
|
|
assert_output_contains "config shows install root" "Install root" "$JHUB" config
|
|
assert_output_contains "config shows port range" "Port range" "$JHUB" config
|
|
assert_output_contains "config shows scan dirs" "Scan directories" "$JHUB" config
|
|
|
|
# ── Which command ─────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "Which command:"
|
|
# Use a port that's almost certainly free
|
|
assert_output_contains "which on free port says free" "free" "$JHUB" which 19999
|
|
|
|
# ── Orphans command ───────────────────────────────────────────────────
|
|
echo ""
|
|
echo "Orphans command:"
|
|
assert_exit_0 "orphans exits 0" "$JHUB" orphans
|
|
|
|
# ── Unknown command ───────────────────────────────────────────────────
|
|
echo ""
|
|
echo "Error handling:"
|
|
assert_output_contains "unknown command prints error" "Unknown command" "$JHUB" nonexistent
|
|
|
|
# ── Summary ───────────────────────────────────────────────────────────
|
|
echo ""
|
|
total=$((passed + failed))
|
|
if (( failed == 0 )); then
|
|
echo "All $total tests passed."
|
|
else
|
|
echo "$passed/$total passed, $failed FAILED."
|
|
exit 1
|
|
fi
|