use super::{INDOUBT, UNFIRED, start};
use crate::channel::entries::WORKSPACE;
use crate::cli::Stream;
use crate::render::Form;
use crate::test_support::Scratch;
use crate::test_support::engine::Answer;
use crate::test_support::wire::{entry, flat, wired};
use serde_json::{Value, json};
fn staged(workspace: &str) -> Value {
json!({"ok": true, "kind": "prepared",
"prepared": {"workspace": workspace, "goal": "",
"lineage": "reviewer", "origin": "world"}})
}
fn started(name: &str) -> Value {
json!({"ok": true, "kind": "started", "conversation": name})
}
#[test]
fn a_start_stages_then_fires_and_the_second_act_carries_the_first_s_answer() {
let scratch = Scratch::new();
let engine = wired(
&scratch,
&flat(),
vec![vec![staged("home")], vec![started("brisk-otter")]],
);
let verdict = start(
scratch.path(),
"home",
"do the thing",
None,
None,
Form::Json,
);
assert_eq!(verdict.code, 0);
assert_eq!(verdict.stream, Stream::Out);
assert_eq!(
verdict.text,
format!("{}\n{}", staged("home"), started("brisk-otter")),
"both streams are the product"
);
let heard = engine.heard();
assert!(
heard.contains(&json!({"op": "prepare", "workspace": "home",
"payload": {"rung": "bare"}})),
"{heard:?}"
);
assert!(
heard.contains(
&json!({"op": "prompt", "goal": "do the thing", "seed": null,
"prepared": {"workspace": "home", "goal": "",
"lineage": "reviewer", "origin": "world"}})
),
"{heard:?}"
);
}
#[test]
fn a_renamed_entry_stages_and_fires_down_the_same_channel() {
let scratch = Scratch::new();
let engine = wired(
&scratch,
&entry("home"),
vec![vec![staged("personal")], vec![started("brisk-otter")]],
);
std::fs::write(
scratch.path().join(entry("home")).join(WORKSPACE),
"personal",
)
.expect("the workspace file");
assert_eq!(
start(scratch.path(), "home", "do it", None, None, Form::Json).code,
0
);
let heard = engine.heard();
assert!(
heard.contains(&json!({"op": "prepare", "workspace": "personal",
"payload": {"rung": "bare"}})),
"{heard:?}"
);
assert!(
heard.iter().any(|said| said["op"] == json!("prompt")
&& said["prepared"]["workspace"] == json!("personal")),
"{heard:?}"
);
}
#[test]
fn a_stage_that_answers_no_body_prints_what_it_said_and_starts_nothing() {
for (answer, expected) in [
(
vec![json!({"ok": false, "error": "unknown workspace \"hoem\""})],
json!({"ok": false, "error": "unknown workspace \"hoem\""}).to_string(),
),
(
vec![json!({"ok": true, "kind": "board", "rows": []})],
json!({"ok": true, "kind": "board", "rows": []}).to_string(),
),
(Vec::new(), String::new()),
] {
let scratch = Scratch::new();
let engine = wired(&scratch, &flat(), vec![answer]);
let verdict = start(scratch.path(), "home", "do it", None, None, Form::Json);
assert_eq!(verdict.code, 1, "{}", verdict.text);
assert_eq!(verdict.stream, Stream::Out);
assert_eq!(verdict.text, expected);
assert!(
!engine
.heard()
.iter()
.any(|said| said["op"] == json!("prompt")),
"nothing is fired: {:?}",
engine.heard()
);
}
}
#[test]
fn the_exit_code_is_the_fire_s_verdict() {
let scratch = Scratch::new();
let refused = json!({"ok": false, "error": "no models on this wall"});
wired(
&scratch,
&flat(),
vec![vec![staged("home")], vec![refused.clone()]],
);
let verdict = start(scratch.path(), "home", "do it", None, None, Form::Json);
assert_eq!(verdict.code, 1);
assert_eq!(verdict.text, format!("{}\n{refused}", staged("home")));
}
#[test]
fn a_fire_that_never_leaves_the_box_says_the_start_was_staged() {
let scratch = Scratch::new();
wired(&scratch, &flat(), vec![vec![staged("home")]]);
let verdict = start(scratch.path(), "home", "do it", None, None, Form::Json);
assert_eq!(verdict.code, 1);
assert_eq!(verdict.stream, Stream::Err);
assert!(verdict.text.contains(UNFIRED), "{}", verdict.text);
}
#[test]
fn a_fire_that_crossed_with_no_answer_refuses_the_retype_and_names_the_read() {
let scratch = Scratch::new();
wired(
&scratch,
&flat(),
vec![Answer::Frames(vec![staged("home")]), Answer::Hangup],
);
let verdict = start(scratch.path(), "home", "do it", None, None, Form::Json);
assert_eq!(verdict.code, 1);
assert_eq!(verdict.stream, Stream::Err);
assert!(verdict.text.contains(INDOUBT), "{}", verdict.text);
assert!(
!verdict.text.contains(UNFIRED),
"an act that crossed did not fail to be sent: {}",
verdict.text
);
assert!(
verdict.text.contains("lernie conversations"),
"the recovery is a read, and it is named: {}",
verdict.text
);
}
#[test]
fn a_box_with_no_channel_says_so_before_it_stages_anything() {
let scratch = Scratch::new();
let verdict = start(scratch.path(), "home", "do it", None, None, Form::Json);
assert_eq!(verdict.code, 1);
assert_eq!(verdict.stream, Stream::Err);
assert!(
verdict.text.contains("no wire provisioned"),
"{}",
verdict.text
);
}
#[test]
fn a_start_with_a_work_target_stages_the_path_rung_and_fires_the_preamble_with_it() {
let scratch = Scratch::new();
let prefilled = json!({"ok": true, "kind": "prepared",
"prepared": {"workspace": "home",
"goal": "Working directory: /w",
"binding": "/w"}});
let engine = wired(
&scratch,
&flat(),
vec![vec![prefilled], vec![started("brisk-otter")]],
);
let verdict = start(
scratch.path(),
"home",
"do the thing",
Some("/w"),
None,
Form::Json,
);
assert_eq!(verdict.code, 0);
let heard = engine.heard();
assert!(
heard.contains(&json!({"op": "prepare", "workspace": "home",
"payload": {"rung": "path", "dir": "/w"}})),
"{heard:?}"
);
assert!(
heard.contains(&json!({"op": "prompt", "seed": null,
"goal": "Working directory: /w\n\ndo the thing",
"prepared": {"workspace": "home",
"goal": "Working directory: /w",
"binding": "/w"}})),
"{heard:?}"
);
}