use super::fixture::{self, world};
use super::painted;
use crate::cli_outbound::Cli;
use crate::keymap::{CenterTab, InspectorTab};
#[test]
fn full_window_reaches_every_data_surface() {
let (lernie, bl) = (Cli::new("lernie"), Cli::new("bl"));
let mut world = world();
let ws = world.ws.clone();
world.model.focus_agent(&ws, "c-1");
world.state.inspector.step_sel = Some(0);
world.model.select_tab(InspectorTab::Transcript);
let base = painted(&mut world, &lernie, &bl);
assert!(base.contains("need attention"), "attention strip:\n{base}");
assert!(
base.contains("⏭ next"),
"the jump-to-next-attention control"
);
assert!(
base.lines().any(|line| line == "new"),
"the tab bar's new mint"
);
assert!(base.contains('⋯'), "the foreign/replay overflow menu");
assert!(
base.contains("Workspaces:"),
"the tab bar's own label:\n{base}"
);
assert!(
base.contains("new conversation"),
"the list's new-conversation affordance"
);
assert!(base.contains("balls"), "the collapsible balls section");
assert!(base.contains("⚙ Config"), "Config entry");
assert!(
base.contains("→ message hello"),
"composer names the selected conversation:\n{base}"
);
assert!(
!base.contains("→ message c-1"),
"the raw agent id must not reach the composer:\n{base}"
);
assert!(base.contains("Message"), "message verb:\n{base}");
assert!(base.contains("activity · 0 ops"), "activity chip:\n{base}");
assert!(
!base.contains("a model call is streaming"),
"an idle conversation paints no in-flight strip:\n{base}"
);
assert!(base.contains("c-1"), "conversation row / header");
assert!(base.contains("budget"), "budget-spent header");
assert!(
base.contains("failed on credentials"),
"auth banner:\n{base}"
);
assert!(base.contains("Login (bz browser sign-in)"), "login surface");
assert!(
base.contains("auth none · no credential needed"),
"a keyless row's credential fact:\n{base}"
);
assert!(
base.contains("keyless — nothing to log in"),
"and the reason it offers no Login:\n{base}"
);
assert!(
base.contains("please ping"),
"transcript delivered:\n{base}"
);
assert!(base.contains("pong reply"), "transcript model reply");
world.model.select_tab(InspectorTab::Steps);
world.state.inspector.step_tab = crate::steps_view::StepTab::Tools;
let steps = painted(&mut world, &lernie, &bl);
assert!(steps.contains("Tokens"), "steps token column:\n{steps}");
assert!(steps.contains("toolu_1"), "steps tool i/o");
world.model.select_tab(InspectorTab::Inbox);
let inbox = painted(&mut world, &lernie, &bl);
assert!(inbox.contains("follow-up message"), "inbox deposit");
assert!(inbox.contains("Scan"), "scan verb:\n{inbox}");
world.model.select_tab(InspectorTab::Files);
world.state.inspector.eph.files_sel = Some(0);
let files = painted(&mut world, &lernie, &bl);
assert!(
files.contains("goal.md"),
"files worktree listing:\n{files}"
);
assert!(files.contains("hello"), "goal.md preview:\n{files}");
world.model.select_tab(InspectorTab::Config);
assert!(
painted(&mut world, &lernie, &bl).contains("policy frozen at"),
"governing config"
);
crate::shell::center::focus(&world.model, &mut world.state, CenterTab::Config);
let editors = painted(&mut world, &lernie, &bl);
assert!(
editors.contains("brazen config.toml"),
"brazen editor:\n{editors}"
);
assert!(
editors.contains("lernie global config"),
"lernie-global editor"
);
assert!(
editors.contains("workspace config branches"),
"config-branch editor"
);
assert!(editors.contains("config/default"), "config branch listing");
}
#[test]
fn the_composer_names_the_conversation_never_the_agent_id() {
let (lernie, bl) = (Cli::new("lernie"), Cli::new("bl"));
let mut world = fixture::world_titled("You are stench-pug.\n\nfix the gate");
let ws = world.ws.clone();
world.model.focus_agent(&ws, "c-1");
let out = painted(&mut world, &lernie, &bl);
assert!(
out.contains("→ message stench-pug"),
"the stamped name is the target line:\n{out}"
);
assert!(
out.lines().any(|line| line == "message stench-pug"),
"and the box's hint is the same fact:\n{out}"
);
assert!(
!out.contains("→ message c-1"),
"no raw agent id in the composer:\n{out}"
);
}
#[test]
fn a_driver_that_dies_after_launch_banners_on_the_sweep_that_folds_its_sink() {
let (lernie, bl) = (Cli::new("lernie"), Cli::new("bl"));
let mut world = world();
let ws = world.ws.clone();
world.model.focus_agent(&ws, "c-1");
crate::opslog::append(
world.model.state_root(),
&crate::opslog::OpEntry {
ts: "17".into(),
argv: vec![
"lernie".into(),
"prompt".into(),
ws.to_string_lossy().into_owned(),
"yo".into(),
],
cwd: ws.to_string_lossy().into_owned(),
exit: crate::opslog::DETACHED_EXIT,
stdout: String::new(),
stderr: String::new(),
origin: crate::opslog::Origin::Conversation,
},
)
.unwrap();
world.model.after_lernie_verb();
world.converge();
let quiet = painted(&mut world, &lernie, &bl);
assert!(
!quiet.contains("was retired"),
"a live launch is not a failure:\n{quiet}"
);
let sink = crate::opslog::detached::sink(world.model.state_root(), "17", &ws);
std::fs::create_dir_all(sink.parent().unwrap()).unwrap();
std::fs::write(&sink, "lernie prompt: config: action was retired\n").unwrap();
world.model.after_lernie_verb();
world.converge();
let banner = painted(&mut world, &lernie, &bl);
assert!(
banner.contains("was retired"),
"the dead driver's stderr tail reaches the paint layer:\n{banner}"
);
assert!(
banner.contains("⚠ lernie prompt"),
"with the attempted argv:\n{banner}"
);
}