From c6ca0be06a00dee6ee3827e08337e2d9529f08ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kub=C5=9B?= Date: Wed, 10 Jun 2026 23:30:30 +0200 Subject: [PATCH 1/2] refactor(ships): extract TestHelpers to different namespaces, remove reflection, add proper ship factories --- Assets/Scripts/Core/Ship/CrewMember.cs | 8 + Assets/Scripts/E2E/E2ETestBase.cs | 3 +- Assets/Scripts/ShipFactory/ShipModuleSO.cs | 14 + .../CalculatorTests.cs | 16 +- Assets/Scripts/Ships/Modules/Cannon.cs | 1 + Assets/Scripts/Ships/Tests/CrewModuleTests.cs | 21 +- .../Ships/Tests/ModuleConnectionTests.cs | 27 +- .../Tests/ModuleDestructionThresholdTests.cs | 35 +-- .../Ships/Tests/ModuleJointLifecycleTests.cs | 37 +-- .../Tests/ShipControlAllocatorThrustTests.cs | 116 +++----- .../Ships/Tests/ShipCrewAssignmentTests.cs | 62 ++--- .../Ships/Tests/ShipDestroyAllModulesTests.cs | 41 +-- .../Ships/Tests/ShipDestructionJunkTests.cs | 29 +- .../Ships/Tests/ShipDisconnectionTests.cs | 255 +++++------------- .../Ships/Tests/ShipGameplayMovementTests.cs | 18 +- .../Ships/Tests/ShipSnapshotServiceTests.cs | 175 ++---------- .../Ships/Tests/TestHelpers/Factories.meta | 3 + .../{ => Factories}/ModuleFactory.cs | 16 +- .../{ => Factories}/ModuleFactory.cs.meta | 0 .../TestHelpers/Factories/ShipTestBuilder.cs | 235 ++++++++++++++++ .../Factories/ShipTestBuilder.cs.meta | 2 + .../TestHelpers/Factories/ShipTestFactory.cs | 86 ++++++ .../Factories/ShipTestFactory.cs.meta | 2 + .../Ships/Tests/TestHelpers/Fixtures.meta | 3 + .../{ => Fixtures}/ShipTestBase.cs | 2 +- .../{ => Fixtures}/ShipTestBase.cs.meta | 0 .../{ => Fixtures}/TestContainerFactory.cs | 3 +- .../TestContainerFactory.cs.meta | 0 .../Tests/TestHelpers/{ => Fixtures}/Utils.cs | 2 +- .../TestHelpers/{ => Fixtures}/Utils.cs.meta | 0 .../Ships/Tests/TestHelpers/Mocks.meta | 3 + .../TestHelpers/Mocks/TestContentCatalog.cs | 46 ++++ .../{ => Mocks}/TestContentCatalog.cs.meta | 0 .../{ => Mocks}/TestDebrisSpawner.cs | 2 +- .../{ => Mocks}/TestDebrisSpawner.cs.meta | 0 .../TestHelpers/{ => Mocks}/TestMapInfo.cs | 2 +- .../{ => Mocks}/TestMapInfo.cs.meta | 0 .../TestHelpers/Mocks/TestModuleCatalog.cs | 21 ++ .../{ => Mocks}/TestModuleCatalog.cs.meta | 0 .../Ships/Tests/TestHelpers/Modules.meta | 3 + .../TestHelpers/{ => Modules}/TestModule.cs | 2 +- .../{ => Modules}/TestModule.cs.meta | 0 .../{ => Modules}/TestPowerModule.cs | 2 +- .../{ => Modules}/TestPowerModule.cs.meta | 0 .../Ships/Tests/TestHelpers/Proxies.meta | 3 + .../{ => Proxies}/MovableShipTestProxy.cs | 4 +- .../MovableShipTestProxy.cs.meta | 0 .../{ => Proxies}/ShipTestProxy.cs | 4 +- .../{ => Proxies}/ShipTestProxy.cs.meta | 0 .../SmallMovableShipTestFactory.cs | 44 --- .../SmallMovableShipTestFactory.cs.meta | 2 - .../Tests/TestHelpers/TestContentCatalog.cs | 32 --- .../Tests/TestHelpers/TestModuleCatalog.cs | 14 - .../UI/MainGame/PauseMenuController.cs | 2 +- 54 files changed, 670 insertions(+), 728 deletions(-) create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Factories.meta rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Factories}/ModuleFactory.cs (88%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Factories}/ModuleFactory.cs.meta (100%) create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs.meta create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs.meta create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Fixtures.meta rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Fixtures}/ShipTestBase.cs (96%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Fixtures}/ShipTestBase.cs.meta (100%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Fixtures}/TestContainerFactory.cs (95%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Fixtures}/TestContainerFactory.cs.meta (100%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Fixtures}/Utils.cs (91%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Fixtures}/Utils.cs.meta (100%) create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Mocks.meta create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestContentCatalog.cs rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Mocks}/TestContentCatalog.cs.meta (100%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Mocks}/TestDebrisSpawner.cs (96%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Mocks}/TestDebrisSpawner.cs.meta (100%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Mocks}/TestMapInfo.cs (86%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Mocks}/TestMapInfo.cs.meta (100%) create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestModuleCatalog.cs rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Mocks}/TestModuleCatalog.cs.meta (100%) create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Modules.meta rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Modules}/TestModule.cs (90%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Modules}/TestModule.cs.meta (100%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Modules}/TestPowerModule.cs (88%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Modules}/TestPowerModule.cs.meta (100%) create mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/Proxies.meta rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Proxies}/MovableShipTestProxy.cs (94%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Proxies}/MovableShipTestProxy.cs.meta (100%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Proxies}/ShipTestProxy.cs (75%) rename Assets/Scripts/Ships/Tests/TestHelpers/{ => Proxies}/ShipTestProxy.cs.meta (100%) delete mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/SmallMovableShipTestFactory.cs delete mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/SmallMovableShipTestFactory.cs.meta delete mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/TestContentCatalog.cs delete mode 100644 Assets/Scripts/Ships/Tests/TestHelpers/TestModuleCatalog.cs diff --git a/Assets/Scripts/Core/Ship/CrewMember.cs b/Assets/Scripts/Core/Ship/CrewMember.cs index b30106b4..69b761f7 100644 --- a/Assets/Scripts/Core/Ship/CrewMember.cs +++ b/Assets/Scripts/Core/Ship/CrewMember.cs @@ -1,8 +1,11 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using LMPro.DataStructures; using UnityEngine; +[assembly: InternalsVisibleTo("Ships.Tests")] + namespace Core.Ship { [Serializable] @@ -49,5 +52,10 @@ public void Kill() IsAlive = false; OnDied?.Invoke(this); } + +#if UNITY_INCLUDE_TESTS + internal int OnDiedSubscriberCountForTesting => + OnDied?.GetInvocationList().Length ?? 0; +#endif } } \ No newline at end of file diff --git a/Assets/Scripts/E2E/E2ETestBase.cs b/Assets/Scripts/E2E/E2ETestBase.cs index 7e08d521..676da165 100644 --- a/Assets/Scripts/E2E/E2ETestBase.cs +++ b/Assets/Scripts/E2E/E2ETestBase.cs @@ -15,7 +15,8 @@ using Ships.ModuleConnection; using Ships.Modules; using Ships.Systems.Sensing; -using Ships.Tests.TestHelpers; +using Ships.Tests.TestHelpers.Factories; +using Ships.Tests.TestHelpers.Mocks; using UnityEngine; using Zenject; using ZLinq; diff --git a/Assets/Scripts/ShipFactory/ShipModuleSO.cs b/Assets/Scripts/ShipFactory/ShipModuleSO.cs index c30edbd2..aaf7e5f2 100644 --- a/Assets/Scripts/ShipFactory/ShipModuleSO.cs +++ b/Assets/Scripts/ShipFactory/ShipModuleSO.cs @@ -1,5 +1,8 @@ +using System.Runtime.CompilerServices; using UnityEngine; +[assembly: InternalsVisibleTo("ShipFactory.Tests")] + namespace ShipFactory { [CreateAssetMenu(fileName = "ShipModuleSO", menuName = "Ship Factory/ShipModuleSO")] @@ -16,5 +19,16 @@ public class ShipModuleSO : ScriptableObject public Vector2Int Dimensions => dimensions; public string Name => partName; public string Description => description; + +#if UNITY_INCLUDE_TESTS + internal void ConfigureForTesting(string newPartName, string moduleDescription, Vector2Int moduleDimensions, + GameObject modulePrefab) + { + partName = newPartName; + description = moduleDescription; + dimensions = moduleDimensions; + prefab = modulePrefab; + } +#endif } } \ No newline at end of file diff --git a/Assets/Scripts/ShipFactory/Tests/LegalPositionCalculator/CalculatorTests.cs b/Assets/Scripts/ShipFactory/Tests/LegalPositionCalculator/CalculatorTests.cs index c3df6b62..37094fcf 100644 --- a/Assets/Scripts/ShipFactory/Tests/LegalPositionCalculator/CalculatorTests.cs +++ b/Assets/Scripts/ShipFactory/Tests/LegalPositionCalculator/CalculatorTests.cs @@ -1,6 +1,4 @@ -using System; using System.Collections.Generic; -using System.Reflection; using Core.Ship; using NSubstitute; using NUnit.Framework; @@ -81,25 +79,13 @@ private ShipModuleSOInstanceBundle CreateBundle(string name, ModuleType moduleTy var moduleSO = ScriptableObject.CreateInstance(); _createdObjects.Add(moduleSO); - SetPrivateField(moduleSO, "partName", name); - SetPrivateField(moduleSO, "description", $"{name} description"); - SetPrivateField(moduleSO, "dimensions", dimensions); - SetPrivateField(moduleSO, "prefab", go); + moduleSO.ConfigureForTesting(name, $"{name} description", dimensions, go); var module = Substitute.For(); module.Type.Returns(moduleType); return new ShipModuleSOInstanceBundle(go, moduleSO, module); } - - private static void SetPrivateField(object target, string fieldName, object value) - { - var field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); - if (field == null) - throw new InvalidOperationException($"Field '{fieldName}' not found on {target.GetType().Name}."); - - field.SetValue(target, value); - } } } diff --git a/Assets/Scripts/Ships/Modules/Cannon.cs b/Assets/Scripts/Ships/Modules/Cannon.cs index 75e6e3c2..d0e9d0b8 100644 --- a/Assets/Scripts/Ships/Modules/Cannon.cs +++ b/Assets/Scripts/Ships/Modules/Cannon.cs @@ -8,6 +8,7 @@ using Zenject; [assembly: InternalsVisibleTo("E2E")] +[assembly: InternalsVisibleTo("Ships.Tests")] namespace Ships.Modules { diff --git a/Assets/Scripts/Ships/Tests/CrewModuleTests.cs b/Assets/Scripts/Ships/Tests/CrewModuleTests.cs index 41926cf3..b822863e 100644 --- a/Assets/Scripts/Ships/Tests/CrewModuleTests.cs +++ b/Assets/Scripts/Ships/Tests/CrewModuleTests.cs @@ -1,11 +1,12 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Reflection; using Core.Ship; using NSubstitute; using NUnit.Framework; -using Ships.Tests.TestHelpers; +using Ships.Tests.TestHelpers.Factories; +using Ships.Tests.TestHelpers.Fixtures; +using Ships.Tests.TestHelpers.Modules; using UnityEngine; using UnityEngine.TestTools; using Object = UnityEngine.Object; @@ -37,12 +38,6 @@ private TestModule CreateStandaloneModule( return module; } - private static Delegate GetOnDiedDelegate(CrewMember crew) - { - var field = typeof(CrewMember).GetField("OnDied", BindingFlags.Instance | BindingFlags.NonPublic); - return field?.GetValue(crew) as Delegate; - } - [Test] public void AssignCrew_ReturnsTrue() { @@ -536,7 +531,7 @@ public void KillAllCrew_DoesNotLeakOnDiedSubscription() module.KillAllCrew(); - Assert.IsNull(GetOnDiedDelegate(crew), + Assert.AreEqual(0, crew.OnDiedSubscriberCountForTesting, "Module should have unsubscribed from OnDied after KillAllCrew"); } @@ -577,7 +572,7 @@ public void RemoveCrew_DoesNotLeakOnDiedSubscription() module.RemoveCrew(crew); - Assert.IsNull(GetOnDiedDelegate(crew), + Assert.AreEqual(0, crew.OnDiedSubscriberCountForTesting, "Module should have unsubscribed from OnDied after RemoveCrew"); } @@ -594,9 +589,9 @@ public void KillRandomCrew_DoesNotLeakOnDiedSubscription() module.KillRandomCrew(3); - Assert.IsNull(GetOnDiedDelegate(crew1), "crew1 OnDied should have no subscribers"); - Assert.IsNull(GetOnDiedDelegate(crew2), "crew2 OnDied should have no subscribers"); - Assert.IsNull(GetOnDiedDelegate(crew3), "crew3 OnDied should have no subscribers"); + Assert.AreEqual(0, crew1.OnDiedSubscriberCountForTesting, "crew1 OnDied should have no subscribers"); + Assert.AreEqual(0, crew2.OnDiedSubscriberCountForTesting, "crew2 OnDied should have no subscribers"); + Assert.AreEqual(0, crew3.OnDiedSubscriberCountForTesting, "crew3 OnDied should have no subscribers"); } } } \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs b/Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs index 4489fe8a..324f4ca0 100644 --- a/Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs +++ b/Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs @@ -1,8 +1,10 @@ using System.Collections; using System.Collections.Generic; using NUnit.Framework; +using Ships; using Ships.Modules; -using Ships.Tests.TestHelpers; +using Ships.Tests.TestHelpers.Factories; +using Ships.Tests.TestHelpers.Fixtures; using UnityEngine; using UnityEngine.TestTools; using ZLinq; @@ -34,22 +36,13 @@ public IEnumerator UnrotatedModuleOnRight_ConnectsToCommandModule() AssertModulesConnected(ship, command, engine); } - private (Ship ship, Command command, Engine engine) CreateCommandWithEngineOnRight(float engineRotationZ) + private CommandWithEngineResult CreateCommandWithEngineOnRight(float engineRotationZ) { - var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects); - - ModuleFactory.CreateCommandModule(shipGo.transform, Vector2.zero, Container, CreatedObjects, - ModulePixelSize, ModulePixelSize); - ModuleFactory.CreateEngineModule(shipGo.transform, new Vector2(ModuleSpacing, 0f), Container, - CreatedObjects, EngineMaxThrust, ModulePixelSize, ModulePixelSize, engineRotationZ); - - var ship = ModuleFactory.WireShip(shipGo, Container); - var command = shipGo.GetComponentInChildren(); - var engine = shipGo.GetComponentInChildren(); - - Container.InjectGameObject(shipGo); - - return (ship, command, engine); + return ShipTestBuilder.CreateShip(Container, CreatedObjects) + .WithCommand("Command", Vector2.zero, ModulePixelSize, ModulePixelSize) + .WithEngineModule(new Vector2(ModuleSpacing, 0f), EngineMaxThrust, ModulePixelSize, ModulePixelSize, + engineRotationZ) + .BuildCommandWithEngineResult(); } private static void AssertModulesConnected(Ship ship, Command command, Engine engine) @@ -76,4 +69,4 @@ private static void AssertModulesConnected(Ship ship, Command command, Engine en "Command module should have connection points to engine"); } } -} \ No newline at end of file +} diff --git a/Assets/Scripts/Ships/Tests/ModuleDestructionThresholdTests.cs b/Assets/Scripts/Ships/Tests/ModuleDestructionThresholdTests.cs index 12a94b36..eb841ac2 100644 --- a/Assets/Scripts/Ships/Tests/ModuleDestructionThresholdTests.cs +++ b/Assets/Scripts/Ships/Tests/ModuleDestructionThresholdTests.cs @@ -1,13 +1,11 @@ using System.Collections; using System.Collections.Generic; using Core.Constants; -using Core.Ship; using NUnit.Framework; -using Ships.Modules; -using Ships.Tests.TestHelpers; +using Ships.Tests.TestHelpers.Factories; +using Ships.Tests.TestHelpers.Fixtures; using UnityEngine; using UnityEngine.TestTools; -using Module = Ships.Modules.Module; namespace Ships.Tests { @@ -27,26 +25,6 @@ public class ModuleDestructionThresholdTests : ShipTestBase private static int PixelsToKeepAtOrAboveThreshold => Mathf.CeilToInt(TotalPixels * GameplayConstants.ModuleDestroyedBelowPixelRatio); - private (Ship ship, Module command, Module other) CreateTwoModuleShip() - { - var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects); - - var commandGo = ModuleFactory.CreateModuleBase("Command", shipGo.transform, Vector2.zero, 0f, - Container, CreatedObjects, ModuleSize, ModuleSize); - var command = commandGo.AddComponent(); - - var otherGo = ModuleFactory.CreateModuleBase("Module2", shipGo.transform, new Vector2(ModuleSize, 0), 0f, - Container, CreatedObjects, ModuleSize, ModuleSize); - var other = otherGo.AddComponent(); - other.SetModuleType(ModuleType.Resources); - - var ship = ModuleFactory.WireShip(shipGo, Container); - - Container.InjectGameObject(shipGo); - - return (ship, command, other); - } - /// /// Removes pixels in row-major order so the kept pixels stay one contiguous region /// (no division/debris side effects). @@ -68,7 +46,8 @@ private static List PixelsToRemoveKeeping(int pixelsToKeep) [UnityTest] public IEnumerator ModuleBelowPixelThreshold_IsDestroyed() { - var (ship, _, other) = CreateTwoModuleShip(); + var (ship, _, other) = + ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects); yield return WaitForLifecycle(); other.PixelatedRigidbody.RemovePixels(PixelsToRemoveKeeping(PixelsToKeepJustBelowThreshold)); @@ -82,7 +61,8 @@ public IEnumerator ModuleBelowPixelThreshold_IsDestroyed() [UnityTest] public IEnumerator ModuleAtPixelThreshold_Survives() { - var (ship, _, other) = CreateTwoModuleShip(); + var (ship, _, other) = + ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects); yield return WaitForLifecycle(); other.PixelatedRigidbody.RemovePixels(PixelsToRemoveKeeping(PixelsToKeepAtOrAboveThreshold)); @@ -95,7 +75,8 @@ public IEnumerator ModuleAtPixelThreshold_Survives() [UnityTest] public IEnumerator CommandModuleBelowPixelThreshold_DestroysShip() { - var (ship, command, _) = CreateTwoModuleShip(); + var (ship, command, _) = + ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects); yield return WaitForLifecycle(); var shipGo = ship.gameObject; diff --git a/Assets/Scripts/Ships/Tests/ModuleJointLifecycleTests.cs b/Assets/Scripts/Ships/Tests/ModuleJointLifecycleTests.cs index c0f218bb..1a343f03 100644 --- a/Assets/Scripts/Ships/Tests/ModuleJointLifecycleTests.cs +++ b/Assets/Scripts/Ships/Tests/ModuleJointLifecycleTests.cs @@ -1,12 +1,10 @@ using System.Collections; using System.Collections.Generic; -using Core.Ship; using NUnit.Framework; -using Ships.Modules; -using Ships.Tests.TestHelpers; +using Ships.Tests.TestHelpers.Factories; +using Ships.Tests.TestHelpers.Fixtures; using UnityEngine; using UnityEngine.TestTools; -using Module = Ships.Modules.Module; using Object = UnityEngine.Object; namespace Ships.Tests @@ -20,32 +18,11 @@ namespace Ships.Tests [TestFixture] public class ModuleJointLifecycleTests : ShipTestBase { - private const int ModuleSize = 5; - - private (Ship ship, Module command, Module other) CreateTwoModuleShip() - { - var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects); - - var commandGo = ModuleFactory.CreateModuleBase("Command", shipGo.transform, Vector2.zero, 0f, - Container, CreatedObjects, ModuleSize, ModuleSize); - var command = commandGo.AddComponent(); - - var otherGo = ModuleFactory.CreateModuleBase("Module2", shipGo.transform, new Vector2(ModuleSize, 0), 0f, - Container, CreatedObjects, ModuleSize, ModuleSize); - var other = otherGo.AddComponent(); - other.SetModuleType(ModuleType.Resources); - - var ship = ModuleFactory.WireShip(shipGo, Container); - - Container.InjectGameObject(shipGo); - - return (ship, command, other); - } - [UnityTest] public IEnumerator InitializeModules_CalledRepeatedly_DoesNotDuplicateJoints() { - var (ship, _, _) = CreateTwoModuleShip(); + var (ship, _, _) = + ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects); yield return WaitForLifecycle(); Assert.AreEqual(1, ship.GetComponentsInChildren(true).Length, @@ -64,7 +41,8 @@ public IEnumerator InitializeModules_CalledRepeatedly_DoesNotDuplicateJoints() [UnityTest] public IEnumerator DestroyedModule_LeavesNoJointsOnRemainingModules() { - var (_, command, other) = CreateTwoModuleShip(); + var (_, command, other) = + ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects); yield return WaitForLifecycle(); Debug.Log("mkay0"); @@ -81,7 +59,8 @@ public IEnumerator DestroyedModule_LeavesNoJointsOnRemainingModules() [UnityTest] public IEnumerator DisconnectedModule_LeavesNoJointsOnEitherBody() { - var (_, command, other) = CreateTwoModuleShip(); + var (_, command, other) = + ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects); yield return WaitForLifecycle(); var commandGo = command.gameObject; diff --git a/Assets/Scripts/Ships/Tests/ShipControlAllocatorThrustTests.cs b/Assets/Scripts/Ships/Tests/ShipControlAllocatorThrustTests.cs index 1a90721a..8851e1f6 100644 --- a/Assets/Scripts/Ships/Tests/ShipControlAllocatorThrustTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipControlAllocatorThrustTests.cs @@ -1,34 +1,22 @@ using System.Collections; -using System.Collections.Generic; using NUnit.Framework; -using Ships.Modules; -using Ships.Tests.TestHelpers; +using Ships.Tests.TestHelpers.Factories; +using Ships.Tests.TestHelpers.Fixtures; using UnityEngine; using UnityEngine.TestTools; -using ZLinq; namespace Ships.Tests { [TestFixture] public class ShipControlAllocatorThrustTests : ShipTestBase { - private struct EngineSpec - { - public Vector2 LocalPosition; - public float LocalRotationZ; - public float MaxThrust; - } - [UnityTest] public IEnumerator ForwardInput_OneRearEngine_UsesAtLeastNinetyPercentThrust() { - var shipWithEngines = CreateShipWithEngines( - new EngineSpec - { - LocalPosition = new Vector2(0f, -5f), - LocalRotationZ = 0f, - MaxThrust = 10f - }); + var shipWithEngines = ShipTestBuilder.CreateShip(Container, CreatedObjects, "AllocatorTestShip") + .WithCommand("Command", Vector2.zero, 5, 5) + .WithEngineModule(new Vector2(0f, -5f), 10f, 5, 5) + .BuildWithEnginesResult(); yield return WaitForLifecycle(); @@ -41,19 +29,11 @@ public IEnumerator ForwardInput_OneRearEngine_UsesAtLeastNinetyPercentThrust() [UnityTest] public IEnumerator BackwardInput_BackwardFacingEngine_UsesAtLeastNinetyPercentThrust() { - var shipWithEngines = CreateShipWithEngines( - new EngineSpec - { - LocalPosition = new Vector2(0f, -5f), - LocalRotationZ = 180f, - MaxThrust = 10f - }, - new EngineSpec - { - LocalPosition = new Vector2(0f, 5f), - LocalRotationZ = 0f, - MaxThrust = 10f - }); + var shipWithEngines = ShipTestBuilder.CreateShip(Container, CreatedObjects, "AllocatorTestShip") + .WithCommand("Command", Vector2.zero, 5, 5) + .WithEngineModule(new Vector2(0f, -5f), 10f, 5, 5, 180f) + .WithEngineModule(new Vector2(0f, 5f), 10f, 5, 5) + .BuildWithEnginesResult(); yield return WaitForLifecycle(); @@ -66,12 +46,14 @@ public IEnumerator BackwardInput_BackwardFacingEngine_UsesAtLeastNinetyPercentTh [UnityTest] public IEnumerator ForwardInput_FiveHighThrustWingEngines_UsesAtLeastNinetyPercentThrust() { - var shipWithEngines = CreateShipWithEngines( - new EngineSpec { LocalPosition = new Vector2(-20f, -45f), LocalRotationZ = 0f, MaxThrust = 3000f }, - new EngineSpec { LocalPosition = new Vector2(-20f, -50f), LocalRotationZ = 0f, MaxThrust = 3000f }, - new EngineSpec { LocalPosition = new Vector2(0f, -48f), LocalRotationZ = 0f, MaxThrust = 3000f }, - new EngineSpec { LocalPosition = new Vector2(20f, -50f), LocalRotationZ = 0f, MaxThrust = 3000f }, - new EngineSpec { LocalPosition = new Vector2(20f, -45f), LocalRotationZ = 0f, MaxThrust = 3000f }); + var shipWithEngines = ShipTestBuilder.CreateShip(Container, CreatedObjects, "AllocatorTestShip") + .WithCommand("Command", Vector2.zero, 5, 5) + .WithEngineModule(new Vector2(-20f, -45f), 3000f, 5, 5) + .WithEngineModule(new Vector2(-20f, -50f), 3000f, 5, 5) + .WithEngineModule(new Vector2(0f, -48f), 3000f, 5, 5) + .WithEngineModule(new Vector2(20f, -50f), 3000f, 5, 5) + .WithEngineModule(new Vector2(20f, -45f), 3000f, 5, 5) + .BuildWithEnginesResult(); yield return WaitForLifecycle(); @@ -85,21 +67,13 @@ public IEnumerator ForwardInput_FiveHighThrustWingEngines_UsesAtLeastNinetyPerce } [UnityTest] - public IEnumerator HorizontalInput_OneRearEngine_UsesAtLeastNinetyPercentThrust() + public IEnumerator HorizontalInput_TwoSymmetricEngines_EngineUsesAtLeastNinetyPercentThrust() { - var shipWithEngines = CreateShipWithEngines( - new EngineSpec - { - LocalPosition = new Vector2(0f, -5f), - LocalRotationZ = 0f, - MaxThrust = 10f - }, - new EngineSpec - { - LocalPosition = new Vector2(0f, 5f), - LocalRotationZ = 0f, - MaxThrust = 10f - }); + var shipWithEngines = ShipTestBuilder.CreateShip(Container, CreatedObjects, "AllocatorTestShip") + .WithCommand("Command", Vector2.zero, 5, 5) + .WithEngineModule(new Vector2(0f, -5f), 10f, 5, 5) + .WithEngineModule(new Vector2(0f, 5f), 10f, 5, 5) + .BuildWithEnginesResult(); yield return WaitForLifecycle(); @@ -112,19 +86,11 @@ public IEnumerator HorizontalInput_OneRearEngine_UsesAtLeastNinetyPercentThrust( [UnityTest] public IEnumerator BackwardInput_ForwardFacingEngine_UsesAtMostTenPercentThrust() { - var shipWithEngines = CreateShipWithEngines( - new EngineSpec - { - LocalPosition = new Vector2(0f, -5f), - LocalRotationZ = 180f, - MaxThrust = 10f - }, - new EngineSpec - { - LocalPosition = new Vector2(0f, 5f), - LocalRotationZ = 0f, - MaxThrust = 10f - }); + var shipWithEngines = ShipTestBuilder.CreateShip(Container, CreatedObjects, "AllocatorTestShip") + .WithCommand("Command", Vector2.zero, 5, 5) + .WithEngineModule(new Vector2(0f, -5f), 10f, 5, 5, 180f) + .WithEngineModule(new Vector2(0f, 5f), 10f, 5, 5) + .BuildWithEnginesResult(); yield return WaitForLifecycle(); @@ -133,25 +99,5 @@ public IEnumerator BackwardInput_ForwardFacingEngine_UsesAtMostTenPercentThrust( Assert.That(shipWithEngines.Engines[1].CurrentThrustRatioForTesting, Is.LessThanOrEqualTo(0.1f)); } - - private (ShipTestProxy Ship, List Engines) CreateShipWithEngines(params EngineSpec[] engineSpecs) - { - var shipGo = ModuleFactory.CreateGameObject("AllocatorTestShip", CreatedObjects); - ModuleFactory.CreateCommandModule(shipGo.transform, Vector2.zero, Container, CreatedObjects, 5, 5); - - var engines = engineSpecs.AsValueEnumerable().Select(spec => - { - ModuleFactory.CreateEngineModule(shipGo.transform, spec.LocalPosition, Container, CreatedObjects, - spec.MaxThrust, 5, 5, spec.LocalRotationZ); - var moduleTransform = shipGo.transform.GetChild(shipGo.transform.childCount - 1); - return moduleTransform.GetComponent(); - }).ToList(); - - var ship = ModuleFactory.WireShip(shipGo, Container); - - Container.InjectGameObject(shipGo); - - return (ship, engines); - } } -} \ No newline at end of file +} diff --git a/Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs b/Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs index 0e11fdee..317b3ebf 100644 --- a/Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs @@ -2,63 +2,39 @@ using System.Collections.Generic; using Core.Ship; using NUnit.Framework; -using Ships.Modules; -using Ships.Tests.TestHelpers; +using Ships; +using Ships.Tests.TestHelpers.Factories; +using Ships.Tests.TestHelpers.Fixtures; using UnityEngine; using UnityEngine.TestTools; +using Zenject; using ZLinq; -using Resources = Core.Ship.Resources; namespace Ships.Tests { [TestFixture] public class ShipCrewAssignmentTests : ShipTestBase { - private Ship CreateShipWithModules(params (int crewNeeded, CrewSkillType mainSkill)[] moduleConfigs) + private static Ship BuildShipWithCrewModules(DiContainer container, ICollection createdObjects, + params (int crewNeeded, CrewSkillType mainSkill)[] moduleConfigs) { - var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects); - - CreateModule("Command", shipGo.transform, Vector2.zero, 5, 5, true, 0, CrewSkillType.Navigation); + var builder = ShipTestBuilder.CreateShip(container, createdObjects) + .WithCommand("Command", Vector2.zero, 5, 5); for (var i = 0; i < moduleConfigs.Length; i++) { var config = moduleConfigs[i]; - CreateModule($"Module{i}", shipGo.transform, - new Vector2(5 * (i + 1), 0), 5, 5, false, - config.crewNeeded, config.mainSkill); - } - - Container.InjectGameObject(shipGo); - - return ModuleFactory.WireShip(shipGo, Container); - } - - private void CreateModule(string name, Transform parent, Vector2 localPosition, - int width, int height, bool isCommand, int crewNeeded, CrewSkillType mainSkill) - { - var moduleGo = ModuleFactory.CreateModuleBase(name, parent, localPosition, 0f, Container, CreatedObjects, - width, height); - - Module module; - if (isCommand) - { - module = moduleGo.AddComponent(); - } - else - { - var testModule = moduleGo.AddComponent(); - testModule.SetModuleType(ModuleType.Resources); - testModule.SetMainSkillType(mainSkill); - module = testModule; + builder.WithCrewModule($"Module{i}", new Vector2(5 * (i + 1), 0), 5, 5, config.crewNeeded, + config.mainSkill); } - module.SetResources(new Resources(0, 0, crewNeeded, 0, 0)); + return builder.Build(); } [UnityTest] public IEnumerator AssignCrewRandomly_DistributesCrewAcrossModules() { - var ship = CreateShipWithModules( + var ship = BuildShipWithCrewModules(Container, CreatedObjects, (crewNeeded: 2, mainSkill: CrewSkillType.Navigation), (crewNeeded: 2, mainSkill: CrewSkillType.Mechanics)); yield return WaitForLifecycle(); @@ -77,7 +53,7 @@ public IEnumerator AssignCrewRandomly_DistributesCrewAcrossModules() [UnityTest] public IEnumerator AssignCrewRandomly_EmptyCrew_NoAssignment() { - var ship = CreateShipWithModules( + var ship = BuildShipWithCrewModules(Container, CreatedObjects, (crewNeeded: 3, mainSkill: CrewSkillType.Navigation)); yield return WaitForLifecycle(); @@ -91,7 +67,7 @@ public IEnumerator AssignCrewRandomly_EmptyCrew_NoAssignment() [UnityTest] public IEnumerator AssignCrewRandomly_ExcessCrew_OnlyAssignsNeeded() { - var ship = CreateShipWithModules( + var ship = BuildShipWithCrewModules(Container, CreatedObjects, (crewNeeded: 1, mainSkill: CrewSkillType.Navigation), (crewNeeded: 1, mainSkill: CrewSkillType.Mechanics)); yield return WaitForLifecycle(); @@ -112,7 +88,7 @@ public IEnumerator AssignCrewRandomly_ExcessCrew_OnlyAssignsNeeded() [UnityTest] public IEnumerator AssignCrewRandomly_AssignsBestSkilledToMatchingModules() { - var ship = CreateShipWithModules( + var ship = BuildShipWithCrewModules(Container, CreatedObjects, (crewNeeded: 1, mainSkill: CrewSkillType.Navigation)); yield return WaitForLifecycle(); @@ -132,7 +108,7 @@ public IEnumerator AssignCrewRandomly_AssignsBestSkilledToMatchingModules() [UnityTest] public IEnumerator CrewMissingCount_SumsAcrossAllModules() { - var ship = CreateShipWithModules( + var ship = BuildShipWithCrewModules(Container, CreatedObjects, (crewNeeded: 3, mainSkill: CrewSkillType.Navigation), (crewNeeded: 5, mainSkill: CrewSkillType.Mechanics)); yield return WaitForLifecycle(); @@ -144,7 +120,7 @@ public IEnumerator CrewMissingCount_SumsAcrossAllModules() [UnityTest] public IEnumerator CrewMissingCount_AfterAssignment_ReflectsRemaining() { - var ship = CreateShipWithModules( + var ship = BuildShipWithCrewModules(Container, CreatedObjects, (crewNeeded: 3, mainSkill: CrewSkillType.Navigation), (crewNeeded: 2, mainSkill: CrewSkillType.Mechanics)); yield return WaitForLifecycle(); @@ -162,7 +138,7 @@ public IEnumerator CrewMissingCount_AfterAssignment_ReflectsRemaining() [UnityTest] public IEnumerator CrewMissingCount_FullyStaffed_ReturnsZero() { - var ship = CreateShipWithModules( + var ship = BuildShipWithCrewModules(Container, CreatedObjects, (crewNeeded: 2, mainSkill: CrewSkillType.Navigation), (crewNeeded: 1, mainSkill: CrewSkillType.Mechanics)); yield return WaitForLifecycle(); @@ -179,7 +155,7 @@ public IEnumerator CrewMissingCount_FullyStaffed_ReturnsZero() [UnityTest] public IEnumerator AssignCrewRandomly_InsufficientCrew_PartiallyFills() { - var ship = CreateShipWithModules( + var ship = BuildShipWithCrewModules(Container, CreatedObjects, (crewNeeded: 5, mainSkill: CrewSkillType.Navigation), (crewNeeded: 5, mainSkill: CrewSkillType.Mechanics)); yield return WaitForLifecycle(); diff --git a/Assets/Scripts/Ships/Tests/ShipDestroyAllModulesTests.cs b/Assets/Scripts/Ships/Tests/ShipDestroyAllModulesTests.cs index a06bf398..910353a1 100644 --- a/Assets/Scripts/Ships/Tests/ShipDestroyAllModulesTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipDestroyAllModulesTests.cs @@ -1,10 +1,10 @@ using System.Collections; using NUnit.Framework; using Services; -using Ships.ModuleConnection; using Ships.Modules; -using Ships.Systems.Resources; -using Ships.Tests.TestHelpers; +using Ships.Tests.TestHelpers.Factories; +using Ships.Tests.TestHelpers.Fixtures; +using Ships.Tests.TestHelpers.Mocks; using UnityEngine; using UnityEngine.TestTools; @@ -26,7 +26,7 @@ public override void SetUp() [UnityTest] public IEnumerator DestroyAllModules_RemovesModulesFromShipHierarchy() { - var ship = CreateShipWithCommandAndEngine(); + var ship = ShipTestFactory.CreateShipWithCommandAndEngine(Container, CreatedObjects, TestRoot.transform); yield return WaitForLifecycle(); Assert.That(ship.GetComponentsInChildren().Length, Is.EqualTo(2)); @@ -40,7 +40,7 @@ public IEnumerator DestroyAllModules_RemovesModulesFromShipHierarchy() [UnityTest] public IEnumerator DestroyAllModules_DetachesModulesFromShipTransform() { - var ship = CreateShipWithCommandAndEngine(); + var ship = ShipTestFactory.CreateShipWithCommandAndEngine(Container, CreatedObjects, TestRoot.transform); yield return WaitForLifecycle(); var modulesBeforeDestroy = ship.GetComponentsInChildren(); @@ -59,7 +59,7 @@ public IEnumerator DestroyAllModules_DetachesModulesFromShipTransform() [UnityTest] public IEnumerator DestroyAllModules_ClearsModuleShipReference() { - var ship = CreateShipWithCommandAndEngine(); + var ship = ShipTestFactory.CreateShipWithCommandAndEngine(Container, CreatedObjects, TestRoot.transform); yield return WaitForLifecycle(); var engine = (Engine)ship.AllModules[1]; @@ -72,7 +72,7 @@ public IEnumerator DestroyAllModules_ClearsModuleShipReference() [UnityTest] public IEnumerator DestroyAllModules_ThenAddCommand_InitializeModules_RebuildsShip() { - var ship = CreateShipWithCommandAndEngine(); + var ship = ShipTestFactory.CreateShipWithCommandAndEngine(Container, CreatedObjects, TestRoot.transform); yield return WaitForLifecycle(); ship.DestroyAllModules(); @@ -88,7 +88,7 @@ public IEnumerator DestroyAllModules_ThenAddCommand_InitializeModules_RebuildsSh [UnityTest] public IEnumerator DestroyAllModules_OnEmptyShip_DoesNotThrow() { - var ship = CreateShipWithCommandAndEngine(); + var ship = ShipTestFactory.CreateShipWithCommandAndEngine(Container, CreatedObjects, TestRoot.transform); yield return WaitForLifecycle(); ship.DestroyAllModules(); @@ -101,7 +101,7 @@ public IEnumerator DestroyAllModules_OnEmptyShip_DoesNotThrow() [UnityTest] public IEnumerator ApplySnapshot_AfterDestroyAllModules_ReplacesModulesCorrectly() { - var ship = CreateShipWithCommandAndEngine(); + var ship = ShipTestFactory.CreateShipWithCommandAndEngine(Container, CreatedObjects, TestRoot.transform); yield return WaitForLifecycle(); var snapshot = _snapshotService.CaptureSnapshot(ship); @@ -122,7 +122,7 @@ public IEnumerator ApplySnapshot_AfterDestroyAllModules_ReplacesModulesCorrectly [UnityTest] public IEnumerator ApplySnapshot_WithDamagedPixels_PreservesDamageAfterDestroyAllModules() { - var ship = CreateShipWithCommandAndEngine(); + var ship = ShipTestFactory.CreateShipWithCommandAndEngine(Container, CreatedObjects, TestRoot.transform); yield return WaitForLifecycle(); var engine = (Engine)ship.AllModules[1]; @@ -139,26 +139,5 @@ public IEnumerator ApplySnapshot_WithDamagedPixels_PreservesDamageAfterDestroyAl var restoredEngine = (Engine)ship.AllModules[1]; Assert.IsFalse(restoredEngine.PixelatedRigidbody.IsPixel(new Vector2Int(2, 2))); } - - private Ship CreateShipWithCommandAndEngine() - { - var shipGo = ModuleFactory.CreateGameObject("Ship", CreatedObjects); - shipGo.transform.SetParent(TestRoot.transform); - shipGo.SetActive(false); - - ModuleFactory.CreateCommandModule(shipGo.transform, Vector2.zero, Container, CreatedObjects, 5, 5); - ModuleFactory.CreateEngineModule(shipGo.transform, new Vector2(5f, 0f), Container, CreatedObjects, 100f, - 5, 5); - - shipGo.AddComponent(); - shipGo.AddComponent(); - - var ship = ModuleFactory.WireShip(shipGo, Container); - ship.InitializeModules(); - - Container.InjectGameObject(shipGo); - - return ship; - } } } \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/ShipDestructionJunkTests.cs b/Assets/Scripts/Ships/Tests/ShipDestructionJunkTests.cs index 71179176..14190689 100644 --- a/Assets/Scripts/Ships/Tests/ShipDestructionJunkTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipDestructionJunkTests.cs @@ -1,13 +1,11 @@ using System.Collections; using System.Collections.Generic; -using Core.Ship; using NUnit.Framework; using Pixelation; -using Ships.Modules; -using Ships.Tests.TestHelpers; +using Ships.Tests.TestHelpers.Factories; +using Ships.Tests.TestHelpers.Fixtures; using UnityEngine; using UnityEngine.TestTools; -using Module = Ships.Modules.Module; namespace Ships.Tests { @@ -22,26 +20,6 @@ public class ShipDestructionJunkTests : ShipTestBase { private const int ModuleSize = 5; - private (Ship ship, Module command, Module other) CreateTwoModuleShip() - { - var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects); - - var commandGo = ModuleFactory.CreateModuleBase("Command", shipGo.transform, Vector2.zero, 0f, - Container, CreatedObjects, ModuleSize, ModuleSize); - var command = commandGo.AddComponent(); - - var otherGo = ModuleFactory.CreateModuleBase("Module2", shipGo.transform, new Vector2(ModuleSize, 0), 0f, - Container, CreatedObjects, ModuleSize, ModuleSize); - var other = otherGo.AddComponent(); - other.SetModuleType(ModuleType.Resources); - - var ship = ModuleFactory.WireShip(shipGo, Container); - - Container.InjectGameObject(shipGo); - - return (ship, command, other); - } - private static List AllPixels() { var pixels = new List(); @@ -54,7 +32,8 @@ private static List AllPixels() [UnityTest] public IEnumerator CommandModuleDestroyed_SurvivingModuleBecomesEnabledJunk() { - var (ship, command, other) = CreateTwoModuleShip(); + var (ship, command, other) = + ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects); yield return WaitForLifecycle(); var shipGo = ship.gameObject; diff --git a/Assets/Scripts/Ships/Tests/ShipDisconnectionTests.cs b/Assets/Scripts/Ships/Tests/ShipDisconnectionTests.cs index 3b0694a6..bbe53e4c 100644 --- a/Assets/Scripts/Ships/Tests/ShipDisconnectionTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipDisconnectionTests.cs @@ -1,10 +1,9 @@ using System.Collections; using System.Collections.Generic; using Core.Pixelation; -using Core.Ship; using NUnit.Framework; -using Ships.Modules; -using Ships.Tests.TestHelpers; +using Ships.Tests.TestHelpers.Factories; +using Ships.Tests.TestHelpers.Fixtures; using UnityEngine; using UnityEngine.TestTools; using ZLinq; @@ -20,134 +19,6 @@ namespace Ships.Tests [TestFixture] public class ShipDisconnectionTests : ShipTestBase { - /// - /// Creates a simple two-module ship where modules are adjacent on the X axis. - /// Command module on the left, other module on the right, touching at their edges. - /// - private TestShipComponents CreateTwoModuleShip(int moduleWidth = 5, int moduleHeight = 5) - { - var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects); - - // Create command module (left side) - var commandModule = CreateModule("Command", shipGo.transform, - new Vector2(0, 0), moduleWidth, moduleHeight, true); - - // Create second module (right side, adjacent to command) - // Position it so the left edge of module2 touches the right edge of command - var module2 = CreateModule("Module2", shipGo.transform, - new Vector2(moduleWidth, 0), moduleWidth, moduleHeight, false); - - var ship = ModuleFactory.WireShip(shipGo, Container); - - Container.InjectGameObject(shipGo); - - return new TestShipComponents(ship, commandModule, new List { module2 }); - } - - /// - /// Creates a three-module linear ship: Command -- Module2 -- Module3 - /// - private TestShipComponents CreateThreeModuleLinearShip(int moduleWidth = 5, int moduleHeight = 5) - { - var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects); - - var commandModule = CreateModule("Command", shipGo.transform, - new Vector2(0, 0), moduleWidth, moduleHeight, true); - - var module2 = CreateModule("Module2", shipGo.transform, - new Vector2(moduleWidth, 0), moduleWidth, moduleHeight, false); - - var module3 = CreateModule("Module3", shipGo.transform, - new Vector2(moduleWidth * 2, 0), moduleWidth, moduleHeight, false); - - var ship = ModuleFactory.WireShip(shipGo, Container); - - Container.InjectGameObject(shipGo); - - return new TestShipComponents(ship, commandModule, new List { module2, module3 }); - } - - /// - /// Creates a ship with alternate paths: Command connects to both A and B, and A connects to B. - /// - private TestShipComponents CreateShipWithAlternatePaths() - { - var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects); - var moduleSize = 5; - - // Command module at origin - var commandModule = CreateModule("Command", shipGo.transform, - new Vector2(0, 0), moduleSize, moduleSize, true); - - // Module A to the right of command - var moduleA = CreateModule("ModuleA", shipGo.transform, - new Vector2(moduleSize, 0), moduleSize, moduleSize, false); - - // Module B above command (and also adjacent to A via diagonal positioning) - var moduleB = CreateModule("ModuleB", shipGo.transform, - new Vector2(0, moduleSize), moduleSize, moduleSize, false); - - // Module C that connects A and B (creates alternate path) - var moduleC = CreateModule("ModuleC", shipGo.transform, - new Vector2(moduleSize, moduleSize), moduleSize, moduleSize, false); - - var ship = ModuleFactory.WireShip(shipGo, Container); - - Container.InjectGameObject(shipGo); - - return new TestShipComponents(ship, commandModule, new List { moduleA, moduleB, moduleC }); - } - - /// - /// Creates a vertical ship: A (top) -- B (central/command) -- C (bottom) - /// Modules are stacked vertically, B is the command module in the middle. - /// - private TestShipComponents CreateVerticalThreeModuleShip(int moduleWidth = 5, int moduleHeight = 10) - { - var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects); - - // Module B (command) in the center - var commandModule = CreateModule("CommandB", shipGo.transform, - new Vector2(0, 0), moduleWidth, moduleHeight, true); - - // Module A above B (touching B's top edge) - var moduleA = CreateModule("ModuleA", shipGo.transform, - new Vector2(0, moduleHeight), moduleWidth, moduleHeight, false); - - // Module C below B (touching B's bottom edge) - var moduleC = CreateModule("ModuleC", shipGo.transform, - new Vector2(0, -moduleHeight), moduleWidth, moduleHeight, false); - - var ship = ModuleFactory.WireShip(shipGo, Container); - - Container.InjectGameObject(shipGo); - - return new TestShipComponents(ship, commandModule, new List { moduleA, moduleC }); - } - - private Module CreateModule(string name, Transform parent, Vector2 localPosition, - int width, int height, bool isCommand) - { - var moduleGo = ModuleFactory.CreateModuleBase(name, parent, localPosition, 0f, Container, CreatedObjects, - width, height); - - // Add module component - Module module; - if (isCommand) - { - module = moduleGo.AddComponent(); - } - else - { - var testModule = moduleGo.AddComponent(); - testModule.SetModuleType(ModuleType.Resources); - module = testModule; - } - - return module; - } - - /// /// Gets the connection points between two modules. /// @@ -163,12 +34,12 @@ private static List GetConnectionPoints(Module from, Module to) public IEnumerator DestroyAllConnectionPoints_ModuleDisconnects() { // Arrange: Create a two-module ship - var components = CreateTwoModuleShip(); + var components = ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects); yield return WaitForLifecycle(); var ship = components.Ship; - var commandModule = components.CommandModule; - var otherModule = components.OtherModules[0]; + var commandModule = components.Command; + var otherModule = components.Other; // Verify initial state - both modules should be in the graph Assert.IsTrue(ship.ModuleGraph.ContainsNode(commandModule), "Command module should be in graph"); @@ -194,7 +65,13 @@ public IEnumerator DestroyAllConnectionPoints_ModuleDisconnects() public IEnumerator DestroyMiddleModule_DownstreamModulesDisconnect() { // Arrange: Create Command -- Module2 -- Module3 - var components = CreateThreeModuleLinearShip(); + const int moduleWidth = 5; + const int moduleHeight = 5; + var components = ShipTestBuilder.CreateShip(Container, CreatedObjects) + .WithCommand("Command", Vector2.zero, moduleWidth, moduleHeight) + .WithModule("Module2", new Vector2(moduleWidth, 0), moduleWidth, moduleHeight) + .WithModule("Module3", new Vector2(moduleWidth * 2, 0), moduleWidth, moduleHeight) + .BuildLayoutResult(); yield return WaitForLifecycle(); var ship = components.Ship; @@ -224,7 +101,13 @@ public IEnumerator DestroyMiddleModule_DownstreamModulesDisconnect() public IEnumerator AlternatePath_ModuleStaysConnected() { // Arrange: Create ship with alternate paths - var components = CreateShipWithAlternatePaths(); + const int moduleSize = 5; + var components = ShipTestBuilder.CreateShip(Container, CreatedObjects) + .WithCommand("Command", Vector2.zero, moduleSize, moduleSize) + .WithModule("ModuleA", new Vector2(moduleSize, 0), moduleSize, moduleSize) + .WithModule("ModuleB", new Vector2(0, moduleSize), moduleSize, moduleSize) + .WithModule("ModuleC", new Vector2(moduleSize, moduleSize), moduleSize, moduleSize) + .BuildLayoutResult(); yield return WaitForLifecycle(); var ship = components.Ship; @@ -267,11 +150,11 @@ public IEnumerator AlternatePath_ModuleStaysConnected() public IEnumerator DestroyCommandModulePixels_ShipDestroyed() { // Arrange: Create a simple ship - var components = CreateTwoModuleShip(3, 3); + var components = ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects, 3, 3); yield return WaitForLifecycle(); var ship = components.Ship; - var commandModule = components.CommandModule; + var commandModule = components.Command; var shipGo = ship.gameObject; // Act: Destroy all pixels in the command module @@ -294,12 +177,12 @@ public IEnumerator DestroyCommandModulePixels_ShipDestroyed() public IEnumerator PartialConnectionPointDestruction_ModuleStaysConnected() { // Arrange: Create a two-module ship with larger modules (more connection points) - var components = CreateTwoModuleShip(10, 10); + var components = ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects, 10, 10); yield return WaitForLifecycle(); var ship = components.Ship; - var commandModule = components.CommandModule; - var otherModule = components.OtherModules[0]; + var commandModule = components.Command; + var otherModule = components.Other; var connectionPoints = GetConnectionPoints(commandModule, otherModule); @@ -323,13 +206,19 @@ public IEnumerator PartialConnectionPointDestruction_ModuleStaysConnected() public IEnumerator SliceCentralModuleNearTop_TopModuleDisconnects() { // Arrange: Create vertical ship A (top) -- B (central/command) -- C (bottom) - var components = CreateVerticalThreeModuleShip(); + const int moduleWidth = 5; + const int moduleHeight = 10; + var components = ShipTestBuilder.CreateShip(Container, CreatedObjects) + .WithCommand("CommandB", Vector2.zero, moduleWidth, moduleHeight) + .WithModule("ModuleA", new Vector2(0, moduleHeight), moduleWidth, moduleHeight) + .WithModule("ModuleC", new Vector2(0, -moduleHeight), moduleWidth, moduleHeight) + .BuildLayoutResult(); yield return WaitForLifecycle(); var ship = components.Ship; - var commandModule = components.CommandModule; // B - central - var moduleA = components.OtherModules[0]; // Top - var moduleC = components.OtherModules[1]; // Bottom + var commandModule = components.CommandModule; + var moduleA = components.OtherModules[0]; + var moduleC = components.OtherModules[1]; // Verify initial state Assert.IsTrue(ship.ModuleGraph.ContainsNode(moduleA), "Module A should be in graph initially"); @@ -369,13 +258,19 @@ public IEnumerator SliceCentralModuleNearTop_TopModuleDisconnects() public IEnumerator SliceCentralModuleNearBottom_BottomModuleDisconnects() { // Arrange: Create vertical ship A (top) -- B (central/command) -- C (bottom) - var components = CreateVerticalThreeModuleShip(); + const int moduleWidth = 5; + const int moduleHeight = 10; + var components = ShipTestBuilder.CreateShip(Container, CreatedObjects) + .WithCommand("CommandB", Vector2.zero, moduleWidth, moduleHeight) + .WithModule("ModuleA", new Vector2(0, moduleHeight), moduleWidth, moduleHeight) + .WithModule("ModuleC", new Vector2(0, -moduleHeight), moduleWidth, moduleHeight) + .BuildLayoutResult(); yield return WaitForLifecycle(); var ship = components.Ship; - var commandModule = components.CommandModule; // B - central - var moduleA = components.OtherModules[0]; // Top - var moduleC = components.OtherModules[1]; // Bottom + var commandModule = components.CommandModule; + var moduleA = components.OtherModules[0]; + var moduleC = components.OtherModules[1]; // Verify initial state Assert.IsTrue(ship.ModuleGraph.ContainsNode(moduleA), "Module A should be in graph initially"); @@ -410,13 +305,19 @@ public IEnumerator SliceCentralModuleNearBottom_BottomModuleDisconnects() public IEnumerator SliceCentralModuleInMiddle_SmallerHalfDisconnects() { // Arrange: Create vertical ship A (top) -- B (central/command) -- C (bottom) - var components = CreateVerticalThreeModuleShip(); + const int moduleWidth = 5; + const int moduleHeight = 10; + var components = ShipTestBuilder.CreateShip(Container, CreatedObjects) + .WithCommand("CommandB", Vector2.zero, moduleWidth, moduleHeight) + .WithModule("ModuleA", new Vector2(0, moduleHeight), moduleWidth, moduleHeight) + .WithModule("ModuleC", new Vector2(0, -moduleHeight), moduleWidth, moduleHeight) + .BuildLayoutResult(); yield return WaitForLifecycle(); var ship = components.Ship; - var commandModule = components.CommandModule; // B - central - var moduleA = components.OtherModules[0]; // Top - var moduleC = components.OtherModules[1]; // Bottom + var commandModule = components.CommandModule; + var moduleA = components.OtherModules[0]; + var moduleC = components.OtherModules[1]; // Verify initial state Assert.IsTrue(ship.ModuleGraph.ContainsNode(moduleA), "Module A should be in graph initially"); @@ -468,15 +369,14 @@ public IEnumerator SliceCannonNearConnectionEdge_CannonDisconnects() const int commandWidth = 6; const int commandHeight = 10; - var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects); - - var commandModule = CreateModule("Command", shipGo.transform, - new Vector2((cannonWidth + commandWidth) / 2f, 0), commandWidth, commandHeight, true); - - var cannonModule = CreateModule("Cannon", shipGo.transform, - new Vector2(0, 0), cannonWidth, cannonHeight, false); - - var ship = ModuleFactory.WireShip(shipGo, Container); + var layout = ShipTestBuilder.CreateShip(Container, CreatedObjects) + .WithoutGameObjectInjection() + .WithCommand("Command", new Vector2((cannonWidth + commandWidth) / 2f, 0), commandWidth, commandHeight) + .WithModule("Cannon", Vector2.zero, cannonWidth, cannonHeight) + .BuildLayoutResult(); + var ship = layout.Ship; + var commandModule = layout.CommandModule; + var cannonModule = layout.OtherModules[0]; yield return WaitForLifecycle(); @@ -661,15 +561,14 @@ public IEnumerator SliceCannonAcrossMultipleFrames_CannonDisconnects() const int commandWidth = 6; const int commandHeight = 10; - var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects); - - var commandModule = CreateModule("Command", shipGo.transform, - new Vector2((cannonWidth + commandWidth) / 2f, 0), commandWidth, commandHeight, true); - - var cannonModule = CreateModule("Cannon", shipGo.transform, - new Vector2(0, 0), cannonWidth, cannonHeight, false); - - var ship = ModuleFactory.WireShip(shipGo, Container); + var layout = ShipTestBuilder.CreateShip(Container, CreatedObjects) + .WithoutGameObjectInjection() + .WithCommand("Command", new Vector2((cannonWidth + commandWidth) / 2f, 0), commandWidth, commandHeight) + .WithModule("Cannon", Vector2.zero, cannonWidth, cannonHeight) + .BuildLayoutResult(); + var ship = layout.Ship; + var commandModule = layout.CommandModule; + var cannonModule = layout.OtherModules[0]; yield return WaitForLifecycle(); @@ -786,19 +685,5 @@ public IEnumerator SliceCannonAcrossMultipleFrames_CannonDisconnects() "Cannon should be disconnected after multi-frame slice separated its connection edge. " + $"Remaining connection points: {finalRemaining.Count}"); } - - private class TestShipComponents - { - public TestShipComponents(Ship ship, Module commandModule, List otherModules) - { - Ship = ship; - CommandModule = commandModule; - OtherModules = otherModules; - } - - public Ship Ship { get; } - public Module CommandModule { get; } - public List OtherModules { get; } - } } } \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/ShipGameplayMovementTests.cs b/Assets/Scripts/Ships/Tests/ShipGameplayMovementTests.cs index d0f2d807..8cdfa07a 100644 --- a/Assets/Scripts/Ships/Tests/ShipGameplayMovementTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipGameplayMovementTests.cs @@ -1,6 +1,8 @@ using System.Collections; using NUnit.Framework; -using Ships.Tests.TestHelpers; +using Ships.Tests.TestHelpers.Factories; +using Ships.Tests.TestHelpers.Fixtures; +using Ships.Tests.TestHelpers.Proxies; using UnityEngine; using UnityEngine.TestTools; @@ -97,7 +99,19 @@ public IEnumerator Ship_SasReachesWithinOnePercentOfDesiredHeading_AfterFiveSeco private MovableShipTestProxy CreateReadyShip() { - return SmallMovableShipTestFactory.Create(Container, CreatedObjects); + const int modulePixelSize = 5; + const float moduleSpacing = 5f; + const float engineMaxThrust = 800f; + + var ship = ShipTestBuilder.CreateShip(Container, CreatedObjects, "GameplayTestShip") + .WithCommand("Command", Vector2.zero, modulePixelSize, modulePixelSize) + .WithPowerModule(new Vector2(0f, moduleSpacing), modulePixelSize, modulePixelSize) + .WithEngineModule(new Vector2(moduleSpacing, 0f), engineMaxThrust, modulePixelSize, modulePixelSize) + .WithEngineModule(new Vector2(-moduleSpacing, 0f), engineMaxThrust, modulePixelSize, modulePixelSize) + .Build(); + + ship.ConfigureAllocatorForTesting(true, 14, 1f, 0.4f, 0.02f); + return ship; } private sealed class HeadingChangeAccumulator diff --git a/Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs b/Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs index 35889202..eff41202 100644 --- a/Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs @@ -1,13 +1,12 @@ using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using Core.Services; using Core.Ship; using NUnit.Framework; -using Pixelation; using Services; +using Ships; using Ships.Modules; -using Ships.Tests.TestHelpers; +using Ships.Tests.TestHelpers.Factories; +using Ships.Tests.TestHelpers.Fixtures; +using Ships.Tests.TestHelpers.Mocks; using UnityEngine; using UnityEngine.TestTools; using Resources = Core.Ship.Resources; @@ -26,61 +25,6 @@ public override void SetUp() _service = new ShipSnapshotService(Container, null, _moduleCatalog, _contentCatalog); } - private sealed class TestContentCatalog : IGameContentCatalog - { - private readonly Dictionary _idToPrefab = new(); - private readonly Dictionary _idToSprite = new(); - private readonly Dictionary _prefabToId = new(); - private readonly Dictionary _spriteToId = new(); - - public bool TryGetPrefab(string contentId, out GameObject prefab) - { - return _idToPrefab.TryGetValue(contentId, out prefab); - } - - public bool TryGetContentId(GameObject prefab, out string contentId) - { - return _prefabToId.TryGetValue(prefab, out contentId); - } - - public bool TryGetSprite(string contentId, out Sprite sprite) - { - return _idToSprite.TryGetValue(contentId, out sprite); - } - - public bool TryGetSpriteContentId(Sprite sprite, out string contentId) - { - return _spriteToId.TryGetValue(sprite, out contentId); - } - - public void AddPrefab(string id, GameObject prefab) - { - _idToPrefab[id] = prefab; - _prefabToId[prefab] = id; - } - - public void AddSprite(string id, Sprite sprite) - { - _idToSprite[id] = sprite; - _spriteToId[sprite] = id; - } - } - - private sealed class TestModuleCatalog : IShipModuleCatalog - { - private readonly Dictionary _idToPrefab = new(); - - public bool TryGetModulePrefab(string archetypeId, out GameObject prefab) - { - return _idToPrefab.TryGetValue(archetypeId, out prefab); - } - - public void Add(string id, GameObject prefab) - { - _idToPrefab[id] = prefab; - } - } - private TestContentCatalog _contentCatalog; private TestModuleCatalog _moduleCatalog; private ShipSnapshotService _service; @@ -94,10 +38,16 @@ public IEnumerator PrefabOriginCannon_RoundTrip_PreservesProjectileAndSprite() _contentCatalog.AddPrefab("bullet_big", projectilePrefab); _contentCatalog.AddSprite("sprite_cannon", weaponSprite); - var cannonPrefab = CreateCannonPrefab(projectilePrefab, weaponSprite); + var cannonPrefab = ShipTestBuilder.CreateCannonPrefab(Container, CreatedObjects, TestRoot.transform, + projectilePrefab, weaponSprite); _moduleCatalog.Add("cannon_small_16", cannonPrefab); - var ship = CreateShipWithCommandAndCannon(cannonPrefab, "cannon_small_16"); + var ship = ShipTestBuilder.CreateShip(Container, CreatedObjects, "Ship") + .ParentedTo(TestRoot.transform) + .WithCustomCommand(Vector2.zero, 5, 5) + .WithInstantiatedCannon(cannonPrefab, new Vector2(2f, 0f), "cannon_small_16", 5) + .Build(initializeModules: true); + yield return null; var snapshot = _service.CaptureSnapshot(ship); @@ -113,7 +63,12 @@ public IEnumerator PrefabOriginCannon_RoundTrip_PreservesProjectileAndSprite() [UnityTest] public IEnumerator CustomScratchModule_RoundTrip_PreservesColorGrid() { - var ship = CreateShipWithScratchEngine(); + var ship = ShipTestBuilder.CreateShip(Container, CreatedObjects, "Ship") + .ParentedTo(TestRoot.transform) + .WithCustomCommand(Vector2.zero, 5, 5) + .WithCustomEngine(new Vector2(2f, 0f), 5, 5, new Resources(0, 2f, 0, 0, 0)) + .Build(initializeModules: true); + yield return null; var snapshot = _service.CaptureSnapshot(ship); @@ -134,7 +89,12 @@ public IEnumerator CustomScratchModule_RoundTrip_PreservesColorGrid() [UnityTest] public IEnumerator PostDamage_RoundTrip_KeepsDestroyedPixelsGone() { - var ship = CreateShipWithScratchEngine(); + var ship = ShipTestBuilder.CreateShip(Container, CreatedObjects, "Ship") + .ParentedTo(TestRoot.transform) + .WithCustomCommand(Vector2.zero, 5, 5) + .WithCustomEngine(new Vector2(2f, 0f), 5, 5, new Resources(0, 2f, 0, 0, 0)) + .Build(initializeModules: true); + yield return null; var engine = (Engine)ship.AllModules[1]; @@ -150,95 +110,10 @@ public IEnumerator PostDamage_RoundTrip_KeepsDestroyedPixelsGone() Assert.IsFalse(restored.PixelatedRigidbody.IsPixel(new Vector2Int(3, 3))); } - private Ship CreateShipWithCommandAndCannon(GameObject cannonPrefab, string archetypeId) - { - var shipGo = ModuleFactory.CreateGameObject("Ship", CreatedObjects); - shipGo.transform.SetParent(TestRoot.transform); - shipGo.SetActive(false); - - CreateCommandModule(shipGo.transform); - - var cannonInstance = Object.Instantiate(cannonPrefab, shipGo.transform); - cannonInstance.transform.localPosition = new Vector3(2f, 0f, 0f); - cannonInstance.SetActive(true); - var cannonPixelRb = cannonInstance.GetComponent(); - cannonPixelRb.SetTextureFromColors(ModuleFactory.CreateSolidPixelGrid(5, 5)); - var cannonIdentity = cannonInstance.GetComponent(); - if (cannonIdentity == null) - cannonIdentity = cannonInstance.AddComponent(); - cannonIdentity.EnsureAssigned(ModuleOrigin.CatalogPrefab, archetypeId); - - var ship = ModuleFactory.WireShip(shipGo, Container); - ship.InitializeModules(); - - Container.InjectGameObject(shipGo); - - return ship; - } - - private Ship CreateShipWithScratchEngine() - { - var shipGo = ModuleFactory.CreateGameObject("Ship", CreatedObjects); - shipGo.transform.SetParent(TestRoot.transform); - shipGo.SetActive(false); - - CreateCommandModule(shipGo.transform); - - var engineGo = ModuleFactory.CreateModuleBase("Engine", shipGo.transform, new Vector2(2f, 0f), 0f, - Container, CreatedObjects, 5, 5); - var exhaustRoot = ModuleFactory.CreateGameObject("Exhaust", CreatedObjects); - exhaustRoot.transform.SetParent(engineGo.transform, false); - exhaustRoot.AddComponent(); - var engine = engineGo.AddComponent(); - engine.SetResources(new Resources(0, 2f, 0, 0, 0)); - var identity = engineGo.AddComponent(); - identity.EnsureAssigned(ModuleOrigin.Custom); - - var ship = ModuleFactory.WireShip(shipGo, Container); - ship.InitializeModules(); - - Container.InjectGameObject(shipGo); - - return ship; - } - - private void CreateCommandModule(Transform parent) - { - var commandGo = ModuleFactory.CreateModuleBase("Command", parent, Vector2.zero, 0f, Container, - CreatedObjects, 5, 5); - var command = commandGo.AddComponent(); - command.SetResources(new Resources(0, 0, 0, 0, 0)); - var identity = commandGo.AddComponent(); - identity.EnsureAssigned(ModuleOrigin.Custom); - } - - private GameObject CreateCannonPrefab(GameObject projectilePrefab, Sprite weaponSprite) - { - var go = ModuleFactory.CreateModuleBase("CannonPrefab", TestRoot.transform, Vector2.zero, 0f, - Container, CreatedObjects, 5, 5); - go.SetActive(false); - var cannon = go.AddComponent(); - cannon.SetResources(new Resources(0, 1, 0, 0, 0)); - SetPrivateField(cannon, "projectilePrefab", projectilePrefab); - SetPrivateField(cannon, "sprite", weaponSprite); - SetPrivateField(cannon, "reloadTime", 1.5f); - SetPrivateField(cannon, "projectileSpeed", 20f); - return go; - } - private static Sprite CreateTestSprite() { var texture = new Texture2D(2, 2); return Sprite.Create(texture, new Rect(0, 0, 2, 2), new Vector2(0.5f, 0.5f)); } - - private static void SetPrivateField(object target, string fieldName, T value) - { - var field = target.GetType().GetField(fieldName, - BindingFlags.Instance | BindingFlags.NonPublic); - if (field == null) - throw new UnityException($"Missing field '{fieldName}' on '{target.GetType().Name}'."); - field.SetValue(target, value); - } } -} \ No newline at end of file +} diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Factories.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Factories.meta new file mode 100644 index 00000000..79c3999d --- /dev/null +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Factories.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 99afaf59edf04717bba06fda9b8045c1 +timeCreated: 1781125637 \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/ModuleFactory.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ModuleFactory.cs similarity index 88% rename from Assets/Scripts/Ships/Tests/TestHelpers/ModuleFactory.cs rename to Assets/Scripts/Ships/Tests/TestHelpers/Factories/ModuleFactory.cs index c6aa3f16..88b67dca 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/ModuleFactory.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ModuleFactory.cs @@ -1,12 +1,14 @@ using System.Collections.Generic; +using Core.Ship; using Pixelation; using Ships.ModuleConnection; using Ships.Modules; using Ships.Systems.Resources; +using Ships.Tests.TestHelpers.Modules; using UnityEngine; using Zenject; -namespace Ships.Tests.TestHelpers +namespace Ships.Tests.TestHelpers.Factories { public static class ModuleFactory { @@ -103,5 +105,17 @@ public static GameObject CreateGameObject(string name, ICollection c createdObjects.Add(go); return go; } + + public static Command AddCommandModuleComponent(GameObject moduleGo) + { + return moduleGo.AddComponent(); + } + + public static TestModule AddTestModuleComponent(GameObject moduleGo, ModuleType type = ModuleType.Resources) + { + var testModule = moduleGo.AddComponent(); + testModule.SetModuleType(type); + return testModule; + } } } \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/ModuleFactory.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ModuleFactory.cs.meta similarity index 100% rename from Assets/Scripts/Ships/Tests/TestHelpers/ModuleFactory.cs.meta rename to Assets/Scripts/Ships/Tests/TestHelpers/Factories/ModuleFactory.cs.meta diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs new file mode 100644 index 00000000..4d185588 --- /dev/null +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs @@ -0,0 +1,235 @@ +using System.Collections.Generic; +using Core.Ship; +using Pixelation; +using Ships.Modules; +using Ships.Tests.TestHelpers.Proxies; +using UnityEngine; +using Zenject; +using Resources = Core.Ship.Resources; + +namespace Ships.Tests.TestHelpers.Factories +{ + public struct ShipLayoutResult + { + public Ship Ship { get; set; } + public Module CommandModule { get; set; } + public List OtherModules { get; set; } + } + + public sealed class ShipTestBuilder + { + private readonly DiContainer _container; + private readonly ICollection _createdObjects; + private readonly List _engines = new(); + private readonly Dictionary _modulesByName = new(); + private readonly List _otherModules = new(); + private readonly GameObject _shipGo; + private Module _commandModule; + private bool _deactivateBeforeWire; + private bool _injectGameObject = true; + private Transform _parent; + + private ShipTestBuilder(DiContainer container, ICollection createdObjects, string shipName) + { + _container = container; + _createdObjects = createdObjects; + _shipGo = ModuleFactory.CreateGameObject(shipName, createdObjects); + } + + public static ShipTestBuilder CreateShip(DiContainer container, ICollection createdObjects, + string shipName = "TestShip") + { + return new ShipTestBuilder(container, createdObjects, shipName); + } + + public ShipTestBuilder ParentedTo(Transform parent, bool deactivateBeforeWire = true) + { + _parent = parent; + _shipGo.transform.SetParent(parent); + if (deactivateBeforeWire) + _shipGo.SetActive(false); + return this; + } + + public ShipTestBuilder WithoutGameObjectInjection() + { + _injectGameObject = false; + return this; + } + + public ShipTestBuilder WithCommand(string name, Vector2 localPosition, int width, int height) + { + var moduleGo = ModuleFactory.CreateModuleBase(name, _shipGo.transform, localPosition, 0f, _container, + _createdObjects, width, height); + var command = ModuleFactory.AddCommandModuleComponent(moduleGo); + RegisterCommand(name, command); + return this; + } + + public ShipTestBuilder WithModule(string name, Vector2 localPosition, int width, int height, + ModuleType type = ModuleType.Resources) + { + var moduleGo = ModuleFactory.CreateModuleBase(name, _shipGo.transform, localPosition, 0f, _container, + _createdObjects, width, height); + var module = ModuleFactory.AddTestModuleComponent(moduleGo, type); + RegisterOtherModule(name, module); + return this; + } + + public ShipTestBuilder WithCrewModule(string name, Vector2 localPosition, int width, int height, + int crewNeeded, CrewSkillType mainSkill) + { + var moduleGo = ModuleFactory.CreateModuleBase(name, _shipGo.transform, localPosition, 0f, _container, + _createdObjects, width, height); + var testModule = ModuleFactory.AddTestModuleComponent(moduleGo); + testModule.SetMainSkillType(mainSkill); + testModule.SetResources(new Resources(0, 0, crewNeeded, 0, 0)); + RegisterOtherModule(name, testModule); + return this; + } + + public ShipTestBuilder WithEngineModule(Vector2 localPosition, float maxThrust, int width, int height, + float rotationZ = 0f, float gimbalRange = 45f) + { + ModuleFactory.CreateEngineModule(_shipGo.transform, localPosition, _container, _createdObjects, maxThrust, + width, height, rotationZ, gimbalRange); + var engine = _shipGo.transform.GetChild(_shipGo.transform.childCount - 1).GetComponent(); + _engines.Add(engine); + return this; + } + + public ShipTestBuilder WithPowerModule(Vector2 localPosition, int width, int height) + { + ModuleFactory.CreatePowerModule(_shipGo.transform, localPosition, _container, _createdObjects, width, + height); + return this; + } + + public ShipTestBuilder WithCustomCommand(Vector2 localPosition, int width, int height) + { + var commandGo = ModuleFactory.CreateModuleBase("Command", _shipGo.transform, localPosition, 0f, _container, + _createdObjects, width, height); + var command = ModuleFactory.AddCommandModuleComponent(commandGo); + command.SetResources(new Resources(0, 0, 0, 0, 0)); + var identity = commandGo.AddComponent(); + identity.EnsureAssigned(ModuleOrigin.Custom); + RegisterCommand("Command", command); + return this; + } + + public ShipTestBuilder WithCustomEngine(Vector2 localPosition, int width, int height, Resources resources) + { + var engineGo = ModuleFactory.CreateModuleBase("Engine", _shipGo.transform, localPosition, 0f, _container, + _createdObjects, width, height); + var exhaustRoot = ModuleFactory.CreateGameObject("Exhaust", _createdObjects); + exhaustRoot.transform.SetParent(engineGo.transform, false); + exhaustRoot.AddComponent(); + var engine = engineGo.AddComponent(); + engine.SetResources(resources); + var identity = engineGo.AddComponent(); + identity.EnsureAssigned(ModuleOrigin.Custom); + RegisterOtherModule("Engine", engine); + return this; + } + + public ShipTestBuilder WithInstantiatedCannon(GameObject cannonPrefab, Vector2 localPosition, + string archetypeId, + int pixelSize) + { + var cannonInstance = Object.Instantiate(cannonPrefab, _shipGo.transform); + cannonInstance.transform.localPosition = localPosition; + cannonInstance.SetActive(true); + var cannonPixelRb = cannonInstance.GetComponent(); + cannonPixelRb.SetTextureFromColors(ModuleFactory.CreateSolidPixelGrid(pixelSize, pixelSize)); + var cannonIdentity = cannonInstance.GetComponent(); + if (cannonIdentity == null) + cannonIdentity = cannonInstance.AddComponent(); + cannonIdentity.EnsureAssigned(ModuleOrigin.CatalogPrefab, archetypeId); + RegisterOtherModule("Cannon", cannonInstance.GetComponent()); + return this; + } + + public Module GetModule(string name) + { + return _modulesByName[name]; + } + + public ShipLayoutResult BuildLayoutResult(bool initializeModules = false) + { + var ship = WireShip(initializeModules); + return new ShipLayoutResult + { + Ship = ship, + CommandModule = _commandModule, + OtherModules = new List(_otherModules) + }; + } + + public Ship Build(bool initializeModules = false) + { + return WireShip(initializeModules); + } + + public T Build(bool initializeModules = false) where T : Ship + { + return WireShip(initializeModules); + } + + public ShipWithEnginesResult BuildWithEnginesResult() + { + var ship = WireShip(false); + return new ShipWithEnginesResult { Ship = ship, Engines = new List(_engines) }; + } + + public CommandWithEngineResult BuildCommandWithEngineResult() + { + var ship = WireShip(false); + return new CommandWithEngineResult + { + Ship = ship, + Command = _shipGo.GetComponentInChildren(), + Engine = _shipGo.GetComponentInChildren() + }; + } + + public static GameObject CreateCannonPrefab(DiContainer container, ICollection createdObjects, + Transform parent, GameObject projectilePrefab, Sprite weaponSprite, int pixelSize = 5) + { + var go = ModuleFactory.CreateModuleBase("CannonPrefab", parent, Vector2.zero, 0f, + container, createdObjects, pixelSize, pixelSize); + go.SetActive(false); + var cannon = go.AddComponent(); + cannon.SetResources(new Resources(0, 1, 0, 0, 0)); + cannon.InternalProjectilePrefab = projectilePrefab; + cannon.InternalSprite = weaponSprite; + cannon.InternalReloadTime = 1.5f; + cannon.InternalProjectileSpeed = 20f; + return go; + } + + private T WireShip(bool initializeModules) where T : Ship + { + if (_parent != null && _deactivateBeforeWire && !_shipGo.activeSelf) + _shipGo.SetActive(false); + + var ship = ModuleFactory.WireShip(_shipGo, _container); + if (initializeModules) + ship.InitializeModules(); + if (_injectGameObject) + _container.InjectGameObject(_shipGo); + return ship; + } + + private void RegisterCommand(string name, Command command) + { + _commandModule = command; + _modulesByName[name] = command; + } + + private void RegisterOtherModule(string name, Module module) + { + _otherModules.Add(module); + _modulesByName[name] = module; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs.meta new file mode 100644 index 00000000..063ea110 --- /dev/null +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 38505184e9fefc6afb81ad3bbd01c43a \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs new file mode 100644 index 00000000..8a662eba --- /dev/null +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using Ships; +using Ships.Modules; +using UnityEngine; +using Zenject; + +namespace Ships.Tests.TestHelpers.Factories +{ + public struct TwoModuleShipResult + { + public Ship Ship { get; set; } + public Command Command { get; set; } + public Module Other { get; set; } + + public void Deconstruct(out Ship ship, out Command command, out Module other) + { + ship = Ship; + command = Command; + other = Other; + } + } + + public struct EngineThrustSpec + { + public Vector2 LocalPosition; + public float LocalRotationZ; + public float MaxThrust; + } + + public struct ShipWithEnginesResult where T : Ship + { + public T Ship { get; set; } + public List Engines { get; set; } + } + + public struct CommandWithEngineResult + { + public Ship Ship { get; set; } + public Command Command { get; set; } + public Engine Engine { get; set; } + + public void Deconstruct(out Ship ship, out Command command, out Engine engine) + { + ship = Ship; + command = Command; + engine = Engine; + } + } + + public static class ShipTestFactory + { + private const int DefaultModulePixelSize = 5; + private const float DefaultModuleSpacing = 5f; + + public static TwoModuleShipResult CreateTwoModuleShip(DiContainer container, + ICollection createdObjects, int moduleWidth = DefaultModulePixelSize, + int moduleHeight = DefaultModulePixelSize) + { + var layout = ShipTestBuilder.CreateShip(container, createdObjects) + .WithCommand("Command", Vector2.zero, moduleWidth, moduleHeight) + .WithModule("Module2", new Vector2(moduleWidth, 0), moduleWidth, moduleHeight) + .BuildLayoutResult(); + + return new TwoModuleShipResult + { + Ship = layout.Ship, + Command = (Command)layout.CommandModule, + Other = layout.OtherModules[0] + }; + } + + public static Ship CreateShipWithCommandAndEngine(DiContainer container, ICollection createdObjects, + Transform parent = null, float engineMaxThrust = 100f, float engineSpacing = DefaultModuleSpacing, + int modulePixelSize = DefaultModulePixelSize) + { + var builder = ShipTestBuilder.CreateShip(container, createdObjects, "Ship"); + if (parent != null) + builder.ParentedTo(parent); + + return builder + .WithCommand("Command", Vector2.zero, modulePixelSize, modulePixelSize) + .WithEngineModule(new Vector2(engineSpacing, 0f), engineMaxThrust, modulePixelSize, modulePixelSize) + .Build(initializeModules: true); + } + } +} diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs.meta new file mode 100644 index 00000000..9a175abe --- /dev/null +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5ea8035d91979ee2a8b35a1720b40339 \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Fixtures.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Fixtures.meta new file mode 100644 index 00000000..e7aa0fcd --- /dev/null +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Fixtures.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 01d38f01faab4aaeaa80e26901098d52 +timeCreated: 1781125622 \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/ShipTestBase.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/ShipTestBase.cs similarity index 96% rename from Assets/Scripts/Ships/Tests/TestHelpers/ShipTestBase.cs rename to Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/ShipTestBase.cs index 014cb695..8aec3e79 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/ShipTestBase.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/ShipTestBase.cs @@ -7,7 +7,7 @@ using ZLinq; using Object = UnityEngine.Object; -namespace Ships.Tests.TestHelpers +namespace Ships.Tests.TestHelpers.Fixtures { public abstract class ShipTestBase { diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/ShipTestBase.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/ShipTestBase.cs.meta similarity index 100% rename from Assets/Scripts/Ships/Tests/TestHelpers/ShipTestBase.cs.meta rename to Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/ShipTestBase.cs.meta diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestContainerFactory.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/TestContainerFactory.cs similarity index 95% rename from Assets/Scripts/Ships/Tests/TestHelpers/TestContainerFactory.cs rename to Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/TestContainerFactory.cs index 3d6a0636..b1a18388 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/TestContainerFactory.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/TestContainerFactory.cs @@ -2,10 +2,11 @@ using Events.Collision; using Events.Ship; using NSubstitute; +using Ships.Tests.TestHelpers.Mocks; using UnityEngine; using Zenject; -namespace Ships.Tests.TestHelpers +namespace Ships.Tests.TestHelpers.Fixtures { public static class TestContainerFactory { diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestContainerFactory.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/TestContainerFactory.cs.meta similarity index 100% rename from Assets/Scripts/Ships/Tests/TestHelpers/TestContainerFactory.cs.meta rename to Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/TestContainerFactory.cs.meta diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Utils.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/Utils.cs similarity index 91% rename from Assets/Scripts/Ships/Tests/TestHelpers/Utils.cs rename to Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/Utils.cs index 876455fe..3fe27943 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/Utils.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/Utils.cs @@ -2,7 +2,7 @@ using System.Collections; using UnityEngine; -namespace Ships.Tests.TestHelpers +namespace Ships.Tests.TestHelpers.Fixtures { public static class Utils { diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Utils.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/Utils.cs.meta similarity index 100% rename from Assets/Scripts/Ships/Tests/TestHelpers/Utils.cs.meta rename to Assets/Scripts/Ships/Tests/TestHelpers/Fixtures/Utils.cs.meta diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Mocks.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks.meta new file mode 100644 index 00000000..43602fb1 --- /dev/null +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 20f5861d652240cb9241a84e38be19e9 +timeCreated: 1781125691 \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestContentCatalog.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestContentCatalog.cs new file mode 100644 index 00000000..0beb6f9b --- /dev/null +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestContentCatalog.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using Core.Services; +using UnityEngine; + +namespace Ships.Tests.TestHelpers.Mocks +{ + public sealed class TestContentCatalog : IGameContentCatalog + { + private readonly Dictionary _idToPrefab = new(); + private readonly Dictionary _idToSprite = new(); + private readonly Dictionary _prefabToId = new(); + private readonly Dictionary _spriteToId = new(); + + public bool TryGetPrefab(string contentId, out GameObject prefab) + { + return _idToPrefab.TryGetValue(contentId, out prefab); + } + + public bool TryGetContentId(GameObject prefab, out string contentId) + { + return _prefabToId.TryGetValue(prefab, out contentId); + } + + public bool TryGetSprite(string contentId, out Sprite sprite) + { + return _idToSprite.TryGetValue(contentId, out sprite); + } + + public bool TryGetSpriteContentId(Sprite sprite, out string contentId) + { + return _spriteToId.TryGetValue(sprite, out contentId); + } + + public void AddPrefab(string id, GameObject prefab) + { + _idToPrefab[id] = prefab; + _prefabToId[prefab] = id; + } + + public void AddSprite(string id, Sprite sprite) + { + _idToSprite[id] = sprite; + _spriteToId[sprite] = id; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestContentCatalog.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestContentCatalog.cs.meta similarity index 100% rename from Assets/Scripts/Ships/Tests/TestHelpers/TestContentCatalog.cs.meta rename to Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestContentCatalog.cs.meta diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestDebrisSpawner.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestDebrisSpawner.cs similarity index 96% rename from Assets/Scripts/Ships/Tests/TestHelpers/TestDebrisSpawner.cs rename to Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestDebrisSpawner.cs index 710ec58e..023722d2 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/TestDebrisSpawner.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestDebrisSpawner.cs @@ -3,7 +3,7 @@ using Core.Services; using UnityEngine; -namespace Ships.Tests.TestHelpers +namespace Ships.Tests.TestHelpers.Mocks { public class TestDebrisSpawner : IDebrisSpawner { diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestDebrisSpawner.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestDebrisSpawner.cs.meta similarity index 100% rename from Assets/Scripts/Ships/Tests/TestHelpers/TestDebrisSpawner.cs.meta rename to Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestDebrisSpawner.cs.meta diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestMapInfo.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestMapInfo.cs similarity index 86% rename from Assets/Scripts/Ships/Tests/TestHelpers/TestMapInfo.cs rename to Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestMapInfo.cs index 11d5bfe5..9ffe40d2 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/TestMapInfo.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestMapInfo.cs @@ -1,7 +1,7 @@ using Core.Services; using UnityEngine; -namespace Ships.Tests.TestHelpers +namespace Ships.Tests.TestHelpers.Mocks { public class TestMapInfo : IMapInfo { diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestMapInfo.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestMapInfo.cs.meta similarity index 100% rename from Assets/Scripts/Ships/Tests/TestHelpers/TestMapInfo.cs.meta rename to Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestMapInfo.cs.meta diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestModuleCatalog.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestModuleCatalog.cs new file mode 100644 index 00000000..e7df2453 --- /dev/null +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestModuleCatalog.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using Core.Services; +using UnityEngine; + +namespace Ships.Tests.TestHelpers.Mocks +{ + public sealed class TestModuleCatalog : IShipModuleCatalog + { + private readonly Dictionary _idToPrefab = new(); + + public bool TryGetModulePrefab(string archetypeId, out GameObject prefab) + { + return _idToPrefab.TryGetValue(archetypeId, out prefab); + } + + public void Add(string id, GameObject prefab) + { + _idToPrefab[id] = prefab; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestModuleCatalog.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestModuleCatalog.cs.meta similarity index 100% rename from Assets/Scripts/Ships/Tests/TestHelpers/TestModuleCatalog.cs.meta rename to Assets/Scripts/Ships/Tests/TestHelpers/Mocks/TestModuleCatalog.cs.meta diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Modules.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Modules.meta new file mode 100644 index 00000000..22ba68de --- /dev/null +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Modules.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c8cf18f290dd48508b466808d04f854a +timeCreated: 1781125672 \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestModule.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Modules/TestModule.cs similarity index 90% rename from Assets/Scripts/Ships/Tests/TestHelpers/TestModule.cs rename to Assets/Scripts/Ships/Tests/TestHelpers/Modules/TestModule.cs index 57e63ae4..68ed44a5 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/TestModule.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Modules/TestModule.cs @@ -1,7 +1,7 @@ using Core.Ship; using Ships.Modules; -namespace Ships.Tests.TestHelpers +namespace Ships.Tests.TestHelpers.Modules { public class TestModule : Module { diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestModule.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Modules/TestModule.cs.meta similarity index 100% rename from Assets/Scripts/Ships/Tests/TestHelpers/TestModule.cs.meta rename to Assets/Scripts/Ships/Tests/TestHelpers/Modules/TestModule.cs.meta diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestPowerModule.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Modules/TestPowerModule.cs similarity index 88% rename from Assets/Scripts/Ships/Tests/TestHelpers/TestPowerModule.cs rename to Assets/Scripts/Ships/Tests/TestHelpers/Modules/TestPowerModule.cs index 99b7d5f4..f953f36b 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/TestPowerModule.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Modules/TestPowerModule.cs @@ -1,7 +1,7 @@ using Core.Ship; using Ships.Modules; -namespace Ships.Tests.TestHelpers +namespace Ships.Tests.TestHelpers.Modules { public sealed class TestPowerModule : Module { diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestPowerModule.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Modules/TestPowerModule.cs.meta similarity index 100% rename from Assets/Scripts/Ships/Tests/TestHelpers/TestPowerModule.cs.meta rename to Assets/Scripts/Ships/Tests/TestHelpers/Modules/TestPowerModule.cs.meta diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Proxies.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Proxies.meta new file mode 100644 index 00000000..8a45562c --- /dev/null +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Proxies.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e059cd3e2a624c86882b32524658c276 +timeCreated: 1781125662 \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/MovableShipTestProxy.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Proxies/MovableShipTestProxy.cs similarity index 94% rename from Assets/Scripts/Ships/Tests/TestHelpers/MovableShipTestProxy.cs rename to Assets/Scripts/Ships/Tests/TestHelpers/Proxies/MovableShipTestProxy.cs index d5547a7f..e851efb5 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/MovableShipTestProxy.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Proxies/MovableShipTestProxy.cs @@ -1,6 +1,6 @@ using UnityEngine; -namespace Ships.Tests.TestHelpers +namespace Ships.Tests.TestHelpers.Proxies { public sealed class MovableShipTestProxy : Ship { @@ -23,4 +23,4 @@ protected override void ApplyMovementPhysics() SasEnabled)); } } -} +} \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/MovableShipTestProxy.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Proxies/MovableShipTestProxy.cs.meta similarity index 100% rename from Assets/Scripts/Ships/Tests/TestHelpers/MovableShipTestProxy.cs.meta rename to Assets/Scripts/Ships/Tests/TestHelpers/Proxies/MovableShipTestProxy.cs.meta diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/ShipTestProxy.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Proxies/ShipTestProxy.cs similarity index 75% rename from Assets/Scripts/Ships/Tests/TestHelpers/ShipTestProxy.cs rename to Assets/Scripts/Ships/Tests/TestHelpers/Proxies/ShipTestProxy.cs index 676df4ba..234c93db 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/ShipTestProxy.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Proxies/ShipTestProxy.cs @@ -1,4 +1,4 @@ -namespace Ships.Tests.TestHelpers +namespace Ships.Tests.TestHelpers.Proxies { public sealed class ShipTestProxy : Ship { @@ -6,4 +6,4 @@ protected override void ApplyMovementPhysics() { } } -} +} \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/ShipTestProxy.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/Proxies/ShipTestProxy.cs.meta similarity index 100% rename from Assets/Scripts/Ships/Tests/TestHelpers/ShipTestProxy.cs.meta rename to Assets/Scripts/Ships/Tests/TestHelpers/Proxies/ShipTestProxy.cs.meta diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/SmallMovableShipTestFactory.cs b/Assets/Scripts/Ships/Tests/TestHelpers/SmallMovableShipTestFactory.cs deleted file mode 100644 index 8b9bd921..00000000 --- a/Assets/Scripts/Ships/Tests/TestHelpers/SmallMovableShipTestFactory.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Collections.Generic; -using Ships.ModuleConnection; -using Ships.Systems.Resources; -using UnityEngine; -using Zenject; - -namespace Ships.Tests.TestHelpers -{ - public static class SmallMovableShipTestFactory - { - private const int ModulePixelSize = 5; - private const float ModuleSpacing = 5f; - private const float EngineMaxThrust = 800f; - - public static MovableShipTestProxy Create(DiContainer container, ICollection createdObjects) - { - var shipGo = ModuleFactory.CreateGameObject("GameplayTestShip", createdObjects); - - ModuleFactory.CreateCommandModule(shipGo.transform, Vector2.zero, container, createdObjects, - ModulePixelSize, ModulePixelSize); - ModuleFactory.CreatePowerModule(shipGo.transform, new Vector2(0f, ModuleSpacing), container, - createdObjects, ModulePixelSize, ModulePixelSize); - ModuleFactory.CreateEngineModule(shipGo.transform, new Vector2(ModuleSpacing, 0f), container, - createdObjects, EngineMaxThrust, ModulePixelSize, ModulePixelSize); - ModuleFactory.CreateEngineModule(shipGo.transform, new Vector2(-ModuleSpacing, 0f), container, - createdObjects, EngineMaxThrust, ModulePixelSize, ModulePixelSize); - - var connectionFactory = shipGo.AddComponent(); - shipGo.AddComponent(); - - shipGo.SetActive(false); - var ship = shipGo.AddComponent(); - container.Inject(ship); - ship.ModuleConnectionFactoryForTesting = connectionFactory; - ship.ConfigureAllocatorForTesting(true, 14, 1f, 0.4f, - 0.02f); - shipGo.SetActive(true); - - container.InjectGameObject(shipGo); - - return ship; - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/SmallMovableShipTestFactory.cs.meta b/Assets/Scripts/Ships/Tests/TestHelpers/SmallMovableShipTestFactory.cs.meta deleted file mode 100644 index e63f8209..00000000 --- a/Assets/Scripts/Ships/Tests/TestHelpers/SmallMovableShipTestFactory.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 0488fae057d1278dfa0a6bcb1978c255 \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestContentCatalog.cs b/Assets/Scripts/Ships/Tests/TestHelpers/TestContentCatalog.cs deleted file mode 100644 index f2336ba9..00000000 --- a/Assets/Scripts/Ships/Tests/TestHelpers/TestContentCatalog.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Core.Services; -using UnityEngine; - -namespace Ships.Tests.TestHelpers -{ - public sealed class TestContentCatalog : IGameContentCatalog - { - public bool TryGetPrefab(string contentId, out GameObject prefab) - { - prefab = null; - return false; - } - - public bool TryGetContentId(GameObject prefab, out string contentId) - { - contentId = null; - return false; - } - - public bool TryGetSprite(string contentId, out Sprite sprite) - { - sprite = null; - return false; - } - - public bool TryGetSpriteContentId(Sprite sprite, out string contentId) - { - contentId = null; - return false; - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/TestModuleCatalog.cs b/Assets/Scripts/Ships/Tests/TestHelpers/TestModuleCatalog.cs deleted file mode 100644 index f530ad42..00000000 --- a/Assets/Scripts/Ships/Tests/TestHelpers/TestModuleCatalog.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Core.Services; -using UnityEngine; - -namespace Ships.Tests.TestHelpers -{ - public sealed class TestModuleCatalog : IShipModuleCatalog - { - public bool TryGetModulePrefab(string archetypeId, out GameObject prefab) - { - prefab = null; - return false; - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/UI/MainGame/PauseMenuController.cs b/Assets/Scripts/UI/MainGame/PauseMenuController.cs index 58c63592..32be8bd3 100644 --- a/Assets/Scripts/UI/MainGame/PauseMenuController.cs +++ b/Assets/Scripts/UI/MainGame/PauseMenuController.cs @@ -50,7 +50,7 @@ private void LateUpdate() private void OnEnable() { if (uiDocument == null || uiDocument.rootVisualElement == null) - return; + throw new UnityException("[PauseMenuController] UI Document not set."); _root = uiDocument.rootVisualElement; InitializePauseUi(); From 185911231d11592c26838ec64c258bd6b3dfae8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kub=C5=9B?= Date: Thu, 11 Jun 2026 21:28:06 +0200 Subject: [PATCH 2/2] fix(ships): pr fixes --- Assets/Scripts/E2E/E2ETestBase.cs | 2 +- Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs | 1 - Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs | 1 - Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs | 1 - .../Ships/Tests/TestHelpers/Factories/ModuleFactory.cs | 8 +++++--- .../Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs | 9 ++------- .../Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs | 1 - 7 files changed, 8 insertions(+), 15 deletions(-) diff --git a/Assets/Scripts/E2E/E2ETestBase.cs b/Assets/Scripts/E2E/E2ETestBase.cs index 676da165..dd7ea17c 100644 --- a/Assets/Scripts/E2E/E2ETestBase.cs +++ b/Assets/Scripts/E2E/E2ETestBase.cs @@ -143,7 +143,7 @@ protected Team CreateTeam(string name, int layer) protected AIShip CreateAIShip(string name, Team team, Vector2 position, bool withWeapons, bool withEngines) { - var shipGo = ModuleFactory.CreateGameObject(name, CreatedObjects); + var shipGo = ModuleFactory.CreateGameObject(name, CreatedObjects, Container); shipGo.layer = team.Layer; shipGo.transform.position = position; diff --git a/Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs b/Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs index 324f4ca0..68e7660f 100644 --- a/Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs +++ b/Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs @@ -1,7 +1,6 @@ using System.Collections; using System.Collections.Generic; using NUnit.Framework; -using Ships; using Ships.Modules; using Ships.Tests.TestHelpers.Factories; using Ships.Tests.TestHelpers.Fixtures; diff --git a/Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs b/Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs index 317b3ebf..2b7d5aa5 100644 --- a/Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipCrewAssignmentTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using Core.Ship; using NUnit.Framework; -using Ships; using Ships.Tests.TestHelpers.Factories; using Ships.Tests.TestHelpers.Fixtures; using UnityEngine; diff --git a/Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs b/Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs index eff41202..c89dc0b4 100644 --- a/Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs +++ b/Assets/Scripts/Ships/Tests/ShipSnapshotServiceTests.cs @@ -2,7 +2,6 @@ using Core.Ship; using NUnit.Framework; using Services; -using Ships; using Ships.Modules; using Ships.Tests.TestHelpers.Factories; using Ships.Tests.TestHelpers.Fixtures; diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ModuleFactory.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ModuleFactory.cs index 88b67dca..65a7e5d1 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ModuleFactory.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ModuleFactory.cs @@ -37,7 +37,7 @@ public static void CreateEngineModule(Transform parent, Vector2 localPosition, D var engineGo = CreateModuleBase("Engine", parent, localPosition, localRotationZ, container, createdObjects, modulePixelWidth, modulePixelHeight); - var particleRoot = CreateGameObject("EngineExhaust", createdObjects); + var particleRoot = CreateGameObject("EngineExhaust", createdObjects, container); particleRoot.transform.SetParent(engineGo.transform, false); particleRoot.AddComponent(); @@ -49,7 +49,7 @@ public static GameObject CreateModuleBase(string name, Transform parent, Vector2 float localRotationZ, DiContainer container, ICollection createdObjects, int modulePixelWidth, int modulePixelHeight) { - var moduleGo = CreateGameObject(name, createdObjects); + var moduleGo = CreateGameObject(name, createdObjects, container); moduleGo.transform.SetParent(parent); moduleGo.transform.localPosition = localPosition; moduleGo.transform.localRotation = Quaternion.Euler(0f, 0f, localRotationZ); @@ -99,10 +99,12 @@ public static T WireShip(GameObject shipGo, DiContainer container) where T : return ship; } - public static GameObject CreateGameObject(string name, ICollection createdObjects) + public static GameObject CreateGameObject(string name, ICollection createdObjects, + DiContainer container) { var go = new GameObject(name); createdObjects.Add(go); + container.Inject(go); return go; } diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs index 4d185588..56953f1f 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestBuilder.cs @@ -27,13 +27,12 @@ public sealed class ShipTestBuilder private Module _commandModule; private bool _deactivateBeforeWire; private bool _injectGameObject = true; - private Transform _parent; private ShipTestBuilder(DiContainer container, ICollection createdObjects, string shipName) { _container = container; _createdObjects = createdObjects; - _shipGo = ModuleFactory.CreateGameObject(shipName, createdObjects); + _shipGo = ModuleFactory.CreateGameObject(shipName, createdObjects, container); } public static ShipTestBuilder CreateShip(DiContainer container, ICollection createdObjects, @@ -44,7 +43,6 @@ public static ShipTestBuilder CreateShip(DiContainer container, ICollection(); var engine = engineGo.AddComponent(); @@ -209,9 +207,6 @@ public static GameObject CreateCannonPrefab(DiContainer container, ICollection(bool initializeModules) where T : Ship { - if (_parent != null && _deactivateBeforeWire && !_shipGo.activeSelf) - _shipGo.SetActive(false); - var ship = ModuleFactory.WireShip(_shipGo, _container); if (initializeModules) ship.InitializeModules(); diff --git a/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs index 8a662eba..b02269de 100644 --- a/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs +++ b/Assets/Scripts/Ships/Tests/TestHelpers/Factories/ShipTestFactory.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Ships; using Ships.Modules; using UnityEngine; using Zenject;