diff --git a/crates/benilla-app/assets/ui/ContainerFrameAdapters.xml b/crates/benilla-app/assets/ui/ContainerFrameAdapters.xml index ef047402..d2b71067 100644 --- a/crates/benilla-app/assets/ui/ContainerFrameAdapters.xml +++ b/crates/benilla-app/assets/ui/ContainerFrameAdapters.xml @@ -45,12 +45,6 @@ on — hovering an ordinary bag slot — runs the real client's code, unedited. ── Named, not hidden: what still does not work through the sourced files ──────────────────── - · `MerchantItemButton_OnClick`. The reference's `ContainerFrameItemButton_OnClick` closes its - shift-right-click-at-a-vendor arm with a `SplitStack` closure that calls that global, and - benilla's merchant window publishes `BenillaMerchantItem_OnClick` instead. Confirming a stack - split with a vendor open therefore raises. That is the same "a Benilla name shadows the - reference's" class this whole seam exists to close, one window over, and it is left loud - rather than guarded (1203): the fix is to publish the merchant global, not to hide the call. · `REPAIR_COST` is read by the reference's repair-mode arm. It is a `GlobalStrings.lua` key and this client sources that file too, so it resolves at runtime — and the arm is unreachable today regardless, since `GameTooltip:SetBagItem`'s repairCost is an INTERIM 0. diff --git a/crates/benilla-app/assets/ui/GameMenuFrame.xml b/crates/benilla-app/assets/ui/GameMenuFrame.xml index 7911677b..41c37c41 100644 --- a/crates/benilla-app/assets/ui/GameMenuFrame.xml +++ b/crates/benilla-app/assets/ui/GameMenuFrame.xml @@ -30,9 +30,9 @@ Options", SOUNDOPTIONS_MENU "Sound Options", UIOPTIONS_MENU "Interface Options", MACROS "Macros", LOGOUT "Logout", EXIT_GAME "Exit Game", RETURN_TO_GAME "Return to Game", MAIN_MENU "Main Menu". Declared as the real globals - (they are addon-visible API, decision 0068) and read back into each button's label in its - OnLoad — the ref's `text="LOGOUT"` attribute IS a global lookup, which this engine's - literal `text=` is not. + (they are addon-visible API, decision 0068) and carried on each button's own + `text=` attribute — which this engine resolves as a global-string lookup exactly as + the reference does (decision 0995, `loader/widgets.rs`'s `resolve_text`). · **The sounds** — the ref's own OnClick lines: igMainMenuOption (the five option buttons), igMainMenuLogout, igMainMenuQuit, igMainMenuContinue. All four kits verified present in SoundEntries.dbc (patch-2.MPQ) alongside the igMainMenuOpen/Close pair already in use. @@ -94,10 +94,9 @@ scripts, so it never actually moves). `frameStrata="DIALOG"` is what puts it over the world UI, and that is kept. **The "no frame-level raise" half of that reason is gone**: the raise law is built - (`script::object::toplevel`, wow-re `ui/scratch/toplevel-raise.md`) and the loader honours - `toplevel="true"`. Re-adding it here is a one-word change and would make the Esc menu come - to the front over any other DIALOG-strata frame it overlaps; left off pending the - director's call on the look, not on the mechanism. + (`script::object::toplevel`, wow-re `ui/scratch/toplevel-raise.md`), the loader honours + `toplevel="true"`, and the frame below carries it — so the Esc menu does come to the + front over any other DIALOG-strata frame it overlaps. --> - + diff --git a/crates/benilla-app/assets/ui/benilla.toc b/crates/benilla-app/assets/ui/benilla.toc index ff39d5b1..49863ce4 100644 --- a/crates/benilla-app/assets/ui/benilla.toc +++ b/crates/benilla-app/assets/ui/benilla.toc @@ -174,9 +174,10 @@ Interface\FrameXML\MoneyFrame.xml # It is groundwork rather than a window, and the windows it is groundwork FOR are named so the # next session does not have to re-derive it: stock `TradeFrame.xml` and `MailFrame.xml` both build # their amount entry from this template and call `MoneyInputFrame_SetMode`/`_GetCopper`/ -# `_SetCopper`/`_ClearFocus`/`_SetTextColor`/`_SetOnvalueChangedFunc` — six of the names below — -# and neither can be sourced until they exist. (Trade still needs four ENGINE verbs beyond this: -# `AddTradeMoney`, `GetCursorMoney`, `GetTradePlayerItemLink`, `GetTradeTargetItemLink`.) +# `_SetCopper`/`_ClearFocus`/`_SetTextColor`/`_SetOnvalueChangedFunc` — six of the names below. +# Both windows are migrated now: `MailFrame.xml` at l.897 and `TradeFrame.xml` at l.906, the +# latter once 1966 bound the four engine verbs it also needed (`AddTradeMoney`, +# `GetCursorMoney`, `GetTradePlayerItemLink`, `GetTradeTargetItemLink`). # # **TWO entries, and the `.lua` was missing.** This `.xml` declares only the template and does not # source its `.lua`; the reference's toc lists both (l.11-12). Listing the `.xml` alone brought the @@ -489,8 +490,8 @@ Interface\FrameXML\MainMenuBarMicroButtons.xml Interface\FrameXML\BattlefieldFrame.xml # Minimap.xml + Minimap.lua: the cluster around the engine-rendered widget hole # (`crate::minimap` fills it), the zone text, the zoom buttons, the tracking / mail / meeting -# stone / battlefield icons, and `MiniMapPing` — a this engine draws no pixels for; the -# app's ping sprite (`minimap/ping.rs`) follows that frame's own show/hide and alpha, so the +# stone / battlefield icons, and `MiniMapPing` — a that renders its own MinimapPing.mdx +# since 2013; `minimap/ping.rs` keeps the pin, the click seat and the wire half, so the # 5 s lifetime is this file's, as the reference's is. After GameTooltip (the zone-text hover). # 0203's transcription is gone. Interface\FrameXML\Minimap.xml @@ -579,8 +580,8 @@ Interface\FrameXML\ColorPickerFrame.xml # s its own blip templates (WorldMapFrameTemplates.xml) before the frames that inherit # them. Its player arrow is the Create/Position/Show/UpdateWorldMapArrowFrames family # (`script/worldmap_arrow.rs`), an anonymous Model pane the app draws as the minimap's arrow -# sprite; its WorldMapPing is a MinimapPing.mdx Model pane this engine holds and draws nothing -# into (named gap, 1980). +# sprite; its WorldMapPing is the same MinimapPing.mdx Model pane, which draws its own file on +# the map sheet since 2013 (closing the gap 1980 named). Interface\FrameXML\WorldMapFrame.xml # ══ THE CAST BAR — the reference's own, off the player's chain (1751) ══ # `CastingBarFrame` + its Border/Flash/Spark/Text children, driven by the SPELLCAST_* events @@ -964,7 +965,7 @@ Interface\FrameXML\BankFrame.xml # a `CSimpleFrame` and nothing else, so it is `FrameKind::Frame` and the route lines stay what the # reference makes them: plain `` children rotated by an 8-argument `SetTexCoord`. # -# Pulls only `TaxiFrame.lua`, and still needs only Fonts/UiPanels/GameTooltip (SetTooltipMoney), +# Pulls only `TaxiFrame.lua`, and still needs only Fonts/UIParent/GameTooltip (SetTooltipMoney), # all loaded above — so it keeps its seat in the "NPC session windows grouped" cluster. Interface\FrameXML\TaxiFrame.xml # The stable-master window (decision 1676): the hunter's three-slot pet stable over the stable @@ -1186,8 +1187,8 @@ Interface\FrameXML\TutorialFrame.xml # options family, the same chain `MainMenuBarMicroButtons` is deferred behind. All three columns # read clean because the file LOADS clean; what it needs is a sibling window, not a verb. # -# Its CAMP/QUIT dialogs and their event driver HAVE moved out, to UiPanels.xml — the reference's -# own homes (StaticPopup.lua l.564/586 for the dialogs, UIParent.lua l.304-315 for the three -# events). The ESC menu never owned them; it was just where ours were first needed. That is one -# less thing to move when the options family lands. +# Its CAMP/QUIT dialogs and their event driver HAVE moved out — the dialogs to `StaticPopup.xml`, +# the driver to `UIParent.xml`, the reference's own homes (StaticPopup.lua l.564/586 for the +# dialogs, UIParent.lua l.304-315 for the three events), both stock since 1988. The ESC menu never +# owned them; it was just where ours were first needed. That is one less thing to move when the options family lands. GameMenuFrame.xml diff --git a/crates/benilla-app/src/addon_harness/mod.rs b/crates/benilla-app/src/addon_harness/mod.rs index b9339c3f..385d511c 100644 --- a/crates/benilla-app/src/addon_harness/mod.rs +++ b/crates/benilla-app/src/addon_harness/mod.rs @@ -1121,7 +1121,7 @@ fn load_dependencies( /// /// **A string literal in the fourth argument, OR a local bound to one in the same file.** The /// literal-only form was the honest under-report this doc used to name — and then a decision was -/// made on the number it produced. `assets/ui/ItemButtonTemplate.xml` declined to build +/// made on the number it produced. `Interface\FrameXML\ItemButtonTemplate.xml` declined to build /// `ItemButtonTemplate` citing "the harness's template demand ranks it at zero on both axes"; the /// zero was real, and pfUI wanted `ContainerFrameItemButtonTemplate` (which inherits it) the whole /// time, through @@ -3575,10 +3575,10 @@ mod dependency_tests { /// **A template named through a local resolves; the shapes that still cannot are asserted too.** /// /// The literal-only scan was an honest under-report — stated at `missing_templates` — and a - /// decision was then made on the number it produced: `assets/ui/ItemButtonTemplate.xml` - /// declined to build `ItemButtonTemplate` citing a demand of zero "on both axes". The zero was - /// real and the demand was not: pfUI binds `local tpl = "ContainerFrameItemButtonTemplate"` - /// and passes the variable, so the one addon that wanted it was invisible to the ranking. + /// decision was then made on the number it produced: + /// `Interface\FrameXML\ItemButtonTemplate.xml` declined to build `ItemButtonTemplate` citing a + /// demand of zero "on both axes". The zero was real and the demand was not: pfUI binds `local + /// tpl = "ContainerFrameItemButtonTemplate"` and passes the variable, so the one addon that wanted it was invisible to the ranking. /// /// Both halves are asserted, because a scanner that quietly widened would be the worse fix: /// the shape it now sees, AND the shapes it still does not, so the next decision quoting this diff --git a/crates/benilla-app/src/capture/fixtures.rs b/crates/benilla-app/src/capture/fixtures.rs index c47ff7d6..67efc141 100644 --- a/crates/benilla-app/src/capture/fixtures.rs +++ b/crates/benilla-app/src/capture/fixtures.rs @@ -252,8 +252,8 @@ pub(super) fn seed_ui_fixture( gossip.quests = vec![(783, 0, 5, "Eagan Peltskinner".into())]; // One short option AND four that WRAP — the live shape both gossip bugs came in as // (the director's screenshots), and a menu deliberately TALLER than the parchment so - // the capture covers the whole chain: the per-row auto-height - // (`BenillaGossipRow_Resize`), the scroll frame that contains the overflow, and the + // the capture covers the whole chain: the stock `GossipResize`'s per-row auto-height, + // the scroll frame that contains the overflow, and the // scrollbar that appears with it. A fixture of one-line labels showed none of this — // every row fit the template's 16 px and nothing ever overflowed. let judgement = [ diff --git a/crates/benilla-app/src/cinematic.rs b/crates/benilla-app/src/cinematic.rs index 6eece84e..4dadd52c 100644 --- a/crates/benilla-app/src/cinematic.rs +++ b/crates/benilla-app/src/cinematic.rs @@ -35,9 +35,9 @@ //! rather than being skipped (`0x48efe0`). //! - **ESC is not an engine binding.** `StopCinematic` has zero native callers in the reference: //! the only skip path is `CinematicFrame.xml`'s own `OnKeyDown`, which is why benilla's copy of -//! that frame (`assets/ui/CinematicFrame.xml`) carries the same handler and why the Lua binding -//! queues [`SessionRequest::StopCinematic`](benilla_ui::script::SessionRequest) rather than -//! reaching in here. +//! that frame (stock `Interface\FrameXML\CinematicFrame.xml`) carries the same handler and why +//! the Lua binding queues [`SessionRequest::StopCinematic`](benilla_ui::script::SessionRequest) +//! rather than reaching in here. //! - **The ack ends the run, once.** `CMSG_COMPLETE_CINEMATIC` goes out on a natural end and on an //! ESC skip alike (`0x48f080`). Decision 0196 is why it can never be dropped: unacked, vmangos //! re-anchors object visibility to its own copy of the flying camera and everything around the diff --git a/crates/benilla-app/src/minimap/ping.rs b/crates/benilla-app/src/minimap/ping.rs index 228fd690..acc5afbf 100644 --- a/crates/benilla-app/src/minimap/ping.rs +++ b/crates/benilla-app/src/minimap/ping.rs @@ -37,7 +37,7 @@ //! `MiniMapPing` `` it shows on `MINIMAP_PING`, re-seats every frame from //! `GetPingPosition()`, holds 5 s (`MINIMAPPING_TIMER`), "fades" 0.5 s through a `SetAlpha(255·t)` //! that clamps to full until the last ~2 ms, and hides. Since 1751's swap that file runs here -//! verbatim (1974), and since decision 2008 the `` it shows **renders its own file** +//! verbatim (1974), and since decision 2013 the `` it shows **renders its own file** //! (`Interface\MiniMap\Ping\MinimapPing.mdx`, through `crate::ui_models`): the spinner on its //! global-sequence clock, the static centre, the ring on the looping Stand — the model's own //! bones, weight tracks and additive quads, on the pane's private clock that runs only while the diff --git a/crates/benilla-app/src/net/apply/chat.rs b/crates/benilla-app/src/net/apply/chat.rs index 99a80e35..4d589326 100644 --- a/crates/benilla-app/src/net/apply/chat.rs +++ b/crates/benilla-app/src/net/apply/chat.rs @@ -186,8 +186,9 @@ pub(super) fn chat_wrong_faction(chat_log: &mut ChatLog) { /// (wow-re `system/ui/ui.md` l.2459). Nothing on this path touches the chat composer. /// /// **This used to push into the chat feed**, as a stand-in from before benilla had an errors -/// frame. It has had a real one for a long time (`assets/ui/ErrorsFrame.xml`, the ref -/// `UIErrorsFrame` as a genuine `MessageFrame`), and the stand-in outlived its reason: vmangos +/// frame. It has had a real one for a long time — the ref `UIErrorsFrame`, a genuine +/// `MessageFrame` (ours until 1751's fourteenth window, the chain's own +/// `Interface\FrameXML\UIErrorsFrame.xml` since) — and the stand-in outlived its reason: vmangos /// `Player::SetGameMaster` answers `.gm on|off` with **both** `SendSysMessage` and /// `SendNotification` (`Objects/Player.cpp:2676-2677`/`2701-2702`), so a client that sinks the /// notification into chat prints "GM mode is ON" **twice** where the reference prints it once. @@ -382,8 +383,8 @@ mod tests { /// handler `0x401800` is "read the cstring, `mov edx,1`, `call 0x4945b0`" — event `0xe0` /// `UI_ERROR_MESSAGE`, the UIErrorsFrame toast — plus a console log, and it never reaches the /// chat composer. Benilla used to park the notice in the chat feed for want of an errors - /// frame; it has had one since `assets/ui/ErrorsFrame.xml`, and the stand-in was what printed - /// "GM mode is ON" twice. + /// frame; it has had one since our own `ErrorsFrame.xml` (the chain's `UIErrorsFrame.xml` + /// since 1751), and the stand-in was what printed "GM mode is ON" twice. /// /// The pair is the test: BOTH halves of one toggle, one chat line, one toast. #[test] diff --git a/crates/benilla-app/src/ui_cast.rs b/crates/benilla-app/src/ui_cast.rs index c2e94c6e..1457f46e 100644 --- a/crates/benilla-app/src/ui_cast.rs +++ b/crates/benilla-app/src/ui_cast.rs @@ -3,7 +3,7 @@ //! The net bridge queues [`CastBarEdge`]s (self-casts only — the producers filter on the self //! guid; the channel pair is self-only *on the wire*), and the drain fires the reference //! client's FrameScript events into the script VM — `SPELLCAST_START` and family, the exact -//! contract `assets/ui/CastingBar.xml` (the extracted 1.12 `CastingBarFrame`) registers for. +//! contract stock `Interface\FrameXML\CastingBarFrame.xml` registers for. //! The spell name rides the event (resolved here from the `Spell.dbc` catalog — the script VM //! has no spell-catalog binding, deliberately: one lookup face, decision 0107). diff --git a/crates/benilla-app/src/ui_mirror.rs b/crates/benilla-app/src/ui_mirror.rs index 8a7a1ab5..591528f7 100644 --- a/crates/benilla-app/src/ui_mirror.rs +++ b/crates/benilla-app/src/ui_mirror.rs @@ -3,7 +3,7 @@ //! //! The net bridge queues [`MirrorTimerEdge`]s and the drain fires the reference client's //! FrameScript events into the script VM — `MIRROR_TIMER_START` / `_PAUSE` / `_STOP`, the exact -//! contract `assets/ui/MirrorTimer.xml` (the transcribed 1.12 `MirrorTimer1/2/3`) registers for. +//! contract stock `Interface\FrameXML\MirrorTimer.xml` (`MirrorTimer1/2/3`) registers for. //! The bars themselves are the reference's: the frame stores the value and integrates //! `value + scale * elapsed` every OnUpdate, so a packet every few seconds is enough to paint a //! smooth countdown. diff --git a/crates/benilla-app/src/ui_script/action_bar_tests.rs b/crates/benilla-app/src/ui_script/action_bar_tests.rs index a00f0679..b165c3b1 100644 --- a/crates/benilla-app/src/ui_script/action_bar_tests.rs +++ b/crates/benilla-app/src/ui_script/action_bar_tests.rs @@ -6,7 +6,7 @@ fn action_ids(s: &mut UiScript) -> Vec { s.take_action_uses().into_iter().map(|u| u.action).collect() } -/// Load the real `assets/ui/ActionBar.xml` (the shipped default bar) into a bare engine and +/// Load the stock `Interface\FrameXML\ActionBarFrame.xml` into a bare engine and /// drive it with a synthetic action snapshot — the slice-1 chain minus Bevy: template /// expansion over 12 instances, the vanilla bonus-page formula, icon paint on events, empty /// slots drawing no icon, and a physical click queuing the right UseAction id. @@ -798,19 +798,20 @@ fn macro_name_line_follows_get_action_text_through_the_xml() { assert!(s.errors().is_empty(), "script errors: {:?}", s.errors()); } -/// The shipped **bag BAR** — `assets/ui/BagFrame.xml` — materialized frame for frame, and then -/// driven end to end: the bar's own backpack toggle opens the backpack window, the fed stack -/// paints in its slot's well, the slot's clicks queue the right intents, and the toggle shuts it -/// again. It lives in this file because the bar seats on `MainMenuBarArtFrame` (ActionBar.xml) — -/// the toggle's anchor arithmetic below is the reason. +/// The **bag BAR** — stock `Interface\FrameXML\MainMenuBarBagButtons.xml` — materialized frame +/// for frame, and then driven end to end: the bar's own backpack toggle opens the backpack +/// window, the fed stack paints in its slot's well, the slot's clicks queue the right intents, +/// and the toggle shuts it again. It lives in this file because the bar seats on +/// `MainMenuBarArtFrame` (`ActionBarFrame.xml`) — the toggle's anchor arithmetic below is the +/// reason. /// /// **What decision 1751 changed.** This asserted `report.frames == 259` over a breakdown that /// counted five bag WINDOWS and a keyring window (37 + 4×42 + 42, plus the bar's own handful). -/// Those windows are gone from this file: the live ones are the reference's `ContainerFrame1..12`, -/// executed off the player's own patch chain, and `BagFrame.xml` is the BAR and nothing else — -/// this client's stand-in for the reference's `MainMenuBarBagButtons.xml`. So the count is -/// recounted from what the file declares today, and the drive reaches the reference's window -/// through the bar's own button rather than showing one of ours by name. +/// Those windows are gone: the live ones are the reference's `ContainerFrame1..12`, executed off +/// the player's own patch chain, and the bar is the reference's own +/// `MainMenuBarBagButtons.xml` (1783). So the count is recounted from what that file declares, +/// and the drive reaches the reference's window through the bar's own button rather than showing +/// one of ours by name. #[test] fn shipped_bag_frame_drives_end_to_end() { let _data = benilla_formats::wow_data_or_skip!(); @@ -829,8 +830,7 @@ fn shipped_bag_frame_drives_end_to_end() { // * StackSplit.xml and MerchantFrame.xml after the bags — the reference's // `ContainerFrameItemButton_OnClick` reads `StackSplitFrame` on both arms and // `MerchantFrame:IsShown()` on the right one, so a slot click raises without them. That - // dependency is the reference's, not ours; MerchantFrame.xml is additionally the home of - // the `BenillaMoney_*` coin rig this chain's windows call. + // dependency is the reference's, not ours. let mut bar_frames = 0; for file in BAG_UI { let frames = load_ui(&s, file); @@ -912,9 +912,9 @@ fn shipped_bag_frame_drives_end_to_end() { // Click the toggle → the backpack window opens and slot 1 paints the jerky. The toggle seats // on the bar's art frame BOTTOMRIGHT +(-6,2), 37×37: art frame BOTTOMRIGHT is the bar's // (full-width, bottom-anchored) corner (1024,0) ⇒ toggle x[981,1018] y[2,39], center - // (999.5,20.5). That arithmetic is THIS file's — the button is `BagFrame.xml`'s and its seat - // is `ActionBar.xml`'s — so the click stays at literal coordinates rather than going through - // `centre_of`: hitting them is part of what is being tested. + // (999.5,20.5). That arithmetic is THIS file's — the button is `MainMenuBarBagButtons.xml`'s + // and its seat is `ActionBarFrame.xml`'s — so the click stays at literal coordinates rather + // than going through `centre_of`: hitting them is part of what is being tested. s.mouse_button(999.0, 20.0, "LeftButton", true); s.mouse_button(999.0, 20.0, "LeftButton", false); s.resolve(); diff --git a/crates/benilla-app/src/ui_script/bag_tests.rs b/crates/benilla-app/src/ui_script/bag_tests.rs index 174379d5..80635e0d 100644 --- a/crates/benilla-app/src/ui_script/bag_tests.rs +++ b/crates/benilla-app/src/ui_script/bag_tests.rs @@ -937,7 +937,8 @@ fn a_second_bag_window_feeds_and_paints_via_the_bag_bar() { ); assert!(!open(&s, 1), "hidden by default"); - // CharacterBag0Slot == bag id 1 (BenillaBagBarSlot_OnLoad(self, 1) in BagFrame.xml). + // CharacterBag0Slot == bag id 1: the stock bar's handlers carry no `bagId` field and + // recompute `this:GetID() - CharacterBag0Slot:GetID() + 1` (see `:2119` below). s.run("CharacterBag0Slot:Click()").unwrap(); let _ = s.take_sounds(); assert!(open(&s, 1), "the bag-bar click opened bag 1's window"); diff --git a/crates/benilla-app/src/ui_script/bagnon_render_tests.rs b/crates/benilla-app/src/ui_script/bagnon_render_tests.rs index 9c419353..3d477ea0 100644 --- a/crates/benilla-app/src/ui_script/bagnon_render_tests.rs +++ b/crates/benilla-app/src/ui_script/bagnon_render_tests.rs @@ -438,7 +438,7 @@ fn without_a_player_at_addon_load_bagnon_draws_an_empty_window() { } /// The **other** fault, pinned on its own so a later regression names itself: the reference's -/// `SetItemButton*` family (`assets/ui/ItemButtonTemplate.xml`). +/// `SetItemButton*` family (`Interface\FrameXML\ItemButtonTemplate.xml`). /// /// Bagnon ends every slot update with `SetItemButtonDesaturated` / `SetItemButtonTexture` / /// `SetItemButtonCount`. While those were nil the raise landed inside `BagnonFrame_AddBag`'s @@ -1133,16 +1133,16 @@ fn a_texture_gradient_tints_the_art_it_sits_on() { /// **The director's report: "when I first open the bags with bagnon the gold numbers are all /// cramped up; if I close and open again it looks good."** /// -/// Bagnon's money display is `SmallMoneyFrameTemplate` — OUR `MoneyFrame.xml`. Its `ShowCoin` used -/// to size each coin with `label:GetStringWidth()`, which is served from the measure round-trip and -/// therefore reads **0 in the tick that set the text**: every coin came out at exactly one icon -/// width and the digits overlapped. The second open looked right because the first open's measure -/// had landed in the cache by then — the reopen was reading the previous open's numbers. +/// Bagnon's money display is `SmallMoneyFrameTemplate`, off the chain's own `MoneyFrame.xml`. Its +/// `ShowCoin` used to size each coin with `label:GetStringWidth()`, which is served from the +/// measure round-trip and therefore reads **0 in the tick that set the text**: every coin came out +/// at exactly one icon width and the digits overlapped. The second open looked right because the +/// first open's measure had landed in the cache by then — the reopen was reading the previous open's numbers. /// -/// The fix sums `BENILLA_DIGIT_W`, the app's per-digit advance feed -/// ([`benilla_ui::script::UiScript::set_digit_advances`]) — data pushed ahead, so the answer exists -/// *in* the tick. That feed's own doc names this frame as what it was built for; only the merchant -/// price had ever used it. +/// The fix is the engine's font measurer answering inside the Lua call that asked +/// (`benilla_ui`'s `script::measure`): `GetStringWidth` returns a real number in the tick that set +/// the text. A digits-only stand-in — a per-digit advance feed pushed ahead from the app — shipped +/// first and was retired by the general answer (decision 1285). /// /// The assertion is the FIRST open, which is the half that was broken. #[test] diff --git a/crates/benilla-app/src/ui_script/basic_controls_tests.rs b/crates/benilla-app/src/ui_script/basic_controls_tests.rs index 62bd6963..a427abdc 100644 --- a/crates/benilla-app/src/ui_script/basic_controls_tests.rs +++ b/crates/benilla-app/src/ui_script/basic_controls_tests.rs @@ -1,5 +1,5 @@ -//! The shipped `assets/ui/BasicControls.xml` — the reference's second file, driven the way an -//! addon drives it. +//! The stock `Interface\FrameXML\BasicControls.xml` — the reference's second file, driven the way +//! an addon drives it. //! //! Nothing benilla ships calls `message`, `TEXT` or `_ERRORMESSAGE`; their only consumers are //! third-party addons (26 call `TEXT`, ~10 genuinely call `message`, two replace `_ERRORMESSAGE`). diff --git a/crates/benilla-app/src/ui_script/buff_tests.rs b/crates/benilla-app/src/ui_script/buff_tests.rs index c67225f1..35f007d6 100644 --- a/crates/benilla-app/src/ui_script/buff_tests.rs +++ b/crates/benilla-app/src/ui_script/buff_tests.rs @@ -1,6 +1,6 @@ -//! The player buff bar (`assets/ui/BuffFrame.xml`, decisions 0255/0257) against its reference -//! behaviour. The XML/Lua is the unit under test; the app-side feed (`crate::ui_aura`) is stubbed by -//! pushing an [`AuraState`] list straight through [`UiScript::set_auras`] and firing +//! The player buff bar (stock `Interface\FrameXML\BuffFrame.xml`, decisions 0255/0257) against its +//! reference behaviour. The XML/Lua is the unit under test; the app-side feed (`crate::ui_aura`) is +//! stubbed by pushing an [`AuraState`] list straight through [`UiScript::set_auras`] and firing //! `PLAYER_AURAS_CHANGED`, so these exercise the *button* handlers — the row/filter wiring, the //! dispel-tinted border, the stack count, the countdown, the warning flash, and the right-click //! cancel — the way the reference's own `BuffButton_*` do. diff --git a/crates/benilla-app/src/ui_script/chat_tests.rs b/crates/benilla-app/src/ui_script/chat_tests.rs index 71006896..59227a62 100644 --- a/crates/benilla-app/src/ui_script/chat_tests.rs +++ b/crates/benilla-app/src/ui_script/chat_tests.rs @@ -1,9 +1,9 @@ //! Shipped end-to-end tests for the chat window + input (decision 0084, the chat arc): the real -//! `assets/ui/ChatFrame.xml` loaded through the engine loader, driven exactly as the app drives it — -//! `add_chat_message` → `resolve`/`extract` (lines render in the pinned colors), the wheel → the Lua -//! `OnMouseWheel` handler → `ScrollUp` (which freezes the fade), and the input EditBox's ENTER → -//! `OnEnterPressed` → `SubmitChatInput` → `take_chat_input` (the app then parses it — see -//! `crate::ui_chat`'s `parse_line` tests for the `/say`//`/yell`//`/w` mapping). +//! `Interface\FrameXML\ChatFrame.xml` loaded through the engine loader, driven exactly as the app +//! drives it — `add_chat_message` → `resolve`/`extract` (lines render in the pinned colors), the +//! wheel → the Lua `OnMouseWheel` handler → `ScrollUp` (which freezes the fade), and the input +//! EditBox's ENTER → `OnEnterPressed` → `SubmitChatInput` → `take_chat_input` (the app then parses +//! it — see `crate::ui_chat`'s `parse_line` tests for the `/say`//`/yell`//`/w` mapping). use benilla_ui::script::{ExtractedQuad, QuadContent, UiScript}; @@ -378,11 +378,11 @@ fn chat_click_dismisses_a_stuck_spell_but_not_an_item() { // ── ChatTypeInfo: the addon-facing color table ──────────────────────────────────────────────── -/// `ChatTypeInfo` carries the shipped default chat colors twice: once in `assets/ui/ChatFrame.xml` -/// for addons to read, and once in [`crate::ui_chat::default_color`] for our own feed to render. -/// Both are the same wow-re byte table (`chat-color-table.md`, the static registry at -/// `.rdata 0x804710`) — so this is the gate that makes the duplication safe: every kind we model -/// must agree to the byte, and the table's shape (`sticky`/`id`) must be the reference's. +/// `ChatTypeInfo` carries the shipped default chat colors twice: once in +/// `Interface\FrameXML\ChatFrame.xml` for addons to read, and once in +/// [`crate::ui_chat::default_color`] for our own feed to render. Both are the same wow-re byte +/// table (`chat-color-table.md`, the static registry at `.rdata 0x804710`) — so this is the gate +/// that makes the duplication safe: every kind we model must agree to the byte, and the table's shape (`sticky`/`id`) must be the reference's. #[test] fn chat_type_info_matches_the_host_color_table() { use crate::ui_chat::{default_color, ChatEventKind as K}; diff --git a/crates/benilla-app/src/ui_script/color_picker_tests.rs b/crates/benilla-app/src/ui_script/color_picker_tests.rs index cd279a37..18bb3e89 100644 --- a/crates/benilla-app/src/ui_script/color_picker_tests.rs +++ b/crates/benilla-app/src/ui_script/color_picker_tests.rs @@ -1,5 +1,5 @@ -//! The shipped `assets/ui/ColorPickerFrame.xml` + the dropdown's colour-swatch row, driven the way -//! the corpus drives them. +//! The stock `Interface\FrameXML\ColorPickerFrame.xml` + the dropdown's colour-swatch row, driven +//! the way the corpus drives them. //! //! Nothing benilla ships opens this window. Its consumers are third-party addons — 86 of the 218 //! reach `ColorPickerFrame`, and 64 of those files are copies of `Dewdrop-2.0.lua`, THE Ace2 menu diff --git a/crates/benilla-app/src/ui_script/delete_item_tests.rs b/crates/benilla-app/src/ui_script/delete_item_tests.rs index d44596f7..a9b4a7a3 100644 --- a/crates/benilla-app/src/ui_script/delete_item_tests.rs +++ b/crates/benilla-app/src/ui_script/delete_item_tests.rs @@ -85,8 +85,9 @@ fn bag_setup() -> UiScript { for file in BAG_UI { load_xml(&s, file); } - // `ContainerFrame_Update` reads `MerchantFrame:IsShown()` on any slot the tooltip owns, and - // `BankFrame` (BAG_UI's last entry) fills its purse through `BenillaMoney_Set`. + // `ContainerFrame_Update` reads `MerchantFrame:IsShown()` on any slot the tooltip owns. + // `BankFrame`'s purse is an ordinary `SmallMoneyFrameTemplate` off the chain's own + // `MoneyFrame.xml` (1937/1962), so it is not a merchant dependency. load_xml(&s, "ScrollTemplates.xml"); // our scroll kit + the placeholder icon load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml"); load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); diff --git a/crates/benilla-app/src/ui_script/errors_tests.rs b/crates/benilla-app/src/ui_script/errors_tests.rs index b979bd4e..295cc865 100644 --- a/crates/benilla-app/src/ui_script/errors_tests.rs +++ b/crates/benilla-app/src/ui_script/errors_tests.rs @@ -1,5 +1,5 @@ -//! The shipped errors/info frame (`assets/ui/ErrorsFrame.xml` — the ref UIErrorsFrame, a real -//! ``) driven engine-only: the yellow `UI_INFO_MESSAGE` toast (the quest +//! The errors/info frame — stock `Interface\FrameXML\UIErrorsFrame.xml`, a real +//! `` — driven engine-only: the yellow `UI_INFO_MESSAGE` toast (the quest //! objective-progress popup's surface), the red `UI_ERROR_MESSAGE` line, insertMode-TOP stacking, //! and the hold+fade expiry. //! @@ -124,7 +124,7 @@ fn an_error_toast_draws_over_an_open_panel_window() { load_xml(&s, "Interface\\FrameXML\\Cooldown.xml"); load_xml(&s, "ScrollTemplates.xml"); // our scroll kit + the placeholder icon load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml"); - load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); // BenillaMoney_* — QuestLogDetail's reward money row + load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); // QuestLogDetail's reward money row (1928) // pane's UIPanelScrollFrameTemplate). A MISSING template is a loader *warning*, so an // under-loaded list passes and then dies on the first FauxScrollFrame_Update. load_xml(&s, "Interface\\FrameXML\\BasicControls.xml"); diff --git a/crates/benilla-app/src/ui_script/escape_tests.rs b/crates/benilla-app/src/ui_script/escape_tests.rs index 43ae3c70..b5c10ddf 100644 --- a/crates/benilla-app/src/ui_script/escape_tests.rs +++ b/crates/benilla-app/src/ui_script/escape_tests.rs @@ -79,7 +79,9 @@ fn escape_closes_bag_and_panel_releases_loot_and_clears_cursor() { load_xml(&s, "Interface\\FrameXML\\LootFrame.xml"); load_xml(&s, "ScrollTemplates.xml"); // our scroll kit + the placeholder icon load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml"); - load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); // BenillaMoney_Set, BankFrame's purse helper + // The reference's own `ContainerFrameItemButton_OnClick` reads `MerchantFrame:IsShown()` + // on the bag-slot click below; the coin rig this line used to name is gone (1937/1962). + load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); s.set_money(0); s.set_container(0, Some(one_item_backpack())); diff --git a/crates/benilla-app/src/ui_script/frame_flag_gate.rs b/crates/benilla-app/src/ui_script/frame_flag_gate.rs index 274169ba..8289b15d 100644 --- a/crates/benilla-app/src/ui_script/frame_flag_gate.rs +++ b/crates/benilla-app/src/ui_script/frame_flag_gate.rs @@ -23,10 +23,10 @@ //! answers the same whichever way it came. //! //! **Divergences are an explicit list with a reason each, never a pattern.** [`KNOWN`] carries -//! them, in both directions; a new one cannot hide inside a tolerance. The list is where the -//! seven frames the reference makes interactive through *handlers we do not carry* are recorded — -//! those want the handler (and its tooltip), never a bare `enableMouse="true"` that would swallow -//! the click and give nothing back. +//! them, in both directions; a new one cannot hide inside a tolerance. **It is empty today** — +//! 1751's window migrations, 1795, 1970 and 1980 each retired a group, and the in-body notes are +//! the record of what each one was. The array stays because an empty list is the thing that +//! notices a divergence arriving. //! //! ## Four flags, and only four //! @@ -68,8 +68,8 @@ //! //! The reference side is **XML only**: a `SetID` or `EnableMouse` the reference makes from Lua at //! `OnLoad` is invisible here and reads as absent. That blind spot only ever under-reports — it -//! can hide a divergence, never invent one — so nothing it misses turns into a false failure; the -//! handful of frames it does hide are in `KNOWN` with that reason. +//! can hide a divergence, never invent one — so nothing it misses turns into a false failure. It +//! would be a `KNOWN` entry's reason if any frame still needed one. //! //! The whole module skips cleanly with no install — `_extracted_framexml/` is a gitignored //! Blizzard asset, like every other client-data test here. @@ -157,16 +157,18 @@ impl std::fmt::Display for Flag { } } -/// The accepted differences, in four groups: **seven frames the reference makes mouse-interactive -/// through HANDLERS we do not carry**, the merchant rows whose mouse we take where it does not, -/// the faux scroll panes we build from a different widget kind, and the ids the reference sets -/// from Lua. Every entry is a judgement someone made; none of them is a tolerance. +/// The accepted differences — **none, today**. The four groups this list once carried (the frames +/// the reference made mouse-interactive through handlers we did not carry, the merchant rows, the +/// faux scroll panes, the Lua-set ids) each retired with the window that owned them; the in-body +/// notes below name the record for each. An empty array is not an oversight: it is what fails the +/// gate the moment a new divergence appears, and every entry it ever holds is a judgement someone +/// made, never a tolerance. const KNOWN: &[Known] = &[ - // ── The reference has it, we do not: all seven are handler gaps, not flag gaps ───────────── + // ── The reference had it and we did not: seven handler gaps, not flag gaps (all retired) ─── // - // In each of these the reference's mouse comes from an ``/`` pair whose body - // we have not built, and the interaction the player would notice is the TOOLTIP those handlers - // show — not the click-blocking the flag gives. Declaring `enableMouse="true"` here would make + // In each of these the reference's mouse came from an ``/`` pair whose body + // we had not built, and the interaction the player would notice was the TOOLTIP those handlers + // show — not the click-blocking the flag gives. Declaring `enableMouse="true"` would have made // the frame swallow the click and hand back nothing, which is worse than the gap. // `PetPaperDollFrameExpBar` RETIRED here (decision 1751's character-sheet window). It read // "the reference bar inherits TextStatusBar, whose OnEnter/OnLeave show the value text; ours is diff --git a/crates/benilla-app/src/ui_script/group_loot_tests.rs b/crates/benilla-app/src/ui_script/group_loot_tests.rs index 4a1d9c64..f8826d27 100644 --- a/crates/benilla-app/src/ui_script/group_loot_tests.rs +++ b/crates/benilla-app/src/ui_script/group_loot_tests.rs @@ -1,5 +1,5 @@ -//! The group-loot roll popups (decision 0591, `assets/ui/GroupLootFrame.xml`): the four stacked -//! `GroupLootFrame`s that answer `START_LOOT_ROLL`/`CANCEL_LOOT_ROLL` off a pushed +//! The group-loot roll popups (decision 0591, stock `Interface\FrameXML\GroupLootFrame.xml`): the +//! four stacked `GroupLootFrame`s that answer `START_LOOT_ROLL`/`CANCEL_LOOT_ROLL` off a pushed //! [`LootRollsState`] snapshot (the `loot_roll.rs` seam's own harness idiom, mirrored here the way //! `loot_tests.rs` mirrors it for `set_loot`/`LootState`). diff --git a/crates/benilla-app/src/ui_script/inspect_tests.rs b/crates/benilla-app/src/ui_script/inspect_tests.rs index 41d12594..3af72bb1 100644 --- a/crates/benilla-app/src/ui_script/inspect_tests.rs +++ b/crates/benilla-app/src/ui_script/inspect_tests.rs @@ -1,7 +1,7 @@ //! The shipped **inspect window** driven end-to-end, engine-only (no Bevy): the real -//! `assets/ui/InspectFrame.xml` loaded behind `Fonts.xml`/`UiPanels.xml`/`GameTooltip.xml` and fed a -//! synthetic target snapshot + a foreign equipment view (decision 0631). `character_tests.rs`'s -//! harness, turned onto the other paper doll. +//! The reference's own `Blizzard_InspectUI` addon loaded behind +//! `Fonts.xml`/`UIParent.xml`/`GameTooltip.xml` and fed a synthetic target snapshot + a foreign +//! equipment view (decision 0631). `character_tests.rs`'s harness, turned onto the other paper doll. //! //! What these are here to falsify, in order of how quietly it could have shipped broken: //! diff --git a/crates/benilla-app/src/ui_script/loot_tests.rs b/crates/benilla-app/src/ui_script/loot_tests.rs index 898db63d..da8b4af8 100644 --- a/crates/benilla-app/src/ui_script/loot_tests.rs +++ b/crates/benilla-app/src/ui_script/loot_tests.rs @@ -595,11 +595,11 @@ fn the_loot_window_draws_over_the_party_frames() { /// previews the row's item in the dressing room (decision 1060), SHIFT posts its link into an open /// chat edit box (decision 1059) — and **neither loots**. /// -/// That last clause is the whole point of the test, and it is ours to get right rather than the -/// reference's: in the real client the loot itself is the C `LootButton` widget's click behaviour -/// (l.94's `button:SetSlot(slot)`), so its Lua arms fall through harmlessly; ours owns the -/// `LootSlot` call, so the arms had to grow a `return` the reference does not have. The unmodified -/// click still loots — the regression that would otherwise ship silently. +/// That last clause is the whole point of the test, and it is the WIDGET's to get right: the loot +/// itself is the `LootButton` kind's click behaviour (`benilla-ui` `script/button.rs`, decision +/// 1799 — `l.94`'s `button:SetSlot(slot)` is what arms it), gated on no shift/ctrl/alt, which is +/// why the stock `LootFrameItem_OnClick` never calls a take itself and needs no `return`. The +/// unmodified click still loots — the regression that would otherwise ship silently. #[test] fn ctrl_and_shift_on_a_loot_row_preview_and_post_without_looting() { const WOOL_LINK: &str = "|cffffffff|Hitem:2589:0:0:0|h[Wool Cloth]|h|r"; diff --git a/crates/benilla-app/src/ui_script/macro_tests.rs b/crates/benilla-app/src/ui_script/macro_tests.rs index 8eb5e3da..7117f220 100644 --- a/crates/benilla-app/src/ui_script/macro_tests.rs +++ b/crates/benilla-app/src/ui_script/macro_tests.rs @@ -1,4 +1,4 @@ -//! The shipped `assets/ui/MacroFrame.xml` — the macro editor + its name/icon popup (decision +//! The reference's own `Blizzard_MacroUI` addon — the macro editor + its name/icon popup (decision //! 0983), driven against the engine's own macro table. //! //! What these guard, end to end through the real file: the window loads clean in its real diff --git a/crates/benilla-app/src/ui_script/merchant_tests.rs b/crates/benilla-app/src/ui_script/merchant_tests.rs index a4f21a90..2b922736 100644 --- a/crates/benilla-app/src/ui_script/merchant_tests.rs +++ b/crates/benilla-app/src/ui_script/merchant_tests.rs @@ -1,6 +1,6 @@ -//! The shipped **merchant window** driven end-to-end, engine-only (no Bevy): the real -//! `assets/ui/MerchantFrame.xml` (+ `GameTooltip.xml` for the hover chain) loaded behind -//! `UiPanels.xml` and fed synthetic stock — the phase-4 vendor arc's machine checks (decision +//! The **merchant window** driven end-to-end, engine-only (no Bevy): the stock +//! `Interface\FrameXML\MerchantFrame.xml` (+ `GameTooltip.xml` for the hover chain) loaded behind +//! `UIParent.xml` and fed synthetic stock — the phase-4 vendor arc's machine checks (decision //! 0081/0084). Split from `panel_tests` (which keeps gossip + the slot manager itself) along the //! folder's one-file-per-window convention. @@ -40,7 +40,7 @@ fn frame_rect(quads: &[ExtractedQuad], w: f32, h: f32) -> benilla_ui::layout::Re .unwrap_or_else(|| panic!("no bare-frame quad sized {w}x{h}")) } -/// Load the real `assets/ui/MerchantFrame.xml` (the shipped vendor window) behind `UiPanels.xml` +/// Load the stock `Interface\FrameXML\MerchantFrame.xml` behind `UIParent.xml` /// into a bare engine and drive it with a synthetic 2-item stock + a purse — the whole phase-4 /// chain minus Bevy (decision 0081), now over the UIPanel slot manager (decision 0084): the /// hidden→shown lifecycle on MERCHANT_SHOW goes through ShowUIPanel (landing at the left slot), @@ -1092,7 +1092,7 @@ fn trade_recipient_money_renders_the_digit_not_ellipsis() { load_xml(&s, f); } load_xml(&s, "ScrollTemplates.xml"); // our scroll kit + the placeholder icon - load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); // the BenillaMoney_* helpers + load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); // MerchantFrame:IsShown(), read on the slot click // TradeFrame's money entry is the chain's own since 1882 — its OnLoad calls MoneyInputFrame_*. load_xml(&s, "Interface\\FrameXML\\MoneyInputFrame.lua"); load_xml(&s, "Interface\\FrameXML\\MoneyInputFrame.xml"); diff --git a/crates/benilla-app/src/ui_script/money_frame_tests.rs b/crates/benilla-app/src/ui_script/money_frame_tests.rs index 31c77508..90f496bd 100644 --- a/crates/benilla-app/src/ui_script/money_frame_tests.rs +++ b/crates/benilla-app/src/ui_script/money_frame_tests.rs @@ -1,12 +1,11 @@ -//! The shipped `assets/ui/MoneyFrame.xml` — the reference's `MoneyFrameTemplate` / +//! The stock `Interface\FrameXML\MoneyFrame.xml` — the reference's `MoneyFrameTemplate` / //! `SmallMoneyFrameTemplate` kit and the `MoneyTypeInfo` table behind it (decision 1190: a name the //! shipped 1.12 UI defines is a name we publish too — under our own implementation of it, 1260). //! -//! Nothing benilla ships consumes this file yet — our own eight coin displays run on -//! MerchantFrame.xml's `BenillaMoney_*` slot kit, and MoneyFrame.xml's header is where the two are -//! reconciled — so these tests ARE its only driver. That makes them the contract: they exercise it -//! the way an addon does (declare a frame on the template, point it at a type, change the type, -//! read the coins back), because that is who calls it. +//! Eight shipped windows consume this file (1937 converged the coin cluster onto it; 1962 put the +//! file itself on the chain). These tests exercise it the way an addon does — declare a frame on +//! the template, point it at a type, change the type, read the coins back — because that is who +//! calls it. //! //! What they guard: the type switch actually rewiring where the number comes from and whether the //! coins take the mouse; the collapse rule per type (`collapse`, `showSmallerCoins`, `fixedWidth`); @@ -203,8 +202,9 @@ fn update_paints_a_static_frame_by_name_and_resizes_it() { // // **The digits used to contribute 0 here and this test asserted the bare 13s that came of it.** // That was the director's cramped gold on a first open: `ShowCoin` sized each coin from a text - // measure that lands a frame later, so it read 0 every first time. It sums the engine's - // `BenillaNumberWidth` feed now, which answers in the same tick. + // measure that lands a frame later, so it read 0 every first time. The engine's font + // measurer answers inside the Lua call that asked now (`script/measure.rs`), so the width + // is real on the first pass. assert_eq!( s.eval::("return TestPurseGoldButton:GetWidth()") .unwrap(), @@ -323,8 +323,8 @@ fn set_money_frame_color_recolours_the_digits_and_not_the_icons() { } /// `MoneyTypeInfo` is read directly by addons, so its shape is part of the contract — all seven -/// reference types, each with an `UpdateFunc`, and the two we cannot source yet answering 0 rather -/// than erroring (the header's `GetSendMailMoney`/`GetSendMailCOD` gap). +/// reference types, each with an `UpdateFunc`, and the two send-mail rows reading the amounts +/// their engine getters hold (`GetSendMailMoney`/`GetSendMailCOD`, built by 1962). #[test] fn the_money_type_table_carries_all_seven_reference_types() { let s = harness(12_345); @@ -345,7 +345,7 @@ fn the_money_type_table_carries_all_seven_reference_types() { "MoneyTypeInfo[\"{t}\"] with an UpdateFunc" ); } - // The two whose engine getters we have not built answer 0 instead of nil-calling. + // The two send-mail rows: with no send-mail amount set, their getters answer 0. for t in ["SEND_MAIL", "SEND_MAIL_COD"] { s.run(&format!( "this = TestPurse MoneyFrame_SetType(\"{t}\") this = nil" @@ -359,7 +359,7 @@ fn the_money_type_table_carries_all_seven_reference_types() { assert_eq!( s.eval::("return TestPurse.staticMoney").unwrap(), 0, - "{t} reads 0 while its engine getter is missing" + "{t} reads its engine getter, which is 0 with no send-mail amount set" ); } } diff --git a/crates/benilla-app/src/ui_script/options_tests.rs b/crates/benilla-app/src/ui_script/options_tests.rs index 3397aca6..b1c1e0ec 100644 --- a/crates/benilla-app/src/ui_script/options_tests.rs +++ b/crates/benilla-app/src/ui_script/options_tests.rs @@ -724,14 +724,15 @@ fn load_definers(s: &UiScript, files: &[&str]) { /// The Interface page's harness (decision 1136), the same posture as `combat_harness` above: the /// **real** definers ahead of the window, in the manifest's own order, so each row captures the -/// same file-scope value it captures in the client. `SHOW_NEWBIE_TIPS` rides in on `GameTooltip.xml` -/// which `harness_on` already loads; the two quest globals need their own windows — -/// `MerchantFrame.xml` for the coin helpers both quest files reuse and `ScrollTemplates.xml` for -/// the kit `QuestFrame.xml` inherits from (the same chain `quest_tests`/`questlog_tests` load). -/// `SHOW_BUFF_DURATIONS` arrives with the bar it re-anchors (1139), behind the two files -/// `buff_tests` loads ahead of it — `Cooldown.xml` (every button's child) and `ActionBar.xml` -/// (`BENILLA_FALLBACK_ICON`), themselves behind `UIParent.xml`. `TextStatusBar.xml` rides in -/// ahead of them for the Status Bar Text row's consumer — the XP bar's numerals (1140). +/// same file-scope value it captures in the client. `SHOW_NEWBIE_TIPS` is set by our own +/// `assets/ui/OptionsFrame.xml` (it lived in our `GameTooltip.xml` until the tooltip went stock, +/// 1968; the reference keeps it in `UIOptionsFrame.lua`), which `harness_on` already loads; the two +/// quest globals need their own windows — `MerchantFrame.xml` for the coin helpers both quest files +/// reuse and `ScrollTemplates.xml` for the kit `QuestFrame.xml` inherits from (the same chain +/// `quest_tests`/`questlog_tests` load). `SHOW_BUFF_DURATIONS` arrives with the bar it re-anchors +/// (1139), behind the two files `buff_tests` loads ahead of it — `Cooldown.xml` (every button's +/// child) and `ActionBar.xml` (`BENILLA_FALLBACK_ICON`), themselves behind `UIParent.xml`. +/// `TextStatusBar.xml` rides in ahead of them for the Status Bar Text row's consumer — the XP bar's numerals (1140). fn interface_harness() -> UiScript { let mut s = audio_harness(); s.set_screen_size(1024.0, 768.0); @@ -1847,8 +1848,9 @@ fn defaults_resets_the_controls_page_to_registered_defaults() { assert!(s.errors().is_empty(), "script errors: {:?}", s.errors()); } -/// Drive the window a few frames so the frame-late fits (the scroll body, the tab widths) -/// converge: rects resolve after Lua runs, so OptionsScroll_Fit answers one frame behind. +/// Drive the window a few frames so the scroll body's frame-late fit converges: rects resolve +/// after Lua runs, so `OptionsScroll_Fit` answers one frame behind. (The tab widths are not in +/// that set — 2028 put them on a one-shot `OptionsTab_FitWidth`.) fn settle(s: &mut UiScript) { for _ in 0..4 { s.resolve(); diff --git a/crates/benilla-app/src/ui_script/panel_template_tests.rs b/crates/benilla-app/src/ui_script/panel_template_tests.rs index 85d80f43..c14ccd5e 100644 --- a/crates/benilla-app/src/ui_script/panel_template_tests.rs +++ b/crates/benilla-app/src/ui_script/panel_template_tests.rs @@ -1,5 +1,5 @@ -//! The shipped `assets/ui/UIPanelTemplates.xml` + `assets/ui/OptionsFrameTemplates.xml` — the -//! reference's SHARED widget kit, driven the way an addon drives it. +//! The stock `Interface\FrameXML\UIPanelTemplates.xml` + our `assets/ui/OptionsFrameTemplates.xml` +//! — the reference's SHARED widget kit, driven the way an addon drives it. //! //! **These are not tests of a window.** Nothing benilla ships instantiates a single template in //! either file: their only consumer is a third-party addon writing @@ -238,7 +238,7 @@ fn a_panel_button_from_the_template_labels_and_paints() { /// `UIPanelCloseButton` — 8 call sites across 4 corpus addons, and the one template here whose /// whole point is its script: `HideUIPanel(this:GetParent())`, resolved at click time against -/// `UiPanels.xml`. +/// the chain's `UIParent.xml`. #[test] fn the_templated_close_button_hides_the_frame_it_sits_on() { let _data = benilla_formats::wow_data_or_skip!(); @@ -438,7 +438,7 @@ fn the_options_check_button_resolves_its_whole_inheritance_chain() { /// real 1.12.1 client has, read from `reference/1.12-globals.tsv`. /// /// Scoped to these two files on purpose: the rest of `assets/ui` is full of deliberately -/// benilla-shaped template names (`BenillaScrollBarTemplate`, `BenillaMacroPanelButtonTemplate`, +/// benilla-shaped template names (`BenillaScrollBarTemplate`, `BenillaScriptLogRowTemplate`, /// `OptionsRedButtonTemplate`), and a whole-tree sweep would be asserting something else. These /// two files make the opposite claim — *these are the reference's own names, which is why an addon /// can find them* — so that claim is the one worth gating. A template renamed to something diff --git a/crates/benilla-app/src/ui_script/panel_tests.rs b/crates/benilla-app/src/ui_script/panel_tests.rs index 3539c4f6..f6268065 100644 --- a/crates/benilla-app/src/ui_script/panel_tests.rs +++ b/crates/benilla-app/src/ui_script/panel_tests.rs @@ -4,9 +4,9 @@ use benilla_ui::script::{ }; /// Load one manifest entry into `s`, panicking on any loader error and returning the frame count -/// it materialized — the panel tests all load `UiPanels.xml` (decision 0084 §2's slot manager) -/// before the panel frame(s) under test, exactly as `benilla.toc`'s own order does, so -/// `ShowUIPanel`/`HideUIPanel` already exist when a frame's OnLoad/OnEvent references them. +/// it materialized — the panel tests all load `Interface\FrameXML\UIParent.xml` (decision 0084 §2's +/// slot manager) before the panel frame(s) under test, exactly as `benilla.toc`'s own order does, +/// so `ShowUIPanel`/`HideUIPanel` already exist when a frame's OnLoad/OnEvent references them. /// /// This was a private disk-only reader until 1751's second window: `BankFrame.xml` is the /// reference's own file off the player's chain now, and a reader that only knows `assets/ui` @@ -30,7 +30,7 @@ fn frame_rect(quads: &[ExtractedQuad], w: f32, h: f32) -> benilla_ui::layout::Re .unwrap_or_else(|| panic!("no bare-frame quad sized {w}x{h}")) } -/// Load the real `assets/ui/GossipFrame.xml` (the shipped gossip window) behind `UiPanels.xml` +/// Load the stock `Interface\FrameXML\GossipFrame.xml` behind `UIParent.xml` /// into a bare engine and drive it with a synthetic gossip menu — the whole phase-3 chain minus /// Bevy (decision 0081), now over the UIPanel slot manager (decision 0084): the hidden→shown /// lifecycle on GOSSIP_SHOW goes through ShowUIPanel (landing the window at the left slot, @@ -738,7 +738,7 @@ fn displacing_an_npc_window_ends_the_displaced_session() { } /// Pin §4's pushable path: a higher-`pushable` occupant (loot's future pushable=7 row, already -/// registered in `UiPanels.xml`) gets pushed to the center slot rather than replaced when a +/// registered in `UIParent.xml`) gets pushed to the center slot rather than replaced when a /// pushable=0 frame (merchant) wants the left spot (UIParent.lua l.734-741) — the synthetic /// registrant the pin calls for, since no loot window ships yet. A bare `CreateFrame` with a /// distinctive 50×50 size stands in for it: it has no visual layers, but `extract` still emits diff --git a/crates/benilla-app/src/ui_script/perf_bar_tests.rs b/crates/benilla-app/src/ui_script/perf_bar_tests.rs index 11956e8e..e399b270 100644 --- a/crates/benilla-app/src/ui_script/perf_bar_tests.rs +++ b/crates/benilla-app/src/ui_script/perf_bar_tests.rs @@ -1,5 +1,5 @@ -//! The shipped `assets/ui/ActionBar.xml`'s performance ("ping") meter — the tinted bar in the -//! main bar's last empty recess — over the real files, never a stub. +//! The stock `Interface\FrameXML\ActionBarFrame.xml`'s performance ("ping") meter — the tinted bar +//! in the main bar's last empty recess — over the real files, never a stub. //! //! What these guard, in order: the ref geometry that puts the bar IN the recess (the whole point of //! the slice); the LOW-strata draw order that makes it show *through* the bar art instead of over diff --git a/crates/benilla-app/src/ui_script/pet_paperdoll_tests.rs b/crates/benilla-app/src/ui_script/pet_paperdoll_tests.rs index b87e7e84..6c633ef8 100644 --- a/crates/benilla-app/src/ui_script/pet_paperdoll_tests.rs +++ b/crates/benilla-app/src/ui_script/pet_paperdoll_tests.rs @@ -398,8 +398,10 @@ fn the_level_line_names_the_family_and_is_untouched_without_one() { // level line at all", because our deleted `assets/ui/PetPaperDollFrame.xml` declared // `PetLevelText` with no `text=` and it started empty. The reference declares it // `text="Level level race class"` (stock `PetPaperDollFrame.xml:70`) — a design-time - // placeholder, and not a GlobalStrings key, so the loader's `text=` lookup falls through to the - // literal and that literal is what a player sees in this state, un-replaced. Both spellings say + // placeholder, and not a GlobalStrings key. **A real 1.12 client draws that literal too**: + // `CSimpleFontString::LoadXML` substitutes the raw attribute when `FrameScript_GetText` comes + // back empty (`771029`-`771032 mov eax,esi`), exactly as `Button::LoadXML 0x778c31` does — so + // this is fidelity, not the loader divergence this comment used to call it. Both spellings say // the same thing about the guard; this one says it about the file that ships. let drawn = with_family(None); assert!( diff --git a/crates/benilla-app/src/ui_script/quest_tests.rs b/crates/benilla-app/src/ui_script/quest_tests.rs index 89e6a210..e7427f64 100644 --- a/crates/benilla-app/src/ui_script/quest_tests.rs +++ b/crates/benilla-app/src/ui_script/quest_tests.rs @@ -1,7 +1,7 @@ //! The shipped **questgiver window** open/close sound, driven engine-only (no Bevy): the real -//! `assets/ui/QuestFrame.xml` loaded behind `UiPanels.xml` and shown/hidden through the wire events. -//! The window-sound convention's machine check for the quest arc (decision 0090), the sibling of the -//! merchant/gossip/bag/loot sound tests. +//! `Interface\FrameXML\QuestFrame.xml` loaded behind `UIParent.xml` and shown/hidden through the +//! wire events. The window-sound convention's machine check for the quest arc (decision 0090), the +//! sibling of the merchant/gossip/bag/loot sound tests. use benilla_ui::script::{QuestPanel, QuestState, ScriptValue, SoundRequest, UiScript}; diff --git a/crates/benilla-app/src/ui_script/questlog_tests.rs b/crates/benilla-app/src/ui_script/questlog_tests.rs index 64acfc2f..21b27198 100644 --- a/crates/benilla-app/src/ui_script/questlog_tests.rs +++ b/crates/benilla-app/src/ui_script/questlog_tests.rs @@ -1,7 +1,7 @@ //! The shipped **quest log window** driven end-to-end, engine-only (no Bevy): the real -//! `assets/ui/QuestLogFrame.xml` loaded behind `UiPanels.xml`/`MerchantFrame.xml` (the money helpers -//! its reward rows reuse) and fed a synthetic 8-entry log + a resolved detail — mirroring -//! `quest_tests.rs`/`bag_tests.rs`'s engine-only harness for the quest-log slice (decision 0088 arc). +//! `Interface\FrameXML\QuestLogFrame.xml` loaded behind `UIParent.xml`/`MerchantFrame.xml` (the +//! money helpers its reward rows reuse) and fed a synthetic 8-entry log + a resolved detail — +//! mirroring `quest_tests.rs`/`bag_tests.rs`'s engine-only harness for the quest-log slice (decision 0088 arc). use benilla_ui::script::{ ExtractedQuad, PartyMemberInfo, PartyState, QuadContent, QuestItemView, QuestLogDetail, @@ -843,15 +843,19 @@ fn empty_quest_log_hides_rows_and_disables_abandon() { s.run("ToggleQuestLog()").unwrap(); assert!(s.errors().is_empty(), "script errors: {:?}", s.errors()); - // A bare FontString region has no Show/Hide/IsVisible in this engine (only Frames/Buttons do — - // `region.rs`'s method table) — the empty-state message is a toggled SetText, read back here. // The empty log says the reference's QUESTLOG_NO_QUESTS_TEXT (GlobalStrings.lua:3225) through - // stock QuestLogNoQuestsText; "Your quest log is empty." was ours (1944). + // stock QuestLogNoQuestsText; "Your quest log is empty." was ours (1944). Regions carry the + // real `Show`/`Hide`/`IsShown`/`IsVisible` (0138), so the label's visibility is assertable + // too — and nothing ever hides this one: `QuestLogFrame.xml:427` is its only mention in the + // whole chain, so it stands behind the rows whether or not the log is empty. assert_eq!( s.eval::("return QuestLogNoQuestsText:GetText()") .unwrap(), "No Active Quests" ); + assert!(s + .eval::("return QuestLogNoQuestsText:IsVisible()") + .unwrap()); assert!(!s.eval::("return QuestLogTitle1:IsVisible()").unwrap()); assert!(!s .eval::("return QuestLogFrameAbandonButton:IsEnabled() ~= 0") @@ -968,14 +972,28 @@ fn reward_rows_follow_the_refs_two_per_row_layout() { // With choices present, the receive text reads "...also..." (QuestFrame.lua:461-462) — it // anchors under choice row 1 (the left/odd column: index=2 is even -> anchorIndex-1 -> 1, this - // function's own logic). GetPoint() isn't wired for FontString regions in this engine (only - // Frame/Button — `region.rs` has no GetPoint), so the anchor CHAIN itself is verified via the - // mandatory capture-loop screenshot (this task's report), not introspected here. + // function's own logic). Regions carry `GetPoint` (1244), so the anchor CHAIN is introspected + // here rather than deferred to a screenshot: TOPLEFT of QuestLogItem1's BOTTOMLEFT, +3/-5. assert_eq!( s.eval::("return QuestLogItemReceiveText:GetText()") .unwrap(), "You will also receive:" ); + assert_eq!( + s.eval::( + "local p, rel, rp = QuestLogItemReceiveText:GetPoint() \ + return p .. '|' .. rel:GetName() .. '|' .. rp" + ) + .unwrap(), + "TOPLEFT|QuestLogItem1|BOTTOMLEFT" + ); + assert_eq!( + s.eval::<(f64, f64)>( + "local _, _, _, x, y = QuestLogItemReceiveText:GetPoint() return x, y" + ) + .unwrap(), + (3.0, -5.0) + ); // One fixed reward shows, chained under the receive text (its own SetPoint target). assert!(s.eval::("return QuestLogItem3:IsShown()").unwrap()); diff --git a/crates/benilla-app/src/ui_script/reference_ui.rs b/crates/benilla-app/src/ui_script/reference_ui.rs index a0cbc0f4..81098e0e 100644 --- a/crates/benilla-app/src/ui_script/reference_ui.rs +++ b/crates/benilla-app/src/ui_script/reference_ui.rs @@ -648,9 +648,10 @@ mod tests { /// reasoning that widget methods are not in `_G`. True, and it meant the report could not see /// a widget method we had *not built*. `MerchantFrame.xml` read `0 engine` and /// [`chain_readiness_report`] read CLEAN while the stock row's `` called - /// `ShoppingTooltip1:SetMerchantCompareItem(...)`, which this engine does not have — so the - /// file loaded, every check passed, and hovering a vendor row would have raised in play. Both - /// instruments were right about what they measure. Neither measured the window. + /// `ShoppingTooltip1:SetMerchantCompareItem(...)`, which this engine did not have then (1802 + /// built it) — so the file loaded, every check passed, and hovering a vendor row would have + /// raised in play. Both instruments were right about what they measure. Neither measured the + /// window. /// /// **A remaining `` in the `fx=` column is usually a LoadOnDemand addon**, not something to /// build. `ClassTrainerFrame_Show`, `CraftFrame_Show`, `MacroFrame_SaveMacro`, @@ -1881,8 +1882,9 @@ mod tests { /// read by the next session as if it were live. /// /// That is not a tidiness problem. Our copies DIVERGE from the reference deliberately, and the - /// divergence is what dies: `UiPanels.xml`'s `PanelTemplates_TabResize` carried a benilla-only - /// `return tabWidth` that the tab settle reads, and the reference's returns nothing. + /// divergence is what dies: our retired `UiPanels.xml` carried a `PanelTemplates_TabResize` + /// with a benilla-only `return tabWidth` that our tab settle read, and the reference's + /// returns nothing (both are gone — 1988, 1993). /// /// The reverse direction — ours seated BELOW the chain's, so we silently override the /// reference — is a real category too, and a wider audit than this gate. diff --git a/crates/benilla-app/src/ui_script/reputation_frame_tests.rs b/crates/benilla-app/src/ui_script/reputation_frame_tests.rs index 035d2ce9..00b99092 100644 --- a/crates/benilla-app/src/ui_script/reputation_frame_tests.rs +++ b/crates/benilla-app/src/ui_script/reputation_frame_tests.rs @@ -1,6 +1,6 @@ -//! The shipped **Reputation tab** (`assets/ui/ReputationFrame.xml`) and the **reputation watch -//! bar** (`assets/ui/ActionBar.xml`) driven end-to-end, engine-only (no Bevy) — the per-window test -//! module the skills/spellbook/bank files already establish. +//! The stock **Reputation tab** (`Interface\FrameXML\ReputationFrame.xml`) and the **reputation +//! watch bar** (`Interface\FrameXML\ActionBarFrame.xml`) driven end-to-end, engine-only (no Bevy) — +//! the per-window test module the skills/spellbook/bank files already establish. //! //! What it pins is the PAINT law, which is the half `benilla-ui`'s own //! `script::reputation::tests` structurally cannot reach: that module drives the twelve globals and diff --git a/crates/benilla-app/src/ui_script/skills_frame_tests.rs b/crates/benilla-app/src/ui_script/skills_frame_tests.rs index 8b47cf32..0dc8a13a 100644 --- a/crates/benilla-app/src/ui_script/skills_frame_tests.rs +++ b/crates/benilla-app/src/ui_script/skills_frame_tests.rs @@ -376,10 +376,11 @@ fn the_pages_close_button_sits_where_the_reference_seats_it_and_closes_the_windo // **"Close", not "CLOSE".** An XML `text=` attribute is a GlobalStrings LOOKUP, not a literal // (`loader::Loader::resolve_text`, wow-re `rf28-typed-widget-loadxml.md` l.36 — // `FrameScript_GetText 0x703bf0`), and `CLOSE = "Close"` (`GlobalStrings.lua:760`). This test - // read "CLOSE" while the page's list carried no `GlobalStrings.lua`: it was asserting our - // loader's miss-fallback (the LITERAL, a deliberate divergence for benilla-authored files), - // not the label the reference client draws. [`super::test_ui::CHARACTER_UI`] loads the - // player's own strings first, as the app does, so this is the real label now. + // read "CLOSE" while the page's list carried no `GlobalStrings.lua`: it was asserting the + // miss-fallback (the raw attribute), which is the REFERENCE's own arm too (`0x778c31` / + // `0x771032`), not the label a client with the strings loaded draws. + // [`super::test_ui::CHARACTER_UI`] loads the player's own strings first, as the app does, so + // this is the real label now. let label = page_quads(&s) .iter() .find_map(|q| match &q.content { diff --git a/crates/benilla-app/src/ui_script/spellbook_tests.rs b/crates/benilla-app/src/ui_script/spellbook_tests.rs index 1997ad84..89cd23a4 100644 --- a/crates/benilla-app/src/ui_script/spellbook_tests.rs +++ b/crates/benilla-app/src/ui_script/spellbook_tests.rs @@ -1,7 +1,7 @@ //! The shipped **spellbook window** driven end-to-end, engine-only (no Bevy): the real -//! `assets/ui/SpellBookFrame.xml` loaded behind `Fonts.xml`/`UiPanels.xml`/`GameTooltip.xml` -//! (plus `ActionBar.xml` for the cross-window place test) and fed a small synthetic book — -//! mirroring `character_tests.rs`'s/`action_bar_tests.rs`'s harness (decision 0216 §8, slice 5). +//! `Interface\FrameXML\SpellBookFrame.xml` loaded behind +//! `Fonts.xml`/`UIParent.xml`/`GameTooltip.xml` (plus `ActionBar.xml` for the cross-window place +//! test) and fed a small synthetic book — mirroring `character_tests.rs`'s/`action_bar_tests.rs`'s harness (decision 0216 §8, slice 5). use benilla_ui::script::{SpellBookState, SpellSlotView, SpellTabView, UiScript}; diff --git a/crates/benilla-app/src/ui_script/static_popup_tests.rs b/crates/benilla-app/src/ui_script/static_popup_tests.rs index 08e8158b..a5eb61d3 100644 --- a/crates/benilla-app/src/ui_script/static_popup_tests.rs +++ b/crates/benilla-app/src/ui_script/static_popup_tests.rs @@ -1,7 +1,7 @@ //! The shared StaticPopup engine (decision 0308 §3 — the ref's registry + Show + OnUpdate -//! machinery, transcribed in UiPanels.xml): the countdown/StartDelay/cancels/ESC laws the death -//! arc's dialogs ride. Entries here are inline test dialogs — the real entries (DELETE_ITEM, -//! ABANDON_QUEST, the death family) are covered by their features' own tests. +//! machinery, stock `Interface\FrameXML\StaticPopup.xml` since 1988): the +//! countdown/StartDelay/cancels/ESC laws the death arc's dialogs ride. Entries here are inline test +//! dialogs — the real entries (DELETE_ITEM, ABANDON_QUEST, the death family) are covered by their features' own tests. use benilla_ui::script::UiScript; diff --git a/crates/benilla-app/src/ui_script/taxi_tests.rs b/crates/benilla-app/src/ui_script/taxi_tests.rs index 9cbfc869..2a51daca 100644 --- a/crates/benilla-app/src/ui_script/taxi_tests.rs +++ b/crates/benilla-app/src/ui_script/taxi_tests.rs @@ -1,10 +1,10 @@ //! The shipped taxi-map window driven end-to-end, engine-only (no Bevy): the real -//! `assets/ui/TaxiFrame.xml` fed a synthetic two-node snapshot (the [`crate::ui_taxi`] feed's exact -//! output shape). Covers what only a runtime load exercises: the Lua parses and every referenced -//! global resolves (including the static node-button pool and the runtime-created route-line -//! textures — TaxiFrame.xml's own header note on both), `TAXIMAP_OPENED` shows the window with the -//! flight master's name and paints the node buttons at their pushed positions, a click on a node -//! drains through `TakeTaxiNode`, and `TAXIMAP_CLOSED` hides it. +//! `Interface\FrameXML\TaxiFrame.xml` fed a synthetic two-node snapshot (the [`crate::ui_taxi`] +//! feed's exact output shape). Covers what only a runtime load exercises: the Lua parses and every +//! referenced global resolves (including the static node-button pool and the runtime-created +//! route-line textures — TaxiFrame.xml's own header note on both), `TAXIMAP_OPENED` shows the +//! window with the flight master's name and paints the node buttons at their pushed positions, a +//! click on a node drains through `TakeTaxiNode`, and `TAXIMAP_CLOSED` hides it. use benilla_ui::script::{ScriptValue, TaxiNodeType, TaxiUiNode, TaxiUiState, UiScript}; @@ -23,12 +23,12 @@ fn taxi_script() -> UiScript { load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua"); load_xml(&s, r"Interface\FrameXML\StaticPopup.xml"); load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml"); // TaxiNodeOnButtonEnter's tooltip + SetTooltipMoney - load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml"); // BenillaErrorsFrame_AddMessage — DrawOneHopLines' refusal + load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml"); // `UIErrorsFrame:AddMessage` — DrawOneHopLines' refusal // Three the reference's own TaxiFrame leans on that our transcription did not: // · GlobalStrings — `ERR_TAXINOPATHS` is a GlobalString, and `AddMessage(nil)` draws an // empty line rather than raising, so its absence is silent. // · UIPanelTemplates (.lua then .xml) — `TaxiCloseButton` inherits `UIPanelCloseButton`, - // which lives there and NOT in our UiPanels.xml. Without it the close button loads as a + // which the chain declares there. Without it the close button loads as a // bare Button with no handler and a click does nothing at all. load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua"); load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml"); @@ -128,10 +128,9 @@ fn shipped_taxi_frame_drives_end_to_end() { /// The "no single-hop destination" refusal (ref `DrawOneHopLines`, fired from `OnShow`): a map /// with only the `Current` node (no `Reachable` neighbor at all) hits `numSingleHops == 0` and -/// calls `BenillaErrorsFrame_AddMessage` (TaxiFrame.xml's deviation 3 from the reference's -/// `UIErrorsFrame:AddMessage`) then hides the window — verified end-to-end since this is the one -/// call this engine has no precedent for outside this window (`ErrorsFrame.xml`'s own Lua seam, -/// not yet exercised from another shipped window's script). +/// calls `UIErrorsFrame:AddMessage(ERR_TAXINOPATHS, …)` (stock `TaxiFrame.lua:161-162`) then +/// hides the window — driven end-to-end because the message frame's Lua seam is what the +/// refusal is visible through. #[test] fn no_single_hop_destination_posts_the_error_and_closes() { let mut s = taxi_script(); diff --git a/crates/benilla-app/src/ui_script/test_ui.rs b/crates/benilla-app/src/ui_script/test_ui.rs index 7aef340d..f2fbf756 100644 --- a/crates/benilla-app/src/ui_script/test_ui.rs +++ b/crates/benilla-app/src/ui_script/test_ui.rs @@ -665,7 +665,7 @@ pub(super) const BAG_UI: &[&str] = &[ // Our adapters over the reference's container files — the keyring tooltip wrapper and the // three bag verbs 0561 shadows (`OpenBackpack`/`CloseBackpack`/`CloseAllBags`). It has to be // AFTER `ContainerFrame.xml` and after the bar, which is why it is here and not up with - // UiPanels.xml. + // `UIParent.xml`. "ContainerFrameAdapters.xml", // `updateContainerFrameAnchors` measures every open bag against `BankFrame:GetRight()` // (ContainerFrame.lua l.505) on EVERY open and close, so the bank window is not optional diff --git a/crates/benilla-app/src/ui_script/tooltip_template_tests.rs b/crates/benilla-app/src/ui_script/tooltip_template_tests.rs index 40502958..6a097bae 100644 --- a/crates/benilla-app/src/ui_script/tooltip_template_tests.rs +++ b/crates/benilla-app/src/ui_script/tooltip_template_tests.rs @@ -1,5 +1,5 @@ -//! `GameTooltipTemplate` as an ADDON sees it — the shipped `assets/ui/GameTooltip.xml` driven the -//! way the corpus drives it. +//! `GameTooltipTemplate` as an ADDON sees it — the stock `Interface\FrameXML\GameTooltip.xml` +//! driven the way the corpus drives it. //! //! **This is not a test of our tooltip window** (that is `tooltip_anchor_tests` / //! `tooltip_compare_tests`, and they are the regression suite this refactor had to leave diff --git a/crates/benilla-app/src/ui_script/trainer_tests.rs b/crates/benilla-app/src/ui_script/trainer_tests.rs index 18ef3905..6eb17d64 100644 --- a/crates/benilla-app/src/ui_script/trainer_tests.rs +++ b/crates/benilla-app/src/ui_script/trainer_tests.rs @@ -1,12 +1,12 @@ //! The shipped **trainer window** driven end-to-end, engine-only (no Bevy): the real -//! `assets/ui/TrainerFrame.xml` — a client-sorted, collapsible **skill-line tree** with a **dropdown** -//! state filter and a draggable **scroll bar** (decisions 0247/0251) — loaded behind its deps -//! (`UiPanels.xml` + `UIDropDownMenu.xml` + `ScrollTemplates.xml` + `MerchantFrame.xml` for the -//! the stock money frames) and fed a synthetic service list. Covers what only a runtime load -//! exercises: the Lua parses and every referenced global resolves, the tree renders interleaved -//! header/service rows, a header click folds its group, the dropdown filter hides a state, the wheel -//! scrolls the list, the NPC name rides `arg1` into the title, the byte-exact GlobalStrings render, the -//! Train button gates on available-and-affordable, and the buy queues the row's spell id. +//! The reference's own `Blizzard_TrainerUI` addon — a client-sorted, collapsible **skill-line +//! tree** with a **dropdown** state filter and a draggable **scroll bar** (decisions 0247/0251) — +//! loaded behind its deps (`UiPanels.xml` + `UIDropDownMenu.xml` + `ScrollTemplates.xml` + +//! `MerchantFrame.xml` for the the stock money frames) and fed a synthetic service list. Covers +//! what only a runtime load exercises: the Lua parses and every referenced global resolves, the +//! tree renders interleaved header/service rows, a header click folds its group, the dropdown +//! filter hides a state, the wheel scrolls the list, the NPC name rides `arg1` into the title, the +//! byte-exact GlobalStrings render, the Train button gates on available-and-affordable, and the buy queues the row's spell id. use benilla_ui::script::{ ExtractedQuad, QuadContent, ScriptValue, SoundRequest, TrainerAbilityReq, TrainerService, diff --git a/crates/benilla-app/src/ui_script/uiparent_tests.rs b/crates/benilla-app/src/ui_script/uiparent_tests.rs index 7f0a02e2..7eca8dc7 100644 --- a/crates/benilla-app/src/ui_script/uiparent_tests.rs +++ b/crates/benilla-app/src/ui_script/uiparent_tests.rs @@ -1,4 +1,4 @@ -//! `assets/ui/UIParent.xml`'s addon-facing helpers, driven from Lua the way an addon drives them. +//! Stock `Interface\FrameXML\UIParent.xml`'s addon-facing helpers, driven from Lua the way an addon drives them. //! //! The panel/ESC machinery in that file is covered by `panel_tests` and `escape_tests`; this is for //! the loose functions the reference's `UIParent.lua` also defines, which benilla itself may never diff --git a/crates/benilla-app/src/ui_script/unit_frame_tests.rs b/crates/benilla-app/src/ui_script/unit_frame_tests.rs index 08b49e1c..f3586270 100644 --- a/crates/benilla-app/src/ui_script/unit_frame_tests.rs +++ b/crates/benilla-app/src/ui_script/unit_frame_tests.rs @@ -603,13 +603,11 @@ fn raid_mark_clicks_through_the_nested_level() { .unwrap(); s.mouse_button(sx as f32, sy as f32, "LeftButton", true); s.mouse_button(sx as f32, sy as f32, "LeftButton", false); - // RED while the `SetRaidTarget` engine binding is absent, and deliberately left that way. // `UnitPopup.xml`'s row calls `SetRaidTargetIcon(menu.unit, mark)`; the definition of that // used to be ours, and since the migration it is the reference's own — `TargetFrame.lua` - // l.486-492 — whose whole body is `SetRaidTarget(unit, 0 or index)`. `SetRaidTarget` is an - // engine verb this house does not have yet, so the click raises - // "attempt to call global 'SetRaidTarget' (a nil value)" and no intent is queued. 1203: it - // gets built, never stubbed. + // l.486-492 — whose whole body is `SetRaidTarget(unit, 0 or index)`. That is the ENGINE + // verb, built by 1820 (`benilla-ui` `script/party.rs`), never the wrapper's name on our + // body: this asserts the intent it queues, and `:638` asserts nothing raised. assert_eq!( s.take_party_requests(), vec![benilla_ui::script::PartyRequest::SetRaidTarget { @@ -1211,8 +1209,8 @@ fn the_party_art_paints_over_the_bars() { let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); // The loot test's prefix (`loot_tests.rs`): PartyFrame's inline