Reorganized debug commands

- Debug dump replaces the root debugdump command
- Debug toggle controls diagnostic logging
- Debug version uses the shared version display
- Root version remains executable but hidden from help
- Diagnostic dump routing retains its separate permission path
- Translations and tests cover the revised command structure
This commit is contained in:
Robert Stoneking committed 2026-09-11 17:21:04 -06:00
1 parent bf12f30d26
commit 251b0e250d
24 files changed
+241 -42

No files matched your search

@@ -0,0 +1,87 @@
package art.arcane.iris.core.commands;
import art.arcane.iris.Iris;
import art.arcane.iris.core.service.CommandSVC;
import art.arcane.iris.util.common.scheduling.J;
import art.arcane.volmlib.util.diagnostics.BukkitDebugDump;
import art.arcane.volmlib.util.director.DirectorEngineOptions;
import art.arcane.volmlib.util.director.compat.DirectorEngineFactory;
import art.arcane.volmlib.util.director.context.DirectorContextRegistry;
import art.arcane.volmlib.util.director.help.DirectorMiniMenu;
import art.arcane.volmlib.util.director.runtime.DirectorInvocation;
import art.arcane.volmlib.util.director.runtime.DirectorRuntimeEngine;
import art.arcane.volmlib.util.director.runtime.DirectorSender;
import art.arcane.volmlib.util.plugin.ComponentMessenger;
import org.bukkit.command.CommandSender;
import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class CommandDebugTest {
@Test
public void nestedDumpPreservesUploadDefaultAndLocalOnlyOption() {
Iris previousPlugin = Iris.instance;
Iris plugin = mock(Iris.class);
Iris.instance = plugin;
BukkitDebugDump dump = mock(BukkitDebugDump.class);
CommandSender sender = mock(CommandSender.class);
DirectorSender invocationSender = mock(DirectorSender.class);
when(plugin.debugDump()).thenReturn(dump);
when(invocationSender.getName()).thenReturn("Console");
DirectorContextRegistry contexts = new DirectorContextRegistry();
contexts.register(CommandSender.class, (invocation, arguments) -> sender);
try (MockedStatic<Iris> iris = mockStatic(Iris.class)) {
DirectorRuntimeEngine engine = DirectorEngineFactory.create(new CommandIris(),
DirectorEngineOptions.builder().contexts(contexts).build());
assertTrue(engine.execute(new DirectorInvocation(invocationSender, "iris", List.of("debug", "dump"))).isSuccess());
assertTrue(engine.execute(new DirectorInvocation(invocationSender, "iris", List.of("debug", "dump", "upload=false"))).isSuccess());
verify(dump).request(sender, true);
verify(dump).request(sender, false);
assertEquals(List.of("dump", "toggle", "version"),
DirectorMiniMenu.resolveHelp(engine, List.of("debug")).orElseThrow().entries().stream()
.map(entry -> entry.getDescriptor().getName()).sorted().toList());
} finally {
Iris.instance = previousPlugin;
}
}
@Test
public void canonicalDumpReachesItsOwnPermissionCheckWithoutTheAdminPermission() {
CommandSender sender = mock(CommandSender.class);
try (MockedStatic<J> scheduling = mockStatic(J.class)) {
new CommandSVC().executeRoot(sender, "iris", new String[]{"debug", "dump", "upload=false"});
scheduling.verify(() -> J.aBukkit(any(Runnable.class)));
verify(sender, never()).hasPermission("iris.all");
}
}
@Test
public void otherDebugCommandsStillRequireTheAdminPermission() {
CommandSender sender = mock(CommandSender.class);
try (MockedStatic<J> scheduling = mockStatic(J.class);
MockedStatic<ComponentMessenger> messages = mockStatic(ComponentMessenger.class)) {
CommandSVC commands = new CommandSVC();
commands.executeRoot(sender, "iris", new String[]{"debug", "version"});
commands.executeRoot(sender, "iris", new String[]{"debug", "toggle"});
commands.executeRoot(sender, "iris", new String[]{"debug", "ver"});
commands.executeRoot(sender, "iris", new String[]{"debug", "tog"});
scheduling.verifyNoInteractions();
}
}
}
@@ -0,0 +1,57 @@
package art.arcane.iris.core.commands;
import art.arcane.iris.Iris;
import art.arcane.volmlib.util.director.DirectorEngineOptions;
import art.arcane.volmlib.util.director.compat.DirectorEngineFactory;
import art.arcane.volmlib.util.director.context.DirectorContextRegistry;
import art.arcane.volmlib.util.director.help.DirectorMiniMenu;
import art.arcane.volmlib.util.director.runtime.DirectorInvocation;
import art.arcane.volmlib.util.director.runtime.DirectorRuntimeEngine;
import art.arcane.volmlib.util.director.runtime.DirectorSender;
import art.arcane.volmlib.util.plugin.ComponentMessenger;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.PluginDescriptionFile;
import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.List;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
public class CommandVersionTest {
@Test
public void nestedVersionAndHiddenShortcutUseTheSameInstalledVersion() {
Iris previousPlugin = Iris.instance;
Iris plugin = mock(Iris.class);
Iris.instance = plugin;
CommandSender sender = mock(CommandSender.class);
DirectorSender invocationSender = mock(DirectorSender.class);
when(plugin.getDescription()).thenReturn(new PluginDescriptionFile("Iris", "3.2.1-test", "test.Plugin"));
when(invocationSender.getName()).thenReturn("Console");
DirectorContextRegistry contexts = new DirectorContextRegistry();
contexts.register(CommandSender.class, (invocation, arguments) -> sender);
try (MockedStatic<Iris> iris = mockStatic(Iris.class);
MockedStatic<ComponentMessenger> messages = mockStatic(ComponentMessenger.class)) {
DirectorRuntimeEngine engine = DirectorEngineFactory.create(new CommandIris(),
DirectorEngineOptions.builder().contexts(contexts).build());
assertTrue(engine.execute(new DirectorInvocation(invocationSender, "iris", List.of("debug", "version"))).isSuccess());
assertTrue(engine.execute(new DirectorInvocation(invocationSender, "iris", List.of("version"))).isSuccess());
messages.verify(() -> ComponentMessenger.sendMarkup(sender,
DirectorMiniMenu.version("Iris", "3.2.1-test", DirectorMiniMenu.Theme.irisGreen())), times(2));
assertFalse(DirectorMiniMenu.resolveHelp(engine, List.of()).orElseThrow().entries().stream()
.anyMatch(entry -> entry.getDescriptor().getName().equals("version")));
assertTrue(DirectorMiniMenu.resolveHelp(engine, List.of("debug")).orElseThrow().entries().stream()
.anyMatch(entry -> entry.getDescriptor().getName().equals("version")));
assertTrue(DirectorMiniMenu.resolveHelp(engine, List.of("debug")).orElseThrow().entries().stream()
.anyMatch(entry -> entry.getDescriptor().getName().equals("toggle")));
} finally {
Iris.instance = previousPlugin;
}
}
}