From 7a4b0f36a1da7101f357e1770c46bdbc8459a8be Mon Sep 17 00:00:00 2001 From: Minecraftschurli Date: Thu, 8 Feb 2024 13:29:15 +0100 Subject: [PATCH] Add tests --- build.gradle.kts | 26 ++- .../potionbundles/AbstractPotionBundle.java | 7 +- .../potionbundles/test/PotionBundleTest.java | 160 ++++++++++++++++++ .../potionbundles/structures/empty_3x3.nbt | Bin 0 -> 97 bytes 4 files changed, 185 insertions(+), 8 deletions(-) create mode 100644 src/test/java/com/github/minecraftschurlimods/potionbundles/test/PotionBundleTest.java create mode 100644 src/test/resources/data/potionbundles/structures/empty_3x3.nbt diff --git a/build.gradle.kts b/build.gradle.kts index 63672d9..4db26bf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -79,11 +79,14 @@ repositories { } } +configurations.testImplementation.configure { extendsFrom(configurations.minecraft.get()) } + dependencies { minecraft("net.minecraftforge:forge:${mc_version}-${forge_version}") compileOnly(fg.deobf("mezz.jei:jei-1.20-common-api:${jei_version}")) runtimeOnly(fg.deobf("mezz.jei:jei-1.20-forge:${jei_version}")) implementation("org.jetbrains:annotations:23.0.0") + testImplementation(sourceSets.main.map { it.output }) } minecraft { @@ -93,23 +96,34 @@ minecraft { create("client") { workingDirectory(file("run")) property("forge.logging.console.level", "debug") - mods.register("potionbundles") { - source(sourceSets.getByName("main")) + mods.register(mod_id) { + source(sourceSets.main.get()) } } create("server") { workingDirectory(file("run")) property("forge.logging.console.level", "debug") - mods.register("potionbundles") { - source(sourceSets.getByName("main")) + mods.register(mod_id) { + source(sourceSets.main.get()) } } create("data") { workingDirectory(file("run")) property("forge.logging.console.level", "debug") args("--mod", mod_id, "--all", "--output", file("src/main/generated/"), "--existing", file("src/main/resources/")) - mods.register("potionbundles") { - source(sourceSets.getByName("main")) + mods.register(mod_id) { + source(sourceSets.main.get()) + } + } + create("gameTestServer") { + workingDirectory(file("run")) + singleInstance(true) + jvmArg("-ea") // Enable assertions + property("forge.logging.markers", "REGISTRIES") + property("forge.enabledGameTestNamespaces", mod_id) + mods.register(mod_id) { + source(sourceSets.main.get()) + source(sourceSets.test.get()) } } } diff --git a/src/main/java/com/github/minecraftschurlimods/potionbundles/AbstractPotionBundle.java b/src/main/java/com/github/minecraftschurlimods/potionbundles/AbstractPotionBundle.java index d8a8785..e0b178e 100644 --- a/src/main/java/com/github/minecraftschurlimods/potionbundles/AbstractPotionBundle.java +++ b/src/main/java/com/github/minecraftschurlimods/potionbundles/AbstractPotionBundle.java @@ -11,6 +11,7 @@ import net.minecraft.world.item.alchemy.PotionUtils; import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.VisibleForTesting; import java.util.List; @@ -19,7 +20,8 @@ public AbstractPotionBundle() { super(new Item.Properties().stacksTo(1)); } - protected int getMaxUses() { + @VisibleForTesting + public int getMaxUses() { return PotionBundles.POTION_BUNDLE_SIZE; } @@ -49,7 +51,8 @@ public Component getName(ItemStack stack) { return Component.translatable(getDescriptionId(), Items.POTION.getName(stack)); } - protected ItemStack createStack(ItemStack string, Potion potion, List customEffects, @Nullable Integer customColor) { + @VisibleForTesting + public ItemStack createStack(ItemStack string, Potion potion, List customEffects, @Nullable Integer customColor) { ItemStack stack = new ItemStack(this); PotionUtils.setPotion(stack, potion); PotionUtils.setCustomEffects(stack, customEffects); diff --git a/src/test/java/com/github/minecraftschurlimods/potionbundles/test/PotionBundleTest.java b/src/test/java/com/github/minecraftschurlimods/potionbundles/test/PotionBundleTest.java new file mode 100644 index 0000000..79e6eeb --- /dev/null +++ b/src/test/java/com/github/minecraftschurlimods/potionbundles/test/PotionBundleTest.java @@ -0,0 +1,160 @@ +package com.github.minecraftschurlimods.potionbundles.test; + +import com.github.minecraftschurlimods.potionbundles.*; +import net.minecraft.core.BlockPos; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestAssertException; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.gametest.framework.GameTestSequence; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.ThrownPotion; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.Potions; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.gametest.PrefixGameTestTemplate; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +@PrefixGameTestTemplate(false) +@GameTestHolder(PotionBundles.MODID) +public class PotionBundleTest { + @GameTest(template = "empty_3x3") + public static void testPotionBundle(GameTestHelper helper) { + ItemStack string = new ItemStack(Items.STRING); + PotionBundle potionBundle = PotionBundles.POTION_BUNDLE.get(); + int maxUses = potionBundle.getMaxUses(); + MobEffectInstance customEffect = new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 20); + ItemStack bundle = potionBundle.createStack(string, Potions.WATER, List.of(customEffect), null); + assertUses(bundle, maxUses, "Uses don't use items max uses"); + int duration = potionBundle.getUseDuration(bundle); + Player player = setupPlayer(helper, bundle); + GameTestSequence sequence = helper.startSequence(); + for (int i = 0; i < maxUses; i++) { + int index = i + 1; + sequence.thenExecute(() -> player.setItemInHand(InteractionHand.MAIN_HAND, bundle.use(helper.getLevel(), player, InteractionHand.MAIN_HAND).getObject())) + .thenExecuteAfter(duration + 1, () -> { + player.stopUsingItem(); + assertBundleUsed(player, index, maxUses, string, bundle); + assertItemsInInventory(player.getInventory(), new ItemStack(Items.GLASS_BOTTLE), index, "Did not return glass bottle"); + MobEffectInstance effect = player.getEffect(customEffect.getEffect()); + if (effect == null || effect.getDuration() + 1 != customEffect.getDuration()) { + fail("Did not apply effect"); + } + }); + } + sequence.thenSucceed(); + } + + @GameTest(template = "empty_3x3") + public static void testSplashPotionBundle(GameTestHelper helper) { + AbstractThrowablePotionBundle potionBundle = PotionBundles.SPLASH_POTION_BUNDLE.get(); + testThrownPotionBundle(helper, potionBundle); + } + + @GameTest(template = "empty_3x3") + public static void testLingeringPotionBundle(GameTestHelper helper) { + AbstractThrowablePotionBundle potionBundle = PotionBundles.LINGERING_POTION_BUNDLE.get(); + testThrownPotionBundle(helper, potionBundle); + } + + private static void testThrownPotionBundle(GameTestHelper helper, AbstractThrowablePotionBundle potionBundle) { + ItemStack string = new ItemStack(Items.STRING); + MobEffectInstance customEffect = new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 20); + int maxUses = potionBundle.getMaxUses(); + ItemStack bundle = potionBundle.createStack(string, Potions.WATER, List.of(customEffect), null); + assertUses(bundle, maxUses, "Uses don't use items max uses"); + Player player = setupPlayer(helper, bundle); + GameTestSequence sequence = helper.startSequence(); + for (int i = 0; i < maxUses; i++) { + int index = i + 1; + sequence.thenExecute(() -> player.setItemInHand(InteractionHand.MAIN_HAND, bundle.use(helper.getLevel(), player, InteractionHand.MAIN_HAND).getObject())) + .thenExecute(() -> { + assertBundleUsed(player, index, maxUses, string, bundle); + List potions = helper.getEntities(EntityType.POTION, new BlockPos(1, 1, 1), 2); + if (potions.isEmpty()) { + fail("Did not throw potion"); + } + if (potions.size() > 1) { + fail("Threw too many potions"); + } + ThrownPotion thrownPotion = potions.get(0); + ItemStack thrownPotionItem = thrownPotion.getItem(); + List mobEffects = PotionUtils.getMobEffects(thrownPotionItem); + if (mobEffects.size() != 1 || !mobEffects.get(0).equals(customEffect)) { + fail("Wrong potion thrown"); + } + if (potionBundle == PotionBundles.SPLASH_POTION_BUNDLE.get()) { + if (!thrownPotionItem.is(Items.SPLASH_POTION)) { + helper.fail("Wrong potion type thrown"); + } + } + if (potionBundle == PotionBundles.LINGERING_POTION_BUNDLE.get()) { + if (!thrownPotionItem.is(Items.LINGERING_POTION)) { + helper.fail("Wrong potion type thrown"); + } + } + thrownPotion.discard(); + }); + } + sequence.thenSucceed(); + } + + private static void assertBundleUsed(Player player, int index, int maxUses, ItemStack string, ItemStack bundle) { + ItemStack inHand = player.getItemInHand(InteractionHand.MAIN_HAND); + assertNotEmpty(inHand, "Bundle should not be empty"); + if (index == maxUses) { + assertSameItem(inHand, string, "Bundle should be empty and returned the string"); + } else { + assertSameItem(inHand, bundle, "Wrong item in hand"); + assertUses(inHand, maxUses - index, "Uses not decremented"); + } + } + + private static void assertSameItem(ItemStack stack, ItemStack expectes, String message) { + if (!ItemStack.isSameItem(stack, expectes)) { + fail(message); + } + } + + private static void assertNotEmpty(ItemStack stack, String message) { + if (stack.isEmpty()) { + fail(message); + } + } + + private static void assertUses(ItemStack bundle, int expectedUses, String message) { + if (PotionBundleUtils.getUses(bundle) != expectedUses) { + fail(message); + } + } + + private static void assertItemsInInventory(Inventory inventory, ItemStack item, int count, String message) { + int slot = inventory.findSlotMatchingItem(item); + if (slot == -1 || inventory.getItem(slot).getCount() != count) { + fail(message); + } + } + + @Contract("_ -> fail") + private static void fail(String message) { + throw new GameTestAssertException(message); + } + + private static @NotNull Player setupPlayer(GameTestHelper helper, ItemStack bundle) { + Player player = helper.makeMockSurvivalPlayer(); + player.setPos(helper.absoluteVec(Vec3.ZERO)); + helper.getLevel().addFreshEntity(player); + player.setItemInHand(InteractionHand.MAIN_HAND, bundle); + return player; + } +} diff --git a/src/test/resources/data/potionbundles/structures/empty_3x3.nbt b/src/test/resources/data/potionbundles/structures/empty_3x3.nbt new file mode 100644 index 0000000000000000000000000000000000000000..6b642c1e11dbb40c32af7b6fdd48f210aca3d632 GIT binary patch literal 97 zcmb2|=3oE=u184;4^k2|&#m!FO-o2%NEAq55uC##v$9fkrs~X