From 00125487f1a068b9bd9b283f08753caa8da5ab60 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sun, 13 Mar 2016 10:17:09 +0100 Subject: [PATCH] Create tests for admin commands --- .../authme/ChangePasswordAdminCommand.java | 7 +- .../executable/authme/FirstSpawnCommand.java | 3 + .../executable/authme/GetEmailCommand.java | 5 +- .../executable/authme/LastLoginCommand.java | 14 +- .../authme/PurgeBannedPlayersCommand.java | 6 +- .../executable/authme/PurgeCommand.java | 15 +- .../authme/PurgeLastPositionCommand.java | 42 ++- src/test/java/fr/xephi/authme/TestHelper.java | 19 ++ .../authme/AccountsCommandTest.java | 8 +- .../executable/authme/AuthMeCommandTest.java | 38 +++ .../ChangePasswordAdminCommandTest.java | 253 ++++++++++++++++++ .../authme/FirstSpawnCommandTest.java | 65 +++++ .../authme/GetEmailCommandTest.java | 68 +++++ .../authme/LastLoginCommandTest.java | 119 ++++++++ .../authme/PurgeLastPositionCommandTest.java | 124 +++++++++ .../executable/authme/ReloadCommandTest.java | 65 +++++ .../authme/SetFirstSpawnCommandTest.java | 66 +++++ .../authme/SetSpawnCommandTest.java | 66 +++++ .../executable/authme/SpawnCommandTest.java | 65 +++++ 19 files changed, 1001 insertions(+), 47 deletions(-) create mode 100644 src/test/java/fr/xephi/authme/command/executable/authme/AuthMeCommandTest.java create mode 100644 src/test/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommandTest.java create mode 100644 src/test/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommandTest.java create mode 100644 src/test/java/fr/xephi/authme/command/executable/authme/GetEmailCommandTest.java create mode 100644 src/test/java/fr/xephi/authme/command/executable/authme/LastLoginCommandTest.java create mode 100644 src/test/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommandTest.java create mode 100644 src/test/java/fr/xephi/authme/command/executable/authme/ReloadCommandTest.java create mode 100644 src/test/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommandTest.java create mode 100644 src/test/java/fr/xephi/authme/command/executable/authme/SetSpawnCommandTest.java create mode 100644 src/test/java/fr/xephi/authme/command/executable/authme/SpawnCommandTest.java diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java index cb6bddcf..10bb4432 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java @@ -2,7 +2,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.datasource.DataSource; @@ -41,6 +40,8 @@ public class ChangePasswordAdminCommand implements ExecutableCommand { commandService.send(sender, MessageKey.INVALID_PASSWORD_LENGTH); return; } + // TODO ljacqu 20160312: The UNSAFE_PASSWORDS should be all lowercase + // -> introduce a lowercase String list property type if (commandService.getProperty(SecuritySettings.UNSAFE_PASSWORDS).contains(playerPassLowerCase)) { commandService.send(sender, MessageKey.PASSWORD_UNSAFE_ERROR); return; @@ -53,8 +54,8 @@ public class ChangePasswordAdminCommand implements ExecutableCommand { public void run() { DataSource dataSource = commandService.getDataSource(); PlayerAuth auth = null; - if (PlayerCache.getInstance().isAuthenticated(playerNameLowerCase)) { - auth = PlayerCache.getInstance().getAuth(playerNameLowerCase); + if (commandService.getPlayerCache().isAuthenticated(playerNameLowerCase)) { + auth = commandService.getPlayerCache().getAuth(playerNameLowerCase); } else if (dataSource.isAuthAvailable(playerNameLowerCase)) { auth = dataSource.getAuth(playerNameLowerCase); } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java index da7b45e4..50b3b169 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java @@ -6,6 +6,9 @@ import org.bukkit.entity.Player; import java.util.List; +/** + * Teleports the player to the first spawn. + */ public class FirstSpawnCommand extends PlayerCommand { @Override diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java index 63d65b47..53a3051c 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java @@ -8,13 +8,16 @@ import org.bukkit.command.CommandSender; import java.util.List; +/** + * Returns a player's email. + */ public class GetEmailCommand implements ExecutableCommand { @Override public void executeCommand(CommandSender sender, List arguments, CommandService commandService) { String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0); - PlayerAuth auth = commandService.getDataSource().getAuth(playerName.toLowerCase()); + PlayerAuth auth = commandService.getDataSource().getAuth(playerName); if (auth == null) { commandService.send(sender, MessageKey.UNKNOWN_USER); } else { diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java index 434a648e..05fdab2b 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java @@ -10,6 +10,7 @@ import java.util.Date; import java.util.List; /** + * Returns the last login date of the given user. */ public class LastLoginCommand implements ExecutableCommand { @@ -18,23 +19,24 @@ public class LastLoginCommand implements ExecutableCommand { // Get the player String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName(); - PlayerAuth auth = commandService.getDataSource().getAuth(playerName.toLowerCase()); + PlayerAuth auth = commandService.getDataSource().getAuth(playerName); if (auth == null) { commandService.send(sender, MessageKey.USER_NOT_REGISTERED); return; } // Get the last login date - long lastLogin = auth.getLastLogin(); + final long lastLogin = auth.getLastLogin(); final long diff = System.currentTimeMillis() - lastLogin; - final String lastLoginMessage = (int) (diff / 86400000) + " days " + (int) (diff / 3600000 % 24) + " hours " - + (int) (diff / 60000 % 60) + " mins " + (int) (diff / 1000 % 60) + " secs"; + final String lastLoginMessage = (int) (diff / 86400000) + " days " + + (int) (diff / 3600000 % 24) + " hours " + + (int) (diff / 60000 % 60) + " mins " + + (int) (diff / 1000 % 60) + " secs"; Date date = new Date(lastLogin); // Show the player status sender.sendMessage("[AuthMe] " + playerName + " last login: " + date.toString()); - sender.sendMessage("[AuthMe] The player " + auth.getNickname() + " last logged in " - + lastLoginMessage + " ago."); + sender.sendMessage("[AuthMe] The player " + playerName + " last logged in " + lastLoginMessage + " ago."); sender.sendMessage("[AuthMe] Last Player's IP: " + auth.getIp()); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java index 1cd3c0ee..0ace9424 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java @@ -10,6 +10,10 @@ import org.bukkit.command.CommandSender; import java.util.ArrayList; import java.util.List; +/** + * Command for purging data of banned players. Depending on the settings + * it purges (deletes) data from third-party plugins as well. + */ public class PurgeBannedPlayersCommand implements ExecutableCommand { @Override @@ -24,7 +28,7 @@ public class PurgeBannedPlayersCommand implements ExecutableCommand { } // Purge the banned players - plugin.getDataSource().purgeBanned(bannedPlayers); + commandService.getDataSource().purgeBanned(bannedPlayers); if (commandService.getProperty(PurgeSettings.REMOVE_ESSENTIALS_FILES) && commandService.getPluginHooks().isEssentialsAvailable()) plugin.dataManager.purgeEssentials(bannedPlayers); diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java index e7c09686..43e1daa5 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java @@ -10,13 +10,16 @@ import org.bukkit.command.CommandSender; import java.util.Calendar; import java.util.List; +/** + * Command for purging the data of players which have not been since for a given number + * of days. Depending on the settings, this removes player data in third-party plugins as well. + */ public class PurgeCommand implements ExecutableCommand { + private static final int MINIMUM_LAST_SEEN_DAYS = 30; + @Override public void executeCommand(CommandSender sender, List arguments, CommandService commandService) { - // AuthMe plugin instance - AuthMe plugin = commandService.getAuthMe(); - // Get the days parameter String daysStr = arguments.get(0); @@ -30,8 +33,9 @@ public class PurgeCommand implements ExecutableCommand { } // Validate the value - if (days < 30) { - sender.sendMessage(ChatColor.RED + "You can only purge data older than 30 days"); + if (days < MINIMUM_LAST_SEEN_DAYS) { + sender.sendMessage(ChatColor.RED + "You can only purge data older than " + + MINIMUM_LAST_SEEN_DAYS + " days"); return; } @@ -47,6 +51,7 @@ public class PurgeCommand implements ExecutableCommand { sender.sendMessage(ChatColor.GOLD + "Deleted " + purged.size() + " user accounts"); // Purge other data + AuthMe plugin = commandService.getAuthMe(); if (commandService.getProperty(PurgeSettings.REMOVE_ESSENTIALS_FILES) && commandService.getPluginHooks().isEssentialsAvailable()) plugin.dataManager.purgeEssentials(purged); diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java index 15a6e80b..118f8460 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java @@ -8,45 +8,39 @@ import org.bukkit.command.CommandSender; import java.util.List; +/** + * Removes the stored last position of a user or of all. + */ public class PurgeLastPositionCommand implements ExecutableCommand { @Override public void executeCommand(final CommandSender sender, List arguments, CommandService commandService) { String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0); - String playerNameLowerCase = playerName.toLowerCase(); - if (playerNameLowerCase.equalsIgnoreCase("*")) - { - for (PlayerAuth auth : commandService.getDataSource().getAllAuths()) - { - // Set the last position - auth.setQuitLocX(0D); - auth.setQuitLocY(0D); - auth.setQuitLocZ(0D); - auth.setWorld("world"); + if ("*".equals(playerName)) { + for (PlayerAuth auth : commandService.getDataSource().getAllAuths()) { + resetLastPosition(auth); commandService.getDataSource().updateQuitLoc(auth); - } - sender.sendMessage("All players last position locations are now reset"); - } - else - { + } + sender.sendMessage("All players last position locations are now reset"); + } else { // Get the user auth and make sure the user exists - PlayerAuth auth = commandService.getDataSource().getAuth(playerNameLowerCase); + PlayerAuth auth = commandService.getDataSource().getAuth(playerName); if (auth == null) { commandService.send(sender, MessageKey.UNKNOWN_USER); return; } - // Set the last position - auth.setQuitLocX(0D); - auth.setQuitLocY(0D); - auth.setQuitLocZ(0D); - auth.setWorld("world"); + resetLastPosition(auth); commandService.getDataSource().updateQuitLoc(auth); - - // Show a status message - sender.sendMessage(playerNameLowerCase + "'s last position location is now reset"); + sender.sendMessage(playerName + "'s last position location is now reset"); } + } + private static void resetLastPosition(PlayerAuth auth) { + auth.setQuitLocX(0d); + auth.setQuitLocY(0d); + auth.setQuitLocZ(0d); + auth.setWorld("world"); } } diff --git a/src/test/java/fr/xephi/authme/TestHelper.java b/src/test/java/fr/xephi/authme/TestHelper.java index 06ff06a4..5a6a2c8b 100644 --- a/src/test/java/fr/xephi/authme/TestHelper.java +++ b/src/test/java/fr/xephi/authme/TestHelper.java @@ -1,10 +1,15 @@ package fr.xephi.authme; +import fr.xephi.authme.command.CommandService; +import org.mockito.ArgumentCaptor; + import java.io.File; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; +import static org.mockito.Mockito.verify; + /** * AuthMe test utilities. */ @@ -47,4 +52,18 @@ public final class TestHelper { return url; } + /** + * Execute a {@link Runnable} passed to a mock's {@link CommandService#runTaskAsynchronously} method. + * Note that calling this method expects that there be a runnable sent to the method and will fail + * otherwise. + * + * @param service The mock service + */ + public static void runInnerRunnable(CommandService service) { + ArgumentCaptor captor = ArgumentCaptor.forClass(Runnable.class); + verify(service).runTaskAsynchronously(captor.capture()); + Runnable runnable = captor.getValue(); + runnable.run(); + } + } diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java index 92bcf4fc..abf422c4 100644 --- a/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java @@ -13,6 +13,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import static fr.xephi.authme.TestHelper.runInnerRunnable; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.BDDMockito.given; @@ -156,13 +157,6 @@ public class AccountsCommandTest { assertThat(messages[1], containsString("Tester, Lester, Taster")); } - private static void runInnerRunnable(CommandService service) { - ArgumentCaptor captor = ArgumentCaptor.forClass(Runnable.class); - verify(service).runTaskAsynchronously(captor.capture()); - Runnable runnable = captor.getValue(); - runnable.run(); - } - private static String[] getMessagesSentToSender(CommandSender sender, int expectedCount) { ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); verify(sender, times(expectedCount)).sendMessage(captor.capture()); diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/AuthMeCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/AuthMeCommandTest.java new file mode 100644 index 00000000..c7038ac6 --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/executable/authme/AuthMeCommandTest.java @@ -0,0 +1,38 @@ +package fr.xephi.authme.command.executable.authme; + +import fr.xephi.authme.command.CommandService; +import fr.xephi.authme.command.ExecutableCommand; +import org.bukkit.command.CommandSender; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.util.Collections; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * Test for {@link AuthMeCommand}. + */ +public class AuthMeCommandTest { + + @Test + public void shouldDisplayInformation() { + // given + ExecutableCommand command = new AuthMeCommand(); + CommandSender sender = mock(CommandSender.class); + CommandService service = mock(CommandService.class); + + // when + command.executeCommand(sender, Collections.EMPTY_LIST, service); + + // then + ArgumentCaptor messagesCaptor = ArgumentCaptor.forClass(String.class); + verify(sender, times(3)).sendMessage(messagesCaptor.capture()); + assertThat(messagesCaptor.getAllValues().get(1), containsString("/authme help")); + assertThat(messagesCaptor.getAllValues().get(2), containsString("/authme about")); + } +} diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommandTest.java new file mode 100644 index 00000000..28a6a3f8 --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommandTest.java @@ -0,0 +1,253 @@ +package fr.xephi.authme.command.executable.authme; + +import com.google.common.base.Strings; +import fr.xephi.authme.ConsoleLoggerTestInitializer; +import fr.xephi.authme.cache.auth.PlayerAuth; +import fr.xephi.authme.cache.auth.PlayerCache; +import fr.xephi.authme.command.CommandService; +import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.output.MessageKey; +import fr.xephi.authme.security.PasswordSecurity; +import fr.xephi.authme.security.crypts.HashedPassword; +import fr.xephi.authme.settings.properties.RestrictionSettings; +import fr.xephi.authme.settings.properties.SecuritySettings; +import org.bukkit.command.CommandSender; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Arrays; + +import static fr.xephi.authme.TestHelper.runInnerRunnable; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +/** + * Test for {@link ChangePasswordAdminCommand}. + */ +public class ChangePasswordAdminCommandTest { + + private CommandService service; + + @BeforeClass + public static void setUpLogger() { + ConsoleLoggerTestInitializer.setupLogger(); + } + + @Before + public void setUpServiceMock() { + service = mock(CommandService.class); + given(service.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX)).willReturn("[a-zA-Z]+"); + given(service.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)).willReturn(3); + given(service.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)).willReturn(20); + given(service.getProperty(SecuritySettings.UNSAFE_PASSWORDS)) + .willReturn(Arrays.asList("unsafe", "otherUnsafe")); + } + + @Test + public void shouldRejectPasswordSameAsUsername() { + // given + ExecutableCommand command = new ChangePasswordAdminCommand(); + CommandSender sender = mock(CommandSender.class); + + // when + command.executeCommand(sender, Arrays.asList("bobby", "Bobby"), service); + + // then + verify(service).send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR); + verify(service, never()).getDataSource(); + } + + @Test + public void shouldRejectPasswordNotMatchingPattern() { + // given + ExecutableCommand command = new ChangePasswordAdminCommand(); + CommandSender sender = mock(CommandSender.class); + // service mock returns pattern a-zA-Z -> numbers should not be accepted + String invalidPassword = "invalid1234"; + + // when + command.executeCommand(sender, Arrays.asList("myPlayer123", invalidPassword), service); + + // then + verify(service).send(sender, MessageKey.PASSWORD_MATCH_ERROR); + verify(service, never()).getDataSource(); + } + + @Test + public void shouldRejectTooShortPassword() { + // given + ExecutableCommand command = new ChangePasswordAdminCommand(); + CommandSender sender = mock(CommandSender.class); + + // when + command.executeCommand(sender, Arrays.asList("player", "ab"), service); + + // then + verify(service).send(sender, MessageKey.INVALID_PASSWORD_LENGTH); + verify(service, never()).getDataSource(); + } + + @Test + public void shouldRejectTooLongPassword() { + // given + ExecutableCommand command = new ChangePasswordAdminCommand(); + CommandSender sender = mock(CommandSender.class); + + // when + command.executeCommand(sender, Arrays.asList("player", Strings.repeat("a", 30)), service); + + // then + verify(service).send(sender, MessageKey.INVALID_PASSWORD_LENGTH); + verify(service, never()).getDataSource(); + } + + @Test + public void shouldRejectUnsafePassword() { + // given + ExecutableCommand command = new ChangePasswordAdminCommand(); + CommandSender sender = mock(CommandSender.class); + + // when + command.executeCommand(sender, Arrays.asList("player", "unsafe"), service); + + // then + verify(service).send(sender, MessageKey.PASSWORD_UNSAFE_ERROR); + verify(service, never()).getDataSource(); + } + + @Test + public void shouldRejectCommandForUnknownUser() { + // given + ExecutableCommand command = new ChangePasswordAdminCommand(); + CommandSender sender = mock(CommandSender.class); + String player = "player"; + + PlayerCache playerCache = mock(PlayerCache.class); + given(playerCache.isAuthenticated(player)).willReturn(false); + given(service.getPlayerCache()).willReturn(playerCache); + + DataSource dataSource = mock(DataSource.class); + given(dataSource.getAuth(player)).willReturn(null); + given(service.getDataSource()).willReturn(dataSource); + + // when + command.executeCommand(sender, Arrays.asList(player, "password"), service); + runInnerRunnable(service); + + // then + verify(service).send(sender, MessageKey.UNKNOWN_USER); + verify(dataSource, never()).updatePassword(any(PlayerAuth.class)); + } + + @Test + public void shouldUpdatePasswordOfLoggedInUser() { + // given + ExecutableCommand command = new ChangePasswordAdminCommand(); + CommandSender sender = mock(CommandSender.class); + + String player = "my_user12"; + String password = "passPass"; + PlayerAuth auth = mock(PlayerAuth.class); + + PlayerCache playerCache = mock(PlayerCache.class); + given(playerCache.isAuthenticated(player)).willReturn(true); + given(playerCache.getAuth(player)).willReturn(auth); + given(service.getPlayerCache()).willReturn(playerCache); + + PasswordSecurity passwordSecurity = mock(PasswordSecurity.class); + HashedPassword hashedPassword = mock(HashedPassword.class); + given(passwordSecurity.computeHash(password, player)).willReturn(hashedPassword); + given(service.getPasswordSecurity()).willReturn(passwordSecurity); + + DataSource dataSource = mock(DataSource.class); + given(dataSource.updatePassword(auth)).willReturn(true); + given(service.getDataSource()).willReturn(dataSource); + + // when + command.executeCommand(sender, Arrays.asList(player, password), service); + runInnerRunnable(service); + + // then + verify(service).send(sender, MessageKey.PASSWORD_CHANGED_SUCCESS); + verify(passwordSecurity).computeHash(password, player); + verify(auth).setPassword(hashedPassword); + verify(dataSource).updatePassword(auth); + } + + @Test + public void shouldUpdatePasswordOfOfflineUser() { + // given + ExecutableCommand command = new ChangePasswordAdminCommand(); + CommandSender sender = mock(CommandSender.class); + + String player = "my_user12"; + String password = "passPass"; + PlayerAuth auth = mock(PlayerAuth.class); + + PlayerCache playerCache = mock(PlayerCache.class); + given(playerCache.isAuthenticated(player)).willReturn(false); + given(service.getPlayerCache()).willReturn(playerCache); + + DataSource dataSource = mock(DataSource.class); + given(dataSource.isAuthAvailable(player)).willReturn(true); + given(dataSource.getAuth(player)).willReturn(auth); + given(dataSource.updatePassword(auth)).willReturn(true); + given(service.getDataSource()).willReturn(dataSource); + + PasswordSecurity passwordSecurity = mock(PasswordSecurity.class); + HashedPassword hashedPassword = mock(HashedPassword.class); + given(passwordSecurity.computeHash(password, player)).willReturn(hashedPassword); + given(service.getPasswordSecurity()).willReturn(passwordSecurity); + + // when + command.executeCommand(sender, Arrays.asList(player, password), service); + runInnerRunnable(service); + + // then + verify(service).send(sender, MessageKey.PASSWORD_CHANGED_SUCCESS); + verify(passwordSecurity).computeHash(password, player); + verify(auth).setPassword(hashedPassword); + verify(dataSource).updatePassword(auth); + } + + @Test + public void shouldReportWhenSaveFailed() { + // given + ExecutableCommand command = new ChangePasswordAdminCommand(); + CommandSender sender = mock(CommandSender.class); + + String player = "my_user12"; + String password = "passPass"; + PlayerAuth auth = mock(PlayerAuth.class); + + PlayerCache playerCache = mock(PlayerCache.class); + given(playerCache.isAuthenticated(player)).willReturn(true); + given(playerCache.getAuth(player)).willReturn(auth); + given(service.getPlayerCache()).willReturn(playerCache); + + PasswordSecurity passwordSecurity = mock(PasswordSecurity.class); + HashedPassword hashedPassword = mock(HashedPassword.class); + given(passwordSecurity.computeHash(password, player)).willReturn(hashedPassword); + given(service.getPasswordSecurity()).willReturn(passwordSecurity); + + DataSource dataSource = mock(DataSource.class); + given(dataSource.updatePassword(auth)).willReturn(false); + given(service.getDataSource()).willReturn(dataSource); + + // when + command.executeCommand(sender, Arrays.asList(player, password), service); + runInnerRunnable(service); + + // then + verify(service).send(sender, MessageKey.ERROR); + verify(passwordSecurity).computeHash(password, player); + verify(auth).setPassword(hashedPassword); + verify(dataSource).updatePassword(auth); + } + +} diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommandTest.java new file mode 100644 index 00000000..d6cc0af3 --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommandTest.java @@ -0,0 +1,65 @@ +package fr.xephi.authme.command.executable.authme; + +import fr.xephi.authme.command.CommandService; +import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.settings.SpawnLoader; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.util.Collections; + +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +/** + * Test for {@link FirstSpawnCommand}. + */ +public class FirstSpawnCommandTest { + + @Test + public void shouldTeleportToFirstSpawn() { + // given + Location firstSpawn = mock(Location.class); + SpawnLoader spawnLoader = mock(SpawnLoader.class); + given(spawnLoader.getFirstSpawn()).willReturn(firstSpawn); + CommandService service = mock(CommandService.class); + given(service.getSpawnLoader()).willReturn(spawnLoader); + Player player = mock(Player.class); + ExecutableCommand command = new FirstSpawnCommand(); + + // when + command.executeCommand(player, Collections.EMPTY_LIST, service); + + // then + verify(player).teleport(firstSpawn); + verify(spawnLoader, atLeastOnce()).getFirstSpawn(); + } + + @Test + public void shouldHandleMissingFirstSpawn() { + // given + SpawnLoader spawnLoader = mock(SpawnLoader.class); + given(spawnLoader.getFirstSpawn()).willReturn(null); + CommandService service = mock(CommandService.class); + given(service.getSpawnLoader()).willReturn(spawnLoader); + Player player = mock(Player.class); + ExecutableCommand command = new FirstSpawnCommand(); + + // when + command.executeCommand(player, Collections.EMPTY_LIST, service); + + // then + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(player).sendMessage(captor.capture()); + assertThat(captor.getValue(), containsString("spawn has failed")); + verify(player, never()).teleport(any(Location.class)); + } +} diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/GetEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/GetEmailCommandTest.java new file mode 100644 index 00000000..247c43ac --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/executable/authme/GetEmailCommandTest.java @@ -0,0 +1,68 @@ +package fr.xephi.authme.command.executable.authme; + +import fr.xephi.authme.cache.auth.PlayerAuth; +import fr.xephi.authme.command.CommandService; +import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.output.MessageKey; +import org.bukkit.command.CommandSender; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.util.Collections; + +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +/** + * Test for {@link GetEmailCommand}. + */ +public class GetEmailCommandTest { + + @Test + public void shouldReportUnknownUser() { + // given + String user = "myTestUser"; + DataSource dataSource = mock(DataSource.class); + given(dataSource.getAuth(user)).willReturn(null); + CommandService service = mock(CommandService.class); + given(service.getDataSource()).willReturn(dataSource); + + CommandSender sender = mock(CommandSender.class); + ExecutableCommand command = new GetEmailCommand(); + + // when + command.executeCommand(sender, Collections.singletonList(user), service); + + // then + verify(service).send(sender, MessageKey.UNKNOWN_USER); + } + + @Test + public void shouldReturnEmail() { + // given + String user = "userToView"; + String email = "user.email@example.org"; + PlayerAuth auth = mock(PlayerAuth.class); + given(auth.getEmail()).willReturn(email); + + DataSource dataSource = mock(DataSource.class); + given(dataSource.getAuth(user)).willReturn(auth); + CommandService service = mock(CommandService.class); + given(service.getDataSource()).willReturn(dataSource); + + CommandSender sender = mock(CommandSender.class); + ExecutableCommand command = new GetEmailCommand(); + + // when + command.executeCommand(sender, Collections.singletonList(user), service); + + // then + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(sender).sendMessage(captor.capture()); + assertThat(captor.getValue(), containsString(email)); + } +} diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/LastLoginCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/LastLoginCommandTest.java new file mode 100644 index 00000000..2df4a610 --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/executable/authme/LastLoginCommandTest.java @@ -0,0 +1,119 @@ +package fr.xephi.authme.command.executable.authme; + +import fr.xephi.authme.cache.auth.PlayerAuth; +import fr.xephi.authme.command.CommandService; +import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.output.MessageKey; +import org.bukkit.command.CommandSender; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.util.Collections; +import java.util.Date; + +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * Test for {@link LastLoginCommand}. + */ +public class LastLoginCommandTest { + + private static final long HOUR_IN_MSEC = 3600 * 1000; + private static final long DAY_IN_MSEC = 24 * HOUR_IN_MSEC; + + @Test + public void shouldRejectNonExistentUser() { + // given + String player = "tester"; + DataSource dataSource = mock(DataSource.class); + given(dataSource.getAuth(player)).willReturn(null); + + CommandService service = mock(CommandService.class); + given(service.getDataSource()).willReturn(dataSource); + + CommandSender sender = mock(CommandSender.class); + ExecutableCommand command = new LastLoginCommand(); + + // when + command.executeCommand(sender, Collections.singletonList(player), service); + + // then + verify(dataSource).getAuth(player); + verify(service).send(sender, MessageKey.USER_NOT_REGISTERED); + } + + @Test + public void shouldDisplayLastLoginOfUser() { + // given + String player = "SomePlayer"; + long lastLogin = System.currentTimeMillis() - + (412 * DAY_IN_MSEC + 10 * HOUR_IN_MSEC - 9000); + PlayerAuth auth = mock(PlayerAuth.class); + given(auth.getLastLogin()).willReturn(lastLogin); + given(auth.getIp()).willReturn("123.45.66.77"); + + DataSource dataSource = mock(DataSource.class); + given(dataSource.getAuth(player)).willReturn(auth); + CommandService service = mock(CommandService.class); + given(service.getDataSource()).willReturn(dataSource); + + CommandSender sender = mock(CommandSender.class); + ExecutableCommand command = new LastLoginCommand(); + + // when + command.executeCommand(sender, Collections.singletonList(player), service); + + // then + verify(dataSource).getAuth(player); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(sender, times(3)).sendMessage(captor.capture()); + String lastLoginString = new Date(lastLogin).toString(); + assertThat(captor.getAllValues().get(0), + allOf(containsString(player), containsString(lastLoginString))); + assertThat(captor.getAllValues().get(1), containsString("412 days 9 hours")); + assertThat(captor.getAllValues().get(2), containsString("123.45.66.77")); + } + + @Test + public void shouldDisplayLastLoginOfCommandSender() { + // given + String name = "CommandSender"; + CommandSender sender = mock(CommandSender.class); + given(sender.getName()).willReturn(name); + + long lastLogin = System.currentTimeMillis() - + (412 * DAY_IN_MSEC + 10 * HOUR_IN_MSEC - 9000); + PlayerAuth auth = mock(PlayerAuth.class); + given(auth.getLastLogin()).willReturn(lastLogin); + given(auth.getIp()).willReturn("123.45.66.77"); + + DataSource dataSource = mock(DataSource.class); + given(dataSource.getAuth(name)).willReturn(auth); + CommandService service = mock(CommandService.class); + given(service.getDataSource()).willReturn(dataSource); + + + ExecutableCommand command = new LastLoginCommand(); + + // when + command.executeCommand(sender, Collections.EMPTY_LIST, service); + + // then + verify(dataSource).getAuth(name); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(sender, times(3)).sendMessage(captor.capture()); + String lastLoginString = new Date(lastLogin).toString(); + assertThat(captor.getAllValues().get(0), + allOf(containsString(name), containsString(lastLoginString))); + assertThat(captor.getAllValues().get(1), containsString("412 days 9 hours")); + assertThat(captor.getAllValues().get(2), containsString("123.45.66.77")); + } + +} diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommandTest.java new file mode 100644 index 00000000..d24d57b4 --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommandTest.java @@ -0,0 +1,124 @@ +package fr.xephi.authme.command.executable.authme; + +import fr.xephi.authme.cache.auth.PlayerAuth; +import fr.xephi.authme.command.CommandService; +import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.output.MessageKey; +import org.bukkit.command.CommandSender; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; + +import static org.hamcrest.Matchers.containsString; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +/** + * Test for {@link PurgeLastPositionCommand}. + */ +public class PurgeLastPositionCommandTest { + + @Test + public void shouldPurgeLastPosOfUser() { + // given + String player = "_Bobby"; + PlayerAuth auth = mock(PlayerAuth.class); + + DataSource dataSource = mock(DataSource.class); + given(dataSource.getAuth(player)).willReturn(auth); + CommandService service = mock(CommandService.class); + given(service.getDataSource()).willReturn(dataSource); + + CommandSender sender = mock(CommandSender.class); + ExecutableCommand command = new PurgeLastPositionCommand(); + + // when + command.executeCommand(sender, Collections.singletonList(player), service); + + // then + verify(dataSource).getAuth(player); + verifyPositionWasReset(auth); + verify(sender).sendMessage(argThat(containsString("last position location is now reset"))); + } + + @Test + public void shouldPurgePositionOfCommandSender() { + // given + String player = "_Bobby"; + CommandSender sender = mock(CommandSender.class); + given(sender.getName()).willReturn(player); + + PlayerAuth auth = mock(PlayerAuth.class); + DataSource dataSource = mock(DataSource.class); + given(dataSource.getAuth(player)).willReturn(auth); + CommandService service = mock(CommandService.class); + given(service.getDataSource()).willReturn(dataSource); + + ExecutableCommand command = new PurgeLastPositionCommand(); + + // when + command.executeCommand(sender, Collections.EMPTY_LIST, service); + + // then + verify(dataSource).getAuth(player); + verifyPositionWasReset(auth); + verify(sender).sendMessage(argThat(containsString("position location is now reset"))); + } + + @Test + public void shouldHandleNonExistentUser() { + // given + DataSource dataSource = mock(DataSource.class); + CommandService service = mock(CommandService.class); + given(service.getDataSource()).willReturn(dataSource); + + ExecutableCommand command = new PurgeLastPositionCommand(); + CommandSender sender = mock(CommandSender.class); + String name = "invalidPlayer"; + + // when + command.executeCommand(sender, Collections.singletonList(name), service); + + // then + verify(dataSource).getAuth(name); + verify(service).send(sender, MessageKey.UNKNOWN_USER); + } + + @Test + public void shouldResetAllLastPositions() { + // given + PlayerAuth auth1 = mock(PlayerAuth.class); + PlayerAuth auth2 = mock(PlayerAuth.class); + PlayerAuth auth3 = mock(PlayerAuth.class); + + DataSource dataSource = mock(DataSource.class); + given(dataSource.getAllAuths()).willReturn(Arrays.asList(auth1, auth2, auth3)); + CommandService service = mock(CommandService.class); + given(service.getDataSource()).willReturn(dataSource); + + ExecutableCommand command = new PurgeLastPositionCommand(); + CommandSender sender = mock(CommandSender.class); + + // when + command.executeCommand(sender, Collections.singletonList("*"), service); + + // then + verify(dataSource).getAllAuths(); + verifyPositionWasReset(auth1); + verifyPositionWasReset(auth2); + verifyPositionWasReset(auth3); + verify(sender).sendMessage(argThat(containsString("last position locations are now reset"))); + } + + + private static void verifyPositionWasReset(PlayerAuth auth) { + verify(auth).setQuitLocX(0); + verify(auth).setQuitLocY(0); + verify(auth).setQuitLocZ(0); + verify(auth).setWorld("world"); + } +} diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/ReloadCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/ReloadCommandTest.java new file mode 100644 index 00000000..deb6c50f --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/executable/authme/ReloadCommandTest.java @@ -0,0 +1,65 @@ +package fr.xephi.authme.command.executable.authme; + +import fr.xephi.authme.AuthMe; +import fr.xephi.authme.ConsoleLoggerTestInitializer; +import fr.xephi.authme.command.CommandService; +import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.output.MessageKey; +import org.bukkit.command.CommandSender; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Collections; + +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.matches; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +/** + * Test for {@link ReloadCommand}. + */ +public class ReloadCommandTest { + + @BeforeClass + public static void setUpLogger() { + ConsoleLoggerTestInitializer.setupLogger(); + } + + @Test + public void shouldReload() throws Exception { + // given + AuthMe authMe = mock(AuthMe.class); + CommandService service = mock(CommandService.class); + given(service.getAuthMe()).willReturn(authMe); + CommandSender sender = mock(CommandSender.class); + ExecutableCommand command = new ReloadCommand(); + + // when + command.executeCommand(sender, Collections.EMPTY_LIST, service); + + // then + verify(authMe).reload(); + verify(service).send(sender, MessageKey.CONFIG_RELOAD_SUCCESS); + } + + @Test + public void shouldHandleReloadError() throws Exception { + // given + AuthMe authMe = mock(AuthMe.class); + doThrow(IllegalStateException.class).when(authMe).reload(); + CommandService service = mock(CommandService.class); + given(service.getAuthMe()).willReturn(authMe); + CommandSender sender = mock(CommandSender.class); + ExecutableCommand command = new ReloadCommand(); + + // when + command.executeCommand(sender, Collections.EMPTY_LIST, service); + + // then + verify(authMe).reload(); + verify(sender).sendMessage(matches("Error occurred.*")); + verify(authMe).stopOrUnload(); + } +} diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommandTest.java new file mode 100644 index 00000000..e56e297b --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommandTest.java @@ -0,0 +1,66 @@ +package fr.xephi.authme.command.executable.authme; + +import fr.xephi.authme.command.CommandService; +import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.settings.SpawnLoader; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.junit.Test; + +import java.util.Collections; + +import static org.hamcrest.Matchers.containsString; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +/** + * Test for {@link SetFirstSpawnCommand}. + */ +public class SetFirstSpawnCommandTest { + + @Test + public void shouldSetFirstSpawn() { + // given + Player player = mock(Player.class); + Location location = mock(Location.class); + given(player.getLocation()).willReturn(location); + + SpawnLoader spawnLoader = mock(SpawnLoader.class); + given(spawnLoader.setFirstSpawn(location)).willReturn(true); + CommandService service = mock(CommandService.class); + given(service.getSpawnLoader()).willReturn(spawnLoader); + + ExecutableCommand command = new SetFirstSpawnCommand(); + + // when + command.executeCommand(player, Collections.EMPTY_LIST, service); + + // then + verify(spawnLoader).setFirstSpawn(location); + verify(player).sendMessage(argThat(containsString("defined new first spawn"))); + } + + @Test + public void shouldHandleError() { + // given + Player player = mock(Player.class); + Location location = mock(Location.class); + given(player.getLocation()).willReturn(location); + + SpawnLoader spawnLoader = mock(SpawnLoader.class); + given(spawnLoader.setFirstSpawn(location)).willReturn(false); + CommandService service = mock(CommandService.class); + given(service.getSpawnLoader()).willReturn(spawnLoader); + + ExecutableCommand command = new SetFirstSpawnCommand(); + + // when + command.executeCommand(player, Collections.EMPTY_LIST, service); + + // then + verify(spawnLoader).setFirstSpawn(location); + verify(player).sendMessage(argThat(containsString("has failed"))); + } +} diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/SetSpawnCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/SetSpawnCommandTest.java new file mode 100644 index 00000000..11c2f42c --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/executable/authme/SetSpawnCommandTest.java @@ -0,0 +1,66 @@ +package fr.xephi.authme.command.executable.authme; + +import fr.xephi.authme.command.CommandService; +import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.settings.SpawnLoader; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.junit.Test; + +import java.util.Collections; + +import static org.hamcrest.Matchers.containsString; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +/** + * Test for {@link SetSpawnCommand}. + */ +public class SetSpawnCommandTest { + + @Test + public void shouldSetSpawn() { + // given + Player player = mock(Player.class); + Location location = mock(Location.class); + given(player.getLocation()).willReturn(location); + + SpawnLoader spawnLoader = mock(SpawnLoader.class); + given(spawnLoader.setSpawn(location)).willReturn(true); + CommandService service = mock(CommandService.class); + given(service.getSpawnLoader()).willReturn(spawnLoader); + + ExecutableCommand command = new SetSpawnCommand(); + + // when + command.executeCommand(player, Collections.EMPTY_LIST, service); + + // then + verify(spawnLoader).setSpawn(location); + verify(player).sendMessage(argThat(containsString("defined new spawn"))); + } + + @Test + public void shouldHandleError() { + // given + Player player = mock(Player.class); + Location location = mock(Location.class); + given(player.getLocation()).willReturn(location); + + SpawnLoader spawnLoader = mock(SpawnLoader.class); + given(spawnLoader.setSpawn(location)).willReturn(false); + CommandService service = mock(CommandService.class); + given(service.getSpawnLoader()).willReturn(spawnLoader); + + ExecutableCommand command = new SetSpawnCommand(); + + // when + command.executeCommand(player, Collections.EMPTY_LIST, service); + + // then + verify(spawnLoader).setSpawn(location); + verify(player).sendMessage(argThat(containsString("has failed"))); + } +} diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/SpawnCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/SpawnCommandTest.java new file mode 100644 index 00000000..305c41ba --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/executable/authme/SpawnCommandTest.java @@ -0,0 +1,65 @@ +package fr.xephi.authme.command.executable.authme; + +import fr.xephi.authme.command.CommandService; +import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.settings.SpawnLoader; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.util.Collections; + +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +/** + * Test for {@link SpawnCommand}. + */ +public class SpawnCommandTest { + + @Test + public void shouldTeleportToSpawn() { + // given + Location spawn = mock(Location.class); + SpawnLoader spawnLoader = mock(SpawnLoader.class); + given(spawnLoader.getSpawn()).willReturn(spawn); + CommandService service = mock(CommandService.class); + given(service.getSpawnLoader()).willReturn(spawnLoader); + Player player = mock(Player.class); + ExecutableCommand command = new SpawnCommand(); + + // when + command.executeCommand(player, Collections.EMPTY_LIST, service); + + // then + verify(player).teleport(spawn); + verify(spawnLoader, atLeastOnce()).getSpawn(); + } + + @Test + public void shouldHandleMissingSpawn() { + // given + SpawnLoader spawnLoader = mock(SpawnLoader.class); + given(spawnLoader.getSpawn()).willReturn(null); + CommandService service = mock(CommandService.class); + given(service.getSpawnLoader()).willReturn(spawnLoader); + Player player = mock(Player.class); + ExecutableCommand command = new FirstSpawnCommand(); + + // when + command.executeCommand(player, Collections.EMPTY_LIST, service); + + // then + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(player).sendMessage(captor.capture()); + assertThat(captor.getValue(), containsString("spawn has failed")); + verify(player, never()).teleport(any(Location.class)); + } +}