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_settings_rows() {
let temp = tempfile::TempDir::new().unwrap();
let (sender, receiver) = bounded::<TuiEvent>(4);
let mut app = test_app(&temp, sender);
crate::config::write_settings(
&app.config.paths,
&crate::config::Settings {
mcp_servers: std::collections::BTreeMap::from([
(
"alpha".to_string(),
crate::config::McpServerConfig::Stdio(crate::config::McpStdioServerConfig {
command: "alpha-mcp".to_string(),
args: Vec::new(),
env: std::collections::BTreeMap::new(),
enabled: true,
timeout: None,
}),
),
(
"beta".to_string(),
crate::config::McpServerConfig::Http(crate::config::McpHttpServerConfig {
url: "https://mcp.example.test/beta".to_string(),
headers: std::collections::BTreeMap::new(),
oauth: None,
enabled: false,
timeout: None,
}),
),
]),
..Default::default()
},
)
.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);
crate::config::write_settings(
&app.config.paths,
&crate::config::Settings {
mcp_servers: std::collections::BTreeMap::from([(
"alpha".to_string(),
crate::config::McpServerConfig::Stdio(crate::config::McpStdioServerConfig {
command: "alpha-mcp".to_string(),
args: Vec::new(),
env: std::collections::BTreeMap::new(),
enabled: true,
timeout: None,
}),
)]),
..Default::default()
},
)
.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();
app.set_mcp_server_enabled("alpha", false, &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!(!settings.mcp_servers.get("alpha").unwrap().enabled());
let raw: serde_json::Value =
serde_json::from_str(&std::fs::read_to_string(&app.config.paths.settings_file).unwrap())
.unwrap();
assert_eq!(raw["capabilities"]["mcp"]["alpha"]["enabled"], false);
}
#[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());
}