edit boxes take focus the way 1.12 does, and the stable shows its pets
- the caret was a wedge in the line: it sat in flow, four units wide, so focusing a login box shoved its text right by one caret and a caret parked mid-word opened a gap; it is a zero-width seam now with the bar drawn as an overlay (a 0×26 seam and a 5×26 bar at the same x, off a node probe), the way the reference anchors its caret quad over the FontString; a blurred box collapses its selection so only the box holding the keyboard shows one; and a dialog answers only keys pressed while it was already on screen — ENTER on an empty form used to open the error dialog and close it in the same frame - `autoFocus` defaults ON in the reference (the ctor leaves flags = 1, and every one of the ten `autoFocus` attributes in the shipped chain is an opt-out), showing an autoFocus box focuses it after its `OnShow`, and hiding the focused box releases the keyboard — the "never focuses on show" note we had transcribed came from a `call`-only census that missed a tail `jmp`; the loader's flag loop could only ever turn a flag on, so `autoFocus="false"` was a no-op, fixed before the default flipped or it would have grabbed exactly the ten boxes the reference exempts; and the EditBox does fire generic `OnChar` with the spliced string, on every typed or pasted character and never on `SetText` - the stable master's portrait was a black disc (its session was missing from the `"npc"` token chain — the third window to ship that way, so the test is now exhaustive over every `impl NpcSession` and names the one you forgot) and its model pane draws the selected pet: a stabled pet is a database row with no world entity, so a `PortraitStandIn(display_id)` — an entity that exists only to be mirrored — feeds the existing booth code unchanged; plus the registrar's two service rows were hidden by an inherited attribute, a charter's tooltip carries the guild name and master on line 3, and the Help window drops three strings pointing at a company that stopped answering Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -812,6 +812,7 @@ fn shipped_bag_frame_drives_end_to_end() {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
|
||||
@@ -435,6 +435,7 @@ fn bag_tooltip_hangs_left_when_the_slot_sits_in_the_right_half() {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
@@ -516,6 +517,7 @@ fn hovered_bag_tooltip_fills_itself_when_the_stats_land() {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
@@ -625,6 +627,7 @@ fn vendor_bag_hover_shows_sell_price_and_arms_the_pouch_cursor() {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
@@ -645,6 +648,7 @@ fn vendor_bag_hover_shows_sell_price_and_arms_the_pouch_cursor() {
|
||||
slots.insert(
|
||||
2,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
@@ -841,6 +845,7 @@ fn drag_across_two_slots_queues_the_same_move_a_click_pickup_would() {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
@@ -930,6 +935,7 @@ fn a_second_bag_window_feeds_and_paints_via_the_bag_bar() {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
@@ -1062,6 +1068,7 @@ fn open_backpack_with_a_five_stack(s: &mut UiScript) -> (f32, f32) {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
|
||||
@@ -107,6 +107,7 @@ fn backpack_with_fitting_helm() -> benilla_ui::script::ContainerState {
|
||||
slots.insert(
|
||||
1,
|
||||
benilla_ui::script::ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
|
||||
@@ -319,6 +319,7 @@ fn chat_click_dismisses_a_stuck_spell_but_not_an_item() {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
|
||||
@@ -32,6 +32,7 @@ fn one_item_backpack() -> ContainerState {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
|
||||
@@ -25,6 +25,7 @@ fn one_item_backpack() -> ContainerState {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
@@ -237,6 +238,7 @@ fn escape_closes_an_open_stack_split_frame() {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
|
||||
@@ -700,6 +700,7 @@ fn backpack() -> ContainerState {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
|
||||
@@ -376,6 +376,59 @@ fn auto_unstuck_casts_and_closes() {
|
||||
assert!(!s.eval::<bool>("return HelpFrame:IsVisible()").unwrap());
|
||||
}
|
||||
|
||||
/// **The retail-only text is gone from the Home page** (director's call, 2026-08-29).
|
||||
///
|
||||
/// The page is entirely GlobalStrings off the player's own chain, so three of its strings still
|
||||
/// pointed at `worldofwarcraft.com` — a dead PvP-policy link, and a closing paragraph directing the
|
||||
/// player to Blizzard's forums and policy pages. The window overrides them before the markup
|
||||
/// resolves.
|
||||
///
|
||||
/// This test exists because the failure mode is *invisible in a test suite*: nothing breaks if the
|
||||
/// override is dropped, the page simply starts advertising dead links again. Asserted on the
|
||||
/// rendered FontStrings rather than the globals, so it also catches the markup being re-pointed at
|
||||
/// a different key.
|
||||
#[test]
|
||||
fn the_home_page_advertises_no_dead_retail_links() {
|
||||
let s = setup();
|
||||
s.run("ShowUIPanel(HelpFrame) HelpFrame_ShowFrame(\"Home\")")
|
||||
.unwrap();
|
||||
|
||||
for frame in [
|
||||
"HelpFrameHomePvpPolicyUrl",
|
||||
"HelpFrameHomeText2",
|
||||
"HelpFrameHomeIssue3",
|
||||
"HelpFrameHomeText1",
|
||||
] {
|
||||
let text = s
|
||||
.eval::<String>(&format!("return {frame}:GetText() or \"\""))
|
||||
.unwrap()
|
||||
.to_lowercase();
|
||||
for dead in [
|
||||
"worldofwarcraft.com",
|
||||
"http://",
|
||||
"www.",
|
||||
".shtml",
|
||||
"the forums",
|
||||
] {
|
||||
assert!(
|
||||
!text.contains(dead),
|
||||
"{frame} still carries retail-only text ({dead:?}): {text:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// The PvP guidance itself is KEPT — only the sentence introducing the link went. A test that
|
||||
// let the whole bullet be emptied would pass on an over-correction, which is the other way to
|
||||
// get this wrong.
|
||||
let pvp = s
|
||||
.eval::<String>("return HelpFrameHomeIssue3:GetText()")
|
||||
.unwrap();
|
||||
assert!(
|
||||
pvp.contains("PVP game mechanics"),
|
||||
"the PvP guidance must survive the link's removal: {pvp:?}"
|
||||
);
|
||||
}
|
||||
|
||||
/// **The geometry oracle** (decision 0675): every element the transcription shares with the
|
||||
/// reference file carries the reference's own `<AbsDimension>` numbers.
|
||||
///
|
||||
|
||||
@@ -187,6 +187,22 @@ fn a_signers_charter_shows_the_sign_face_and_nine_rows() {
|
||||
);
|
||||
}
|
||||
|
||||
// The charter's own static furniture — the three labels, the nine rows and the instructions
|
||||
// all draw, not merely hold text.
|
||||
for part in [
|
||||
"PetitionFrameCharterTitle",
|
||||
"PetitionFrameCharterName",
|
||||
"PetitionFrameMasterTitle",
|
||||
"PetitionFrameMasterName",
|
||||
"PetitionFrameMemberTitle",
|
||||
"PetitionFrameMemberName1",
|
||||
"PetitionFrameMemberName9",
|
||||
"PetitionFrameInstructions",
|
||||
"PetitionFrameCancelButton",
|
||||
"PetitionFrameCloseButton",
|
||||
] {
|
||||
assert!(visible(&s, part), "{part} is on screen");
|
||||
}
|
||||
assert!(visible(&s, "PetitionFrameSignButton"));
|
||||
assert!(!visible(&s, "PetitionFrameRequestButton"));
|
||||
assert!(
|
||||
@@ -348,6 +364,16 @@ fn the_registrar_opens_on_services_and_purchase_is_a_local_panel_swap() {
|
||||
assert!(visible(&s, "GuildRegistrarFrame"));
|
||||
assert!(visible(&s, "GuildRegistrarGreetingFrame"));
|
||||
assert!(!visible(&s, "GuildRegistrarPurchaseFrame"));
|
||||
// **The two service rows must be VISIBLE, not merely labelled.** This assertion is here
|
||||
// because its absence shipped the bug: the rows inherited `hidden="true"` from a template
|
||||
// modelled on the quest list's POOLED rows, which are shown one at a time by code. These are
|
||||
// static and nothing ever calls `:Show()` on them, so both were permanently invisible — the
|
||||
// window came up as a bare "Available Services" heading over blank parchment — while every
|
||||
// `GetText()` assertion below passed, because a hidden button still knows its own label.
|
||||
// Decision 0672's lesson in another key: a frame that loads is not a frame that draws.
|
||||
for row in ["GuildRegistrarButton1", "GuildRegistrarButton2"] {
|
||||
assert!(visible(&s, row), "{row} is on screen, not just loaded");
|
||||
}
|
||||
assert_eq!(
|
||||
text(&s, "GuildRegistrarButton1"),
|
||||
"Purchase a Guild Charter"
|
||||
@@ -361,6 +387,18 @@ fn the_registrar_opens_on_services_and_purchase_is_a_local_panel_swap() {
|
||||
s.run("GuildRegistrarButton1:Click()").unwrap();
|
||||
assert!(visible(&s, "GuildRegistrarPurchaseFrame"));
|
||||
assert!(!visible(&s, "GuildRegistrarGreetingFrame"));
|
||||
// The purchase panel's own furniture, for the reason the services rows above are checked: a
|
||||
// window whose parts load but do not draw passes every text assertion.
|
||||
for part in [
|
||||
"GuildRegistrarPurchaseText",
|
||||
"GuildRegistrarCostLabel",
|
||||
"GuildRegistrarMoneyFrame",
|
||||
"GuildRegistrarFrameEditBox",
|
||||
"GuildRegistrarFramePurchaseButton",
|
||||
"GuildRegistrarFrameCancelButton",
|
||||
] {
|
||||
assert!(visible(&s, part), "{part} is on screen");
|
||||
}
|
||||
assert_eq!(calls(&s), "", "the swap sends nothing");
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ fn seed_items(s: &mut UiScript) {
|
||||
slots.insert(
|
||||
1,
|
||||
ContainerSlot {
|
||||
petition: None,
|
||||
already_bound: false,
|
||||
bar_placeable: true,
|
||||
durability: None,
|
||||
|
||||
Reference in New Issue
Block a user