From 326b8ca0cf9a14f584861cecef8ab5c25c090951 Mon Sep 17 00:00:00 2001 From: tastybento Date: Mon, 19 Nov 2018 08:54:31 -0800 Subject: [PATCH] Fixed item removal. Added unit tests. https://github.com/BentoBoxWorld/addon-challenges/issues/27 --- .../addon/challenges/panel/TryToComplete.java | 43 +++-- .../challenges/panel/TryToCompleteTest.java | 166 ++++++++++++++++++ 2 files changed, 195 insertions(+), 14 deletions(-) create mode 100644 src/test/java/bentobox/addon/challenges/panel/TryToCompleteTest.java diff --git a/src/main/java/bentobox/addon/challenges/panel/TryToComplete.java b/src/main/java/bentobox/addon/challenges/panel/TryToComplete.java index 944c763..bea600d 100644 --- a/src/main/java/bentobox/addon/challenges/panel/TryToComplete.java +++ b/src/main/java/bentobox/addon/challenges/panel/TryToComplete.java @@ -241,24 +241,39 @@ public class TryToComplete { } // If remove items, then remove them if (challenge.isTakeItems()) { - for (ItemStack req : required) { - int amountToBeRemoved = req.getAmount(); - List itemsInInv = Arrays.stream(user.getInventory().getContents()).filter(Objects::nonNull).filter(i -> i.getType().equals(req.getType())).collect(Collectors.toList()); - for (ItemStack i : itemsInInv) { - if (amountToBeRemoved > 0) { - // Remove all of this item - HashMap remaining = user.getInventory().removeItem(i); - if (!remaining.isEmpty()) { - remaining.forEach((k,v) -> addon.logError("Could not remove items: " + v)); - } else { - amountToBeRemoved -= i.getAmount(); - } + removeItems(required); + + } + // Return the result + return new ChallengeResult().setMeetsRequirements().setRepeat(manager.isChallengeComplete(user, challenge.getUniqueId(), world)); + } + + /** + * Removes items from a user's inventory + * @param required - a list of item stacks to be removed + * @return Map of item type and quantity that were successfully removed from the user's inventory + */ + public Map removeItems(List required) { + Map removed = new HashMap<>(); + for (ItemStack req : required) { + int amountToBeRemoved = req.getAmount(); + List itemsInInv = Arrays.stream(user.getInventory().getContents()).filter(Objects::nonNull).filter(i -> i.getType().equals(req.getType())).collect(Collectors.toList()); + for (ItemStack i : itemsInInv) { + if (amountToBeRemoved > 0) { + // Remove either the full amount or the remaining amount + i.setAmount(Math.min(i.getAmount(), amountToBeRemoved)); + // Remove all of this item + HashMap remaining = user.getInventory().removeItem(i); + if (!remaining.isEmpty()) { + remaining.forEach((k,v) -> addon.logError("Could not remove items: " + v.getType() + " x " + v.getAmount())); + } else { + amountToBeRemoved -= i.getAmount(); + removed.merge(i.getType(), i.getAmount(), Integer::sum); } } } } - // Return the result - return new ChallengeResult().setMeetsRequirements().setRepeat(manager.isChallengeComplete(user, challenge.getUniqueId(), world)); + return removed; } private ChallengeResult checkLevel() { diff --git a/src/test/java/bentobox/addon/challenges/panel/TryToCompleteTest.java b/src/test/java/bentobox/addon/challenges/panel/TryToCompleteTest.java new file mode 100644 index 0000000..7fc6853 --- /dev/null +++ b/src/test/java/bentobox/addon/challenges/panel/TryToCompleteTest.java @@ -0,0 +1,166 @@ +/** + * + */ +package bentobox.addon.challenges.panel; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.modules.junit4.PowerMockRunner; + +import bentobox.addon.challenges.ChallengesAddon; +import world.bentobox.bentobox.api.user.User; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +public class TryToCompleteTest { + + private User user; + ItemStack[] stacks = { new ItemStack(Material.PAPER, 32), + new ItemStack(Material.ACACIA_BOAT), + null, + null, + new ItemStack(Material.CACTUS, 32), + new ItemStack(Material.CACTUS, 32), + new ItemStack(Material.CACTUS, 32), + new ItemStack(Material.GOLD_BLOCK, 32) + }; + List required; + private ChallengesAddon addon; + private PlayerInventory inv; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + user = mock(User.class); + inv = mock(PlayerInventory.class); + when(inv.getContents()).thenReturn(stacks); + when(user.getInventory()).thenReturn(inv); + addon = mock(ChallengesAddon.class); + required = new ArrayList<>(); + } + + /** + * Test method for {@link bentobox.addon.challenges.panel.TryToComplete#removeItems(java.util.List)}. + */ + @Test + public void testRemoveItemsSuccess() { + Material reqMat = Material.PAPER; + int reqQty = 21; + required.add(new ItemStack(reqMat, reqQty)); + TryToComplete x = new TryToComplete(addon); + x.user(user); + Map removed = x.removeItems(required); + assertTrue(removed.get(reqMat) == reqQty); + } + + /** + * Test method for {@link bentobox.addon.challenges.panel.TryToComplete#removeItems(java.util.List)}. + */ + @Test + public void testRemoveItemsMax() { + Material reqMat = Material.PAPER; + int reqQty = 50; + required.add(new ItemStack(reqMat, reqQty)); + TryToComplete x = new TryToComplete(addon); + x.user(user); + Map removed = x.removeItems(required); + assertTrue(removed.get(reqMat) == 32); + } + + /** + * Test method for {@link bentobox.addon.challenges.panel.TryToComplete#removeItems(java.util.List)}. + */ + @Test + public void testRemoveItemsZero() { + Material reqMat = Material.PAPER; + int reqQty = 0; + required.add(new ItemStack(reqMat, reqQty)); + TryToComplete x = new TryToComplete(addon); + x.user(user); + Map removed = x.removeItems(required); + assertTrue(removed.get(reqMat) == null); + } + + /** + * Test method for {@link bentobox.addon.challenges.panel.TryToComplete#removeItems(java.util.List)}. + */ + @Test + public void testRemoveItemsSuccessMultiple() { + required.add(new ItemStack(Material.PAPER, 11)); + required.add(new ItemStack(Material.PAPER, 5)); + required.add(new ItemStack(Material.PAPER, 5)); + TryToComplete x = new TryToComplete(addon); + x.user(user); + Map removed = x.removeItems(required); + assertTrue(removed.get(Material.PAPER) == 21); + } + + /** + * Test method for {@link bentobox.addon.challenges.panel.TryToComplete#removeItems(java.util.List)}. + */ + @Test + public void testRemoveItemsSuccessMultipleOther() { + required.add(new ItemStack(Material.CACTUS, 5)); + required.add(new ItemStack(Material.PAPER, 11)); + required.add(new ItemStack(Material.PAPER, 5)); + required.add(new ItemStack(Material.PAPER, 5)); + required.add(new ItemStack(Material.CACTUS, 5)); + TryToComplete x = new TryToComplete(addon); + x.user(user); + Map removed = x.removeItems(required); + assertTrue(removed.get(Material.PAPER) == 21); + assertTrue(removed.get(Material.CACTUS) == 10); + } + + /** + * Test method for {@link bentobox.addon.challenges.panel.TryToComplete#removeItems(java.util.List)}. + */ + @Test + public void testRemoveItemsMultipleOtherFail() { + required.add(new ItemStack(Material.ACACIA_FENCE, 5)); + required.add(new ItemStack(Material.ARROW, 11)); + required.add(new ItemStack(Material.STONE, 5)); + required.add(new ItemStack(Material.BAKED_POTATO, 5)); + required.add(new ItemStack(Material.GHAST_SPAWN_EGG, 5)); + TryToComplete x = new TryToComplete(addon); + x.user(user); + Map removed = x.removeItems(required); + assertTrue(removed.isEmpty()); + + } + + /** + * Test method for {@link bentobox.addon.challenges.panel.TryToComplete#removeItems(java.util.List)}. + */ + @Test + public void testRemoveItemsFail() { + HashMap unremovable = new HashMap<>(); + unremovable.put(0, new ItemStack(Material.GOLD_BLOCK, 2)); + when(inv.removeItem(Mockito.any(ItemStack.class))).thenReturn(unremovable); + required.add(new ItemStack(Material.GOLD_BLOCK, 5)); + TryToComplete x = new TryToComplete(addon); + x.user(user); + Map removed = x.removeItems(required); + assertTrue(removed.isEmpty()); + Mockito.verify(addon, Mockito.times(1)).logError(Mockito.anyString()); + } +}