diff --git a/crates/benilla-app/assets/ui/ColorPickerFrame.xml b/crates/benilla-app/assets/ui/ColorPickerFrame.xml deleted file mode 100644 index d4d7992c..00000000 --- a/crates/benilla-app/assets/ui/ColorPickerFrame.xml +++ /dev/null @@ -1,390 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ( OpacityFrame.opacityFunc ) then - OpacityFrame.opacityFunc(); - end - - - - - - - - - - - OpacityFrameCloseButton:Show(); - - - OpacityFrameCloseButton:Hide(); - - - - diff --git a/crates/benilla-app/assets/ui/ErrorsFrame.xml b/crates/benilla-app/assets/ui/ErrorsFrame.xml deleted file mode 100644 index b8a26a70..00000000 --- a/crates/benilla-app/assets/ui/ErrorsFrame.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - UIErrorsFrame_OnLoad() - UIErrorsFrame_OnEvent(event, arg1) - - - - - - - - - - - - - - - - diff --git a/crates/benilla-app/assets/ui/GuildRegistrarFrame.xml b/crates/benilla-app/assets/ui/GuildRegistrarFrame.xml deleted file mode 100644 index 42df2fbc..00000000 --- a/crates/benilla-app/assets/ui/GuildRegistrarFrame.xml +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - this:SetFrameLevel(this:GetFrameLevel() + 2) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MoneyFrame_OnLoad() - MoneyFrame_SetType("STATIC") - - - - - - - - - - - - - - - - - - - - - - - - - - - GuildRegistrar_Purchase(this:GetText()) - GuildRegistrar_RefocusChat() - - - - - - - - - this:RegisterEvent("GUILD_REGISTRAR_SHOW") - this:RegisterEvent("GUILD_REGISTRAR_CLOSED") - - GuildRegistrar_OnEvent(event) - - GuildRegistrar_OnShow() - PlaySound("igQuestListOpen") - - - - PlaySound("igQuestListClose") - CloseGuildRegistrar() - - - - diff --git a/crates/benilla-app/assets/ui/HonorFrame.xml b/crates/benilla-app/assets/ui/HonorFrame.xml deleted file mode 100644 index 12a69a08..00000000 --- a/crates/benilla-app/assets/ui/HonorFrame.xml +++ /dev/null @@ -1,652 +0,0 @@ - - - - - - - - - BenillaHonorRow_OnEnter(self) - GameTooltip:Hide() - - - - - - - - - - - - - - - - - - - BenillaHonorRow_OnLoad(self, HONORABLE_KILLS, NEWBIE_TOOLTIP_HONORABLE_KILLS) - - - - - - - - - - - - - - - - - - - BenillaHonorRow_OnLoad(self, DISHONORABLE_KILLS, NEWBIE_TOOLTIP_DISHONORABLE_KILLS) - - - - - - - - - - - - - - - - - - - BenillaHonorRow_OnLoad(self, HONOR_CONTRIBUTION_POINTS, NEWBIE_TOOLTIP_HONOR_CONTRIBUTION_POINTS) - - - - - - - - - - - - - - - - - - - BenillaHonorRow_OnLoad(self, HONOR_STANDING, NEWBIE_TOOLTIP_HONOR_STANDING) - - - - - - - - - - - - - - - - - - - BenillaHonorRow_OnLoad(self, RANK, NEWBIE_TOOLTIP_RANK) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BenillaTooltip_AddNewbieTipFor(self, RANK, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b, NEWBIE_TOOLTIP_RANK) - GameTooltip:Hide() - - - - - - - - - - - self:SetFrameLevel(self:GetFrameLevel() - 1) - BenillaTooltip_AddNewbieTipFor(self, RANK_POSITION, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b, NEWBIE_TOOLTIP_RANK_POSITION) - GameTooltip:Hide() - - - - - self:SetFrameLevel(self:GetFrameLevel() - 1) - - - - - - HonorFrame_OnLoad(self) - HonorFrame_OnEvent(event) - - - diff --git a/crates/benilla-app/assets/ui/InspectFrame.xml b/crates/benilla-app/assets/ui/InspectFrame.xml index 3c361078..c3e269d1 100644 --- a/crates/benilla-app/assets/ui/InspectFrame.xml +++ b/crates/benilla-app/assets/ui/InspectFrame.xml @@ -54,6 +54,113 @@ (CharacterFrame.xml hit the identical wall) — click-only, so no OnUpdate is wired. --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - this:SetFrameLevel(this:GetFrameLevel() + 2) - - - - - - - - - - - - - - - this:RegisterEvent("PETITION_SHOW") - this:RegisterEvent("PETITION_CLOSED") - - PetitionFrame_OnEvent(event) - PlaySound("igQuestListOpen") - - - PlaySound("igQuestListClose") - ClosePetition() - - - return - - - diff --git a/crates/benilla-app/assets/ui/QuestFrame.xml b/crates/benilla-app/assets/ui/QuestFrame.xml index cab3d730..f927a9cb 100644 --- a/crates/benilla-app/assets/ui/QuestFrame.xml +++ b/crates/benilla-app/assets/ui/QuestFrame.xml @@ -845,10 +845,15 @@ QuestRewardItem_OnClick() - - - - - - - - - - - + + + + + + + + + diff --git a/crates/benilla-app/assets/ui/QuestLogFrame.xml b/crates/benilla-app/assets/ui/QuestLogFrame.xml index 2e64fc48..b903f217 100644 --- a/crates/benilla-app/assets/ui/QuestLogFrame.xml +++ b/crates/benilla-app/assets/ui/QuestLogFrame.xml @@ -69,6 +69,16 @@ to be the real widget method rather than a benilla global. --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - QuestTimerFrame_OnLoad(self) - QuestTimerFrame_OnUpdate() - QuestTimerFrame_OnEvent() - - UIParent_ManageFramePositions() - UIParent_ManageFramePositions() - - - diff --git a/crates/benilla-app/assets/ui/StackSplit.xml b/crates/benilla-app/assets/ui/StackSplit.xml deleted file mode 100644 index 574caae1..00000000 --- a/crates/benilla-app/assets/ui/StackSplit.xml +++ /dev/null @@ -1,314 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - StackSplitFrame_OnHide() - StackSplitFrame_OnChar() - StackSplitFrame_OnKeyDown() - - - diff --git a/crates/benilla-app/assets/ui/UiPanels.xml b/crates/benilla-app/assets/ui/UiPanels.xml index 0b99154c..a4992194 100644 --- a/crates/benilla-app/assets/ui/UiPanels.xml +++ b/crates/benilla-app/assets/ui/UiPanels.xml @@ -1660,6 +1660,45 @@ hideOnEscape = 1, } + -- The guild-charter rename box, ref StaticPopup.lua l.133-160 — **in the reference's own + -- home, which is this file**. It lived in our PetitionFrame.xml on the reasoning that "a + -- popup belongs to the window that raises it"; that is a fine rule and it is not 1.12's, + -- which keeps every dialog in one registry. 1751's twelfth window made the charter the + -- reference's own file, whose Rename button calls `StaticPopup_Show("RENAME_GUILD")` and + -- registers nothing, so the entry had to come here. + -- + -- 24 letters is the server's MAX_CHARTER_NAME, so the box cannot compose a name that will + -- be refused for length. Accept and Enter run the same two lines; the reference spells + -- them out twice (l.139-147), and its Enter arm hides the dialog while its Accept arm does + -- not — the popup engine hides on a plain Accept anyway. + StaticPopupDialogs["RENAME_GUILD"] = { + text = RENAME_GUILD_LABEL, + button1 = ACCEPT, + button2 = CANCEL, + hasEditBox = 1, + maxLetters = 24, + OnAccept = function() + RenamePetition(getglobal(this:GetParent():GetName() .. "EditBox"):GetText()) + end, + EditBoxOnEnterPressed = function() + RenamePetition(getglobal(this:GetParent():GetName() .. "EditBox"):GetText()) + this:GetParent():Hide() + end, + OnShow = function() + getglobal(this:GetName() .. "EditBox"):SetFocus() + end, + OnHide = function() + if ChatFrameEditBox and ChatFrameEditBox:IsVisible() then + ChatFrameEditBox:SetFocus() + end + getglobal(this:GetName() .. "EditBox"):SetText("") + end, + timeout = 0, + exclusive = 1, + whileDead = 1, + hideOnEscape = 1, + } + -- ref UIParent.lua l.324-343 + l.356-360, the four arms on one driver. Each equip arm -- hides the OTHER dialog first — the two questions are mutually exclusive by construction -- (one item, one destination), and the hide is what cancels the record the new question diff --git a/crates/benilla-app/assets/ui/benilla.toc b/crates/benilla-app/assets/ui/benilla.toc index 1ad9d32e..ebfad01e 100644 --- a/crates/benilla-app/assets/ui/benilla.toc +++ b/crates/benilla-app/assets/ui/benilla.toc @@ -317,21 +317,27 @@ UIPanelTemplates.xml # UICheckButtonTemplate and UIPanelButtonTemplate. Not benilla's own options window # (OptionsFrame.xml, far below): these are the shared names addons build panels out of. OptionsFrameTemplates.xml -# The shared colour dialog + its opacity slider (`ColorPickerFrame`, `OpacitySliderFrame`, -# `ColorPickerOkayButton`, `ColorPickerCancelButton`). Last of the "shared FrameXML surface with no -# benilla consumer yet" cluster that runs from UIPanelTemplates.xml down — the same posture as -# MoneyFrame.xml above, and for the same reason: 86 of the 218 corpus addons reach this window (64 -# of those files are `Dewdrop-2.0.lua`, which drives THIS one rather than rolling its own), and -# nothing we ship opens it. The seat is a REQUIREMENT, not tidiness: its Okay/Cancel buttons -# `inherits="GameMenuButtonTemplate"`, which is resolved at LOAD, and that template lives in +# ══ THE COLOUR DIALOG — the reference's own, off the player's chain (1751, window 11) ══ +# `ColorPickerFrame` (a ``), `OpacitySliderFrame`, `ColorPickerOkayButton`, +# `ColorPickerCancelButton`, and the separate `OpacityFrame` beside them. The file ships no `.lua` +# — its whole script is inline, and the one function that drives it +# (`UIDropDownMenuButton_OpenColorPicker`) lives in UIDropDownMenu.lua. +# +# Last of the "shared FrameXML surface with no benilla consumer yet" cluster that runs from +# UIPanelTemplates.xml down, and the swap is exactly why that posture was worth holding: **86 of +# the 218 corpus addons reach this window** (64 of those files are `Dewdrop-2.0.lua`, which drives +# THIS one rather than rolling its own), and nothing we ship opens it — so every one of them is now +# talking to the reference's own frames rather than to our re-expression of them. +# +# THE SEAT IS A REQUIREMENT, not tidiness: the Okay/Cancel buttons +# `inherits="GameMenuButtonTemplate"`, resolved at LOAD, and that template lives in # UIPanelTemplates.xml six lines up (it moved there from GameMenuFrame.xml — the reference's own -# file for it — precisely because GameMenuFrame.xml is deliberately LAST). Everything else it needs -# is far above (Fonts' GameFontNormal/…Small trio; UiPanels' ShowUIPanel/HideUIPanel, its -# UISpecialFrames entry and the ESC rung that cancel-clicks it). UIDropDownMenu.xml, which owns the -# colour-swatch row that OPENS this window, sits above too — but that direction is call-time only -# (`UIDropDownMenuButton_OpenColorPicker` reaches `ColorPickerFrame` by name when the swatch is -# clicked), so the two could sit either way round. -ColorPickerFrame.xml +# file for it — precisely because GameMenuFrame.xml is deliberately LAST, which is also why this +# entry does not follow the reference's own position below it). Everything else it needs is far +# above: Fonts' GameFontNormal trio, and UiPanels' ShowUIPanel/HideUIPanel plus its UISpecialFrames +# entry and the ESC rung that cancel-clicks it. UIDropDownMenu.xml sits above too, but that +# direction is call-time only, so the two could sit either way round. +Interface\FrameXML\ColorPickerFrame.xml # The fullscreen world map (decision 0203 phase 2), over the worldmap host API # (`crate::ui_world_map` feeds it); the 'M' binding (ui_script/input.rs) calls its # ToggleWorldMap(). @@ -397,7 +403,28 @@ BuffFrame.xml # bind. It is reachable only from the dead `enchantTimer` branch above, so it is left absent rather # than stubbed (1203) — the honest state is "nothing calls it", not "we answer it with a lie". Interface\FrameXML\DurabilityFrame.xml -ErrorsFrame.xml +# ══ THE ERROR TOASTS AND THE RAID WARNING — the reference's own (1751, window 14) ══ +# `UIErrorsFrame` (the red/yellow toast strip) and `UIErrorsFrame_OnLoad`/`_OnEvent`, then +# `RaidWarningFrame` and `RaidBossEmoteFrame` with `RaidWarningFrame_OnLoad`/`_OnEvent`. Two files, +# in the reference's own split and its own order: the warning frame anchors `relativeTo= +# "UIErrorsFrame"`, resolved at LOAD, so it cannot precede it. +# +# Our single `ErrorsFrame.xml` held both and is deleted. It declared `RaidWarningFrame` with **no +# `` at all**, and the reason it gave was wrong: *"we already deliver that chat type +# through `ui_chat::feed`, so wiring a second consumer would print every raid warning TWICE"*. +# Checked rather than inherited — `ui_chat` fires `CHAT_MSG_RAID_WARNING` as an ordinary chat event +# and nothing of ours consumes it for a display. So the reference's handler adds the big centre +# text and its `PlaySound("RaidWarning")` **beside** the chat line, which is exactly what 1.12 +# does: the chat window and the warning frame are two consumers of one event there too. +# +# It also brings `RaidBossEmoteFrame`, which our copy withheld on the "no corpus caller, and a +# shadowed name with no caller is building against a guess" rule (1222). That rule is about names +# WE would invent; this one is the reference's own declaration, so there is nothing left to guess. +# +# `ChatTypeInfo["RAID_WARNING"]` comes from ChatFrame.xml far below — read at call time, so the +# order does not bind. +Interface\FrameXML\UIErrorsFrame.xml +Interface\FrameXML\RaidWarning.xml # ══ THE BAG WINDOWS — the reference's own, off the player's chain (decision 1751, window 1) ══ # `ContainerFrame1..12`, `ContainerFrameTemplate`, `ContainerFrameItemButtonTemplate` and the whole # `ToggleBag`/`ToggleBackpack`/`OpenAllBags`/`IsBagOpen`/`ToggleKeyRing` verb family — the real @@ -453,7 +480,7 @@ Interface\FrameXML\MainMenuBarBagButtons.xml # click handler (the reference's `ContainerFrameItemButton_OnClick`) calls `OpenStackSplitFrame`. # Order between the two doesn't matter for correctness (Lua globals resolve at call time, and # neither file's XML `inherits=` reaches into the other's templates) — adjacent for legibility. -StackSplit.xml +Interface\FrameXML\StackSplitFrame.xml # Our ADAPTERS over the reference's own container files — one wrapper, for the keyring tooltip # detour benilla answers differently (0765). Must load AFTER them, since it captures at load the # body it wraps; its own header says what it stopped needing to do when the XML became sourceable. @@ -505,7 +532,7 @@ SkillFrame.xml # declared here, and `inherits=` resolves at LOAD. The reference has the identical edge — its # `HonorFrameTemplates.xml` is ``d by `HonorFrame.xml` and inherited by the LoadOnDemand # `Blizzard_InspectUI`, which loads later still. -HonorFrame.xml +Interface\FrameXML\HonorFrame.xml # The inspect window (decision 0631): another player's paper doll. Beside the character # window it mirrors — it needs the same three (Fonts/UiPanels/GameTooltip) plus # `CharacterFrameTabButtonTemplate` from UiPanels.xml, and nothing from CharacterFrame.xml @@ -651,15 +678,27 @@ GroupLootFrame.xml # art conventions); its title/panel-button labels use the auto-centred ButtonText slot. QuestFrame.xml # The two guild-charter windows (decision 1672): the guild registrar — the window the "How do I -# form a guild?" gossip row opens — and the charter itself, the sheet nine people sign. Loaded -# here, right after QuestFrame, because both wear the QuestGreeting parchment and its QuestFont / +# form a guild?" gossip row opens — and the charter itself, the sheet nine people sign. **Both are +# the reference's own files off the player's chain now** (1751, windows 12 and 13). Loaded here, +# right after QuestFrame, because both wear the QuestGreeting parchment and its QuestFont / # QuestTitleFont objects and read as that family; they need UiPanels (the panel manager seats both, -# and PetitionFrame registers its RENAME_GUILD dialog on the shared popup engine), MoneyFrame (the -# registrar's price rides MoneyFrameTemplate, resolved at LOAD — decision 1580's ordering rule) and -# UIPanelTemplates (the close/action buttons), all far above. The registrar must come first: no -# load-order dependency links them, but the flow does, and the pair reads in the order it is used. -GuildRegistrarFrame.xml -PetitionFrame.xml +# and the RENAME_GUILD dialog the charter raises is registered there, where 1.12 keeps every +# dialog), MoneyFrame (the registrar's price rides MoneyFrameTemplate, resolved at LOAD — decision +# 1580's ordering rule) and UIPanelTemplates (the close/action buttons), all far above. The +# registrar must come first: no load-order dependency links them, but the flow does, and the pair +# reads in the order it is used. +Interface\FrameXML\GuildRegistrarFrame.xml +# ══ THE GUILD CHARTER — the reference's own, off the player's chain (1751, window 12) ══ +# `PetitionFrame` and its nine signature rows, `PetitionFrame_Update`, `MAX_PETITION_SIGNATURES`, +# and the leader/signer button pair that share one anchor. Ours was the same window under the same +# names (decision 1672) with a different expression of the same painter; the reference's file is +# what that expression was written from. +# +# The seat is unchanged and every dependency it names is above: UiPanels (the panel manager seats +# it, and its RENAME_GUILD dialog rides the shared popup engine), MoneyFrame, UIPanelTemplates (the +# close/action buttons `inherits=` at LOAD), and the QuestGreeting parchment family it shares with +# GuildRegistrarFrame directly above. +Interface\FrameXML\PetitionFrame.xml # The quest log window (decision 0088 arc, the quest-log slice): durable player state, not an # NPC session — loaded after MerchantFrame (the BenillaMoney coin helpers it reuses) and # alongside QuestFrame (same arc); the 'L' binding (ui_script/input.rs) calls its @@ -669,7 +708,7 @@ QuestLogFrame.xml # file split. After MinimapCluster (its anchor), UIParent (the manage pass that re-seats it, # and SecondsToTime), GameTooltip (its row hover), and QuestLogFrame — whose window a row # click opens, and whose MAX_QUESTS it shares. -QuestTimerFrame.xml +Interface\FrameXML\QuestTimerFrame.xml ChatFrame.xml # The macro window (decision 0983): the editor + its name/icon popup, driven over the # engine's OWN macro table (`benilla_ui::script::macros` — 1.12 macros have no server diff --git a/crates/benilla-app/src/ui_action/feed_tests.rs b/crates/benilla-app/src/ui_action/feed_tests.rs index c61799b4..de618a34 100644 --- a/crates/benilla-app/src/ui_action/feed_tests.rs +++ b/crates/benilla-app/src/ui_action/feed_tests.rs @@ -415,16 +415,10 @@ fn pre_resolved_lines_land_on_the_errors_frame_in_the_arms_colour() { { let mut script = app.world_mut().non_send_resource_mut::(); script.set_screen_size(1024.0, 768.0); - for file in ["Fonts.xml", "ErrorsFrame.xml"] { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(&script, &doc, &|_| None); - assert!(report.errors.is_empty(), "{file}: {:?}", report.errors); + // The errors frame is the reference's own file since 1751 window 14, so this reads both + // stores through the one loader that speaks them. + for file in ["Fonts.xml", "Interface\\FrameXML\\UIErrorsFrame.xml"] { + crate::ui_script::load_ui_for_test(&script, file); } } 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 30044d65..4adcb718 100644 --- a/crates/benilla-app/src/ui_script/action_bar_tests.rs +++ b/crates/benilla-app/src/ui_script/action_bar_tests.rs @@ -784,7 +784,7 @@ fn shipped_bag_frame_drives_end_to_end() { bar_frames = frames; } } - load_ui(&s, "StackSplit.xml"); + load_ui(&s, "Interface\\FrameXML\\StackSplitFrame.xml"); load_ui(&s, "MerchantFrame.xml"); assert_eq!( diff --git a/crates/benilla-app/src/ui_script/bag_tests.rs b/crates/benilla-app/src/ui_script/bag_tests.rs index 213e424f..b8fa1d8b 100644 --- a/crates/benilla-app/src/ui_script/bag_tests.rs +++ b/crates/benilla-app/src/ui_script/bag_tests.rs @@ -1006,7 +1006,7 @@ fn open_backpack_with_a_five_stack(s: &mut UiScript) -> (f32, f32) { load_xml(s, file); } load_xml(s, "MerchantFrame.xml"); - load_xml(s, "StackSplit.xml"); + load_xml(s, "Interface\\FrameXML\\StackSplitFrame.xml"); s.set_money(0); let mut slots = std::collections::HashMap::new(); @@ -1233,14 +1233,18 @@ fn typing_a_number_into_the_split_spinner_sets_the_count() { "and the label follows" ); - // A second digit appends, then clamps to the 5-stack rather than being thrown away. + // A second digit that would overflow the stack is **IGNORED**, not clamped — the reference's + // `StackSplitFrame_OnChar` writes `this.split` only inside `if split <= this.maxStack` + // (StackSplitFrame.lua l.72-85), so 37 against a 5-stack leaves 3 standing. Our own copy + // clamped to 5 instead, and this assertion was written against that; the window is the + // reference's since 1751 window 17, so the ignore is the behaviour. assert!(s.char_input("7")); assert_eq!( s.eval::("return StackSplitFrame.split").unwrap(), - 5, - "37 against a 5-stack clamps to 5" + 3, + "37 against a 5-stack keeps the 3 — the ref ignores the digit, it does not clamp" ); - // BACKSPACE drops a digit off the clamped value. + // BACKSPACE drops a digit off it. assert!(s.frame_key_input("BACKSPACE"), "the dialog took BACKSPACE"); assert_eq!(s.eval::("return StackSplitFrame.split").unwrap(), 1); @@ -1273,10 +1277,10 @@ fn split_okay_then_a_placement_queues_the_split_move() { assert!(s.eval::("return StackSplitFrame:IsShown()").unwrap()); // Bump the spinner from 1 to 3, then Okay — the carry lands on the cursor. - s.run("BenillaStackSplitRight_Click()").unwrap(); - s.run("BenillaStackSplitRight_Click()").unwrap(); + click(&mut s, "StackSplitRightButton", "LeftButton"); + click(&mut s, "StackSplitRightButton", "LeftButton"); assert_eq!(s.eval::("return StackSplitFrame.split").unwrap(), 3); - s.run("BenillaStackSplitOkay_Click()").unwrap(); + click(&mut s, "StackSplitOkayButton", "LeftButton"); assert!( !s.eval::("return StackSplitFrame:IsShown()").unwrap(), "Okay hides the spinner" @@ -1548,7 +1552,7 @@ fn keyring_surface(s: &UiScript) { load_xml(s, file); } load_xml(s, "MerchantFrame.xml"); - load_xml(s, "ErrorsFrame.xml"); + load_xml(s, "Interface\\FrameXML\\UIErrorsFrame.xml"); } /// **The gate** (decision 0765): no key ⇒ no keyring anywhere on the bar — the button is hidden and 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 f52e5907..525f909d 100644 --- a/crates/benilla-app/src/ui_script/basic_controls_tests.rs +++ b/crates/benilla-app/src/ui_script/basic_controls_tests.rs @@ -7,22 +7,7 @@ use benilla_ui::script::UiScript; -/// One shipped file into `s`, asserting it loaded clean. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// Fonts then BasicControls — the manifest's own order, and the whole dependency this file has. fn basic_controls() -> UiScript { diff --git a/crates/benilla-app/src/ui_script/buff_tests.rs b/crates/benilla-app/src/ui_script/buff_tests.rs index b9e594c2..51d0f5e4 100644 --- a/crates/benilla-app/src/ui_script/buff_tests.rs +++ b/crates/benilla-app/src/ui_script/buff_tests.rs @@ -17,22 +17,7 @@ use benilla_ui::script::{AuraState, ExtractedQuad, QuadContent, UiScript}; -/// Load one shipped `assets/ui/`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; fn harness() -> UiScript { let mut s = UiScript::new().unwrap(); diff --git a/crates/benilla-app/src/ui_script/cast_tests.rs b/crates/benilla-app/src/ui_script/cast_tests.rs index dce0d853..153814ec 100644 --- a/crates/benilla-app/src/ui_script/cast_tests.rs +++ b/crates/benilla-app/src/ui_script/cast_tests.rs @@ -10,22 +10,7 @@ use benilla_ui::script::{ExtractedQuad, QuadContent, ScriptValue, UiScript}; -/// Load one shipped `assets/ui/`, panicking on any loader error (the bag/panel tests' loader). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; fn harness() -> UiScript { let mut s = UiScript::new().unwrap(); diff --git a/crates/benilla-app/src/ui_script/character_tests.rs b/crates/benilla-app/src/ui_script/character_tests.rs index 97b59cce..8e82d9b3 100644 --- a/crates/benilla-app/src/ui_script/character_tests.rs +++ b/crates/benilla-app/src/ui_script/character_tests.rs @@ -18,23 +18,7 @@ use benilla_ui::script::{ UnitCombatStats, UnitState, }; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error (the questlog/panel -/// tests' loader, duplicated so this file is self-contained). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// A Night Elf Warrior, level 12 — the fixture every test below shares for the level/name line. fn player_unit() -> UnitState { @@ -138,6 +122,7 @@ fn backpack_with_fitting_helm() -> benilla_ui::script::ContainerState { /// attack/damage/ranged rows + 5 resistance frames + the model pane + its 2 rotate buttons + chrome). #[test] fn shipped_character_frame_loads_clean() { + let _data = benilla_formats::wow_data_or_skip!(); let s = UiScript::new().unwrap(); load_xml(&s, "Fonts.xml"); load_xml(&s, "MoneyFrame.xml"); @@ -154,6 +139,7 @@ fn shipped_character_frame_loads_clean() { /// and a second toggle closes it again — each transition its own sound. #[test] fn shipped_character_frame_drives_end_to_end() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); load_xml(&s, "Fonts.xml"); @@ -369,6 +355,7 @@ fn shipped_character_frame_drives_end_to_end() { /// page's own quads. Checked on the real extracted draw order, not merely the level integer. #[test] fn close_button_draws_above_the_paper_doll_page() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); load_xml(&s, "Fonts.xml"); @@ -414,6 +401,7 @@ fn close_button_draws_above_the_paper_doll_page() { /// comment) keep `format()` from erroring outright, rather than the window failing to open at all. #[test] fn level_line_survives_no_player_snapshot_yet() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); load_xml(&s, "Fonts.xml"); @@ -447,6 +435,7 @@ fn level_line_survives_no_player_snapshot_yet() { /// the SAME slot cancels: the cursor empties and the dim clears. #[test] fn clicking_an_occupied_doll_slot_picks_it_up_and_locks_it() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); load_xml(&s, "Fonts.xml"); @@ -501,6 +490,7 @@ fn clicking_an_occupied_doll_slot_picks_it_up_and_locks_it() { /// this file's own header comment on the emulation). #[test] fn cursor_update_highlights_fitting_doll_slots_while_holding_a_bag_item() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); load_xml(&s, "Fonts.xml"); @@ -544,6 +534,7 @@ fn cursor_update_highlights_fitting_doll_slots_while_holding_a_bag_item() { /// `(bag, slot)` source, cursor cleared. #[test] fn model_pane_click_auto_equips_a_held_bag_item() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); load_xml(&s, "Fonts.xml"); @@ -581,6 +572,7 @@ fn model_pane_click_auto_equips_a_held_bag_item() { /// armor guy). Repairing it restores both to white. #[test] fn broken_equipped_item_tints_its_doll_slot_red() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); load_xml(&s, "Fonts.xml"); @@ -657,6 +649,7 @@ fn broken_equipped_item_tints_its_doll_slot_red() { /// HERE, not on the director's screen. Zero collected handler errors allowed anywhere. #[test] fn tab_round_trip_with_a_selected_skill_by_point() { + let _data = benilla_formats::wow_data_or_skip!(); use benilla_ui::script::{SkillEntry, SkillsState}; let mut s = UiScript::new().unwrap(); @@ -857,6 +850,7 @@ fn tab_round_trip_with_a_selected_skill_by_point() { /// click-LEFT subtracts); that quirk is quoted, so it is asserted here rather than "corrected". #[test] fn rotate_arrows_tap_twice_and_spin_while_held() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); load_xml(&s, "Fonts.xml"); @@ -950,6 +944,7 @@ fn rotate_arrows_tap_twice_and_spin_while_held() { /// to miss. #[test] fn a_keybind_page_switch_moves_the_tab_row_with_it() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); load_xml(&s, "Fonts.xml"); @@ -964,7 +959,7 @@ fn a_keybind_page_switch_moves_the_tab_row_with_it() { load_xml(&s, "PetPaperDollFrame.xml"); load_xml(&s, "ReputationFrame.xml"); load_xml(&s, "SkillFrame.xml"); - load_xml(&s, "HonorFrame.xml"); + load_xml(&s, "Interface\\FrameXML\\HonorFrame.xml"); s.set_unit("player", Some(player_unit())); // THE INVARIANT the fix rests on: a page's `id=` is its slot in this window's own tab row, and @@ -1060,6 +1055,7 @@ fn a_keybind_page_switch_moves_the_tab_row_with_it() { /// when it passes `this:GetParent()`. #[test] fn an_addons_tab_click_selects_through_the_generic_entry_point() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); load_xml(&s, "Fonts.xml"); diff --git a/crates/benilla-app/src/ui_script/chat_options_tests.rs b/crates/benilla-app/src/ui_script/chat_options_tests.rs index 3bf17ebd..4cc68c27 100644 --- a/crates/benilla-app/src/ui_script/chat_options_tests.rs +++ b/crates/benilla-app/src/ui_script/chat_options_tests.rs @@ -13,22 +13,7 @@ use benilla_ui::script::UiScript; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The GlobalStrings the menu labels itself with. The app runs the real /// `Interface\FrameXML\GlobalStrings.lua` off the player's own patch chain at boot @@ -62,7 +47,7 @@ fn chat_with_menu() -> UiScript { "UIDropDownMenu.xml", "ScrollTemplates.xml", "UIPanelTemplates.xml", - "ColorPickerFrame.xml", + "Interface\\FrameXML\\ColorPickerFrame.xml", "ChatFrame.xml", ] { load_xml(&s, file); @@ -125,6 +110,7 @@ fn left_click(s: &mut UiScript, frame: &str) { /// options at all" rather than "the menu is missing a row". #[test] fn right_clicking_a_chat_tab_opens_its_options_menu() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_with_menu(); assert!( s.eval::("return not DropDownList1:IsVisible()") @@ -173,6 +159,7 @@ fn right_clicking_a_chat_tab_opens_its_options_menu() { /// change. (The reference's own fork: the right-button arm returns before the select.) #[test] fn a_left_click_still_selects_the_tab_and_opens_no_menu() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_with_menu(); left_click(&mut s, "ChatFrame2Tab"); assert_eq!( @@ -206,6 +193,7 @@ fn a_left_click_still_selects_the_tab_and_opens_no_menu() { /// `204/255`, not as 0.8. #[test] fn the_background_row_opens_the_picker_and_its_opacity_slider_drives_the_window() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_with_menu(); right_click(&mut s, "ChatFrame1Tab"); @@ -274,6 +262,7 @@ fn the_background_row_opens_the_picker_and_its_opacity_slider_drives_the_window( /// hover ramp, which is the look the director signed off in 0288. #[test] fn the_shipped_window_still_fades_zero_to_a_quarter() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_with_menu(); s.mouse_move(1500.0, 850.0); for _ in 0..4 { @@ -301,6 +290,7 @@ fn the_shipped_window_still_fades_zero_to_a_quarter() { /// pick moves both the live font and the stored `SIZE`. #[test] fn the_font_size_submenu_resizes_the_window_and_stores_the_pick() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_with_menu(); right_click(&mut s, "ChatFrame1Tab"); @@ -343,6 +333,7 @@ fn the_font_size_submenu_resizes_the_window_and_stores_the_pick() { /// parent, so a single shared capsule would have written window 1 whichever tab was clicked. #[test] fn each_tabs_menu_writes_its_own_window() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_with_menu(); right_click(&mut s, "ChatFrame2Tab"); assert_eq!( @@ -370,6 +361,7 @@ fn each_tabs_menu_writes_its_own_window() { /// `previousValues` contract, which the reference reaches through the same `cancelFunc` field. #[test] fn cancelling_the_picker_puts_the_window_back() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_with_menu(); // Start from a non-default look so "restored" is distinguishable from "reset". s.run("FCF_SetWindowAlpha(ChatFrame1, 0.4) FCF_SetWindowColor(ChatFrame1, 0.2, 0.4, 0.6)") @@ -405,6 +397,7 @@ fn cancelling_the_picker_puts_the_window_back() { /// the fade latch. #[test] fn the_restore_event_repaints_the_window_from_the_store() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_with_menu(); s.set_chat_window_looks([( 0, diff --git a/crates/benilla-app/src/ui_script/chat_resize_tests.rs b/crates/benilla-app/src/ui_script/chat_resize_tests.rs index 7d841db3..cf49c057 100644 --- a/crates/benilla-app/src/ui_script/chat_resize_tests.rs +++ b/crates/benilla-app/src/ui_script/chat_resize_tests.rs @@ -11,22 +11,7 @@ use benilla_ui::script::UiScript; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The chat dock with everything its tab menu and its grips reach under it. fn chat_ui() -> UiScript { @@ -40,7 +25,7 @@ fn chat_ui() -> UiScript { "UIDropDownMenu.xml", "ScrollTemplates.xml", "UIPanelTemplates.xml", - "ColorPickerFrame.xml", + "Interface\\FrameXML\\ColorPickerFrame.xml", "ChatFrame.xml", ] { load_xml(&s, file); @@ -102,6 +87,7 @@ fn grab_grip(s: &mut UiScript, grip: &str) -> (f32, f32) { /// `GetChatWindowInfo` answers, because it is the chat-cache's own `LOCKED 1`. #[test] fn both_dock_windows_ship_locked() { + let _data = benilla_formats::wow_data_or_skip!(); let s = chat_ui(); for i in 1..=2 { assert_eq!( @@ -133,6 +119,7 @@ fn both_dock_windows_ship_locked() { /// locked, `LOCK_WINDOW` when it is not, `notCheckable`. #[test] fn the_tab_menus_lock_row_toggles_the_window_and_flips_its_label() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_ui(); right_click(&mut s, "ChatFrame1Tab"); // Shipped locked, so the row offers the way OUT of it. @@ -183,6 +170,7 @@ fn the_tab_menus_lock_row_toggles_the_window_and_flips_its_label() { /// it — see the template's note), and `FCF_Resize` must refuse even if something did reach it. #[test] fn a_locked_window_refuses_a_grip_drag() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_ui(); let before = width(&mut s); assert_eq!(before, 430.0, "the authored width"); @@ -229,6 +217,7 @@ fn a_locked_window_refuses_a_grip_drag() { /// so a window held past its minimum stops shrinking and starts *walking*. #[test] fn an_unlocked_bottom_right_grip_resizes_and_clamps_at_the_bounds() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_ui(); s.run("FCF_SetLocked(ChatFrame1, nil)").unwrap(); assert!( @@ -277,6 +266,7 @@ fn an_unlocked_bottom_right_grip_resizes_and_clamps_at_the_bounds() { /// the session. #[test] fn the_release_ends_the_resize_from_anywhere_on_screen() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_ui(); s.run("FCF_SetLocked(ChatFrame1, nil)").unwrap(); let (x, y) = grab_grip(&mut s, "ChatFrame1ResizeBottomRight"); @@ -308,6 +298,7 @@ fn the_release_ends_the_resize_from_anywhere_on_screen() { /// held-spell dismissal working on the same button. #[test] fn the_body_drag_moves_an_unlocked_window_and_a_locked_one_stays_put() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_ui(); let (cx, cy) = centre(&mut s, "ChatFrame1"); let start = left(&mut s); @@ -348,6 +339,7 @@ fn the_body_drag_moves_an_unlocked_window_and_a_locked_one_stays_put() { /// back on the bottom-stack seat. #[test] fn a_moved_window_is_user_placed_and_the_managed_pass_skips_it() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_ui(); // The managed pass owns the seat to begin with — the control for the assertion below. s.run("UIParent_ManageFramePositions()").unwrap(); @@ -388,6 +380,7 @@ fn a_moved_window_is_user_placed_and_the_managed_pass_skips_it() { /// seat it into a *fresh* VM whose windows are all on their authored anchors. #[test] fn the_geometry_round_trips_through_the_save_file() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_ui(); s.run("FCF_SetLocked(ChatFrame1, nil)").unwrap(); @@ -455,6 +448,7 @@ fn the_geometry_round_trips_through_the_save_file() { /// so the handles appear with the box and are invisible without it. #[test] fn the_grip_art_follows_the_windows_reveal_and_tint() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_ui(); // Off-hover, at the shipped alpha-0 base: everything in the set is invisible. s.run("BenillaFCF.hover = false FCF_OnUpdate(1.0)").unwrap(); @@ -497,6 +491,7 @@ fn the_grip_art_follows_the_windows_reveal_and_tint() { /// clause the box would fade out from under the hand holding it. #[test] fn a_drag_in_flight_holds_the_chrome_visible() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_ui(); s.run("FCF_SetLocked(ChatFrame1, nil)").unwrap(); grab_grip(&mut s, "ChatFrame1ResizeBottomRight"); @@ -524,6 +519,7 @@ fn a_drag_in_flight_holds_the_chrome_visible() { /// `FCF_Get_ChatLocked()` gate, which is the first line of both verbs. #[test] fn the_chat_locked_global_overrides_the_per_window_lock() { + let _data = benilla_formats::wow_data_or_skip!(); let s = chat_ui(); s.run("FCF_SetLocked(ChatFrame1, nil)").unwrap(); assert!(s @@ -556,6 +552,7 @@ fn the_chat_locked_global_overrides_the_per_window_lock() { /// reference's third gate — `isDocked and chatFrame ~= DEFAULT_CHAT_FRAME`. #[test] fn the_docked_combat_log_cannot_be_moved_or_resized_on_its_own() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = chat_ui(); s.run("FCF_SetLocked(ChatFrame2, nil)").unwrap(); assert!( diff --git a/crates/benilla-app/src/ui_script/chat_tests.rs b/crates/benilla-app/src/ui_script/chat_tests.rs index b05e7294..3d5cc85f 100644 --- a/crates/benilla-app/src/ui_script/chat_tests.rs +++ b/crates/benilla-app/src/ui_script/chat_tests.rs @@ -7,22 +7,7 @@ use benilla_ui::script::{ExtractedQuad, QuadContent, UiScript}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The full ChatFrame stack (fonts first, so the FontString's `inherits="ChatFontNormal"` resolves). fn chat_frame() -> UiScript { diff --git a/crates/benilla-app/src/ui_script/cinematic_tests.rs b/crates/benilla-app/src/ui_script/cinematic_tests.rs index 93c47e5f..e39b2eeb 100644 --- a/crates/benilla-app/src/ui_script/cinematic_tests.rs +++ b/crates/benilla-app/src/ui_script/cinematic_tests.rs @@ -15,17 +15,7 @@ use benilla_ui::script::UiScript; -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!(report.errors.is_empty(), "{file}: {:?}", report.errors); -} +use super::test_ui::load_ui as load_xml; /// The frame tree a cinematic actually runs against: `UIParent` (whose `ShowUIPanel` the frame's /// `CINEMATIC_START` arm calls) and the cinematic frame itself. 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 c9d32be3..dfbbaf98 100644 --- a/crates/benilla-app/src/ui_script/color_picker_tests.rs +++ b/crates/benilla-app/src/ui_script/color_picker_tests.rs @@ -9,22 +9,7 @@ use benilla_ui::script::{QuadContent, UiScript}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The manifest prefix the picker needs: fonts, the panel manager (`ShowUIPanel`/`HideUIPanel`, /// `UISpecialFrames`, the ESC chain), the shared widget kit (`GameMenuButtonTemplate`), then the @@ -40,7 +25,7 @@ fn picker() -> UiScript { "UIDropDownMenu.xml", "ScrollTemplates.xml", "UIPanelTemplates.xml", - "ColorPickerFrame.xml", + "Interface\\FrameXML\\ColorPickerFrame.xml", ] { load_xml(&s, file); } @@ -73,6 +58,7 @@ fn after_round_trip(r: f64, g: f64, b: f64) -> (f64, f64, f64) { /// `ColorPickerOkayButton` is nil. #[test] fn the_named_pieces_exist_and_their_scripts_are_fetchable() { + let _data = benilla_formats::wow_data_or_skip!(); let s = picker(); assert!(s .eval::("return ColorPickerFrame ~= nil and ColorPickerFrame.SetColorRGB ~= nil") @@ -110,6 +96,7 @@ fn the_named_pieces_exist_and_their_scripts_are_fetchable() { /// this test while the swatch drew nothing. What the renderer receives is the only honest witness. #[test] fn set_color_rgb_paints_the_swatch_and_reads_back_the_widgets_colour() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = picker(); s.run("ShowUIPanel(ColorPickerFrame)").unwrap(); s.run("ColorPickerFrame:SetColorRGB(0.2, 0.4, 0.8)") @@ -139,6 +126,7 @@ fn set_color_rgb_paints_the_swatch_and_reads_back_the_widgets_colour() { /// WIDTH with it. Both arms of the reference's `OnShow` (l.161-170). #[test] fn has_opacity_shows_the_slider_and_widens_the_window() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = picker(); // Without it: no slider, the narrow window. (`GetWidth` reports the *resolved* rect, so the @@ -179,6 +167,7 @@ fn has_opacity_shows_the_slider_and_widens_the_window() { /// and the reference's own `` (l.146-152). #[test] fn the_opacity_slider_drives_opacity_func_on_every_change() { + let _data = benilla_formats::wow_data_or_skip!(); let s = picker(); s.run( r#" @@ -247,6 +236,7 @@ fn dewdrop_open(s: &UiScript, r: f64, g: f64, b: f64, opacity: f64) { /// quantized colour and the slider-derived alpha, and the window closes. #[test] fn the_dewdrop_sequence_commits_on_okay() { + let _data = benilla_formats::wow_data_or_skip!(); let s = picker(); dewdrop_open(&s, 0.1, 0.5, 0.9, 0.25); assert!(s.errors().is_empty(), "{:?}", s.errors()); @@ -296,6 +286,7 @@ fn the_dewdrop_sequence_commits_on_okay() { /// in with, and it does it by *calling `cancelFunc`* — the window has no memory of its own. #[test] fn cancel_restores_the_previous_colour_through_cancel_func() { + let _data = benilla_formats::wow_data_or_skip!(); let s = picker(); dewdrop_open(&s, 0.1, 0.5, 0.9, 0.25); @@ -331,6 +322,7 @@ fn cancel_restores_the_previous_colour_through_cancel_func() { /// open behind it. #[test] fn escape_cancels_rather_than_merely_hiding() { + let _data = benilla_formats::wow_data_or_skip!(); let s = picker(); dewdrop_open(&s, 0.1, 0.5, 0.9, 0.25); s.run("ColorPickerFrame:SetColorRGB(1, 0, 0)").unwrap(); @@ -356,6 +348,7 @@ fn escape_cancels_rather_than_merely_hiding() { /// this library. #[test] fn ace_console_can_chain_the_okay_buttons_onclick() { + let _data = benilla_formats::wow_data_or_skip!(); let s = picker(); s.run( r#" @@ -392,6 +385,7 @@ fn ace_console_can_chain_the_okay_buttons_onclick() { /// world's windows. #[test] fn the_picker_is_a_uispecialframe_and_close_windows_puts_it_away() { + let _data = benilla_formats::wow_data_or_skip!(); let s = picker(); let listed: bool = s .eval( @@ -426,6 +420,7 @@ fn the_picker_is_a_uispecialframe_and_close_windows_puts_it_away() { /// exact one FloatingChatFrame's colour rows use. #[test] fn a_dropdown_row_with_has_color_swatch_opens_the_picker_and_cancel_restores() { + let _data = benilla_formats::wow_data_or_skip!(); let s = picker(); s.run( r#" @@ -506,6 +501,7 @@ fn a_dropdown_row_with_has_color_swatch_opens_the_picker_and_cancel_restores() { /// menu row from sprouting a colour button. #[test] fn a_row_without_the_flag_has_no_swatch() { + let _data = benilla_formats::wow_data_or_skip!(); let s = picker(); s.run( r#" @@ -536,6 +532,7 @@ fn a_row_without_the_flag_has_no_swatch() { /// the picker addresses it by name. #[test] fn the_shipped_window_carries_the_wheel_at_the_references_geometry() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = picker(); s.run("ShowUIPanel(ColorPickerFrame)").unwrap(); s.resolve(); @@ -593,6 +590,7 @@ fn the_shipped_window_carries_the_wheel_at_the_references_geometry() { /// The click is at the wheel's right rim, which the pick law makes 180° — cyan. #[test] fn a_click_on_the_wheel_reaches_the_callers_func() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = picker(); // Dewdrop-2.0.lua l.425-465's block, as transcribed in this file's other tests. s.run( @@ -641,6 +639,7 @@ fn a_click_on_the_wheel_reaches_the_callers_func() { /// if the content is (decision 1592 §4). #[test] fn the_generated_art_reaches_the_renderer_carrying_only_what_moves_a_pixel() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = picker(); s.run("ColorPickerFrame:SetColorRGB(0.15, 0.55, 0.75); ShowUIPanel(ColorPickerFrame)") .unwrap(); diff --git a/crates/benilla-app/src/ui_script/combat_text_tests.rs b/crates/benilla-app/src/ui_script/combat_text_tests.rs index a6e5ca98..024d4383 100644 --- a/crates/benilla-app/src/ui_script/combat_text_tests.rs +++ b/crates/benilla-app/src/ui_script/combat_text_tests.rs @@ -4,23 +4,7 @@ use benilla_ui::script::{ScriptValue, UiScript, UnitState}; -/// Load one shipped `assets/ui/` (the panel tests' loader, duplicated to stay -/// self-contained), panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; fn load_combat_text() -> UiScript { let mut s = UiScript::new().unwrap(); diff --git a/crates/benilla-app/src/ui_script/dressup_tests.rs b/crates/benilla-app/src/ui_script/dressup_tests.rs index fe8407c3..9f07a1df 100644 --- a/crates/benilla-app/src/ui_script/dressup_tests.rs +++ b/crates/benilla-app/src/ui_script/dressup_tests.rs @@ -32,7 +32,7 @@ const ROOM_UI: &[&str] = &[ "UnitPopup.xml", "Interface\\FrameXML\\ItemRef.xml", "MerchantFrame.xml", - "StackSplit.xml", + "Interface\\FrameXML\\StackSplitFrame.xml", "DressUpFrame.xml", "ChatFrame.xml", ]; diff --git a/crates/benilla-app/src/ui_script/dropdown_tests.rs b/crates/benilla-app/src/ui_script/dropdown_tests.rs index 6f9500f5..e79836ff 100644 --- a/crates/benilla-app/src/ui_script/dropdown_tests.rs +++ b/crates/benilla-app/src/ui_script/dropdown_tests.rs @@ -12,21 +12,7 @@ use benilla_ui::script::UiScript; -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The production prefix the lists need (ui_script/mod.rs order): the fonts (this OnLoad reads a /// real font height off Button1's NormalText), UIParent (the lists declare `parent="UIParent"`), diff --git a/crates/benilla-app/src/ui_script/enchant_confirm_tests.rs b/crates/benilla-app/src/ui_script/enchant_confirm_tests.rs index 55ee5ace..ada479d3 100644 --- a/crates/benilla-app/src/ui_script/enchant_confirm_tests.rs +++ b/crates/benilla-app/src/ui_script/enchant_confirm_tests.rs @@ -10,22 +10,7 @@ use benilla_ui::script::{EnchantConfirm, ScriptValue, UiScript}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; fn setup() -> UiScript { let mut s = UiScript::new().unwrap(); diff --git a/crates/benilla-app/src/ui_script/errors_tests.rs b/crates/benilla-app/src/ui_script/errors_tests.rs index d19b5ff7..a5295d07 100644 --- a/crates/benilla-app/src/ui_script/errors_tests.rs +++ b/crates/benilla-app/src/ui_script/errors_tests.rs @@ -10,23 +10,7 @@ use benilla_ui::script::{ExtractedQuad, QuadContent, ScriptValue, UiScript}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error (the panel/quest -/// tests' loader, duplicated so this file is self-contained). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The toast lines as drawn, **top row first**, each with its colour+alpha and its band bottom. fn toast_lines(s: &mut UiScript) -> Vec<(String, [f32; 4], f32)> { @@ -55,7 +39,7 @@ fn info_and_error_messages_stack_hold_and_expire() { let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); load_xml(&s, "Fonts.xml"); - load_xml(&s, "ErrorsFrame.xml"); + load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml"); // Empty at load. The frame itself is shown — a MessageFrame with nothing to say simply draws // nothing, where the hand-rolled version had to `Hide()` itself. @@ -126,7 +110,7 @@ fn an_error_toast_draws_over_an_open_panel_window() { load_xml(&s, "Fonts.xml"); load_xml(&s, "MoneyFrame.xml"); load_xml(&s, "UiPanels.xml"); - load_xml(&s, "ErrorsFrame.xml"); + load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml"); load_xml(&s, "GameTooltip.xml"); load_xml(&s, "Cooldown.xml"); load_xml(&s, "MerchantFrame.xml"); // BenillaMoney_* — QuestLogDetail's reward money row diff --git a/crates/benilla-app/src/ui_script/escape_tests.rs b/crates/benilla-app/src/ui_script/escape_tests.rs index dd5cd340..cf52ebe2 100644 --- a/crates/benilla-app/src/ui_script/escape_tests.rs +++ b/crates/benilla-app/src/ui_script/escape_tests.rs @@ -231,7 +231,7 @@ fn escape_closes_an_open_stack_split_frame() { } load_xml(&s, "MerchantFrame.xml"); // ContainerFrameItemButton_OnClick reads MerchantFrame load_xml(&s, "ChatFrame.xml"); // …and ChatFrameEditBox, the shift fork's first test - load_xml(&s, "StackSplit.xml"); + load_xml(&s, "Interface\\FrameXML\\StackSplitFrame.xml"); s.set_money(0); let mut slots = std::collections::HashMap::new(); diff --git a/crates/benilla-app/src/ui_script/fade_tests.rs b/crates/benilla-app/src/ui_script/fade_tests.rs index 99282d9f..70e2c4f0 100644 --- a/crates/benilla-app/src/ui_script/fade_tests.rs +++ b/crates/benilla-app/src/ui_script/fade_tests.rs @@ -5,24 +5,7 @@ use benilla_ui::script::UiScript; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error — the same -/// per-file loader every `ui_script` test file carries (these tests only ever need -/// `UiPanels.xml`, where the fade kit lives). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// **The idle fade driver parks itself** (decision 1396's class, the audit's driver-hide item): /// with `FADEFRAMES` empty there is nothing to walk, so the driver's OnUpdate hides its own frame diff --git a/crates/benilla-app/src/ui_script/faux_scroll_tests.rs b/crates/benilla-app/src/ui_script/faux_scroll_tests.rs index f4452656..7b8eae64 100644 --- a/crates/benilla-app/src/ui_script/faux_scroll_tests.rs +++ b/crates/benilla-app/src/ui_script/faux_scroll_tests.rs @@ -17,22 +17,7 @@ use benilla_ui::script::UiScript; -/// One shipped file into `s`, asserting it loaded clean. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// A document written here in the test, loaded against the templates already registered — the /// cross-file template registry is on the `Model`, so an inline doc reaches `ScrollTemplates.xml`'s 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 42da56b0..7b355f0c 100644 --- a/crates/benilla-app/src/ui_script/frame_flag_gate.rs +++ b/crates/benilla-app/src/ui_script/frame_flag_gate.rs @@ -287,11 +287,6 @@ const KNOWN: &[Known] = &[ flag: Flag::Mouse, why: "inherits BenillaMerchantItemTemplate", }, - Known { - frame: "HonorFrameProgressBar", - flag: Flag::Mouse, - why: "our honour bar carries its own hover tooltip; the reference's page has none", - }, Known { frame: "WorldMapFrame", flag: Flag::Mouse, diff --git a/crates/benilla-app/src/ui_script/friends_tests.rs b/crates/benilla-app/src/ui_script/friends_tests.rs index 0aa4b332..17ec34fe 100644 --- a/crates/benilla-app/src/ui_script/friends_tests.rs +++ b/crates/benilla-app/src/ui_script/friends_tests.rs @@ -9,39 +9,7 @@ use benilla_ui::script::{FriendInfo, SocialRequest, SocialState, UiScript, WhoInfo}; -/// Load one shipped `assets/ui/`, panicking on any loader error — **and on any -/// unknown-template warning**. -/// -/// That second check is not decoration. `inherits=` a template this house doesn't ship is a -/// *warning*, not an error: the frame is still created, just with none of the template's art or -/// size. Every test below stayed green while all eight action buttons and the close button were -/// invisible, because a bare Button still clicks. Only a live run showed it. The guard is here so -/// the next window cannot repeat it. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); - let missing: Vec<&String> = report - .warnings - .iter() - .filter(|w| w.contains("unknown template")) - .collect(); - assert!( - missing.is_empty(), - "{file}: inherits a template this house does not ship (the frame loads, its ART does \ - not): {missing:?}" - ); -} +use super::test_ui::load_ui_strict as load_xml; /// The window's own manifest slice, in `load_default_ui` order. fn setup() -> UiScript { diff --git a/crates/benilla-app/src/ui_script/guild_tests.rs b/crates/benilla-app/src/ui_script/guild_tests.rs index 05573471..5a3befac 100644 --- a/crates/benilla-app/src/ui_script/guild_tests.rs +++ b/crates/benilla-app/src/ui_script/guild_tests.rs @@ -22,40 +22,7 @@ use benilla_ui::script::{GuildState, ScriptValue, UiScript, UnitState}; -/// Load one shipped `assets/ui/`, panicking on any loader error — **and on any -/// unknown-template warning**. -/// -/// Copied from `friends_tests` on purpose, and the reason is its own: `inherits=` a template this -/// house doesn't ship is a *warning*, not an error — the frame is still created, just with none of -/// the template's art or size. Every social-window test stayed green while all eight action buttons -/// and the close button were invisible, because a bare Button still clicks (decision 0672). The -/// guild pane inherits four shared templates from `UIPanelTemplates.xml` and four local ones; this -/// is what makes a typo in any of the eight loud. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); - let missing: Vec<&String> = report - .warnings - .iter() - .filter(|w| w.contains("unknown template")) - .collect(); - assert!( - missing.is_empty(), - "{file}: inherits a template this house does not ship (the frame loads, its ART does \ - not): {missing:?}" - ); -} +use super::test_ui::load_ui_strict as load_xml; /// The guild engine API, stood in for in Lua (see the module header). /// diff --git a/crates/benilla-app/src/ui_script/honor_frame_tests.rs b/crates/benilla-app/src/ui_script/honor_frame_tests.rs index 9bd8524b..6977993f 100644 --- a/crates/benilla-app/src/ui_script/honor_frame_tests.rs +++ b/crates/benilla-app/src/ui_script/honor_frame_tests.rs @@ -19,23 +19,7 @@ use benilla_ui::script::{HonorState, UiScript, UnitState}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error (the -/// character/reputation tests' loader, duplicated so this file is self-contained). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The fixture snapshot — a rank-12 Alliance character with a figure in every bucket, all thirteen /// distinct so a swapped pair of rows cannot pass. Deliberately the same numbers as the protocol @@ -92,7 +76,7 @@ fn load_page(s: &UiScript) { "UIPanelTemplates.xml", "OptionsFrameTemplates.xml", "CharacterFrame.xml", - "HonorFrame.xml", + "Interface\\FrameXML\\HonorFrame.xml", ] { load_xml(s, file); } @@ -138,6 +122,7 @@ fn text(s: &mut UiScript, frame: &str) -> String { /// standing against a kill count — fails here and only here. #[test] fn every_figure_lands_in_its_own_row() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = shown_honor_page(); for (frame, want) in [ ("HonorFrameCurrentHKValue", "17"), @@ -164,6 +149,7 @@ fn every_figure_lands_in_its_own_row() { /// makes it impossible to ship. #[test] fn the_title_is_the_internal_rank_and_the_badge_is_the_visual_one() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = shown_honor_page(); assert_eq!(text(&mut s, "HonorFrameCurrentPVPTitle"), "Knight-Captain"); // Internal 12 → visual 8. The line reads "(Rank 8)", never "(Rank 12)". @@ -186,6 +172,7 @@ fn the_title_is_the_internal_rank_and_the_badge_is_the_visual_one() { /// badge. The nil is the mechanism, so this is the case that proves the pane never invents a title. #[test] fn an_unranked_character_reads_none_and_shows_no_badge() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = shown_honor_page(); s.set_honor(Some(HonorState { rank: 0, @@ -217,6 +204,7 @@ fn an_unranked_character_reads_none_and_shows_no_badge() { /// resolved — a bar with no colour at all would read as a broken pane. #[test] fn the_bar_takes_the_fraction_and_the_faction_colour() { + let _data = benilla_formats::wow_data_or_skip!(); let s = shown_honor_page(); // Against the binding's own arithmetic, not against `191/255`. The client MULTIPLIES by the // f32 nearest 1/255 (`0x3B808081`, wow-re `honor-panel-law.md` `0x51aace`) rather than @@ -255,6 +243,7 @@ fn the_bar_takes_the_fraction_and_the_faction_colour() { /// the flag's *derivation from the event name* is the half that can be got wrong. #[test] fn a_kill_repaints_the_session_but_not_the_week() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = shown_honor_page(); // Everything moves in the snapshot — including a weekly figure, which is the bait. s.set_honor(Some(HonorState { @@ -262,8 +251,7 @@ fn a_kill_repaints_the_session_but_not_the_week() { this_week_hk: 124, ..state() })); - s.run(r#"HonorFrame_OnEvent("PLAYER_PVP_KILLS_CHANGED")"#) - .unwrap(); + s.fire_event("PLAYER_PVP_KILLS_CHANGED", vec![]); s.resolve(); assert_eq!( text(&mut s, "HonorFrameCurrentHKValue"), @@ -277,8 +265,7 @@ fn a_kill_repaints_the_session_but_not_the_week() { ); // World entry is the flag that says "repaint those too". - s.run(r#"HonorFrame_OnEvent("PLAYER_ENTERING_WORLD")"#) - .unwrap(); + s.fire_event("PLAYER_ENTERING_WORLD", vec![]); s.resolve(); assert_eq!(text(&mut s, "HonorFrameThisWeekHKValue"), "124"); assert!(s.errors().is_empty(), "script errors: {:?}", s.errors()); @@ -378,7 +365,7 @@ fn shown_inspect_honor_page() -> UiScript { "GameTooltip.xml", // Before InspectFrame.xml — the honor page inherits this file's row templates and calls // its two shared painters, and `inherits=` resolves at load (the manifest's own order). - "HonorFrame.xml", + "Interface\\FrameXML\\HonorFrame.xml", "InspectFrame.xml", ] { load_xml(&s, file); @@ -406,6 +393,7 @@ fn shown_inspect_honor_page() -> UiScript { /// not the player. Everything the character page's row test pins, on the other feed. #[test] fn the_inspect_page_paints_the_reply_it_holds() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = shown_inspect_honor_page(); for (frame, want) in [ ("BenillaInspectHonorFrameCurrentHKValue", "17"), @@ -454,6 +442,7 @@ fn the_inspect_page_paints_the_reply_it_holds() { /// happens to be held looks identical either way. #[test] fn the_page_asks_only_when_it_holds_nothing() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = shown_inspect_honor_page(); // Held: the open above consumed no request. assert_eq!( diff --git a/crates/benilla-app/src/ui_script/inspect_tests.rs b/crates/benilla-app/src/ui_script/inspect_tests.rs index 29449029..eeaf2ec8 100644 --- a/crates/benilla-app/src/ui_script/inspect_tests.rs +++ b/crates/benilla-app/src/ui_script/inspect_tests.rs @@ -35,22 +35,7 @@ fn reach(dist_sq: f64) -> UnitReach { } } -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The inspected player: a Dwarf Paladin, level 34. fn target_unit() -> UnitState { @@ -132,7 +117,7 @@ fn armed() -> UiScript { // Before InspectFrame.xml, and required rather than tidy: this window's honor page inherits // HonorFrame.xml's five row templates and `inherits=` resolves at LOAD, so without it the // twelve honor rows materialize bare (decision 1512; the manifest states the same order). - load_xml(&s, "HonorFrame.xml"); + load_xml(&s, "Interface\\FrameXML\\HonorFrame.xml"); load_xml(&s, "InspectFrame.xml"); s.set_unit("target", Some(target_unit())); s.set_inspect(Some(inspect_view("target"))); @@ -144,6 +129,7 @@ fn armed() -> UiScript { /// The loader itself: the window and its 19 slots + model pane materialize with no errors. #[test] fn shipped_inspect_frame_loads_clean() { + let _data = benilla_formats::wow_data_or_skip!(); let s = UiScript::new().unwrap(); load_xml(&s, "Fonts.xml"); load_xml(&s, "MoneyFrame.xml"); @@ -152,7 +138,7 @@ fn shipped_inspect_frame_loads_clean() { // Before InspectFrame.xml, and required rather than tidy: this window's honor page inherits // HonorFrame.xml's five row templates and `inherits=` resolves at LOAD, so without it the // twelve honor rows materialize bare (decision 1512; the manifest states the same order). - load_xml(&s, "HonorFrame.xml"); + load_xml(&s, "Interface\\FrameXML\\HonorFrame.xml"); load_xml(&s, "InspectFrame.xml"); // All 19 slots exist and carry their GetInventorySlotInfo id (1..=19, no ammo slot). for (name, id) in [ @@ -174,6 +160,7 @@ fn shipped_inspect_frame_loads_clean() { /// call in range does both. A `CanInspect` stuck truthy passes every other test in this file. #[test] fn inspect_unit_refuses_out_of_range() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = armed(); // 11 yards (d² = 121) — past the verified 100.0 threshold. s.set_unit_reach(HashMap::from([("target".to_string(), reach(121.0))])); @@ -212,6 +199,7 @@ fn inspect_unit_refuses_out_of_range() { /// silently normalizes — hence a test on the boundary itself. #[test] fn range_predicates_transcribe_the_verified_thresholds() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = armed(); for (d2, can_inspect, interact1) in [ (99.9_f64, true, true), @@ -301,6 +289,7 @@ fn range_predicates_transcribe_the_verified_thresholds() { /// slot; the inspected token must read the foreign one and `"player"` must still read ours. #[test] fn inventory_bindings_route_by_unit_token() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = armed(); s.set_inventory_slots(own_slots()); @@ -336,6 +325,7 @@ fn inventory_bindings_route_by_unit_token() { /// moving the booth yaw, and closing firing `ClearInspectPlayer`. #[test] fn shipped_inspect_frame_drives_end_to_end() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = armed(); // Hidden at load, and no sound queued (never transitions on startup). @@ -473,6 +463,7 @@ fn shipped_inspect_frame_drives_end_to_end() { /// second one non-obvious. #[test] fn the_active_tab_is_inert_and_toggle_inspect_closes() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = armed(); s.run(r#"InspectUnit("target")"#).unwrap(); let _ = s.take_sounds(); diff --git a/crates/benilla-app/src/ui_script/instance_tests.rs b/crates/benilla-app/src/ui_script/instance_tests.rs index 94032649..fc04bf96 100644 --- a/crates/benilla-app/src/ui_script/instance_tests.rs +++ b/crates/benilla-app/src/ui_script/instance_tests.rs @@ -8,22 +8,7 @@ use benilla_ui::script::UiScript; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The three bindings answer with the reference's own shapes — `IsInInstance` a PAIR, both /// readers `1`/`nil` rather than `true`/`false` (the reference pushes the double 1.0), and diff --git a/crates/benilla-app/src/ui_script/mod.rs b/crates/benilla-app/src/ui_script/mod.rs index fa05ed51..5af9e319 100644 --- a/crates/benilla-app/src/ui_script/mod.rs +++ b/crates/benilla-app/src/ui_script/mod.rs @@ -767,6 +767,13 @@ impl benilla_ui::script::TextMeasure for FixedWidthFont { #[cfg(test)] mod test_ui; +/// [`test_ui::load_ui`] for a test module OUTSIDE `ui_script` — `ui_action::feed_tests` drives the +/// real `UIErrorsFrame` end to end and needs the same both-stores reader everything else uses. +#[cfg(test)] +pub(crate) fn load_ui_for_test(script: &benilla_ui::script::UiScript, entry: &str) -> usize { + test_ui::load_ui(script, entry) +} + #[cfg(test)] mod cinematic_tests; 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 d173502a..bb0861a7 100644 --- a/crates/benilla-app/src/ui_script/money_frame_tests.rs +++ b/crates/benilla-app/src/ui_script/money_frame_tests.rs @@ -15,22 +15,7 @@ use benilla_ui::script::{QuadContent, UiScript}; -/// One shipped file into `s`, asserting it loaded clean. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The kit plus the two frames an addon would declare: one on each template. fn harness(money: u64) -> UiScript { diff --git a/crates/benilla-app/src/ui_script/multibar_stance_tests.rs b/crates/benilla-app/src/ui_script/multibar_stance_tests.rs index 40b7351c..37f8174b 100644 --- a/crates/benilla-app/src/ui_script/multibar_stance_tests.rs +++ b/crates/benilla-app/src/ui_script/multibar_stance_tests.rs @@ -7,22 +7,7 @@ use benilla_ui::script::{ActionSlot, QuadContent, ScriptValue, SpellTooltipView, UiScript}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "loader errors in {file}: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// Load the shipped `UIParent.xml` (UIParent_ManageFramePositions — the stance bar's /// OnShow/OnHide calls it, decision 0272; the runtime loads it before every bar) + 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 d6e25e62..a368ce81 100644 --- a/crates/benilla-app/src/ui_script/panel_template_tests.rs +++ b/crates/benilla-app/src/ui_script/panel_template_tests.rs @@ -30,17 +30,7 @@ use benilla_ui::script::UiScript; -/// One shipped file into `s`, asserting it loaded clean. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string(ui_dir().join(file)).unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; fn ui_dir() -> std::path::PathBuf { std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("assets/ui") 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 5e8ca494..f6e072ab 100644 --- a/crates/benilla-app/src/ui_script/perf_bar_tests.rs +++ b/crates/benilla-app/src/ui_script/perf_bar_tests.rs @@ -7,22 +7,7 @@ use benilla_ui::script::{QuadContent, UiScript}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The bar on a 1024×768 screen. 1024 wide is deliberate: the 1024-wide bar then spans x 0..1024, /// so every ref offset below is also an absolute screen coordinate. diff --git a/crates/benilla-app/src/ui_script/pet_bar_tests.rs b/crates/benilla-app/src/ui_script/pet_bar_tests.rs index b840b4a9..5ea329d4 100644 --- a/crates/benilla-app/src/ui_script/pet_bar_tests.rs +++ b/crates/benilla-app/src/ui_script/pet_bar_tests.rs @@ -4,22 +4,7 @@ use benilla_ui::script::{PetActionView, QuadContent, UiScript}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "loader errors in {file}: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The pet bar's own load prerequisites, in manifest order: UiPanels (`SetDesaturation`, the /// disabled-bar grey), UIParent (the managed bottom stack its OnShow/OnHide re-fires), Cooldown diff --git a/crates/benilla-app/src/ui_script/pet_frame_tests.rs b/crates/benilla-app/src/ui_script/pet_frame_tests.rs index 6d1c3ec9..3849e4ec 100644 --- a/crates/benilla-app/src/ui_script/pet_frame_tests.rs +++ b/crates/benilla-app/src/ui_script/pet_frame_tests.rs @@ -9,23 +9,7 @@ use benilla_ui::script::{ AuraState, QuadContent, ScriptValue, SelectionRequest, UiScript, UnitState, }; -/// Load one shipped `assets/ui/`, panicking on any loader error (the unit-frame tests' -/// loader). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The pet frame's production load prefix — it is parented to `PlayerFrame`, so the whole /// unit-frame file comes with it, and the tooltip/dropdown kit its hover and its neighbours need. 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 4b04233f..fca956e1 100644 --- a/crates/benilla-app/src/ui_script/pet_paperdoll_tests.rs +++ b/crates/benilla-app/src/ui_script/pet_paperdoll_tests.rs @@ -11,22 +11,7 @@ use benilla_ui::script::{ PetStats, QuadContent, ScriptValue, UiScript, UnitCombatStats, UnitState, }; -/// Load one shipped `assets/ui/`, panicking on any loader error (the character tests' loader). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The page's production load prefix — it leans on `CharacterFrame.xml` for the shared setters, /// the row templates and the tab row itself, exactly as the manifest orders them. diff --git a/crates/benilla-app/src/ui_script/petition_tests.rs b/crates/benilla-app/src/ui_script/petition_tests.rs index 03b0c866..925566e7 100644 --- a/crates/benilla-app/src/ui_script/petition_tests.rs +++ b/crates/benilla-app/src/ui_script/petition_tests.rs @@ -19,36 +19,7 @@ use benilla_ui::script::UiScript; -/// Load one shipped `assets/ui/`, panicking on any loader error **and on any -/// unknown-template warning** — `guild_tests`' loader, and the decision-0672 reason is the same: -/// `inherits=` a template this house doesn't ship is a *warning*, the frame still loads, and a -/// bare Button still clicks. Both windows here inherit from `UIPanelTemplates.xml` and -/// `MoneyFrame.xml`, and the registrar defines one local template of its own. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); - let missing: Vec<&String> = report - .warnings - .iter() - .filter(|w| w.contains("unknown template")) - .collect(); - assert!( - missing.is_empty(), - "{file}: inherits a template this house does not ship (the frame loads, its ART does \ - not): {missing:?}" - ); -} +use super::test_ui::load_ui_strict as load_xml; /// The charter engine API, stood in for in Lua. /// @@ -114,13 +85,31 @@ fn setup() -> UiScript { let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); s.run(PETITION_FIXTURE).unwrap(); + // The player's own strings: the reference's `PetitionFrame_Update` formats + // GUILD_CHARTER_TEMPLATE and reads GUILD_PETITION_*_INSTRUCTIONS and NOT_YET_SIGNED straight + // out of GlobalStrings, with no fallback of its own — `format(nil, …)` raises, and the window + // never paints. + load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua"); load_xml(&s, "Fonts.xml"); load_xml(&s, "BasicControls.xml"); load_xml(&s, "MoneyFrame.xml"); load_xml(&s, "UiPanels.xml"); load_xml(&s, "UIPanelTemplates.xml"); - load_xml(&s, "GuildRegistrarFrame.xml"); - load_xml(&s, "PetitionFrame.xml"); + // `QuestTitleButtonTemplate`, which the reference's registrar inherits for its two service + // rows — 1.12 declares it in QuestFrameTemplates.xml, an `` of QuestFrame.xml, and + // ours declares it in QuestFrame.xml directly. An unknown template is a loader WARNING, so + // without this the rows build with no art at all and nothing goes red — which is exactly the + // failure `load_ui_strict` exists to turn into a red test. + load_xml(&s, "ScrollTemplates.xml"); + load_xml(&s, "QuestFrame.xml"); + // `ChatFrameEditBox`, which the reference's own purchase button indexes on every click to + // decide where focus goes after the name box closes — a nil there raises before the charter is + // bought. Ours guarded it; the reference does not. + load_xml(&s, "GameTooltip.xml"); // TOOLTIP_DEFAULT_COLOR, read by the dropdown backdrops + load_xml(&s, "UIDropDownMenu.xml"); // ChatFrame's seven dropdowns inherit its template + load_xml(&s, "ChatFrame.xml"); + load_xml(&s, "Interface\\FrameXML\\GuildRegistrarFrame.xml"); + load_xml(&s, "Interface\\FrameXML\\PetitionFrame.xml"); s } @@ -161,6 +150,7 @@ fn show_registrar(s: &mut UiScript) { /// blank row 2 while every other assertion here still passed. #[test] fn a_signers_charter_shows_the_sign_face_and_nine_rows() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = setup(); show_petition(&mut s); @@ -223,6 +213,7 @@ fn a_signers_charter_shows_the_sign_face_and_nine_rows() { /// either view alone. #[test] fn the_owners_charter_swaps_sign_for_request_and_rename() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = setup(); s.run("BenillaPetitionFixture.isOriginator = 1").unwrap(); show_petition(&mut s); @@ -245,6 +236,7 @@ fn the_owners_charter_swaps_sign_for_request_and_rename() { /// still pass. #[test] fn request_signature_disables_at_the_wires_requirement_not_at_nine() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = setup(); s.run( r#" @@ -279,6 +271,7 @@ fn request_signature_disables_at_the_wires_requirement_not_at_nine() { /// a signer's view and still be unsignable (already signed, already guilded, full). #[test] fn the_sign_button_follows_can_sign_petition() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = setup(); show_petition(&mut s); assert!(s @@ -304,6 +297,7 @@ fn the_sign_button_follows_can_sign_petition() { /// window closes, and without it the engine keeps a charter session for a window nobody can see. #[test] fn the_charter_buttons_reach_their_verbs_and_the_close_clears_the_session() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = setup(); show_petition(&mut s); let _ = calls(&s); @@ -326,6 +320,7 @@ fn the_charter_buttons_reach_their_verbs_and_the_close_clears_the_session() { /// 24-character charter-name limit. #[test] fn rename_guild_sends_the_box_text_and_caps_at_twenty_four() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = setup(); s.run("BenillaPetitionFixture.isOriginator = 1").unwrap(); show_petition(&mut s); @@ -358,6 +353,7 @@ fn rename_guild_sends_the_box_text_and_caps_at_twenty_four() { /// before the player has typed a name. #[test] fn the_registrar_opens_on_services_and_purchase_is_a_local_panel_swap() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = setup(); show_registrar(&mut s); @@ -409,6 +405,7 @@ fn the_registrar_opens_on_services_and_purchase_is_a_local_panel_swap() { /// window will be told. #[test] fn purchase_sends_the_typed_name_and_register_turns_the_charter_in() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = setup(); show_registrar(&mut s); s.run("GuildRegistrarButton1:Click()").unwrap(); @@ -444,6 +441,7 @@ fn purchase_sends_the_typed_name_and_register_turns_the_charter_in() { /// charter list, and the greeting panel never displays one. #[test] fn the_charter_price_is_read_when_the_purchase_panel_opens() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = setup(); show_registrar(&mut s); s.run("GuildRegistrarButton1:Click()").unwrap(); @@ -456,6 +454,7 @@ fn the_charter_price_is_read_when_the_purchase_panel_opens() { /// panel left over from last time. #[test] fn reopening_the_registrar_returns_to_the_services_list() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = setup(); show_registrar(&mut s); s.run("GuildRegistrarButton1:Click()").unwrap(); @@ -472,6 +471,7 @@ fn reopening_the_registrar_returns_to_the_services_list() { /// in no slot and two left-slot windows paint over each other (B288's shape, decision 1507). #[test] fn both_charter_windows_are_registered_left_slot_panels() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = setup(); for frame in ["GuildRegistrarFrame", "PetitionFrame"] { assert_eq!( diff --git a/crates/benilla-app/src/ui_script/quest_tests.rs b/crates/benilla-app/src/ui_script/quest_tests.rs index f71ed81b..5068eaa0 100644 --- a/crates/benilla-app/src/ui_script/quest_tests.rs +++ b/crates/benilla-app/src/ui_script/quest_tests.rs @@ -5,23 +5,7 @@ use benilla_ui::script::{QuestPanel, QuestState, ScriptValue, SoundRequest, UiScript}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error (the panel tests' -/// loader, duplicated so this file is self-contained). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The questgiver window's open/close kits — the window-sound convention (decision 0090). The real /// QuestFrame.lua plays igQuestListOpen in QuestFrame_OnShow (l.285) and igQuestListClose in diff --git a/crates/benilla-app/src/ui_script/quest_timer_tests.rs b/crates/benilla-app/src/ui_script/quest_timer_tests.rs index e22356f2..1c14cec5 100644 --- a/crates/benilla-app/src/ui_script/quest_timer_tests.rs +++ b/crates/benilla-app/src/ui_script/quest_timer_tests.rs @@ -13,22 +13,7 @@ use benilla_ui::script::{ QuestLogEntryView, QuestLogObjectiveView, QuestLogState, ScriptValue, UiScript, }; -/// Load one shipped `assets/ui/`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// Fonts + UIParent (SecondsToTime lives there) + the window itself. Deliberately NOT the whole /// manifest: the window must stand up on its own dependencies, and a harness that loads everything @@ -36,9 +21,22 @@ fn load_xml(s: &UiScript, file: &str) { fn harness() -> UiScript { let mut s = UiScript::new().unwrap(); s.set_screen_size(1024.0, 768.0); + // The window's title is `text="QUEST_TIMERS"`, resolved against the global at load — without + // the player's own strings it draws the KEY, which is exactly what a `text=` attribute does + // with an unknown name. + load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua"); load_xml(&s, "Fonts.xml"); + // `SecondsToTime`, which the reference's `QuestTimerFrame_Update` formats every row with, and + // `UIParent_ManageFramePositions`, which its OnShow/OnHide call. load_xml(&s, "UIParent.xml"); - load_xml(&s, "QuestTimerFrame.xml"); + // `MAX_QUESTS`, the loop bound the reference's repaint hides its spare rows with. 1.12 + // declares it on QuestLogFrame.lua:2 and so do we (1751 window 16) — a nil there is + // `'for' limit must be a number` on the first repaint, not a missing row. + load_xml(&s, "MoneyFrame.xml"); + load_xml(&s, "UiPanels.xml"); + load_xml(&s, "ScrollTemplates.xml"); + load_xml(&s, "QuestLogFrame.xml"); + load_xml(&s, "Interface\\FrameXML\\QuestTimerFrame.xml"); s } @@ -83,6 +81,7 @@ fn row_text(s: &UiScript, i: u32) -> String { /// `45 + 16·n`; and back to hidden when the last timer goes. #[test] fn the_window_follows_the_timed_quests() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = harness(); // An untimed log: QUEST_LOG_UPDATE fires, the frame stays down. @@ -132,6 +131,7 @@ fn the_window_follows_the_timed_quests() { /// and `mirror_timer_tests` were both written for. #[test] fn the_countdown_reaches_the_draw_list() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = harness(); s.set_quest_log(log(vec![quest(1, "Deliver the Message", 1_000_860)])); s.set_server_unix_time(1_000_000.0); @@ -162,6 +162,7 @@ fn the_countdown_reaches_the_draw_list() { /// change again. #[test] fn a_world_entry_paints_a_quest_already_running() { + let _data = benilla_formats::wow_data_or_skip!(); let mut s = harness(); s.set_quest_log(log(vec![quest(1, "Deliver the Message", 1_000_090)])); s.set_server_unix_time(1_000_000.0); @@ -181,12 +182,20 @@ fn a_world_entry_paints_a_quest_already_running() { /// `QuestTimer1: ours [(140.0, 16.0), (0.0, -29.0)] != ref [(140.0, 16.0), (0.0, -30.0)]`. #[test] fn the_window_geometry_matches_the_reference_framexml() { - let Some(reference) = super::framexml_diff::reference("QuestTimerFrame.xml") else { + let _data = benilla_formats::wow_data_or_skip!(); + let Some(reference) = + super::framexml_diff::reference("Interface\\FrameXML\\QuestTimerFrame.xml") + else { eprintln!("skipping: no extracted FrameXML"); return; }; // No exemptions: this window's frames keep the reference's bare names (decision 0591 §3 — the // manage pass and the ref's own row lookup both resolve by literal name), and every number in // it is the reference's. If an entry ever needs to go here, it names its reason. - super::framexml_diff::assert_geometry_matches("QuestTimerFrame.xml", &reference, &[], 22); + super::framexml_diff::assert_geometry_matches( + "Interface\\FrameXML\\QuestTimerFrame.xml", + &reference, + &[], + 22, + ); } diff --git a/crates/benilla-app/src/ui_script/questlog_tests.rs b/crates/benilla-app/src/ui_script/questlog_tests.rs index 66c1ccd1..95869563 100644 --- a/crates/benilla-app/src/ui_script/questlog_tests.rs +++ b/crates/benilla-app/src/ui_script/questlog_tests.rs @@ -8,23 +8,7 @@ use benilla_ui::script::{ QuestLogEntryView, QuestLogObjectiveView, QuestLogState, SoundRequest, UiScript, }; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error (the panel/quest -/// tests' loader, duplicated so this file is self-contained). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// Find a bare frame's own rect via its `QuadContent::Frame` entry (`panel_tests.rs`'s helper, /// duplicated) — used to locate the window so the wheel test's coordinates land inside it. @@ -427,11 +411,11 @@ fn watch_guards_no_op_without_erroring() { load_xml(&s, "MoneyFrame.xml"); load_xml(&s, "UiPanels.xml"); load_xml(&s, "MerchantFrame.xml"); - load_xml(&s, "ErrorsFrame.xml"); // the guards' red-line surface - // ScrollTemplates.xml + UIPanelTemplates.xml are NOT optional: the detail pane inherits - // UIPanelScrollFrameTemplate, and a MISSING template is a loader *warning*, not an error — - // an under-loaded list passes load_xml and then loses the wheel, the arrows and the bar - // silently. + load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml"); // the guards' red-line surface + // ScrollTemplates.xml + UIPanelTemplates.xml are NOT optional: the detail pane inherits + // UIPanelScrollFrameTemplate, and a MISSING template is a loader *warning*, not an error — + // an under-loaded list passes load_xml and then loses the wheel, the arrows and the bar + // silently. load_xml(&s, "ScrollTemplates.xml"); load_xml(&s, "UIPanelTemplates.xml"); load_xml(&s, "QuestLogFrame.xml"); diff --git a/crates/benilla-app/src/ui_script/raid_tests.rs b/crates/benilla-app/src/ui_script/raid_tests.rs index 98cb1632..f7474695 100644 --- a/crates/benilla-app/src/ui_script/raid_tests.rs +++ b/crates/benilla-app/src/ui_script/raid_tests.rs @@ -16,35 +16,7 @@ use benilla_ui::script::{ UiScript, }; -/// Load one shipped `assets/ui/`, panicking on any loader error **or unknown-template -/// warning** — `friends_tests::load_xml`'s reason verbatim: `inherits=` a template this house does -/// not ship is a warning, the frame still loads, and every behavioural test stays green while the -/// art is missing. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); - let missing: Vec<&String> = report - .warnings - .iter() - .filter(|w| w.contains("unknown template")) - .collect(); - assert!( - missing.is_empty(), - "{file}: inherits a template this house does not ship (the frame loads, its ART does \ - not): {missing:?}" - ); -} +use super::test_ui::load_ui_strict as load_xml; /// The window's slice of the manifest, in `load_default_ui` order. `UIParent.xml` is in it for /// two functions the pane really calls — `MouseIsOver` (the drag's hover sweep) and 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 5156c872..b4085586 100644 --- a/crates/benilla-app/src/ui_script/reputation_frame_tests.rs +++ b/crates/benilla-app/src/ui_script/reputation_frame_tests.rs @@ -15,23 +15,7 @@ use benilla_ui::script::{FactionEntry, ReputationState, UiScript, UnitState}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error (the -/// skills/character tests' loader, duplicated so this file is self-contained). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// An ordinary bar row: visible, not a header, `standing_id` 5 ("Friendly") sitting 1000 into a /// 6000-wide rank window. The same numbers `benilla-ui`'s own fixture uses. diff --git a/crates/benilla-app/src/ui_script/screenshot_tests.rs b/crates/benilla-app/src/ui_script/screenshot_tests.rs index 2174c3b2..c2182023 100644 --- a/crates/benilla-app/src/ui_script/screenshot_tests.rs +++ b/crates/benilla-app/src/ui_script/screenshot_tests.rs @@ -8,21 +8,7 @@ use benilla_ui::script::UiScript; -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; fn harness() -> UiScript { let mut s = UiScript::new().unwrap(); 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 2d27b3a0..9e84b890 100644 --- a/crates/benilla-app/src/ui_script/skills_frame_tests.rs +++ b/crates/benilla-app/src/ui_script/skills_frame_tests.rs @@ -14,23 +14,7 @@ use benilla_ui::script::{QuadContent, SkillEntry, SkillsState, UiScript}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error (the -/// character/spellbook tests' loader, duplicated so this file is self-contained). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; fn skill( skill_id: u32, diff --git a/crates/benilla-app/src/ui_script/spellbook_tests.rs b/crates/benilla-app/src/ui_script/spellbook_tests.rs index 490c5e8f..cb3e422a 100644 --- a/crates/benilla-app/src/ui_script/spellbook_tests.rs +++ b/crates/benilla-app/src/ui_script/spellbook_tests.rs @@ -5,23 +5,7 @@ use benilla_ui::script::{SpellBookState, SpellSlotView, SpellTabView, UiScript}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error (the -/// character/questlog tests' loader, duplicated so this file is self-contained). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// Two tabs' worth of a small book: "Fire" (Fireball, Fire Blast — slots 0-1) and "Frost" (Frost /// Armor — slot 2), the flat `slots` in tab order. `offset` is each tab's 0-based start index into diff --git a/crates/benilla-app/src/ui_script/target_aura_tests.rs b/crates/benilla-app/src/ui_script/target_aura_tests.rs index 024f0f65..9c03bb95 100644 --- a/crates/benilla-app/src/ui_script/target_aura_tests.rs +++ b/crates/benilla-app/src/ui_script/target_aura_tests.rs @@ -11,21 +11,7 @@ use benilla_ui::script::{AuraState, QuadContent, ScriptValue, UiScript, UnitState}; -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; fn harness() -> UiScript { let mut s = UiScript::new().unwrap(); diff --git a/crates/benilla-app/src/ui_script/taxi_tests.rs b/crates/benilla-app/src/ui_script/taxi_tests.rs index 6a38d972..0e50f667 100644 --- a/crates/benilla-app/src/ui_script/taxi_tests.rs +++ b/crates/benilla-app/src/ui_script/taxi_tests.rs @@ -8,23 +8,7 @@ use benilla_ui::script::{ScriptValue, TaxiNodeType, TaxiUiNode, TaxiUiState, UiScript}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) -> usize { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); - report.frames -} +use super::test_ui::load_ui as load_xml; /// Load the taxi window + its deps into a fresh script, screen sized. fn taxi_script() -> UiScript { @@ -34,7 +18,7 @@ fn taxi_script() -> UiScript { load_xml(&s, "MoneyFrame.xml"); load_xml(&s, "UiPanels.xml"); load_xml(&s, "GameTooltip.xml"); // TaxiNodeOnButtonEnter's tooltip + SetTooltipMoney - load_xml(&s, "ErrorsFrame.xml"); // BenillaErrorsFrame_AddMessage — DrawOneHopLines' refusal + load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml"); // BenillaErrorsFrame_AddMessage — DrawOneHopLines' refusal load_xml(&s, "TaxiFrame.xml"); s } diff --git a/crates/benilla-app/src/ui_script/test_ui.rs b/crates/benilla-app/src/ui_script/test_ui.rs index 8b712792..f8fc34f9 100644 --- a/crates/benilla-app/src/ui_script/test_ui.rs +++ b/crates/benilla-app/src/ui_script/test_ui.rs @@ -28,6 +28,21 @@ use benilla_ui::script::UiScript; /// **A chain entry needs client data**, so a test that names one has to open with /// `benilla_formats::wow_data_or_skip!()`; [`BAG_UI`] is a list that always does. pub(super) fn load_ui(s: &UiScript, entry: &str) -> usize { + load_entry(s, entry, false) +} + +/// [`load_ui`], and **a missing template is a failure too**. +/// +/// A frame that inherits a template nothing declares is a loader *warning*, not an error: the frame +/// is built and simply has none of the template's art. So an under-loaded dependency list passes +/// [`load_ui`] and then loses a window's whole skin silently — which is why four of the social +/// windows' test modules grew this check by hand. It is one function now rather than four copies, +/// and any test may ask for it. +pub(super) fn load_ui_strict(s: &UiScript, entry: &str) -> usize { + load_entry(s, entry, true) +} + +fn load_entry(s: &UiScript, entry: &str, strict_templates: bool) -> usize { let path = entry.replace('\\', "/"); let bytes = read(&path).unwrap_or_else(|| panic!("{entry}: not found")); if path.to_ascii_lowercase().ends_with(".lua") { @@ -44,6 +59,18 @@ pub(super) fn load_ui(s: &UiScript, entry: &str) -> usize { "{entry}: loader errors: {:?}", report.errors ); + if strict_templates { + let missing: Vec<&String> = report + .warnings + .iter() + .filter(|w| w.contains("unknown template")) + .collect(); + assert!( + missing.is_empty(), + "{entry}: inherits a template this house does not ship (the frame loads, its ART does \ + not): {missing:?}" + ); + } report.frames } @@ -112,7 +139,7 @@ pub(super) const BAG_UI: &[&str] = &[ // `StackSplitFrame` is not optional either: the reference's own // `ContainerFrameItemButton_OnClick` calls `StackSplitFrame:Hide()` on EVERY plain click // (ContainerFrame.lua l.581) before the pickup, and opens it on the shift fork. - "StackSplit.xml", + "Interface\\FrameXML\\StackSplitFrame.xml", // …nor is the chat edit box. The reference's SHIFT arm opens with // `if ( ChatFrameEditBox:IsShown() )` (ContainerFrame.lua l.569) to decide between posting the // item's link and splitting the stack, so a VM without it raises before either. diff --git a/crates/benilla-app/src/ui_script/tooltip_anchor_tests.rs b/crates/benilla-app/src/ui_script/tooltip_anchor_tests.rs index cbd16e27..2bebf415 100644 --- a/crates/benilla-app/src/ui_script/tooltip_anchor_tests.rs +++ b/crates/benilla-app/src/ui_script/tooltip_anchor_tests.rs @@ -11,23 +11,7 @@ use benilla_ui::script::{AuraState, UiScript, UnitState}; -/// Load one shipped `assets/ui/` into `s`, panicking on any loader error (the bag/panel -/// tests' loader, duplicated so this file is self-contained). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// A 1024×768 screen with the anchor law's three fixed files (fonts, the real UIParent, the /// real GameTooltip) plus `extra`. `CONTAINER_OFFSET_X/Y` hold their UIParent.xml load values 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 95ac3fcb..22626fd7 100644 --- a/crates/benilla-app/src/ui_script/tooltip_template_tests.rs +++ b/crates/benilla-app/src/ui_script/tooltip_template_tests.rs @@ -27,21 +27,7 @@ use benilla_ui::script::UiScript; -fn ui_dir() -> std::path::PathBuf { - std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("assets/ui") -} - -/// One shipped `assets/ui/` into `s`, asserting it loaded clean. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string(ui_dir().join(file)).unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// An **addon's** document text, loaded after the shipped files exactly as `LoadAddOn` would — /// the template registry is persistent, so `inherits=` reaches what `GameTooltip.xml` registered. diff --git a/crates/benilla-app/src/ui_script/tot_frame_tests.rs b/crates/benilla-app/src/ui_script/tot_frame_tests.rs index 93875098..1be4f4ac 100644 --- a/crates/benilla-app/src/ui_script/tot_frame_tests.rs +++ b/crates/benilla-app/src/ui_script/tot_frame_tests.rs @@ -18,22 +18,7 @@ use benilla_ui::script::{ SelectionRequest, UiScript, UnitState, }; -/// Load one shipped `assets/ui/`, panicking on any loader error (the unit-frame tests'). -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// A unit snapshot with a guid — the identity `UnitIsUnit` compares, which the "your target is /// you" gate reads. 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 ad7f5ffd..5e807e4f 100644 --- a/crates/benilla-app/src/ui_script/unit_frame_tests.rs +++ b/crates/benilla-app/src/ui_script/unit_frame_tests.rs @@ -2,23 +2,7 @@ use benilla_ui::script::{ QuadContent, ScriptValue, SelectionRequest, SoundRequest, UiScript, UnitState, }; -/// Load one shipped `assets/ui/` (the panel tests' loader, duplicated to stay -/// self-contained), panicking on any loader error. -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; /// The unit frames' production load prefix (ui_script/mod.rs order): fonts + UIParent + /// tooltip, then the dropdown kit + unit popups the frames' DropDown children initialize into. diff --git a/crates/benilla-app/src/ui_script/world_state_tests.rs b/crates/benilla-app/src/ui_script/world_state_tests.rs index 4f49b3d9..e5607ffc 100644 --- a/crates/benilla-app/src/ui_script/world_state_tests.rs +++ b/crates/benilla-app/src/ui_script/world_state_tests.rs @@ -9,21 +9,7 @@ use benilla_ui::script::{QuadContent, ScriptValue, UiScript, WorldStateUiView}; -fn load_xml(s: &UiScript, file: &str) { - let text = std::fs::read_to_string( - std::path::Path::new(env!("CARGO_MANIFEST_DIR")) - .join("assets/ui") - .join(file), - ) - .unwrap(); - let doc = benilla_ui::framexml::parse(&text).unwrap(); - let report = benilla_ui::loader::load(s, &doc, &|_| None); - assert!( - report.errors.is_empty(), - "{file}: loader errors: {:?}", - report.errors - ); -} +use super::test_ui::load_ui as load_xml; pub(crate) fn harness() -> UiScript { let mut s = UiScript::new().unwrap(); diff --git a/crates/benilla-ui/src/script/lua50.rs b/crates/benilla-ui/src/script/lua50.rs index 5f8f9d6b..90a23bc2 100644 --- a/crates/benilla-ui/src/script/lua50.rs +++ b/crates/benilla-ui/src/script/lua50.rs @@ -45,6 +45,19 @@ //! `foreachi`. `reference/1.12-globals.tsv` lists all three; we had the other seventeen of that //! family and not these. //! +//! ## What this module does NOT have to do: the vararg `arg` table +//! +//! Lua 5.0 gives every vararg function an implicit `arg` table with an `n` field, and 1.12's +//! FrameXML uses it directly — `QuestTimerFrame_Update(...)` walks `for i=1, arg.n`, and so do +//! `FCFDropDown_LoadChannels`, `TradeSkill_OnEvent` and the GM-ticket and CVar families. Three of +//! our own transcriptions carry a note saying they rewrote it "the 5.1-native way" with +//! `select("#", ...)`, which reads as though the dialect demanded it. +//! +//! **It does not.** mlua's vendored 5.1 is built with `LUA_COMPAT_VARARG`, so `arg` and `arg.n` +//! are already there — measured, not assumed: `local function f(...) return arg.n end; f('a','b')` +//! answers 2 in this VM. That matters for 1751: a stock file using 5.0 varargs needs nothing from +//! this module, and the rewrite was a precaution against a problem we did not have. +//! //! ## The one known divergence, stated rather than hidden //! //! `table.insert`/`table.remove` stay on 5.1's `#t` border rather than consulting `getn`. **This