修复 PlayMode 测试主线程阻塞
This commit is contained in:
@@ -1,15 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FlowScope.Resources;
|
using FlowScope.Resources;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
namespace FlowScope.Tests.PlayMode.Resources
|
namespace FlowScope.Tests.PlayMode.Resources
|
||||||
{
|
{
|
||||||
public sealed class AddressablesResourceServiceTests
|
public sealed class AddressablesResourceServiceTests
|
||||||
{
|
{
|
||||||
[Test]
|
[UnityTest]
|
||||||
public void LoadAsync_WhenSameKeyLoadsConcurrently_SharesOneBackendLoad()
|
public IEnumerator LoadAsync_WhenSameKeyLoadsConcurrently_SharesOneBackendLoad()
|
||||||
{
|
{
|
||||||
var backendLoads = 0;
|
var backendLoads = 0;
|
||||||
var releaseCount = 0;
|
var releaseCount = 0;
|
||||||
@@ -26,8 +28,10 @@ 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 = first.GetAwaiter().GetResult();
|
IResourceHandle<TestAsset> firstHandle = null;
|
||||||
var secondHandle = second.GetAwaiter().GetResult();
|
IResourceHandle<TestAsset> secondHandle = null;
|
||||||
|
yield return AwaitTask(first, handle => firstHandle = handle);
|
||||||
|
yield return AwaitTask(second, handle => secondHandle = handle);
|
||||||
|
|
||||||
Assert.AreEqual(1, backendLoads);
|
Assert.AreEqual(1, backendLoads);
|
||||||
Assert.AreSame(firstHandle.Asset, secondHandle.Asset);
|
Assert.AreSame(firstHandle.Asset, secondHandle.Asset);
|
||||||
@@ -38,34 +42,58 @@ namespace FlowScope.Tests.PlayMode.Resources
|
|||||||
Assert.AreEqual(1, releaseCount);
|
Assert.AreEqual(1, releaseCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[UnityTest]
|
||||||
public void LoadAsync_WhenBackendFails_IncludesKeyAndBackend()
|
public IEnumerator LoadAsync_WhenBackendFails_IncludesKeyAndBackend()
|
||||||
{
|
{
|
||||||
var service = new AddressablesResourceService(
|
var service = new AddressablesResourceService(
|
||||||
(_, _, _) => throw new InvalidOperationException("missing"),
|
(_, _, _) => throw new InvalidOperationException("missing"),
|
||||||
(_, _) => { });
|
(_, _) => { });
|
||||||
|
|
||||||
var exception = ThrowsAsync<InvalidOperationException>(
|
InvalidOperationException exception = null;
|
||||||
() => service.LoadAsync<TestAsset>("missing-key", CancellationToken.None));
|
yield return ThrowsAsync<InvalidOperationException>(
|
||||||
|
() => service.LoadAsync<TestAsset>("missing-key", CancellationToken.None),
|
||||||
|
caught => exception = caught);
|
||||||
|
|
||||||
StringAssert.Contains("missing-key", exception.Message);
|
StringAssert.Contains("missing-key", exception.Message);
|
||||||
StringAssert.Contains("Addressables", exception.Message);
|
StringAssert.Contains("Addressables", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TException ThrowsAsync<TException>(Func<Task> action)
|
private static IEnumerator ThrowsAsync<TException>(Func<Task> action, Action<TException> onCaught)
|
||||||
where TException : Exception
|
where TException : Exception
|
||||||
{
|
{
|
||||||
try
|
var task = action();
|
||||||
|
while (!task.IsCompleted)
|
||||||
{
|
{
|
||||||
action().GetAwaiter().GetResult();
|
yield return null;
|
||||||
}
|
}
|
||||||
catch (TException exception)
|
|
||||||
|
if (task.IsFaulted && task.Exception?.GetBaseException() is TException exception)
|
||||||
{
|
{
|
||||||
return exception;
|
onCaught(exception);
|
||||||
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.Fail($"Expected {typeof(TException).Name}.");
|
Assert.Fail($"Expected {typeof(TException).Name}.");
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
private static IEnumerator AwaitTask<T>(Task<T> task, Action<T> onCompleted)
|
||||||
|
{
|
||||||
|
while (!task.IsCompleted)
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.IsFaulted)
|
||||||
|
{
|
||||||
|
throw task.Exception.GetBaseException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.IsCanceled)
|
||||||
|
{
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCompleted(task.Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class TestAsset
|
private sealed class TestAsset
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FlowScope.Samples.MainMenuP0;
|
using FlowScope.Samples.MainMenuP0;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace FlowScope.Tests.PlayMode.Samples
|
namespace FlowScope.Tests.PlayMode.Samples
|
||||||
{
|
{
|
||||||
@@ -20,8 +24,8 @@ namespace FlowScope.Tests.PlayMode.Samples
|
|||||||
Assert.AreEqual(1, data.Gold.Value);
|
Assert.AreEqual(1, data.Gold.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[UnityTest]
|
||||||
public void Bootstrap_CanConstructAndShutdownWithoutSceneAsset()
|
public IEnumerator 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,10 +40,28 @@ namespace FlowScope.Tests.PlayMode.Samples
|
|||||||
panel.Configure(label, button);
|
panel.Configure(label, button);
|
||||||
|
|
||||||
var bootstrap = root.AddComponent<GameBootstrap>();
|
var bootstrap = root.AddComponent<GameBootstrap>();
|
||||||
bootstrap.ShutdownAsync(CancellationToken.None).GetAwaiter().GetResult();
|
yield return AwaitTask(bootstrap.ShutdownAsync(CancellationToken.None));
|
||||||
|
|
||||||
Object.DestroyImmediate(panelObject);
|
Object.DestroyImmediate(panelObject);
|
||||||
Object.DestroyImmediate(root);
|
Object.DestroyImmediate(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IEnumerator AwaitTask(Task task)
|
||||||
|
{
|
||||||
|
while (!task.IsCompleted)
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.IsFaulted)
|
||||||
|
{
|
||||||
|
throw task.Exception.GetBaseException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.IsCanceled)
|
||||||
|
{
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -6,6 +7,7 @@ using FlowScope.Resources;
|
|||||||
using FlowScope.UI;
|
using FlowScope.UI;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
namespace FlowScope.Tests.PlayMode.UI
|
namespace FlowScope.Tests.PlayMode.UI
|
||||||
{
|
{
|
||||||
@@ -27,8 +29,8 @@ namespace FlowScope.Tests.PlayMode.UI
|
|||||||
_objects.Clear();
|
_objects.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[UnityTest]
|
||||||
public void OpenAsync_UsesAttributePathAndMountsPanelToRegisteredLayer()
|
public IEnumerator OpenAsync_UsesAttributePathAndMountsPanelToRegisteredLayer()
|
||||||
{
|
{
|
||||||
var canvas = CreateCanvas("popup");
|
var canvas = CreateCanvas("popup");
|
||||||
var prefab = CreatePrefab<ExplicitPathPanel>("ExplicitPathPrefab");
|
var prefab = CreatePrefab<ExplicitPathPanel>("ExplicitPathPrefab");
|
||||||
@@ -38,7 +40,10 @@ 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 = manager.OpenAsync<ExplicitPathPanel, TestViewModel>(viewModel, CancellationToken.None).GetAwaiter().GetResult();
|
ExplicitPathPanel panel = null;
|
||||||
|
yield return AwaitTask(
|
||||||
|
manager.OpenAsync<ExplicitPathPanel, TestViewModel>(viewModel, CancellationToken.None),
|
||||||
|
result => panel = result);
|
||||||
|
|
||||||
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));
|
||||||
@@ -48,8 +53,8 @@ namespace FlowScope.Tests.PlayMode.UI
|
|||||||
Assert.That(manager.IsOpen<ExplicitPathPanel>(), Is.True);
|
Assert.That(manager.IsOpen<ExplicitPathPanel>(), Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[UnityTest]
|
||||||
public void OpenAsync_WhenPathIsMissing_UsesPanelNameConvention()
|
public IEnumerator OpenAsync_WhenPathIsMissing_UsesPanelNameConvention()
|
||||||
{
|
{
|
||||||
var canvas = CreateCanvas("hud");
|
var canvas = CreateCanvas("hud");
|
||||||
var prefab = CreatePrefab<MainHudPanel>("MainHudPrefab");
|
var prefab = CreatePrefab<MainHudPanel>("MainHudPrefab");
|
||||||
@@ -58,13 +63,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);
|
||||||
|
|
||||||
manager.OpenAsync<MainHudPanel, TestViewModel>(new TestViewModel("hud"), CancellationToken.None).GetAwaiter().GetResult();
|
yield return AwaitTask(manager.OpenAsync<MainHudPanel, TestViewModel>(new TestViewModel("hud"), CancellationToken.None));
|
||||||
|
|
||||||
Assert.That(resources.LoadedKeys, Is.EqualTo(new[] { "UI/MainHud/Prefab" }));
|
Assert.That(resources.LoadedKeys, Is.EqualTo(new[] { "UI/MainHud/Prefab" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[UnityTest]
|
||||||
public void Close_WhenPanelIsNotLayerTop_ThrowsInvalidOperationException()
|
public IEnumerator Close_WhenPanelIsNotLayerTop_ThrowsInvalidOperationException()
|
||||||
{
|
{
|
||||||
var canvas = CreateCanvas("popup");
|
var canvas = CreateCanvas("popup");
|
||||||
var resources = new FakeResourceService();
|
var resources = new FakeResourceService();
|
||||||
@@ -72,16 +77,16 @@ 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);
|
||||||
manager.OpenAsync<ExplicitPathPanel, TestViewModel>(new TestViewModel("first"), CancellationToken.None).GetAwaiter().GetResult();
|
yield return AwaitTask(manager.OpenAsync<ExplicitPathPanel, TestViewModel>(new TestViewModel("first"), CancellationToken.None));
|
||||||
manager.OpenAsync<SecondPanel, TestViewModel>(new TestViewModel("second"), CancellationToken.None).GetAwaiter().GetResult();
|
yield return AwaitTask(manager.OpenAsync<SecondPanel, TestViewModel>(new TestViewModel("second"), CancellationToken.None));
|
||||||
|
|
||||||
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);
|
||||||
Assert.That(manager.IsOpen<SecondPanel>(), Is.True);
|
Assert.That(manager.IsOpen<SecondPanel>(), Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[UnityTest]
|
||||||
public void Close_WithDestroyStrategy_UnbindsDestroysInstanceAndDisposesHandle()
|
public IEnumerator Close_WithDestroyStrategy_UnbindsDestroysInstanceAndDisposesHandle()
|
||||||
{
|
{
|
||||||
var canvas = CreateCanvas("popup");
|
var canvas = CreateCanvas("popup");
|
||||||
var prefab = CreatePrefab<ExplicitPathPanel>("ExplicitPathPrefab");
|
var prefab = CreatePrefab<ExplicitPathPanel>("ExplicitPathPrefab");
|
||||||
@@ -89,7 +94,10 @@ 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 = manager.OpenAsync<ExplicitPathPanel, TestViewModel>(new TestViewModel("first"), CancellationToken.None).GetAwaiter().GetResult();
|
ExplicitPathPanel panel = null;
|
||||||
|
yield return AwaitTask(
|
||||||
|
manager.OpenAsync<ExplicitPathPanel, TestViewModel>(new TestViewModel("first"), CancellationToken.None),
|
||||||
|
result => panel = result);
|
||||||
var handle = resources.Handles[0];
|
var handle = resources.Handles[0];
|
||||||
|
|
||||||
manager.Close<ExplicitPathPanel>();
|
manager.Close<ExplicitPathPanel>();
|
||||||
@@ -100,8 +108,8 @@ namespace FlowScope.Tests.PlayMode.UI
|
|||||||
Assert.That(manager.IsOpen<ExplicitPathPanel>(), Is.False);
|
Assert.That(manager.IsOpen<ExplicitPathPanel>(), Is.False);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[UnityTest]
|
||||||
public void OpenAsync_WithCacheStrategy_ReusesHiddenInstanceAndBindsAgain()
|
public IEnumerator OpenAsync_WithCacheStrategy_ReusesHiddenInstanceAndBindsAgain()
|
||||||
{
|
{
|
||||||
var canvas = CreateCanvas("dialog");
|
var canvas = CreateCanvas("dialog");
|
||||||
var prefab = CreatePrefab<CachedPanel>("CachedPrefab");
|
var prefab = CreatePrefab<CachedPanel>("CachedPrefab");
|
||||||
@@ -112,9 +120,15 @@ 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 = manager.OpenAsync<CachedPanel, TestViewModel>(firstViewModel, CancellationToken.None).GetAwaiter().GetResult();
|
CachedPanel first = null;
|
||||||
|
yield return AwaitTask(
|
||||||
|
manager.OpenAsync<CachedPanel, TestViewModel>(firstViewModel, CancellationToken.None),
|
||||||
|
result => first = result);
|
||||||
manager.Close<CachedPanel>();
|
manager.Close<CachedPanel>();
|
||||||
var second = manager.OpenAsync<CachedPanel, TestViewModel>(secondViewModel, CancellationToken.None).GetAwaiter().GetResult();
|
CachedPanel second = null;
|
||||||
|
yield return AwaitTask(
|
||||||
|
manager.OpenAsync<CachedPanel, TestViewModel>(secondViewModel, CancellationToken.None),
|
||||||
|
result => second = result);
|
||||||
|
|
||||||
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);
|
||||||
@@ -124,8 +138,8 @@ namespace FlowScope.Tests.PlayMode.UI
|
|||||||
Assert.That(resources.Handles[0].IsDisposed, Is.False);
|
Assert.That(resources.Handles[0].IsDisposed, Is.False);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[UnityTest]
|
||||||
public void CloseLayer_OnlyClosesRequestedLayer()
|
public IEnumerator CloseLayer_OnlyClosesRequestedLayer()
|
||||||
{
|
{
|
||||||
var popupCanvas = CreateCanvas("popup");
|
var popupCanvas = CreateCanvas("popup");
|
||||||
var hudCanvas = CreateCanvas("hud");
|
var hudCanvas = CreateCanvas("hud");
|
||||||
@@ -135,8 +149,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);
|
||||||
manager.OpenAsync<ExplicitPathPanel, TestViewModel>(new TestViewModel("popup"), CancellationToken.None).GetAwaiter().GetResult();
|
yield return AwaitTask(manager.OpenAsync<ExplicitPathPanel, TestViewModel>(new TestViewModel("popup"), CancellationToken.None));
|
||||||
manager.OpenAsync<MainHudPanel, TestViewModel>(new TestViewModel("hud"), CancellationToken.None).GetAwaiter().GetResult();
|
yield return AwaitTask(manager.OpenAsync<MainHudPanel, TestViewModel>(new TestViewModel("hud"), CancellationToken.None));
|
||||||
|
|
||||||
manager.CloseLayer("popup");
|
manager.CloseLayer("popup");
|
||||||
|
|
||||||
@@ -144,8 +158,8 @@ namespace FlowScope.Tests.PlayMode.UI
|
|||||||
Assert.That(manager.IsOpen<MainHudPanel>(), Is.True);
|
Assert.That(manager.IsOpen<MainHudPanel>(), Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[UnityTest]
|
||||||
public void OpenAsync_WhenBindThrows_DisposesHandleAndDestroysCreatedInstance()
|
public IEnumerator OpenAsync_WhenBindThrows_DisposesHandleAndDestroysCreatedInstance()
|
||||||
{
|
{
|
||||||
var canvas = CreateCanvas("popup");
|
var canvas = CreateCanvas("popup");
|
||||||
var prefab = CreatePrefab<ThrowingBindPanel>("ThrowingPrefab");
|
var prefab = CreatePrefab<ThrowingBindPanel>("ThrowingPrefab");
|
||||||
@@ -154,7 +168,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);
|
||||||
|
|
||||||
ThrowsAsync<InvalidOperationException>(
|
yield return 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,20 +183,21 @@ namespace FlowScope.Tests.PlayMode.UI
|
|||||||
return gameObject.AddComponent<Canvas>();
|
return gameObject.AddComponent<Canvas>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TException ThrowsAsync<TException>(Func<Task> action)
|
private static IEnumerator ThrowsAsync<TException>(Func<Task> action)
|
||||||
where TException : Exception
|
where TException : Exception
|
||||||
{
|
{
|
||||||
try
|
var task = action();
|
||||||
|
while (!task.IsCompleted)
|
||||||
{
|
{
|
||||||
action().GetAwaiter().GetResult();
|
yield return null;
|
||||||
}
|
}
|
||||||
catch (TException exception)
|
|
||||||
|
if (task.IsFaulted && task.Exception?.GetBaseException() is TException)
|
||||||
{
|
{
|
||||||
return exception;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.Fail($"Expected {typeof(TException).Name}.");
|
Assert.Fail($"Expected {typeof(TException).Name}.");
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private GameObject CreatePrefab<TPanel>(string name)
|
private GameObject CreatePrefab<TPanel>(string name)
|
||||||
@@ -194,6 +209,44 @@ namespace FlowScope.Tests.PlayMode.UI
|
|||||||
return gameObject;
|
return gameObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IEnumerator AwaitTask(Task task)
|
||||||
|
{
|
||||||
|
while (!task.IsCompleted)
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.IsFaulted)
|
||||||
|
{
|
||||||
|
throw task.Exception.GetBaseException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.IsCanceled)
|
||||||
|
{
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerator AwaitTask<T>(Task<T> task, Action<T> onCompleted)
|
||||||
|
{
|
||||||
|
while (!task.IsCompleted)
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.IsFaulted)
|
||||||
|
{
|
||||||
|
throw task.Exception.GetBaseException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.IsCanceled)
|
||||||
|
{
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCompleted(task.Result);
|
||||||
|
}
|
||||||
|
|
||||||
private sealed class FakeResourceService : IResourceService
|
private sealed class FakeResourceService : IResourceService
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, GameObject> _assets = new();
|
private readonly Dictionary<string, GameObject> _assets = new();
|
||||||
|
|||||||
Reference in New Issue
Block a user