修复 Unity Test Runner 测试签名

This commit is contained in:
JSD\13999
2026-05-19 10:41:31 +08:00
parent 210715d0cd
commit 48785f9f6a
8 changed files with 97 additions and 90 deletions

View File

@@ -9,71 +9,71 @@ namespace FlowScope.Tests.EditMode.Config
public sealed class JsonConfigProviderTests public sealed class JsonConfigProviderTests
{ {
[Test] [Test]
public async Task LoadAllAsync_LoadsRegisteredJsonRows() public void LoadAllAsync_LoadsRegisteredJsonRows()
{ {
var provider = new JsonConfigProvider(new[] var provider = new JsonConfigProvider(new[]
{ {
JsonConfigProvider.Mapping<WeaponConfig>("weapons.json", _ => Task.FromResult("[{\"id\":101,\"name\":\"Axe\"}]")) JsonConfigProvider.Mapping<WeaponConfig>("weapons.json", _ => Task.FromResult("[{\"id\":101,\"name\":\"Axe\"}]"))
}); });
await provider.LoadAllAsync(CancellationToken.None); provider.LoadAllAsync(CancellationToken.None).GetAwaiter().GetResult();
Assert.That(provider.Get<WeaponConfig>(101).Name, Is.EqualTo("Axe")); Assert.That(provider.Get<WeaponConfig>(101).Name, Is.EqualTo("Axe"));
} }
[Test] [Test]
public async Task Get_MissingId_ReturnsNull() public void Get_MissingId_ReturnsNull()
{ {
var provider = new JsonConfigProvider(new[] var provider = new JsonConfigProvider(new[]
{ {
JsonConfigProvider.Mapping<WeaponConfig>("weapons.json", _ => Task.FromResult("[{\"id\":101,\"name\":\"Axe\"}]")) JsonConfigProvider.Mapping<WeaponConfig>("weapons.json", _ => Task.FromResult("[{\"id\":101,\"name\":\"Axe\"}]"))
}); });
await provider.LoadAllAsync(CancellationToken.None); provider.LoadAllAsync(CancellationToken.None).GetAwaiter().GetResult();
Assert.That(provider.Get<WeaponConfig>(999), Is.Null); Assert.That(provider.Get<WeaponConfig>(999), Is.Null);
} }
[Test] [Test]
public async Task GetAll_UnloadedType_ReturnsEmptyList() public void GetAll_UnloadedType_ReturnsEmptyList()
{ {
var provider = new JsonConfigProvider(Array.Empty<JsonConfigProvider.ConfigMapping>()); var provider = new JsonConfigProvider(Array.Empty<JsonConfigProvider.ConfigMapping>());
await provider.LoadAllAsync(CancellationToken.None); provider.LoadAllAsync(CancellationToken.None).GetAwaiter().GetResult();
Assert.That(provider.GetAll<WeaponConfig>(), Is.Empty); Assert.That(provider.GetAll<WeaponConfig>(), Is.Empty);
} }
[Test] [Test]
public async Task LoadAllAsync_DuplicateId_ThrowsWithId() public void LoadAllAsync_DuplicateId_ThrowsWithId()
{ {
var provider = new JsonConfigProvider(new[] var provider = new JsonConfigProvider(new[]
{ {
JsonConfigProvider.Mapping<WeaponConfig>("weapons.json", _ => Task.FromResult("[{\"id\":101,\"name\":\"Axe\"},{\"id\":101,\"name\":\"Sword\"}]")) JsonConfigProvider.Mapping<WeaponConfig>("weapons.json", _ => Task.FromResult("[{\"id\":101,\"name\":\"Axe\"},{\"id\":101,\"name\":\"Sword\"}]"))
}); });
var exception = await ThrowsAsync<InvalidOperationException>( var exception = ThrowsAsync<InvalidOperationException>(
async () => await provider.LoadAllAsync(CancellationToken.None)); () => provider.LoadAllAsync(CancellationToken.None));
Assert.That(exception.Message, Does.Contain("101")); Assert.That(exception.Message, Does.Contain("101"));
} }
[Test] [Test]
public async Task LoadAllAsync_MalformedJson_ThrowsWithFileName() public void LoadAllAsync_MalformedJson_ThrowsWithFileName()
{ {
var provider = new JsonConfigProvider(new[] var provider = new JsonConfigProvider(new[]
{ {
JsonConfigProvider.Mapping<WeaponConfig>("weapons.json", _ => Task.FromResult("[{\"id\":101")) JsonConfigProvider.Mapping<WeaponConfig>("weapons.json", _ => Task.FromResult("[{\"id\":101"))
}); });
var exception = await ThrowsAsync<InvalidOperationException>( var exception = ThrowsAsync<InvalidOperationException>(
async () => await provider.LoadAllAsync(CancellationToken.None)); () => provider.LoadAllAsync(CancellationToken.None));
Assert.That(exception.Message, Does.Contain("weapons.json")); Assert.That(exception.Message, Does.Contain("weapons.json"));
} }
[Test] [Test]
public async Task LoadAllAsync_CanceledToken_ThrowsOperationCanceledException() public void LoadAllAsync_CanceledToken_ThrowsOperationCanceledException()
{ {
using var cts = new CancellationTokenSource(); using var cts = new CancellationTokenSource();
cts.Cancel(); cts.Cancel();
@@ -82,16 +82,16 @@ namespace FlowScope.Tests.EditMode.Config
JsonConfigProvider.Mapping<WeaponConfig>("weapons.json", _ => Task.FromResult("[]")) JsonConfigProvider.Mapping<WeaponConfig>("weapons.json", _ => Task.FromResult("[]"))
}); });
await ThrowsAsync<OperationCanceledException>( ThrowsAsync<OperationCanceledException>(
async () => await provider.LoadAllAsync(cts.Token)); () => provider.LoadAllAsync(cts.Token));
} }
private static async Task<TException> ThrowsAsync<TException>(Func<Task> action) private static TException ThrowsAsync<TException>(Func<Task> action)
where TException : Exception where TException : Exception
{ {
try try
{ {
await action(); action().GetAwaiter().GetResult();
} }
catch (TException exception) catch (TException exception)
{ {

View File

@@ -12,25 +12,25 @@ namespace FlowScope.Tests.EditMode.Flow
public sealed class FeatureBaseTests public sealed class FeatureBaseTests
{ {
[Test] [Test]
public async Task LoadAsync_StoresContext() public void LoadAsync_StoresContext()
{ {
var context = CreateContext(); var context = CreateContext();
var feature = new TestFeature(); var feature = new TestFeature();
await feature.LoadAsync(context); feature.LoadAsync(context).GetAwaiter().GetResult();
Assert.That(feature.ExposedContext, Is.SameAs(context)); Assert.That(feature.ExposedContext, Is.SameAs(context));
} }
[Test] [Test]
public async Task ExitAsync_ClearsContextDisposables() public void ExitAsync_ClearsContextDisposables()
{ {
var context = CreateContext(); var context = CreateContext();
var disposable = new SpyDisposable(); var disposable = new SpyDisposable();
context.Disposables.Add(disposable); context.Disposables.Add(disposable);
var feature = new TestFeature(); var feature = new TestFeature();
await feature.ExitAsync(context); feature.ExitAsync(context).GetAwaiter().GetResult();
Assert.That(disposable.IsDisposed, Is.True); Assert.That(disposable.IsDisposed, Is.True);
} }

View File

@@ -24,14 +24,14 @@ namespace FlowScope.Tests.EditMode.Flow
} }
[Test] [Test]
public async Task StartupAsync_LoadsConfigCreatesContextAndEntersInitialFeature() public void StartupAsync_LoadsConfigCreatesContextAndEntersInitialFeature()
{ {
var services = new TestServices(); var services = new TestServices();
var root = services.CreateRoot(); var root = services.CreateRoot();
using var cts = new CancellationTokenSource(); using var cts = new CancellationTokenSource();
var flow = new GameFlow(); var flow = new GameFlow();
await flow.StartupAsync<FirstFeature>(root, cts.Token); flow.StartupAsync<FirstFeature>(root, cts.Token).GetAwaiter().GetResult();
Assert.That(flow.State, Is.EqualTo(GameFlowState.Running)); Assert.That(flow.State, Is.EqualTo(GameFlowState.Running));
Assert.That(services.Config.LoadCalls, Is.EqualTo(1)); Assert.That(services.Config.LoadCalls, Is.EqualTo(1));
@@ -42,14 +42,14 @@ namespace FlowScope.Tests.EditMode.Flow
} }
[Test] [Test]
public async Task SwitchToAsync_ExitsDisposesAndReleasesOldContextBeforeEnteringNextFeature() public void SwitchToAsync_ExitsDisposesAndReleasesOldContextBeforeEnteringNextFeature()
{ {
var services = new TestServices(); var services = new TestServices();
var root = services.CreateRoot(); var root = services.CreateRoot();
var flow = new GameFlow(); var flow = new GameFlow();
await flow.StartupAsync<FirstFeature>(root, CancellationToken.None); flow.StartupAsync<FirstFeature>(root, CancellationToken.None).GetAwaiter().GetResult();
await flow.SwitchToAsync<SecondFeature>(CancellationToken.None); flow.SwitchToAsync<SecondFeature>(CancellationToken.None).GetAwaiter().GetResult();
Assert.That(flow.State, Is.EqualTo(GameFlowState.Running)); Assert.That(flow.State, Is.EqualTo(GameFlowState.Running));
Assert.That(FirstFeature.Instance.Calls, Is.EqualTo(new[] { "Load", "Enter", "Exit", "Dispose" })); Assert.That(FirstFeature.Instance.Calls, Is.EqualTo(new[] { "Load", "Enter", "Exit", "Dispose" }));
@@ -59,14 +59,14 @@ namespace FlowScope.Tests.EditMode.Flow
} }
[Test] [Test]
public async Task StartupAsync_WhenFeatureLoadFails_CleansCreatedFeatureAndReturnsIdle() public void StartupAsync_WhenFeatureLoadFails_CleansCreatedFeatureAndReturnsIdle()
{ {
var services = new TestServices(); var services = new TestServices();
var root = services.CreateRoot(); var root = services.CreateRoot();
var flow = new GameFlow(); var flow = new GameFlow();
await ThrowsAsync<InvalidOperationException>( ThrowsAsync<InvalidOperationException>(
async () => await flow.StartupAsync<FailingLoadFeature>(root, CancellationToken.None)); () => flow.StartupAsync<FailingLoadFeature>(root, CancellationToken.None));
Assert.That(flow.State, Is.EqualTo(GameFlowState.Idle)); Assert.That(flow.State, Is.EqualTo(GameFlowState.Idle));
Assert.That(FailingLoadFeature.Instance.Calls, Is.EqualTo(new[] { "Load", "Dispose" })); Assert.That(FailingLoadFeature.Instance.Calls, Is.EqualTo(new[] { "Load", "Dispose" }));
@@ -74,15 +74,15 @@ namespace FlowScope.Tests.EditMode.Flow
} }
[Test] [Test]
public async Task SwitchToAsync_WhenNextEnterFails_CleansNextFeatureAndLeavesNoActiveFeature() public void SwitchToAsync_WhenNextEnterFails_CleansNextFeatureAndLeavesNoActiveFeature()
{ {
var services = new TestServices(); var services = new TestServices();
var root = services.CreateRoot(); var root = services.CreateRoot();
var flow = new GameFlow(); var flow = new GameFlow();
await flow.StartupAsync<FirstFeature>(root, CancellationToken.None); flow.StartupAsync<FirstFeature>(root, CancellationToken.None).GetAwaiter().GetResult();
await ThrowsAsync<InvalidOperationException>( ThrowsAsync<InvalidOperationException>(
async () => await flow.SwitchToAsync<FailingEnterFeature>(CancellationToken.None)); () => flow.SwitchToAsync<FailingEnterFeature>(CancellationToken.None));
Assert.That(flow.State, Is.EqualTo(GameFlowState.NoActiveFeature)); Assert.That(flow.State, Is.EqualTo(GameFlowState.NoActiveFeature));
Assert.That(FirstFeature.Instance.Calls, Does.Contain("Dispose")); Assert.That(FirstFeature.Instance.Calls, Does.Contain("Dispose"));
@@ -91,55 +91,55 @@ namespace FlowScope.Tests.EditMode.Flow
} }
[Test] [Test]
public async Task SwitchToAsync_WhenIdle_ThrowsWithOperationAndCurrentState() public void SwitchToAsync_WhenIdle_ThrowsWithOperationAndCurrentState()
{ {
var flow = new GameFlow(); var flow = new GameFlow();
var exception = await ThrowsAsync<InvalidOperationException>( var exception = ThrowsAsync<InvalidOperationException>(
async () => await flow.SwitchToAsync<FirstFeature>(CancellationToken.None)); () => flow.SwitchToAsync<FirstFeature>(CancellationToken.None));
Assert.That(exception.Message, Does.Contain(nameof(GameFlow.SwitchToAsync))); Assert.That(exception.Message, Does.Contain(nameof(GameFlow.SwitchToAsync)));
Assert.That(exception.Message, Does.Contain(GameFlowState.Idle.ToString())); Assert.That(exception.Message, Does.Contain(GameFlowState.Idle.ToString()));
} }
[Test] [Test]
public async Task ShutdownAsync_WhenFeatureCleanupThrows_StillReachesDisposed() public void ShutdownAsync_WhenFeatureCleanupThrows_StillReachesDisposed()
{ {
var services = new TestServices(); var services = new TestServices();
var root = services.CreateRoot(); var root = services.CreateRoot();
var flow = new GameFlow(); var flow = new GameFlow();
await flow.StartupAsync<ThrowingExitAndDisposeFeature>(root, CancellationToken.None); flow.StartupAsync<ThrowingExitAndDisposeFeature>(root, CancellationToken.None).GetAwaiter().GetResult();
await flow.ShutdownAsync(CancellationToken.None); flow.ShutdownAsync(CancellationToken.None).GetAwaiter().GetResult();
Assert.That(flow.State, Is.EqualTo(GameFlowState.Disposed)); Assert.That(flow.State, Is.EqualTo(GameFlowState.Disposed));
Assert.That(services.Resource.Groups[0].IsDisposed, Is.True); Assert.That(services.Resource.Groups[0].IsDisposed, Is.True);
} }
[Test] [Test]
public async Task ShutdownAsync_WhenCancellationIsAlreadyRequested_CleansUpThenThrowsCancellation() public void ShutdownAsync_WhenCancellationIsAlreadyRequested_CleansUpThenThrowsCancellation()
{ {
var services = new TestServices(); var services = new TestServices();
var root = services.CreateRoot(); var root = services.CreateRoot();
var flow = new GameFlow(); var flow = new GameFlow();
await flow.StartupAsync<FirstFeature>(root, CancellationToken.None); flow.StartupAsync<FirstFeature>(root, CancellationToken.None).GetAwaiter().GetResult();
using var cts = new CancellationTokenSource(); using var cts = new CancellationTokenSource();
cts.Cancel(); cts.Cancel();
await ThrowsAsync<OperationCanceledException>( ThrowsAsync<OperationCanceledException>(
async () => await flow.ShutdownAsync(cts.Token)); () => flow.ShutdownAsync(cts.Token));
Assert.That(flow.State, Is.EqualTo(GameFlowState.Disposed)); Assert.That(flow.State, Is.EqualTo(GameFlowState.Disposed));
Assert.That(FirstFeature.Instance.Calls, Does.Contain("Dispose")); Assert.That(FirstFeature.Instance.Calls, Does.Contain("Dispose"));
Assert.That(services.Resource.Groups[0].IsDisposed, Is.True); Assert.That(services.Resource.Groups[0].IsDisposed, Is.True);
} }
private static async Task<TException> ThrowsAsync<TException>(Func<Task> action) private static TException ThrowsAsync<TException>(Func<Task> action)
where TException : Exception where TException : Exception
{ {
try try
{ {
await action(); action().GetAwaiter().GetResult();
} }
catch (TException exception) catch (TException exception)
{ {

View File

@@ -11,43 +11,43 @@ namespace FlowScope.Tests.EditMode.Save
public sealed class SaveServiceTests public sealed class SaveServiceTests
{ {
[Test] [Test]
public async Task SaveAsync_ThenLoadAsync_ReturnsEquivalentData() public void SaveAsync_ThenLoadAsync_ReturnsEquivalentData()
{ {
var service = new SaveService(new MemorySaveStorage(), new JsonSaveSerializer()); var service = new SaveService(new MemorySaveStorage(), new JsonSaveSerializer());
var data = new PlayerData(); var data = new PlayerData();
data.Gold.Value = 88; data.Gold.Value = 88;
await service.SaveAsync("player", data, CancellationToken.None); service.SaveAsync("player", data, CancellationToken.None).GetAwaiter().GetResult();
var loaded = await service.LoadAsync("player", new PlayerData(), CancellationToken.None); var loaded = service.LoadAsync("player", new PlayerData(), CancellationToken.None).GetAwaiter().GetResult();
Assert.That(loaded.Gold.Value, Is.EqualTo(88)); Assert.That(loaded.Gold.Value, Is.EqualTo(88));
} }
[Test] [Test]
public async Task LoadAsync_MissingKey_ReturnsDefaultValue() public void LoadAsync_MissingKey_ReturnsDefaultValue()
{ {
var service = new SaveService(new MemorySaveStorage(), new JsonSaveSerializer()); var service = new SaveService(new MemorySaveStorage(), new JsonSaveSerializer());
var fallback = new PlayerData(); var fallback = new PlayerData();
fallback.Gold.Value = 5; fallback.Gold.Value = 5;
var loaded = await service.LoadAsync("missing", fallback, CancellationToken.None); var loaded = service.LoadAsync("missing", fallback, CancellationToken.None).GetAwaiter().GetResult();
Assert.That(loaded, Is.SameAs(fallback)); Assert.That(loaded, Is.SameAs(fallback));
} }
[Test] [Test]
public async Task Delete_RemovesExistingKey() public void Delete_RemovesExistingKey()
{ {
var service = new SaveService(new MemorySaveStorage(), new JsonSaveSerializer()); var service = new SaveService(new MemorySaveStorage(), new JsonSaveSerializer());
await service.SaveAsync("player", new PlayerData(), CancellationToken.None); service.SaveAsync("player", new PlayerData(), CancellationToken.None).GetAwaiter().GetResult();
service.Delete("player"); service.Delete("player");
Assert.That(service.Exists("player"), Is.False); Assert.That(service.Exists("player"), Is.False);
} }
[Test] [Test]
public async Task LoadAsync_DeserializeFailure_ReturnsDefaultValue() public void LoadAsync_DeserializeFailure_ReturnsDefaultValue()
{ {
var storage = new MemorySaveStorage(); var storage = new MemorySaveStorage();
storage.Seed("player", new byte[] { 123, 34, 71, 111, 108, 100 }); storage.Seed("player", new byte[] { 123, 34, 71, 111, 108, 100 });
@@ -55,39 +55,39 @@ namespace FlowScope.Tests.EditMode.Save
var fallback = new PlayerData(); var fallback = new PlayerData();
fallback.Gold.Value = 9; fallback.Gold.Value = 9;
var loaded = await service.LoadAsync("player", fallback, CancellationToken.None); var loaded = service.LoadAsync("player", fallback, CancellationToken.None).GetAwaiter().GetResult();
Assert.That(loaded, Is.SameAs(fallback)); Assert.That(loaded, Is.SameAs(fallback));
} }
[Test] [Test]
public async Task SaveAsync_WriteFailure_ThrowsWithKey() public void SaveAsync_WriteFailure_ThrowsWithKey()
{ {
var service = new SaveService(new FailingWriteStorage(), new JsonSaveSerializer()); var service = new SaveService(new FailingWriteStorage(), new JsonSaveSerializer());
var exception = await ThrowsAsync<InvalidOperationException>( var exception = ThrowsAsync<InvalidOperationException>(
async () => await service.SaveAsync("player", new PlayerData(), CancellationToken.None)); () => service.SaveAsync("player", new PlayerData(), CancellationToken.None));
Assert.That(exception.Message, Does.Contain("player")); Assert.That(exception.Message, Does.Contain("player"));
} }
[Test] [Test]
public async Task SaveAsync_CanceledToken_ThrowsOperationCanceledException() public void SaveAsync_CanceledToken_ThrowsOperationCanceledException()
{ {
using var cts = new CancellationTokenSource(); using var cts = new CancellationTokenSource();
cts.Cancel(); cts.Cancel();
var service = new SaveService(new MemorySaveStorage(), new JsonSaveSerializer()); var service = new SaveService(new MemorySaveStorage(), new JsonSaveSerializer());
await ThrowsAsync<OperationCanceledException>( ThrowsAsync<OperationCanceledException>(
async () => await service.SaveAsync("player", new PlayerData(), cts.Token)); () => service.SaveAsync("player", new PlayerData(), cts.Token));
} }
private static async Task<TException> ThrowsAsync<TException>(Func<Task> action) private static TException ThrowsAsync<TException>(Func<Task> action)
where TException : Exception where TException : Exception
{ {
try try
{ {
await action(); action().GetAwaiter().GetResult();
} }
catch (TException exception) catch (TException exception)
{ {

View File

@@ -9,7 +9,7 @@ namespace FlowScope.Tests.PlayMode.Resources
public sealed class AddressablesResourceServiceTests public sealed class AddressablesResourceServiceTests
{ {
[Test] [Test]
public async Task LoadAsync_WhenSameKeyLoadsConcurrently_SharesOneBackendLoad() public void LoadAsync_WhenSameKeyLoadsConcurrently_SharesOneBackendLoad()
{ {
var backendLoads = 0; var backendLoads = 0;
var releaseCount = 0; var releaseCount = 0;
@@ -26,8 +26,8 @@ namespace FlowScope.Tests.PlayMode.Resources
var second = service.LoadAsync<TestAsset>("shared", CancellationToken.None); var second = service.LoadAsync<TestAsset>("shared", CancellationToken.None);
gate.SetResult(new TestAsset()); gate.SetResult(new TestAsset());
var firstHandle = await first; var firstHandle = first.GetAwaiter().GetResult();
var secondHandle = await second; var secondHandle = second.GetAwaiter().GetResult();
Assert.AreEqual(1, backendLoads); Assert.AreEqual(1, backendLoads);
Assert.AreSame(firstHandle.Asset, secondHandle.Asset); Assert.AreSame(firstHandle.Asset, secondHandle.Asset);
@@ -39,25 +39,25 @@ namespace FlowScope.Tests.PlayMode.Resources
} }
[Test] [Test]
public async Task LoadAsync_WhenBackendFails_IncludesKeyAndBackend() public void LoadAsync_WhenBackendFails_IncludesKeyAndBackend()
{ {
var service = new AddressablesResourceService( var service = new AddressablesResourceService(
(_, _, _) => throw new InvalidOperationException("missing"), (_, _, _) => throw new InvalidOperationException("missing"),
(_, _) => { }); (_, _) => { });
var exception = await ThrowsAsync<InvalidOperationException>( var exception = ThrowsAsync<InvalidOperationException>(
() => service.LoadAsync<TestAsset>("missing-key", CancellationToken.None)); () => service.LoadAsync<TestAsset>("missing-key", CancellationToken.None));
StringAssert.Contains("missing-key", exception.Message); StringAssert.Contains("missing-key", exception.Message);
StringAssert.Contains("Addressables", exception.Message); StringAssert.Contains("Addressables", exception.Message);
} }
private static async Task<TException> ThrowsAsync<TException>(Func<Task> action) private static TException ThrowsAsync<TException>(Func<Task> action)
where TException : Exception where TException : Exception
{ {
try try
{ {
await action(); action().GetAwaiter().GetResult();
} }
catch (TException exception) catch (TException exception)
{ {

View File

@@ -21,7 +21,7 @@ namespace FlowScope.Tests.PlayMode.Samples
} }
[Test] [Test]
public async Task Bootstrap_CanConstructAndShutdownWithoutSceneAsset() public void Bootstrap_CanConstructAndShutdownWithoutSceneAsset()
{ {
var root = new GameObject("bootstrap-test"); var root = new GameObject("bootstrap-test");
var panelObject = new GameObject("panel-prefab"); var panelObject = new GameObject("panel-prefab");
@@ -36,7 +36,7 @@ namespace FlowScope.Tests.PlayMode.Samples
panel.Configure(label, button); panel.Configure(label, button);
var bootstrap = root.AddComponent<GameBootstrap>(); var bootstrap = root.AddComponent<GameBootstrap>();
await bootstrap.ShutdownAsync(CancellationToken.None); bootstrap.ShutdownAsync(CancellationToken.None).GetAwaiter().GetResult();
Object.DestroyImmediate(panelObject); Object.DestroyImmediate(panelObject);
Object.DestroyImmediate(root); Object.DestroyImmediate(root);

View File

@@ -28,7 +28,7 @@ namespace FlowScope.Tests.PlayMode.UI
} }
[Test] [Test]
public async Task OpenAsync_UsesAttributePathAndMountsPanelToRegisteredLayer() public void OpenAsync_UsesAttributePathAndMountsPanelToRegisteredLayer()
{ {
var canvas = CreateCanvas("popup"); var canvas = CreateCanvas("popup");
var prefab = CreatePrefab<ExplicitPathPanel>("ExplicitPathPrefab"); var prefab = CreatePrefab<ExplicitPathPanel>("ExplicitPathPrefab");
@@ -38,7 +38,7 @@ namespace FlowScope.Tests.PlayMode.UI
manager.RegisterLayer("popup", canvas, 120); manager.RegisterLayer("popup", canvas, 120);
var viewModel = new TestViewModel("first"); var viewModel = new TestViewModel("first");
var panel = await manager.OpenAsync<ExplicitPathPanel, TestViewModel>(viewModel, CancellationToken.None); var panel = manager.OpenAsync<ExplicitPathPanel, TestViewModel>(viewModel, CancellationToken.None).GetAwaiter().GetResult();
Assert.That(resources.LoadedKeys, Is.EqualTo(new[] { "Custom/Explicit" })); Assert.That(resources.LoadedKeys, Is.EqualTo(new[] { "Custom/Explicit" }));
Assert.That(panel.transform.parent, Is.EqualTo(canvas.transform)); Assert.That(panel.transform.parent, Is.EqualTo(canvas.transform));
@@ -49,7 +49,7 @@ namespace FlowScope.Tests.PlayMode.UI
} }
[Test] [Test]
public async Task OpenAsync_WhenPathIsMissing_UsesPanelNameConvention() public void OpenAsync_WhenPathIsMissing_UsesPanelNameConvention()
{ {
var canvas = CreateCanvas("hud"); var canvas = CreateCanvas("hud");
var prefab = CreatePrefab<MainHudPanel>("MainHudPrefab"); var prefab = CreatePrefab<MainHudPanel>("MainHudPrefab");
@@ -58,13 +58,13 @@ namespace FlowScope.Tests.PlayMode.UI
var manager = new UIManager(resources); var manager = new UIManager(resources);
manager.RegisterLayer("hud", canvas, 10); manager.RegisterLayer("hud", canvas, 10);
await manager.OpenAsync<MainHudPanel, TestViewModel>(new TestViewModel("hud"), CancellationToken.None); manager.OpenAsync<MainHudPanel, TestViewModel>(new TestViewModel("hud"), CancellationToken.None).GetAwaiter().GetResult();
Assert.That(resources.LoadedKeys, Is.EqualTo(new[] { "UI/MainHud/Prefab" })); Assert.That(resources.LoadedKeys, Is.EqualTo(new[] { "UI/MainHud/Prefab" }));
} }
[Test] [Test]
public async Task Close_WhenPanelIsNotLayerTop_ThrowsInvalidOperationException() public void Close_WhenPanelIsNotLayerTop_ThrowsInvalidOperationException()
{ {
var canvas = CreateCanvas("popup"); var canvas = CreateCanvas("popup");
var resources = new FakeResourceService(); var resources = new FakeResourceService();
@@ -72,8 +72,8 @@ namespace FlowScope.Tests.PlayMode.UI
resources.Register("UI/Second/Prefab", CreatePrefab<SecondPanel>("SecondPrefab")); resources.Register("UI/Second/Prefab", CreatePrefab<SecondPanel>("SecondPrefab"));
var manager = new UIManager(resources); var manager = new UIManager(resources);
manager.RegisterLayer("popup", canvas, 0); manager.RegisterLayer("popup", canvas, 0);
await manager.OpenAsync<ExplicitPathPanel, TestViewModel>(new TestViewModel("first"), CancellationToken.None); manager.OpenAsync<ExplicitPathPanel, TestViewModel>(new TestViewModel("first"), CancellationToken.None).GetAwaiter().GetResult();
await manager.OpenAsync<SecondPanel, TestViewModel>(new TestViewModel("second"), CancellationToken.None); manager.OpenAsync<SecondPanel, TestViewModel>(new TestViewModel("second"), CancellationToken.None).GetAwaiter().GetResult();
Assert.Throws<InvalidOperationException>(() => manager.Close<ExplicitPathPanel>()); Assert.Throws<InvalidOperationException>(() => manager.Close<ExplicitPathPanel>());
Assert.That(manager.IsOpen<ExplicitPathPanel>(), Is.True); Assert.That(manager.IsOpen<ExplicitPathPanel>(), Is.True);
@@ -81,7 +81,7 @@ namespace FlowScope.Tests.PlayMode.UI
} }
[Test] [Test]
public async Task Close_WithDestroyStrategy_UnbindsDestroysInstanceAndDisposesHandle() public void Close_WithDestroyStrategy_UnbindsDestroysInstanceAndDisposesHandle()
{ {
var canvas = CreateCanvas("popup"); var canvas = CreateCanvas("popup");
var prefab = CreatePrefab<ExplicitPathPanel>("ExplicitPathPrefab"); var prefab = CreatePrefab<ExplicitPathPanel>("ExplicitPathPrefab");
@@ -89,7 +89,7 @@ namespace FlowScope.Tests.PlayMode.UI
resources.Register("Custom/Explicit", prefab); resources.Register("Custom/Explicit", prefab);
var manager = new UIManager(resources); var manager = new UIManager(resources);
manager.RegisterLayer("popup", canvas, 0, PanelStrategy.Destroy); manager.RegisterLayer("popup", canvas, 0, PanelStrategy.Destroy);
var panel = await manager.OpenAsync<ExplicitPathPanel, TestViewModel>(new TestViewModel("first"), CancellationToken.None); var panel = manager.OpenAsync<ExplicitPathPanel, TestViewModel>(new TestViewModel("first"), CancellationToken.None).GetAwaiter().GetResult();
var handle = resources.Handles[0]; var handle = resources.Handles[0];
manager.Close<ExplicitPathPanel>(); manager.Close<ExplicitPathPanel>();
@@ -101,7 +101,7 @@ namespace FlowScope.Tests.PlayMode.UI
} }
[Test] [Test]
public async Task OpenAsync_WithCacheStrategy_ReusesHiddenInstanceAndBindsAgain() public void OpenAsync_WithCacheStrategy_ReusesHiddenInstanceAndBindsAgain()
{ {
var canvas = CreateCanvas("dialog"); var canvas = CreateCanvas("dialog");
var prefab = CreatePrefab<CachedPanel>("CachedPrefab"); var prefab = CreatePrefab<CachedPanel>("CachedPrefab");
@@ -112,9 +112,9 @@ namespace FlowScope.Tests.PlayMode.UI
var firstViewModel = new TestViewModel("first"); var firstViewModel = new TestViewModel("first");
var secondViewModel = new TestViewModel("second"); var secondViewModel = new TestViewModel("second");
var first = await manager.OpenAsync<CachedPanel, TestViewModel>(firstViewModel, CancellationToken.None); var first = manager.OpenAsync<CachedPanel, TestViewModel>(firstViewModel, CancellationToken.None).GetAwaiter().GetResult();
manager.Close<CachedPanel>(); manager.Close<CachedPanel>();
var second = await manager.OpenAsync<CachedPanel, TestViewModel>(secondViewModel, CancellationToken.None); var second = manager.OpenAsync<CachedPanel, TestViewModel>(secondViewModel, CancellationToken.None).GetAwaiter().GetResult();
Assert.That(second, Is.SameAs(first)); Assert.That(second, Is.SameAs(first));
Assert.That(second.gameObject.activeSelf, Is.True); Assert.That(second.gameObject.activeSelf, Is.True);
@@ -125,7 +125,7 @@ namespace FlowScope.Tests.PlayMode.UI
} }
[Test] [Test]
public async Task CloseLayer_OnlyClosesRequestedLayer() public void CloseLayer_OnlyClosesRequestedLayer()
{ {
var popupCanvas = CreateCanvas("popup"); var popupCanvas = CreateCanvas("popup");
var hudCanvas = CreateCanvas("hud"); var hudCanvas = CreateCanvas("hud");
@@ -135,8 +135,8 @@ namespace FlowScope.Tests.PlayMode.UI
var manager = new UIManager(resources); var manager = new UIManager(resources);
manager.RegisterLayer("popup", popupCanvas, 0); manager.RegisterLayer("popup", popupCanvas, 0);
manager.RegisterLayer("hud", hudCanvas, 0); manager.RegisterLayer("hud", hudCanvas, 0);
await manager.OpenAsync<ExplicitPathPanel, TestViewModel>(new TestViewModel("popup"), CancellationToken.None); manager.OpenAsync<ExplicitPathPanel, TestViewModel>(new TestViewModel("popup"), CancellationToken.None).GetAwaiter().GetResult();
await manager.OpenAsync<MainHudPanel, TestViewModel>(new TestViewModel("hud"), CancellationToken.None); manager.OpenAsync<MainHudPanel, TestViewModel>(new TestViewModel("hud"), CancellationToken.None).GetAwaiter().GetResult();
manager.CloseLayer("popup"); manager.CloseLayer("popup");
@@ -145,7 +145,7 @@ namespace FlowScope.Tests.PlayMode.UI
} }
[Test] [Test]
public async Task OpenAsync_WhenBindThrows_DisposesHandleAndDestroysCreatedInstance() public void OpenAsync_WhenBindThrows_DisposesHandleAndDestroysCreatedInstance()
{ {
var canvas = CreateCanvas("popup"); var canvas = CreateCanvas("popup");
var prefab = CreatePrefab<ThrowingBindPanel>("ThrowingPrefab"); var prefab = CreatePrefab<ThrowingBindPanel>("ThrowingPrefab");
@@ -154,7 +154,7 @@ namespace FlowScope.Tests.PlayMode.UI
var manager = new UIManager(resources); var manager = new UIManager(resources);
manager.RegisterLayer("popup", canvas, 0); manager.RegisterLayer("popup", canvas, 0);
await ThrowsAsync<InvalidOperationException>( ThrowsAsync<InvalidOperationException>(
() => manager.OpenAsync<ThrowingBindPanel, TestViewModel>(new TestViewModel("boom"), CancellationToken.None)); () => manager.OpenAsync<ThrowingBindPanel, TestViewModel>(new TestViewModel("boom"), CancellationToken.None));
Assert.That(resources.Handles[0].IsDisposed, Is.True); Assert.That(resources.Handles[0].IsDisposed, Is.True);
@@ -169,12 +169,12 @@ namespace FlowScope.Tests.PlayMode.UI
return gameObject.AddComponent<Canvas>(); return gameObject.AddComponent<Canvas>();
} }
private static async Task<TException> ThrowsAsync<TException>(Func<Task> action) private static TException ThrowsAsync<TException>(Func<Task> action)
where TException : Exception where TException : Exception
{ {
try try
{ {
await action(); action().GetAwaiter().GetResult();
} }
catch (TException exception) catch (TException exception)
{ {

View File

@@ -201,6 +201,13 @@
}, },
"url": "https://unitynuget-registry.openupm.com" "url": "https://unitynuget-registry.openupm.com"
}, },
"org.nuget.system.numerics.vectors": {
"version": "4.4.0",
"depth": 2,
"source": "registry",
"dependencies": {},
"url": "https://unitynuget-registry.openupm.com"
},
"org.nuget.system.runtime.compilerservices.unsafe": { "org.nuget.system.runtime.compilerservices.unsafe": {
"version": "6.0.0", "version": "6.0.0",
"depth": 1, "depth": 1,