From 26716b0f790bd8dec139629f3e80303be2e85216 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Fri, 7 Oct 2016 22:28:08 +0200 Subject: [PATCH] #293 Create class for handling messages from file with fallback - Move logic for loading a messages file with a default fallback into one class - Remove message-specific handling from Settings class --- .../authme/command/help/HelpMessageKey.java | 38 ++-- .../command/help/HelpMessagesService.java | 56 ++---- .../authme/message/MessageFileCopier.java | 63 ------- .../authme/message/MessageFileHandler.java | 89 +++++++++ .../message/MessageFileHandlerProvider.java | 67 +++++++ .../fr/xephi/authme/message/Messages.java | 52 +----- .../fr/xephi/authme/settings/Settings.java | 45 ----- .../authme/command/help/HelpProviderTest.java | 4 + .../MessageFileHandlerProviderTest.java | 175 ++++++++++++++++++ .../message/MessagesIntegrationTest.java | 23 +-- .../xephi/authme/settings/SettingsTest.java | 85 +-------- 11 files changed, 385 insertions(+), 312 deletions(-) delete mode 100644 src/main/java/fr/xephi/authme/message/MessageFileCopier.java create mode 100644 src/main/java/fr/xephi/authme/message/MessageFileHandler.java create mode 100644 src/main/java/fr/xephi/authme/message/MessageFileHandlerProvider.java create mode 100644 src/test/java/fr/xephi/authme/message/MessageFileHandlerProviderTest.java diff --git a/src/main/java/fr/xephi/authme/command/help/HelpMessageKey.java b/src/main/java/fr/xephi/authme/command/help/HelpMessageKey.java index bfa5ba910..dbd6b7939 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpMessageKey.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpMessageKey.java @@ -6,44 +6,44 @@ package fr.xephi.authme.command.help; */ public enum HelpMessageKey { - SHORT_DESCRIPTION("description.short", "Short description"), + SHORT_DESCRIPTION("description.short"), - DETAILED_DESCRIPTION("description.detailed", "Detailed description"), + DETAILED_DESCRIPTION("description.detailed"), - USAGE("usage", "Usage"), + USAGE("usage"), - ARGUMENTS("arguments", "Arguments"), + ARGUMENTS("arguments"), - OPTIONAL("optional", "(Optional)"), + OPTIONAL("optional"), - HAS_PERMISSION("hasPermission", "You have permission"), + HAS_PERMISSION("hasPermission"), - NO_PERMISSION("noPermission", "No permission"), + NO_PERMISSION("noPermission"), - ALTERNATIVES("alternatives", "Alternatives"), + ALTERNATIVES("alternatives"), - DEFAULT("default", "Default"), + DEFAULT("default"), - RESULT("result", "Result"), + RESULT("result"), - PERMISSIONS("permissions", "Permissions"), + PERMISSIONS("permissions"), - COMMANDS("commands", "Commands"); + COMMANDS("commands"); private final String key; - private final String fallback; - HelpMessageKey(String key, String fallback) { + /** + * Constructor. + * + * @param key the message key + */ + HelpMessageKey(String key) { this.key = "common." + key; - this.fallback = fallback; } + /** @return the message key */ public String getKey() { return key; } - - public String getFallback() { - return fallback; - } } diff --git a/src/main/java/fr/xephi/authme/command/help/HelpMessagesService.java b/src/main/java/fr/xephi/authme/command/help/HelpMessagesService.java index 92d39a456..621c2cc3b 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpMessagesService.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpMessagesService.java @@ -5,16 +5,11 @@ import fr.xephi.authme.command.CommandArgumentDescription; import fr.xephi.authme.command.CommandDescription; import fr.xephi.authme.command.CommandUtils; import fr.xephi.authme.initialization.Reloadable; -import fr.xephi.authme.message.MessageFileCopier; -import fr.xephi.authme.message.MessageFileCopier.MessageFileData; -import fr.xephi.authme.message.Messages; +import fr.xephi.authme.message.MessageFileHandlerProvider; +import fr.xephi.authme.message.MessageFileHandler; import fr.xephi.authme.permission.DefaultPermission; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; import javax.inject.Inject; -import java.io.InputStream; -import java.io.InputStreamReader; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -28,14 +23,12 @@ public class HelpMessagesService implements Reloadable { private static final String DETAILED_DESCRIPTION_SUFFIX = ".detailedDescription"; private static final String DEFAULT_PERMISSIONS_PATH = "common.defaultPermissions."; - private final MessageFileCopier fileCopier; - private FileConfiguration fileConfiguration; - private String defaultFile; - private FileConfiguration defaultConfiguration; + private final MessageFileHandlerProvider messageFileHandlerProvider; + private MessageFileHandler messageFileHandler; @Inject - HelpMessagesService(MessageFileCopier fileCopier) { - this.fileCopier = fileCopier; + HelpMessagesService(MessageFileHandlerProvider messageFileHandlerProvider) { + this.messageFileHandlerProvider = messageFileHandlerProvider; reload(); } @@ -47,7 +40,7 @@ public class HelpMessagesService implements Reloadable { */ public CommandDescription buildLocalizedDescription(CommandDescription command) { final String path = getCommandPath(command); - if (fileConfiguration.get(path) == null) { + if (!messageFileHandler.hasSection(path)) { // Messages file does not have a section for this command - return the provided command return command; } @@ -73,49 +66,24 @@ public class HelpMessagesService implements Reloadable { } public String getMessage(HelpMessageKey key) { - String message = fileConfiguration.getString(key.getKey()); - return message == null - ? getDefault(key.getKey()) - : message; + return messageFileHandler.getMessage(key.getKey()); } public String getMessage(DefaultPermission defaultPermission) { // e.g. {default_permissions_path}.opOnly for DefaultPermission.OP_ONLY String path = DEFAULT_PERMISSIONS_PATH + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, defaultPermission.name()); - String message = fileConfiguration.getString(path); - if (message != null) { - return message; - } - return getDefault(path); + return messageFileHandler.getMessage(path); } @Override public void reload() { - MessageFileData fileData = fileCopier.initializeData(lang -> "messages/help_" + lang + ".yml"); - this.fileConfiguration = YamlConfiguration.loadConfiguration(fileData.getFile()); - this.defaultFile = fileData.getDefaultFile(); - } - - private String getDefault(String code) { - if (defaultFile == null) { - return getDefaultErrorMessage(code); - } - - if (defaultConfiguration == null) { - InputStream stream = Messages.class.getResourceAsStream(defaultFile); - defaultConfiguration = YamlConfiguration.loadConfiguration(new InputStreamReader(stream)); - } - String message = defaultConfiguration.getString(code); - return message == null ? getDefaultErrorMessage(code) : message; - } - - private static String getDefaultErrorMessage(String code) { - return "Error retrieving message '" + code + "'"; + messageFileHandler = messageFileHandlerProvider.initializeHandler( + lang -> "messages/help_" + lang + ".yml"); } private String getText(String path, Supplier defaultTextGetter) { - String message = fileConfiguration.getString(path); + String message = messageFileHandler.getMessageIfExists(path); return message == null ? defaultTextGetter.get() : message; diff --git a/src/main/java/fr/xephi/authme/message/MessageFileCopier.java b/src/main/java/fr/xephi/authme/message/MessageFileCopier.java deleted file mode 100644 index b8e32b7dd..000000000 --- a/src/main/java/fr/xephi/authme/message/MessageFileCopier.java +++ /dev/null @@ -1,63 +0,0 @@ -package fr.xephi.authme.message; - -import fr.xephi.authme.initialization.DataFolder; -import fr.xephi.authme.settings.Settings; -import fr.xephi.authme.settings.properties.PluginSettings; -import fr.xephi.authme.util.FileUtils; - -import javax.inject.Inject; -import java.io.File; -import java.util.function.Function; - -public class MessageFileCopier { - - private static final String DEFAULT_LANGUAGE = "en"; - - private final File dataFolder; - private final Settings settings; - - @Inject - MessageFileCopier(@DataFolder File dataFolder, Settings settings) { - this.dataFolder = dataFolder; - this.settings = settings; - } - - public MessageFileData initializeData(Function pathBuilder) { - String language = settings.getProperty(PluginSettings.MESSAGES_LANGUAGE); - return new MessageFileData( - initializeFile(language, pathBuilder), - pathBuilder.apply(DEFAULT_LANGUAGE)); - } - - private File initializeFile(String language, Function pathBuilder) { - String filePath = pathBuilder.apply(language); - File file = new File(dataFolder, filePath); - if (FileUtils.copyFileFromResource(file, filePath)) { - return file; - } - - String defaultFilePath = pathBuilder.apply(DEFAULT_LANGUAGE); - if (FileUtils.copyFileFromResource(file, defaultFilePath)) { - return file; - } - return null; - } - - public static final class MessageFileData { - private final File file; - private final String defaultFile; - - MessageFileData(File file, String defaultFile) { - this.file = file; - this.defaultFile = defaultFile; - } - - public File getFile() { - return file; - } - - public String getDefaultFile() { - return defaultFile; - } - } -} diff --git a/src/main/java/fr/xephi/authme/message/MessageFileHandler.java b/src/main/java/fr/xephi/authme/message/MessageFileHandler.java new file mode 100644 index 000000000..be7f69286 --- /dev/null +++ b/src/main/java/fr/xephi/authme/message/MessageFileHandler.java @@ -0,0 +1,89 @@ +package fr.xephi.authme.message; + +import fr.xephi.authme.ConsoleLogger; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** + * Handles a YAML message file with a default file fallback. + */ +public final class MessageFileHandler { + + // regular file + private final String filename; + private final FileConfiguration configuration; + // default file + private final String defaultFile; + private FileConfiguration defaultConfiguration; + + /** + * Constructor. + * + * @param file the file to use for messages + * @param defaultFile the default file from the JAR to use if no message is found + */ + MessageFileHandler(File file, String defaultFile) { + this.filename = file.getName(); + this.configuration = YamlConfiguration.loadConfiguration(file); + this.defaultFile = defaultFile; + } + + /** + * Returns whether the message file configuration has an entry at the given path. + * + * @param path the path to verify + * @return true if an entry exists for the path in the messages file, false otherwise + */ + public boolean hasSection(String path) { + return configuration.get(path) != null; + } + + /** + * Returns the message for the given key. + * + * @param key the key to retrieve the message for + * @return the message + */ + public String getMessage(String key) { + String message = configuration.getString(key); + + if (message == null) { + ConsoleLogger.warning("Error getting message with key '" + key + "'. " + + "Please verify your config file at '" + filename + "'"); + return getDefault(key); + } + return message; + } + + /** + * Returns the message for the given key only if it exists, + * i.e. without falling back to the default file. + * + * @param key the key to retrieve the message for + * @return the message, or {@code null} if not available + */ + public String getMessageIfExists(String key) { + return configuration.getString(key); + } + + /** + * Gets the message from the default file. + * + * @param key the key to retrieve the message for + * @return the message from the default file + */ + private String getDefault(String key) { + if (defaultConfiguration == null) { + InputStream stream = Messages.class.getResourceAsStream(defaultFile); + defaultConfiguration = YamlConfiguration.loadConfiguration(new InputStreamReader(stream)); + } + String message = defaultConfiguration.getString(key); + return message == null + ? "Error retrieving message '" + key + "'" + : message; + } +} diff --git a/src/main/java/fr/xephi/authme/message/MessageFileHandlerProvider.java b/src/main/java/fr/xephi/authme/message/MessageFileHandlerProvider.java new file mode 100644 index 000000000..987caeccc --- /dev/null +++ b/src/main/java/fr/xephi/authme/message/MessageFileHandlerProvider.java @@ -0,0 +1,67 @@ +package fr.xephi.authme.message; + +import com.google.common.annotations.VisibleForTesting; +import fr.xephi.authme.initialization.DataFolder; +import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.settings.properties.PluginSettings; +import fr.xephi.authme.util.FileUtils; + +import javax.inject.Inject; +import java.io.File; +import java.util.function.Function; + +/** + * Injectable creator of {@link MessageFileHandler} instances. + * + * @see MessageFileHandler + */ +public class MessageFileHandlerProvider { + + private static final String DEFAULT_LANGUAGE = "en"; + + @Inject + @DataFolder + private File dataFolder; + @Inject + private Settings settings; + + MessageFileHandlerProvider() { + } + + /** + * Initializes a message file handler with the messages file of the configured language. + * Ensures beforehand that the messages file exists or creates it otherwise. + * + * @param pathBuilder function taking the configured language code as argument and returning the messages file + * @return the message file handler + */ + public MessageFileHandler initializeHandler(Function pathBuilder) { + String language = settings.getProperty(PluginSettings.MESSAGES_LANGUAGE); + return new MessageFileHandler( + initializeFile(language, pathBuilder), + pathBuilder.apply(DEFAULT_LANGUAGE)); + } + + /** + * Copies the messages file from the JAR if it doesn't exist. + * + * @param language the configured language code + * @param pathBuilder function returning message file name with language as argument + * @return the messages file to use + */ + @VisibleForTesting + File initializeFile(String language, Function pathBuilder) { + String filePath = pathBuilder.apply(language); + File file = new File(dataFolder, filePath); + if (FileUtils.copyFileFromResource(file, filePath)) { + return file; + } + + String defaultFilePath = pathBuilder.apply(DEFAULT_LANGUAGE); + if (FileUtils.copyFileFromResource(file, defaultFilePath)) { + return file; + } + return null; + } + +} diff --git a/src/main/java/fr/xephi/authme/message/Messages.java b/src/main/java/fr/xephi/authme/message/Messages.java index ff3ebeee9..86fa2db6f 100644 --- a/src/main/java/fr/xephi/authme/message/Messages.java +++ b/src/main/java/fr/xephi/authme/message/Messages.java @@ -2,16 +2,10 @@ package fr.xephi.authme.message; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.initialization.Reloadable; -import fr.xephi.authme.message.MessageFileCopier.MessageFileData; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; import javax.inject.Inject; -import java.io.File; -import java.io.InputStream; -import java.io.InputStreamReader; /** * Class for retrieving and sending translatable messages to players. @@ -21,18 +15,15 @@ public class Messages implements Reloadable { // Custom Authme tag replaced to new line private static final String NEWLINE_TAG = "%nl%"; - private final MessageFileCopier fileCopier; - private FileConfiguration configuration; - private String fileName; - private String defaultFile; - private FileConfiguration defaultConfiguration; + private final MessageFileHandlerProvider messageFileHandlerProvider; + private MessageFileHandler messageFileHandler; /* * Constructor. */ @Inject - Messages(MessageFileCopier fileCopier) { - this.fileCopier = fileCopier; + Messages(MessageFileHandlerProvider messageFileHandlerProvider) { + this.messageFileHandlerProvider = messageFileHandlerProvider; reload(); } @@ -87,15 +78,8 @@ public class Messages implements Reloadable { * @return The message from the file */ private String retrieveMessage(MessageKey key) { - final String code = key.getKey(); - String message = configuration.getString(code); - - if (message == null) { - ConsoleLogger.warning("Error getting message with key '" + code + "'. " - + "Please verify your config file at '" + fileName + "'"); - return formatMessage(getDefault(code)); - } - return formatMessage(message); + return formatMessage( + messageFileHandler.getMessage(key.getKey())); } /** @@ -122,28 +106,8 @@ public class Messages implements Reloadable { @Override public void reload() { - MessageFileData messageFileData = fileCopier.initializeData(lang -> "messages/messages_" + lang + ".yml"); - File messageFile = messageFileData.getFile(); - this.configuration = YamlConfiguration.loadConfiguration(messageFile); - this.fileName = messageFile.getName(); - this.defaultFile = messageFileData.getDefaultFile(); - } - - private String getDefault(String code) { - if (defaultFile == null) { - return getDefaultErrorMessage(code); - } - - if (defaultConfiguration == null) { - InputStream stream = Messages.class.getResourceAsStream(defaultFile); - defaultConfiguration = YamlConfiguration.loadConfiguration(new InputStreamReader(stream)); - } - String message = defaultConfiguration.getString(code); - return message == null ? getDefaultErrorMessage(code) : message; - } - - private static String getDefaultErrorMessage(String code) { - return "Error retrieving message '" + code + "'"; + this.messageFileHandler = messageFileHandlerProvider + .initializeHandler(lang -> "messages/messages_" + lang + ".yml"); } private static String formatMessage(String message) { diff --git a/src/main/java/fr/xephi/authme/settings/Settings.java b/src/main/java/fr/xephi/authme/settings/Settings.java index 2f5a34cc4..e2ebd0aa6 100644 --- a/src/main/java/fr/xephi/authme/settings/Settings.java +++ b/src/main/java/fr/xephi/authme/settings/Settings.java @@ -6,8 +6,6 @@ import com.github.authme.configme.migration.MigrationService; import com.github.authme.configme.resource.PropertyResource; import com.google.common.io.Files; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.settings.properties.PluginSettings; -import fr.xephi.authme.util.FileUtils; import java.io.File; import java.io.IOException; @@ -22,8 +20,6 @@ import static fr.xephi.authme.util.FileUtils.copyFileFromResource; public class Settings extends SettingsManager { private final File pluginFolder; - /** The file with the localized messages based on {@link PluginSettings#MESSAGES_LANGUAGE}. */ - private File messagesFile; private String[] welcomeMessage; private String passwordEmailMessage; private String recoveryCodeEmailMessage; @@ -43,24 +39,6 @@ public class Settings extends SettingsManager { loadSettingsFromFiles(); } - /** - * Return the messages file based on the messages language config. - * - * @return The messages file to read messages from - */ - public File getMessagesFile() { - return messagesFile; - } - - /** - * Return the path to the default messages file within the JAR. - * - * @return The default messages file path - */ - public String getDefaultMessagesFile() { - return "/messages/messages_en.yml"; - } - /** * Return the text to use in email registrations. * @@ -89,7 +67,6 @@ public class Settings extends SettingsManager { } private void loadSettingsFromFiles() { - messagesFile = buildMessagesFile(); passwordEmailMessage = readFile("email.html"); recoveryCodeEmailMessage = readFile("recovery_code_email.html"); welcomeMessage = readFile("welcome.txt").split("\n"); @@ -101,28 +78,6 @@ public class Settings extends SettingsManager { loadSettingsFromFiles(); } - private File buildMessagesFile() { - String languageCode = getProperty(PluginSettings.MESSAGES_LANGUAGE); - - String filePath = buildMessagesFilePathFromCode(languageCode); - File messagesFile = new File(pluginFolder, filePath); - if (copyFileFromResource(messagesFile, filePath)) { - return messagesFile; - } - - // File doesn't exist or couldn't be copied - try again with default, "en" - String defaultFilePath = buildMessagesFilePathFromCode("en"); - File defaultFile = new File(pluginFolder, defaultFilePath); - copyFileFromResource(defaultFile, defaultFilePath); - - // No matter the result, need to return a file - return defaultFile; - } - - private static String buildMessagesFilePathFromCode(String language) { - return FileUtils.makePath("messages", "messages_" + language + ".yml"); - } - /** * Reads a file from the plugin folder or copies it from the JAR to the plugin folder. * diff --git a/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java b/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java index e78fc9d61..1308b2407 100644 --- a/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java +++ b/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java @@ -18,6 +18,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.mockito.internal.stubbing.answers.ReturnsArgumentAt; import java.util.Arrays; import java.util.Collections; @@ -38,6 +39,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; 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.verify; @@ -70,6 +72,8 @@ public class HelpProviderTest { @BeforeInjecting public void setInitialSettings() { given(settings.getProperty(PluginSettings.HELP_HEADER)).willReturn(HELP_HEADER); + given(helpMessagesService.buildLocalizedDescription(any(CommandDescription.class))) + .willAnswer(new ReturnsArgumentAt(0)); } @Test diff --git a/src/test/java/fr/xephi/authme/message/MessageFileHandlerProviderTest.java b/src/test/java/fr/xephi/authme/message/MessageFileHandlerProviderTest.java new file mode 100644 index 000000000..044b3411d --- /dev/null +++ b/src/test/java/fr/xephi/authme/message/MessageFileHandlerProviderTest.java @@ -0,0 +1,175 @@ +package fr.xephi.authme.message; + +import ch.jalu.injector.testing.BeforeInjecting; +import ch.jalu.injector.testing.DelayedInjectionRunner; +import ch.jalu.injector.testing.InjectDelayed; +import com.google.common.io.Files; +import fr.xephi.authme.TestHelper; +import fr.xephi.authme.initialization.DataFolder; +import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.settings.properties.PluginSettings; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; + +import java.io.File; +import java.io.IOException; +import java.util.function.Function; + +import static fr.xephi.authme.TestHelper.getJarFile; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; + +/** + * Test for {@link MessageFileHandlerProvider}. + */ +@RunWith(DelayedInjectionRunner.class) +public class MessageFileHandlerProviderTest { + + private static final Function MESSAGES_BUILDER = lang -> "messages/messages_" + lang + ".yml"; + + @InjectDelayed + private MessageFileHandlerProvider handlerProvider; + + @DataFolder + private File dataFolder; + @Mock + private Settings settings; + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @BeforeClass + public static void initLogger() { + TestHelper.setupLogger(); + } + + @BeforeInjecting + public void initDataFolder() throws IOException { + this.dataFolder = temporaryFolder.newFolder(); + } + + @Test + public void shouldReturnExistingMessagesFile() { + // given + String language = "fr"; + // use another language file to make sure we won't copy over it + String jarFile = "/messages/messages_it.yml"; + File existingFile = copyFromJar(MESSAGES_BUILDER.apply(language), jarFile); + + // when + File result = handlerProvider.initializeFile(language, MESSAGES_BUILDER); + + // then + assertThat(result, equalTo(existingFile)); + assertThat(result.exists(), equalTo(true)); + assertThat(result, equalToFile(getJarFile(jarFile))); + } + + @Test + public void shouldCopyFromJarFile() { + // given + String language = "nl"; + + // when + File result = handlerProvider.initializeFile(language, MESSAGES_BUILDER); + + // then + File expectedFile = new File(dataFolder, MESSAGES_BUILDER.apply(language)); + assertThat(result, equalTo(expectedFile)); + assertThat(result.exists(), equalTo(true)); + assertThat(result, equalToFile(getJarFile("/messages/messages_nl.yml"))); + } + + @Test + public void shouldCopyDefaultFileForUnknownLanguage() { + // given + String language = "zxx"; + + // when + File result = handlerProvider.initializeFile(language, MESSAGES_BUILDER); + + // then + File expectedFile = new File(dataFolder, MESSAGES_BUILDER.apply(language)); + assertThat(result, equalTo(expectedFile)); + assertThat(result.exists(), equalTo(true)); + assertThat(result, equalToFile(getJarFile("/messages/messages_en.yml"))); + } + + @Test + public void shouldReturnNullForNonExistentDefault() { + // given + Function fileFunction = s -> "bogus"; + + // when + File result = handlerProvider.initializeFile("gsw", fileFunction); + + // then + assertThat(result, nullValue()); + } + + @Test + public void shouldCreateHandler() { + // given + String language = "fr"; + given(settings.getProperty(PluginSettings.MESSAGES_LANGUAGE)).willReturn(language); + + MessageFileHandlerProvider provider = Mockito.spy(handlerProvider); + Function fileFunction = lang -> "file_" + lang + ".txt"; + File file = new File(dataFolder, "some_file.txt"); + doReturn(file).when(provider).initializeFile(language, fileFunction); + + // when + MessageFileHandler handler = provider.initializeHandler(fileFunction); + + // then + assertThat(handler, not(nullValue())); + verify(settings).getProperty(PluginSettings.MESSAGES_LANGUAGE); + verify(provider).initializeFile(language, fileFunction); + } + + private File copyFromJar(String path, String jarPath) { + File file = new File(dataFolder, path); + if (!file.getParentFile().mkdirs()) { + throw new IllegalStateException("Could not create folders for '" + file + "'"); + } + try { + Files.copy(getJarFile(jarPath), file); + return file; + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + private static Matcher equalToFile(File file) { + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(File item) { + try { + return Files.equal(item, file); + } catch (IOException e) { + throw new IllegalStateException("IOException during matcher evaluation", e); + } + } + + @Override + public void describeTo(Description description) { + description.appendText("Equal to file '" + file + "'"); + } + }; + } + + +} diff --git a/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java b/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java index 271a87a5f..8479c8298 100644 --- a/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java @@ -2,7 +2,6 @@ package fr.xephi.authme.message; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.TestHelper; -import fr.xephi.authme.settings.Settings; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.junit.Before; @@ -54,11 +53,8 @@ public class MessagesIntegrationTest { @Before public void setUpMessages() { File testFile = TestHelper.getJarFile(YML_TEST_FILE); - Settings settings = mock(Settings.class); - given(settings.getMessagesFile()).willReturn(testFile); - given(settings.getDefaultMessagesFile()).willReturn(YML_DEFAULT_TEST_FILE); - MessageFileCopier copier = copierReturning(testFile, YML_DEFAULT_TEST_FILE); - messages = new Messages(copier); + MessageFileHandlerProvider provider = providerReturning(testFile, YML_DEFAULT_TEST_FILE); + messages = new Messages(provider); } @Test @@ -237,8 +233,9 @@ public class MessagesIntegrationTest { @Test public void shouldAllowNullAsDefaultFile() { // given - MessageFileCopier fileCopier = copierReturning(TestHelper.getJarFile(YML_TEST_FILE), YML_DEFAULT_TEST_FILE); - Messages testMessages = new Messages(fileCopier); + MessageFileHandlerProvider provider = + providerReturning(TestHelper.getJarFile(YML_TEST_FILE), YML_DEFAULT_TEST_FILE); + Messages testMessages = new Messages(provider); // Key not present in test file MessageKey key = MessageKey.TWO_FACTOR_CREATE; @@ -262,10 +259,10 @@ public class MessagesIntegrationTest { } @SuppressWarnings("unchecked") - private static MessageFileCopier copierReturning(File file, String defaultFile) { - MessageFileCopier copier = mock(MessageFileCopier.class); - given(copier.initializeData(any(Function.class))) - .willReturn(new MessageFileCopier.MessageFileData(file, defaultFile)); - return copier; + private static MessageFileHandlerProvider providerReturning(File file, String defaultFile) { + MessageFileHandlerProvider handler = mock(MessageFileHandlerProvider.class); + given(handler.initializeHandler(any(Function.class))) + .willReturn(new MessageFileHandler(file, defaultFile)); + return handler; } } diff --git a/src/test/java/fr/xephi/authme/settings/SettingsTest.java b/src/test/java/fr/xephi/authme/settings/SettingsTest.java index 1e85a7420..8dc2316f5 100644 --- a/src/test/java/fr/xephi/authme/settings/SettingsTest.java +++ b/src/test/java/fr/xephi/authme/settings/SettingsTest.java @@ -2,8 +2,6 @@ package fr.xephi.authme.settings; import com.github.authme.configme.knownproperties.PropertyEntry; import com.github.authme.configme.knownproperties.PropertyFieldsCollector; -import com.github.authme.configme.migration.PlainMigrationService; -import com.github.authme.configme.properties.Property; import com.github.authme.configme.resource.PropertyResource; import fr.xephi.authme.TestHelper; import fr.xephi.authme.settings.properties.RegistrationSettings; @@ -16,25 +14,15 @@ import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.nio.file.Files; -import java.util.Collections; import java.util.List; -import static fr.xephi.authme.settings.properties.PluginSettings.MESSAGES_LANGUAGE; -import static fr.xephi.authme.util.FileUtils.makePath; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayWithSize; -import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; import static org.mockito.BDDMockito.given; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * Unit tests for {@link Settings}. @@ -58,62 +46,6 @@ public class SettingsTest { testPluginFolder = temporaryFolder.newFolder(); } - @Test - public void shouldReturnDefaultFile() throws IOException { - // given - PropertyResource resource = mock(PropertyResource.class); - List knownProperties = Collections.emptyList(); - Settings settings = new Settings(testPluginFolder, resource, new PlainMigrationService(), knownProperties); - - // when - String defaultFile = settings.getDefaultMessagesFile(); - - // then - assertThat(defaultFile, not(nullValue())); - InputStream stream = this.getClass().getResourceAsStream(defaultFile); - assertThat(stream, not(nullValue())); - assertThat(stream.read(), not(equalTo(0))); - } - - @Test - public void shouldReturnMessagesFile() { - // given - // Use some code that is for sure not present in our JAR - String languageCode = "notinjar"; - File file = new File(testPluginFolder, makePath("messages", "messages_" + languageCode + ".yml")); - createFile(file); - - PropertyResource resource = mock(PropertyResource.class); - given(resource.contains(anyString())).willReturn(true); - setReturnValue(resource, MESSAGES_LANGUAGE, languageCode); - Settings settings = new Settings(testPluginFolder, resource, - TestSettingsMigrationServices.alwaysFulfilled(), knownProperties); - - // when - File messagesFile = settings.getMessagesFile(); - - // then - assertThat(messagesFile.getPath(), endsWith("messages_" + languageCode + ".yml")); - assertThat(messagesFile.exists(), equalTo(true)); - } - - @Test - public void shouldCopyDefaultForUnknownLanguageCode() { - // given - PropertyResource resource = mock(PropertyResource.class); - given(resource.contains(anyString())).willReturn(true); - setReturnValue(resource, MESSAGES_LANGUAGE, "doesntexist"); - Settings settings = new Settings(testPluginFolder, resource, - TestSettingsMigrationServices.alwaysFulfilled(), knownProperties); - - // when - File messagesFile = settings.getMessagesFile(); - - // then - assertThat(messagesFile.getPath(), endsWith("messages_en.yml")); - assertThat(messagesFile.exists(), equalTo(true)); - } - @Test public void shouldLoadWelcomeMessage() throws IOException { // given @@ -123,7 +55,7 @@ public class SettingsTest { Files.write(welcomeFile.toPath(), welcomeMessage.getBytes()); PropertyResource resource = mock(PropertyResource.class); - setReturnValue(resource, RegistrationSettings.USE_WELCOME_MESSAGE, true); + given(resource.getBoolean(RegistrationSettings.USE_WELCOME_MESSAGE.getPath())).willReturn(true); Settings settings = new Settings(testPluginFolder, resource, TestSettingsMigrationServices.alwaysFulfilled(), knownProperties); @@ -154,21 +86,6 @@ public class SettingsTest { assertThat(result, equalTo(emailMessage)); } - private static void setReturnValue(PropertyResource resource, Property property, T value) { - if (value instanceof String) { - when(resource.getString(eq(property.getPath()))).thenReturn((String) value); - } else if (value instanceof Integer) { - when(resource.getInt(eq(property.getPath()))).thenReturn((Integer) value); - } else if (value instanceof Boolean) { - when(resource.getBoolean(eq(property.getPath()))).thenReturn((Boolean) value); - } else if (value instanceof Enum) { - when(resource.getString(property.getPath())).thenReturn(((Enum) value).name()); - } else { - throw new UnsupportedOperationException("Value has unsupported type '" - + (value == null ? "null" : value.getClass().getSimpleName()) + "'"); - } - } - private static void createFile(File file) { try { file.getParentFile().mkdirs();