summaryrefslogtreecommitdiff
path: root/platform-paper
diff options
context:
space:
mode:
authorSho Sakuma <me@m1sk9.dev>2026-02-26 00:17:21 +0900
committerSho Sakuma <me@m1sk9.dev>2026-02-26 00:17:21 +0900
commit70c785eee4c61601ba7fffa17cc8b992b4793491 (patch)
tree2bb41b90c19cfd3cfbe638f9f8fbd420ab96aa86 /platform-paper
parent365d9ede9d0abaae2bad03231b6bc5243013fc92 (diff)
downloadLunaticChat-70c785eee4c61601ba7fffa17cc8b992b4793491.tar.gz
LunaticChat-70c785eee4c61601ba7fffa17cc8b992b4793491.tar.bz2
LunaticChat-70c785eee4c61601ba7fffa17cc8b992b4793491.zip
test: expand test coverage across all modules
- Add 23 new test files covering exceptions, data classes, permissions, setting handlers, commands, and cross-server relay - Change command execute methods from private to internal visibility to enable unit testing (16 command files) - Engine coverage: 65.5% → 92.4% - Platform-paper coverage: 16.8% → 40.0% - Platform-velocity coverage: 62.4% → 76.8% Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'platform-paper')
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelBanCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelCreateCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInfoCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInviteCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelKickCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelModCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelOwnershipCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelUnbanCommand.kt2
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommand.kt2
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommandTest.kt125
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelBanCommandTest.kt137
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelCreateCommandTest.kt128
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommandTest.kt95
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInfoCommandTest.kt123
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInviteCommandTest.kt152
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommandTest.kt151
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelKickCommandTest.kt136
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommandTest.kt125
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommandTest.kt107
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelModCommandTest.kt147
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelOwnershipCommandTest.kt139
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommandTest.kt142
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommandTest.kt108
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelUnbanCommandTest.kt121
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommandTest.kt88
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/setting/SettingHandlerRegistryTest.kt101
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/setting/handler/SettingHandlerTest.kt191
34 files changed, 2332 insertions, 16 deletions
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommand.kt
index a3dea37..82dcd9f 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommand.kt
@@ -39,7 +39,7 @@ class StatusCommand(
handleResult(context, result)
}
- private fun execute(ctx: CommandContext): CommandResult {
+ internal fun execute(ctx: CommandContext): CommandResult {
val sender = ctx.requirePlayer()
val features = configuration.features
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelBanCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelBanCommand.kt
index 90d4e6d..5a6b52f 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelBanCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelBanCommand.kt
@@ -68,7 +68,7 @@ class ChannelBanCommand(
},
)
- private fun execute(
+ internal fun execute(
ctx: CommandContext,
playerName: String,
): CommandResult {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelCreateCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelCreateCommand.kt
index cad2231..fa97a46 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelCreateCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelCreateCommand.kt
@@ -81,7 +81,7 @@ class ChannelCreateCommand(
),
)
- private fun execute(
+ internal fun execute(
ctx: CommandContext,
channelId: String,
name: String,
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommand.kt
index 8ca3a55..f39d8e8 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommand.kt
@@ -72,7 +72,7 @@ class ChannelDeleteCommand(
},
)
- private fun execute(
+ internal fun execute(
ctx: CommandContext,
channelId: String,
): CommandResult {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInfoCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInfoCommand.kt
index cb040d6..fc32f9b 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInfoCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInfoCommand.kt
@@ -63,7 +63,7 @@ class ChannelInfoCommand(
},
)
- private fun execute(
+ internal fun execute(
ctx: CommandContext,
channelIdArg: String?,
): CommandResult {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInviteCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInviteCommand.kt
index d4ce07a..37c8d7a 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInviteCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInviteCommand.kt
@@ -58,7 +58,7 @@ class ChannelInviteCommand(
},
)
- private fun execute(
+ internal fun execute(
ctx: CommandContext,
playerName: String,
): CommandResult {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommand.kt
index 83a40b9..2edb0da 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommand.kt
@@ -62,7 +62,7 @@ class ChannelJoinCommand(
},
)
- private fun execute(
+ internal fun execute(
ctx: CommandContext,
channelId: String,
): CommandResult {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelKickCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelKickCommand.kt
index 672cf2d..452c48d 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelKickCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelKickCommand.kt
@@ -66,7 +66,7 @@ class ChannelKickCommand(
},
)
- private fun execute(
+ internal fun execute(
ctx: CommandContext,
playerName: String,
): CommandResult {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommand.kt
index 5e45d27..d763853 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommand.kt
@@ -40,7 +40,7 @@ class ChannelLeaveCommand(
handleResult(context, result)
}
- private fun execute(ctx: CommandContext): CommandResult {
+ internal fun execute(ctx: CommandContext): CommandResult {
val sender = ctx.requirePlayer()
// Get current channel before leaving
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommand.kt
index 1004baf..c0df8bf 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommand.kt
@@ -58,7 +58,7 @@ class ChannelListCommand(
},
)
- private fun execute(
+ internal fun execute(
ctx: CommandContext,
page: Int,
): CommandResult {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelModCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelModCommand.kt
index 82caa39..a368abb 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelModCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelModCommand.kt
@@ -64,7 +64,7 @@ class ChannelModCommand(
},
)
- private fun execute(
+ internal fun execute(
ctx: CommandContext,
playerName: String,
): CommandResult {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelOwnershipCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelOwnershipCommand.kt
index 576b072..6724052 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelOwnershipCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelOwnershipCommand.kt
@@ -64,7 +64,7 @@ class ChannelOwnershipCommand(
},
)
- private fun execute(
+ internal fun execute(
ctx: CommandContext,
playerName: String,
): CommandResult {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommand.kt
index 3b65765..7fb41c6 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommand.kt
@@ -48,7 +48,7 @@ class ChannelStatusCommand(
handleResult(context, result)
}
- private fun execute(ctx: CommandContext): CommandResult {
+ internal fun execute(ctx: CommandContext): CommandResult {
val sender = ctx.requirePlayer()
// Get active channel
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommand.kt
index 13d44d2..6f8cc8f 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommand.kt
@@ -58,7 +58,7 @@ class ChannelSwitchCommand(
},
)
- private fun execute(
+ internal fun execute(
ctx: CommandContext,
channelId: String,
): CommandResult {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelUnbanCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelUnbanCommand.kt
index e7a7295..043ca01 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelUnbanCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelUnbanCommand.kt
@@ -63,7 +63,7 @@ class ChannelUnbanCommand(
},
)
- private fun execute(
+ internal fun execute(
ctx: CommandContext,
playerName: String,
): CommandResult {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommand.kt
index cea1814..e447639 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommand.kt
@@ -37,7 +37,7 @@ class ChatModeToggleCommand(
handleResult(context, result)
}
- private fun execute(ctx: CommandContext): CommandResult {
+ internal fun execute(ctx: CommandContext): CommandResult {
val sender = ctx.requirePlayer()
val newMode = chatModeManager.toggleChatMode(sender.uniqueId)
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommandTest.kt
new file mode 100644
index 0000000..95c8b92
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/StatusCommandTest.kt
@@ -0,0 +1,125 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc
+
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.paper.BuildInfo
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.config.LunaticChatConfiguration
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import dev.m1sk9.lunaticChat.paper.velocity.VelocityConnectionManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.mockkObject
+import io.mockk.unmockkObject
+import io.mockk.verify
+import net.kyori.adventure.text.Component
+import java.util.UUID
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class StatusCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+
+ private fun createDependencies(configuration: LunaticChatConfiguration = TestUtils.createTestConfiguration()): TestDeps {
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val languageManager = mockk<LanguageManager>(relaxed = true)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+
+ every { plugin.velocityConnectionManager } returns null
+
+ val mockPlayer = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns mockPlayer
+
+ val command = StatusCommand(plugin, languageManager, configuration)
+ return TestDeps(command, ctx, plugin, languageManager, configuration, mockPlayer)
+ }
+
+ private data class TestDeps(
+ val command: StatusCommand,
+ val ctx: CommandContext,
+ val plugin: LunaticChat,
+ val languageManager: LanguageManager,
+ val configuration: LunaticChatConfiguration,
+ val mockPlayer: org.bukkit.entity.Player,
+ )
+
+ @Test
+ fun `execute should return Success`() {
+ val deps = createDependencies()
+
+ mockkObject(BuildInfo)
+ try {
+ every { BuildInfo.versionWithCommit() } returns "0.10.0-test"
+
+ val result = deps.command.execute(deps.ctx)
+
+ assertIs<CommandResult.Success>(result)
+ } finally {
+ unmockkObject(BuildInfo)
+ }
+ }
+
+ @Test
+ fun `execute should send messages to player`() {
+ val deps = createDependencies()
+
+ mockkObject(BuildInfo)
+ try {
+ every { BuildInfo.versionWithCommit() } returns "0.10.0-test"
+
+ deps.command.execute(deps.ctx)
+
+ verify(atLeast = 1) { deps.mockPlayer.sendMessage(any<Component>()) }
+ } finally {
+ unmockkObject(BuildInfo)
+ }
+ }
+
+ @Test
+ fun `execute with velocity enabled should check connection state`() {
+ val velocityConfig =
+ TestUtils.createTestConfiguration().let { config ->
+ config.copy(
+ features =
+ config.features.copy(
+ velocityIntegration = config.features.velocityIntegration.copy(enabled = true),
+ ),
+ )
+ }
+ val deps = createDependencies(configuration = velocityConfig)
+
+ val velocityManager = mockk<VelocityConnectionManager>(relaxed = true)
+ every { velocityManager.getState() } returns VelocityConnectionManager.ConnectionState.CONNECTED
+ every { deps.plugin.velocityConnectionManager } returns velocityManager
+
+ mockkObject(BuildInfo)
+ try {
+ every { BuildInfo.versionWithCommit() } returns "0.10.0-test"
+
+ val result = deps.command.execute(deps.ctx)
+
+ assertIs<CommandResult.Success>(result)
+ } finally {
+ unmockkObject(BuildInfo)
+ }
+ }
+
+ @Test
+ fun `execute should display feature toggles`() {
+ val deps = createDependencies()
+
+ mockkObject(BuildInfo)
+ try {
+ every { BuildInfo.versionWithCommit() } returns "0.10.0-test"
+
+ deps.command.execute(deps.ctx)
+
+ // Verify multiple sendMessage calls for version, health, features, config, and links
+ verify(atLeast = 5) { deps.mockPlayer.sendMessage(any<Component>()) }
+ } finally {
+ unmockkObject(BuildInfo)
+ }
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelBanCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelBanCommandTest.kt
new file mode 100644
index 0000000..59fc98a
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelBanCommandTest.kt
@@ -0,0 +1,137 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.chat.channel.Channel
+import dev.m1sk9.lunaticChat.engine.chat.channel.ChannelRole
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.engine.exception.ChannelPlayerAlreadyBannedException
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
+import dev.m1sk9.lunaticChat.paper.chat.handler.ChannelNotificationHandler
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.mockkStatic
+import io.mockk.unmockkStatic
+import io.mockk.verify
+import org.bukkit.Bukkit
+import org.bukkit.OfflinePlayer
+import java.util.UUID
+import kotlin.test.AfterTest
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelBanCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+ private val targetUUID = UUID.fromString("00000002-0000-0000-0000-000000000000")
+ private val channelId = "test-ch"
+
+ private val plugin = mockk<LunaticChat>(relaxed = true)
+ private val channelManager = mockk<ChannelManager>(relaxed = true)
+ private val membershipManager = mockk<ChannelMembershipManager>(relaxed = true)
+ private val notificationHandler = mockk<ChannelNotificationHandler>(relaxed = true)
+ private val languageManager = mockk<LanguageManager>(relaxed = true)
+
+ private val command = ChannelBanCommand(plugin, channelManager, membershipManager, notificationHandler, languageManager)
+
+ @BeforeTest
+ fun setUp() {
+ mockkStatic(Bukkit::class)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+ }
+
+ @AfterTest
+ fun tearDown() {
+ unmockkStatic(Bukkit::class)
+ }
+
+ private fun createContext(): CommandContext {
+ val mockPlayer = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns mockPlayer
+ return ctx
+ }
+
+ private fun setupOfflinePlayer(
+ hasPlayedBefore: Boolean = true,
+ isOnline: Boolean = false,
+ ): OfflinePlayer {
+ val offlinePlayer = mockk<OfflinePlayer>(relaxed = true)
+ every { offlinePlayer.uniqueId } returns targetUUID
+ every { offlinePlayer.hasPlayedBefore() } returns hasPlayedBefore
+ every { offlinePlayer.isOnline } returns isOnline
+ every { offlinePlayer.name } returns "TargetPlayer"
+ every { Bukkit.getOfflinePlayer(any<String>()) } returns offlinePlayer
+ return offlinePlayer
+ }
+
+ @Test
+ fun `execute should return SuccessWithMessage on ban`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer()
+ every { Bukkit.getPlayer(any<String>()) } returns null
+
+ val channel = Channel(id = channelId, name = "Test Channel", ownerId = testUUID, createdAt = 1000L)
+ every { channelManager.banPlayer(channelId, targetUUID) } returns Result.success(channel)
+ every { channelManager.getChannel(channelId) } returns Result.success(channel)
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ verify { channelManager.banPlayer(channelId, targetUUID) }
+ }
+
+ @Test
+ fun `execute should return Failure when no active channel`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns null
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when no permission`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.MEMBER
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when player not found`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer(hasPlayedBefore = false, isOnline = false)
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when already banned`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer()
+ every { Bukkit.getPlayer(any<String>()) } returns null
+
+ every { channelManager.banPlayer(channelId, targetUUID) } returns
+ Result.failure(ChannelPlayerAlreadyBannedException(targetUUID, channelId))
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelCreateCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelCreateCommandTest.kt
new file mode 100644
index 0000000..9c57eec
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelCreateCommandTest.kt
@@ -0,0 +1,128 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.engine.exception.ChannelLimitExceededException
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.verify
+import java.util.UUID
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelCreateCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+
+ private fun createDependencies(): Triple<CommandContext, ChannelManager, LanguageManager> {
+ val player = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns player
+
+ val channelManager = mockk<ChannelManager>(relaxed = true)
+ val languageManager = mockk<LanguageManager>(relaxed = true)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+ every { languageManager.getMessage(any()) } returns "test message"
+
+ return Triple(ctx, channelManager, languageManager)
+ }
+
+ @Test
+ fun `execute with valid ID should return SuccessWithMessage`() {
+ val (ctx, channelManager, languageManager) = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelCreateCommand(plugin, channelManager, languageManager)
+
+ every { channelManager.createChannel(any()) } returns
+ Result.success(
+ TestUtils.createTestChannel(id = "test-ch", name = "Test Channel", ownerId = testUUID),
+ )
+
+ val result = command.execute(ctx, "test-ch", "Test Channel", null, false)
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ }
+
+ @Test
+ fun `execute with private channel should return SuccessWithMessage`() {
+ val (ctx, channelManager, languageManager) = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelCreateCommand(plugin, channelManager, languageManager)
+
+ every { channelManager.createChannel(any()) } returns
+ Result.success(
+ TestUtils.createTestChannel(id = "private-ch", name = "Private Channel", ownerId = testUUID, isPrivate = true),
+ )
+
+ val result = command.execute(ctx, "private-ch", "Private Channel", null, true)
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ }
+
+ @Test
+ fun `execute with invalid ID pattern should return Failure`() {
+ val (ctx, channelManager, languageManager) = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelCreateCommand(plugin, channelManager, languageManager)
+
+ val result = command.execute(ctx, "ab", "Short ID", null, false)
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute when channel already exists should return Failure`() {
+ val (ctx, channelManager, languageManager) = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelCreateCommand(plugin, channelManager, languageManager)
+
+ every { channelManager.createChannel(any()) } returns
+ Result.failure(
+ IllegalArgumentException("Channel already exists"),
+ )
+
+ val result = command.execute(ctx, "existing-ch", "Existing Channel", null, false)
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute when limit exceeded should return Failure`() {
+ val (ctx, channelManager, languageManager) = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelCreateCommand(plugin, channelManager, languageManager)
+
+ every { channelManager.createChannel(any()) } returns
+ Result.failure(
+ ChannelLimitExceededException(10),
+ )
+
+ val result = command.execute(ctx, "new-channel", "New Channel", null, false)
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute with description should pass it to channel`() {
+ val (ctx, channelManager, languageManager) = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelCreateCommand(plugin, channelManager, languageManager)
+
+ every { channelManager.createChannel(any()) } returns
+ Result.success(
+ TestUtils.createTestChannel(id = "desc-ch", name = "Desc Channel", description = "test desc", ownerId = testUUID),
+ )
+
+ val result = command.execute(ctx, "desc-ch", "Desc Channel", "test desc", false)
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ verify {
+ channelManager.createChannel(
+ match { it.description == "test desc" },
+ )
+ }
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommandTest.kt
new file mode 100644
index 0000000..5b76978
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommandTest.kt
@@ -0,0 +1,95 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.engine.exception.ChannelNoOwnerPermissionException
+import dev.m1sk9.lunaticChat.engine.exception.ChannelNotFoundException
+import dev.m1sk9.lunaticChat.engine.permission.LunaticChatPermissionNode
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.verify
+import java.util.UUID
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelDeleteCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+
+ private fun createDependencies(hasBypass: Boolean = false): Triple<CommandContext, ChannelManager, LanguageManager> {
+ val player = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ every { player.hasPermission(LunaticChatPermissionNode.ChannelBypass.permissionNode) } returns hasBypass
+
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns player
+
+ val channelManager = mockk<ChannelManager>(relaxed = true)
+ val languageManager = mockk<LanguageManager>(relaxed = true)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+ every { languageManager.getMessage(any()) } returns "test message"
+
+ return Triple(ctx, channelManager, languageManager)
+ }
+
+ @Test
+ fun `execute should return SuccessWithMessage on successful delete`() {
+ val (ctx, channelManager, languageManager) = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelDeleteCommand(plugin, channelManager, languageManager)
+
+ every { channelManager.deleteChannel("test-ch", testUUID, false) } returns Result.success(Unit)
+
+ val result = command.execute(ctx, "test-ch")
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when channel not found`() {
+ val (ctx, channelManager, languageManager) = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelDeleteCommand(plugin, channelManager, languageManager)
+
+ every { channelManager.deleteChannel("unknown-ch", testUUID, false) } returns
+ Result.failure(
+ ChannelNotFoundException("unknown-ch"),
+ )
+
+ val result = command.execute(ctx, "unknown-ch")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when no owner permission`() {
+ val (ctx, channelManager, languageManager) = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelDeleteCommand(plugin, channelManager, languageManager)
+
+ every { channelManager.deleteChannel("other-ch", testUUID, false) } returns
+ Result.failure(
+ ChannelNoOwnerPermissionException(testUUID),
+ )
+
+ val result = command.execute(ctx, "other-ch")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute with bypass permission should pass hasBypass true`() {
+ val (ctx, channelManager, languageManager) = createDependencies(hasBypass = true)
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelDeleteCommand(plugin, channelManager, languageManager)
+
+ every { channelManager.deleteChannel("test-ch", testUUID, true) } returns Result.success(Unit)
+
+ val result = command.execute(ctx, "test-ch")
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ verify { channelManager.deleteChannel("test-ch", testUUID, true) }
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInfoCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInfoCommandTest.kt
new file mode 100644
index 0000000..f1cd3a3
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInfoCommandTest.kt
@@ -0,0 +1,123 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.engine.exception.ChannelNotFoundException
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.mockkStatic
+import io.mockk.unmockkStatic
+import org.bukkit.Bukkit
+import org.bukkit.OfflinePlayer
+import java.util.UUID
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelInfoCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+ private val channelId = "test-channel-1"
+
+ private fun createDependencies(): TestDeps {
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val channelManager = mockk<ChannelManager>(relaxed = true)
+ val languageManager = mockk<LanguageManager>(relaxed = true)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+
+ val mockPlayer = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns mockPlayer
+
+ val command = ChannelInfoCommand(plugin, channelManager, languageManager)
+ return TestDeps(command, ctx, channelManager, languageManager, mockPlayer)
+ }
+
+ private data class TestDeps(
+ val command: ChannelInfoCommand,
+ val ctx: CommandContext,
+ val channelManager: ChannelManager,
+ val languageManager: LanguageManager,
+ val mockPlayer: org.bukkit.entity.Player,
+ )
+
+ private fun mockBukkitOfflinePlayer() {
+ val offlinePlayer = mockk<OfflinePlayer>(relaxed = true)
+ every { offlinePlayer.name } returns "Player1"
+ every { Bukkit.getOfflinePlayer(any<UUID>()) } returns offlinePlayer
+ }
+
+ @Test
+ fun `execute with channelId should return Success`() {
+ val deps = createDependencies()
+ val channel = TestUtils.createTestChannel(id = channelId, ownerId = testUUID)
+ val members =
+ listOf(
+ TestUtils.createTestChannelMember(channelId = channelId, playerId = testUUID),
+ )
+
+ every { deps.channelManager.getChannel(channelId) } returns Result.success(channel)
+ every { deps.channelManager.getChannelMembers(channelId) } returns Result.success(members)
+
+ mockkStatic(Bukkit::class)
+ try {
+ mockBukkitOfflinePlayer()
+
+ val result = deps.command.execute(deps.ctx, channelId)
+
+ assertIs<CommandResult.Success>(result)
+ } finally {
+ unmockkStatic(Bukkit::class)
+ }
+ }
+
+ @Test
+ fun `execute with null channelId should use active channel`() {
+ val deps = createDependencies()
+ val channel = TestUtils.createTestChannel(id = channelId, ownerId = testUUID)
+ val members =
+ listOf(
+ TestUtils.createTestChannelMember(channelId = channelId, playerId = testUUID),
+ )
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { deps.channelManager.getChannel(channelId) } returns Result.success(channel)
+ every { deps.channelManager.getChannelMembers(channelId) } returns Result.success(members)
+
+ mockkStatic(Bukkit::class)
+ try {
+ mockBukkitOfflinePlayer()
+
+ val result = deps.command.execute(deps.ctx, null)
+
+ assertIs<CommandResult.Success>(result)
+ } finally {
+ unmockkStatic(Bukkit::class)
+ }
+ }
+
+ @Test
+ fun `execute should return Failure when no channel specified and no active channel`() {
+ val deps = createDependencies()
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns null
+
+ val result = deps.command.execute(deps.ctx, null)
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when channel not found`() {
+ val deps = createDependencies()
+
+ every { deps.channelManager.getChannel("nonexistent") } returns
+ Result.failure(ChannelNotFoundException("nonexistent"))
+
+ val result = deps.command.execute(deps.ctx, "nonexistent")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInviteCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInviteCommandTest.kt
new file mode 100644
index 0000000..c51f460
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelInviteCommandTest.kt
@@ -0,0 +1,152 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.chat.channel.ChannelRole
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.mockkStatic
+import io.mockk.unmockkStatic
+import org.bukkit.Bukkit
+import java.util.UUID
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelInviteCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+ private val targetUUID = UUID.fromString("00000002-0000-0000-0000-000000000000")
+ private val channelId = "test-channel-1"
+
+ private fun createDependencies(): TestDeps {
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val channelManager = mockk<ChannelManager>(relaxed = true)
+ val membershipManager = mockk<ChannelMembershipManager>(relaxed = true)
+ val languageManager = mockk<LanguageManager>(relaxed = true)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+
+ val mockPlayer = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns mockPlayer
+
+ val command = ChannelInviteCommand(plugin, channelManager, membershipManager, languageManager)
+ return TestDeps(command, ctx, channelManager, membershipManager, languageManager, mockPlayer)
+ }
+
+ private data class TestDeps(
+ val command: ChannelInviteCommand,
+ val ctx: CommandContext,
+ val channelManager: ChannelManager,
+ val membershipManager: ChannelMembershipManager,
+ val languageManager: LanguageManager,
+ val mockPlayer: org.bukkit.entity.Player,
+ )
+
+ @Test
+ fun `execute should return SuccessWithMessage on invite`() {
+ val deps = createDependencies()
+ val targetPlayer = TestUtils.createMockPlayer(uuid = targetUUID, name = "TargetPlayer")
+ val channel = TestUtils.createTestChannel(id = channelId, ownerId = testUUID)
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { deps.membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ every { deps.channelManager.isPlayerBanned(channelId, targetUUID) } returns Result.success(false)
+ every { deps.membershipManager.joinChannel(targetUUID, channelId, bypassPrivateCheck = true) } returns Result.success(Unit)
+ every { deps.channelManager.getChannel(channelId) } returns Result.success(channel)
+
+ mockkStatic(Bukkit::class)
+ try {
+ every { Bukkit.getPlayer(any<String>()) } returns targetPlayer
+
+ val result = deps.command.execute(deps.ctx, "TargetPlayer")
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ } finally {
+ unmockkStatic(Bukkit::class)
+ }
+ }
+
+ @Test
+ fun `execute should return Failure when inviting self`() {
+ val deps = createDependencies()
+ val selfTarget = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { deps.membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+
+ mockkStatic(Bukkit::class)
+ try {
+ every { Bukkit.getPlayer(any<String>()) } returns selfTarget
+
+ val result = deps.command.execute(deps.ctx, "Player1")
+
+ assertIs<CommandResult.Failure>(result)
+ } finally {
+ unmockkStatic(Bukkit::class)
+ }
+ }
+
+ @Test
+ fun `execute should return Failure when target is banned`() {
+ val deps = createDependencies()
+ val targetPlayer = TestUtils.createMockPlayer(uuid = targetUUID, name = "TargetPlayer")
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { deps.membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ every { deps.channelManager.isPlayerBanned(channelId, targetUUID) } returns Result.success(true)
+
+ mockkStatic(Bukkit::class)
+ try {
+ every { Bukkit.getPlayer(any<String>()) } returns targetPlayer
+
+ val result = deps.command.execute(deps.ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ } finally {
+ unmockkStatic(Bukkit::class)
+ }
+ }
+
+ @Test
+ fun `execute should return Failure when player not found`() {
+ val deps = createDependencies()
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { deps.membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+
+ mockkStatic(Bukkit::class)
+ try {
+ every { Bukkit.getPlayer(any<String>()) } returns null
+
+ val result = deps.command.execute(deps.ctx, "OfflinePlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ } finally {
+ unmockkStatic(Bukkit::class)
+ }
+ }
+
+ @Test
+ fun `execute should return Failure when no permission`() {
+ val deps = createDependencies()
+ val targetPlayer = TestUtils.createMockPlayer(uuid = targetUUID, name = "TargetPlayer")
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { deps.membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.MEMBER
+
+ mockkStatic(Bukkit::class)
+ try {
+ every { Bukkit.getPlayer(any<String>()) } returns targetPlayer
+
+ val result = deps.command.execute(deps.ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ } finally {
+ unmockkStatic(Bukkit::class)
+ }
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommandTest.kt
new file mode 100644
index 0000000..72f0040
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommandTest.kt
@@ -0,0 +1,151 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.engine.exception.ChannelAlreadyActiveException
+import dev.m1sk9.lunaticChat.engine.exception.ChannelMemberAlreadyException
+import dev.m1sk9.lunaticChat.engine.exception.ChannelNotFoundException
+import dev.m1sk9.lunaticChat.engine.exception.ChannelPlayerBannedException
+import dev.m1sk9.lunaticChat.engine.exception.ChannelPrivateRequiresInvitationException
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
+import dev.m1sk9.lunaticChat.paper.chat.handler.ChannelNotificationHandler
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import java.util.UUID
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelJoinCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+
+ private data class Dependencies(
+ val ctx: CommandContext,
+ val channelManager: ChannelManager,
+ val membershipManager: ChannelMembershipManager,
+ val notificationHandler: ChannelNotificationHandler,
+ val languageManager: LanguageManager,
+ )
+
+ private fun createDependencies(): Dependencies {
+ val player = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns player
+
+ val channelManager = mockk<ChannelManager>(relaxed = true)
+ val membershipManager = mockk<ChannelMembershipManager>(relaxed = true)
+ val notificationHandler = mockk<ChannelNotificationHandler>(relaxed = true)
+ val languageManager = mockk<LanguageManager>(relaxed = true)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+ every { languageManager.getMessage(any()) } returns "test message"
+
+ every { channelManager.getChannel(any()) } returns
+ Result.success(
+ TestUtils.createTestChannel(id = "test-ch", name = "Test Channel"),
+ )
+
+ return Dependencies(ctx, channelManager, membershipManager, notificationHandler, languageManager)
+ }
+
+ @Test
+ fun `execute should return SuccessWithMessage on join`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command =
+ ChannelJoinCommand(plugin, deps.channelManager, deps.membershipManager, deps.notificationHandler, deps.languageManager)
+
+ every { deps.membershipManager.joinChannel(testUUID, "test-ch") } returns Result.success(Unit)
+
+ val result = command.execute(deps.ctx, "test-ch")
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when channel not found`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command =
+ ChannelJoinCommand(plugin, deps.channelManager, deps.membershipManager, deps.notificationHandler, deps.languageManager)
+
+ every { deps.membershipManager.joinChannel(testUUID, "unknown-ch") } returns
+ Result.failure(
+ ChannelNotFoundException("unknown-ch"),
+ )
+
+ val result = command.execute(deps.ctx, "unknown-ch")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when already active`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command =
+ ChannelJoinCommand(plugin, deps.channelManager, deps.membershipManager, deps.notificationHandler, deps.languageManager)
+
+ every { deps.membershipManager.joinChannel(testUUID, "test-ch") } returns
+ Result.failure(
+ ChannelAlreadyActiveException(testUUID, "test-ch"),
+ )
+
+ val result = command.execute(deps.ctx, "test-ch")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when already member`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command =
+ ChannelJoinCommand(plugin, deps.channelManager, deps.membershipManager, deps.notificationHandler, deps.languageManager)
+
+ every { deps.membershipManager.joinChannel(testUUID, "test-ch") } returns
+ Result.failure(
+ ChannelMemberAlreadyException(testUUID, "test-ch"),
+ )
+
+ val result = command.execute(deps.ctx, "test-ch")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when banned`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command =
+ ChannelJoinCommand(plugin, deps.channelManager, deps.membershipManager, deps.notificationHandler, deps.languageManager)
+
+ every { deps.membershipManager.joinChannel(testUUID, "test-ch") } returns
+ Result.failure(
+ ChannelPlayerBannedException(testUUID, "test-ch"),
+ )
+
+ val result = command.execute(deps.ctx, "test-ch")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when private without invite`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command =
+ ChannelJoinCommand(plugin, deps.channelManager, deps.membershipManager, deps.notificationHandler, deps.languageManager)
+
+ every { deps.membershipManager.joinChannel(testUUID, "private-ch") } returns
+ Result.failure(
+ ChannelPrivateRequiresInvitationException(testUUID, "private-ch"),
+ )
+
+ val result = command.execute(deps.ctx, "private-ch")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelKickCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelKickCommandTest.kt
new file mode 100644
index 0000000..cab6ef0
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelKickCommandTest.kt
@@ -0,0 +1,136 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.chat.channel.Channel
+import dev.m1sk9.lunaticChat.engine.chat.channel.ChannelRole
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
+import dev.m1sk9.lunaticChat.paper.chat.handler.ChannelNotificationHandler
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.mockkStatic
+import io.mockk.unmockkStatic
+import io.mockk.verify
+import org.bukkit.Bukkit
+import org.bukkit.OfflinePlayer
+import java.util.UUID
+import kotlin.test.AfterTest
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelKickCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+ private val targetUUID = UUID.fromString("00000002-0000-0000-0000-000000000000")
+ private val channelId = "test-ch"
+
+ private val plugin = mockk<LunaticChat>(relaxed = true)
+ private val channelManager = mockk<ChannelManager>(relaxed = true)
+ private val membershipManager = mockk<ChannelMembershipManager>(relaxed = true)
+ private val notificationHandler = mockk<ChannelNotificationHandler>(relaxed = true)
+ private val languageManager = mockk<LanguageManager>(relaxed = true)
+
+ private val command = ChannelKickCommand(plugin, channelManager, membershipManager, notificationHandler, languageManager)
+
+ @BeforeTest
+ fun setUp() {
+ mockkStatic(Bukkit::class)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+ }
+
+ @AfterTest
+ fun tearDown() {
+ unmockkStatic(Bukkit::class)
+ }
+
+ private fun createContext(): CommandContext {
+ val mockPlayer = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns mockPlayer
+ return ctx
+ }
+
+ private fun setupOfflinePlayer(
+ hasPlayedBefore: Boolean = true,
+ isOnline: Boolean = false,
+ ): OfflinePlayer {
+ val offlinePlayer = mockk<OfflinePlayer>(relaxed = true)
+ every { offlinePlayer.uniqueId } returns targetUUID
+ every { offlinePlayer.hasPlayedBefore() } returns hasPlayedBefore
+ every { offlinePlayer.isOnline } returns isOnline
+ every { offlinePlayer.name } returns "TargetPlayer"
+ every { Bukkit.getOfflinePlayer(any<String>()) } returns offlinePlayer
+ return offlinePlayer
+ }
+
+ @Test
+ fun `execute should return SuccessWithMessage on kick`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer()
+ every { Bukkit.getPlayer(any<String>()) } returns null
+ every { membershipManager.isMember(targetUUID, channelId) } returns Result.success(true)
+
+ val channel = Channel(id = channelId, name = "Test Channel", ownerId = testUUID, createdAt = 1000L)
+ every { channelManager.removeMember(channelId, targetUUID) } returns Result.success(Unit)
+ every { channelManager.getPlayerChannel(targetUUID) } returns channelId
+ every { channelManager.getChannel(channelId) } returns Result.success(channel)
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ verify { channelManager.removeMember(channelId, targetUUID) }
+ }
+
+ @Test
+ fun `execute should return Failure when no active channel`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns null
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when no permission`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.MEMBER
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when target not member`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer()
+ every { Bukkit.getPlayer(any<String>()) } returns null
+ every { membershipManager.isMember(targetUUID, channelId) } returns Result.success(false)
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when player not found`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer(hasPlayedBefore = false, isOnline = false)
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommandTest.kt
new file mode 100644
index 0000000..b97fe99
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommandTest.kt
@@ -0,0 +1,125 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.engine.exception.ChannelNotMemberException
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
+import dev.m1sk9.lunaticChat.paper.chat.handler.ChannelNotificationHandler
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.verify
+import java.util.UUID
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelLeaveCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+
+ private data class Dependencies(
+ val ctx: CommandContext,
+ val channelManager: ChannelManager,
+ val membershipManager: ChannelMembershipManager,
+ val notificationHandler: ChannelNotificationHandler,
+ val languageManager: LanguageManager,
+ )
+
+ private fun createDependencies(): Dependencies {
+ val player = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns player
+
+ val channelManager = mockk<ChannelManager>(relaxed = true)
+ val membershipManager = mockk<ChannelMembershipManager>(relaxed = true)
+ val notificationHandler = mockk<ChannelNotificationHandler>(relaxed = true)
+ val languageManager = mockk<LanguageManager>(relaxed = true)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+ every { languageManager.getMessage(any()) } returns "test message"
+
+ return Dependencies(ctx, channelManager, membershipManager, notificationHandler, languageManager)
+ }
+
+ @Test
+ fun `execute should return SuccessWithMessage on leave`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command =
+ ChannelLeaveCommand(plugin, deps.channelManager, deps.membershipManager, deps.notificationHandler, deps.languageManager)
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns "ch-1"
+ every { deps.channelManager.getChannel("ch-1") } returns
+ Result.success(
+ TestUtils.createTestChannel(id = "ch-1", name = "Channel One"),
+ )
+ every { deps.membershipManager.leaveChannel(testUUID) } returns Result.success(Unit)
+
+ val result = command.execute(deps.ctx)
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when no active channel`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command =
+ ChannelLeaveCommand(plugin, deps.channelManager, deps.membershipManager, deps.notificationHandler, deps.languageManager)
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns null
+ every { deps.membershipManager.leaveChannel(testUUID) } returns
+ Result.failure(
+ ChannelNotMemberException(testUUID, ""),
+ )
+
+ val result = command.execute(deps.ctx)
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should broadcast leave notification`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command =
+ ChannelLeaveCommand(plugin, deps.channelManager, deps.membershipManager, deps.notificationHandler, deps.languageManager)
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns "ch-1"
+ every { deps.channelManager.getChannel("ch-1") } returns
+ Result.success(
+ TestUtils.createTestChannel(id = "ch-1", name = "Channel One"),
+ )
+ every { deps.membershipManager.leaveChannel(testUUID) } returns Result.success(Unit)
+
+ command.execute(deps.ctx)
+
+ verify { deps.notificationHandler.broadcastLeave("ch-1", "Player1") }
+ }
+
+ @Test
+ fun `execute should show channel name in success message`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command =
+ ChannelLeaveCommand(plugin, deps.channelManager, deps.membershipManager, deps.notificationHandler, deps.languageManager)
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns "ch-1"
+ every { deps.channelManager.getChannel("ch-1") } returns
+ Result.success(
+ TestUtils.createTestChannel(id = "ch-1", name = "My Channel"),
+ )
+ every { deps.membershipManager.leaveChannel(testUUID) } returns Result.success(Unit)
+
+ val result = command.execute(deps.ctx)
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ verify {
+ deps.languageManager.getMessage(
+ "channel.leave.success",
+ match { it["channelName"] == "My Channel" },
+ )
+ }
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommandTest.kt
new file mode 100644
index 0000000..5ca6184
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommandTest.kt
@@ -0,0 +1,107 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.engine.exception.ChannelNotFoundException
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import java.util.UUID
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelListCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+
+ private fun createDependencies(): TestDeps {
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val channelManager = mockk<ChannelManager>(relaxed = true)
+ val languageManager = mockk<LanguageManager>(relaxed = true)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+
+ val mockPlayer = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns mockPlayer
+
+ val command = ChannelListCommand(plugin, channelManager, languageManager)
+ return TestDeps(command, ctx, channelManager, languageManager, mockPlayer)
+ }
+
+ private data class TestDeps(
+ val command: ChannelListCommand,
+ val ctx: CommandContext,
+ val channelManager: ChannelManager,
+ val languageManager: LanguageManager,
+ val mockPlayer: org.bukkit.entity.Player,
+ )
+
+ @Test
+ fun `execute should return Success with public channels`() {
+ val deps = createDependencies()
+ val channels =
+ listOf(
+ TestUtils.createTestChannel(id = "channel-1", name = "Channel 1", ownerId = testUUID),
+ TestUtils.createTestChannel(id = "channel-2", name = "Channel 2", ownerId = testUUID),
+ )
+ val members =
+ listOf(
+ TestUtils.createTestChannelMember(channelId = "channel-1", playerId = testUUID),
+ )
+
+ every { deps.channelManager.getPublicChannels() } returns Result.success(channels)
+ every { deps.channelManager.getChannelMembers(any()) } returns Result.success(members)
+
+ val result = deps.command.execute(deps.ctx, 1)
+
+ assertIs<CommandResult.Success>(result)
+ }
+
+ @Test
+ fun `execute should return Success with empty list message`() {
+ val deps = createDependencies()
+
+ every { deps.channelManager.getPublicChannels() } returns Result.success(emptyList())
+
+ val result = deps.command.execute(deps.ctx, 1)
+
+ assertIs<CommandResult.Success>(result)
+ }
+
+ @Test
+ fun `execute should return Success on page 1 of multiple`() {
+ val deps = createDependencies()
+ val channels =
+ (1..15).map { i ->
+ TestUtils.createTestChannel(
+ id = "channel-$i",
+ name = "Channel $i",
+ ownerId = testUUID,
+ )
+ }
+ val members =
+ listOf(
+ TestUtils.createTestChannelMember(channelId = "channel-1", playerId = testUUID),
+ )
+
+ every { deps.channelManager.getPublicChannels() } returns Result.success(channels)
+ every { deps.channelManager.getChannelMembers(any()) } returns Result.success(members)
+
+ val result = deps.command.execute(deps.ctx, 1)
+
+ assertIs<CommandResult.Success>(result)
+ }
+
+ @Test
+ fun `execute should return Failure on error`() {
+ val deps = createDependencies()
+
+ every { deps.channelManager.getPublicChannels() } returns Result.failure(ChannelNotFoundException("error"))
+
+ val result = deps.command.execute(deps.ctx, 1)
+
+ assertIs<CommandResult.Failure>(result)
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelModCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelModCommandTest.kt
new file mode 100644
index 0000000..da7c7e2
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelModCommandTest.kt
@@ -0,0 +1,147 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.chat.channel.Channel
+import dev.m1sk9.lunaticChat.engine.chat.channel.ChannelRole
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.mockkStatic
+import io.mockk.unmockkStatic
+import io.mockk.verify
+import org.bukkit.Bukkit
+import org.bukkit.OfflinePlayer
+import java.util.UUID
+import kotlin.test.AfterTest
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelModCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+ private val targetUUID = UUID.fromString("00000002-0000-0000-0000-000000000000")
+ private val channelId = "test-ch"
+
+ private val plugin = mockk<LunaticChat>(relaxed = true)
+ private val channelManager = mockk<ChannelManager>(relaxed = true)
+ private val membershipManager = mockk<ChannelMembershipManager>(relaxed = true)
+ private val languageManager = mockk<LanguageManager>(relaxed = true)
+
+ private val command = ChannelModCommand(plugin, channelManager, membershipManager, languageManager)
+
+ @BeforeTest
+ fun setUp() {
+ mockkStatic(Bukkit::class)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+ }
+
+ @AfterTest
+ fun tearDown() {
+ unmockkStatic(Bukkit::class)
+ }
+
+ private fun createContext(): CommandContext {
+ val mockPlayer = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns mockPlayer
+ return ctx
+ }
+
+ private fun setupOfflinePlayer(
+ hasPlayedBefore: Boolean = true,
+ isOnline: Boolean = false,
+ ): OfflinePlayer {
+ val offlinePlayer = mockk<OfflinePlayer>(relaxed = true)
+ every { offlinePlayer.uniqueId } returns targetUUID
+ every { offlinePlayer.hasPlayedBefore() } returns hasPlayedBefore
+ every { offlinePlayer.isOnline } returns isOnline
+ every { offlinePlayer.name } returns "TargetPlayer"
+ every { Bukkit.getOfflinePlayer(any<String>()) } returns offlinePlayer
+ return offlinePlayer
+ }
+
+ @Test
+ fun `execute should promote to moderator`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer()
+ every { membershipManager.getMemberRoleOrNull(targetUUID, channelId) } returns ChannelRole.MEMBER
+
+ val channel = Channel(id = channelId, name = "Test Channel", ownerId = testUUID, createdAt = 1000L)
+ every { channelManager.updateMemberRole(channelId, targetUUID, ChannelRole.MODERATOR) } returns Result.success(Unit)
+ every { channelManager.getChannel(channelId) } returns Result.success(channel)
+ every { Bukkit.getPlayer(any<String>()) } returns null
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ verify { channelManager.updateMemberRole(channelId, targetUUID, ChannelRole.MODERATOR) }
+ }
+
+ @Test
+ fun `execute should demote from moderator`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer()
+ every { membershipManager.getMemberRoleOrNull(targetUUID, channelId) } returns ChannelRole.MODERATOR
+
+ val channel = Channel(id = channelId, name = "Test Channel", ownerId = testUUID, createdAt = 1000L)
+ every { channelManager.updateMemberRole(channelId, targetUUID, ChannelRole.MEMBER) } returns Result.success(Unit)
+ every { channelManager.getChannel(channelId) } returns Result.success(channel)
+ every { Bukkit.getPlayer(any<String>()) } returns null
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ verify { channelManager.updateMemberRole(channelId, targetUUID, ChannelRole.MEMBER) }
+ }
+
+ @Test
+ fun `execute should return Failure when modding self`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+
+ val offlinePlayer = mockk<OfflinePlayer>(relaxed = true)
+ every { offlinePlayer.uniqueId } returns testUUID
+ every { offlinePlayer.hasPlayedBefore() } returns true
+ every { offlinePlayer.isOnline } returns false
+ every { offlinePlayer.name } returns "Player1"
+ every { Bukkit.getOfflinePlayer(any<String>()) } returns offlinePlayer
+
+ val result = command.execute(ctx, "Player1")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when not owner`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.MODERATOR
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when target not member`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer()
+ every { membershipManager.getMemberRoleOrNull(targetUUID, channelId) } returns null
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelOwnershipCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelOwnershipCommandTest.kt
new file mode 100644
index 0000000..9f25264
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelOwnershipCommandTest.kt
@@ -0,0 +1,139 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.chat.channel.Channel
+import dev.m1sk9.lunaticChat.engine.chat.channel.ChannelRole
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.mockkStatic
+import io.mockk.unmockkStatic
+import io.mockk.verify
+import org.bukkit.Bukkit
+import org.bukkit.OfflinePlayer
+import java.util.UUID
+import kotlin.test.AfterTest
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelOwnershipCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+ private val targetUUID = UUID.fromString("00000002-0000-0000-0000-000000000000")
+ private val channelId = "test-ch"
+
+ private val plugin = mockk<LunaticChat>(relaxed = true)
+ private val channelManager = mockk<ChannelManager>(relaxed = true)
+ private val membershipManager = mockk<ChannelMembershipManager>(relaxed = true)
+ private val languageManager = mockk<LanguageManager>(relaxed = true)
+
+ private val command = ChannelOwnershipCommand(plugin, channelManager, membershipManager, languageManager)
+
+ @BeforeTest
+ fun setUp() {
+ mockkStatic(Bukkit::class)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+ }
+
+ @AfterTest
+ fun tearDown() {
+ unmockkStatic(Bukkit::class)
+ }
+
+ private fun createContext(): CommandContext {
+ val mockPlayer = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns mockPlayer
+ return ctx
+ }
+
+ private fun setupOfflinePlayer(
+ hasPlayedBefore: Boolean = true,
+ isOnline: Boolean = false,
+ ): OfflinePlayer {
+ val offlinePlayer = mockk<OfflinePlayer>(relaxed = true)
+ every { offlinePlayer.uniqueId } returns targetUUID
+ every { offlinePlayer.hasPlayedBefore() } returns hasPlayedBefore
+ every { offlinePlayer.isOnline } returns isOnline
+ every { offlinePlayer.name } returns "TargetPlayer"
+ every { Bukkit.getOfflinePlayer(any<String>()) } returns offlinePlayer
+ return offlinePlayer
+ }
+
+ @Test
+ fun `execute should transfer ownership successfully`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer()
+ every { membershipManager.getMemberRoleOrNull(targetUUID, channelId) } returns ChannelRole.MEMBER
+
+ val updatedChannel = Channel(id = channelId, name = "Test Channel", ownerId = targetUUID, createdAt = 1000L)
+ every { channelManager.updateChannelOwner(channelId, targetUUID) } returns Result.success(updatedChannel)
+ every { Bukkit.getPlayer(any<String>()) } returns null
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ verify { channelManager.updateChannelOwner(channelId, targetUUID) }
+ }
+
+ @Test
+ fun `execute should return Failure when transferring to self`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+
+ val offlinePlayer = mockk<OfflinePlayer>(relaxed = true)
+ every { offlinePlayer.uniqueId } returns testUUID
+ every { offlinePlayer.hasPlayedBefore() } returns true
+ every { offlinePlayer.isOnline } returns false
+ every { offlinePlayer.name } returns "Player1"
+ every { Bukkit.getOfflinePlayer(any<String>()) } returns offlinePlayer
+
+ val result = command.execute(ctx, "Player1")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when target not member`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer()
+ every { membershipManager.getMemberRoleOrNull(targetUUID, channelId) } returns null
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when not owner`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.MODERATOR
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when player not found`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer(hasPlayedBefore = false, isOnline = false)
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommandTest.kt
new file mode 100644
index 0000000..301160b
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommandTest.kt
@@ -0,0 +1,142 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.engine.exception.ChannelNotFoundException
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.mockkStatic
+import io.mockk.unmockkStatic
+import org.bukkit.Bukkit
+import org.bukkit.OfflinePlayer
+import java.util.UUID
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelStatusCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+ private val channelId = "test-channel-1"
+
+ private fun createDependencies(): TestDeps {
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val channelManager = mockk<ChannelManager>(relaxed = true)
+ val membershipManager = mockk<ChannelMembershipManager>(relaxed = true)
+ val languageManager = mockk<LanguageManager>(relaxed = true)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+
+ val mockPlayer = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns mockPlayer
+
+ val command = ChannelStatusCommand(plugin, channelManager, membershipManager, languageManager)
+ return TestDeps(command, ctx, channelManager, membershipManager, languageManager, mockPlayer)
+ }
+
+ private data class TestDeps(
+ val command: ChannelStatusCommand,
+ val ctx: CommandContext,
+ val channelManager: ChannelManager,
+ val membershipManager: ChannelMembershipManager,
+ val languageManager: LanguageManager,
+ val mockPlayer: org.bukkit.entity.Player,
+ )
+
+ private fun mockBukkitOfflinePlayer() {
+ val offlinePlayer = mockk<OfflinePlayer>(relaxed = true)
+ every { offlinePlayer.name } returns "Player1"
+ every { Bukkit.getOfflinePlayer(any<UUID>()) } returns offlinePlayer
+ }
+
+ @Test
+ fun `execute with active channel should return Success`() {
+ val deps = createDependencies()
+ val channel = TestUtils.createTestChannel(id = channelId, ownerId = testUUID)
+ val members =
+ listOf(
+ TestUtils.createTestChannelMember(channelId = channelId, playerId = testUUID),
+ )
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { deps.channelManager.getChannel(channelId) } returns Result.success(channel)
+ every { deps.channelManager.getChannelMembers(channelId) } returns Result.success(members)
+ every { deps.membershipManager.getPlayerChannels(testUUID) } returns Result.success(listOf(channelId))
+
+ mockkStatic(Bukkit::class)
+ try {
+ mockBukkitOfflinePlayer()
+
+ val result = deps.command.execute(deps.ctx)
+
+ assertIs<CommandResult.Success>(result)
+ } finally {
+ unmockkStatic(Bukkit::class)
+ }
+ }
+
+ @Test
+ fun `execute without active channel should return Success`() {
+ val deps = createDependencies()
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns null
+ every { deps.membershipManager.getPlayerChannels(testUUID) } returns Result.success(emptyList())
+
+ mockkStatic(Bukkit::class)
+ try {
+ mockBukkitOfflinePlayer()
+
+ val result = deps.command.execute(deps.ctx)
+
+ assertIs<CommandResult.Success>(result)
+ } finally {
+ unmockkStatic(Bukkit::class)
+ }
+ }
+
+ @Test
+ fun `execute with multiple channels should return Success`() {
+ val deps = createDependencies()
+ val channelIds = listOf("channel-1", "channel-2", "channel-3")
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns "channel-1"
+ every { deps.channelManager.getChannel("channel-1") } returns
+ Result.success(TestUtils.createTestChannel(id = "channel-1", name = "Channel 1", ownerId = testUUID))
+ every { deps.channelManager.getChannel("channel-2") } returns
+ Result.success(TestUtils.createTestChannel(id = "channel-2", name = "Channel 2", ownerId = testUUID))
+ every { deps.channelManager.getChannel("channel-3") } returns
+ Result.success(TestUtils.createTestChannel(id = "channel-3", name = "Channel 3", ownerId = testUUID))
+ every { deps.channelManager.getChannelMembers(any()) } returns
+ Result.success(
+ listOf(TestUtils.createTestChannelMember(playerId = testUUID)),
+ )
+ every { deps.membershipManager.getPlayerChannels(testUUID) } returns Result.success(channelIds)
+
+ mockkStatic(Bukkit::class)
+ try {
+ mockBukkitOfflinePlayer()
+
+ val result = deps.command.execute(deps.ctx)
+
+ assertIs<CommandResult.Success>(result)
+ } finally {
+ unmockkStatic(Bukkit::class)
+ }
+ }
+
+ @Test
+ fun `execute should return Failure on error`() {
+ val deps = createDependencies()
+
+ every { deps.channelManager.getPlayerChannel(testUUID) } returns null
+ every { deps.membershipManager.getPlayerChannels(testUUID) } returns
+ Result.failure(ChannelNotFoundException("error"))
+
+ val result = deps.command.execute(deps.ctx)
+
+ assertIs<CommandResult.Failure>(result)
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommandTest.kt
new file mode 100644
index 0000000..eb78956
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommandTest.kt
@@ -0,0 +1,108 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.engine.exception.ChannelAlreadyActiveException
+import dev.m1sk9.lunaticChat.engine.exception.ChannelNotFoundException
+import dev.m1sk9.lunaticChat.engine.exception.ChannelNotMemberException
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import java.util.UUID
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelSwitchCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+
+ private data class Dependencies(
+ val ctx: CommandContext,
+ val channelManager: ChannelManager,
+ val membershipManager: ChannelMembershipManager,
+ val languageManager: LanguageManager,
+ )
+
+ private fun createDependencies(): Dependencies {
+ val player = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns player
+
+ val channelManager = mockk<ChannelManager>(relaxed = true)
+ val membershipManager = mockk<ChannelMembershipManager>(relaxed = true)
+ val languageManager = mockk<LanguageManager>(relaxed = true)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+ every { languageManager.getMessage(any()) } returns "test message"
+
+ every { channelManager.getChannel(any()) } returns
+ Result.success(
+ TestUtils.createTestChannel(id = "test-ch", name = "Test Channel"),
+ )
+
+ return Dependencies(ctx, channelManager, membershipManager, languageManager)
+ }
+
+ @Test
+ fun `execute should return SuccessWithMessage on switch`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelSwitchCommand(plugin, deps.channelManager, deps.membershipManager, deps.languageManager)
+
+ every { deps.membershipManager.switchChannel(testUUID, "test-ch") } returns Result.success(Unit)
+
+ val result = command.execute(deps.ctx, "test-ch")
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when channel not found`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelSwitchCommand(plugin, deps.channelManager, deps.membershipManager, deps.languageManager)
+
+ every { deps.membershipManager.switchChannel(testUUID, "unknown-ch") } returns
+ Result.failure(
+ ChannelNotFoundException("unknown-ch"),
+ )
+
+ val result = command.execute(deps.ctx, "unknown-ch")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when already active`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelSwitchCommand(plugin, deps.channelManager, deps.membershipManager, deps.languageManager)
+
+ every { deps.membershipManager.switchChannel(testUUID, "test-ch") } returns
+ Result.failure(
+ ChannelAlreadyActiveException(testUUID, "test-ch"),
+ )
+
+ val result = command.execute(deps.ctx, "test-ch")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when not member`() {
+ val deps = createDependencies()
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val command = ChannelSwitchCommand(plugin, deps.channelManager, deps.membershipManager, deps.languageManager)
+
+ every { deps.membershipManager.switchChannel(testUUID, "other-ch") } returns
+ Result.failure(
+ ChannelNotMemberException(testUUID, "other-ch"),
+ )
+
+ val result = command.execute(deps.ctx, "other-ch")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelUnbanCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelUnbanCommandTest.kt
new file mode 100644
index 0000000..16dd383
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelUnbanCommandTest.kt
@@ -0,0 +1,121 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel
+
+import dev.m1sk9.lunaticChat.engine.chat.channel.Channel
+import dev.m1sk9.lunaticChat.engine.chat.channel.ChannelRole
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.engine.exception.ChannelPlayerNotBannedException
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
+import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.mockkStatic
+import io.mockk.unmockkStatic
+import io.mockk.verify
+import org.bukkit.Bukkit
+import org.bukkit.OfflinePlayer
+import java.util.UUID
+import kotlin.test.AfterTest
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChannelUnbanCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+ private val targetUUID = UUID.fromString("00000002-0000-0000-0000-000000000000")
+ private val channelId = "test-ch"
+
+ private val plugin = mockk<LunaticChat>(relaxed = true)
+ private val channelManager = mockk<ChannelManager>(relaxed = true)
+ private val membershipManager = mockk<ChannelMembershipManager>(relaxed = true)
+ private val languageManager = mockk<LanguageManager>(relaxed = true)
+
+ private val command = ChannelUnbanCommand(plugin, channelManager, membershipManager, languageManager)
+
+ @BeforeTest
+ fun setUp() {
+ mockkStatic(Bukkit::class)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+ }
+
+ @AfterTest
+ fun tearDown() {
+ unmockkStatic(Bukkit::class)
+ }
+
+ private fun createContext(): CommandContext {
+ val mockPlayer = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns mockPlayer
+ return ctx
+ }
+
+ private fun setupOfflinePlayer(
+ hasPlayedBefore: Boolean = true,
+ isOnline: Boolean = false,
+ ): OfflinePlayer {
+ val offlinePlayer = mockk<OfflinePlayer>(relaxed = true)
+ every { offlinePlayer.uniqueId } returns targetUUID
+ every { offlinePlayer.hasPlayedBefore() } returns hasPlayedBefore
+ every { offlinePlayer.isOnline } returns isOnline
+ every { offlinePlayer.name } returns "TargetPlayer"
+ every { Bukkit.getOfflinePlayer(any<String>()) } returns offlinePlayer
+ return offlinePlayer
+ }
+
+ @Test
+ fun `execute should return SuccessWithMessage on unban`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer()
+
+ val channel = Channel(id = channelId, name = "Test Channel", ownerId = testUUID, createdAt = 1000L)
+ every { channelManager.unbanPlayer(channelId, targetUUID) } returns Result.success(channel)
+ every { channelManager.getChannel(channelId) } returns Result.success(channel)
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.SuccessWithMessage>(result)
+ verify { channelManager.unbanPlayer(channelId, targetUUID) }
+ }
+
+ @Test
+ fun `execute should return Failure when no active channel`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns null
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when no permission`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.MEMBER
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+
+ @Test
+ fun `execute should return Failure when player not banned`() {
+ val ctx = createContext()
+ every { channelManager.getPlayerChannel(testUUID) } returns channelId
+ every { membershipManager.getMemberRoleOrNull(testUUID, channelId) } returns ChannelRole.OWNER
+ setupOfflinePlayer()
+
+ every { channelManager.unbanPlayer(channelId, targetUUID) } returns
+ Result.failure(ChannelPlayerNotBannedException(targetUUID, channelId))
+
+ val result = command.execute(ctx, "TargetPlayer")
+
+ assertIs<CommandResult.Failure>(result)
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommandTest.kt
new file mode 100644
index 0000000..d43c867
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommandTest.kt
@@ -0,0 +1,88 @@
+package dev.m1sk9.lunaticChat.paper.command.impl.lc.chatmode
+
+import dev.m1sk9.lunaticChat.engine.chat.ChatMode
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.paper.LunaticChat
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.chat.ChatModeManager
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.verify
+import net.kyori.adventure.text.Component
+import java.util.UUID
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class ChatModeToggleCommandTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+
+ private fun createDependencies(): TestDeps {
+ val plugin = mockk<LunaticChat>(relaxed = true)
+ val chatModeManager = mockk<ChatModeManager>(relaxed = true)
+ val languageManager = mockk<LanguageManager>(relaxed = true)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+
+ val mockPlayer = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns mockPlayer
+
+ val command = ChatModeToggleCommand(plugin, chatModeManager, languageManager)
+ return TestDeps(command, ctx, chatModeManager, languageManager, mockPlayer)
+ }
+
+ private data class TestDeps(
+ val command: ChatModeToggleCommand,
+ val ctx: CommandContext,
+ val chatModeManager: ChatModeManager,
+ val languageManager: LanguageManager,
+ val mockPlayer: org.bukkit.entity.Player,
+ )
+
+ @Test
+ fun `execute should toggle to CHANNEL mode`() {
+ val deps = createDependencies()
+
+ every { deps.chatModeManager.toggleChatMode(testUUID) } returns ChatMode.CHANNEL
+
+ val result = deps.command.execute(deps.ctx)
+
+ assertIs<CommandResult.Success>(result)
+ verify { deps.chatModeManager.toggleChatMode(testUUID) }
+ }
+
+ @Test
+ fun `execute should toggle to GLOBAL mode`() {
+ val deps = createDependencies()
+
+ every { deps.chatModeManager.toggleChatMode(testUUID) } returns ChatMode.GLOBAL
+
+ val result = deps.command.execute(deps.ctx)
+
+ assertIs<CommandResult.Success>(result)
+ verify { deps.chatModeManager.toggleChatMode(testUUID) }
+ }
+
+ @Test
+ fun `execute should send message to player`() {
+ val deps = createDependencies()
+
+ every { deps.chatModeManager.toggleChatMode(testUUID) } returns ChatMode.CHANNEL
+
+ deps.command.execute(deps.ctx)
+
+ verify { deps.mockPlayer.sendMessage(any<Component>()) }
+ }
+
+ @Test
+ fun `execute should return Success`() {
+ val deps = createDependencies()
+
+ every { deps.chatModeManager.toggleChatMode(testUUID) } returns ChatMode.GLOBAL
+
+ val result = deps.command.execute(deps.ctx)
+
+ assertIs<CommandResult.Success>(result)
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/setting/SettingHandlerRegistryTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/setting/SettingHandlerRegistryTest.kt
new file mode 100644
index 0000000..52927a8
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/setting/SettingHandlerRegistryTest.kt
@@ -0,0 +1,101 @@
+package dev.m1sk9.lunaticChat.paper.command.setting
+
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertNull
+import kotlin.test.assertTrue
+
+class SettingHandlerRegistryTest {
+ private fun createMockHandler(settingKey: SettingKey): SettingHandler =
+ object : SettingHandler {
+ override val key: SettingKey = settingKey
+
+ override fun execute(
+ ctx: CommandContext,
+ enable: Boolean,
+ ): CommandResult = CommandResult.Success
+
+ override fun showStatus(ctx: CommandContext): CommandResult = CommandResult.Success
+ }
+
+ @Test
+ fun `register should make handler retrievable`() {
+ val registry = SettingHandlerRegistry()
+ val handler = createMockHandler(SettingKey.Japanese)
+
+ registry.register(handler)
+
+ assertEquals(handler, registry.getHandler(SettingKey.Japanese))
+ }
+
+ @Test
+ fun `registerAll should register multiple handlers`() {
+ val registry = SettingHandlerRegistry()
+ val handler1 = createMockHandler(SettingKey.Japanese)
+ val handler2 = createMockHandler(SettingKey.Notice)
+ val handler3 = createMockHandler(SettingKey.ChNotice)
+
+ registry.registerAll(handler1, handler2, handler3)
+
+ assertEquals(handler1, registry.getHandler(SettingKey.Japanese))
+ assertEquals(handler2, registry.getHandler(SettingKey.Notice))
+ assertEquals(handler3, registry.getHandler(SettingKey.ChNotice))
+ }
+
+ @Test
+ fun `getHandler should return null for unregistered key`() {
+ val registry = SettingHandlerRegistry()
+
+ assertNull(registry.getHandler(SettingKey.Japanese))
+ }
+
+ @Test
+ fun `getAvailableKeys should return registered keys`() {
+ val registry = SettingHandlerRegistry()
+ registry.register(createMockHandler(SettingKey.Japanese))
+ registry.register(createMockHandler(SettingKey.Notice))
+
+ val keys = registry.getAvailableKeys()
+
+ assertEquals(2, keys.size)
+ assertTrue(keys.contains("japanese"))
+ assertTrue(keys.contains("notice"))
+ }
+
+ @Test
+ fun `getAvailableKeys should return empty list for empty registry`() {
+ val registry = SettingHandlerRegistry()
+ assertTrue(registry.getAvailableKeys().isEmpty())
+ }
+
+ @Test
+ fun `register should overwrite handler with same key`() {
+ val registry = SettingHandlerRegistry()
+ val handler1 = createMockHandler(SettingKey.Japanese)
+ val handler2 = createMockHandler(SettingKey.Japanese)
+
+ registry.register(handler1)
+ registry.register(handler2)
+
+ assertEquals(handler2, registry.getHandler(SettingKey.Japanese))
+ assertEquals(1, registry.getAvailableKeys().size)
+ }
+
+ @Test
+ fun `register should return registry for method chaining`() {
+ val registry = SettingHandlerRegistry()
+ val result = registry.register(createMockHandler(SettingKey.Japanese))
+
+ assertEquals(registry, result)
+ }
+
+ @Test
+ fun `registerAll should return registry for method chaining`() {
+ val registry = SettingHandlerRegistry()
+ val result = registry.registerAll(createMockHandler(SettingKey.Japanese))
+
+ assertEquals(registry, result)
+ }
+}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/setting/handler/SettingHandlerTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/setting/handler/SettingHandlerTest.kt
new file mode 100644
index 0000000..1967e1c
--- /dev/null
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/setting/handler/SettingHandlerTest.kt
@@ -0,0 +1,191 @@
+package dev.m1sk9.lunaticChat.paper.command.setting.handler
+
+import dev.m1sk9.lunaticChat.engine.command.CommandResult
+import dev.m1sk9.lunaticChat.paper.TestUtils
+import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
+import dev.m1sk9.lunaticChat.paper.command.setting.SettingKey
+import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import dev.m1sk9.lunaticChat.paper.settings.PlayerSettingsManager
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.verify
+import net.kyori.adventure.text.Component
+import java.util.UUID
+import kotlin.test.Test
+import kotlin.test.assertIs
+
+class SettingHandlerTest {
+ private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
+
+ private fun createDependencies(): Triple<CommandContext, PlayerSettingsManager, LanguageManager> {
+ val player = TestUtils.createMockPlayer(uuid = testUUID, name = "TestPlayer")
+ val ctx = mockk<CommandContext>(relaxed = true)
+ every { ctx.requirePlayer() } returns player
+
+ val settingsManager = mockk<PlayerSettingsManager>(relaxed = true)
+ every { settingsManager.getSettings(testUUID) } returns
+ TestUtils.createTestPlayerSettings(uuid = testUUID)
+
+ val languageManager = mockk<LanguageManager>(relaxed = true)
+ every { languageManager.getMessage(any(), any()) } returns "test message"
+ every { languageManager.getToggleText(any()) } returns "ON"
+
+ return Triple(ctx, settingsManager, languageManager)
+ }
+
+ // --- JapaneseConversionSettingHandler ---
+
+ @Test
+ fun `JapaneseConversionSettingHandler key should be Japanese`() {
+ val (_, settingsManager, languageManager) = createDependencies()
+ val handler = JapaneseConversionSettingHandler(settingsManager, languageManager)
+ assertIs<SettingKey.Japanese>(handler.key)
+ }
+
+ @Test
+ fun `JapaneseConversionSettingHandler execute enable should return Success`() {
+ val (ctx, settingsManager, languageManager) = createDependencies()
+ val handler = JapaneseConversionSettingHandler(settingsManager, languageManager)
+
+ val result = handler.execute(ctx, true)
+
+ assertIs<CommandResult.Success>(result)
+ verify { settingsManager.updateSettings(match { it.japaneseConversionEnabled }) }
+ }
+
+ @Test
+ fun `JapaneseConversionSettingHandler execute disable should return Success`() {
+ val (ctx, settingsManager, languageManager) = createDependencies()
+ val handler = JapaneseConversionSettingHandler(settingsManager, languageManager)
+
+ val result = handler.execute(ctx, false)
+
+ assertIs<CommandResult.Success>(result)
+ verify { settingsManager.updateSettings(match { !it.japaneseConversionEnabled }) }
+ }
+
+ @Test
+ fun `JapaneseConversionSettingHandler showStatus should return Success`() {
+ val (ctx, settingsManager, languageManager) = createDependencies()
+ val handler = JapaneseConversionSettingHandler(settingsManager, languageManager)
+
+ val result = handler.showStatus(ctx)
+
+ assertIs<CommandResult.Success>(result)
+ }
+
+ @Test
+ fun `JapaneseConversionSettingHandler execute should send message to player`() {
+ val (ctx, settingsManager, languageManager) = createDependencies()
+ val handler = JapaneseConversionSettingHandler(settingsManager, languageManager)
+
+ handler.execute(ctx, true)
+
+ val player = ctx.requirePlayer()
+ verify { player.sendMessage(any<Component>()) }
+ }
+
+ // --- DirectMessageNoticeSettingHandler ---
+
+ @Test
+ fun `DirectMessageNoticeSettingHandler key should be Notice`() {
+ val (_, settingsManager, languageManager) = createDependencies()
+ val handler = DirectMessageNoticeSettingHandler(settingsManager, languageManager)
+ assertIs<SettingKey.Notice>(handler.key)
+ }
+
+ @Test
+ fun `DirectMessageNoticeSettingHandler execute enable should return Success`() {
+ val (ctx, settingsManager, languageManager) = createDependencies()
+ val handler = DirectMessageNoticeSettingHandler(settingsManager, languageManager)
+
+ val result = handler.execute(ctx, true)
+
+ assertIs<CommandResult.Success>(result)
+ verify { settingsManager.updateSettings(match { it.directMessageNotificationEnabled }) }
+ }
+
+ @Test
+ fun `DirectMessageNoticeSettingHandler execute disable should return Success`() {
+ val (ctx, settingsManager, languageManager) = createDependencies()
+ val handler = DirectMessageNoticeSettingHandler(settingsManager, languageManager)
+
+ val result = handler.execute(ctx, false)
+
+ assertIs<CommandResult.Success>(result)
+ verify { settingsManager.updateSettings(match { !it.directMessageNotificationEnabled }) }
+ }
+
+ @Test
+ fun `DirectMessageNoticeSettingHandler showStatus should return Success`() {
+ val (ctx, settingsManager, languageManager) = createDependencies()
+ val handler = DirectMessageNoticeSettingHandler(settingsManager, languageManager)
+
+ val result = handler.showStatus(ctx)
+
+ assertIs<CommandResult.Success>(result)
+ }
+
+ @Test
+ fun `DirectMessageNoticeSettingHandler execute should send message to player`() {
+ val (ctx, settingsManager, languageManager) = createDependencies()
+ val handler = DirectMessageNoticeSettingHandler(settingsManager, languageManager)
+
+ handler.execute(ctx, true)
+
+ val player = ctx.requirePlayer()
+ verify { player.sendMessage(any<Component>()) }
+ }
+
+ // --- ChannelMessageNoticeSettingHandler ---
+
+ @Test
+ fun `ChannelMessageNoticeSettingHandler key should be ChNotice`() {
+ val (_, settingsManager, languageManager) = createDependencies()
+ val handler = ChannelMessageNoticeSettingHandler(settingsManager, languageManager)
+ assertIs<SettingKey.ChNotice>(handler.key)
+ }
+
+ @Test
+ fun `ChannelMessageNoticeSettingHandler execute enable should return Success`() {
+ val (ctx, settingsManager, languageManager) = createDependencies()
+ val handler = ChannelMessageNoticeSettingHandler(settingsManager, languageManager)
+
+ val result = handler.execute(ctx, true)
+
+ assertIs<CommandResult.Success>(result)
+ verify { settingsManager.updateSettings(match { it.channelMessageNotificationEnabled }) }
+ }
+
+ @Test
+ fun `ChannelMessageNoticeSettingHandler execute disable should return Success`() {
+ val (ctx, settingsManager, languageManager) = createDependencies()
+ val handler = ChannelMessageNoticeSettingHandler(settingsManager, languageManager)
+
+ val result = handler.execute(ctx, false)
+
+ assertIs<CommandResult.Success>(result)
+ verify { settingsManager.updateSettings(match { !it.channelMessageNotificationEnabled }) }
+ }
+
+ @Test
+ fun `ChannelMessageNoticeSettingHandler showStatus should return Success`() {
+ val (ctx, settingsManager, languageManager) = createDependencies()
+ val handler = ChannelMessageNoticeSettingHandler(settingsManager, languageManager)
+
+ val result = handler.showStatus(ctx)
+
+ assertIs<CommandResult.Success>(result)
+ }
+
+ @Test
+ fun `ChannelMessageNoticeSettingHandler execute should send message to player`() {
+ val (ctx, settingsManager, languageManager) = createDependencies()
+ val handler = ChannelMessageNoticeSettingHandler(settingsManager, languageManager)
+
+ handler.execute(ctx, true)
+
+ val player = ctx.requirePlayer()
+ verify { player.sendMessage(any<Component>()) }
+ }
+}