The battleground queue slots answer "none" from the first frame, so a party login no longer breaks BattlefieldFrame_Update (#603)

The reference's three queue slots are a static array (`0xb6e9d0`): `GetBattlefieldStatus(1..3)`
always reads one (`0x4ab4df`-`0x4ab4f3`), and a zeroed slot answers "none". The VM held an empty
list until the app's first push, so an in-range index took the off-slot leg and answered a nil
status. A party login fires PARTY_LEADER_CHANGED before that push, `BattlefieldFrame_Update` read
the nil status as queued and concatenated the nil map name (`BattlefieldFrame.lua:242`). The VM
now holds exactly three slots, zeroed until pushed, and the push takes three.

Verified: the new app test fires PARTY_LEADER_CHANGED on the stock BattlefieldFrame before any
push and failed with the reported error before the change; live, Probefive relogged into a stored
party raised the same error on the old build and none on this one (slot 1 reads "none", "Eastern
Kingdoms"), and a solo login after leaving the party is clean. Built on macOS only; no platform
seam.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sam Sung
2026-09-29 15:53:20 +07:00
committed by GitHub
co-authored by Claude Opus 5.5
parent ca7111ed1a
commit e4b06c5c2f
4 changed files with 46 additions and 17 deletions
@@ -77,7 +77,7 @@ fn the_queue_icon_follows_the_slots_across_update_battlefield_status() {
let mut s = session();
assert!(!visible(&s, "MiniMapBattlefieldFrame"), "no queue at load");
s.set_battlefield_queue(vec![slot(529, "Arathi Basin", 1, 0), empty(), empty()], 0);
s.set_battlefield_queue([slot(529, "Arathi Basin", 1, 0), empty(), empty()], 0);
s.fire_event("UPDATE_BATTLEFIELD_STATUS", vec![]);
assert!(
visible(&s, "MiniMapBattlefieldFrame"),
@@ -103,7 +103,7 @@ fn the_queue_icon_follows_the_slots_across_update_battlefield_status() {
assert!(!visible(&s, "StaticPopup1"), "queued is not yet a question");
// Status 2, ready to enter: the confirm dialog and the port countdown.
s.set_battlefield_queue(vec![slot(529, "Arathi Basin", 2, 3), empty(), empty()], 0);
s.set_battlefield_queue([slot(529, "Arathi Basin", 2, 3), empty(), empty()], 0);
s.fire_event("UPDATE_BATTLEFIELD_STATUS", vec![]);
assert!(
visible(&s, "StaticPopup1"),
@@ -127,7 +127,7 @@ fn the_queue_icon_follows_the_slots_across_update_battlefield_status() {
s.run("StaticPopup1Button1:Click()").unwrap();
assert_eq!(s.take_battlefield_port_requests(), vec![(1, true)]);
s.set_battlefield_queue(vec![empty(), empty(), empty()], 0);
s.set_battlefield_queue([empty(), empty(), empty()], 0);
s.fire_event("UPDATE_BATTLEFIELD_STATUS", vec![]);
assert!(
!visible(&s, "MiniMapBattlefieldFrame"),
@@ -154,7 +154,7 @@ fn the_list_window_opens_on_battlefields_show_and_joins_the_selection() {
}),
group_queue: true,
});
s.set_battlefield_queue(vec![empty(), empty(), empty()], 0);
s.set_battlefield_queue([empty(), empty(), empty()], 0);
assert!(!visible(&s, "BattlefieldFrame"));
s.fire_event("BATTLEFIELDS_SHOW", vec![]);
assert!(visible(&s, "BattlefieldFrame"), "the event shows the panel");
@@ -228,7 +228,7 @@ fn the_list_rows_carry_the_queue_status() {
}),
..Default::default()
});
s.set_battlefield_queue(vec![slot(529, "Arathi Basin", 1, 4), empty(), empty()], 0);
s.set_battlefield_queue([slot(529, "Arathi Basin", 1, 4), empty(), empty()], 0);
s.fire_event("BATTLEFIELDS_SHOW", vec![]);
assert_eq!(
s.eval::<String>("return BattlefieldZone2Status:GetText()")
@@ -243,3 +243,14 @@ fn the_list_rows_carry_the_queue_status() {
(`FontString:GetText 0x79d690` substitutes nil)"
);
}
#[test]
fn a_party_leader_change_before_any_queue_push_updates_the_list_cleanly() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = session();
s.take_errors();
// A party login fires PARTY_LEADER_CHANGED, which runs `BattlefieldFrame_Update`; it reads
// `GetBattlefieldStatus(1..3)` and concatenates the name of any status but "none" (line 242).
s.fire_event("PARTY_LEADER_CHANGED", vec![]);
assert_eq!(s.take_errors(), Vec::<String>::new());
}