using System.IO;
using System.Text.Json;
using AcDream.App.UI.Layout;
namespace AcDream.App.Tests.UI.Layout;
///
/// Loads the committed layout ElementInfo fixtures and builds widget trees —
/// no dats required. Fixtures were generated from the real portal.dat and
/// serialized with .
///
public static class FixtureLoader
{
private static readonly JsonSerializerOptions _opts = new()
{
IncludeFields = true,
};
///
/// Deserializes the committed vitals_2100006C.json fixture (copied to
/// the test output directory via the csproj CopyToOutputDirectory item)
/// into an tree, then builds and returns the
/// using a null-returning sprite resolver and no
/// dat font — sufficient for conformance checks on tree structure and slice ids.
///
public static ImportedLayout LoadVitals()
{
var root = LoadVitalsInfos();
return LayoutImporter.Build(root, _ => (0u, 0, 0), null);
}
///
/// Deserializes the committed vitals_2100006C.json fixture into a raw
/// tree WITHOUT calling .
/// Use this when the test needs to inspect the resolved
/// tree directly (e.g. inheritance-resolution checks) without exercising the
/// widget factory.
///
public static AcDream.App.UI.Layout.ElementInfo LoadVitalsInfos()
=> LoadInfos("vitals_2100006C.json");
///
/// Deserializes the committed chat_21000006.json fixture into a raw
/// tree and builds the
/// using a null-returning sprite resolver and no dat font — sufficient for
/// conformance checks on tree structure and resolved types.
///
public static ImportedLayout LoadChat()
=> LayoutImporter.Build(LoadChatInfos(), _ => (0u, 0, 0), null);
///
/// Deserializes the committed chat_21000006.json fixture into a raw
/// tree WITHOUT calling .
/// Use this when the test needs to inspect the resolved
/// tree directly (e.g. resolved Type values per element id).
///
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(ReadOnlySpan)
// does not reject the first byte.
ReadOnlySpan span = bytes;
if (span.Length >= 3 && span[0] == 0xEF && span[1] == 0xBB && span[2] == 0xBF)
span = span[3..];
return JsonSerializer.Deserialize(span, _opts)
?? throw new InvalidOperationException($"fixture deserialized to null: {path}");
}
}