From 06ccb8a5e0d76c5210c5e64522657919b98f250a Mon Sep 17 00:00:00 2001 From: tastybento Date: Thu, 10 Aug 2023 21:57:41 -0700 Subject: [PATCH] Fixed issue with demoting or promoting above yourself. Addresses #2164 Added test class to check command. Added new error text. --- .../island/team/IslandTeamPromoteCommand.java | 58 ++-- src/main/resources/locales/en-US.yml | 4 + .../team/IslandTeamCoopCommandTest.java | 2 - .../team/IslandTeamPromoteCommandTest.java | 302 ++++++++++++++++++ 4 files changed, 345 insertions(+), 21 deletions(-) create mode 100644 src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommandTest.java diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommand.java index d4a32daeb..988f74201 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommand.java @@ -17,6 +17,8 @@ import world.bentobox.bentobox.util.Util; public class IslandTeamPromoteCommand extends CompositeCommand { + private User target; + public IslandTeamPromoteCommand(CompositeCommand islandTeamCommand, String string) { super(islandTeamCommand, string); } @@ -35,11 +37,18 @@ public class IslandTeamPromoteCommand extends CompositeCommand { this.setConfigurableRankCommand(); } + @Override - public boolean execute(User user, String label, List args) { + public boolean canExecute(User user, String label, List args) { + // If args are not right, show help + if (args.size() != 1) { + showHelp(this, user); + return false; + } + if (!getIslands().inTeam(getWorld(), user.getUniqueId())) { user.sendMessage("general.errors.no-team"); - return true; + return false; } // Check rank to use command Island island = getIslands().getIsland(getWorld(), user); @@ -49,38 +58,49 @@ public class IslandTeamPromoteCommand extends CompositeCommand { return false; } - // If args are not right, show help - if (args.size() != 1) { - showHelp(this, user); - return false; - } // Get target - User target = getPlayers().getUser(args.get(0)); + target = getPlayers().getUser(args.get(0)); if (target == null) { user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); - return true; + return false; } // Check if the user is not trying to promote/ demote himself - if (target == user) { - user.sendMessage("commands.island.team.demote.errors.cant-demote-yourself"); - return true; + if (target.equals(user)) { + if (this.getLabel().equals("promote")) { + user.sendMessage("commands.island.team.promote.errors.cant-promote-yourself"); + } else { + user.sendMessage("commands.island.team.demote.errors.cant-demote-yourself"); + } + + return false; } - if (!inTeam(getWorld(), target) || !Objects.requireNonNull(getOwner(getWorld(), user), "Island has no owner!").equals(getOwner(getWorld(), target))) { - user.sendMessage("general.errors.not-in-team"); - return true; + // Check that user is not trying to promote above their own rank + // Check that user is not trying to demote ranks higher than them + if (island.getRank(target) >= island.getRank(user)) { + if (this.getLabel().equals("promote")) { + user.sendMessage("commands.island.team.promote.errors.cant-promote"); + } else { + user.sendMessage("commands.island.team.demote.errors.cant-demote"); + } + return false; } + return true; + } + + @Override + public boolean execute(User user, String label, List args) { return change(user, target); } private boolean change(User user, User target) { - Island island = getIslands().getIsland(getWorld(), user.getUniqueId()); + Island island = getIslands().getIsland(getWorld(), user); int currentRank = island.getRank(target); if (this.getLabel().equals("promote")) { int nextRank = getPlugin().getRanksManager().getRankUpValue(currentRank); // Stop short of owner if (nextRank != RanksManager.OWNER_RANK && nextRank > currentRank) { - getIslands().getIsland(getWorld(), user.getUniqueId()).setRank(target, nextRank); + island.setRank(target, nextRank); String rankName = user.getTranslation(getPlugin().getRanksManager().getRank(nextRank)); user.sendMessage("commands.island.team.promote.success", TextVariables.NAME, target.getName(), TextVariables.RANK, rankName, TextVariables.DISPLAY_NAME, target.getDisplayName()); IslandEvent.builder() @@ -100,7 +120,7 @@ public class IslandTeamPromoteCommand extends CompositeCommand { int prevRank = getPlugin().getRanksManager().getRankDownValue(currentRank); // Lowest is Member if (prevRank >= RanksManager.MEMBER_RANK && prevRank < currentRank) { - getIslands().getIsland(getWorld(), user.getUniqueId()).setRank(target, prevRank); + island.setRank(target, prevRank); String rankName = user.getTranslation(getPlugin().getRanksManager().getRank(prevRank)); user.sendMessage("commands.island.team.demote.success", TextVariables.NAME, target.getName(), TextVariables.RANK, rankName, TextVariables.DISPLAY_NAME, target.getDisplayName()); IslandEvent.builder() @@ -120,7 +140,7 @@ public class IslandTeamPromoteCommand extends CompositeCommand { @Override public Optional> tabComplete(User user, String alias, List args) { - Island island = getIslands().getIsland(getWorld(), user.getUniqueId()); + Island island = getIslands().getIsland(getWorld(), user); if (island != null) { List options = island.getMemberSet().stream() .map(Bukkit::getOfflinePlayer) diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index a0f906643..2c742076c 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -670,11 +670,15 @@ commands: parameters: "" errors: cant-demote-yourself: "&c You can't demote yourself!" + cant-demote: "&c You can't demote higher ranks!" failure: "&c Player cannot be demoted any further!" success: "&a Demoted [name] to [rank]" promote: description: "promote a player on your island up a rank" parameters: "" + errors: + cant-promote-yourself: "&c You can't promote yourself!" + cant-promote: "&c You can't promote above your rank!" failure: "&c Player cannot be promoted any further!" success: "&a Promoted [name] to [rank]" setowner: diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCoopCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCoopCommandTest.java index 38aae1ad6..224e71ead 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCoopCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCoopCommandTest.java @@ -67,8 +67,6 @@ public class IslandTeamCoopCommandTest { @Mock private Island island; - /** - */ @Before public void setUp() throws Exception { // Set up plugin diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommandTest.java new file mode 100644 index 000000000..e9072ebc3 --- /dev/null +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommandTest.java @@ -0,0 +1,302 @@ +package world.bentobox.bentobox.api.commands.island.team; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.eclipse.jdt.annotation.Nullable; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import com.google.common.collect.ImmutableSet; + +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.Settings; +import world.bentobox.bentobox.api.localization.TextVariables; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.CommandsManager; +import world.bentobox.bentobox.managers.IslandWorldManager; +import world.bentobox.bentobox.managers.IslandsManager; +import world.bentobox.bentobox.managers.PlaceholdersManager; +import world.bentobox.bentobox.managers.PlayersManager; +import world.bentobox.bentobox.managers.RanksManager; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class, BentoBox.class, User.class }) +public class IslandTeamPromoteCommandTest { + + @Mock + Player player; + @Mock + private IslandTeamCommand ic; + @Mock + User user; + @Mock + IslandsManager im; + + // DUT + private IslandTeamPromoteCommand ipc; + private IslandTeamPromoteCommand idc; + @Mock + private PlayersManager pm; + @Mock + private World world; + @Mock + private IslandWorldManager iwm; + @Mock + private @Nullable Island island; + @Mock + private User target; + + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + // Set up plugin + BentoBox plugin = mock(BentoBox.class); + Whitebox.setInternalState(BentoBox.class, "instance", plugin); + + // Command manager + CommandsManager cm = mock(CommandsManager.class); + when(plugin.getCommandsManager()).thenReturn(cm); + + // Parent command has no aliases + when(ic.getSubCommandAliases()).thenReturn(new HashMap<>()); + when(ic.getWorld()).thenReturn(world); + + // Settings + Settings settings = new Settings(); + when(plugin.getSettings()).thenReturn(settings); + + UUID uuid = UUID.randomUUID(); + when(user.getUniqueId()).thenReturn(uuid); + when(user.getName()).thenReturn("tastybento"); + when(user.getPlayer()).thenReturn(player); + when(pm.getUser("target")).thenReturn(target); + when(target.getName()).thenReturn("target"); + when(target.getDisplayName()).thenReturn("Target"); + + // Managers + when(plugin.getIslands()).thenReturn(im); + when(plugin.getPlayers()).thenReturn(pm); + when(plugin.getIWM()).thenReturn(iwm); + + // Translations + when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); + // Placeholders + PlaceholdersManager phm = mock(PlaceholdersManager.class); + when(phm.replacePlaceholders(any(), any())).thenAnswer(invocation -> invocation.getArgument(1, String.class)); + // Placeholder manager + when(plugin.getPlaceholdersManager()).thenReturn(phm); + + // In team + when(im.inTeam(world, uuid)).thenReturn(true); + + // Ranks Manager + RanksManager rm = new RanksManager(); + when(plugin.getRanksManager()).thenReturn(rm); + when(island.getRankCommand(anyString())).thenReturn(RanksManager.SUB_OWNER_RANK); // Allow sub owners + when(island.getRank(user)).thenReturn(RanksManager.SUB_OWNER_RANK); + when(island.getRank(target)).thenReturn(RanksManager.SUB_OWNER_RANK); + + // Island + when(im.getIsland(world, user)).thenReturn(island); + ImmutableSet team = ImmutableSet.of(uuid); + when(island.getMemberSet()).thenReturn(team); + + // Bukkit + PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); + when(Bukkit.getOfflinePlayer(uuid)).thenReturn(player); + when(player.getName()).thenReturn("tastybento"); + + + ipc = new IslandTeamPromoteCommand(ic, "promote"); + idc = new IslandTeamPromoteCommand(ic, "demote"); + + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + User.clearUsers(); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#IslandTeamPromoteCommand(world.bentobox.bentobox.api.commands.CompositeCommand, java.lang.String)}. + */ + @Test + public void testIslandTeamPromoteCommand() { + assertNotNull(ipc); + assertNotNull(idc); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#setup()}. + */ + @Test + public void testSetup() { + assertEquals("island.team.promote", ipc.getPermission()); + assertEquals("island.team.promote", idc.getPermission()); + assertTrue(ipc.isOnlyPlayer()); + assertTrue(idc.isOnlyPlayer()); + assertEquals("commands.island.team.promote.parameters", ipc.getParameters()); + assertEquals("commands.island.team.demote.parameters", idc.getParameters()); + assertEquals("commands.island.team.promote.description", ipc.getDescription()); + assertEquals("commands.island.team.demote.description", idc.getDescription()); + assertTrue(ipc.isConfigurableRankCommand()); + assertTrue(idc.isConfigurableRankCommand()); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteUserStringListOfStringShowHelp() { + assertFalse(ipc.canExecute(user, "promote", List.of())); // Nothing + verify(user).sendMessage("commands.help.header", TextVariables.LABEL, null); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteUserStringListOfStringNoTeam() { + when(im.inTeam(any(), any())).thenReturn(false); + assertFalse(ipc.canExecute(user, "promote", List.of("tastybento"))); + verify(user).sendMessage("general.errors.no-team"); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteUserStringListOfStringInsufficientRank() { + when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); + assertFalse(ipc.canExecute(user, "promote", List.of("tastybento"))); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, RanksManager.MEMBER_RANK_REF); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteUserStringListOfStringUnknownPlayer() { + when(pm.getUser(anyString())).thenReturn(null); + assertFalse(ipc.canExecute(user, "promote", List.of("tastybento"))); + verify(user).sendMessage("general.errors.unknown-player", TextVariables.NAME, "tastybento"); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteUserStringListOfStringSameUser() { + when(pm.getUser(anyString())).thenReturn(user); + assertFalse(ipc.canExecute(user, "promote", List.of("tastybento"))); + verify(user).sendMessage("commands.island.team.promote.errors.cant-promote-yourself"); + assertFalse(idc.canExecute(user, "demote", List.of("tastybento"))); + verify(user).sendMessage("commands.island.team.demote.errors.cant-demote-yourself"); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteUserStringListOfStringDemoteOwner() { + when(island.getRank(target)).thenReturn(RanksManager.OWNER_RANK); + assertFalse(idc.canExecute(user, "demote", List.of("target"))); + verify(user).sendMessage("commands.island.team.demote.errors.cant-demote"); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteUserStringListOfStringPromoteAboveSelf() { + when(island.getRank(target)).thenReturn(RanksManager.SUB_OWNER_RANK); + assertFalse(ipc.canExecute(user, "promote", List.of("target"))); + verify(user).sendMessage("commands.island.team.promote.errors.cant-promote"); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteUserStringListOfStringSuccess() { + when(island.getRank(target)).thenReturn(RanksManager.MEMBER_RANK); + assertTrue(ipc.canExecute(user, "promote", List.of("target"))); + assertTrue(idc.canExecute(user, "demote", List.of("target"))); + verify(user, never()).sendMessage(any()); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testExecuteUserStringListOfString() { + when(island.getRank(target)).thenReturn(RanksManager.MEMBER_RANK); + ipc.canExecute(user, "promote", List.of("target")); + assertTrue(ipc.execute(user, "promote", List.of("target"))); + verify(island).setRank(target, RanksManager.SUB_OWNER_RANK); + verify(user).sendMessage("commands.island.team.promote.success", TextVariables.NAME, "target", TextVariables.RANK, RanksManager.SUB_OWNER_RANK_REF, TextVariables.DISPLAY_NAME, "Target"); + + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#tabComplete(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testTabCompleteUserStringListOfStringNoIsland() { + when(im.getIsland(world, user)).thenReturn(null); + Optional> options = ipc.tabComplete(user, "promote", List.of("p")); + assertTrue(options.isEmpty()); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamPromoteCommand#tabComplete(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testTabCompleteUserStringListOfString() { + Optional> options = ipc.tabComplete(user, "promote", List.of("p")); + assertFalse(options.isEmpty()); + assertTrue(options.get().isEmpty()); + + options = ipc.tabComplete(user, "promote", List.of("t")); + assertFalse(options.isEmpty()); + assertFalse(options.get().isEmpty()); + assertEquals("tastybento", options.get().get(0)); + } + +}