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);
}
}