use ralph::memory::MemoryStore;
use tempfile::TempDir;
fn store(dir: &TempDir) -> MemoryStore {
MemoryStore::from_path(dir.path().join("memory.json"))
}
#[test]
fn upsert_stores_and_retrieves_fact() {
let dir = TempDir::new().unwrap();
let mut m = store(&dir);
m.upsert("lang", "Rust");
let facts = m.all_facts();
assert_eq!(facts.len(), 1);
assert_eq!(facts[0].key, "lang");
assert_eq!(facts[0].value, "Rust");
}
#[test]
fn upsert_updates_existing_key() {
let dir = TempDir::new().unwrap();
let mut m = store(&dir);
m.upsert("lang", "Python");
m.upsert("lang", "Rust");
let facts = m.all_facts();
assert_eq!(facts.len(), 1);
assert_eq!(facts[0].value, "Rust");
}
#[test]
fn upsert_is_case_insensitive_on_key() {
let dir = TempDir::new().unwrap();
let mut m = store(&dir);
m.upsert("Lang", "Python");
m.upsert("lang", "Rust");
assert_eq!(m.all_facts().len(), 1);
}
#[test]
fn search_finds_by_key_substring() {
let dir = TempDir::new().unwrap();
let mut m = store(&dir);
m.upsert("database_host", "localhost");
m.upsert("api_key_env", "MY_KEY");
let results = m.search("database");
assert_eq!(results.len(), 1);
assert_eq!(results[0].key, "database_host");
}
#[test]
fn search_finds_by_value_substring() {
let dir = TempDir::new().unwrap();
let mut m = store(&dir);
m.upsert("host", "production-server-01");
let results = m.search("production");
assert_eq!(results.len(), 1);
}
#[test]
fn search_empty_query_returns_nothing() {
let dir = TempDir::new().unwrap();
let mut m = store(&dir);
m.upsert("key", "value");
let results = m.search("zzznomatch");
assert!(results.is_empty());
}
#[test]
fn add_episode_persists() {
let dir = TempDir::new().unwrap();
let mut m = store(&dir);
m.add_episode(
"sess-1",
"Did the thing",
vec!["src/main.rs".to_string()],
"done",
);
assert_eq!(m.episodes_count(), 1);
}
#[test]
fn add_episode_caps_at_50() {
let dir = TempDir::new().unwrap();
let mut m = store(&dir);
for i in 0..55 {
m.add_episode(&format!("sess-{}", i), "summary", vec![], "done");
}
assert_eq!(m.episodes_count(), 50);
}
#[test]
fn format_for_prompt_is_none_when_empty() {
let dir = TempDir::new().unwrap();
let m = store(&dir);
assert!(m.format_for_prompt().is_none());
}
#[test]
fn format_for_prompt_includes_facts() {
let dir = TempDir::new().unwrap();
let mut m = store(&dir);
m.upsert("framework", "axum");
let prompt = m.format_for_prompt().unwrap();
assert!(prompt.contains("framework"));
assert!(prompt.contains("axum"));
}
#[test]
fn format_for_prompt_includes_episodes() {
let dir = TempDir::new().unwrap();
let mut m = store(&dir);
m.add_episode("s1", "Refactored the auth module", vec![], "done");
let prompt = m.format_for_prompt().unwrap();
assert!(prompt.contains("Refactored the auth module"));
}
#[test]
fn memory_persists_across_reload() {
let dir = TempDir::new().unwrap();
let path = dir.path().join("memory.json");
{
let mut m = MemoryStore::from_path(path.clone());
m.upsert("project_type", "web_api");
}
let m2 = MemoryStore::from_path(path);
let facts = m2.all_facts();
assert_eq!(facts.len(), 1);
assert_eq!(facts[0].value, "web_api");
}