use super::Harness;
use crate::watch::Mark;
use std::time::Duration;
#[test]
fn a_message_echoes_without_claiming_the_focus() {
let h = Harness::new();
let (clock, mut model) = h.model();
model.focus_agent(&h.ws, "c-1");
let landed = model
.tree(&h.ws)
.and_then(|t| t.agents.first().map(|a| a.messages))
.expect("the fixture's conversation");
model.await_message(&h.ws, "c-1", "and again", 0);
model.refresh();
let echoed = model
.tree(&h.ws)
.and_then(|t| t.agents.first().cloned())
.expect("the folded row");
assert_eq!(
echoed.pending.len(),
1,
"the send is on the row as the undelivered deposit it is (§5.1 #11)"
);
assert!(
echoed.pending[0].in_memory(),
"and it is yog's word, not disk's"
);
assert_eq!(echoed.pending[0].deposit.body, "and again");
model.focus_workspace(&crate::naming::leaf(&h.ws));
model.refresh();
assert!(
model.focus().agent.is_none(),
"a follow-up's echo carries no focus claim to spend"
);
let messages = h.ws.join("agents/c-1/messages");
std::fs::create_dir_all(&messages).unwrap();
std::fs::write(
messages.join(format!("{:03}-user.md", landed + 1)),
"and again",
)
.unwrap();
model.dirty_handle().mark_all([(h.ws.clone(), Mark::Watch)]);
model.tick();
clock.advance(Duration::from_millis(150));
assert!(model.tick(), "the derivation carries the message now");
assert!(
model
.tree(&h.ws)
.and_then(|t| t.agents.first())
.is_some_and(|a| a.pending.is_empty()),
"the echo gave its seat up rather than doubling the message"
);
}
#[test]
fn an_idle_frame_refolds_nothing_and_hands_back_the_same_pointer() {
use std::sync::Arc;
let h = Harness::new();
let (_c, mut model) = h.model();
model.refresh();
let quiet = Arc::clone(&model.snap);
model.refresh();
assert!(
Arc::ptr_eq(&quiet, &model.snap),
"nothing pending, nothing published: the same snapshot, not a copy of it"
);
model.await_message(&h.ws, "c-1", "and again", 0);
model.refresh();
let folded = Arc::clone(&model.snap);
assert!(!Arc::ptr_eq(&quiet, &folded), "a new echo is a new fold");
model.refresh();
assert!(
Arc::ptr_eq(&folded, &model.snap),
"and holding the same echo over the same derivation folds nothing again"
);
}
fn listed(name: &str, body: &str) -> crate::inboxview::InboxEntry {
crate::inboxview::InboxEntry {
name: name.into(),
raw: body.as_bytes().to_vec(),
deposit: crate::inboxview::Deposit {
sender: Some("user".into()),
body: body.into(),
..crate::inboxview::Deposit::default()
},
}
}
#[test]
fn the_queue_echo_yields_the_moment_the_answer_carries_its_deposit() {
let h = Harness::new();
let (_c, mut model) = h.model();
model.focus_agent(&h.ws, "c-1");
model.await_message(&h.ws, "c-1", "and again", 1);
let stale = vec![listed("user-001.md", "already mail")];
let echoed = model.echoed_pending("c-1", stale.clone());
assert_eq!(echoed.len(), 2, "the answer has not moved: the echo shows");
assert!(echoed[1].in_memory(), "and it is yog's word, not disk's");
assert_eq!(echoed[1].deposit.body, "and again");
let mut fresh = stale.clone();
fresh.push(listed("user-002.md", "and again"));
let yielded = model.echoed_pending("c-1", fresh.clone());
assert_eq!(yielded, fresh, "one row, and it is the deposit's own");
assert!(
!yielded.iter().any(crate::inboxview::InboxEntry::in_memory),
"nothing faded is left beside it (§7.2)"
);
assert_eq!(model.echoed_pending("c-2", stale.clone()), stale);
}