use super::TEMPLATE_PROVIDERS;
use crate::model_pick::{
ConfigPoint, NEW_CONVERSATION_EXIT, birth_row, conversation_row, row_role,
};
fn governing() -> ConfigPoint {
point("1a2b3c4dfeed", "1a2b3c4d", TEMPLATE_PROVIDERS)
}
fn point(oid: &str, short_oid: &str, providers_yaml: &str) -> ConfigPoint {
ConfigPoint {
oid: oid.to_string(),
short_oid: short_oid.to_string(),
providers_yaml: providers_yaml.to_string(),
}
}
fn advanced(model: &str) -> ConfigPoint {
point(
"9f8e7d6cbeef",
"9f8e7d6c",
&TEMPLATE_PROVIDERS.replace("model: gpt-5.4\n", &format!("model: {model}\n")),
)
}
#[test]
fn the_row_is_the_pair_and_the_freeze_rides_the_hover() {
let gov = governing();
let row = conversation_row(&gov, &gov, "worker");
assert_eq!(row.provider, "codex");
assert_eq!(row.model, "gpt-5.4");
assert!(!row.drifted());
assert!(row.hover.contains("1a2b3c4d"));
assert!(row.hover.contains("next conversation"));
assert!(row.hover.contains("frozen"));
}
#[test]
fn the_dropdowns_show_the_tip_the_pick_advances_not_the_frozen_pair() {
let row = conversation_row(&governing(), &advanced("gpt-5.6-sol"), "worker");
assert_eq!(row.model, "gpt-5.6-sol");
}
#[test]
fn an_advanced_workspace_default_names_the_frozen_pair_beside_it() {
let row = conversation_row(&governing(), &advanced("gpt-5.6-sol"), "worker");
assert_eq!(
row.drift.as_deref(),
Some("this conversation is frozen on codex · gpt-5.4 at 1a2b3c4d")
);
assert!(row.drifted());
}
#[test]
fn a_moved_default_carrying_the_same_model_still_drifts() {
let row = conversation_row(&governing(), &advanced("gpt-5.4"), "worker");
assert!(row.drifted());
assert!(
row.drift
.unwrap_or_default()
.contains("gpt-5.4 at 1a2b3c4d")
);
}
#[test]
fn a_conversation_on_the_current_default_carries_no_clause() {
let gov = governing();
assert!(conversation_row(&gov, &gov, "worker").drift.is_none());
}
#[test]
fn a_row_for_an_undeclared_role_paints_the_absence() {
let row = conversation_row(&governing(), &governing(), "nonesuch");
assert_eq!(row.provider, "(none)");
assert_eq!(row.model, "(none)");
let empty = point("bbb", "abc", "");
let row = conversation_row(&empty, &empty, "worker");
assert_eq!(row.model, "(none)");
}
#[test]
fn the_exit_label_promises_a_new_conversation_not_adoption() {
assert!(NEW_CONVERSATION_EXIT.contains("new conversation"));
assert!(NEW_CONVERSATION_EXIT.contains("current config"));
}
#[test]
fn the_birth_row_names_the_pair_and_the_branch_head_it_forks() {
let row = birth_row(&governing(), "worker", "default");
assert_eq!(
(row.provider.as_str(), row.model.as_str()),
("codex", "gpt-5.4")
);
assert!(row.drift.is_none());
assert!(row.hover.contains("forks the head of config/default"));
assert!(row.hover.contains("1a2b3c4d"));
assert!(row.hover.contains("no per-conversation config"));
}
#[test]
fn a_birth_tip_with_no_worker_role_still_paints_the_row() {
let none = point(
"aaa",
"abc",
"roles:\n compactor:\n provider: p\n model: m\n",
);
assert_eq!(birth_row(&none, "worker", "default").provider, "(none)");
}
#[test]
fn the_bare_row_reports_the_worker_role() {
assert_eq!(row_role(None), "worker");
assert_eq!(row_role(Some("compactor")), "compactor");
}