use super::super::*;
use super::support::*;
#[test]
fn active_modals_ignore_layout_shortcuts() {
let modal_key = modified_key(KeyCode::Right, KeyModifiers::CONTROL | KeyModifiers::SHIFT);
let mut session = MissionControlState::default();
session.open_session_picker(
vec![crate::tui::state::SessionPickerRow {
id: "session-a".into(),
label: "session-a".into(),
is_current: false,
preview: None,
}],
1,
);
handle_key(modal_key, &mut session);
assert_eq!(
session.layout_mode,
crate::tui::state::TuiLayoutMode::TranscriptFocused
);
let mut skills = MissionControlState::default();
skills.open_skills_modal(
vec![crate::tui::state::SkillToggleRow {
name: "skill-a".into(),
source: "test".to_string(),
enabled: true,
}],
1,
);
handle_key(modal_key, &mut skills);
assert_eq!(
skills.layout_mode,
crate::tui::state::TuiLayoutMode::TranscriptFocused
);
let mut subagents = MissionControlState::default();
subagents.open_subagents_modal(
vec![crate::tui::state::SubagentProfileToggleRow {
id: "agent-a".into(),
description: "Agent A".into(),
enabled: true,
}],
1,
);
handle_key(modal_key, &mut subagents);
assert_eq!(
subagents.layout_mode,
crate::tui::state::TuiLayoutMode::TranscriptFocused
);
let mut mcp = MissionControlState::default();
mcp.open_mcp_modal(
vec![crate::tui::state::McpServerToggleRow {
name: "server-a".into(),
kind: "stdio",
enabled: true,
}],
1,
);
handle_key(modal_key, &mut mcp);
assert_eq!(
mcp.layout_mode,
crate::tui::state::TuiLayoutMode::TranscriptFocused
);
let mut system = MissionControlState::default();
system.open_system_prompt_modal("modal".into());
handle_key(modal_key, &mut system);
assert_eq!(
system.layout_mode,
crate::tui::state::TuiLayoutMode::TranscriptFocused
);
let mut connect = MissionControlState::default();
connect.open_connect_provider(
vec![crate::tui::state::LoginProviderEntry {
id: "openai-codex".into(),
label: "OpenAI Codex".into(),
description: String::new(),
status: String::new(),
}],
None,
);
handle_key(modal_key, &mut connect);
assert_eq!(
connect.layout_mode,
crate::tui::state::TuiLayoutMode::TranscriptFocused
);
let mut oauth = MissionControlState::default();
oauth.open_connect_provider(Vec::new(), None);
oauth.start_connect_oauth("openai-codex".into());
handle_key(modal_key, &mut oauth);
assert_eq!(
oauth.layout_mode,
crate::tui::state::TuiLayoutMode::TranscriptFocused
);
let mut model = MissionControlState {
provider: "openai-codex".to_string(),
model: "gpt-a".to_string(),
..Default::default()
};
model.open_model_picker(
vec![crate::model_catalog::ModelCatalogEntry::new_codex("gpt-a")],
std::collections::BTreeSet::new(),
None,
1,
);
handle_key(modal_key, &mut model);
assert_eq!(
model.layout_mode,
crate::tui::state::TuiLayoutMode::TranscriptFocused
);
}
#[test]
fn mcp_modal_enter_toggles_selected_server() {
let mut state = MissionControlState::default();
state.open_mcp_modal(
vec![
crate::tui::state::McpServerToggleRow {
name: "server-a".into(),
kind: "stdio",
enabled: true,
},
crate::tui::state::McpServerToggleRow {
name: "server-b".into(),
kind: "http",
enabled: false,
},
],
2,
);
assert_eq!(
handle_key(key(KeyCode::Down), &mut state),
InputAction::None
);
assert_eq!(
handle_key(key(KeyCode::Enter), &mut state),
InputAction::SetMcpServerEnabled {
name: "server-b".into(),
enabled: true
}
);
}
#[test]
fn active_modals_ignore_pane_focus_shortcuts() {
let pane_focus_key = modified_key(KeyCode::Char('1'), KeyModifiers::ALT);
let mut state = MissionControlState {
focus_pane: crate::tui::state::TuiFocusPane::Prompt,
..Default::default()
};
state.open_session_picker(
vec![crate::tui::state::SessionPickerRow {
id: "session-a".into(),
label: "session-a".into(),
is_current: false,
preview: None,
}],
1,
);
handle_key(pane_focus_key, &mut state);
assert!(state.is_prompt_focused());
assert!(state.session_picker_visible());
}
#[test]
fn modal_priority_prefers_session_picker_over_later_modals() {
let mut state = MissionControlState::default();
state.open_skills_modal(
vec![crate::tui::state::SkillToggleRow {
name: "skill-a".to_string(),
source: "test".to_string(),
enabled: true,
}],
1,
);
state.open_session_picker(
vec![crate::tui::state::SessionPickerRow {
id: "session-a".to_string(),
label: "session-a".to_string(),
is_current: false,
preview: None,
}],
1,
);
assert!(matches!(
handle_key(key(KeyCode::Enter), &mut state),
InputAction::SelectSession(session) if session == "session-a"
));
assert!(!state.session_picker_visible());
assert!(state.skills_modal_visible());
assert!(state.modals.skills_modal.as_ref().unwrap().rows[0].enabled);
}
#[test]
fn subagent_viewer_precedes_logout_confirmation_without_confirming_it() {
let mut state = MissionControlState::default();
let batch = ActivityId::new("precedence-batch");
state.apply_activity_event(ActivityEvent::Started {
id: batch.clone(),
parent_id: None,
kind: ActivityKind::SubagentBatch,
status: ActivityStatus::Running,
metadata: ActivityMetadata::new("subagents"),
});
let first = batch.child("g1");
let second = batch.child("g2");
for task in [&first, &second] {
state.apply_activity_event(ActivityEvent::Started {
id: task.clone(),
parent_id: Some(batch.clone()),
kind: ActivityKind::SubagentTask,
status: ActivityStatus::Running,
metadata: ActivityMetadata::new(task.as_str()),
});
}
assert!(state.open_subagent_viewer(batch, first.clone()));
state.open_logout_confirmation("provider".to_string(), "Provider".to_string());
assert_eq!(
state.top_modal(),
Some(crate::tui::state::ModalKind::SubagentViewer)
);
assert_eq!(
handle_key(key(KeyCode::Enter), &mut state),
InputAction::None
);
assert_eq!(state.subagent_viewer_selected_task_id(), Some(first));
assert!(state.modals.logout_confirmation.is_some());
assert_eq!(
handle_key(key(KeyCode::Right), &mut state),
InputAction::None
);
assert_eq!(state.subagent_viewer_selected_task_id(), Some(second));
assert!(state.modals.logout_confirmation.is_some());
assert_eq!(handle_key(key(KeyCode::Esc), &mut state), InputAction::None);
assert!(!state.subagent_viewer_visible());
assert!(state.modals.logout_confirmation.is_some());
}