Files
ccs/tests/native/unix/install.sh
T
kaitranntt 66e93fcae1 refactor(tests): Phase 3 - Move native tests to new structure
- Copy Unix and Windows tests to native/ directories
- Update Unix tests to source shared helpers
- Remove Section 10 (npm tests) from native tests
- Update final results to use shared helper functions
2025-11-05 11:16:16 -05:00

447 lines
16 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# CCS --install Functionality Testing (Linux/macOS)
# Comprehensive tests for the --install command
set +e # Don't exit on errors, we're testing
PASS_COUNT=0
FAIL_COUNT=0
TOTAL_TESTS=0
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
GRAY='\033[0;37m'
NC='\033[0m' # No Color
# Get script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CCS_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
CCS_PATH="$CCS_ROOT/ccs"
# Backup/restore paths
CLAUDE_DIR="$HOME/.claude"
BACKUP_DIR="/tmp/ccs-test-backup-$(date +%s)"
TEST_HOME="/tmp/ccs-test-home"
TEST_CLAUDE_DIR="$TEST_HOME/.claude"
test_case() {
local name="$1"
local expected="$2"
shift 2
((TOTAL_TESTS++))
echo ""
echo -e "${CYAN}[$TOTAL_TESTS] $name${NC}"
echo -e "${GRAY} Expected: $expected${NC}"
if "$@"; then
echo -e "${GREEN} Result: PASS${NC}"
((PASS_COUNT++))
return 0
else
echo -e "${RED} Result: FAIL${NC}"
((FAIL_COUNT++))
return 1
fi
}
cleanup_and_restore() {
echo ""
echo -e "${YELLOW}Cleaning up and restoring...${NC}"
# Remove test directory
rm -rf "$TEST_HOME"
# Restore backup if it exists
if [[ -d "$BACKUP_DIR" ]]; then
if [[ -d "$CLAUDE_DIR" ]]; then
echo " Removing test data from $CLAUDE_DIR"
rm -rf "$CLAUDE_DIR"
fi
echo " Restoring backup from $BACKUP_DIR"
mv "$BACKUP_DIR" "$CLAUDE_DIR"
echo -e "${GREEN} Backup restored successfully${NC}"
fi
}
# Trap to ensure cleanup happens even if script fails
trap cleanup_and_restore EXIT
echo -e "${YELLOW}========================================${NC}"
echo -e "${YELLOW}CCS --INSTALL FUNCTIONALITY TESTING${NC}"
echo -e "${YELLOW}========================================${NC}"
echo ""
# ============================================================================
# SAFETY: BACKUP EXISTING ~/.claude/
# ============================================================================
echo -e "${CYAN}Safety: Backing up existing ~/.claude/...${NC}"
if [[ -d "$CLAUDE_DIR" ]]; then
echo " Found existing ~/.claude/, creating backup at $BACKUP_DIR"
cp -r "$CLAUDE_DIR" "$BACKUP_DIR"
echo -e "${GREEN} Backup created successfully${NC}"
else
echo " No existing ~/.claude/ found, no backup needed"
fi
echo ""
# ============================================================================
# PRE-CHECKS
# ============================================================================
echo -e "${YELLOW}===== PRE-CHECKS =====${NC}"
test_case "CCS executable exists" "ccs script found at $CCS_PATH" bash -c "
[[ -f '$CCS_PATH' ]]
"
test_case "CCS executable is executable" "ccs has execute permissions" bash -c "
[[ -x '$CCS_PATH' ]]
"
test_case "Source .claude directory exists" ".claude/ in CCS repo" bash -c "
[[ -d '$CCS_ROOT/.claude' ]]
"
test_case "Source commands exist" "ccs.md command file exists" bash -c "
[[ -f '$CCS_ROOT/.claude/commands/ccs.md' ]]
"
test_case "Source skills exist" "ccs-delegation skill directory exists" bash -c "
[[ -d '$CCS_ROOT/.claude/skills/ccs-delegation' ]]
"
# ============================================================================
# SECTION 1: FRESH INSTALLATION (NO ~/.claude/)
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 1: FRESH INSTALLATION =====${NC}"
# Clean any existing test directory
rm -rf "$TEST_HOME"
mkdir -p "$TEST_HOME"
test_case "Fresh install: Command executes without error" "Exit code 0" bash -c "
HOME='$TEST_HOME' '$CCS_PATH' --install > /tmp/ccs-install-output.txt 2>&1
"
test_case "Fresh install: Commands directory created" "~/.claude/commands/ exists" bash -c "
[[ -d '$TEST_CLAUDE_DIR/commands' ]]
"
test_case "Fresh install: Skills directory created" "~/.claude/skills/ exists" bash -c "
[[ -d '$TEST_CLAUDE_DIR/skills' ]]
"
test_case "Fresh install: ccs.md command installed" "ccs.md file exists in commands/" bash -c "
[[ -f '$TEST_CLAUDE_DIR/commands/ccs.md' ]]
"
test_case "Fresh install: ccs-delegation skill installed" "ccs-delegation/ exists in skills/" bash -c "
[[ -d '$TEST_CLAUDE_DIR/skills/ccs-delegation' ]]
"
test_case "Fresh install: SKILL.md exists" "SKILL.md in ccs-delegation/" bash -c "
[[ -f '$TEST_CLAUDE_DIR/skills/ccs-delegation/SKILL.md' ]]
"
test_case "Fresh install: references directory exists" "references/ subdirectory present" bash -c "
[[ -d '$TEST_CLAUDE_DIR/skills/ccs-delegation/references' ]]
"
test_case "Fresh install: delegation-patterns.md exists" "Pattern reference file present" bash -c "
[[ -f '$TEST_CLAUDE_DIR/skills/ccs-delegation/references/delegation-patterns.md' ]]
"
# ============================================================================
# SECTION 2: OUTPUT FORMATTING (BOX-DRAWING CHARACTERS)
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 2: OUTPUT FORMATTING =====${NC}"
# Clean for fresh test
rm -rf "$TEST_HOME"
mkdir -p "$TEST_HOME"
test_case "Output: Contains box-drawing header" "Output has ┌─" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ ┌─ ]]
"
test_case "Output: Contains box-drawing footer" "Output has └─" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ └─ ]]
"
test_case "Output: Contains pipe for indentation" "Output has │" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ │ ]]
"
test_case "Output: Contains checkmark indicator" "Output has ✓" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ ✓ ]]
"
test_case "Output: Shows source directory" "Output includes source path" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ Source: ]]
"
test_case "Output: Shows target directory" "Output includes target path" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ Target: ]]
"
test_case "Output: Shows installation complete message" "Success message present" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ 'Installation complete' ]]
"
test_case "Output: Shows installed count" "Displays number of installed items" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ 'Installed:' ]]
"
test_case "Output: NO emoji characters used" "Output uses only box-drawing and symbols" bash -c "
# Check for actual emoji characters (not box-drawing or symbols like ✓ ✗)
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
! [[ \$output =~ [🚀📋🎯🎉] ]]
"
# ============================================================================
# SECTION 3: IDEMPOTENCY (MULTIPLE RUNS)
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 3: IDEMPOTENCY =====${NC}"
# Start fresh
rm -rf "$TEST_HOME"
mkdir -p "$TEST_HOME"
HOME="$TEST_HOME" "$CCS_PATH" --install > /dev/null 2>&1
test_case "Idempotent: Second run succeeds" "Second --install doesn't error" bash -c "
HOME='$TEST_HOME' '$CCS_PATH' --install > /tmp/ccs-install-second.txt 2>&1
"
test_case "Idempotent: Shows skip messages" "Output contains 'Skipping existing'" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ 'Skipping existing' ]]
"
test_case "Idempotent: Uses info indicator " "Skip messages have indicator" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ ]]
"
test_case "Idempotent: Skipped count shown" "Displays number of skipped items" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ 'Skipped:' ]]
"
test_case "Idempotent: Files remain unchanged" "Original files not modified" bash -c "
# Get modification time before second install
mtime1=\$(stat -c %Y '$TEST_CLAUDE_DIR/commands/ccs.md' 2>/dev/null || stat -f %m '$TEST_CLAUDE_DIR/commands/ccs.md')
sleep 1
HOME='$TEST_HOME' '$CCS_PATH' --install > /dev/null 2>&1
mtime2=\$(stat -c %Y '$TEST_CLAUDE_DIR/commands/ccs.md' 2>/dev/null || stat -f %m '$TEST_CLAUDE_DIR/commands/ccs.md')
[[ \$mtime1 == \$mtime2 ]]
"
test_case "Idempotent: Third run still safe" "Multiple runs are safe" bash -c "
HOME='$TEST_HOME' '$CCS_PATH' --install > /dev/null 2>&1
HOME='$TEST_HOME' '$CCS_PATH' --install > /dev/null 2>&1
[[ -f '$TEST_CLAUDE_DIR/commands/ccs.md' ]] && [[ -d '$TEST_CLAUDE_DIR/skills/ccs-delegation' ]]
"
# ============================================================================
# SECTION 4: CONFLICT HANDLING (EXISTING FILES)
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 4: CONFLICT HANDLING =====${NC}"
# Create existing files with different content
rm -rf "$TEST_CLAUDE_DIR"
mkdir -p "$TEST_CLAUDE_DIR/commands"
mkdir -p "$TEST_CLAUDE_DIR/skills/ccs-delegation"
echo "EXISTING COMMAND CONTENT" > "$TEST_CLAUDE_DIR/commands/ccs.md"
echo "EXISTING SKILL CONTENT" > "$TEST_CLAUDE_DIR/skills/ccs-delegation/SKILL.md"
test_case "Conflict: Skips existing command file" "Doesn't overwrite ccs.md" bash -c "
HOME='$TEST_HOME' '$CCS_PATH' --install > /dev/null 2>&1
content=\$(cat '$TEST_CLAUDE_DIR/commands/ccs.md')
[[ \$content == 'EXISTING COMMAND CONTENT' ]]
"
test_case "Conflict: Skips existing skill directory" "Doesn't overwrite skill" bash -c "
content=\$(cat '$TEST_CLAUDE_DIR/skills/ccs-delegation/SKILL.md')
[[ \$content == 'EXISTING SKILL CONTENT' ]]
"
test_case "Conflict: Output shows skip message" "User informed about skips" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ 'Skipping existing command: ccs.md' ]]
"
test_case "Conflict: No data loss" "Original files preserved" bash -c "
[[ -f '$TEST_CLAUDE_DIR/commands/ccs.md' ]] &&
grep -q 'EXISTING COMMAND CONTENT' '$TEST_CLAUDE_DIR/commands/ccs.md'
"
# ============================================================================
# SECTION 5: FILE INTEGRITY
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 5: FILE INTEGRITY =====${NC}"
# Fresh install for integrity checks
rm -rf "$TEST_HOME"
mkdir -p "$TEST_HOME"
HOME="$TEST_HOME" "$CCS_PATH" --install > /dev/null 2>&1
test_case "Integrity: Command file not empty" "ccs.md has content" bash -c "
[[ -s '$TEST_CLAUDE_DIR/commands/ccs.md' ]]
"
test_case "Integrity: Skill file not empty" "SKILL.md has content" bash -c "
[[ -s '$TEST_CLAUDE_DIR/skills/ccs-delegation/SKILL.md' ]]
"
test_case "Integrity: Command file matches source" "ccs.md content identical" bash -c "
diff -q '$CCS_ROOT/.claude/commands/ccs.md' '$TEST_CLAUDE_DIR/commands/ccs.md'
"
test_case "Integrity: Skill file matches source" "SKILL.md content identical" bash -c "
diff -q '$CCS_ROOT/.claude/skills/ccs-delegation/SKILL.md' '$TEST_CLAUDE_DIR/skills/ccs-delegation/SKILL.md'
"
test_case "Integrity: Reference file matches source" "delegation-patterns.md identical" bash -c "
diff -q '$CCS_ROOT/.claude/skills/ccs-delegation/references/delegation-patterns.md' \
'$TEST_CLAUDE_DIR/skills/ccs-delegation/references/delegation-patterns.md'
"
test_case "Integrity: Directory structure preserved" "All subdirectories present" bash -c "
[[ -d '$TEST_CLAUDE_DIR/skills/ccs-delegation/references' ]]
"
# ============================================================================
# SECTION 6: ERROR HANDLING
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 6: ERROR HANDLING =====${NC}"
test_case "Error: Missing source directory handled" "Graceful error when source missing" bash -c "
# Temporarily move .claude directory
mv '$CCS_ROOT/.claude' '$CCS_ROOT/.claude.backup'
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1 || true)
mv '$CCS_ROOT/.claude.backup' '$CCS_ROOT/.claude'
[[ \$output =~ 'Error: Source directory not found' ]]
"
test_case "Error: Shows helpful error message" "Error message explains the issue" bash -c "
mv '$CCS_ROOT/.claude' '$CCS_ROOT/.claude.backup'
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1 || true)
mv '$CCS_ROOT/.claude.backup' '$CCS_ROOT/.claude'
[[ \$output =~ 'CCS repository directory' ]]
"
test_case "Error: Uses error indicator ✗" "Error messages have ✗ indicator" bash -c "
mv '$CCS_ROOT/.claude' '$CCS_ROOT/.claude.backup'
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1 || true)
mv '$CCS_ROOT/.claude.backup' '$CCS_ROOT/.claude'
[[ \$output =~ ✗ ]]
"
# ============================================================================
# SECTION 7: PERMISSIONS AND OWNERSHIP
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 7: PERMISSIONS AND OWNERSHIP =====${NC}"
rm -rf "$TEST_CLAUDE_DIR"
HOME=$(dirname "$TEST_CLAUDE_DIR") "$CCS_PATH" --install > /dev/null 2>&1
test_case "Permissions: Command file is readable" "ccs.md has read permissions" bash -c "
[[ -r '$TEST_CLAUDE_DIR/commands/ccs.md' ]]
"
test_case "Permissions: Skill file is readable" "SKILL.md has read permissions" bash -c "
[[ -r '$TEST_CLAUDE_DIR/skills/ccs-delegation/SKILL.md' ]]
"
test_case "Permissions: Directories are accessible" "Can list directory contents" bash -c "
ls '$TEST_CLAUDE_DIR/commands' > /dev/null 2>&1 &&
ls '$TEST_CLAUDE_DIR/skills' > /dev/null 2>&1
"
# ============================================================================
# SECTION 8: INTEGRATION WITH CCS
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 8: INTEGRATION WITH CCS =====${NC}"
test_case "Integration: --install flag recognized" "--install doesn't show 'Profile not found'" bash -c "
output=\$('$CCS_PATH' --install 2>&1 || true)
! [[ \$output =~ 'Profile.*--install.*not found' ]]
"
test_case "Integration: --version still works after --install" "Version command functional" bash -c "
output=\$('$CCS_PATH' --version 2>&1)
[[ \$output =~ 'CCS' ]]
"
test_case "Integration: --help still works after --install" "Help command functional" bash -c "
output=\$('$CCS_PATH' --help 2>&1)
[[ \$output =~ 'Usage' ]] || [[ \$output =~ 'Claude' ]]
"
# ============================================================================
# FINAL RESULTS
# ============================================================================
echo ""
echo -e "${YELLOW}========================================${NC}"
echo -e "${YELLOW}TEST RESULTS SUMMARY${NC}"
echo -e "${YELLOW}========================================${NC}"
echo ""
echo -e "${CYAN}Total Tests: $TOTAL_TESTS${NC}"
echo -e "${GREEN}Passed: $PASS_COUNT${NC}"
if [[ $FAIL_COUNT -eq 0 ]]; then
echo -e "${GREEN}Failed: $FAIL_COUNT${NC}"
else
echo -e "${RED}Failed: $FAIL_COUNT${NC}"
fi
echo ""
SUCCESS_RATE=$(awk "BEGIN {printf \"%.2f\", ($PASS_COUNT / $TOTAL_TESTS) * 100}")
if awk "BEGIN {exit !($SUCCESS_RATE >= 90)}"; then
echo -e "${GREEN}Success Rate: $SUCCESS_RATE%${NC}"
elif awk "BEGIN {exit !($SUCCESS_RATE >= 70)}"; then
echo -e "${YELLOW}Success Rate: $SUCCESS_RATE%${NC}"
else
echo -e "${RED}Success Rate: $SUCCESS_RATE%${NC}"
fi
echo ""
if [[ $FAIL_COUNT -eq 0 ]]; then
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}ALL TESTS PASSED!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo -e "${GREEN}--install functionality is production ready!${NC}"
exit 0
else
echo -e "${YELLOW}========================================${NC}"
echo -e "${YELLOW}SOME TESTS FAILED${NC}"
echo -e "${YELLOW}========================================${NC}"
echo ""
echo -e "${YELLOW}Review failed tests above for details${NC}"
exit 1
fi