use super::*;
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
use crate::app::supervisor::DemoSupervisor;
use crate::features::demo;
use crate::shared::api::contract::EngineBackend;
use crate::shared::api::mock::MockBackend;
async fn collect_reply(
cmd_tx: &UnboundedSender<AppCommand>,
evt_rx: &mut UnboundedReceiver<AppEvent>,
text: &str,
) -> String {
cmd_tx.send(AppCommand::SendMessage(text.into())).unwrap();
let mut out = String::new();
while let Some(ev) = evt_rx.recv().await {
match &ev {
AppEvent::Chunk { text, .. } => out.push_str(text),
AppEvent::Finished { .. } => break,
_ => {}
}
}
out
}
#[tokio::test]
async fn demo_boot_streams_cycling_canned_replies() {
let dir = tempfile::tempdir().unwrap();
let storage = Arc::new(Storage::open(Paths::with_root(dir.path())).unwrap());
demo::provision(&storage).unwrap();
let config = storage.json().load_config().unwrap();
assert_eq!(
config.last_active_chat,
Some(demo::chat_id()),
"the demo opens on the showcase chat"
);
let (cmd_tx, cmd_rx) = unbounded_channel();
let (evt_tx, mut evt_rx) = unbounded_channel();
let backend: Arc<dyn EngineBackend> = Arc::new(MockBackend::cycling(demo::demo_replies(), 0));
let _handle = tokio::spawn(run(OrchestratorDeps {
cmd_rx,
evt_tx,
storage,
config,
supervisor: Arc::new(DemoSupervisor::new(backend)),
default_language: crate::shared::i18n::Lang::En,
extra_tools: Vec::new(),
}));
let first = collect_reply(&cmd_tx, &mut evt_rx, "Who am I talking to?").await;
assert!(
first.contains("demo engine"),
"the first canned reply says what it is: {first:?}"
);
let second = collect_reply(&cmd_tx, &mut evt_rx, "Show me something.").await;
assert!(!second.is_empty(), "the engine never runs dry");
assert_ne!(first, second, "cycling rotates to the next script");
}