]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add reagent dispenser BUI test (#15443)
authorLeon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Sun, 16 Apr 2023 16:34:36 +0000 (04:34 +1200)
committerGitHub <noreply@github.com>
Sun, 16 Apr 2023 16:34:36 +0000 (02:34 +1000)
Content.IntegrationTests/Tests/Chemistry/DispenserTest.cs [new file with mode: 0644]
Content.IntegrationTests/Tests/Interaction/InteractionTest.EntitySpecifier.cs
Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs
Content.IntegrationTests/Tests/Interaction/InteractionTest.cs

diff --git a/Content.IntegrationTests/Tests/Chemistry/DispenserTest.cs b/Content.IntegrationTests/Tests/Chemistry/DispenserTest.cs
new file mode 100644 (file)
index 0000000..cbe3ee4
--- /dev/null
@@ -0,0 +1,35 @@
+using System.Threading.Tasks;
+using Content.IntegrationTests.Tests.Interaction;
+using Content.Shared.Chemistry;
+using Content.Shared.Containers.ItemSlots;
+using NUnit.Framework;
+
+namespace Content.IntegrationTests.Tests.Chemistry;
+
+public sealed class DispenserTest : InteractionTest
+{
+    /// <summary>
+    ///     Basic test that checks that a beaker can be inserted and ejected from a dispenser.
+    /// </summary>
+    [Test]
+    public async Task InsertEjectBuiTest()
+    {
+        await SpawnTarget("chem_dispenser");
+        ToggleNeedPower();
+
+        // Insert beaker
+        await Interact("Beaker");
+        Assert.IsNull(Hands.ActiveHandEntity);
+
+        // Open BUI
+        await Interact("");
+
+        // Eject beaker via BUI.
+        var ev = new ItemSlotButtonPressedEvent(SharedChemMaster.InputSlotName);
+        await SendBui(ReagentDispenserUiKey.Key, ev);
+
+        // Beaker is back in the player's hands
+        Assert.IsNotNull(Hands.ActiveHandEntity);
+        AssertPrototype("Beaker", Hands.ActiveHandEntity);
+    }
+}
index 3949389919b0dcdaa3694a823b60570b1eaf087a..2e8314ec97514c872345f67ee7a29ad901865cc1 100644 (file)
@@ -62,6 +62,10 @@ public abstract partial class InteractionTest
                 return;
 
             Converted = true;
+
+            if (string.IsNullOrWhiteSpace(Prototype))
+                return;
+
             if (protoMan.HasIndex<StackPrototype>(Prototype))
                 return;
 
@@ -121,6 +125,6 @@ public abstract partial class InteractionTest
         var meta = SEntMan.GetComponent<MetaDataComponent>(uid);
         Assert.NotNull(meta.EntityPrototype);
 
-        return new (meta.EntityPrototype.ID, 1) { Converted = true };
+        return new (meta.EntityPrototype!.ID, 1) { Converted = true };
     }
 }
index d07af1dd529cbe6a9389fedabe5c2963293e3a75..634755062bae5a0511176535fe512b6374e1bbcb 100644 (file)
@@ -1,14 +1,17 @@
 #nullable enable
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Threading.Tasks;
 using Content.Client.Construction;
 using Content.Server.Construction.Components;
+using Content.Server.Power.Components;
 using Content.Server.Tools.Components;
 using Content.Shared.Construction.Prototypes;
 using Content.Shared.Item;
 using NUnit.Framework;
+using Robust.Client.GameObjects;
 using Robust.Shared.GameObjects;
 using Robust.Shared.Log;
 using Robust.Shared.Map;
@@ -139,7 +142,7 @@ public abstract partial class InteractionTest
 
         await DeleteHeldEntity();
 
-        if (entity == null)
+        if (entity == null || string.IsNullOrWhiteSpace(entity.Prototype))
         {
             await RunTicks(1);
             Assert.That(Hands.ActiveHandEntity == null);
@@ -238,13 +241,19 @@ public abstract partial class InteractionTest
     /// <summary>
     /// Place an entity prototype into the players hand and interact with the given entity (or target position)
     /// </summary>
-    protected async Task Interact(string? id, int quantity = 1, bool shouldSucceed = true, bool awaitDoAfters = true)
-        => await Interact(id == null ? null : (id, quantity), shouldSucceed, awaitDoAfters);
+    /// <remarks>
+    /// Empty strings imply empty hands.
+    /// </remarks>
+    protected async Task Interact(string id, int quantity = 1, bool shouldSucceed = true, bool awaitDoAfters = true)
+        => await Interact((id, quantity), shouldSucceed, awaitDoAfters);
 
     /// <summary>
     /// Place an entity prototype into the players hand and interact with the given entity (or target position)
     /// </summary>
-    protected async Task Interact(EntitySpecifier? entity, bool shouldSucceed = true, bool awaitDoAfters = true)
+    /// <remarks>
+    /// Empty strings imply empty hands.
+    /// </remarks>
+    protected async Task Interact(EntitySpecifier entity, bool shouldSucceed = true, bool awaitDoAfters = true)
     {
         // For every interaction, we will also examine the entity, just in case this breaks something, somehow.
         // (e.g., servers attempt to assemble construction examine hints).
@@ -376,7 +385,10 @@ public abstract partial class InteractionTest
     /// <summary>
     /// Variant of <see cref="InteractUsing"/> that performs several interactions using different entities.
     /// </summary>
-    protected async Task Interact(params EntitySpecifier?[] specifiers)
+    /// <remarks>
+    /// Empty strings imply empty hands.
+    /// </remarks>
+    protected async Task Interact(params EntitySpecifier[] specifiers)
     {
         foreach (var spec in specifiers)
         {
@@ -386,32 +398,60 @@ public abstract partial class InteractionTest
 
     #region Asserts
 
-    protected void AssertPrototype(string? prototype)
+    protected void AssertPrototype(string? prototype, EntityUid? target = null)
     {
-        var meta = Comp<MetaDataComponent>();
+        target ??= Target;
+        if (target == null)
+        {
+            Assert.Fail("No target specified");
+            return;
+        }
+
+        var meta = SEntMan.GetComponent<MetaDataComponent>(target.Value);
         Assert.That(meta.EntityPrototype?.ID, Is.EqualTo(prototype));
     }
 
-    protected void AssertAnchored(bool anchored = true)
+    protected void AssertAnchored(bool anchored = true, EntityUid? target = null)
     {
-        var sXform = SEntMan.GetComponent<TransformComponent>(Target!.Value);
-        var cXform = CEntMan.GetComponent<TransformComponent>(Target.Value);
+        target ??= Target;
+        if (target == null)
+        {
+            Assert.Fail("No target specified");
+            return;
+        }
+
+        var sXform = SEntMan.GetComponent<TransformComponent>(target.Value);
+        var cXform = CEntMan.GetComponent<TransformComponent>(target.Value);
         Assert.That(sXform.Anchored, Is.EqualTo(anchored));
         Assert.That(cXform.Anchored, Is.EqualTo(anchored));
     }
 
-    protected void AssertDeleted(bool deleted = true)
+    protected void AssertDeleted(bool deleted = true, EntityUid? target = null)
     {
-        Assert.That(SEntMan.Deleted(Target), Is.EqualTo(deleted));
-        Assert.That(CEntMan.Deleted(Target), Is.EqualTo(deleted));
+        target ??= Target;
+        if (target == null)
+        {
+            Assert.Fail("No target specified");
+            return;
+        }
+
+        Assert.That(SEntMan.Deleted(target), Is.EqualTo(deleted));
+        Assert.That(CEntMan.Deleted(target), Is.EqualTo(deleted));
     }
 
     /// <summary>
     /// Assert whether or not the target has the given component.
     /// </summary>
-    protected void AssertComp<T>(bool hasComp = true)
+    protected void AssertComp<T>(bool hasComp = true, EntityUid? target = null)
     {
-        Assert.That(SEntMan.HasComponent<T>(Target), Is.EqualTo(hasComp));
+        target ??= Target;
+        if (target == null)
+        {
+            Assert.Fail("No target specified");
+            return;
+        }
+
+        Assert.That(SEntMan.HasComponent<T>(target), Is.EqualTo(hasComp));
     }
 
     /// <summary>
@@ -553,7 +593,6 @@ public abstract partial class InteractionTest
 
     #endregion
 
-
     /// <summary>
     /// List of currently active DoAfters on the player.
     /// </summary>
@@ -563,7 +602,14 @@ public abstract partial class InteractionTest
     /// <summary>
     /// Convenience method to get components on the target. Returns SERVER-SIDE components.
     /// </summary>
-    protected T Comp<T>() => SEntMan.GetComponent<T>(Target!.Value);
+    protected T Comp<T>(EntityUid? target = null)
+    {
+        target ??= Target;
+        if (target == null)
+            Assert.Fail("No target specified");
+
+        return SEntMan.GetComponent<T>(target!.Value);
+    }
 
     /// <summary>
     /// Set the tile at the target position to some prototype.
@@ -611,4 +657,77 @@ public abstract partial class InteractionTest
 
     protected async Task RunSeconds(float seconds)
         => await RunTicks((int) Math.Ceiling(seconds / TickPeriod));
+
+    #region BUI
+    /// <summary>
+    ///     Sends a bui message using the given bui key.
+    /// </summary>
+    protected async Task SendBui(Enum key, BoundUserInterfaceMessage msg, EntityUid? target = null)
+    {
+        if (!TryGetBui(key, out var bui))
+            return;
+
+        await Client.WaitPost(() => bui.SendMessage(msg));
+
+        // allow for client -> server and server -> client messages to be sent.
+        await RunTicks(15);
+    }
+
+    /// <summary>
+    ///     Sends a bui message using the given bui key.
+    /// </summary>
+    protected async Task CloseBui(Enum key, EntityUid? target = null)
+    {
+        if (!TryGetBui(key, out var bui))
+            return;
+
+        await Client.WaitPost(() => bui.Close());
+
+        // allow for client -> server and server -> client messages to be sent.
+        await RunTicks(15);
+    }
+
+    protected bool TryGetBui(Enum key, [NotNullWhen(true)] out BoundUserInterface? bui, EntityUid? target = null, bool shouldSucceed = true)
+    {
+        bui = null;
+        target ??= Target;
+        if (target == null)
+        {
+            Assert.Fail("No target specified");
+            return false;
+        }
+
+        if (!CEntMan.TryGetComponent(target, out ClientUserInterfaceComponent? ui))
+        {
+            if (shouldSucceed)
+                Assert.Fail($"Entity {SEntMan.ToPrettyString(target.Value)} does not have a bui component");
+            return false;
+        }
+
+        var first = ui.Interfaces.First();
+
+
+        bui = ui.Interfaces.FirstOrDefault(x => x.UiKey.Equals(key));
+        if (bui == null)
+        {
+            if (shouldSucceed)
+                Assert.Fail($"Entity {SEntMan.ToPrettyString(target.Value)} does not have an open bui with key {key.GetType()}.{key}.");
+            return false;
+        }
+
+        Assert.That(shouldSucceed, Is.True);
+        return true;
+    }
+
+    #endregion
+
+    #region Power
+
+    protected void ToggleNeedPower(EntityUid? target = null)
+    {
+        var comp = Comp<ApcPowerReceiverComponent>(target);
+        comp.NeedsPower = !comp.NeedsPower;
+    }
+
+    #endregion
 }
index 582e68aac7f6f7b3fc87c7408fffc581b1dec9d3..16f6c71ca004f9a86f9ce0a33d37bc04b0c2ebf4 100644 (file)
@@ -13,6 +13,7 @@ using Content.Shared.Hands.Components;
 using Content.Shared.Hands.EntitySystems;
 using Content.Shared.Interaction;
 using NUnit.Framework;
+using Robust.Client.GameObjects;
 using Robust.Shared.GameObjects;
 using Robust.Shared.Map;
 using Robust.Shared.Prototypes;
@@ -97,11 +98,12 @@ public abstract partial class InteractionTest
     // player components
     protected HandsComponent Hands = default!;
     protected DoAfterComponent DoAfters = default!;
+    protected UserInterfaceSystem CUISystem = default!;
 
     public float TickPeriod => (float)Timing.TickPeriod.TotalSeconds;
 
     [SetUp]
-    public async Task Setup()
+    public virtual async Task Setup()
     {
         PairTracker = await PoolManager.GetServerClient(new PoolSettings());
 
@@ -126,6 +128,7 @@ public abstract partial class InteractionTest
         CTestSystem = CEntMan.System<InteractionTestSystem>();
         CConSys = CEntMan.System<ConstructionSystem>();
         ExamineSys = CEntMan.System<ExamineSystem>();
+        CUISystem = CEntMan.System<UserInterfaceSystem>();
 
         // Setup map.
         MapData = await PoolManager.CreateTestMap(PairTracker);
@@ -189,7 +192,7 @@ public abstract partial class InteractionTest
     }
 
     [TearDown]
-    public async Task Cleanup()
+    public virtual async Task Cleanup()
     {
         await Server.WaitPost(() => MapMan.DeleteMap(MapId));
         await PairTracker.CleanReturnAsync();