use super::snapshot;
use crate::boundary::dispatch::{Deps, dispatch, prompt};
use crate::boundary::line::Context;
use crate::boundary::{Action, Gesture, codec, line};
use crate::cli_outbound::Cli;
use crate::opslog::Origin;
use crate::start::Prepared;
use crate::test_support::world::no_world;
use crate::ui_state::UiState;
use std::path::{Path, PathBuf};
use std::sync::Arc;
const WS: &str = "alba";
const REFUSAL: &str = "the goal is blank";
fn prepared() -> Prepared {
Prepared {
workspace: WS.to_owned(),
binding: None,
lineage: None,
role: None,
goal: String::new(),
origin: Origin::Conversation,
}
}
fn deps(state: &Path, yog: &Path) -> Deps {
let ws = crate::binding::workspace_path(yog, WS);
Deps {
litany: Cli::new("/no/such/litany"),
bl: Cli::new("/no/such/bl"),
state_root: state.to_path_buf(),
yog_binary: PathBuf::from("/no/such/yog"),
world: no_world(),
home: yog.to_path_buf(),
yog_data_root: yog.to_path_buf(),
snapshot: Arc::new(snapshot(&ws, WS, vec![], vec![])),
caller: crate::boundary::dispatch::Caller::default(),
}
}
#[test]
fn the_typed_door_refuses_an_empty_goal_and_pays_nothing() {
let state = tempfile::tempdir().unwrap();
let yog = tempfile::tempdir().unwrap();
let deps = deps(state.path(), yog.path());
let ui = UiState::open(PathBuf::from("/nonexistent/ui.json"));
let ws = crate::binding::workspace_path(yog.path(), WS);
let refusal = prompt(&deps, &ui, "T1", &ws, &prepared(), "", None).unwrap_err();
assert!(refusal.contains(REFUSAL), "{refusal}");
assert!(
!state.path().join("ops.jsonl").exists(),
"a blank goal costs no trail row: the gate stands ahead of the ceiling's"
);
}
#[test]
fn whitespace_only_is_blank() {
let state = tempfile::tempdir().unwrap();
let yog = tempfile::tempdir().unwrap();
let deps = deps(state.path(), yog.path());
let ui = UiState::open(PathBuf::from("/nonexistent/ui.json"));
let ws = crate::binding::workspace_path(yog.path(), WS);
for goal in [" ", "\t", "\n", " \t\r\n "] {
let refusal = prompt(&deps, &ui, "T1", &ws, &prepared(), goal, None).unwrap_err();
assert!(refusal.contains(REFUSAL), "{goal:?}: {refusal}");
}
assert!(!state.path().join("ops.jsonl").exists());
}
#[test]
fn the_deposited_envelope_refuses_a_whitespace_goal() {
let state = tempfile::tempdir().unwrap();
let yog = tempfile::tempdir().unwrap();
let deps = deps(state.path(), yog.path());
let mut ui = UiState::open(PathBuf::from("/nonexistent/ui.json"));
let wire = codec::encode(&Gesture::Act(Action::Prompt {
prepared: prepared(),
goal: " ".to_owned(),
seed: None,
}));
let Ok(Gesture::Act(action)) = codec::decode(&wire) else {
unreachable!("the prompt envelope round-trips")
};
let refusal = dispatch(&deps, &mut ui, "T1", &action).unwrap_err();
assert!(refusal.contains(REFUSAL), "{refusal}");
assert!(!state.path().join("ops.jsonl").exists());
}
#[test]
fn the_line_spelling_never_produces_a_blank_gesture() {
let ctx = Context {
prepared: Some(prepared()),
..Context::default()
};
for draft in ["/prompt", "/prompt ", "/prompt \t"] {
let refusal = line::parse(draft, &ctx).unwrap_err();
assert!(refusal.contains("/prompt"), "{draft:?}: {refusal}");
}
}