use super::{DEPOSITS, Sent};
use crate::channel::Reach;
use crate::reply::transcript::Transcript;
use crate::reply::{Outcome, Read, Reply};
use crate::test_support::window::{own, said, seated};
use crate::ui::Model;
const HERE: &str = "20260830T051200Z-a1b2";
const THERE: &str = "20260830T052000Z-b2c3";
fn ran(exit: i32) -> Read {
Read::Answer(Reply::Outcome(Outcome {
exit,
stdout: String::new(),
stderr: String::new(),
}))
}
fn having_sent(words: &str) -> Model {
let mut model = seated();
model.deposit(
crate::verbs::message,
"home".to_owned(),
HERE.to_owned(),
words.to_owned(),
);
model
}
#[test]
fn a_deposit_is_recorded_the_frame_it_is_composed() {
let mut model = having_sent("ship it");
assert_eq!(
model.sent,
vec![Sent {
conversation: HERE.to_owned(),
words: "ship it".to_owned(),
after: 1,
acked: false,
}]
);
assert_eq!(model.outbox.len(), 1);
assert!(crate::ui::slash::fire(&mut model, "interrupt", "no, this"));
assert_eq!(model.sent[1].words, "no, this");
assert_eq!(model.outbox[1].envelope["op"], "interrupt");
assert!(DEPOSITS.contains(&"interrupt"));
}
#[test]
fn an_ok_receipt_acknowledges_the_oldest_record_and_retires_nothing() {
let mut model = having_sent("one");
model.deposit(
crate::verbs::message,
"home".to_owned(),
HERE.to_owned(),
"two".to_owned(),
);
let flat = own().channel;
model.receipt(&flat, crate::verbs::NUDGE.word, ran(0));
assert!(model.sent.iter().all(|sent| !sent.acked));
model.receipt(&flat, crate::verbs::MESSAGE.word, ran(0));
assert_eq!(
model.sent.iter().map(|sent| sent.acked).collect::<Vec<_>>(),
vec![true, false]
);
model.receipt(&flat, crate::verbs::INTERRUPT.word, ran(1));
assert!(!model.sent[1].acked, "a failed run is the bar's");
model.receipt(&flat, crate::verbs::INTERRUPT.word, ran(0));
assert!(model.sent.iter().all(|sent| sent.acked));
model.receipt(&flat, crate::verbs::MESSAGE.word, ran(0));
assert_eq!(model.sent.len(), 2, "a receipt with nothing left to answer");
}
#[test]
fn a_refusal_gives_the_words_back_ahead_of_the_draft() {
let flat = own().channel;
let mut model = having_sent("ship it");
model.receipt(
&flat,
crate::verbs::MESSAGE.word,
Read::Refusal("no".to_owned()),
);
assert!(model.sent.is_empty());
assert_eq!(model.draft, "ship it");
let mut model = having_sent("ship it");
model.draft = "and then".to_owned();
model.receipt(
&flat,
crate::verbs::INTERRUPT.word,
Read::Refusal("no".to_owned()),
);
assert_eq!(model.draft, "ship it\nand then");
}
#[test]
fn the_transcript_that_carries_the_words_retires_the_record() {
let flat = own().channel;
let mut model = having_sent("port it");
let committed = |entries: Vec<crate::reply::transcript::Entry>| {
Read::Answer(Reply::Transcript(Transcript { entries }))
};
model.absorb(&flat, committed(vec![said("op", "port it")]));
assert_eq!(model.sent.len(), 1, "the one before it is not this one");
model.absorb(
&flat,
committed(vec![said("op", "port it"), said("peer", "port it")]),
);
assert_eq!(model.sent.len(), 1, "a peer's row is not the operator's");
model.absorb(
&flat,
committed(vec![said("op", "port it"), said("user", "port it")]),
);
assert!(model.sent.is_empty());
assert_eq!(model.transcript.entries.len(), 2);
let mut model = having_sent("ship it");
model.sent.push(Sent {
conversation: THERE.to_owned(),
words: "ship it".to_owned(),
after: 0,
acked: false,
});
model.absorb(
&flat,
committed(vec![said("op", "port it"), said("op", "ship it")]),
);
assert_eq!(
model
.sent
.iter()
.map(|sent| sent.conversation.as_str())
.collect::<Vec<_>>(),
vec![THERE],
"the read is the selected conversation's"
);
}
#[test]
fn a_record_stands_with_its_own_conversation() {
let mut model = having_sent("ship it");
model.select(THERE);
assert!(model.sent_here().next().is_none());
model.deposit(
crate::verbs::message,
"home".to_owned(),
THERE.to_owned(),
"there".to_owned(),
);
assert_eq!(
model
.sent_here()
.map(|sent| sent.words.as_str())
.collect::<Vec<_>>(),
vec!["there"]
);
model.select(HERE);
assert_eq!(
model
.sent_here()
.map(|sent| sent.words.as_str())
.collect::<Vec<_>>(),
vec!["ship it"]
);
}
#[test]
fn an_unsent_act_drops_its_record_and_an_unanswered_one_keeps_it() {
let mut model = having_sent("ship it");
model.acted(
crate::verbs::NUDGE.word,
&Reach::Unsent("connect: connection refused".to_owned()),
None,
);
assert_eq!(
model.sent.len(),
1,
"another op's failure is not this one's"
);
model.acted(
crate::verbs::MESSAGE.word,
&Reach::Unanswered("read: timed out".to_owned()),
Some("ship it".to_owned()),
);
assert_eq!(model.sent.len(), 1, "the engine may have it");
model.acted(
crate::verbs::MESSAGE.word,
&Reach::Unsent("connect: connection refused".to_owned()),
Some("ship it".to_owned()),
);
assert!(model.sent.is_empty());
assert_eq!(model.draft, "ship it", "the words are the refund's");
}