use std::path::PathBuf;
use super::record::ManagedSessionState;
use super::tests::make_manager;
#[tokio::test]
async fn manager_send_input_rejected_for_provisioning_and_errored() {
let dir = crate::test_support::hermetic_temp_dir();
let (mgr, fake) = make_manager(&dir).await;
let record = mgr
.create(
"task".into(),
Some(PathBuf::from("/tmp/x")),
None,
None,
None,
None,
)
.await
.expect("create");
assert_eq!(record.state, ManagedSessionState::Provisioning);
let result = mgr.send_input(&record.id, "rm -rf /").await;
assert!(
result.is_err(),
"send_input must fail for Provisioning sessions (pre-fix: this proceeds)"
);
assert!(
fake.send_calls.lock().unwrap().is_empty(),
"no send-line may fire for a Provisioning session — this is the shell-execution risk"
);
mgr.mark_errored(&record.id, "spawn failed")
.await
.expect("mark_errored");
let result = mgr.send_input(&record.id, "rm -rf /").await;
assert!(
result.is_err(),
"send_input must fail for Errored sessions (pre-fix: this proceeds)"
);
assert!(
fake.send_calls.lock().unwrap().is_empty(),
"no send-line may fire for an Errored session — this is the shell-execution risk"
);
}
#[tokio::test]
async fn manager_send_input_rejected_when_pane_shows_blocking_modal() {
let dir = crate::test_support::hermetic_temp_dir();
let (mgr, fake) = make_manager(&dir).await;
let record = mgr
.create(
"task".into(),
Some(PathBuf::from("/tmp/x")),
None,
None,
None,
None,
)
.await
.expect("create");
{
let mut store = mgr.store.write().await;
let mut r = store.get(&record.id).await.unwrap();
r.state = ManagedSessionState::Active;
store.upsert(r).await.unwrap();
}
fake.capture_responses.lock().unwrap().insert(
record.tmux_name.clone(),
"Do you trust the files in this folder?".into(),
);
let result = mgr.send_input(&record.id, "hello").await;
assert!(
result.is_err(),
"send_input must fail when the pane shows a blocking modal (pre-fix: this proceeds)"
);
assert!(
fake.send_calls.lock().unwrap().is_empty(),
"no send-line may fire while a blocking modal is showing"
);
}
#[tokio::test]
async fn manager_send_input_skips_modal_probe_for_tcode() {
let dir = crate::test_support::hermetic_temp_dir();
let (mgr, fake) = make_manager(&dir).await;
let record = mgr
.create(
"task".into(),
Some(PathBuf::from("/tmp/x")),
None,
None,
None,
None,
)
.await
.expect("create");
{
let mut store = mgr.store.write().await;
let mut r = store.get(&record.id).await.unwrap();
r.state = ManagedSessionState::Active;
r.runtime = crate::runtime::RuntimeKind::Tcode;
store.upsert(r).await.unwrap();
}
fake.capture_responses.lock().unwrap().insert(
record.tmux_name.clone(),
"Do you trust the files in this folder?".into(),
);
mgr.send_input(&record.id, "hello tcode")
.await
.expect("send_input must succeed for an Active tcode session even with a ClaudeCode-shaped marker in its pane");
let calls = fake.send_calls.lock().unwrap();
assert!(calls.iter().any(|(_, text)| text == "hello tcode"));
}
#[tokio::test]
async fn send_input_observed_reports_unsubmitted_paste() {
let dir = crate::test_support::hermetic_temp_dir();
let (mgr, fake) = make_manager(&dir).await;
let record = mgr
.create(
"task".into(),
Some(PathBuf::from("/tmp/x")),
None,
None,
None,
None,
)
.await
.expect("create");
{
let mut store = mgr.store.write().await;
let mut r = store.get(&record.id).await.unwrap();
r.state = ManagedSessionState::Active;
store.upsert(r).await.unwrap();
}
fake.capture_responses.lock().unwrap().insert(
record.tmux_name.clone(),
"❯ [Pasted text #1][Pasted text #2]".into(),
);
let state = mgr
.send_input_observed(&record.id, "a very long coordination message")
.await
.expect("the send itself succeeds — only the SUBMIT is in question");
assert_eq!(
state,
crate::session_manager::SubmitState::UnsubmittedPaste,
"a pane still showing a collapsed paste proves the Enter did not commit"
);
assert!(
!state.delivered(),
"`sent` must be false for an observed unsubmitted paste (pre-fix: hardcoded true)"
);
assert!(
fake.send_calls
.lock()
.unwrap()
.iter()
.any(|(_, text)| text == "a very long coordination message"),
"the text was typed — the verdict is about submission, not dispatch"
);
}
#[tokio::test]
async fn send_input_observed_reports_submitted_on_a_clean_prompt() {
let dir = crate::test_support::hermetic_temp_dir();
let (mgr, fake) = make_manager(&dir).await;
let record = mgr
.create(
"task".into(),
Some(PathBuf::from("/tmp/x")),
None,
None,
None,
None,
)
.await
.expect("create");
{
let mut store = mgr.store.write().await;
let mut r = store.get(&record.id).await.unwrap();
r.state = ManagedSessionState::Active;
store.upsert(r).await.unwrap();
}
fake.capture_responses
.lock()
.unwrap()
.insert(record.tmux_name.clone(), "● Working…\n❯ ".into());
let state = mgr
.send_input_observed(&record.id, "short message")
.await
.expect("send");
assert_eq!(state, crate::session_manager::SubmitState::Submitted);
assert!(state.delivered());
}