243 lines
9.1 KiB
C#
243 lines
9.1 KiB
C#
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();
|
|
}
|
|
} |