using Recordingtest.Bridge; using Recordingtest.Sut.EgBim.PluginHost; using Xunit; namespace Recordingtest.Sut.EgBim.PluginHost.Tests; public class ReflectionEngineStateProviderTests { private sealed class FakeAccessor : IAppManagerAccessor { public object? AppManager { get; set; } = new object(); public object? ActiveDocument { get; set; } public object? ActiveViewport { get; set; } public IReadOnlyList SelectedIds { get; set; } = Array.Empty(); public int ObjectCount { get; set; } public string? DocumentPath { get; set; } public (double[] Eye, double[] Target, double[] Up, double Fov)? Camera { get; set; } public bool ThrowOnSelection { get; set; } public bool ThrowOnCamera { get; set; } public bool ThrowOnScene { get; set; } public object? GetAppManager() => AppManager; public object? GetActiveDocument() => ActiveDocument; public object? GetActiveViewport() => ActiveViewport; public IReadOnlyList GetSelectedIds() { if (ThrowOnSelection) throw new InvalidOperationException("boom"); return SelectedIds; } public int GetObjectCount() { if (ThrowOnScene) throw new InvalidOperationException("boom"); return ObjectCount; } public string? GetDocumentPath() { if (ThrowOnScene) throw new InvalidOperationException("boom"); return DocumentPath; } public (double[] Eye, double[] Target, double[] Up, double Fov)? GetCameraTuple() { if (ThrowOnCamera) throw new InvalidOperationException("boom"); return Camera; } } [Fact] public void GetSelectedIds_Returns_Accessor_Values() { var fa = new FakeAccessor { SelectedIds = new[] { "a", "b" } }; var p = new ReflectionEngineStateProvider(fa); var ids = p.GetSelectedIds(); Assert.Equal(new[] { "a", "b" }, ids); } [Fact] public void GetSelectedIds_Swallows_Exception_Returns_Empty() { var fa = new FakeAccessor { ThrowOnSelection = true }; var p = new ReflectionEngineStateProvider(fa); Assert.Empty(p.GetSelectedIds()); } [Fact] public void GetCamera_Returns_Accessor_Tuple() { var fa = new FakeAccessor { Camera = ( Eye: new double[] { 1, 2, 3 }, Target: new double[] { 4, 5, 6 }, Up: new double[] { 0, 0, 1 }, Fov: 60.0) }; var p = new ReflectionEngineStateProvider(fa); var c = p.GetCamera(); Assert.Equal(new double[] { 1, 2, 3 }, c.Eye); Assert.Equal(new double[] { 4, 5, 6 }, c.Target); Assert.Equal(60.0, c.Fov); } [Fact] public void GetCamera_Null_Tuple_Returns_Default() { var fa = new FakeAccessor { Camera = null }; var p = new ReflectionEngineStateProvider(fa); var c = p.GetCamera(); Assert.Equal(45.0, c.Fov); Assert.Equal(new double[] { 0, 0, 1 }, c.Up); } [Fact] public void GetCamera_Throwing_Accessor_Returns_Default_Not_Throw() { var fa = new FakeAccessor { ThrowOnCamera = true }; var p = new ReflectionEngineStateProvider(fa); var c = p.GetCamera(); Assert.Equal(45.0, c.Fov); } [Fact] public void GetScene_Returns_Accessor_Values() { var fa = new FakeAccessor { ObjectCount = 42, DocumentPath = "C:/x.hmeg" }; var p = new ReflectionEngineStateProvider(fa); var s = p.GetScene(); Assert.Equal(42, s.ObjectCount); Assert.Equal("C:/x.hmeg", s.DocumentPath); } [Fact] public void GetScene_Throwing_Accessor_Returns_Empty_Default() { var fa = new FakeAccessor { ThrowOnScene = true }; var p = new ReflectionEngineStateProvider(fa); var s = p.GetScene(); Assert.Equal(0, s.ObjectCount); Assert.Null(s.DocumentPath); } [Fact] public void Default_Reflection_Accessor_Without_Hmeg_Returns_Null_Safely() { // CI process has no Editor.AppManager.AppManager type loaded; the // accessor must return null/empty/default without throwing. var acc = new ReflectionAppManagerAccessor(seedRoot: new object()); Assert.Null(acc.GetAppManager()); Assert.Null(acc.GetActiveDocument()); Assert.Null(acc.GetActiveViewport()); Assert.Empty(acc.GetSelectedIds()); Assert.Equal(0, acc.GetObjectCount()); Assert.Null(acc.GetDocumentPath()); Assert.Null(acc.GetCameraTuple()); } [Fact] public void Provider_With_Default_Accessor_Without_Hmeg_Returns_Defaults() { // End-to-end fallback: provider built from a non-HmEG seed must // produce the v2 safe defaults so /state continues to respond. var p = new ReflectionEngineStateProvider(seedRoot: new object()); Assert.Empty(p.GetSelectedIds()); var c = p.GetCamera(); Assert.Equal(45.0, c.Fov); var s = p.GetScene(); Assert.Equal(0, s.ObjectCount); Assert.True(p.GetRenderComplete()); } }