Files
galaxy/app/src/ai/active_agent_views_model_tests.rs
T

214 lines
7.0 KiB
Rust

use std::str::FromStr;
use galaxyui::{App, EntityId, WindowId};
use super::*;
fn setup_model(app: &mut App) -> ModelHandle<ActiveAgentViewsModel> {
app.add_singleton_model(|_| ActiveAgentViewsModel::new())
}
fn new_task_id() -> AmbientAgentTaskId {
AmbientAgentTaskId::from_str(&uuid::Uuid::new_v4().to_string()).unwrap()
}
#[test]
fn per_window_focused_state_is_independent() {
App::test((), |mut app| async move {
let model = setup_model(&mut app);
let window_a = WindowId::new();
let window_b = WindowId::new();
let terminal_a = EntityId::new();
let terminal_b = EntityId::new();
let task_a = new_task_id();
let task_b = new_task_id();
model.update(&mut app, |model, ctx| {
model.handle_pane_focus_change(window_a, Some(terminal_a), Some(task_a), ctx);
model.handle_pane_focus_change(window_b, Some(terminal_b), Some(task_b), ctx);
});
model.read(&app, |model, _| {
assert_eq!(
model.get_focused_conversation(window_a),
Some(ConversationOrTaskId::TaskId(task_a))
);
assert_eq!(
model.get_focused_conversation(window_b),
Some(ConversationOrTaskId::TaskId(task_b))
);
});
});
}
#[test]
fn clearing_one_window_does_not_affect_other() {
App::test((), |mut app| async move {
let model = setup_model(&mut app);
let window_a = WindowId::new();
let window_b = WindowId::new();
let terminal_a = EntityId::new();
let terminal_b = EntityId::new();
let task_a = new_task_id();
let task_b = new_task_id();
model.update(&mut app, |model, ctx| {
model.handle_pane_focus_change(window_a, Some(terminal_a), Some(task_a), ctx);
model.handle_pane_focus_change(window_b, Some(terminal_b), Some(task_b), ctx);
});
// Clear window A's focus by passing None for terminal_view_id.
model.update(&mut app, |model, ctx| {
model.handle_pane_focus_change(window_a, None, None, ctx);
});
model.read(&app, |model, _| {
assert_eq!(model.get_focused_conversation(window_a), None);
assert_eq!(
model.get_focused_conversation(window_b),
Some(ConversationOrTaskId::TaskId(task_b))
);
});
});
}
#[test]
fn last_focused_terminal_tracks_most_recent_globally() {
App::test((), |mut app| async move {
let model = setup_model(&mut app);
let window_a = WindowId::new();
let window_b = WindowId::new();
let terminal_a = EntityId::new();
let terminal_b = EntityId::new();
let task_a = new_task_id();
let task_b = new_task_id();
model.update(&mut app, |model, ctx| {
model.handle_pane_focus_change(window_a, Some(terminal_a), Some(task_a), ctx);
});
model.read(&app, |model, _| {
assert_eq!(model.get_last_focused_terminal_id(), Some(terminal_a));
});
model.update(&mut app, |model, ctx| {
model.handle_pane_focus_change(window_b, Some(terminal_b), Some(task_b), ctx);
});
model.read(&app, |model, _| {
assert_eq!(model.get_last_focused_terminal_id(), Some(terminal_b));
});
// Clearing window B's focus should NOT clear last_focused (it persists).
model.update(&mut app, |model, ctx| {
model.handle_pane_focus_change(window_b, None, None, ctx);
});
model.read(&app, |model, _| {
assert_eq!(model.get_last_focused_terminal_id(), Some(terminal_b));
});
});
}
#[test]
fn unknown_window_returns_none() {
App::test((), |mut app| async move {
let model = setup_model(&mut app);
let window_a = WindowId::new();
let unknown_window = WindowId::new();
let terminal = EntityId::new();
let task = new_task_id();
model.update(&mut app, |model, ctx| {
model.handle_pane_focus_change(window_a, Some(terminal), Some(task), ctx);
});
model.read(&app, |model, _| {
assert_eq!(model.get_focused_conversation(unknown_window), None);
});
});
}
#[test]
fn focus_change_without_task_id_has_no_conversation() {
App::test((), |mut app| async move {
let model = setup_model(&mut app);
let window = WindowId::new();
let terminal = EntityId::new();
// No agent view handles registered, no task_id → active_conversation_id should be None.
model.update(&mut app, |model, ctx| {
model.handle_pane_focus_change(window, Some(terminal), None, ctx);
});
model.read(&app, |model, _| {
assert_eq!(model.get_focused_conversation(window), None);
});
});
}
#[test]
fn remove_focused_state_for_window_cleans_up() {
App::test((), |mut app| async move {
let model = setup_model(&mut app);
let window_a = WindowId::new();
let window_b = WindowId::new();
let terminal_a = EntityId::new();
let terminal_b = EntityId::new();
let task_a = new_task_id();
let task_b = new_task_id();
model.update(&mut app, |model, ctx| {
model.handle_pane_focus_change(window_a, Some(terminal_a), Some(task_a), ctx);
model.handle_pane_focus_change(window_b, Some(terminal_b), Some(task_b), ctx);
});
// Remove window A's state (simulating undo-close expiry).
model.update(&mut app, |model, ctx| {
model.remove_focused_state_for_window(window_a, ctx);
});
model.read(&app, |model, _| {
assert_eq!(model.get_focused_conversation(window_a), None);
assert_eq!(
model.get_focused_conversation(window_b),
Some(ConversationOrTaskId::TaskId(task_b))
);
});
// Removing again is a no-op.
model.update(&mut app, |model, ctx| {
model.remove_focused_state_for_window(window_a, ctx);
});
});
}
#[test]
fn overwriting_same_window_updates_state() {
App::test((), |mut app| async move {
let model = setup_model(&mut app);
let window = WindowId::new();
let terminal_1 = EntityId::new();
let terminal_2 = EntityId::new();
let task_1 = new_task_id();
let task_2 = new_task_id();
model.update(&mut app, |model, ctx| {
model.handle_pane_focus_change(window, Some(terminal_1), Some(task_1), ctx);
});
model.read(&app, |model, _| {
assert_eq!(
model.get_focused_conversation(window),
Some(ConversationOrTaskId::TaskId(task_1))
);
});
model.update(&mut app, |model, ctx| {
model.handle_pane_focus_change(window, Some(terminal_2), Some(task_2), ctx);
});
model.read(&app, |model, _| {
assert_eq!(
model.get_focused_conversation(window),
Some(ConversationOrTaskId::TaskId(task_2))
);
});
});
}