fix: complete retail parity stability pass
All checks were successful
CI / linux-portable (push) Successful in 3m41s
CI / windows-gate (push) Successful in 6m49s
CI / release (push) Successful in 3m22s

This commit is contained in:
Erik 2026-08-28 20:01:39 +02:00
parent d3df4cb20a
commit f7aa8e0eb7
131 changed files with 7765 additions and 1190 deletions

View file

@ -177,9 +177,11 @@ public class UiMenuTests
}
// ── G5 (vendor gate finding): Scrollable single-column popup ──────────────
// Retail's vendor category dropdown (LayoutDesc 0x21000043) is a SCROLLABLE
// single column with a docked scrollbar, not a column-major grid — see
// VendorUiController's "G5 correction" class-doc paragraph. Chat's own popup
// Retail's vendor category dropdown (LayoutDesc 0x21000043) is a scrollable
// single-column ListBox with a docked scrollbar, not a column-major grid.
// Its four-edge docking subsequently sizes the popup to content and property
// 0x79 hides that scrollbar when disabled; the fixed-viewport tests below
// retain coverage of UiMenu's actual overflow path. Chat's own popup
// (exercised by every test above, Scrollable left at its false default) is
// completely unaffected: it's a structurally different code path
// (DrawGridPopup / the grid branch of OnEvent's MouseDown handling).
@ -541,6 +543,45 @@ public class UiMenuTests
Assert.False(menu.IsOpen); // picking closes, same as every other path
}
[Fact]
public void SizeToContent_WithAuthoredHideWhenDisabled_HidesTheScrollbarAndItsInput()
{
UiMenu menu = MakeScrollableMenu(3, sizeToContent: true);
menu.PopupScrollbarHideWhenDisabled = true;
Assert.Equal(menu.ColumnWidth + 2 * 5f, menu.PopupOuterWidth);
Assert.True(menu.OnEvent(new UiEvent(0, menu, UiEventType.MouseDown, 0, 10, 5))); // open
// Configure the exact content/view extents used by both drawing and
// pointer dispatch. Size-to-content makes them equal, so retail's
// authored scrollbar property 0x79 hides the entire sibling widget.
Assert.True(menu.OnEvent(new UiEvent(0, menu, UiEventType.Scroll, Data0: 0)));
Assert.False(menu.PopupScroll.HasOverflow);
Assert.False(menu.IsPopupScrollbarPresentationVisible);
// The old 16px sibling column is outside the popup now. A direct event
// at that old coordinate must not page/line scroll or leave an invisible
// control holding the popup open (UiRoot hit testing would not target the
// menu there at all because PopupOuterWidth has already collapsed).
float lx = 5f + menu.ColumnWidth + menu.ScrollbarWidth / 2f;
float ly = menu.Height + 5f + menu.RowHeight / 2f;
Assert.True(menu.OnEvent(new UiEvent(0, menu, UiEventType.MouseDown, 0, (int)lx, (int)ly)));
Assert.Equal(0, menu.PopupScroll.ScrollY);
Assert.False(menu.IsOpen);
}
[Fact]
public void FixedViewport_WithOverflow_KeepsHideWhenDisabledScrollbarVisible()
{
UiMenu menu = MakeScrollableMenu(18, sizeToContent: false);
menu.PopupScrollbarHideWhenDisabled = true;
Assert.True(menu.OnEvent(new UiEvent(0, menu, UiEventType.MouseDown, 0, 10, 5))); // open
Assert.True(menu.OnEvent(new UiEvent(0, menu, UiEventType.Scroll, Data0: 0)));
Assert.True(menu.PopupScroll.HasOverflow);
Assert.True(menu.IsPopupScrollbarPresentationVisible);
Assert.Equal(menu.ColumnWidth + menu.ScrollbarWidth + 2 * 5f, menu.PopupOuterWidth);
}
[Fact]
public void EmptyItems_ButtonClickDoesNotOpen()
{
@ -552,14 +593,16 @@ public class UiMenuTests
}
[Fact]
public void TextStyleDefaults_PreserveChatAndVendorBehavior()
public void MenuRetailBehaviorFlags_DefaultOff_ForMenusThatDoNotAuthorThem()
{
// The three 2026-08-13 additions are opt-in: chat's gold left-aligned
// caption and vendor's fixed 6-row window are untouched by default.
// These are per-menu authored behaviors. Chat's grid popup keeps the
// generic left-aligned, non-resizing defaults; vendor opts into both
// content sizing and property-0x79 scrollbar hiding in its controller.
var menu = new UiMenu();
Assert.False(menu.ButtonTextCentered);
Assert.False(menu.ItemTextCentered);
Assert.False(menu.PopupSizeToContent);
Assert.False(menu.PopupScrollbarHideWhenDisabled);
}
/// <summary>