using AcDream.App.UI; using AcDream.App.UI.Layout; namespace AcDream.App.Tests.UI.Layout; /// /// Dat-free conformance tests for the committed chat_floaty_2100005b.json /// golden fixture — retail's ACTUAL floating chat window (LayoutDesc /// 0x2100005B, window root 0x100004F7, authored 250x108; CH6a/b /// REJECT-review SHOULD-FIX 4, /// docs/research/2026-08-10-ch6ab-review-findings.md). Pins the resolved /// widget types assumes at /// Bind time — before this fixture existed those assumptions were /// untested against real dat data. /// public class FloatingChatLayoutConformanceTests { private static ElementInfo? Find(ElementInfo n, uint id) { if (n.Id == id) return n; foreach (var c in n.Children) { var f = Find(c, id); if (f is not null) return f; } return null; } [Fact] public void FloatyFixture_ResolvesKnownElements() { var root = FixtureLoader.LoadFloatyChatInfos(); Assert.NotNull(Find(root, 0x10000011u)); // transcript Assert.NotNull(Find(root, 0x10000016u)); // input Assert.NotNull(Find(root, 0x10000012u)); // scrollbar track Assert.NotNull(Find(root, 0x10000019u)); // send button Assert.NotNull(Find(root, 0x100004D9u)); // title bar Assert.NotNull(Find(root, 0x1000052Au)); // close button Assert.NotNull(Find(root, 0x10000529u)); // title-bar drag handle // No talk-focus menu, no max/min button, no 1-4 indicators — a floaty // window has none of these (research doc §2.2). Assert.Null(Find(root, 0x10000014u)); Assert.Null(Find(root, 0x1000046Fu)); Assert.Null(Find(root, 0x10000522u)); } [Fact] public void FloatyFixture_ResolvedTypes_MatchRetailRegistry() { // CH6a/b REJECT-review SHOULD-FIX 4's three flagged untested // assumptions: the chat entry field, the title bar, and the close // button. All three are confirmed correct against the real fixture. var root = FixtureLoader.LoadFloatyChatInfos(); Assert.Equal(12u, Find(root, 0x10000016u)!.Type); // Text/style-prototype (input) + Editable 0x16 Assert.True(Find(root, 0x10000016u)!.TryGetEffectiveBool(0x16u, out bool editable) && editable); Assert.Equal(12u, Find(root, 0x100004D9u)!.Type); // Text (title bar) — no Editable Assert.False(Find(root, 0x100004D9u)!.TryGetEffectiveBool(0x16u, out bool titleEditable) && titleEditable); Assert.Equal(1u, Find(root, 0x10000019u)!.Type); // Button (Send) Assert.Equal(1u, Find(root, 0x1000052Au)!.Type); // Button (Close) Assert.Equal(11u, Find(root, 0x10000012u)!.Type); // Scrollbar Assert.Equal(2u, Find(root, 0x10000529u)!.Type); // Dragbar (title-bar move handle) } [Fact] public void MountedFloatyWindow_ResolvesToTheExpectedWidgetTypes() { // The resolved WIDGET types (post-DatWidgetFactory), not just the raw // dat Type numbers above — this is what FloatingChatWindowController.Bind // actually casts against. var layout = FixtureLoader.LoadFloatyChat(); Assert.IsType(layout.FindElement(0x10000016u)); // Editable 0x16 -> UiField Assert.IsType(layout.FindElement(0x100004D9u)); // no Editable -> UiText Assert.IsType(layout.FindElement(0x10000019u)); // Send Assert.IsType(layout.FindElement(0x1000052Au)); // Close Assert.IsType(layout.FindElement(0x10000012u)); } // ── Border/corner grips — CH6a/b SHOULD-FIX 4's "also determines whether // floaties resize from real grips" ──────────────────────────────────────── [Theory] [InlineData(0x100004FCu)] // TL corner [InlineData(0x1000000Fu)] // top edge [InlineData(0x100004FEu)] // TR corner [InlineData(0x100004D2u)] // left edge [InlineData(0x10000501u)] // BL corner [InlineData(0x100004D4u)] // bottom edge [InlineData(0x10000503u)] // BR corner [InlineData(0x100004D3u)] // right edge public void FloatyFixture_EveryBorderElement_IsALiveResizeGrip(uint elementId) { // Unlike the main window (whose plain top EDGE strip is a Type-2 // Dragbar move handle, not a grip — the main window has no title bar // so the top strip doubles as the move handle), the floaty window's // move handle is its OWN title-bar group (0x10000529, Type 2) — so // ALL EIGHT border/corner elements here are genuine Type-9 Resizebar // grips. A floaty window resizes from every edge and every corner. var root = FixtureLoader.LoadFloatyChatInfos(); Assert.Equal(9u, Find(root, elementId)!.Type); } [Theory] [InlineData(0x100004FCu)] [InlineData(0x1000000Fu)] [InlineData(0x100004FEu)] [InlineData(0x100004D2u)] [InlineData(0x10000501u)] [InlineData(0x100004D4u)] [InlineData(0x10000503u)] [InlineData(0x100004D3u)] public void MountedFloatyWindow_EveryLiveGrip_ResolvesNonZeroSprite(uint elementId) { // BLOCKER 1's regression guard extended to the floaty layout: every // one of the eight live grips must carry real authored border/corner // media, not draw nothing. var layout = FixtureLoader.LoadFloatyChat(); var grip = Assert.IsType(layout.FindElement(elementId)); Assert.NotEqual(0u, grip.SpriteFile); } }