ralph-claude-code/tests/helpers/test_helper.bash
Frank Bria c7e7a1c6a3
refactor(naming): remove @ prefix from on-disk filenames (#131)
* refactor(naming): remove @ prefix from on-disk filenames

BREAKING CHANGE: Renames @fix_plan.md → fix_plan.md and @AGENT.md → AGENT.md

This change improves POSIX compliance and compatibility with command-line tools.
The @ prefix was originally used to avoid naming conflicts, but with the .ralph/
folder structure introduced in v0.10.0, this convention is no longer necessary.

Changes:
- Update all scripts to use new naming (fix_plan.md, AGENT.md)
- Update migration script to handle both old and new naming conventions
- Update templates to use new naming
- Update all documentation references
- Update all 420 tests to expect new naming (TDD approach)

Migration:
- Existing projects with @-prefixed files will be automatically renamed
  when running ralph-migrate
- Projects already using the new naming will continue to work unchanged

* docs(claude): update file naming conventions section

* fix(migrate): prevent orphaned @-prefixed files during migration

When both root/@fix_plan.md and .ralph/@fix_plan.md exist, the root file
now takes priority and the .ralph/@fix_plan.md is removed (backup exists).
This prevents orphaned legacy files after migration.

---------

Co-authored-by: Test User <test@example.com>
2026-01-26 15:40:27 -07:00

227 lines
5.3 KiB
Bash

#!/usr/bin/env bash
# Test Helper Utilities for Ralph Test Suite
# Helper: Fail with message (for use in assertions)
fail() {
echo "$1"
return 1
}
# Simple assertion functions (replacing bats-assert)
assert_success() {
if [ "$status" -ne 0 ]; then
echo "Expected success but got status $status"
echo "Output: $output"
return 1
fi
}
assert_failure() {
if [ "$status" -eq 0 ]; then
echo "Expected failure but got success"
echo "Output: $output"
return 1
fi
}
assert_equal() {
if [ "$1" != "$2" ]; then
echo "Expected '$2' but got '$1'"
return 1
fi
}
assert_output() {
local expected="$1"
if [ "$output" != "$expected" ]; then
echo "Expected output: '$expected'"
echo "Actual output: '$output'"
return 1
fi
}
# Test temporary directory management
export BATS_TEST_TMPDIR="${BATS_TEST_TMPDIR:-/tmp/bats-ralph-$$}"
# Setup function - runs before each test
setup() {
# Create unique temp directory for this test
export TEST_TEMP_DIR="$(mktemp -d "${BATS_TEST_TMPDIR}/test.XXXXXX")"
cd "$TEST_TEMP_DIR"
# Set up test environment variables with .ralph/ subfolder structure
export RALPH_DIR=".ralph"
export PROMPT_FILE="$RALPH_DIR/PROMPT.md"
export LOG_DIR="$RALPH_DIR/logs"
export DOCS_DIR="$RALPH_DIR/docs/generated"
export STATUS_FILE="$RALPH_DIR/status.json"
export PROGRESS_FILE="$RALPH_DIR/progress.json"
export CALL_COUNT_FILE="$RALPH_DIR/.call_count"
export TIMESTAMP_FILE="$RALPH_DIR/.last_reset"
export EXIT_SIGNALS_FILE="$RALPH_DIR/.exit_signals"
export RESPONSE_ANALYSIS_FILE="$RALPH_DIR/.response_analysis"
# Create necessary directories
mkdir -p "$LOG_DIR" "$DOCS_DIR" "$RALPH_DIR"
# Initialize files
echo "0" > "$CALL_COUNT_FILE"
echo "$(date +%Y%m%d%H)" > "$TIMESTAMP_FILE"
echo '{"test_only_loops": [], "done_signals": [], "completion_indicators": []}' > "$EXIT_SIGNALS_FILE"
}
# Teardown function - runs after each test
teardown() {
# Clean up temp directory
if [[ -n "$TEST_TEMP_DIR" && -d "$TEST_TEMP_DIR" ]]; then
rm -rf "$TEST_TEMP_DIR"
fi
}
# Helper: Strip ANSI color codes from output
strip_colors() {
sed 's/\x1b\[[0-9;]*m//g'
}
# Helper: Create a mock PROMPT.md file
create_mock_prompt() {
mkdir -p "$RALPH_DIR"
cat > "$PROMPT_FILE" << 'EOF'
# Test Prompt
This is a test prompt for Ralph.
## Task
Test the system.
EOF
}
# Helper: Create a mock fix_plan.md file
create_mock_fix_plan() {
local total=${1:-5}
local completed=${2:-0}
local fix_plan_file="$RALPH_DIR/fix_plan.md"
mkdir -p "$RALPH_DIR"
cat > "$fix_plan_file" << EOF
# Fix Plan
## High Priority
EOF
for ((i=1; i<=completed; i++)); do
echo "- [x] Completed task $i" >> "$fix_plan_file"
done
for ((i=completed+1; i<=total; i++)); do
echo "- [ ] Pending task $i" >> "$fix_plan_file"
done
}
# Helper: Create a mock status.json file
create_mock_status() {
local loop_count=${1:-1}
local calls_made=${2:-0}
local max_calls=${3:-100}
cat > "$STATUS_FILE" << EOF
{
"timestamp": "$(date -Iseconds)",
"loop_count": $loop_count,
"calls_made_this_hour": $calls_made,
"max_calls_per_hour": $max_calls,
"last_action": "test",
"status": "running",
"exit_reason": ""
}
EOF
}
# Helper: Create a mock exit signals file
create_mock_exit_signals() {
local test_loops=${1:-0}
local done_signals=${2:-0}
local completion=${3:-0}
local test_array="[]"
local done_array="[]"
local comp_array="[]"
if [[ $test_loops -gt 0 ]]; then
test_array="[$(seq -s, 1 $test_loops)]"
fi
if [[ $done_signals -gt 0 ]]; then
done_array="[$(seq -s, 1 $done_signals)]"
fi
if [[ $completion -gt 0 ]]; then
comp_array="[$(seq -s, 1 $completion)]"
fi
cat > "$EXIT_SIGNALS_FILE" << EOF
{
"test_only_loops": $test_array,
"done_signals": $done_array,
"completion_indicators": $comp_array
}
EOF
}
# Helper: Validate JSON structure
assert_valid_json() {
local file=$1
run jq empty "$file"
assert_success
}
# Helper: Get JSON field value
get_json_field() {
local file=$1
local field=$2
jq -r ".$field" "$file"
}
# Helper: Assert file exists
assert_file_exists() {
local file=$1
[[ -f "$file" ]] || fail "File does not exist: $file"
}
# Helper: Assert file does not exist
assert_file_not_exists() {
local file=$1
[[ ! -f "$file" ]] || fail "File exists but should not: $file"
}
# Helper: Assert directory exists
assert_dir_exists() {
local dir=$1
[[ -d "$dir" ]] || fail "Directory does not exist: $dir"
}
# Helper: Mock date command for deterministic tests
mock_date() {
local timestamp=$1
function date() {
if [[ "$1" == "+%Y%m%d%H" ]]; then
echo "$timestamp"
elif [[ "$1" == "-Iseconds" ]]; then
echo "2025-09-30T12:00:00-04:00"
else
command date "$@"
fi
}
export -f date
}
# Helper: Restore original date command
restore_date() {
unset -f date
}
# Helper: Source ralph functions without executing main
source_ralph_functions() {
# Source the script but prevent main execution
# We'll extract functions into a separate file for testing
:
}