Add fuse test. Also made some modification to allow the test to work

This commit is contained in:
alexcrea 2024-10-24 10:29:29 +02:00
parent 2008b41b09
commit 99a7829990
No known key found for this signature in database
GPG key ID: 43FD265DB0DBF91F
15 changed files with 514 additions and 52 deletions

View file

@ -1,44 +1,15 @@
package io.delilaheve;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import xyz.alexcrea.cuanvil.DefaultCustomAnvilTest;
public class CustomAnvilTests {
private ServerMock server;
private CustomAnvil plugin;
@BeforeEach
public void setUp() {
// Start the mock server
server = MockBukkit.mock();
// Load your plugin
plugin = MockBukkit.load(CustomAnvil.class);
}
@AfterEach
public void tearDown() {
// Stop the mock server
MockBukkit.unmock();
}
public class CustomAnvilTests extends DefaultCustomAnvilTest {
@Test
public void simpleInitTest() {
// Continue initialization of the plugin
server.getScheduler().performOneTick();
Assertions.assertNotNull(server);
Assertions.assertNotNull(plugin);
}
}

View file

@ -0,0 +1,53 @@
package xyz.alexcrea.cuanvil;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock;
import io.delilaheve.CustomAnvil;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry;
import java.util.ArrayList;
import java.util.List;
public class DefaultCustomAnvilTest {
protected ServerMock server;
protected CustomAnvil plugin;
@BeforeEach
public void setUp() {
// Start the mock server
server = MockBukkit.mock();
// Load your plugin
plugin = MockBukkit.load(CustomAnvil.class);
// Continue initialization of the plugin
server.getScheduler().performOneTick();
}
@AfterEach
public void tearDown() {
// Set config to null
ConfigHolder.DEFAULT_CONFIG = null;
ConfigHolder.ITEM_GROUP_HOLDER = null;
ConfigHolder.CONFLICT_HOLDER = null;
ConfigHolder.UNIT_REPAIR_HOLDER = null;
ConfigHolder.CUSTOM_RECIPE_HOLDER = null;
// Stop the mock server
MockBukkit.unmock();
// Unregister enchantments
List<CAEnchantment> toUnregister = new ArrayList<>(
CAEnchantmentRegistry.getInstance().values()
);
for (CAEnchantment caEnchantment : toUnregister) {
CAEnchantmentRegistry.getInstance().unregister(caEnchantment);
}
}
}

View file

@ -0,0 +1,81 @@
package xyz.alexcrea.cuanvil.anvil;
import be.seeseemelk.mockbukkit.entity.PlayerMock;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import xyz.alexcrea.cuanvil.DefaultCustomAnvilTest;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.util.AnvilFuseTestData;
import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil;
import xyz.alexcrea.cuanvil.util.CommonItemUtil;
public class AnvilFuseTest extends DefaultCustomAnvilTest {
private AnvilInventory anvil;
private PlayerMock player;
@Override
@BeforeEach
public void setUp() {
super.setUp();
// Mock used player & open anvil
player = server.addPlayer();
Inventory anvil = server.createInventory(player, InventoryType.ANVIL);
this.anvil = (AnvilInventory) anvil;
player.openInventory(anvil);
ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log", true);
ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log_verbose", true);
}
@Test
public void mergeFuseTest(){
// Literally just test a sharpness 4 + sharpness 4
ItemStack sharpness4 = CommonItemUtil.sharpness(4);
ItemStack sharpness5 = CommonItemUtil.sharpness(5);
AnvilFuseTestData data = new AnvilFuseTestData(
sharpness4, sharpness4,
sharpness5
// TODO add expected price
);
AnvilFuseTestUtil.executeAnvilTest(anvil, player, data);
}
@Test
public void overFuseTest(){
// Test sharpness 4 + sharpness 5
ItemStack sharpness4 = CommonItemUtil.sharpness(4);
ItemStack sharpness5 = CommonItemUtil.sharpness(5);
AnvilFuseTestData data = new AnvilFuseTestData(
sharpness4, sharpness5,
sharpness5
// TODO add expected price
);
AnvilFuseTestUtil.executeAnvilTest(anvil, player, data);
}
@Test
public void underFuseTest(){
// test sharpness 5 + 4. Custom Anvil should not allow it to be as it result as the same item as left item
ItemStack sharpness4 = CommonItemUtil.sharpness(4);
ItemStack sharpness5 = CommonItemUtil.sharpness(5);
AnvilFuseTestData data = new AnvilFuseTestData(
sharpness5, sharpness4,
null
);
AnvilFuseTestUtil.executeAnvilTest(anvil, player, data);
}
}

View file

@ -0,0 +1,76 @@
package xyz.alexcrea.cuanvil.mock;
import be.seeseemelk.mockbukkit.inventory.PlayerInventoryViewMock;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.view.AnvilView;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings({"removal"})
public class AnvilViewMock extends PlayerInventoryViewMock implements AnvilView {
private @NotNull AnvilInventory top;
/**
* Constructs a new {@link PlayerInventoryViewMock} for the provided player, with the specified top inventory.
*
* @param player The player to create the view for.
* @param top The top inventory.
*/
public AnvilViewMock(@NotNull HumanEntity player, @NotNull AnvilInventory top) {
super(player, top);
this.top = top;
}
@Override
public @Nullable String getRenameText() {
return top.getRenameText();
}
@Override
public int getRepairItemCountCost() {
return top.getRepairCostAmount();
}
@Override
public int getRepairCost() {
return top.getRepairCost();
}
@Override
public int getMaximumRepairCost() {
return top.getMaximumRepairCost();
}
@Override
public void setRepairItemCountCost(int amount) {
top.setRepairCostAmount(amount);
}
@Override
public void setRepairCost(int cost) {
top.setRepairCost(cost);
}
@Override
public void setMaximumRepairCost(int levels) {
top.setMaximumRepairCost(levels);
}
@Override
public boolean bypassesEnchantmentLevelRestriction() {
throw new UnsupportedOperationException("Custom anvil was not think with this existing");
}
@Override
public void bypassEnchantmentLevelRestriction(boolean bypassEnchantmentLevelRestriction) {
throw new UnsupportedOperationException("Custom anvil was not think with this existing");
}
@Override
public @NotNull AnvilInventory getTopInventory() {
return top;
}
}

View file

@ -0,0 +1,56 @@
package xyz.alexcrea.cuanvil.mock;
import be.seeseemelk.mockbukkit.inventory.ItemStackMock;
import com.google.common.collect.ImmutableMap;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class EnchantedItemStackMock extends ItemStackMock {
EnchantedItemStackMock(){}
public EnchantedItemStackMock(@NotNull Material type, int amount) {
super(type, amount);
}
public EnchantedItemStackMock(@NotNull Material type) {
this(type, 1);
}
public EnchantedItemStackMock(@NotNull ItemStack stack) throws IllegalArgumentException {
super(stack);
}
@Override
public int removeEnchantment(@NotNull Enchantment ench) {
int level = this.getEnchantmentLevel(ench);
this.getItemMeta().removeEnchant(ench);
return level;
}
@Override
public void removeEnchantments() {
this.getItemMeta().removeEnchantments();
}
// badly imitate paper (and I hope spigot) behavior and avoid concurrent modification exception
@Override
public @NotNull Map<Enchantment, Integer> getEnchantments() {
return ImmutableMap.copyOf(super.getEnchantments());
}
@Override
public @NotNull ItemStack clone() {
ItemStackMock clone = new EnchantedItemStackMock(this.getType());
clone.setAmount(this.getAmount());
clone.setDurability(this.getDurability());
clone.setItemMeta(this.hasItemMeta() ? this.getItemMeta().clone() : null);
return clone;
}
}

View file

@ -0,0 +1,39 @@
package xyz.alexcrea.cuanvil.util;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
public record AnvilFuseTestData(
@Nullable ItemStack leftItem,
@Nullable ItemStack rightItem,
@Nullable ItemStack expectedResult,
@Nullable ItemStack expectedAfterLeftPlaced,
@Nullable ItemStack expectedAfterRightPlaced,
@Nullable Integer expectedPriceAfterLeftPlaced,
@Nullable Integer expectedPriceAfterRightPlaced,
@Nullable Integer expectedPriceAfterBothPlaced
){
public AnvilFuseTestData(
@Nullable ItemStack leftItem,
@Nullable ItemStack rightItem,
@Nullable ItemStack expectedResult,
@Nullable Integer expectedPriceAfterBothPlaced
){
this(leftItem, rightItem, expectedResult,
null, null, null, null,
expectedPriceAfterBothPlaced
);
}
public AnvilFuseTestData(
@Nullable ItemStack leftItem,
@Nullable ItemStack rightItem,
@Nullable ItemStack expectedResult
){
this(leftItem, rightItem, expectedResult, null
);
}
}

View file

@ -0,0 +1,138 @@
package xyz.alexcrea.cuanvil.util;
import io.delilaheve.util.ItemUtil;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.PrepareAnvilEvent;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.Assertions;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener;
import xyz.alexcrea.cuanvil.mock.AnvilViewMock;
import xyz.alexcrea.cuanvil.mock.EnchantedItemStackMock;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class AnvilFuseTestUtil {
public static ItemStack prepareItem(@NotNull Material material,
@NotNull List<CAEnchantment> enchantments,
@NotNull List<Integer> level){
Assertions.assertEquals(enchantments.size(), level.size());
HashMap<CAEnchantment, Integer> enchantmentMap = new HashMap<>();
for (int i = 0; i < enchantments.size(); i++) {
enchantmentMap.put(enchantments.get(i), level.get(i));
}
ItemStack item = new EnchantedItemStackMock(material);
ItemUtil.INSTANCE.setEnchantmentsUnsafe(item, enchantmentMap);
return item;
}
public static ItemStack prepareItem(@NotNull Material material,
@NotNull List<String> enchantmentNames,
Integer... levels){
List<CAEnchantment> enchantments = new ArrayList<>();
for (String enchantmentName : enchantmentNames) {
List<CAEnchantment> enchantmentList = CAEnchantment.getListByName(enchantmentName);
Assertions.assertNotEquals(0, enchantmentList.size(),
"Could not find enchantment \"" + enchantmentName + "\"");
enchantments.addAll(enchantmentList);
}
return prepareItem(material, enchantments, List.of(levels));
}
/*
* Need to use that as it seems setting item in the inventory will not trigger the anvil click even
*
* Not the best for non-custom anvil plugins but work in the context of CA
*/
public static void imitateAnvilUpdate(
@NotNull HumanEntity player,
@NotNull AnvilInventory anvil) {
AnvilViewMock view = new AnvilViewMock(player, anvil);
try {
PrepareAnvilEvent event = new PrepareAnvilEvent(view, anvil.getItem(2));
// Not ideal but possible and the easiest so why not
new PrepareAnvilListener().anvilCombineCheck(event);
anvil.setResult(event.getResult());
} catch (Exception e){
e.printStackTrace();
Assertions.fail();
}
}
public static void executeAnvilTest(
@NotNull AnvilInventory anvil,
@NotNull HumanEntity player,
@NotNull AnvilFuseTestData data
){
Assertions.assertEquals(player.getOpenInventory().getTopInventory(), anvil,
"Openned inventory is not anvil");
// Test with only the left item
testPlacingItem(anvil, player,
0, data.expectedPriceAfterLeftPlaced(),
data.leftItem(), data.expectedAfterLeftPlaced());
// Test with only the right item
anvil.setItem(0, null); // We only want the right item. so we remove the left one
testPlacingItem(anvil, player,
1, data.expectedPriceAfterRightPlaced(),
data.rightItem(), data.expectedAfterRightPlaced());
// Test with both placed
testPlacingItem(anvil, player,
0, data.expectedPriceAfterBothPlaced(),
data.leftItem(), data.expectedResult());
// Sadly, can't currently test player click
}
@SuppressWarnings({"removal"})
private static void testPlacingItem(
@NotNull AnvilInventory anvil,
@NotNull HumanEntity player,
int slot,
Integer expectedPrice,
@Nullable ItemStack toPlace,
@Nullable ItemStack expectedResult){
anvil.setItem(slot, toPlace);
AnvilFuseTestUtil.imitateAnvilUpdate(player, anvil);
ItemStack result = anvil.getItem(2);
assertEqual(result, expectedResult);
assertPriceEqual(expectedPrice, anvil.getRepairCost());
}
public static void assertEqual(@Nullable ItemStack item1, @Nullable ItemStack item2) {
if(isAir(item1)) Assertions.assertTrue(isAir(item2));
else Assertions.assertEquals(item1, item2);
}
public static boolean isAir(@Nullable ItemStack item){
return item == null || item.isEmpty();
}
public static void assertPriceEqual(Integer expectedPrice, int price){
if(expectedPrice == null) return;
Assertions.assertEquals(price, expectedPrice);
}
}

View file

@ -0,0 +1,21 @@
package xyz.alexcrea.cuanvil.util;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public class CommonItemUtil {
public static ItemStack sharpness(int level){
return AnvilFuseTestUtil.prepareItem(
Material.DIAMOND_SWORD,
List.of("sharpness"),
level
);
}
}