use super::support::*;
use super::*;
#[test]
fn submit_help_opens_help_without_worker_or_provider_run() {
assert_eq!(
tui_submit_command(" /help ignored ", &CommandRegistry::mvp()),
TuiSubmitCommand::Help
);
assert!(!tui_submit_command("/help", &CommandRegistry::mvp()).requires_idle());
let temp = tempfile::TempDir::new().unwrap();
let (sender, receiver) = bounded::<TuiEvent>(4);
let mut app = test_app(&temp, sender);
app.active_run = true;
let mut ui_state = state::MissionControlState {
..Default::default()
};
let submitted = app.submit("/help".to_string(), &mut ui_state, &receiver, test_area());
assert!(!submitted);
assert!(ui_state.show_help);
assert_eq!(ui_state.help_offset(), 0);
assert_eq!(ui_state.status, "showing help");
assert!(app.active_run);
assert!(app.worker.is_none());
assert!(receiver.try_recv().is_err());
}
#[test]
fn submit_system_prompt_and_quit_preserve_active_run_bypass_behavior() {
let temp = tempfile::TempDir::new().unwrap();
let (sender, receiver) = bounded::<TuiEvent>(4);
let mut app = test_app(&temp, sender);
app.active_run = true;
let mut ui_state = state::MissionControlState::default();
app.submit(
"/system-prompt".to_string(),
&mut ui_state,
&receiver,
test_area(),
);
assert!(ui_state.system_prompt_modal_visible());
assert!(app.active_run);
assert!(app.worker.is_none());
assert!(receiver.try_recv().is_err());
app.submit("/quit".to_string(), &mut ui_state, &receiver, test_area());
assert!(app.active_run);
assert!(app.worker.is_none());
assert!(receiver.try_recv().is_err());
}
#[test]
fn submit_system_prompt_prepares_modal_without_provider_worker_or_session_event() {
let temp = tempfile::TempDir::new().unwrap();
let (sender, receiver) = bounded::<TuiEvent>(4);
let session = SessionManager::new(temp.path().join("sessions"))
.create()
.unwrap();
let paths = test_paths(temp.path());
fs::create_dir_all(&paths.subagents).unwrap();
fs::write(
paths.subagents.join("reviewer.md"),
"---\nname: Reviewer\ndescription: Code review\n---\nSECRET REVIEW PROMPT\n",
)
.unwrap();
let mut app = test_app_with_active_session(&temp, sender, Some(session.clone()));
let mut ui_state = state::MissionControlState {
prompt_editor: state::PromptEditor::new("preserved draft", "preserved draft".len()),
transcript: vec!["existing transcript".to_string()].into(),
model: "test-model".to_string(),
provider_ready: false,
..Default::default()
};
ui_state.set_scroll_offset(&ui_state.scroll_views.detail, 3);
app.submit(
"/system-prompt".to_string(),
&mut ui_state,
&receiver,
test_area(),
);
assert_eq!(ui_state.status, "preparing system prompt…");
reap_owned_worker(
&mut app,
&mut ui_state,
MissionControlApp::reconcile_system_prompt_worker,
);
let modal = ui_state.modals.system_prompt_modal.as_ref().unwrap();
assert!(!modal.content.trim().is_empty());
assert!(modal.content.contains("tokens /"));
assert!(modal.content.contains("max ("));
assert!(modal.content.contains("<Tools>"));
assert!(!modal.content.contains("Available tools:"));
assert!(modal.content.contains("<Subagents>"));
assert!(modal.content.contains("- `reviewer` — Code review"));
let tools_index = modal.content.find("<Tools>").unwrap();
let subagents_index = modal.content.find("<Subagents>").unwrap();
let skills_index = modal.content.find("<Available-Skills>").unwrap();
let instructions_index = modal
.content
.find("No AGENTS.md instruction files")
.unwrap();
assert!(tools_index < subagents_index);
assert!(subagents_index < skills_index);
assert!(skills_index < instructions_index);
assert!(!modal.content.contains("SECRET REVIEW PROMPT"));
assert_eq!(
ui_state.scroll_offset(&ui_state.scroll_views.system_prompt),
0
);
assert_eq!(ui_state.prompt_plain_text(), "preserved draft");
assert_eq!(ui_state.transcript, vec!["existing transcript"]);
assert_eq!(ui_state.detail_offset(), 3);
assert!(!app.active_run);
assert!(app.worker.is_none());
assert!(matches!(
receiver.recv_timeout(Duration::from_secs(1)),
Ok(TuiEvent::WorkerOutcomeReady)
));
assert!(session.read_events().unwrap().is_empty());
}
#[test]
fn submit_mcp_opens_modal_with_approved_and_disabled_definitions() {
let temp = tempfile::TempDir::new().unwrap();
let (sender, receiver) = bounded::<TuiEvent>(4);
let mut app = test_app(&temp, sender);
std::fs::create_dir_all(&app.config.paths.root).unwrap();
std::fs::write(
app.config.paths.root.join(".mcp.json"),
r#"{"mcpServers": {
"alpha": {"command": "alpha-mcp"},
"beta": {"type": "http", "url": "https://mcp.example.test/beta"}
}}"#,
)
.unwrap();
crate::config::set_mcp_server_enabled(&app.config.paths, "alpha", true).unwrap();
let mut ui_state = state::MissionControlState::default();
let submitted = app.submit("/mcp".to_string(), &mut ui_state, &receiver, test_area());
assert!(!submitted);
assert_eq!(ui_state.status, "showing MCP servers");
let modal = ui_state.modals.mcp_modal.as_ref().unwrap();
assert_eq!(modal.rows.len(), 2);
assert_eq!(modal.rows[0].name, "alpha");
assert_eq!(modal.rows[0].kind, "stdio");
assert!(modal.rows[0].enabled);
assert_eq!(modal.rows[1].name, "beta");
assert_eq!(modal.rows[1].kind, "http");
assert!(!modal.rows[1].enabled);
assert!(app.worker.is_none());
assert!(!app.active_run);
assert!(receiver.try_recv().is_err());
}
#[test]
fn submit_mcp_extra_reports_usage_without_opening_modal() {
let temp = tempfile::TempDir::new().unwrap();
let (sender, receiver) = bounded::<TuiEvent>(4);
let mut app = test_app(&temp, sender);
let mut ui_state = state::MissionControlState::default();
let submitted = app.submit(
"/mcp extra".to_string(),
&mut ui_state,
&receiver,
test_area(),
);
assert!(!submitted);
assert_eq!(ui_state.status, "usage: /mcp");
assert!(!ui_state.mcp_modal_visible());
assert!(app.worker.is_none());
assert!(!app.active_run);
assert!(receiver.try_recv().is_err());
}
#[test]
fn set_mcp_server_enabled_persists_setting_without_reloading_runtime_manager() {
let temp = tempfile::TempDir::new().unwrap();
let (sender, _receiver) = bounded::<TuiEvent>(1);
let mut app = test_app(&temp, sender);
std::fs::create_dir_all(&app.config.paths.root).unwrap();
let definitions = r#"{"mcpServers":{"alpha":{"command":"alpha-mcp"}}}"#;
let definitions_path = app.config.paths.root.join(".mcp.json");
std::fs::write(&definitions_path, definitions).unwrap();
let runtime_manager = std::sync::Arc::new(std::sync::Mutex::new(
crate::mcp::manager::McpManager::from_settings(&crate::config::McpServersSettings::new()),
));
app.mcp = Some(std::sync::Arc::clone(&runtime_manager));
let mut ui_state = state::MissionControlState::default();
for enabled in [true, false] {
app.open_mcp_modal(&mut ui_state, test_area());
app.set_mcp_server_enabled("alpha", enabled, &mut ui_state);
reap_owned_worker(
&mut app,
&mut ui_state,
MissionControlApp::reap_settings_persistence_worker,
);
assert_eq!(
ui_state.status,
"MCP server setting saved; takes effect next magi-code launch"
);
assert!(
app.mcp
.as_ref()
.is_some_and(|current| std::sync::Arc::ptr_eq(current, &runtime_manager))
);
let settings = crate::config::read_settings(&app.config.paths).unwrap();
assert_eq!(
settings.mcp_servers.get("alpha").unwrap().enabled(),
enabled
);
app.open_mcp_modal(&mut ui_state, test_area());
assert_eq!(
ui_state.modals.mcp_modal.as_ref().unwrap().rows[0].enabled,
enabled
);
assert_eq!(
std::fs::read_to_string(&definitions_path).unwrap(),
definitions
);
}
}
#[test]
fn failed_mcp_server_enabled_save_rolls_back_optimistic_row() {
let temp = tempfile::TempDir::new().unwrap();
let (sender, _receiver) = bounded::<TuiEvent>(1);
let mut app = test_app(&temp, sender);
crate::config::write_settings(&app.config.paths, &crate::config::Settings::default()).unwrap();
let mut ui_state = state::MissionControlState::default();
ui_state.open_mcp_modal(
vec![state::McpServerToggleRow {
name: "missing-server".to_string(),
kind: "stdio",
enabled: false,
}],
1,
);
app.set_mcp_server_enabled("missing-server", false, &mut ui_state);
reap_owned_worker(
&mut app,
&mut ui_state,
MissionControlApp::reap_settings_persistence_worker,
);
let modal = ui_state.modals.mcp_modal.as_ref().unwrap();
assert!(modal.rows[0].enabled);
assert!(
ui_state
.status
.contains("failed to save setting: mcp server not found: missing-server"),
"{}",
ui_state.status
);
}
#[test]
fn submit_compact_requires_active_session_and_creates_no_worker() {
let temp = tempfile::TempDir::new().unwrap();
let (sender, receiver) = bounded::<TuiEvent>(4);
let mut app = test_app(&temp, sender);
let mut ui_state = state::MissionControlState::default();
app.submit(
"/compact".to_string(),
&mut ui_state,
&receiver,
test_area(),
);
assert_eq!(
ui_state.status,
"/compact requires an active persisted session; start without --no-session or run /new"
);
assert!(receiver.try_recv().is_err());
}