test(D.2b): chat golden fixture + resolved-Type conformance (widget-generalization Task 1)
- Add ChatLayoutFixtureGenerator.cs (Skip-by-default) to regenerate
chat_21000006.json from the live portal.dat via LayoutImporter.ImportInfos
- Commit generated fixture chat_21000006.json (13 KB, 400 lines) — dat-free,
auto-copied to test output via existing *.json csproj glob
- Refactor FixtureLoader: extract shared LoadInfos(fileName) helper; add
LoadChat() + LoadChatInfos() mirroring the vitals pattern; LoadVitalsInfos()
now delegates to the shared loader (behavior unchanged, vitals tests green)
- Add ChatLayoutConformanceTests: ResolvesKnownElements + ResolvedTypes_MatchRetailRegistry
Confirmed resolved Types from live dat:
0x10000011 (transcript) → Type 12 (style-prototype, skipped by factory)
0x10000016 (input) → Type 12 (style-prototype, skipped by factory)
0x10000014 (menu) → Type 6
0x10000012 (scrollbar) → Type 11
0x10000019 (send) → Type 1
0x1000046F (max/min) → Type 1
Also fix pre-existing build break: UiChatInput.MoveCaret(int delta) was made
private in ce848c1 but UiChatInputTests.Backspace_DeletesBeforeCaret called it
as public. Expose a public MoveCaret(int) overload (no-shift) alongside the
private MoveCaret(int,bool) — restores the intended test surface.
Full suite: 398 passed, 2 skipped (generator + pre-existing), 0 failed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
34e79096f3
commit
d1b13a7dbf
5 changed files with 661 additions and 9 deletions
|
|
@ -5,9 +5,9 @@ using AcDream.App.UI.Layout;
|
|||
namespace AcDream.App.Tests.UI.Layout;
|
||||
|
||||
/// <summary>
|
||||
/// Loads the committed vitals ElementInfo fixture and builds the widget tree —
|
||||
/// no dats required. The fixture was generated from layout <c>0x2100006C</c>
|
||||
/// via the real portal.dat and serialized with <see cref="System.Text.Json"/>.
|
||||
/// Loads the committed layout ElementInfo fixtures and builds widget trees —
|
||||
/// no dats required. Fixtures were generated from the real portal.dat and
|
||||
/// serialized with <see cref="System.Text.Json"/>.
|
||||
/// </summary>
|
||||
public static class FixtureLoader
|
||||
{
|
||||
|
|
@ -37,18 +37,39 @@ public static class FixtureLoader
|
|||
/// widget factory.
|
||||
/// </summary>
|
||||
public static AcDream.App.UI.Layout.ElementInfo LoadVitalsInfos()
|
||||
{
|
||||
var fixturePath = Path.Combine(AppContext.BaseDirectory, "UI", "Layout", "fixtures", "vitals_2100006C.json");
|
||||
if (!File.Exists(fixturePath))
|
||||
throw new FileNotFoundException($"Vitals fixture not found at: {fixturePath}");
|
||||
=> LoadInfos("vitals_2100006C.json");
|
||||
|
||||
var bytes = File.ReadAllBytes(fixturePath);
|
||||
/// <summary>
|
||||
/// Deserializes the committed <c>chat_21000006.json</c> fixture into a raw
|
||||
/// <see cref="ElementInfo"/> tree and builds the <see cref="ImportedLayout"/>
|
||||
/// using a null-returning sprite resolver and no dat font — sufficient for
|
||||
/// conformance checks on tree structure and resolved types.
|
||||
/// </summary>
|
||||
public static ImportedLayout LoadChat()
|
||||
=> LayoutImporter.Build(LoadChatInfos(), _ => (0u, 0, 0), null);
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the committed <c>chat_21000006.json</c> fixture into a raw
|
||||
/// <see cref="ElementInfo"/> tree WITHOUT calling <see cref="LayoutImporter.Build"/>.
|
||||
/// Use this when the test needs to inspect the resolved <see cref="ElementInfo"/>
|
||||
/// tree directly (e.g. resolved Type values per element id).
|
||||
/// </summary>
|
||||
public static AcDream.App.UI.Layout.ElementInfo LoadChatInfos()
|
||||
=> LoadInfos("chat_21000006.json");
|
||||
|
||||
// ── Shared loader ────────────────────────────────────────────────────────
|
||||
|
||||
private static AcDream.App.UI.Layout.ElementInfo LoadInfos(string fileName)
|
||||
{
|
||||
var path = Path.Combine(AppContext.BaseDirectory, "UI", "Layout", "fixtures", fileName);
|
||||
if (!File.Exists(path)) throw new FileNotFoundException($"fixture not found at: {path}");
|
||||
var bytes = File.ReadAllBytes(path);
|
||||
// Strip UTF-8 BOM (EF BB BF) if present so JsonSerializer.Deserialize<T>(ReadOnlySpan<byte>)
|
||||
// does not reject the first byte.
|
||||
ReadOnlySpan<byte> span = bytes;
|
||||
if (span.Length >= 3 && span[0] == 0xEF && span[1] == 0xBB && span[2] == 0xBF)
|
||||
span = span[3..];
|
||||
return JsonSerializer.Deserialize<AcDream.App.UI.Layout.ElementInfo>(span, _opts)
|
||||
?? throw new InvalidOperationException($"fixture deserialized to null: {fixturePath}");
|
||||
?? throw new InvalidOperationException($"fixture deserialized to null: {path}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue