ralph-coder 0.2.1

An agentic code generation CLI powered by multiple LLM backends
Documentation
/// Tests for the search_available predicate and tool_defs gating.
use ralph::tools::search_tools::search_available;
use ralph::tools::tool_defs;

// ── search_available ──────────────────────────────────────────────────────────

#[test]
fn no_search_keys_means_no_search() {
    // Neither Brave nor SerpAPI key set — search unavailable for all providers.
    assert!(!search_available(
        "DEFINITELY_NOT_SET_XYZ123",
        "DEFINITELY_NOT_SET_XYZ456"
    ));
}

#[test]
fn brave_key_enables_search() {
    std::env::set_var("RALPH_TEST_BRAVE_KEY", "test-key-value");
    let result = search_available("RALPH_TEST_BRAVE_KEY", "DEFINITELY_NOT_SET_XYZ456");
    std::env::remove_var("RALPH_TEST_BRAVE_KEY");
    assert!(result);
}

#[test]
fn serp_key_enables_search() {
    std::env::set_var("RALPH_TEST_SERP_KEY", "serp-key-value");
    let result = search_available("DEFINITELY_NOT_SET_XYZ123", "RALPH_TEST_SERP_KEY");
    std::env::remove_var("RALPH_TEST_SERP_KEY");
    assert!(result);
}

#[test]
fn both_keys_enables_search() {
    std::env::set_var("RALPH_TEST_BRAVE_KEY_B", "brave-val");
    std::env::set_var("RALPH_TEST_SERP_KEY_B", "serp-val");
    let result = search_available("RALPH_TEST_BRAVE_KEY_B", "RALPH_TEST_SERP_KEY_B");
    std::env::remove_var("RALPH_TEST_BRAVE_KEY_B");
    std::env::remove_var("RALPH_TEST_SERP_KEY_B");
    assert!(result);
}

#[test]
fn empty_keys_count_as_absent() {
    std::env::set_var("RALPH_TEST_BRAVE_EMPTY", "");
    std::env::set_var("RALPH_TEST_SERP_EMPTY", "   ");
    let result = search_available("RALPH_TEST_BRAVE_EMPTY", "RALPH_TEST_SERP_EMPTY");
    std::env::remove_var("RALPH_TEST_BRAVE_EMPTY");
    std::env::remove_var("RALPH_TEST_SERP_EMPTY");
    assert!(!result, "whitespace-only keys should be treated as absent");
}

// ── tool_defs gating ──────────────────────────────────────────────────────────

#[test]
fn search_web_absent_when_search_disabled() {
    let defs = tool_defs(false, false);
    assert!(
        !defs.iter().any(|t| t.name == "search_web"),
        "search_web should not be in tool_defs when search_enabled=false"
    );
}

#[test]
fn search_web_present_when_search_enabled() {
    let defs = tool_defs(true, false);
    assert!(
        defs.iter().any(|t| t.name == "search_web"),
        "search_web should be in tool_defs when search_enabled=true"
    );
}

#[test]
fn core_tools_always_present() {
    for enabled in [true, false] {
        let defs = tool_defs(enabled, false);
        let names: Vec<&str> = defs.iter().map(|t| t.name.as_str()).collect();
        for required in &[
            "read_file",
            "write_file",
            "edit_file",
            "delete_file",
            "list_dir",
            "load_files",
            "explain_code",
            "run_command",
            "run_test",
            "run_build",
            "search_codebase",
            "ask_user",
            "declare_done",
            "declare_failed",
        ] {
            assert!(
                names.contains(required),
                "tool '{}' missing from tool_defs(search_enabled={})",
                required,
                enabled
            );
        }
    }
}

// ── PR/CI tool gating ─────────────────────────────────────────────────────────

#[test]
fn pr_tools_absent_when_pr_disabled() {
    let defs = tool_defs(false, false);
    assert!(
        !defs.iter().any(|t| t.name == "create_pr"),
        "create_pr should be absent when pr_enabled=false"
    );
    assert!(
        !defs.iter().any(|t| t.name == "get_ci_status"),
        "get_ci_status should be absent when pr_enabled=false"
    );
}

#[test]
fn pr_tools_present_when_pr_enabled() {
    let defs = tool_defs(false, true);
    assert!(
        defs.iter().any(|t| t.name == "create_pr"),
        "create_pr should be present when pr_enabled=true"
    );
    assert!(
        defs.iter().any(|t| t.name == "get_ci_status"),
        "get_ci_status should be present when pr_enabled=true"
    );
}

// ── system prompt gating ──────────────────────────────────────────────────────

#[test]
fn system_prompt_includes_search_web_when_enabled() {
    let prompt = ralph::prompts::system_prompt("/workspace", true, None, None, None);
    assert!(prompt.contains("search_web"));
    assert!(prompt.contains("Always Search Before Assuming"));
}

#[test]
fn system_prompt_excludes_search_web_when_disabled() {
    let prompt = ralph::prompts::system_prompt("/workspace", false, None, None, None);
    assert!(!prompt.contains("search_web"));
    assert!(prompt.contains("Working Without Web Search"));
}