Files
recordingtest/tests/Sut/EgBim/Recordingtest.Sut.EgBim.PluginHost.Tests/ChainedEngineStateProviderTests.cs
minsung 11eb92b2b2 feat: camera-restore + LauncherUI UX 개선 + player fallback 강화 (#15)
camera-restore:
- IEngineStateProvider.SetCamera 반사 쓰기 (HmegDirectStateProvider)
- POST /camera/restore (BridgeHttpServer, StateRouter)
- Recorder --sidecar-url + camera_snapshot 캡처
- UiaPlayerHost.TryRestoreCamera, PlayerEngine 재생 전 복원
- 149 tests

LauncherUI (#15):
- Sidecar URL 체크박스 + 입력란 (녹화/재생 모두 연동)
- 재생 속도 슬라이더 (0.25x~4.0x, 기본 1.0x)
- 빌드 타임스탬프 타이틀바 표시
- 녹화 완료 후 RecordNameBox 초기화
- UiAnalysisWindow 추가

PlayerEngine (#15):
- CancellationToken 지원 (중단 버튼 동작)
- Focus 스텝 early return (no-op, issue #11)
- Type/Drag unresolvable UIA path fallback
- SpeedMultiplier 옵션

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 18:37:13 +09:00

95 lines
3.3 KiB
C#

using Recordingtest.Bridge;
using Recordingtest.Sut.EgBim.PluginHost;
using Xunit;
namespace Recordingtest.Sut.EgBim.PluginHost.Tests;
public class ChainedEngineStateProviderTests
{
private sealed class ScriptedProvider : IEngineStateProvider
{
public IReadOnlyList<string> SelectedIds = Array.Empty<string>();
public CameraSnapshot Camera = new(
new double[] { 0, 0, 0 },
new double[] { 0, 0, 0 },
new double[] { 0, 0, 1 },
45.0);
public SceneSnapshot Scene = new(0, null);
public bool Render = true;
public IReadOnlyList<string> GetSelectedIds() => SelectedIds;
public CameraSnapshot GetCamera() => Camera;
public SceneSnapshot GetScene() => Scene;
public bool GetRenderComplete() => Render;
public void SetCamera(CameraSnapshot snapshot) { /* tracked if needed */ }
}
[Fact]
public void Selection_Primary_NonEmpty_Wins()
{
var p = new ScriptedProvider { SelectedIds = new[] { "a" } };
var f = new ScriptedProvider { SelectedIds = new[] { "fallback" } };
var c = new ChainedEngineStateProvider(p, f);
Assert.Equal(new[] { "a" }, c.GetSelectedIds());
}
[Fact]
public void Selection_Primary_Empty_Falls_Through()
{
var p = new ScriptedProvider();
var f = new ScriptedProvider { SelectedIds = new[] { "fallback" } };
var c = new ChainedEngineStateProvider(p, f);
Assert.Equal(new[] { "fallback" }, c.GetSelectedIds());
}
[Fact]
public void Camera_Primary_Default_Falls_Through()
{
var p = new ScriptedProvider();
var fc = new CameraSnapshot(new double[] { 1, 2, 3 }, new double[] { 4, 5, 6 }, new double[] { 0, 0, 1 }, 60);
var f = new ScriptedProvider { Camera = fc };
var c = new ChainedEngineStateProvider(p, f);
Assert.Equal(60.0, c.GetCamera().Fov);
}
[Fact]
public void Camera_Primary_NonDefault_Wins()
{
var pc = new CameraSnapshot(new double[] { 1, 0, 0 }, new double[] { 0, 0, 0 }, new double[] { 0, 0, 1 }, 30);
var p = new ScriptedProvider { Camera = pc };
var f = new ScriptedProvider();
var c = new ChainedEngineStateProvider(p, f);
Assert.Equal(30.0, c.GetCamera().Fov);
}
[Fact]
public void Scene_Primary_Empty_Falls_Through()
{
var p = new ScriptedProvider();
var f = new ScriptedProvider { Scene = new(7, "x.hmeg") };
var c = new ChainedEngineStateProvider(p, f);
var s = c.GetScene();
Assert.Equal(7, s.ObjectCount);
Assert.Equal("x.hmeg", s.DocumentPath);
}
[Fact]
public void Scene_Primary_Has_Path_Wins_Even_With_Zero_Objects()
{
var p = new ScriptedProvider { Scene = new(0, "primary.hmeg") };
var f = new ScriptedProvider { Scene = new(99, "fallback.hmeg") };
var c = new ChainedEngineStateProvider(p, f);
var s = c.GetScene();
Assert.Equal("primary.hmeg", s.DocumentPath);
}
[Fact]
public void Render_Primary_Always_Wins()
{
var p = new ScriptedProvider { Render = false };
var f = new ScriptedProvider { Render = true };
var c = new ChainedEngineStateProvider(p, f);
Assert.False(c.GetRenderComplete());
}
}