use std::collections::HashSet;
use super::SessionManager;
use crate::domain::session::{Session, SessionId};
impl SessionManager {
pub(in crate::app::session) fn startup_history_replay_set(
sessions: &[Session],
) -> HashSet<SessionId> {
sessions
.iter()
.filter(|session| session.status.allows_review_actions())
.map(|session| session.id.clone())
.collect()
}
pub(super) fn mark_history_replay_pending(&mut self, session_id: &str) {
self.pending_history_replay
.insert(SessionId::from(session_id));
}
pub(super) fn clear_history_replay_pending(&mut self, session_id: &str) {
self.pending_history_replay.remove(session_id);
}
pub(super) fn should_replay_history(&self, session_id: &str) -> bool {
self.pending_history_replay.contains(session_id)
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::{Instant, SystemTime};
use ratatui::widgets::TableState;
use super::*;
use crate::app::SessionState;
use crate::app::session::{Clock, SessionDefaults};
use crate::domain::agent::{AgentKind, AgentModel};
use crate::domain::session::{SessionSize, SessionStats, Status};
use crate::infra::git;
struct FixedClock;
impl Clock for FixedClock {
fn now_instant(&self) -> Instant {
Instant::now()
}
fn now_system_time(&self) -> SystemTime {
SystemTime::UNIX_EPOCH
}
}
fn test_session(session_id: &str, status: Status) -> Session {
Session {
base_branch: "main".to_string(),
created_at: 0,
draft_attachments: Vec::new(),
folder: PathBuf::from("/tmp/test"),
follow_up_tasks: Vec::new(),
id: session_id.into(),
in_progress_started_at: None,
in_progress_total_seconds: 0,
is_draft: false,
model: AgentModel::AntigravityGemini3FlashPreview,
output: String::new(),
parent_session_id: None,
project_name: "project".to_string(),
prompt: String::new(),
queued_messages: Vec::new(),
reasoning_level_override: None,
published_upstream_ref: None,
published_branch_sync_status: crate::domain::session::PublishedBranchSyncStatus::Idle,
questions: Vec::new(),
review_request: None,
size: SessionSize::Xs,
stats: SessionStats::default(),
status,
summary: None,
title: None,
updated_at: 0,
workflow_notice: None,
}
}
fn session_manager_with(sessions: Vec<Session>) -> SessionManager {
SessionManager::new(
SessionDefaults {
model: AgentKind::Antigravity.default_model(),
},
Arc::new(git::MockGitClient::new()),
SessionState::new(
HashMap::new(),
sessions,
TableState::default(),
Arc::new(FixedClock),
0,
0,
),
Vec::new(),
)
}
#[test]
fn test_startup_replay_set_collects_review_sessions() {
let sessions = vec![
test_session("review-1", Status::Review),
test_session("in-progress", Status::InProgress),
test_session("review-2", Status::Review),
];
let replay_set = SessionManager::startup_history_replay_set(&sessions);
assert_eq!(replay_set.len(), 2);
assert!(replay_set.contains("review-1"));
assert!(replay_set.contains("review-2"));
}
#[test]
fn test_startup_replay_set_collects_agent_review_sessions() {
let sessions = vec![test_session("review-1", Status::AgentReview)];
let replay_set = SessionManager::startup_history_replay_set(&sessions);
assert_eq!(replay_set.len(), 1);
assert!(replay_set.contains("review-1"));
}
#[test]
fn test_startup_replay_set_returns_empty_when_no_review_sessions() {
let sessions = vec![
test_session("new-1", Status::Draft),
test_session("done-1", Status::Done),
];
let replay_set = SessionManager::startup_history_replay_set(&sessions);
assert!(replay_set.is_empty());
}
#[test]
fn test_startup_replay_set_returns_empty_for_empty_list() {
let replay_set = SessionManager::startup_history_replay_set(&[]);
assert!(replay_set.is_empty());
}
#[test]
fn test_mark_and_check_replay_pending() {
let mut manager = session_manager_with(Vec::new());
manager.mark_history_replay_pending("sess-1");
assert!(manager.should_replay_history("sess-1"));
}
#[test]
fn test_should_replay_returns_false_when_not_marked() {
let manager = session_manager_with(Vec::new());
assert!(!manager.should_replay_history("unknown"));
}
#[test]
fn test_clear_removes_pending_replay() {
let mut manager = session_manager_with(Vec::new());
manager.mark_history_replay_pending("sess-1");
manager.clear_history_replay_pending("sess-1");
assert!(!manager.should_replay_history("sess-1"));
}
#[test]
fn test_clear_is_idempotent_for_unmarked_session() {
let mut manager = session_manager_with(Vec::new());
manager.clear_history_replay_pending("nonexistent");
}
#[test]
fn test_constructor_marks_review_sessions_for_replay() {
let sessions = vec![
test_session("review-sess", Status::Review),
test_session("new-sess", Status::Draft),
];
let manager = session_manager_with(sessions);
assert!(manager.should_replay_history("review-sess"));
assert!(!manager.should_replay_history("new-sess"));
}
}