feat(studio): FixtureProvider — sample data populates the 2-D panels
Task 4 of the UI Studio plan: adds SampleData (static ClientObjectTable builder with a synthetic player, 6 loose items, 2 side bags, and 3 equipped pieces) and FixtureProvider (switches on layoutId and calls the production controller Bind methods — VitalsController, ToolbarController, InventoryController — so the studio previews panels with plausible data instead of empty widgets). Icon ids approach: raw-resolve stub — resolves the base iconId via RenderStack.ResolveChrome and returns the GL handle directly. This is v1 (single-layer icon); the full 5-layer IconComposer composite is a live-game concern, not a layout-preview concern. StudioWindow wires FixtureProvider.Populate after _source.Load; the ClientObjectTable is stored on _objects so controller event subscriptions (ObjectAdded/ObjectMoved) remain live for the window's lifetime. 4 new FixtureProviderTests (SampleTable_hasPackContents, SampleTable_hasWeaponAndArmor, SampleTable_hasEquippedItems, SampleTable_hasSideBags) — all pass. Full App suite: 602 passed / 2 skipped (pre-existing) / 0 failed. Build green. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
101a35cc2d
commit
0bdc866c15
4 changed files with 402 additions and 0 deletions
105
tests/AcDream.App.Tests/Studio/FixtureProviderTests.cs
Normal file
105
tests/AcDream.App.Tests/Studio/FixtureProviderTests.cs
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
using AcDream.App.Studio;
|
||||
using AcDream.Core.Items;
|
||||
|
||||
namespace AcDream.App.Tests.Studio;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for <see cref="FixtureProvider"/> and <see cref="SampleData"/>.
|
||||
/// These tests have NO GL/dat dependency — they only exercise the in-memory
|
||||
/// ClientObjectTable population that FixtureProvider uses.
|
||||
/// </summary>
|
||||
public class FixtureProviderTests
|
||||
{
|
||||
/// <summary>
|
||||
/// SampleData.BuildObjectTable() must place at least 6 items in the
|
||||
/// player's main pack (ContainerId == PlayerGuid) and the player object
|
||||
/// itself must exist with the right capacities.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SampleTable_hasPackContents()
|
||||
{
|
||||
var t = SampleData.BuildObjectTable();
|
||||
|
||||
// Player object must exist.
|
||||
var player = t.Get(SampleData.PlayerGuid);
|
||||
Assert.NotNull(player);
|
||||
Assert.Equal(102, player!.ItemsCapacity);
|
||||
Assert.Equal(7, player.ContainersCapacity);
|
||||
|
||||
// At least 6 loose items must be in the main pack.
|
||||
var contents = t.GetContents(SampleData.PlayerGuid);
|
||||
Assert.True(contents.Count >= 6,
|
||||
$"Expected >= 6 items in player pack; got {contents.Count}");
|
||||
|
||||
// Verify the first item has a non-zero IconId and a recognised Type.
|
||||
var firstId = contents[0];
|
||||
var first = t.Get(firstId);
|
||||
Assert.NotNull(first);
|
||||
Assert.NotEqual(0u, first!.IconId);
|
||||
Assert.NotEqual(ItemType.None, first.Type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spot-check that the sample table also seeds a sword-like item
|
||||
/// (MeleeWeapon) and a piece of armor so icon resolution has
|
||||
/// recognisable item types to work with.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SampleTable_hasWeaponAndArmor()
|
||||
{
|
||||
var t = SampleData.BuildObjectTable();
|
||||
var contents = t.GetContents(SampleData.PlayerGuid);
|
||||
|
||||
bool hasMelee = false, hasArmor = false;
|
||||
foreach (var guid in contents)
|
||||
{
|
||||
var obj = t.Get(guid);
|
||||
if (obj is null) continue;
|
||||
if ((obj.Type & ItemType.MeleeWeapon) != 0) hasMelee = true;
|
||||
if ((obj.Type & ItemType.Armor) != 0) hasArmor = true;
|
||||
}
|
||||
|
||||
Assert.True(hasMelee, "Expected at least one MeleeWeapon in sample pack");
|
||||
Assert.True(hasArmor, "Expected at least one Armor item in sample pack");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sample table must include at least 1 equipped item whose
|
||||
/// CurrentlyEquippedLocation is non-None.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SampleTable_hasEquippedItems()
|
||||
{
|
||||
var t = SampleData.BuildObjectTable();
|
||||
|
||||
bool anyEquipped = false;
|
||||
foreach (var obj in t.Objects)
|
||||
{
|
||||
if (obj.CurrentlyEquippedLocation != EquipMask.None)
|
||||
{ anyEquipped = true; break; }
|
||||
}
|
||||
|
||||
Assert.True(anyEquipped, "Expected at least one equipped item in sample table");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sample table must include at least 2 side-bag containers in the
|
||||
/// player's pack (ContainerId == PlayerGuid, Type has Container bit).
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SampleTable_hasSideBags()
|
||||
{
|
||||
var t = SampleData.BuildObjectTable();
|
||||
|
||||
int bagCount = 0;
|
||||
foreach (var guid in t.GetContents(SampleData.PlayerGuid))
|
||||
{
|
||||
var obj = t.Get(guid);
|
||||
if (obj is not null && (obj.Type & ItemType.Container) != 0)
|
||||
bagCount++;
|
||||
}
|
||||
|
||||
Assert.True(bagCount >= 2,
|
||||
$"Expected >= 2 side-bag containers in player pack; got {bagCount}");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue