use super::{model_focused, world};
use crate::boundary::{Action, reply::Reply};
use crate::cli_outbound::Cli;
use crate::test_support::{authoring_new_arm, engine, spawn_guard};
use std::fs;
use std::os::unix::fs::PermissionsExt;
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_lernie(dir: &Path, body: &str) -> Cli {
let path = dir.join("lernie");
fs::write(&path, body).unwrap();
let mut perms = fs::metadata(&path).unwrap().permissions();
perms.set_mode(0o755);
fs::set_permissions(&path, perms).unwrap();
Cli::new(path)
}
fn staged(
m: &mut crate::AppModel,
lernie: &Cli,
inputs: &crate::start::StartInputs,
) -> Result<crate::start::Prepared, String> {
let deps = m.boundary_deps(lernie, &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 seed(yog_data_root: &Path) {
let lernie = crate::world::layout_under(yog_data_root).lernie;
fs::create_dir_all(&lernie).unwrap();
fs::write(lernie.join("models.yaml"), b"models: {}\n").unwrap();
}
#[test]
fn a_raise_focuses_the_raised_workspace_and_retargets_the_bare_rung() {
let bin = tempdir().unwrap();
let w = world();
seed(&w.roots.yog_data);
let (_c, mut m) = model_focused(&w, &w.ws_cobalt);
assert_eq!(m.focused_workspace(), Some(w.ws_cobalt.clone()));
let _g = spawn_guard();
let inputs = m.new_workspace_inputs("ops");
let prepared = staged(&mut m, &fake_lernie(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(), "`lernie new` ran");
m.adopt_workspace(&raised);
assert_eq!(
m.focused_ws_name().as_deref(),
Some("ops"),
"the focus is the §3.1 name (bl-7407)"
);
assert_eq!(
m.focused_workspace(),
Some(raised.clone()),
"and it resolves through the raise claim, on the frame the receipt landed"
);
assert_eq!(
m.start_bare_inputs().workspace,
raised,
"the bare rung names the start's own workspace"
);
}
#[test]
fn a_failed_prepare_moves_the_focus_nowhere() {
let bin = tempdir().unwrap();
let w = world();
seed(&w.roots.yog_data);
let (_c, mut m) = model_focused(&w, &w.ws_cobalt);
let _g = spawn_guard();
let inputs = m.new_workspace_inputs("ops");
let err = staged(&mut m, &fake_lernie(bin.path(), FAILS), &inputs).unwrap_err();
assert!(err.contains("boom"), "the refusal rode back");
assert_eq!(
m.focused_workspace(),
Some(w.ws_cobalt.clone()),
"nothing was resolved, so nothing moved"
);
}
#[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_focused(&w, &w.ws_cobalt);
let _g = spawn_guard();
let inputs = m.new_ball_inputs(Path::new("/nowhere/at/all"), "Fresh", "do it");
let err = staged(&mut m, &fake_lernie(bin.path(), &news()), &inputs).unwrap_err();
assert_eq!(err, "unknown project \"/nowhere/at/all\"");
}