benilla-app ui_script tests: each checks what it claims, no dead probes (#306)

Test health in `benilla-app`'s `ui_script` tests, found while the crate's comments were rewritten. No shipped code changes.

- `every_texture_frame_outranks_its_status_bars` listed `ManaBar` twice, so its floor of 6 counted each mana pair twice. It checks the two bars of each texture frame once now, with a floor of 4.
- `the_unit_frames_publish_every_name_the_reference_declares` exempted the five `PlayerFrameGroupIndicator*` names, which the stock `PlayerFrame.xml` declares and the loader now builds. The exemption hid their loss and is gone.
- Two tests renamed for what they assert: `escape_closes_bag_and_panel_releases_loot_and_keeps_the_held_item` (ESC keeps the held item, as stock `ToggleGameMenu` has no `ClearCursor`) and `in_flight_roll_opens_without_a_name_or_icon`.
- Dead lines out: two `LOOT_UPDATE` fires (not a 1.12 event; nothing registers it), a read of a Lua global nothing sets, and a string table that the real `GlobalStrings.lua`, loaded right after, overwrote.
- Comments on the camera-style dropdown (`OptionsFrame.xml` and its test) now give 1.12's values as the stock dropdown writes them (`UIOptionsFrame.lua:525,536,547`): Smart 1, Always 2, Never 0. They are not a deviation.

The edited tests pass with the install present (82 run, none skipped) before the land gates.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sam Sung
2026-09-25 17:41:21 +07:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 9863554f69
commit 60f5999e7b
9 changed files with 15 additions and 43 deletions
@@ -901,8 +901,8 @@
return
end
if key == "Controls" then
-- l.715-719: Auto-Follow Speed is dead while the style is Never, "0" in the
-- engine's values and "3" as the reference's dropdown writes it.
-- l.715-719: Auto-Follow Speed is dead while the style is Never: "0", or a stray
-- "3", which the validator also accepts and which reads as Never.
local style = GetCVar("cameraSmoothStyle")
OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyControlsRowAutoFollowSpeed,
style ~= "0" and style ~= "3")
@@ -1703,9 +1703,8 @@
</OnLoad></Scripts>
</Frame>
<!-- 1.12's UIOptionsFrameCameraDropDown, with its
tooltips. Deviation: values are the engine's 0/1/2;
1.12 writes 3 for Never, which its terrain-tilt
consumer reads past its table's end. -->
tooltips and values: Smart 1, Always 2, Never 0
(UIOptionsFrame.lua:525, 536, 547). -->
<Frame name="$parentRowCameraFollowStyle" inherits="OptionsDropdownRowTemplate">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parentRowMouseSpeed" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
@@ -41,7 +41,7 @@ fn one_item_backpack() -> ContainerState {
/// `CloseAllWindows` (`UIParent.lua:1491`) closes the bag and the loot panel, whose `OnHide`
/// releases the loot; with no edit box focused the key is left to the binding.
#[test]
fn escape_closes_bag_and_panel_releases_loot_and_clears_cursor() {
fn escape_closes_bag_and_panel_releases_loot_and_keeps_the_held_item() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
@@ -757,8 +757,6 @@ fn the_menu_rides_the_shared_era_window_scale() {
s.run("ShowUIPanel(GameMenuFrame)").unwrap();
s.resolve();
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
let ran = s.eval::<f64>("return BENILLA_MENU_ONSHOW or -99").unwrap();
println!("handler ran probe: {ran}");
let k = s.eval::<f64>("return GameMenuFrame:GetScale()").unwrap();
let want = s.eval::<f64>("return ERA_WINDOW_SCALE").unwrap();
assert!((k - want).abs() < 1e-6, "menu scale {k} != knob {want}");
@@ -332,7 +332,7 @@ fn cancel_loot_roll_hides_only_that_frame() {
/// A roll with its item template in flight opens without error, with no name and no icon.
#[test]
fn in_flight_roll_does_not_error_and_falls_back() {
fn in_flight_roll_opens_without_a_name_or_icon() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = setup();
load_group_loot(&s);
@@ -30,18 +30,6 @@ fn state() -> HonorState {
}
}
/// The strings the inspect page's titles read, verbatim from 1.12's `GlobalStrings.lua` (`:2795`,
/// `:3075`, `:3150-3161`, `:3297`).
const RANK_GLOBALS: &str = r#"
NONE = "None"
RANK = "Rank"
PLAYER_LEVEL = "Level %d %s %s"
PVP_RANK_12_1 = "Knight-Captain"
PVP_RANK_12_0 = "Legionnaire"
PVP_RANK_14_1 = "Lieutenant Commander"
PVP_RANK_14_0 = "Champion"
"#;
/// The character window, whose fifth tab this page is; [`super::test_ui::CHARACTER_UI`] carries
/// `HonorFrame.xml`, as `PaperDollFrame.lua:103` writes into it on every show.
fn load_page(s: &UiScript) {
@@ -350,7 +338,6 @@ fn inspect_reply() -> InspectHonorData {
fn shown_inspect_honor_page() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
s.run(RANK_GLOBALS).unwrap();
for file in [
"Interface\\FrameXML\\Fonts.xml",
// `TEXT`, the stock level line's formatter.
@@ -221,7 +221,7 @@ fn shipped_loot_frame_drives_end_to_end() {
assert!(!s.take_loot_close());
// The looted coin row hides in place, off `LOOT_SLOT_CLEARED` alone, and the items keep their
// rows; `LOOT_UPDATE` is not a 1.12 event and reaches nothing.
// rows.
let mut coin_looted = coin_and_two_items();
coin_looted.rows[0] = None;
s.set_loot(Some(coin_looted));
@@ -229,7 +229,6 @@ fn shipped_loot_frame_drives_end_to_end() {
"LOOT_SLOT_CLEARED",
vec![benilla_ui::script::ScriptValue::Int(1)],
);
s.fire_event("LOOT_UPDATE", vec![]);
let vis2: (bool, bool, bool) = s
.eval(
"return LootButton1:IsVisible(), LootButton2:IsVisible(),\n\
@@ -401,7 +400,7 @@ fn shipped_loot_frame_pages_five_items() {
assert_eq!(pager2, (true, false), "page 2: Up shown, Down hidden");
// Loot out page 1: it pages down by itself, off `LOOT_SLOT_CLEARED` alone
// (LootFrame.lua:38-50); `LOOT_UPDATE` is not a 1.12 event and reaches nothing.
// (LootFrame.lua:38-50).
s.run("LootFrame_PageUp()").unwrap();
let mut cleared = rows;
cleared[0] = None;
@@ -418,7 +417,6 @@ fn shipped_loot_frame_pages_five_items() {
vec![benilla_ui::script::ScriptValue::Int(row)],
);
}
s.fire_event("LOOT_UPDATE", vec![]);
assert_eq!(
s.eval::<i64>("return LootFrame.page").unwrap(),
2,
@@ -3701,10 +3701,10 @@ fn the_max_camera_distance_slider_stores_a_factor_and_reads_out_yards() {
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
}
/// 1.12's dropdown writes 1/2/3 for `cameraSmoothStyle`, but the engine's tables are 0 Never,
/// 1 Smart, 2 Always: the validator (`0x50c060`) accepts 3 while the terrain-tilt consumer
/// (`0x50dbc0`) reads past its table. The entries carry the engine's values in the reference's
/// order, a stray 3 still reads Never, and the plate follows the selection.
/// 1.12's dropdown writes Smart 1, Always 2 and Never 0 for `cameraSmoothStyle`
/// (`UIOptionsFrame.lua:525,536,547`); the validator (`0x50c060`) also accepts 3, which the
/// terrain-tilt consumer (`0x50dbc0`) reads past its table. The entries carry those values in the
/// reference's order, a stray 3 reads Never, and the plate follows the selection.
#[test]
fn the_camera_following_style_dropdown_carries_the_engine_enum_and_plate() {
benilla_formats::wow_data_or_skip!();
@@ -680,7 +680,7 @@ fn every_texture_frame_outranks_its_status_bars() {
let Some(base) = texture_frame.strip_suffix("TextureFrame") else {
continue;
};
for suffix in ["HealthBar", "ManaBar", "ManaBar"] {
for suffix in ["HealthBar", "ManaBar"] {
let bar = format!("{base}{suffix}");
let Some(&(bar_strata, bar_level)) = level_of.get(&bar) else {
continue;
@@ -699,9 +699,9 @@ fn every_texture_frame_outranks_its_status_bars() {
}
// The reference names two TextureFrames, `TargetFrameTextureFrame` and
// `TargetofTargetTextureFrame` (TargetFrame.xml); the player, pet and party frames nest their
// art in anonymous frames instead. Two families × the three suffixes (ManaBar twice) = 6.
// art in anonymous frames instead: two families with two bars each.
assert!(
checked >= 6,
checked >= 4,
"only {checked} texture-frame/bar pairs checked — the name sweep found nothing"
);
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
@@ -1867,16 +1867,6 @@ fn the_unit_frames_publish_every_name_the_reference_declares() {
missing.push(name);
}
}
// The raid "Group N" tab (`PlayerFrame_UpdateGroupIndicator`, `PlayerFrame.lua:214-232`),
// exempt from the check, though stock `PlayerFrame.xml:359-416` declares all five.
let unbuilt = [
"PlayerFrameGroupIndicator",
"PlayerFrameGroupIndicatorLeft",
"PlayerFrameGroupIndicatorMiddle",
"PlayerFrameGroupIndicatorRight",
"PlayerFrameGroupIndicatorText",
];
missing.retain(|m| !unbuilt.contains(m));
assert!(
missing.is_empty(),
"the reference declares these and we do not publish them — an addon reading any of them \