More unit tests, fixes
This commit is contained in:
243
Plugins/PkmnLib.Plugin.Gen7.Tests/Scripts/Moves/BugBiteTests.cs
Normal file
243
Plugins/PkmnLib.Plugin.Gen7.Tests/Scripts/Moves/BugBiteTests.cs
Normal file
@@ -0,0 +1,243 @@
|
||||
using PkmnLib.Dynamic.Events;
|
||||
using PkmnLib.Dynamic.Libraries;
|
||||
using PkmnLib.Dynamic.Models;
|
||||
using PkmnLib.Dynamic.ScriptHandling;
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
using PkmnLib.Static;
|
||||
using PkmnLib.Static.Moves;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the <see cref="BugBite"/> move script.
|
||||
/// Behavior is verified against the Bulbapedia page for Bug Bite.
|
||||
/// </summary>
|
||||
public class BugBiteTests
|
||||
{
|
||||
private const string BerryEffectName = "test_berry_effect";
|
||||
|
||||
/// <summary>
|
||||
/// Minimal <see cref="ItemScript"/> that records whether its effect was applied through
|
||||
/// <see cref="ItemScript.OnUse"/>.
|
||||
/// </summary>
|
||||
private class RecordingItemScript : ItemScript
|
||||
{
|
||||
public RecordingItemScript(IItem item) : base(item)
|
||||
{
|
||||
}
|
||||
|
||||
public bool WasUsed { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsItemUsable => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnUse(EventHook eventHook) => WasUsed = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a fully mocked test setup for BugBite tests. The battle's <see cref="ScriptResolver"/> is a
|
||||
/// real resolver with a single registered item script constructor for <see cref="BerryEffectName"/>, so
|
||||
/// eating a Berry runs a <see cref="RecordingItemScript"/> that the test can inspect.
|
||||
/// </summary>
|
||||
private static (BugBite bugBite, IExecutingMove move, IPokemon target, IHitData hitData, List<RecordingItemScript>
|
||||
createdItemScripts) CreateTestSetup(IItem? targetHeldItem, bool canSteal = true)
|
||||
{
|
||||
var bugBite = new BugBite();
|
||||
|
||||
var createdItemScripts = new List<RecordingItemScript>();
|
||||
var resolver = new ScriptResolver(new Dictionary<(ScriptCategory, StringKey), Func<Script>>(),
|
||||
new Dictionary<StringKey, Func<IItem, ItemScript>>
|
||||
{
|
||||
{
|
||||
new StringKey(BerryEffectName), item =>
|
||||
{
|
||||
var script = new RecordingItemScript(item);
|
||||
createdItemScripts.Add(script);
|
||||
return script;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var battle = Substitute.For<IBattle>();
|
||||
battle.EventHook.Returns(new EventHook());
|
||||
var dynamicLibrary = Substitute.For<IDynamicLibrary>();
|
||||
dynamicLibrary.ScriptResolver.Returns(resolver);
|
||||
battle.Library.Returns(dynamicLibrary);
|
||||
|
||||
var battleData = Substitute.For<IPokemonBattleData>();
|
||||
battleData.Battle.Returns(battle);
|
||||
|
||||
var user = Substitute.For<IPokemon>();
|
||||
user.BattleData.Returns(battleData);
|
||||
|
||||
var move = Substitute.For<IExecutingMove>();
|
||||
move.User.Returns(user);
|
||||
move.Battle.Returns(battle);
|
||||
|
||||
var target = Substitute.For<IPokemon>();
|
||||
target.HeldItem.Returns(targetHeldItem);
|
||||
if (targetHeldItem != null && canSteal)
|
||||
{
|
||||
target.TryStealHeldItem(out Arg.Any<IItem?>()).Returns(x =>
|
||||
{
|
||||
x[0] = targetHeldItem;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
target.TryStealHeldItem(out Arg.Any<IItem?>()).Returns(false);
|
||||
}
|
||||
|
||||
var hitData = Substitute.For<IHitData>();
|
||||
move.GetHitData(target, 0).Returns(hitData);
|
||||
|
||||
return (bugBite, move, target, hitData, createdItemScripts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a mocked Berry item whose battle effect is <see cref="BerryEffectName"/>.
|
||||
/// </summary>
|
||||
private static IItem CreateBerry()
|
||||
{
|
||||
var berry = Substitute.For<IItem>();
|
||||
berry.Category.Returns(ItemCategory.Berry);
|
||||
berry.BattleEffect.Returns(new SecondaryEffectImpl(-1, new StringKey(BerryEffectName),
|
||||
new Dictionary<StringKey, object?>()));
|
||||
return berry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "If the target is holding a Berry, the user will eat the Berry and gain its effect."
|
||||
/// Eating the Berry removes it from the target via <see cref="IPokemon.ForceSetHeldItem"/>.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_TargetHoldsBerry_BerryIsRemovedFromTarget()
|
||||
{
|
||||
// Arrange
|
||||
var (bugBite, move, target, _, _) = CreateTestSetup(CreateBerry());
|
||||
|
||||
// Act
|
||||
bugBite.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(target.ReceivedCalls().Any(c =>
|
||||
c.GetMethodInfo().Name == "ForceSetHeldItem" && c.GetArguments()[0] == null)).IsTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "If the target is holding a Berry, the user will eat the Berry and gain its effect."
|
||||
/// The Berry's item script is executed for the user, applying its effect.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_TargetHoldsBerry_UserGainsBerryEffect()
|
||||
{
|
||||
// Arrange
|
||||
var (bugBite, move, target, _, createdItemScripts) = CreateTestSetup(CreateBerry());
|
||||
|
||||
// Act
|
||||
bugBite.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert - exactly one berry script was resolved and its effect was applied
|
||||
await Assert.That(createdItemScripts.Count).IsEqualTo(1);
|
||||
await Assert.That(createdItemScripts[0].WasUsed).IsTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "If the target is holding a Berry, the user will eat the Berry and gain its effect."
|
||||
/// When the Berry is successfully eaten, the secondary effect must not be marked as failed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_TargetHoldsBerry_HitDoesNotFail()
|
||||
{
|
||||
// Arrange
|
||||
var (bugBite, move, target, hitData, _) = CreateTestSetup(CreateBerry());
|
||||
|
||||
// Act
|
||||
bugBite.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(hitData.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Fail")).IsFalse();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "If the target is holding a Berry, the user will eat the Berry and gain its effect."
|
||||
/// A held item that is not a Berry is not eaten: the secondary effect fails and the target keeps
|
||||
/// its item.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_TargetHoldsNonBerryItem_EffectFailsAndItemIsKept()
|
||||
{
|
||||
// Arrange
|
||||
var nonBerry = Substitute.For<IItem>();
|
||||
nonBerry.Category.Returns(ItemCategory.MiscItem);
|
||||
var (bugBite, move, target, hitData, _) = CreateTestSetup(nonBerry);
|
||||
|
||||
// Act
|
||||
bugBite.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(hitData.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Fail")).IsTrue();
|
||||
await Assert.That(target.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ForceSetHeldItem")).IsFalse();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "If the target is holding a Berry, the user will eat the Berry and gain its effect."
|
||||
/// With no held item at all there is nothing to eat, so the secondary effect fails.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_TargetHoldsNoItem_EffectFails()
|
||||
{
|
||||
// Arrange
|
||||
var (bugBite, move, target, hitData, _) = CreateTestSetup(null);
|
||||
|
||||
// Act
|
||||
bugBite.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(hitData.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Fail")).IsTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Bug Bite will not consume the Berry of a target that has the Ability Sticky Hold."
|
||||
/// When the Berry cannot be stolen (<see cref="IPokemon.TryStealHeldItem"/> returns false, as with
|
||||
/// Sticky Hold), the target keeps its Berry and the effect fails.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_BerryCannotBeStolen_TargetKeepsBerry()
|
||||
{
|
||||
// Arrange
|
||||
var (bugBite, move, target, hitData, createdItemScripts) = CreateTestSetup(CreateBerry(), false);
|
||||
|
||||
// Act
|
||||
bugBite.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert - the berry is not removed, its effect is not gained, and the effect fails
|
||||
await Assert.That(target.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ForceSetHeldItem")).IsFalse();
|
||||
await Assert.That(createdItemScripts.Count).IsEqualTo(0);
|
||||
await Assert.That(hitData.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Fail")).IsTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the user has no <see cref="IPokemon.BattleData"/>, the script does nothing: no Berry is eaten
|
||||
/// and the hit is not failed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_UserHasNoBattleData_DoesNothing()
|
||||
{
|
||||
// Arrange
|
||||
var (bugBite, move, target, hitData, _) = CreateTestSetup(CreateBerry());
|
||||
var user = Substitute.For<IPokemon>();
|
||||
user.BattleData.Returns((IPokemonBattleData?)null);
|
||||
move.User.Returns(user);
|
||||
|
||||
// Act
|
||||
bugBite.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(target.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ForceSetHeldItem")).IsFalse();
|
||||
await Assert.That(hitData.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Fail")).IsFalse();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user