use super::{model, world};
use crate::boundary::{Action, reply::Reply};
use crate::cli_outbound::Cli;
use crate::test_support::{authoring_new_arm, engine};
use std::fs;
use std::path::Path;
use tempfile::tempdir;
fn news() -> String {
format!(
"#!/bin/sh\ncase \"$1\" in\n{}esac\nexit 0\n",
authoring_new_arm()
)
}
const FAILS: &str = "#!/bin/sh\nprintf 'boom\\n' 1>&2\nexit 3\n";
fn fake_litany(dir: &Path, body: &str) -> Cli {
let path = dir.join("litany");
crate::test_support::write_exec(&path, body);
Cli::new(path)
}
fn staged(
m: &mut crate::AppModel,
litany: &Cli,
inputs: &crate::start::StartInputs,
) -> Result<crate::start::Prepared, String> {
let deps = m.boundary_deps(litany, &Cli::new("/no/bl"));
let action = Action::Prepare {
workspace: m.snap.ws_name(&inputs.workspace),
payload: inputs.payload.clone(),
};
match engine::act(m, &deps, "TS", &action)? {
Reply::Prepared(prepared) => Ok(prepared),
other => panic!("the prepare door answers a Prepared, not {other:?}"),
}
}
fn inputs(
m: &crate::AppModel,
w: &super::World,
workspace: &Path,
payload: crate::start::Payload,
) -> crate::start::StartInputs {
crate::start::StartInputs {
workspace: workspace.to_path_buf(),
payload,
repo: None,
home: w.roots.home.clone(),
yog_data_root: w.roots.yog_data.clone(),
balls_state_root: m.balls_state_root(),
conversation_names: Vec::new(),
}
}
fn seed(yog_data_root: &Path) {
let litany = crate::world::layout_under(yog_data_root).litany;
fs::create_dir_all(&litany).unwrap();
fs::write(litany.join("models.yaml"), b"models: {}\n").unwrap();
}
#[test]
fn a_raise_founds_the_wall_the_reply_names() {
let bin = tempdir().unwrap();
let w = world();
seed(&w.roots.yog_data);
let (_c, mut m) = model(&w);
let target = crate::binding::workspace_path(&w.roots.yog_data, "ops");
let inputs = inputs(&m, &w, &target, crate::start::Payload::Bare);
let prepared = staged(&mut m, &fake_litany(bin.path(), &news()), &inputs).unwrap();
assert_eq!(
prepared.workspace, "ops",
"the operator's own name (§3.1) — the address and the stamp are one"
);
let raised = crate::binding::workspace_path(&w.roots.yog_data, &prepared.workspace);
assert_ne!(raised, w.ws_cobalt, "the raise always raises a fresh wall");
assert!(raised.join("repo.git").is_dir(), "`litany new` ran");
assert_eq!(crate::naming::leaf(&raised), prepared.workspace);
}
#[test]
fn a_failed_prepare_answers_the_refusal_and_founds_nothing() {
let bin = tempdir().unwrap();
let w = world();
seed(&w.roots.yog_data);
let (_c, mut m) = model(&w);
let raised = crate::binding::workspace_path(&w.roots.yog_data, "ops");
let inputs = inputs(&m, &w, &raised, crate::start::Payload::Bare);
let err = staged(&mut m, &fake_litany(bin.path(), FAILS), &inputs).unwrap_err();
assert!(err.contains("boom"), "the refusal rode back");
assert!(
!raised.join("repo.git").is_dir(),
"nothing was founded, so there is nothing to adopt"
);
}
#[test]
fn a_ball_rung_whose_project_this_world_does_not_enumerate_refuses_by_name() {
let bin = tempdir().unwrap();
let w = world();
seed(&w.roots.yog_data);
let (_c, mut m) = model(&w);
let inputs = inputs(
&m,
&w,
&crate::binding::workspace_path(&w.roots.yog_data, "ops"),
crate::start::Payload::Ball {
project: "/nowhere/at/all".to_owned(),
ball: crate::start::BallSpec::New {
title: "Fresh".to_owned(),
body: "do it".to_owned(),
},
},
);
let err = staged(&mut m, &fake_litany(bin.path(), &news()), &inputs).unwrap_err();
assert_eq!(err, "unknown project \"/nowhere/at/all\" — known: a");
}