use super::{AppModel, FakeBl};
use crate::app::Roots;
use crate::git_tree::tests::fixture::Fixture;
use crate::projects::join::JoinState;
use crate::test_support::FakeClock;
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use tempfile::tempdir;
const LIST: &str = r#"[{"id":"bl-work","title":"Work","claimant":"cobalt"}]"#;
fn model() -> (tempfile::TempDir, Fixture, AppModel) {
let root = tempdir().unwrap();
let roots = Roots {
yog_data: root.path().join("yog"),
lernie_data: root.path().join("lernie"),
yog_state: root.path().join("state"),
balls_clones: root.path().join("clones"),
home: root.path().join("home"),
world: crate::test_support::no_world(),
};
std::fs::create_dir_all(roots.balls_clones.join("%2Fproj%2Fa")).unwrap();
std::fs::create_dir_all(&roots.yog_state).unwrap();
std::fs::create_dir_all(roots.yog_data.join("workspaces")).unwrap();
let fx = Fixture::new();
fx.build_agent(
"conv1",
"You are ochre-tern.\n\nBall bl-work: Work\n\ndo the work",
);
fx.build_agent(
"conv2",
"You are jade-vole.\n\nBall bl-ghost: Ghost\n\ngone",
);
fx.build_agent("bare", "You are slate-newt.\n\njust chatting, no ball");
let ws = roots.yog_data.join("workspaces").join("cobalt");
std::os::unix::fs::symlink(&fx.path, &ws).unwrap();
let bl = FakeBl {
live: Arc::new(Mutex::new(HashMap::from([(
PathBuf::from("/proj/a"),
LIST.to_string(),
)]))),
closed: Arc::new(Mutex::new(HashMap::new())),
fail: Arc::new(Mutex::new(HashSet::new())),
};
let (m, _deriver) = AppModel::boot(
roots,
Some(ws),
FakeClock::new().arc(),
Box::new(bl),
Some("me".to_string()),
);
(root, fx, m)
}
fn ball_of(m: &AppModel, root: &str) -> Option<crate::nav::convs::ConvBall> {
crate::test_support::convs::conversations(m, 1000)
.into_iter()
.find(|r| r.root_id == root)
.and_then(|r| r.ball)
}
#[test]
fn a_conversation_row_carries_its_goal_stamp_ball_coloured_by_the_join() {
let (_root, _fx, m) = model();
let bound = ball_of(&m, "conv1").expect("conv1's stamped ball");
assert_eq!(bound.id, "bl-work");
assert_eq!(bound.state, Some(JoinState::Bound));
assert_eq!(bound.title.as_deref(), Some("Work"));
assert_eq!(bound.badge, None, "a Bound ball needs no badge");
let ghost = ball_of(&m, "conv2").expect("conv2's stamped ball renders from source 1");
assert_eq!(ghost.id, "bl-ghost");
assert_eq!(ghost.state, None);
assert_eq!(ghost.title, None);
assert!(ball_of(&m, "bare").is_none(), "no stamp, no ball");
}
#[test]
fn the_conversation_mint_reads_its_occupied_set_off_the_stamped_roots() {
let (root, _fx, m) = model();
let ws = m.focused_workspace().expect("cobalt is focused").clone();
let mut names = crate::boundary::answer::names_in(&m.snap, &ws);
names.sort();
assert_eq!(names, ["jade-vole", "ochre-tern", "slate-newt"]);
assert!(
crate::boundary::answer::names_in(&m.snap, &root.path().join("nowhere")).is_empty(),
"no tree, no occupied names"
);
let mut seat =
crate::nav::convs::names_in_rows(&crate::test_support::convs::conversations(&m, 1000));
seat.sort();
assert_eq!(seat, names, "one occupied set, two projections");
}
#[test]
fn the_header_ball_and_the_groups_are_one_answers_own_field() {
let (_root, _fx, m) = model();
let rows = crate::test_support::convs::conversations(&m, 1000);
let header = crate::nav::convs::selection(&rows, "conv1")
.ball
.expect("conv1 header ball");
assert_eq!(header.id, "bl-work");
assert_eq!(header.state, Some(JoinState::Bound));
assert!(
crate::nav::convs::selection(&rows, "bare").ball.is_none(),
"no stamp, no header ball"
);
assert!(
crate::nav::convs::selection(&rows, "nonexistent")
.ball
.is_none(),
"an unknown root has no ball"
);
let groups = crate::nav::convs::group::group_by_ball(rows);
let work = groups
.iter()
.find(|g| g.ball.as_ref().map(|b| b.id.as_str()) == Some("bl-work"))
.expect("a group headed by bl-work");
assert!(work.convs.iter().any(|c| c.root_id == "conv1"));
let bare_group = groups
.iter()
.find(|g| g.ball.is_none())
.expect("the trailing unassociated group");
assert!(bare_group.convs.iter().any(|c| c.root_id == "bare"));
assert_eq!(
groups.last().map(|g| g.ball.is_none()),
Some(true),
"unassociated conversations group last"
);
}