focus/crates/focus-tui/tests/app_session_tests.rs

87 lines
2.7 KiB
Rust
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.

//! App 级会话持久化的测试(临时数据目录,零网络)。
//! App-level session persistence tests (temp data dir, zero network).
use focus_core::model::Message;
use focus_harness::session::SessionStore;
use focus_tui::app::App;
use std::path::PathBuf;
use std::sync::atomic::{AtomicUsize, Ordering};
static DIR_SEQ: AtomicUsize = AtomicUsize::new(0);
fn temp_data_dir(tag: &str) -> PathBuf {
let seq = DIR_SEQ.fetch_add(1, Ordering::SeqCst);
let d = std::env::temp_dir().join(format!(
"focus-tui-app-{}-{}-{}",
tag,
std::process::id(),
seq
));
let _ = std::fs::remove_dir_all(&d);
std::fs::create_dir_all(&d).unwrap();
d
}
/// 构造一个使用临时数据目录的 App避免环境变量在并行测试间竞争
/// Build an App on a temp data dir (avoids env-var races in parallel tests).
fn app_on(dir: &PathBuf) -> App {
let mut app = App::new();
app.store = SessionStore::new(dir);
app
}
#[test]
fn persist_and_reload_session() {
let dir = temp_data_dir("persist");
let mut app = app_on(&dir);
assert_eq!(app.session_id, None);
app.ensure_session();
let sid = app.session_id.clone().unwrap();
app.persist_entries(&[Message::user_text("first")]);
app.persist_entries(&[Message::user_text("second")]);
assert_eq!(app.persisted, 2);
assert_eq!(app.last_entry_id.as_deref(), Some("e2"));
// 另一个 App 实例加载同一会话。
// Another App instance loads the same session.
let mut app2 = app_on(&dir);
app2.load_session(&sid);
assert_eq!(app2.transcript.len(), 2);
assert_eq!(app2.persisted, 2);
let text = match &app2.transcript[1] {
Message::User(u) => u.content[0].as_text().map(|t| t.text.clone()),
_ => None,
};
assert_eq!(text.as_deref(), Some("second"));
// 续写追加消息parentId 链延续到 e3
// Continue: appending continues the parentId chain at e3.
app2.persist_entries(&[Message::user_text("third")]);
assert_eq!(app2.last_entry_id.as_deref(), Some("e3"));
let sessions = app2.store.list_sessions().unwrap();
assert_eq!(sessions, vec![sid.clone()]);
}
#[test]
fn new_session_resets_state() {
let dir = temp_data_dir("new");
let mut app = app_on(&dir);
app.ensure_session();
let sid1 = app.session_id.clone().unwrap();
app.persist_entries(&[Message::user_text("hi")]);
assert_eq!(app.persisted, 1);
app.new_session();
assert_eq!(app.session_id, None);
assert_eq!(app.transcript.len(), 0);
assert_eq!(app.persisted, 0);
assert_eq!(app.last_entry_id, None);
app.ensure_session();
let sid2 = app.session_id.clone().unwrap();
assert_ne!(sid1, sid2);
}