diff --git a/src/test/java/com/diamonddagger590/mccore/bootstrap/CoreBootstrapTest.java b/src/test/java/com/diamonddagger590/mccore/bootstrap/CoreBootstrapTest.java index 2a51890..01d0016 100644 --- a/src/test/java/com/diamonddagger590/mccore/bootstrap/CoreBootstrapTest.java +++ b/src/test/java/com/diamonddagger590/mccore/bootstrap/CoreBootstrapTest.java @@ -1,6 +1,7 @@ package com.diamonddagger590.mccore.bootstrap; import com.diamonddagger590.mccore.CorePlugin; +import com.diamonddagger590.mccore.command.CoreCommandManager; import com.diamonddagger590.mccore.database.Database; import com.diamonddagger590.mccore.database.DatabaseManager; import com.diamonddagger590.mccore.database.driver.DriverRegistry; @@ -10,6 +11,7 @@ import com.diamonddagger590.mccore.registry.manager.ManagerRegistry; import com.diamonddagger590.mccore.testing.RegistryResetExtension; import com.diamonddagger590.mccore.util.TimeProvider; +import org.mockito.MockedConstruction; import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.plugin.PluginManager; @@ -23,6 +25,7 @@ import java.util.logging.Logger; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; @@ -31,6 +34,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockConstruction; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -192,6 +196,22 @@ void start_registersAllCoreRegistries_whenProdProfile() { assertNotNull(RegistryAccess.registryAccess().registry(RegistryKey.DRIVER)); } + @Test + @DisplayName("Given prod profile with mocked command manager, when start is called, then CoreCommandManager is registered in ManagerRegistry") + void start_registersCoreCommandManager_whenProdProfileWithMockedConstruction() { + TestBootstrap bootstrap = new TestBootstrap(mockPlugin); + + try (MockedConstruction mocked = mockConstruction(CoreCommandManager.class)) { + bootstrap.start(StartupProfile.PROD); + + assertEquals(1, mocked.constructed().size(), + "Exactly one CoreCommandManager should be constructed during PROD start"); + ManagerRegistry managerRegistry = RegistryAccess.registryAccess().registry(RegistryKey.MANAGER); + assertTrue(managerRegistry.registered(mocked.constructed().get(0)), + "CoreCommandManager should be registered in the ManagerRegistry"); + } + } + @Test @DisplayName("Given a registered database manager, when stop is called with prod profile, then database is shut down") void stop_shutsDownDatabase_whenDatabaseManagerRegistered() { diff --git a/src/test/java/com/diamonddagger590/mccore/bootstrap/registrar/CommandRegistrarTest.java b/src/test/java/com/diamonddagger590/mccore/bootstrap/registrar/CommandRegistrarTest.java new file mode 100644 index 0000000..431a48f --- /dev/null +++ b/src/test/java/com/diamonddagger590/mccore/bootstrap/registrar/CommandRegistrarTest.java @@ -0,0 +1,83 @@ +package com.diamonddagger590.mccore.bootstrap.registrar; + +import com.diamonddagger590.mccore.CorePlugin; +import com.diamonddagger590.mccore.bootstrap.BootstrapContext; +import com.diamonddagger590.mccore.bootstrap.StartupProfile; +import com.diamonddagger590.mccore.command.CoreCommandManager; +import com.diamonddagger590.mccore.registry.RegistryAccess; +import com.diamonddagger590.mccore.registry.RegistryKey; +import com.diamonddagger590.mccore.registry.manager.ManagerRegistry; +import com.diamonddagger590.mccore.testing.RegistryResetExtension; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedConstruction; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mockConstruction; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class CommandRegistrarTest { + + private CommandRegistrar registrar; + + @Mock + private CorePlugin mockPlugin; + + @BeforeEach + void setUp() { + registrar = new CommandRegistrar<>(); + RegistryResetExtension.setupRegistry(); + when(mockPlugin.registryAccess()).thenReturn(RegistryAccess.registryAccess()); + } + + @AfterEach + void tearDown() { + RegistryResetExtension.resetRegistry(); + } + + @Test + @DisplayName("Given a bootstrap context, when registering, then CoreCommandManager is created and registered in ManagerRegistry") + void register_registersCoreCommandManager() { + BootstrapContext context = new BootstrapContext<>(mockPlugin, StartupProfile.PROD); + + try (MockedConstruction mocked = mockConstruction(CoreCommandManager.class)) { + registrar.register(context); + + assertEquals(1, mocked.constructed().size(), + "Exactly one CoreCommandManager should be constructed"); + ManagerRegistry managerRegistry = RegistryAccess.registryAccess().registry(RegistryKey.MANAGER); + assertTrue(managerRegistry.registered(mocked.constructed().get(0)), + "The constructed CoreCommandManager should be registered in the ManagerRegistry"); + } + } + + @Test + @DisplayName("Given a bootstrap context, when registering, then CoreCommandManager is constructed with the context's plugin") + void register_constructsCoreCommandManager_withContextPlugin() { + BootstrapContext context = new BootstrapContext<>(mockPlugin, StartupProfile.PROD); + List> capturedArgs = new ArrayList<>(); + + try (MockedConstruction mocked = mockConstruction(CoreCommandManager.class, + (mock, ctx) -> capturedArgs.add(new ArrayList<>(ctx.arguments())))) { + registrar.register(context); + + assertEquals(1, capturedArgs.size(), + "Constructor should be called exactly once"); + assertEquals(1, capturedArgs.get(0).size(), + "CoreCommandManager should be constructed with exactly one argument"); + assertSame(mockPlugin, capturedArgs.get(0).get(0), + "CoreCommandManager should be constructed with the context's plugin"); + } + } +} diff --git a/src/test/java/com/diamonddagger590/mccore/gui/GuiRefreshDefaultMethodTest.java b/src/test/java/com/diamonddagger590/mccore/gui/GuiRefreshDefaultMethodTest.java new file mode 100644 index 0000000..c0bc5d4 --- /dev/null +++ b/src/test/java/com/diamonddagger590/mccore/gui/GuiRefreshDefaultMethodTest.java @@ -0,0 +1,89 @@ +package com.diamonddagger590.mccore.gui; + +import com.diamonddagger590.mccore.gui.slot.Slot; +import com.diamonddagger590.mccore.player.CorePlayer; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; + +class GuiRefreshDefaultMethodTest { + + @Test + @DisplayName("Given a Gui implementation, when refreshGUI is called, then paintInventory is invoked") + void refreshGUI_callsPaintInventory_whenInvoked() { + AtomicInteger paintCount = new AtomicInteger(0); + Gui gui = new TestGui(paintCount); + + gui.refreshGUI(); + + assertEquals(1, paintCount.get(), + "refreshGUI should delegate to paintInventory exactly once"); + } + + @Test + @DisplayName("Given a Gui implementation, when refreshGUI is called twice, then paintInventory is invoked twice") + void refreshGUI_callsPaintInventoryTwice_whenInvokedTwice() { + AtomicInteger paintCount = new AtomicInteger(0); + Gui gui = new TestGui(paintCount); + + gui.refreshGUI(); + gui.refreshGUI(); + + assertEquals(2, paintCount.get(), + "refreshGUI should delegate to paintInventory each time it is called"); + } + + @SuppressWarnings("unchecked") + private static class TestGui implements Gui { + + private final UUID uuid = UUID.randomUUID(); + private final AtomicInteger paintCount; + + TestGui(AtomicInteger paintCount) { + this.paintCount = paintCount; + } + + @Override + @NotNull + public UUID getUUID() { + return uuid; + } + + @Override + @NotNull + public Slot getSlot(int index) { + return mock(Slot.class); + } + + @Override + @NotNull + public Inventory getInventory() { + return mock(Inventory.class); + } + + @Override + public void handleClickEvent(@NotNull InventoryClickEvent inventoryClickEvent) { + } + + @Override + public void paintInventory() { + paintCount.incrementAndGet(); + } + + @Override + public void registerListeners() { + } + + @Override + public void unregisterListeners() { + } + } +} diff --git a/src/test/java/com/diamonddagger590/mccore/player/CorePlayerTest.java b/src/test/java/com/diamonddagger590/mccore/player/CorePlayerTest.java index 5a76946..2ba26c3 100644 --- a/src/test/java/com/diamonddagger590/mccore/player/CorePlayerTest.java +++ b/src/test/java/com/diamonddagger590/mccore/player/CorePlayerTest.java @@ -54,6 +54,20 @@ public boolean isAfk(CorePlayer corePlayer) { } } + private static class SecondTestAfkPluginHook extends PluginHook implements AfkPluginHook { + private final boolean afk; + + SecondTestAfkPluginHook(boolean afk) { + super(null); + this.afk = afk; + } + + @Override + public boolean isAfk(CorePlayer corePlayer) { + return afk; + } + } + private UUID testUUID; private TestCorePlayer player; @@ -140,6 +154,22 @@ void isAfk_returnsFalse_whenRegisteredHookReturnsFalse() { assertFalse(player.isAfk()); } + @Test + @DisplayName("Given multiple AfkPluginHooks where first returns false and second returns true, when calling isAfk, then returns true") + void isAfk_returnsTrue_whenSecondHookReturnsTrue() { + RegistryAccess.registryAccess().registry(RegistryKey.PLUGIN_HOOK).register(new TestAfkPluginHook(false)); + RegistryAccess.registryAccess().registry(RegistryKey.PLUGIN_HOOK).register(new SecondTestAfkPluginHook(true)); + assertTrue(player.isAfk()); + } + + @Test + @DisplayName("Given multiple AfkPluginHooks that all return false, when calling isAfk, then returns false") + void isAfk_returnsFalse_whenAllHooksReturnFalse() { + RegistryAccess.registryAccess().registry(RegistryKey.PLUGIN_HOOK).register(new TestAfkPluginHook(false)); + RegistryAccess.registryAccess().registry(RegistryKey.PLUGIN_HOOK).register(new SecondTestAfkPluginHook(false)); + assertFalse(player.isAfk()); + } + // --- equals --- @Test @@ -166,12 +196,14 @@ void equals_returnsTrue_whenComparedToSelf() { @DisplayName("Given a CorePlayer, when compared to a non-CorePlayer object, then returns not equal") void equals_returnsFalse_whenComparedToNonCorePlayer() { assertNotEquals("not a player", player); + assertFalse(player.equals("not a player")); } @Test @DisplayName("Given a CorePlayer, when compared to null, then returns not equal") void equals_returnsFalse_whenComparedToNull() { assertNotEquals(null, player); + assertFalse(player.equals(null)); } // --- hashCode ---