Files
benilla-octo/crates/benilla-app/src/ui_script/minimap_tests.rs
T
SamandClaude Fable 5 3b6975fdef the pet gets its frame, flooded rooms fill, and macros really fire
- the pet gets its own unit frame beside yours, and an Attack order no longer latches as the standing command
- five rooms that always read bone dry hold their water now, the Deeprun Tram's flooded stretches among them
- macros fire through the client's own chat door, and the macro window fits its tabs and scrolls its icon chooser
- the options window grows a Nameplates page and its first dropdown, and the name-display switches apply live in the world

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 19:03:43 +07:00

128 lines
5.3 KiB
Rust

//! The shipped `MinimapCluster.xml` driven engine-only: the +/- zoom buttons must re-sync their
//! enabled state when the active zoom index switches (stepping inside/outside a WMO flips to the
//! other, independent level). Regression guard for the director-caught stale-button bug (2026-07-09):
//! `ZoomIn` greyed from an outdoor max-zoom stayed greyed indoors at the middle default level.
use benilla_ui::script::UiScript;
/// Load one shipped `assets/ui/<file>` into `s`, panicking on any loader error (the other tests'
/// loader, duplicated so this file is self-contained).
fn load_xml(s: &UiScript, file: &str) {
let text = std::fs::read_to_string(
std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("assets/ui")
.join(file),
)
.unwrap();
let doc = benilla_ui::framexml::parse(&text).unwrap();
let report = benilla_ui::loader::load(s, &doc, &|_| None);
assert!(
report.errors.is_empty(),
"{file}: loader errors: {:?}",
report.errors
);
}
fn enabled(s: &UiScript, button: &str) -> bool {
s.eval::<bool>(&format!("return {button}:IsEnabled()"))
.unwrap()
}
#[test]
fn minimap_zoom_buttons_resync_when_switching_inside_and_outside() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
// Host globals the cluster's OnLoad/clicks lean on that a bare engine doesn't install.
s.run("function GetMinimapZoneText() return '' end")
.unwrap();
s.run("function PlaySound() end").unwrap();
load_xml(&s, "Fonts.xml");
// The shipped load order provides GameTooltip before the cluster; Minimap_Update's verbatim
// ref block (the PVP tint slice, decision 0287) touches it from OnLoad on.
load_xml(&s, "GameTooltip.xml");
load_xml(&s, "MinimapCluster.xml");
// OnLoad seeds the +/- state from the live zoom. The CVar default is 3 — a middle level, so
// BOTH buttons start enabled (the old hardcoded `MinimapZoomOut:Disable()` assumed zoom 0).
assert_eq!(s.eval::<u8>("return Minimap:GetZoom()").unwrap(), 3);
assert!(enabled(&s, "MinimapZoomIn"));
assert!(enabled(&s, "MinimapZoomOut"));
// Outdoors, zoom fully in (index 5 = max): the click handler greys ZoomIn.
s.run("Minimap:SetZoom(5)").unwrap();
s.fire_event("MINIMAP_UPDATE_ZOOM", vec![]);
assert!(!enabled(&s, "MinimapZoomIn"), "at max zoom ZoomIn disables");
assert!(enabled(&s, "MinimapZoomOut"));
// Step INSIDE: the API now routes to the indoor index, still at its own untouched default 3.
// The app fires MINIMAP_UPDATE_ZOOM on the transition; the cluster must re-sync to the new level.
s.set_minimap_inside(true);
s.fire_event("MINIMAP_UPDATE_ZOOM", vec![]);
assert_eq!(
s.eval::<u8>("return Minimap:GetZoom()").unwrap(),
3,
"indoors reads the separate indoor index"
);
assert!(
enabled(&s, "MinimapZoomIn"),
"the stale outdoor max-zoom greying must clear — this is the reported bug"
);
assert!(enabled(&s, "MinimapZoomOut"));
// Indoors, zoom fully out (index 0 = widest): ZoomOut greys.
s.run("Minimap:SetZoom(0)").unwrap();
s.fire_event("MINIMAP_UPDATE_ZOOM", vec![]);
assert!(
!enabled(&s, "MinimapZoomOut"),
"at min zoom ZoomOut disables"
);
assert!(enabled(&s, "MinimapZoomIn"));
// Step back OUTSIDE: the outdoor index is exactly where we left it (5 = max), so ZoomIn is
// greyed again and the indoor min-zoom greying of ZoomOut is gone.
s.set_minimap_inside(false);
s.fire_event("MINIMAP_UPDATE_ZOOM", vec![]);
assert_eq!(s.eval::<u8>("return Minimap:GetZoom()").unwrap(), 5);
assert!(!enabled(&s, "MinimapZoomIn"), "outdoor max-zoom survived");
assert!(enabled(&s, "MinimapZoomOut"));
}
/// The tracking icon (ref-Minimap.xml l.109-174, transcribed verbatim): hidden at load, and the
/// verbatim OnEvent follows `GetTrackingTexture()` across `PLAYER_AURAS_CHANGED` — the event the
/// aura feed fires beside `UNIT_AURA` on every display-state change (`ui_aura`). Show with a
/// tracking state pushed, hide when it clears.
#[test]
fn tracking_frame_follows_get_tracking_texture_across_player_auras_changed() {
use benilla_ui::script::TrackingState;
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
s.run("function GetMinimapZoneText() return '' end")
.unwrap();
s.run("function PlaySound() end").unwrap();
load_xml(&s, "Fonts.xml");
load_xml(&s, "GameTooltip.xml");
load_xml(&s, "MinimapCluster.xml");
let vis = |s: &UiScript| {
s.eval::<bool>("return MiniMapTrackingFrame:IsVisible()")
.unwrap()
};
assert!(!vis(&s), "no tracking at load — the frame starts hidden");
// The feed pushes a tracking aura (a miner's Find Minerals) and fires the rebuild event.
s.set_tracking(Some(TrackingState {
spell_id: 2580,
name: Some("Find Minerals".into()),
icon: Some("Interface\\Icons\\Trade_Mining".into()),
cancelable: true,
}));
s.fire_event("PLAYER_AURAS_CHANGED", vec![]);
assert!(vis(&s), "a live tracking texture shows the icon");
// Tracking cancelled/expired: the same event path hides it.
s.set_tracking(None);
s.fire_event("PLAYER_AURAS_CHANGED", vec![]);
assert!(!vis(&s), "no tracking texture hides the frame again");
}