lala 0.1.0

A modern, lightweight text editor with GUI and CLI support for Markdown, HTML, Mermaid, and LaTeX
Documentation
/// Tests for LLM integration module
///
/// Tests cover:
/// - Client creation
/// - API key validation
/// - Error handling
/// - Feature flag handling
use lala::llm::GeminiClient;

// === Client Creation Tests ===

#[test]
fn test_gemini_client_without_api_key() {
    // Remove API key if set
    std::env::remove_var("GEMINI_API_KEY");

    let result = GeminiClient::from_env();
    assert!(result.is_err());
    assert!(result
        .unwrap_err()
        .contains("GEMINI_API_KEY environment variable not set"));
}

#[test]
fn test_gemini_client_with_empty_api_key() {
    // Test using new() directly to avoid env var interference
    let result = GeminiClient::new("".to_string());
    // Empty API key should fail due to validation
    assert!(result.is_err());
    assert!(result.unwrap_err().contains("API key cannot be empty"));
}

#[test]
fn test_gemini_client_with_valid_api_key() {
    // Test using new() directly to avoid env var interference
    let result = GeminiClient::new("test_api_key_12345".to_string());
    assert!(result.is_ok());
}

// === Feature Flag Tests ===

#[cfg(not(feature = "llm"))]
#[test]
fn test_llm_feature_disabled() {
    std::env::set_var("GEMINI_API_KEY", "test_key");

    let client = GeminiClient::from_env().unwrap();
    let result = client.improve_markdown("# Test");

    assert!(result.is_err());
    assert!(result.unwrap_err().contains("LLM feature is not enabled"));
}

#[cfg(not(feature = "llm"))]
#[test]
fn test_fix_command_feature_disabled() {
    std::env::set_var("GEMINI_API_KEY", "test_key");

    let client = GeminiClient::from_env().unwrap();
    let result = client.fix_command("ls -la", None);

    assert!(result.is_err());
    assert!(result.unwrap_err().contains("LLM feature is not enabled"));
}

// === API Method Tests (without actual API calls) ===

#[test]
fn test_improve_markdown_input_validation() {
    std::env::set_var("GEMINI_API_KEY", "test_key");

    if let Ok(client) = GeminiClient::from_env() {
        // Test with empty input
        let result = client.improve_markdown("");
        // Should either succeed (empty request) or fail gracefully
        assert!(result.is_ok() || result.is_err());
    }
}

#[test]
fn test_fix_command_with_error() {
    std::env::set_var("GEMINI_API_KEY", "test_key");

    if let Ok(client) = GeminiClient::from_env() {
        let result = client.fix_command("invalid_command", Some("command not found"));
        // Should either succeed or fail gracefully
        assert!(result.is_ok() || result.is_err());
    }
}

#[test]
fn test_fix_command_without_error() {
    std::env::set_var("GEMINI_API_KEY", "test_key");

    if let Ok(client) = GeminiClient::from_env() {
        let result = client.fix_command("ls -la", None);
        // Should either succeed or fail gracefully
        assert!(result.is_ok() || result.is_err());
    }
}

// === Edge Cases ===

#[test]
fn test_multiple_client_instances() {
    std::env::set_var("GEMINI_API_KEY", "test_key");

    let client1 = GeminiClient::from_env();
    let client2 = GeminiClient::from_env();

    assert!(client1.is_ok());
    assert!(client2.is_ok());
}

#[test]
fn test_client_after_api_key_change() {
    // Test using new() directly to avoid env var interference
    let client1 = GeminiClient::new("key1".to_string());
    assert!(client1.is_ok());

    let client2 = GeminiClient::new("key2".to_string());
    assert!(client2.is_ok());
}

// === Japanese Text Tests ===

#[test]
fn test_improve_markdown_with_japanese() {
    std::env::set_var("GEMINI_API_KEY", "test_key");

    if let Ok(client) = GeminiClient::from_env() {
        let japanese_text = "# テスト\n\nこれは日本語のMarkdownです。";
        let result = client.improve_markdown(japanese_text);
        // Should handle Japanese text gracefully
        assert!(result.is_ok() || result.is_err());
    }
}

#[test]
fn test_fix_command_with_japanese() {
    std::env::set_var("GEMINI_API_KEY", "test_key");

    if let Ok(client) = GeminiClient::from_env() {
        let result = client.fix_command("ls -la", Some("コマンドが見つかりません"));
        // Should handle Japanese error messages
        assert!(result.is_ok() || result.is_err());
    }
}

// === Long Input Tests ===

#[test]
fn test_improve_markdown_long_text() {
    std::env::set_var("GEMINI_API_KEY", "test_key");

    if let Ok(client) = GeminiClient::from_env() {
        let long_text = "# Heading\n\n".to_string() + &"This is a test paragraph. ".repeat(1000);
        let result = client.improve_markdown(&long_text);
        // Should handle long text
        assert!(result.is_ok() || result.is_err());
    }
}

#[test]
fn test_special_characters_in_markdown() {
    std::env::set_var("GEMINI_API_KEY", "test_key");

    if let Ok(client) = GeminiClient::from_env() {
        let text_with_special_chars =
            "# Test\n\n**Bold** *italic* `code` [link](url)\n\n> Quote\n\n- List item";
        let result = client.improve_markdown(text_with_special_chars);
        assert!(result.is_ok() || result.is_err());
    }
}

// === Cleanup ===
// Note: No cleanup test needed - tests run in parallel and shouldn't
// rely on global state being cleaned up