using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; using Sirenix.Utilities; using Test.Util; using UnityEditor; using UnityEngine; using VOID.Generic.Objects.Abstract; namespace Test.EditMode.Prefabs.Generic { public class AbstractObjectTest { private List _gameObjects = new(); [OneTimeSetUp] public void Setup() { AssetDatabase.FindAssets("t:GameObject").ForEach(gameObjectGuid => { var gameObjectPath = AssetDatabase.GUIDToAssetPath(gameObjectGuid); var gameObject = AssetDatabase.LoadAssetAtPath(gameObjectPath); var abstractObjects = gameObject.GetComponentsInChildren(); // If prefab have any AbstractObject or any its children anywhere - take it, we will test it if (abstractObjects.Length > 0) _gameObjects.Add(gameObject); }); } [OneTimeTearDown] public void Cleanup() { _gameObjects?.Clear(); _gameObjects = null; } [Test] [Obsolete("Obsolete", false)] public void IsPrefab() { _gameObjects.ForEach(gameObject => { var isPrefab = PrefabUtility.GetPrefabParent(gameObject) == null && PrefabUtility.GetPrefabObject(gameObject) != null; if (isPrefab) return; var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); Debug.LogError( $"{prefabPathHyperlink} is not prefab, instances of '{nameof(AbstractObject)}' should be placed only on main GameObject of prefab", gameObject); }); } [Test] public void OnlyOnePerPrefab() { _gameObjects.ForEach(gameObject => { var abstractObject = gameObject.GetComponentsInChildren(); if (abstractObject.Length == 1) return; var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); Debug.LogError($"Prefab: {prefabPathHyperlink}, prefab have attached more than one instance of '{nameof(AbstractObject)}'", gameObject); }); } [Test] public void OnlyInPrefabRoot() { _gameObjects.ForEach(gameObject => { var abstractObject = gameObject.GetComponent(); var insideAbstractObject = gameObject.GetComponentsInChildren().ToList(); insideAbstractObject.Remove(abstractObject); if (insideAbstractObject.Count == 0) return; var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); Debug.LogError($"Prefab: {prefabPathHyperlink}, any instance of '{nameof(AbstractObject)}' should be placed ONLY on main GameObject of prefab, not inside its children", abstractObject); }); } [Test] public void BasicData_DisplayName() { _gameObjects.ForEach(gameObject => { var abstractObject = gameObject.GetComponent(); if (!abstractObject) return; var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); var name = abstractObject.basicData.finalName; var trimName = name.Trim(); if (!name.Equals(trimName)) Debug.LogWarning( $"Prefab's display name trimmed is different (contain whitespaces at start or end): {prefabPathHyperlink}"); if (trimName.Length > 0) return; Debug.LogError($"Prefab's display name is empty: {prefabPathHyperlink}", abstractObject); }); } [Test] public void UnitData_Size() { _gameObjects.ForEach(gameObject => { var abstractObject = gameObject.GetComponent(); var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); if (abstractObject.basicData.height <= 0f) Debug.LogError($"{nameof(AbstractObject)}'s height is lesser or equal to zero: {prefabPathHyperlink}", abstractObject); if (abstractObject.basicData.radius <= 0f) Debug.LogWarning($"{nameof(AbstractObject)}'s width is lesser or equal to zero: {prefabPathHyperlink}", abstractObject); }); } [Test] public void BasicData_BasicResources() { _gameObjects.ForEach(gameObject => { var abstractObject = gameObject.GetComponent(); if (!abstractObject) return; var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); var health = abstractObject.basicData.currentResources.health; var baseHealth = abstractObject.basicData.baseMaxResources.health; if (baseHealth <= 0f) Debug.LogError($"Prefab's baseHealth cannot be 0 or lower: {prefabPathHyperlink}", abstractObject); if (health > baseHealth) Debug.LogError($"Prefab's current health is greater than baseMaxHealth: {prefabPathHyperlink}", abstractObject); }); } [Test] public void StatusManager_DuplicatedStatuses() { _gameObjects.ForEach(gameObject => { var abstractObject = gameObject.GetComponent(); if (!abstractObject) return; var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); var statuses = abstractObject.statusManager.GetStatuses().ToList(); if (statuses.Distinct().Count() != statuses.Count) Debug.LogError($"Prefab's '{nameof(AbstractObjectStatusManager)}' contain duplicated statuses: {prefabPathHyperlink}", abstractObject); }); } [Test] public void StatusManager_InvalidStatusCombination() { _gameObjects.ForEach(gameObject => { var abstractObject = gameObject.GetComponent(); if (!abstractObject) return; var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID()); var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath); var statuses = abstractObject.statusManager.GetStatuses().ToList(); statuses.ForEach(status => { statuses .Where(otherStatus => otherStatus != status) .Where(otherStatus => status.removes.Contains(otherStatus)) .ForEach(invalidStatus => Debug.LogError($"Invalid combination of '{status.displayName}' and '{invalidStatus.displayName}': {prefabPathHyperlink}", abstractObject)); }); }); } } }