use concinnity_cook::authoring::registry::RegisteredType;
use concinnity_core::ecs::World;
use crate::editor::hook::EditorHook;
use crate::editor::hook::tests::fixtures::{
click_row, entry, expandable_hook, generated_group, hook, seed_tree, set_field,
world_with_fields,
};
use crate::editor::panels::asset_tree::{self, TreeRow};
use crate::editor::hook::tests::fixtures::entry_target;
use crate::editor::hook::tests::fixtures::{active, selected};
use crate::editor::panels::assets_panel::{self, PanelAction};
use crate::editor::panels::registry::PanelKey;
#[test]
fn tree_rows_group_by_origin_and_narrow_by_search() {
let mut h = hook(vec![entry("lamp", "PointLight"), entry("sign", "Decal")]);
let mut world = world_with_fields();
h.open[PanelKey::Assets] = true;
seed_tree(
&mut h,
vec![generated_group(
"fox",
&[("fox_mat", RegisteredType::Material)],
)],
);
let names = |h: &EditorHook, w: &World| -> Vec<String> {
h.tree_rows(w)
.iter()
.filter_map(|r| match r {
TreeRow::Asset { name, .. } => Some(name.clone()),
_ => None,
})
.collect()
};
assert_eq!(names(&h, &world), ["lamp", "sign", "fox_mat"]);
let headers: Vec<String> = h
.tree_rows(&world)
.iter()
.filter_map(|r| match r {
TreeRow::Header { label, .. } => Some(label.clone()),
_ => None,
})
.collect();
assert_eq!(headers, [asset_tree::WORLD_GROUP, "fox"]);
set_field(&mut world, assets_panel::SEARCH_INPUT, "mat");
assert_eq!(names(&h, &world), ["fox_mat"]);
set_field(&mut world, assets_panel::SEARCH_INPUT, "PointLight");
assert_eq!(names(&h, &world), ["lamp"], "a type match reaches the row");
}
#[test]
fn the_tree_is_cooked_only_while_the_panel_is_up() {
let _guard = crate::test_support::lock();
let mut h = expandable_hook();
h.open[PanelKey::Assets] = false;
assert!(h.assets.stale);
h.refresh_tree_if_needed();
assert!(
h.assets.stale && h.assets.groups.is_empty(),
"a hidden panel does not cook"
);
h.open[PanelKey::Assets] = true;
h.refresh_tree_if_needed();
assert!(!h.assets.stale);
assert!(
!h.assets.groups.is_empty(),
"the injected companions are grouped"
);
assert_eq!(h.assets.status, None);
}
#[test]
fn an_edit_restales_the_tree() {
let _guard = crate::test_support::lock();
let mut h = expandable_hook();
h.refresh_tree_if_needed();
assert!(!h.assets.stale);
h.mark_changed();
assert!(h.assets.stale, "the expansion follows the entries");
h.mark_changed();
h.refresh_tree_if_needed();
assert!(!h.assets.stale, "one refresh covers the burst");
}
#[test]
fn groups_fold_and_unfold() {
let _guard = crate::test_support::lock();
let mut h = expandable_hook();
let world = world_with_fields();
h.refresh_tree_if_needed();
let folded = h.tree_rows(&world).len();
assert_eq!(folded, h.assets.groups.len(), "headers only");
h.apply_panel(PanelAction::ToggleGroup(0), &mut world_with_fields());
assert!(h.tree_rows(&world).len() > folded, "the group unfolded");
h.apply_panel(PanelAction::ToggleGroup(0), &mut world_with_fields());
assert_eq!(h.tree_rows(&world).len(), folded, "and folded again");
}
#[test]
fn tree_row_click_selects_and_opens_the_form() {
let mut world = world_with_fields();
let mut h = hook(vec![entry("box", "Sprite"), entry("cam", "Camera3D")]);
h.open[PanelKey::Assets] = true;
seed_tree(&mut h, Vec::new());
click_row(&mut h, "box", &mut world);
assert_eq!(active(&h).as_deref(), Some("box"));
assert!(
h.open[PanelKey::Assets],
"the assets UI comes up around the form"
);
assert_eq!(
h.form.target,
entry_target(&h, 0),
"the form targets the clicked entry"
);
h.shift_held = true;
click_row(&mut h, "cam", &mut world);
assert_eq!(selected(&h), ["box", "cam"], "a shift click adds");
click_row(&mut h, "cam", &mut world);
assert_eq!(selected(&h), ["box"], "a second shift click removes");
}