Merge remote-tracking branch 'origin/MV5' into better-revamp-config

This commit is contained in:
Jeremy Wood 2023-03-30 01:06:00 -04:00
commit 2a5b670ce6
No known key found for this signature in database
GPG Key ID: C5BAD04C77B91B4B
13 changed files with 705 additions and 30 deletions

View File

@ -114,6 +114,7 @@ dependencies {
}
testImplementation 'org.jetbrains.kotlin:kotlin-test'
testImplementation 'com.natpryce:hamkrest:1.8.0.1'
testImplementation 'org.mockito.kotlin:mockito-kotlin:4.1.0'
// Old Tests
oldTestImplementation 'org.spigotmc:spigot-api:1.19.3-R0.1-SNAPSHOT'
@ -241,7 +242,7 @@ javadoc {
project.configurations.api.canBeResolved = true
shadowJar {
relocate 'co.aikar', 'com.onarandombox.acf'
relocate 'co.aikar.commands', 'com.onarandombox.acf'
relocate 'com.dumptruckman.minecraft.util.Logging', 'com.onarandombox.MultiverseCore.utils.CoreLogging'
relocate 'com.dumptruckman.minecraft.util.DebugLog', 'com.onarandombox.MultiverseCore.utils.DebugFileLogger'
relocate 'de.themoep.idconverter', 'com.onarandombox.idconverter'

View File

@ -0,0 +1,13 @@
package co.aikar.commands;
import org.bukkit.command.CommandSender;
/**
* Exists just so we can extend BukkitCommandIssuer since it has a package-private constructor.
*/
public abstract class OpenBukkitCommandIssuer extends BukkitCommandIssuer {
protected OpenBukkitCommandIssuer(BukkitCommandManager manager, CommandSender sender) {
super(manager, sender);
}
}

View File

@ -23,6 +23,7 @@ import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.PluginLocales;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
import com.onarandombox.MultiverseCore.economy.MVEconomist;
@ -68,6 +69,8 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
private Provider<MetricsConfigurator> metricsConfiguratorProvider;
@Inject
private Provider<MVEconomist> economistProvider;
@Inject
private Provider<PluginLocales> pluginLocalesProvider;
// Counter for the number of plugins that have registered with us
private int pluginCount;
@ -129,8 +132,8 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
// Init all the other stuff
this.loadAnchors();
this.registerEvents();
this.registerCommands();
this.setUpLocales();
this.registerCommands();
this.registerDestinations();
this.setupMetrics();
this.loadPlaceholderAPIIntegration();
@ -173,13 +176,19 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
private void loadEconomist() {
Try.run(() -> economistProvider.get())
.onFailure(e -> Logging.severe("Failed to load economy integration", e));
.onFailure(e -> {
Logging.severe("Failed to load economy integration");
e.printStackTrace();
});
}
private void loadAnchors() {
Try.of(() -> anchorManagerProvider.get())
.onSuccess(AnchorManager::loadAnchors)
.onFailure(e -> Logging.severe("Failed to load anchors", e));
.onFailure(e -> {
Logging.severe("Failed to load anchors");
e.printStackTrace();
});
}
/**
@ -204,7 +213,10 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
serviceLocator.getAllServices(MultiverseCommand.class)
.forEach(commandManager::registerCommand);
})
.onFailure(e -> Logging.severe("Failed to register commands", e));
.onFailure(e -> {
Logging.severe("Failed to register commands");
e.printStackTrace();
});
}
/**
@ -212,12 +224,18 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
*/
private void setUpLocales() {
Try.of(() -> commandManagerProvider.get())
.andThenTry(commandManager -> {
.andThen(commandManager -> {
commandManager.usePerIssuerLocale(true, true);
commandManager.getLocales().addFileResClassLoader(this);
commandManager.getLocales().addMessageBundles("multiverse-core");
})
.onFailure(e -> Logging.severe("Failed to register locales", e));
.mapTry(commandManager -> pluginLocalesProvider.get())
.andThen(pluginLocales -> {
pluginLocales.addFileResClassLoader(this);
pluginLocales.addMessageBundles("multiverse-core");
})
.onFailure(e -> {
Logging.severe("Failed to register locales");
e.printStackTrace();
});
}
/**
@ -229,7 +247,10 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
serviceLocator.getAllServices(Destination.class)
.forEach(destinationsProvider::registerDestination);
})
.onFailure(e -> Logging.severe("Failed to register destinations", e));
.onFailure(e -> {
Logging.severe("Failed to register destinations");
e.printStackTrace();
});
}
/**
@ -239,7 +260,10 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
if (TestingMode.isDisabled()) {
// Load metrics
Try.of(() -> metricsConfiguratorProvider.get())
.onFailure(e -> Logging.severe("Failed to setup metrics", e));
.onFailure(e -> {
Logging.severe("Failed to setup metrics");
e.printStackTrace();
});
} else {
Logging.info("Metrics are disabled in testing mode.");
}
@ -261,7 +285,10 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
if (config.isRegisterPapiHook()
&& getServer().getPluginManager().getPlugin("PlaceholderAPI") != null) {
Try.run(() -> serviceLocator.createAndInitialize(MultiverseCorePlaceholders.class))
.onFailure(e -> Logging.severe("Failed to load PlaceholderAPI integration.", e));
.onFailure(e -> {
Logging.severe("Failed to load PlaceholderAPI integration.");
e.printStackTrace();
});
}
}

View File

@ -0,0 +1,48 @@
package com.onarandombox.MultiverseCore.commandtools;
import co.aikar.commands.MessageType;
import co.aikar.commands.OpenBukkitCommandIssuer;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.utils.message.Message;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class MVCommandIssuer extends OpenBukkitCommandIssuer {
private final MVCommandManager commandManager;
MVCommandIssuer(@NotNull MVCommandManager commandManager, @NotNull CommandSender sender) {
super(commandManager, sender);
this.commandManager = commandManager;
}
@Override
public MVCommandManager getManager() {
return commandManager;
}
public void sendError(Message message) {
sendMessage(MessageType.ERROR, message);
}
public void sendSyntax(Message message) {
sendMessage(MessageType.SYNTAX, message);
}
public void sendInfo(Message message) {
sendMessage(MessageType.INFO, message);
}
private void sendMessage(MessageType messageType, Message message) {
if (message instanceof MessageKeyProvider) {
sendMessage(messageType, (MessageKeyProvider) message, message.getReplacements());
} else {
var formatter = getManager().getFormat(messageType);
if (formatter != null) {
sendMessage(formatter.format(message.formatted()));
} else {
sendMessage(message.formatted());
}
}
}
}

View File

@ -4,6 +4,7 @@ import java.util.List;
import co.aikar.commands.BukkitCommandCompletionContext;
import co.aikar.commands.BukkitCommandExecutionContext;
import co.aikar.commands.BukkitLocales;
import co.aikar.commands.CommandCompletions;
import co.aikar.commands.CommandContexts;
import co.aikar.commands.CommandHelp;
@ -15,6 +16,8 @@ import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagsManager;
import com.onarandombox.MultiverseCore.commandtools.queue.CommandQueueManager;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@ -28,7 +31,6 @@ public class MVCommandManager extends PaperCommandManager {
private final CommandQueueManager commandQueueManager;
private final Provider<MVCommandContexts> commandContextsProvider;
private final Provider<MVCommandCompletions> commandCompletionsProvider;
private PluginLocales pluginLocales;
@Inject
public MVCommandManager(
@ -48,6 +50,18 @@ public class MVCommandManager extends PaperCommandManager {
MVCommandConditions.load(this, worldManager);
}
void loadLanguages(PluginLocales locales) {
if (this.locales == null) {
this.locales = locales;
this.locales.loadLanguages();
}
}
@Override
public BukkitLocales getLocales() {
return this.locales;
}
/**
* Gets class responsible for flag handling.
*
@ -57,21 +71,6 @@ public class MVCommandManager extends PaperCommandManager {
return flagsManager;
}
/**
* Gets class responsible for locale handling.
*
* @return A not-null {@link PluginLocales}.
*/
@Override
public PluginLocales getLocales() {
if (this.pluginLocales == null) {
this.pluginLocales = new PluginLocales(this);
this.locales = pluginLocales; // For parent class
this.pluginLocales.loadLanguages();
}
return this.pluginLocales;
}
/**
* Manager for command that requires /mv confirm before execution.
*
@ -120,4 +119,17 @@ public class MVCommandManager extends PaperCommandManager {
}
help.showHelp();
}
public @NotNull MVCommandIssuer getConsoleCommandIssuer() {
return getCommandIssuer(Bukkit.getConsoleSender());
}
@Override
public @NotNull MVCommandIssuer getCommandIssuer(Object issuer) {
if (!(issuer instanceof CommandSender)) {
throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer.");
} else {
return new MVCommandIssuer(this, (CommandSender)issuer);
}
}
}

View File

@ -1,14 +1,16 @@
package com.onarandombox.MultiverseCore.commandtools;
import co.aikar.commands.BukkitCommandManager;
import co.aikar.commands.BukkitLocales;
import com.onarandombox.MultiverseCore.utils.file.FileResClassLoader;
import jakarta.inject.Inject;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
/**
* Locale manager with additional methods for loading locales from plugin's locales folder.
*/
@Service
public class PluginLocales extends BukkitLocales {
private static final String DEFAULT_LOCALE_FOLDER_PATH = "locales";
@ -18,8 +20,10 @@ public class PluginLocales extends BukkitLocales {
*
* @param manager The command manager.
*/
public PluginLocales(BukkitCommandManager manager) {
@Inject
public PluginLocales(MVCommandManager manager) {
super(manager);
manager.loadLanguages(this);
}
/**

View File

@ -0,0 +1,52 @@
package com.onarandombox.MultiverseCore.exceptions;
import com.onarandombox.MultiverseCore.commandtools.MVCommandIssuer;
import com.onarandombox.MultiverseCore.utils.message.Message;
import org.jetbrains.annotations.Nullable;
/**
* A base exception for Multiverse.
* <br/>
* {@link #getMVMessage()} provides access to a {@link Message} which can be used to provide a localized message. See
* {@link MVCommandIssuer#sendInfo(Message)}.
*/
public class MultiverseException extends Exception {
private final @Nullable Message message;
/**
* Creates a new exception with the given message and cause.
* <br/>
* If the message is not null, this exception will also contain a {@link Message} which can be accessed via
* {@link #getMVMessage()}. This message will just be the given message wrapped in a {@link Message}.
*
* @param message The message for the exception
* @param cause The cause of the exception
*/
public MultiverseException(@Nullable String message, @Nullable Throwable cause) {
this(message != null ? Message.of(message) : null, cause);
}
/**
* Creates a new exception with the given message and cause.
* <br/>
* If the message is not null, this exception will also contain a String message which can be accessed via
* {@link #getMessage()}. This message will just be the given message formatted without locale support.
*
* @param message The message for the exception
* @param cause The cause of the exception
*/
public MultiverseException(@Nullable Message message, @Nullable Throwable cause) {
super(message != null ? message.formatted() : null, cause);
this.message = message;
}
/**
* Gets the {@link Message} for this exception.
*
* @return The message, or null if none was provided
*/
public final @Nullable Message getMVMessage() {
return message;
}
}

View File

@ -2,6 +2,9 @@ package com.onarandombox.MultiverseCore.utils;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.utils.message.Message;
import com.onarandombox.MultiverseCore.utils.message.MessageReplacement;
import org.jetbrains.annotations.NotNull;
public enum MVCorei18n implements MessageKeyProvider {
// config status
@ -84,4 +87,9 @@ public enum MVCorei18n implements MessageKeyProvider {
public MessageKey getMessageKey() {
return this.key;
}
@NotNull
public Message bundle(@NotNull String nonLocalizedMessage, @NotNull MessageReplacement... replacements) {
return Message.of(this, nonLocalizedMessage, replacements);
}
}

View File

@ -0,0 +1,40 @@
package com.onarandombox.MultiverseCore.utils.message;
import co.aikar.commands.ACFUtil;
import co.aikar.commands.CommandIssuer;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.commandtools.PluginLocales;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
final class LocalizedMessage extends Message implements MessageKeyProvider {
private final @NotNull MessageKeyProvider messageKeyProvider;
LocalizedMessage(
@NotNull MessageKeyProvider messageKeyProvider,
@NotNull String message,
@NotNull MessageReplacement... replacements
) {
super(message, replacements);
this.messageKeyProvider = messageKeyProvider;
}
@Override
public MessageKey getMessageKey() {
return messageKeyProvider.getMessageKey();
}
@Override
public @NotNull String formatted(@NotNull PluginLocales locales, @Nullable CommandIssuer commandIssuer) {
Objects.requireNonNull(locales, "locales must not be null");
if (getReplacements().length == 0) {
return raw();
}
return ACFUtil.replaceStrings(locales.getMessage(commandIssuer, getMessageKey()), getReplacements());
}
}

View File

@ -0,0 +1,140 @@
package com.onarandombox.MultiverseCore.utils.message;
import co.aikar.commands.ACFUtil;
import co.aikar.commands.CommandIssuer;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.commandtools.PluginLocales;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
/**
* A message that can be formatted with replacements and localized.
*/
public sealed class Message permits LocalizedMessage {
/**
* Creates a basic non-localized Message with the given message and replacements.
*
* @param message The message
* @param replacements The replacements
* @return A new Message
*/
@Contract(value = "_, _ -> new", pure = true)
public static Message of(@NotNull String message, @NotNull MessageReplacement... replacements) {
Objects.requireNonNull(message, "message must not be null");
for (MessageReplacement replacement : replacements) {
Objects.requireNonNull(replacement, "replacements must not contain null");
}
return new Message(message, replacements);
}
/**
* Creates a localized Message with the given message key provider, non-localized message and replacements.
* <br/>
* The non-localized message is required for conditions where it is not practical to provide a localized message.
* <br/>
* This message will extend {@link MessageKeyProvider} and delegate to the given message key provider.
*
* @param messageKeyProvider The message key provider
* @param nonLocalizedMessage The non-localized message
* @param replacements The replacements
* @return A new localizable Message
*/
@Contract(value = "_, _, _ -> new", pure = true)
public static Message of(
@NotNull MessageKeyProvider messageKeyProvider,
@NotNull String nonLocalizedMessage,
@NotNull MessageReplacement... replacements
) {
Objects.requireNonNull(messageKeyProvider, "messageKeyProvider must not be null");
Objects.requireNonNull(nonLocalizedMessage, "message must not be null");
for (MessageReplacement replacement : replacements) {
Objects.requireNonNull(replacement, "replacements must not contain null");
}
return new LocalizedMessage(messageKeyProvider, nonLocalizedMessage, replacements);
}
private final @NotNull String message;
private final @NotNull String[] replacements;
protected Message(@NotNull String message, @NotNull MessageReplacement... replacements) {
this.message = message;
this.replacements = toReplacementsArray(replacements);
}
/**
* Gets the replacements for this message.
* <br/>
* This array is guaranteed to be of even length and suitable for use with
* {@link ACFUtil#replaceStrings(String, String...)}.
*
* @return The replacements
*/
public @NotNull String[] getReplacements() {
return replacements;
}
/**
* Gets the raw, non-localized, non-replaced message.
*
* @return The raw message
*/
public @NotNull String raw() {
return message;
}
/**
* Gets the formatted message.
* <br/>
* This is the raw, non-localized message with replacements applied.
*
* @return The formatted message
*/
public @NotNull String formatted() {
if (replacements.length == 0) {
return raw();
}
return ACFUtil.replaceStrings(message, replacements);
}
/**
* Gets the formatted message from localization data.
* <br/>
* This is the localized message with replacements applied. The message is localized using the default locale.
*
* @param locales The MultiverseCore locales provider
* @return The formatted, localized message
*/
public @NotNull String formatted(@NotNull PluginLocales locales) {
return formatted(locales, null);
}
/**
* Gets the formatted message from localization data.
* <br/>
* This is the localized message with replacements applied. The message is localized using the locale of the given
* command issuer, if not null.
*
* @param locales The MultiverseCore locales provider
* @param commandIssuer The command issuer the message is for, or null for the console (default locale)
* @return The formatted, localized message
*/
public @NotNull String formatted(@NotNull PluginLocales locales, @Nullable CommandIssuer commandIssuer) {
return formatted();
}
private static String[] toReplacementsArray(@NotNull MessageReplacement... replacements) {
String[] replacementsArray = new String[replacements.length * 2];
int i = 0;
for (MessageReplacement replacement : replacements) {
replacementsArray[i++] = replacement.getKey();
replacementsArray[i++] = replacement.getReplacement();
}
return replacementsArray;
}
}

View File

@ -0,0 +1,68 @@
package com.onarandombox.MultiverseCore.utils.message;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Captures string replacements for {@link Message}s.
*/
public final class MessageReplacement {
/**
* Creates a replacement key for the given key string.
*
* @param key The string to replace
* @return A new replacement key which can be used to create a replacement
*/
@Contract(value = "_ -> new", pure = true)
public static MessageReplacement.Key replace(@NotNull String key) {
return new MessageReplacement.Key(key);
}
public static final class Key {
private final @NotNull String key;
private Key(@NotNull String key) {
this.key = key;
}
/**
* Creates a replacement for this key.
*
* @param replacement The replacement value, if null it will be replaced with a string equal to "null"
* @return A new message replacement
*/
@Contract(value = "_ -> new", pure = true)
public MessageReplacement with(@Nullable Object replacement) {
return new MessageReplacement(key, replacement);
}
}
private final @NotNull String key;
private final @NotNull String replacement;
private MessageReplacement(@NotNull String key, @Nullable Object replacement) {
this.key = key;
this.replacement = String.valueOf(replacement);
}
/**
* Gets the string to be replaced.
*
* @return The key
*/
public @NotNull String getKey() {
return key;
}
/**
* Gets the replacement value.
*
* @return The replacement
*/
public @NotNull String getReplacement() {
return replacement;
}
}

View File

@ -0,0 +1,256 @@
package org.mvplugins.multiverse.core.commandtools
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.containsSubstring
import com.onarandombox.MultiverseCore.commandtools.MVCommandIssuer
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager
import com.onarandombox.MultiverseCore.commandtools.PluginLocales
import com.onarandombox.MultiverseCore.utils.MVCorei18n
import com.onarandombox.MultiverseCore.utils.message.Message
import com.onarandombox.MultiverseCore.utils.message.MessageReplacement.replace
import org.bukkit.Bukkit
import org.bukkit.command.CommandSender
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Nested
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.spy
import org.mockito.kotlin.verify
import org.mvplugins.multiverse.core.TestWithMockBukkit
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
import kotlin.test.assertNotNull
class LocalizationTest : TestWithMockBukkit() {
private lateinit var locales: PluginLocales
private lateinit var commandManager: MVCommandManager
@BeforeTest
fun setUpLocale() {
locales = assertNotNull(multiverseCore.getService(PluginLocales::class.java))
commandManager = assertNotNull(multiverseCore.getService(MVCommandManager::class.java))
}
@Nested
@DisplayName("Given a Message with only a non-localized message")
inner class BasicMessage {
private val messageString = "This is a test message"
private val message = Message.of(messageString)
@Test
fun `The raw message should be the same as the original`() {
assertEquals(messageString, message.raw())
}
@Test
fun `The formatted message should be the same as the original`() {
assertEquals(messageString, message.formatted())
}
@Test
fun `The formatted message with PluginLocales should be the same as the original`() {
assertEquals(messageString, message.formatted(locales))
}
@Test
fun `The formatted message with PluginLocales for a CommandIssuer should be the same as the original`() {
assertEquals(messageString, message.formatted(locales, commandManager.consoleCommandIssuer))
}
@Nested
@DisplayName("And a command sender is provided")
inner class WithCommandSender {
private lateinit var sender: CommandSender
private lateinit var issuer: MVCommandIssuer
@BeforeTest
fun setUp() {
sender = spy(Bukkit.getConsoleSender())
issuer = commandManager.getCommandIssuer(sender)
}
@Test
fun `Sending the issuer the message should send the formatted message to the sender`() {
issuer.sendInfo(message);
verify(sender).sendMessage("§9§9$messageString")
}
}
}
@Nested
@DisplayName("Given a Message with a non-localized message and one replacement")
inner class MessageWithOneReplacement {
private val replacementKey = "{count}"
private val messageString = "This is a test message with $replacementKey replacement"
private val replacedMessageString = messageString.replace(replacementKey, "one")
private val message = Message.of(messageString, replace(replacementKey).with("one"))
@Test
fun `The raw message should be the same as the original`() {
assertEquals(messageString, message.raw())
}
@Test
fun `The formatted message should be the replaced message string`() {
assertEquals(replacedMessageString, message.formatted())
}
@Test
fun `The formatted message with PluginLocales should be the replaced message string`() {
assertEquals(replacedMessageString, message.formatted(locales))
}
@Test
fun `The formatted message with PluginLocales for a CommandIssuer should be the replaced message string`() {
assertEquals(replacedMessageString, message.formatted(locales, commandManager.consoleCommandIssuer))
}
@Nested
@DisplayName("And a command sender is provided")
inner class WithCommandSender {
private lateinit var sender: CommandSender
private lateinit var issuer: MVCommandIssuer
@BeforeTest
fun setUp() {
sender = spy(Bukkit.getConsoleSender())
issuer = commandManager.getCommandIssuer(sender)
}
@Test
fun `Sending the issuer the message should send the formatted message to the sender`() {
issuer.sendInfo(message);
verify(sender).sendMessage("§9§9$replacedMessageString")
}
}
}
@Nested
@DisplayName("Given a Message with a non-localized message and two replacements")
inner class MessageWithTwoReplacements {
private val replacementKey1 = "{thing1}"
private val replacementKey2 = "{thing2}"
private val messageString = "$replacementKey1 $replacementKey2"
private val replacedMessageString = messageString
.replace(replacementKey1, "one")
.replace(replacementKey2, "two")
private val message = Message.of(
messageString,
replace(replacementKey1).with("one"),
replace(replacementKey2).with("two"),
)
@Test
fun `The raw message should be the same as the original`() {
assertEquals(messageString, message.raw())
}
@Test
fun `The formatted message should be the replaced message string`() {
assertEquals(replacedMessageString, message.formatted())
}
@Test
fun `The formatted message with PluginLocales should be the replaced message string`() {
assertEquals(replacedMessageString, message.formatted(locales))
}
@Test
fun `The formatted message with PluginLocales for a CommandIssuer should be the replaced message string`() {
assertEquals(replacedMessageString, message.formatted(locales, commandManager.consoleCommandIssuer))
}
@Nested
@DisplayName("And a command sender is provided")
inner class WithCommandSender {
private lateinit var sender: CommandSender
private lateinit var issuer: MVCommandIssuer
@BeforeTest
fun setUp() {
sender = spy(Bukkit.getConsoleSender())
issuer = commandManager.getCommandIssuer(sender)
}
@Test
fun `Sending the issuer the message should send the formatted message to the sender`() {
issuer.sendInfo(message);
verify(sender).sendMessage("§9§9$replacedMessageString")
}
}
}
@Nested
@DisplayName("Given a Message with a localized message with one replacement")
inner class LocalizedMessage {
private val replacementKey = "{world}"
private val replacementValue = "World"
private val messageString = "Hello $replacementKey!"
private val replacedMessageString = messageString.replace(replacementKey, replacementValue)
private val message = MVCorei18n.CLONE_SUCCESS
.bundle(messageString, replace(replacementKey).with(replacementValue))
@Test
fun `The raw message should be the same as the original`() {
assertEquals(messageString, message.raw())
}
@Test
fun `The formatted message should be the replaced original string`() {
assertEquals(replacedMessageString, message.formatted())
}
@Test
fun `The formatted message with PluginLocales should be different from the replaced original string`() {
assertNotEquals(replacedMessageString, message.formatted(locales))
}
@Test
fun `The formatted message with PluginLocales should have performed replacement`() {
assertThat(message.formatted(locales), !containsSubstring(replacementKey))
assertThat(message.formatted(locales), containsSubstring(replacementValue))
}
@Nested
@DisplayName("And a command sender is provided")
inner class WithCommandSender {
private lateinit var sender: CommandSender
private lateinit var issuer: MVCommandIssuer
@BeforeTest
fun setUp() {
sender = spy(Bukkit.getConsoleSender())
issuer = commandManager.getCommandIssuer(sender)
}
@Test
fun `Sending the issuer the message should send the formatted message to the sender`() {
issuer.sendInfo(message);
val sentMessage = argumentCaptor<String> {
verify(sender).sendMessage(capture())
}.firstValue
assertNotEquals(replacedMessageString, sentMessage)
assertThat(sentMessage, !containsSubstring(replacementKey))
assertThat(sentMessage, containsSubstring(replacementValue))
}
}
}
}

View File

@ -9,6 +9,7 @@ import com.onarandombox.MultiverseCore.api.MVWorldManager
import com.onarandombox.MultiverseCore.api.SafeTTeleporter
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand
import com.onarandombox.MultiverseCore.commandtools.PluginLocales
import com.onarandombox.MultiverseCore.config.MVCoreConfig
import com.onarandombox.MultiverseCore.economy.MVEconomist
import com.onarandombox.MultiverseCore.listeners.MVChatListener
@ -135,4 +136,9 @@ class InjectionTest : TestWithMockBukkit() {
// Also making sure this is not loaded automatically since it's supposed to be disabled during tests
assertNull(multiverseCore.getService(MetricsConfigurator::class.java))
}
@Test
fun `PluginLocales is available as a service`() {
assertNotNull(multiverseCore.getService(PluginLocales::class.java))
}
}