Files
tiny_tackle_heroes/Assets/_Project/Tests/PlayMode/Defense25DStatusVisualPlayModeTests.cs
T
2026-09-27 21:08:05 +09:00

148 lines
7.4 KiB
C#

using System.Collections;
using System.Reflection;
using BumpCombat.Defense.Comparison;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using Object = UnityEngine.Object;
namespace BumpCombat.Tests
{
public sealed class Defense25DStatusVisualPlayModeTests
{
private GameObject enemyObject;
private GameObject actorObject;
private GameObject spriteObject;
private GameObject worldObject;
[UnityTearDown]
public IEnumerator TearDown()
{
if (worldObject != null) Object.Destroy(worldObject);
else
{
if (enemyObject != null) Object.Destroy(enemyObject);
if (actorObject != null) Object.Destroy(actorObject);
if (spriteObject != null) Object.Destroy(spriteObject);
}
yield return null;
}
[UnityTest]
public IEnumerator ActiveStatusesRenderExistingFramesAndClearWhenTheirTimersExpire()
{
const string ignitePath = "Artifacts/ThreeColor-v1/StatusEffects/Ignite-Warlock-v1";
Sprite[] importedFrames = Resources.LoadAll<Sprite>(ignitePath);
Texture2D igniteTexture = importedFrames.Length > 0
? importedFrames[0].texture : Resources.Load<Texture2D>(ignitePath);
Assert.That(igniteTexture, Is.Not.Null);
worldObject = new GameObject("Status visual world");
Defense25DComparison owner = worldObject.AddComponent<Defense25DComparison>();
SetBackingField(owner, "IsRunning", true);
SetBackingField(owner, "Paused", true);
spriteObject = new GameObject("Status visual source");
SpriteRenderer sourceRenderer = spriteObject.AddComponent<SpriteRenderer>();
actorObject = new GameObject("Status visual actor");
actorObject.transform.SetParent(worldObject.transform, false);
spriteObject.transform.SetParent(actorObject.transform, false);
spriteObject.transform.rotation = Quaternion.Euler(30f, 0f, 0f);
sourceRenderer.sortingOrder = 12;
sourceRenderer.flipX = true;
sourceRenderer.color = new Color(1f, 1f, 1f, .4f);
Defense25DActor actor = actorObject.AddComponent<Defense25DActor>();
SetBackingField(actor, "CurrentHealth", 10f);
Defense25DSprite actorVisual = actorObject.AddComponent<Defense25DSprite>();
SetPrivateField(actorVisual, "sprite", sourceRenderer);
actorVisual.enabled = false;
SetBackingField(actor, "Visual", actorVisual);
enemyObject = new GameObject("Status visual enemy");
enemyObject.transform.SetParent(worldObject.transform, false);
Defense25DEnemy enemy = enemyObject.AddComponent<Defense25DEnemy>();
SetBackingField(enemy, "Actor", actor);
SetPrivateField(enemy, "world", owner);
SetPrivateField(enemy, "igniteRemaining", .5f);
SetPrivateField(enemy, "shockRemaining", .5f);
SetPrivateField(enemy, "stunUntil", .5f);
SetPrivateField(enemy, "stunVisualRevision", 1);
Defense25DStatusVisual statusVisual = enemyObject.AddComponent<Defense25DStatusVisual>();
statusVisual.Bind(enemy);
statusVisual.SendMessage("LateUpdate");
Transform igniteVisual = spriteObject.transform.Find("Ignite Status Visual");
Transform shockVisual = spriteObject.transform.Find("Shock Status Visual");
Assert.That(igniteVisual, Is.Not.Null);
Assert.That(shockVisual, Is.Not.Null);
Assert.That(enemy.IsIgnited, Is.True);
Assert.That(enemy.IsShocked, Is.True);
Assert.That(GetPrivateField(GetPrivateField(statusVisual, "ignite"), "FrameElapsed"),
Is.EqualTo(0f));
Assert.That(GetPrivateField(GetPrivateField(statusVisual, "shock"), "FrameElapsed"),
Is.EqualTo(0f));
Assert.That(GetPrivateField(statusVisual, "stunElapsed"), Is.EqualTo(0f));
Transform stunMarker = actorObject.transform.Find("Stun Runes");
Assert.That(stunMarker, Is.Not.Null);
SpriteRenderer stunRenderer = stunMarker.GetComponent<SpriteRenderer>();
Assert.That(stunRenderer.sharedMaterial, Is.SameAs(sourceRenderer.sharedMaterial));
Assert.That(stunRenderer.color.a, Is.EqualTo(sourceRenderer.color.a).Within(.001f));
Assert.That(stunMarker.localPosition.z, Is.GreaterThan(0f));
SpriteRenderer igniteRenderer = igniteVisual.GetComponent<SpriteRenderer>();
Assert.That(igniteRenderer.sprite, Is.Not.Null);
Assert.That(igniteRenderer.sprite.texture, Is.SameAs(igniteTexture));
Assert.That(igniteRenderer.sortingOrder, Is.EqualTo(sourceRenderer.sortingOrder + 1));
Assert.That(igniteRenderer.flipX, Is.EqualTo(sourceRenderer.flipX));
Assert.That(igniteRenderer.color.a, Is.EqualTo(sourceRenderer.color.a).Within(.001f));
Assert.That(igniteVisual.localPosition.y,
Is.EqualTo(Defense25DStatusVisual.StatusVisualAnchorOffsetY).Within(.001f));
SetPrivateField(enemy, "igniteRemaining", 0f);
SetPrivateField(enemy, "shockRemaining", 0f);
statusVisual.SendMessage("LateUpdate");
Assert.That(enemy.IsIgnited, Is.False);
Assert.That(enemy.IsShocked, Is.False);
Assert.That(GetPrivateField(GetPrivateField(statusVisual, "ignite"), "Root"), Is.Null);
Assert.That(GetPrivateField(GetPrivateField(statusVisual, "shock"), "Root"), Is.Null);
SetPrivateField(enemy, "igniteRemaining", .5f);
SetBackingField(owner, "Paused", false);
statusVisual.SendMessage("LateUpdate");
Assert.That(GetPrivateField(GetPrivateField(statusVisual, "ignite"), "Root"), Is.Not.Null);
SetBackingField(owner, "IsRunning", false);
statusVisual.SendMessage("LateUpdate");
Assert.That(GetPrivateField(GetPrivateField(statusVisual, "ignite"), "Root"), Is.Null);
SetBackingField(owner, "IsRunning", true);
statusVisual.SendMessage("LateUpdate");
Assert.That(GetPrivateField(GetPrivateField(statusVisual, "ignite"), "Root"), Is.Not.Null);
owner.enabled = false;
statusVisual.SendMessage("LateUpdate");
Assert.That(GetPrivateField(GetPrivateField(statusVisual, "ignite"), "Root"), Is.Null);
yield return null;
}
private static void SetBackingField(object target, string propertyName, object value) =>
SetPrivateField(target, $"<{propertyName}>k__BackingField", value);
private static void SetPrivateField(object target, string fieldName, object value)
{
FieldInfo field = target.GetType().GetField(
fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
Assert.That(field, Is.Not.Null, $"Missing test field {fieldName}");
field.SetValue(target, value);
}
private static object GetPrivateField(object target, string fieldName)
{
FieldInfo field = target.GetType().GetField(
fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
Assert.That(field, Is.Not.Null, $"Missing test field {fieldName}");
return field.GetValue(target);
}
}
}