diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs index 3302b1bafc..8a5859fe06 100644 --- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs +++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs @@ -264,9 +264,10 @@ public abstract partial class InteractionTest /// The entity or stack prototype to spawn and place into the users hand /// The number of entities to spawn. If the prototype is a stack, this sets the stack count. /// Whether or not to wait for any do-afters to complete - protected async Task InteractUsing(string id, int quantity = 1, bool awaitDoAfters = true) + /// If true, perform an alternate interaction instead of a standard one. + protected async Task InteractUsing(string id, int quantity = 1, bool awaitDoAfters = true, bool altInteract = false) { - await InteractUsing((id, quantity), awaitDoAfters); + await InteractUsing((id, quantity), awaitDoAfters, altInteract); } /// @@ -274,7 +275,8 @@ public abstract partial class InteractionTest /// /// The entity type & quantity to spawn and place into the users hand /// Whether or not to wait for any do-afters to complete - protected async Task InteractUsing(EntitySpecifier entity, bool awaitDoAfters = true) + /// If true, perform an alternate interaction instead of a standard one. + protected async Task InteractUsing(EntitySpecifier entity, bool awaitDoAfters = true, bool altInteract = false) { // 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). @@ -284,18 +286,19 @@ public abstract partial class InteractionTest } await PlaceInHands(entity); - await Interact(awaitDoAfters); + await Interact(awaitDoAfters, altInteract); } /// /// Interact with an entity using the currently held entity. /// /// Whether or not to wait for any do-afters to complete - protected async Task Interact(bool awaitDoAfters = true) + /// If true, performs an alternate interaction instead of a standard one. + protected async Task Interact(bool awaitDoAfters = true, bool altInteract = false) { if (Target == null || !Target.Value.IsClientSide()) { - await Interact(Target, TargetCoords, awaitDoAfters); + await Interact(Target, TargetCoords, awaitDoAfters, altInteract); return; } @@ -311,23 +314,23 @@ public abstract partial class InteractionTest await CheckTargetChange(); } - /// - protected async Task Interact(NetEntity? target, NetCoordinates coordinates, bool awaitDoAfters = true) + /// + protected async Task Interact(NetEntity? target, NetCoordinates coordinates, bool awaitDoAfters = true, bool altInteract = false) { Assert.That(SEntMan.TryGetEntity(target, out var sTarget) || target == null); var coords = SEntMan.GetCoordinates(coordinates); Assert.That(coords.IsValid(SEntMan)); - await Interact(sTarget, coords, awaitDoAfters); + await Interact(sTarget, coords, awaitDoAfters, altInteract); } /// /// Interact with an entity using the currently held entity. /// - protected async Task Interact(EntityUid? target, EntityCoordinates coordinates, bool awaitDoAfters = true) + protected async Task Interact(EntityUid? target, EntityCoordinates coordinates, bool awaitDoAfters = true, bool altInteract = false) { Assert.That(SEntMan.TryGetEntity(Player, out var player)); - await Server.WaitPost(() => InteractSys.UserInteraction(player!.Value, coordinates, target)); + await Server.WaitPost(() => InteractSys.UserInteraction(player!.Value, coordinates, target, altInteract: altInteract)); await RunTicks(1); if (awaitDoAfters) diff --git a/Content.IntegrationTests/Tests/Nutrition/WaterCoolerInteractionTest.cs b/Content.IntegrationTests/Tests/Nutrition/WaterCoolerInteractionTest.cs new file mode 100644 index 0000000000..c15de639de --- /dev/null +++ b/Content.IntegrationTests/Tests/Nutrition/WaterCoolerInteractionTest.cs @@ -0,0 +1,99 @@ +using Content.IntegrationTests.Tests.Interaction; +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; +using Content.Shared.Storage.Components; +using Robust.Shared.Prototypes; + +namespace Content.IntegrationTests.Tests.Nutrition; + +public sealed class WaterCoolerInteractionTest : InteractionTest +{ + /// + /// ProtoId of the water cooler entity. + /// + private static readonly EntProtoId WaterCooler = "WaterCooler"; + + /// + /// ProtoId of the paper cup entity dispensed by the water cooler. + /// + private static readonly EntProtoId PaperCup = "DrinkWaterCup"; + + /// + /// ProtoId of the water reagent that is stored in the water cooler. + /// + private static readonly ProtoId Water = "Water"; + + /// + /// Spawns a water cooler and tests that the player can retrieve a paper cup + /// by interacting with it, and can return the paper cup by alt-interacting with it. + /// + [Test] + public async Task GetAndReturnCup() + { + // Spawn the water cooler + var cooler = await SpawnTarget(WaterCooler); + + // Record how many paper cups are in the cooler + var binComp = Comp(cooler); + var initialCount = binComp.Items.Count; + Assert.That(binComp.Items, Is.Not.Empty, "Water cooler didn't start with any cups"); + + // Interact with the water cooler using an empty hand to grab a paper cup + await Interact(); + + var cup = HandSys.GetActiveItem((SPlayer, Hands)); + + Assert.Multiple(() => + { + // Make sure the player is now holding a cup + Assert.That(cup, Is.Not.Null, "Player's hand is empty"); + AssertPrototype(PaperCup, SEntMan.GetNetEntity(cup)); + + // Make sure the number of cups in the cooler has decreased by one + Assert.That(binComp.Items, Has.Count.EqualTo(initialCount - 1), "Number of cups in cooler bin did not decrease by one"); + + // Make sure the cup isn't somehow still in the cooler too + Assert.That(binComp.Items, Does.Not.Contain(cup)); + }); + + // Alt-interact with the water cooler while holding the cup to put it back + await Interact(altInteract: true); + + Assert.Multiple(() => + { + // Make sure the player's hand is empty + Assert.That(HandSys.ActiveHandIsEmpty((SPlayer, Hands)), "Player's hand is not empty"); + + // Make sure the count has gone back up by one + Assert.That(binComp.Items, Has.Count.EqualTo(initialCount), "Number of cups in cooler bin did not return to initial count"); + + // Make sure the cup is in the cooler + Assert.That(binComp.Items, Contains.Item(cup), "Cup was not returned to cooler"); + }); + } + + /// + /// Spawns a water cooler and gives the player an empty paper cup. + /// Tests that the player can put water into the cup by interacting + /// with the water cooler while holding the cup. + /// + [Test] + public async Task FillCup() + { + var solutionSys = Server.System(); + + // Spawn the water cooler + await SpawnTarget(WaterCooler); + + // Give the player a cup + var cup = await PlaceInHands(PaperCup); + + // Make the player interact with the water cooler using the held cup + await Interact(); + + // Make sure the cup now contains water + Assert.That(solutionSys.GetTotalPrototypeQuantity(ToServer(cup), Water), Is.GreaterThan(FixedPoint2.Zero), + "Cup does not contain any water"); + } +}