acdream/tests/AcDream.App.Tests/UI/Layout/CreatureAppraisalRowsTests.cs
Erik 7eaa68a5f4 feat(ui): port retail creature appraisal presentation
Render assessed creatures through the shared private viewport with retail heading, bounding-box camera, and light. Build the exact authored nine-row stat list and resolve creature names from the retail EnumMapper while keeping remaining font/sequencer adaptations explicit.

Co-authored-by: Codex <codex@openai.com>
2026-07-23 12:55:24 +02:00

100 lines
3.3 KiB
C#

using AcDream.App.UI.Layout;
using AcDream.Core.Net.Messages;
namespace AcDream.App.Tests.UI.Layout;
public sealed class CreatureAppraisalRowsTests
{
[Fact]
public void FailedAssessmentShowsOnlyHealthPercentAndUnknownOtherValues()
{
var profile = Profile(
health: 25u,
healthMax: 100u,
highlights: (ushort)0,
colors: (ushort)0);
IReadOnlyList<CreatureAppraisalRow> rows =
CreatureAppraisalRows.Build(profile, success: false);
Assert.All(
rows,
row => Assert.Equal(
CreatureAppraisalValueStyle.Incomplete,
row.Style));
Assert.Equal("25 %", rows[6].Value);
Assert.Equal("???", rows[0].Value);
Assert.Equal("???", rows[7].Value);
Assert.Equal("???", rows[8].Value);
}
[Fact]
public void EnchantmentBitsSelectRetailPositiveAndNegativeStyles()
{
var profile = Profile(
health: 100u,
healthMax: 100u,
highlights: (ushort)((1 << 0) | (1 << 6)),
colors: (ushort)(1 << 0));
IReadOnlyList<CreatureAppraisalRow> rows =
CreatureAppraisalRows.Build(profile, success: true);
Assert.Equal(CreatureAppraisalValueStyle.Positive, rows[0].Style);
Assert.Equal(CreatureAppraisalValueStyle.Negative, rows[6].Style);
Assert.Equal(CreatureAppraisalValueStyle.Normal, rows[1].Style);
}
[Fact]
public void AuthoredRowTemplateCarriesRetailOverlappingLabelValueGeometry()
{
ElementInfo template =
FixtureLoader.LoadExaminationRowTemplateInfos();
Assert.Equal(CreatureAppraisalRowTemplateFactory.TemplateId, template.Id);
Assert.Equal((292f, 20f), (template.Width, template.Height));
ElementInfo label = Assert.Single(
template.Children,
child => child.Id == CreatureAppraisalRowTemplateFactory.LabelId);
ElementInfo value = Assert.Single(
template.Children,
child => child.Id == CreatureAppraisalRowTemplateFactory.ValueId);
Assert.Equal((0f, 128f), (label.X, label.Width));
Assert.Equal((27f, 256f), (value.X, value.Width));
Assert.Equal(0x40000001u, label.FontDid);
Assert.Equal(0x40000001u, value.FontDid);
}
[Fact]
public void CreatureNameResolverUsesLoadedRetailMappingAndSafeFallback()
{
var resolver = new CreatureDisplayNameResolver(
new Dictionary<uint, string> { [77u] = "Ghost" });
Assert.Equal("Ghost", resolver.Resolve(77));
Assert.Equal(string.Empty, resolver.Resolve(0));
Assert.Equal(string.Empty, resolver.Resolve(999));
}
private static AppraiseInfoParser.CreatureProfile Profile(
uint health,
uint healthMax,
ushort highlights,
ushort colors)
=> new(
Flags: 0x09u,
Health: health,
HealthMax: healthMax,
Strength: null,
Endurance: null,
Quickness: null,
Coordination: null,
Focus: null,
Self: null,
Stamina: 50u,
Mana: 75u,
StaminaMax: 100u,
ManaMax: 100u,
AttributeHighlights: highlights,
AttributeColors: colors);
}