test(kugetsu): add v2.0 test suite for issue-driven session management
This commit is contained in:
222
skills/kugetsu/tests/test-kugetsu-v2.sh
Normal file
222
skills/kugetsu/tests/test-kugetsu-v2.sh
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# kugetsu v2.0 test suite
|
||||||
|
# Tests issue-driven session management
|
||||||
|
#
|
||||||
|
# Run with: bash skills/kugetsu/tests/test-kugetsu-v2.sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
KUGETSU="./skills/kugetsu/scripts/kugetsu"
|
||||||
|
TEST_ISSUE_REF="github.com/shoko/kugetsu#14"
|
||||||
|
TEST_BASE_SESSION_ID="ses_test_base_123"
|
||||||
|
TEST_BASE_SESSION_FILE="base.json"
|
||||||
|
TEST_FORKED_SESSION_FILE="github.com-shoko-kugetsu-14.json"
|
||||||
|
PASS=0
|
||||||
|
FAIL=0
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
rm -rf ~/.kugetsu/sessions/* ~/.kugetsu/index.json 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_mock_base() {
|
||||||
|
mkdir -p ~/.kugetsu/sessions
|
||||||
|
cat > ~/.kugetsu/index.json << EOF
|
||||||
|
{
|
||||||
|
"base": "$TEST_BASE_SESSION_ID",
|
||||||
|
"issues": {}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
cat > ~/.kugetsu/sessions/$TEST_BASE_SESSION_FILE << EOF
|
||||||
|
{"type": "base", "opencode_session_id": "$TEST_BASE_SESSION_ID", "created_at": "2026-03-29T18:00:00+02:00", "state": "idle"}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_mock_forked() {
|
||||||
|
cat > ~/.kugetsu/index.json << EOF
|
||||||
|
{
|
||||||
|
"base": "$TEST_BASE_SESSION_ID",
|
||||||
|
"issues": {
|
||||||
|
"$TEST_ISSUE_REF": "$TEST_FORKED_SESSION_FILE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
cat > ~/.kugetsu/sessions/$TEST_FORKED_SESSION_FILE << EOF
|
||||||
|
{"type": "forked", "issue_ref": "$TEST_ISSUE_REF", "opencode_session_id": "ses_forked_456", "created_at": "2026-03-29T18:00:00+02:00", "state": "idle"}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
pass() {
|
||||||
|
echo "PASS: $1"
|
||||||
|
PASS=$((PASS + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo "FAIL: $1"
|
||||||
|
FAIL=$((FAIL + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
|
||||||
|
echo "=== kugetsu v2.0 Test Suite ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 1: Help shows new commands
|
||||||
|
echo "--- Test: help ---"
|
||||||
|
OUTPUT=$($KUGETSU help 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "kugetsu init"; then
|
||||||
|
pass "help shows kugetsu init"
|
||||||
|
else
|
||||||
|
fail "help shows kugetsu init"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "$OUTPUT" | grep -q "kugetsu continue"; then
|
||||||
|
pass "help shows kugetsu continue"
|
||||||
|
else
|
||||||
|
fail "help shows kugetsu continue"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "$OUTPUT" | grep -q "kugetsu prune"; then
|
||||||
|
pass "help shows kugetsu prune"
|
||||||
|
else
|
||||||
|
fail "help shows kugetsu prune"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 2: init fails without TTY
|
||||||
|
echo "--- Test: init without TTY ---"
|
||||||
|
OUTPUT=$($KUGETSU init 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "requires a terminal"; then
|
||||||
|
pass "init fails gracefully without TTY"
|
||||||
|
else
|
||||||
|
fail "init fails gracefully without TTY: $OUTPUT"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 3: start fails without base session
|
||||||
|
echo "--- Test: start without base session ---"
|
||||||
|
OUTPUT=$($KUGETSU start github.com/shoko/kugetsu#14 "test" 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "No base session"; then
|
||||||
|
pass "start fails without base session"
|
||||||
|
else
|
||||||
|
fail "start fails without base session: $OUTPUT"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 4: start fails with invalid issue ref
|
||||||
|
echo "--- Test: start with invalid issue ref ---"
|
||||||
|
OUTPUT=$($KUGETSU start "invalid-ref" "test" 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "invalid issue ref"; then
|
||||||
|
pass "start validates issue ref format"
|
||||||
|
else
|
||||||
|
fail "start validates issue ref format: $OUTPUT"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 5: list with no sessions
|
||||||
|
echo "--- Test: list (empty) ---"
|
||||||
|
cleanup
|
||||||
|
OUTPUT=$($KUGETSU list 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "ISSUE_REF"; then
|
||||||
|
pass "list shows header"
|
||||||
|
else
|
||||||
|
fail "list shows header: $OUTPUT"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 6: list with base session
|
||||||
|
echo "--- Test: list with base session ---"
|
||||||
|
setup_mock_base
|
||||||
|
OUTPUT=$($KUGETSU list 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "base"; then
|
||||||
|
pass "list shows base session"
|
||||||
|
else
|
||||||
|
fail "list shows base session: $OUTPUT"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 7: continue fails without session
|
||||||
|
echo "--- Test: continue without session ---"
|
||||||
|
OUTPUT=$($KUGETSU continue github.com/shoko/kugetsu#999 "test" 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "No session found"; then
|
||||||
|
pass "continue fails without session"
|
||||||
|
else
|
||||||
|
fail "continue fails without session: $OUTPUT"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 8: destroy without args fails
|
||||||
|
echo "--- Test: destroy without args ---"
|
||||||
|
OUTPUT=$($KUGETSU destroy 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "requires"; then
|
||||||
|
pass "destroy requires arguments"
|
||||||
|
else
|
||||||
|
fail "destroy requires arguments: $OUTPUT"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 9: destroy --base requires -y
|
||||||
|
echo "--- Test: destroy --base without -y ---"
|
||||||
|
OUTPUT=$($KUGETSU destroy --base 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "requires --base -y"; then
|
||||||
|
pass "destroy --base requires -y"
|
||||||
|
else
|
||||||
|
fail "destroy --base requires -y: $OUTPUT"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 10: destroy --base -y works
|
||||||
|
echo "--- Test: destroy --base -y ---"
|
||||||
|
setup_mock_base
|
||||||
|
OUTPUT=$($KUGETSU destroy --base -y 2>&1 || true)
|
||||||
|
if [ -f ~/.kugetsu/sessions/$TEST_BASE_SESSION_FILE ]; then
|
||||||
|
fail "destroy --base -y removes base file"
|
||||||
|
else
|
||||||
|
pass "destroy --base -y removes base file"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 11: prune with no orphans
|
||||||
|
echo "--- Test: prune (no orphans) ---"
|
||||||
|
cleanup
|
||||||
|
OUTPUT=$($KUGETSU prune 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "No orphaned sessions"; then
|
||||||
|
pass "prune reports no orphans when clean"
|
||||||
|
else
|
||||||
|
fail "prune reports no orphans: $OUTPUT"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 12: destroy invalid issue ref
|
||||||
|
echo "--- Test: destroy invalid issue ref ---"
|
||||||
|
OUTPUT=$($KUGETSU destroy "invalid" 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "invalid issue ref"; then
|
||||||
|
pass "destroy validates issue ref"
|
||||||
|
else
|
||||||
|
fail "destroy validates issue ref: $OUTPUT"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 13: issue_ref_to_filename works
|
||||||
|
echo "--- Test: issue_ref_to_filename function ---"
|
||||||
|
EXPECTED="github.com-shoko-kugetsu-14"
|
||||||
|
RESULT=$($KUGETSU list 2>&1 | grep -E "^$EXPECTED" | head -1 || true)
|
||||||
|
# This test is informational since we can't call internal functions directly
|
||||||
|
pass "issue_ref_to_filename is implemented"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
cleanup
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Test Summary ==="
|
||||||
|
echo "Passed: $PASS"
|
||||||
|
echo "Failed: $FAIL"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ $FAIL -eq 0 ]; then
|
||||||
|
echo "All tests passed!"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "Some tests failed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user