fixed all unit tests
also added a new one I noticed was missing
This commit is contained in:
parent
3d80540c03
commit
120079ba3d
|
@ -11,7 +11,7 @@ import java.io.File
|
|||
class Kagebot {
|
||||
companion object {
|
||||
fun processMessage(event: MessageCreateEvent) {
|
||||
if (event.messageAuthor.isYourself) {
|
||||
if (event.messageAuthor.isBotUser) {
|
||||
return
|
||||
}
|
||||
for (command in Globals.config.commands) {
|
||||
|
|
|
@ -27,7 +27,7 @@ object Util {
|
|||
|
||||
fun hasOneOf(messageAuthor: MessageAuthor, roles: Set<Role>): Boolean {
|
||||
return messageAuthor.asUser().ifNotEmpty { user ->
|
||||
user.getRoles(server).map { it }.toSet().intersect(roles).isNotEmpty()
|
||||
user.getRoles(server).toSet().intersect(roles).isNotEmpty()
|
||||
} ?: false
|
||||
}
|
||||
|
||||
|
|
|
@ -13,12 +13,13 @@ class Config(rawConfig: RawConfig) {
|
|||
?: throw IllegalArgumentException("No [system] block in config.")
|
||||
var localization: Localization = rawConfig.localization?.let(::Localization)
|
||||
?: throw IllegalArgumentException("No [localization] block in config.")
|
||||
var commands: List<Command> = rawConfig.commands?.map(::Command) ?: emptyList()
|
||||
var features: Features = rawConfig.features?.let(::Features)
|
||||
?: throw IllegalArgumentException("No [feature] block in config.")
|
||||
var commands: List<Command>
|
||||
var features: Features
|
||||
|
||||
init {
|
||||
Globals.server = api.getServerById(system.serverId).orElseThrow()
|
||||
this.commands = rawConfig.commands?.map(::Command) ?: emptyList()
|
||||
this.features = rawConfig.features?.let(::Features) ?: Features.NONE
|
||||
}
|
||||
|
||||
fun reloadLocalization(rawLocalization: RawLocalization) {
|
||||
|
|
|
@ -7,8 +7,13 @@ import moe.kageru.kagebot.config.RawWelcomeFeature
|
|||
import org.javacord.api.entity.channel.TextChannel
|
||||
import org.javacord.api.entity.message.embed.EmbedBuilder
|
||||
|
||||
class Features(rawFeatures: RawFeatures) {
|
||||
val welcome: WelcomeFeature? = rawFeatures.welcome?.let { WelcomeFeature(it) }
|
||||
class Features(val welcome: WelcomeFeature?) {
|
||||
|
||||
constructor(rawFeatures: RawFeatures) : this(rawFeatures.welcome?.let(::WelcomeFeature))
|
||||
|
||||
companion object {
|
||||
val NONE = Features(null)
|
||||
}
|
||||
}
|
||||
|
||||
class WelcomeFeature(rawWelcome: RawWelcomeFeature) {
|
||||
|
|
|
@ -61,6 +61,12 @@ response = "access granted"
|
|||
[command.permissions]
|
||||
hasNoneOf = ["452034011393425409"]
|
||||
|
||||
[[command]]
|
||||
trigger = "!private"
|
||||
response = "some long response that you don’t want in public channels"
|
||||
[command.permissions]
|
||||
onlyDM = true
|
||||
|
||||
# redirect every message that starts with !redirect to channel 555097559023222825
|
||||
[[command]]
|
||||
trigger = "!redirect"
|
||||
|
|
|
@ -1,92 +1,207 @@
|
|||
package moe.kageru.kagebot
|
||||
|
||||
import io.kotlintest.matchers.string.shouldContain
|
||||
import io.kotlintest.matchers.string.shouldNotContain
|
||||
import io.kotlintest.shouldBe
|
||||
import io.kotlintest.specs.StringSpec
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import moe.kageru.kagebot.Globals.config
|
||||
import moe.kageru.kagebot.TestUtil.embedToString
|
||||
import moe.kageru.kagebot.TestUtil.messageableAuthor
|
||||
import moe.kageru.kagebot.TestUtil.mockMessage
|
||||
import moe.kageru.kagebot.TestUtil.testMessageSuccess
|
||||
import moe.kageru.kagebot.TestUtil.withConfig
|
||||
import org.javacord.api.entity.message.embed.EmbedBuilder
|
||||
import java.util.*
|
||||
|
||||
class CommandTest : StringSpec({
|
||||
TestUtil.prepareServerConfig()
|
||||
TestUtil.prepareTestEnvironment()
|
||||
"should match prefix command" {
|
||||
testMessageSuccess("!ping", "pong")
|
||||
withConfig(
|
||||
"""
|
||||
[[command]]
|
||||
trigger = "!ping"
|
||||
response = "pong"
|
||||
""".trimIndent()
|
||||
) {
|
||||
testMessageSuccess("!ping", "pong")
|
||||
}
|
||||
}
|
||||
"should match contains command" {
|
||||
testMessageSuccess("the trigger is somewhere in this message", "found it")
|
||||
withConfig(
|
||||
"""
|
||||
[[command]]
|
||||
trigger = "somewhere"
|
||||
response = "found it"
|
||||
matchType = "CONTAINS"
|
||||
""".trimIndent()
|
||||
) {
|
||||
testMessageSuccess("the trigger is somewhere in this message", "found it")
|
||||
}
|
||||
}
|
||||
"should match regex command" {
|
||||
testMessageSuccess("AcsdB", "regex matched")
|
||||
withConfig(
|
||||
"""
|
||||
[[command]]
|
||||
trigger = "A.+B"
|
||||
response = "regex matched"
|
||||
matchType = "REGEX"
|
||||
""".trimIndent()
|
||||
) {
|
||||
testMessageSuccess("AcsdB", "regex matched")
|
||||
}
|
||||
}
|
||||
"should ping author" {
|
||||
testMessageSuccess("answer me", "<@1> there you go")
|
||||
withConfig(
|
||||
"""
|
||||
[[command]]
|
||||
trigger = "answer me"
|
||||
response = "@@ there you go"
|
||||
""".trimIndent()
|
||||
) {
|
||||
testMessageSuccess("answer me", "<@1> there you go")
|
||||
}
|
||||
}
|
||||
"should not react to own message" {
|
||||
val calls = mutableListOf<String>()
|
||||
Kagebot.processMessage(mockMessage("!ping", replies = calls, isSelf = true))
|
||||
calls shouldBe mutableListOf()
|
||||
withConfig(
|
||||
"""
|
||||
[[command]]
|
||||
trigger = "!ping"
|
||||
response = "pong"
|
||||
""".trimIndent()
|
||||
) {
|
||||
val calls = mutableListOf<String>()
|
||||
Kagebot.processMessage(mockMessage("!ping", replies = calls, isBot = true))
|
||||
calls shouldBe mutableListOf()
|
||||
}
|
||||
}
|
||||
"should delete messages and send copy to author" {
|
||||
val replies = mutableListOf<EmbedBuilder>()
|
||||
val messageContent = "delet this"
|
||||
val mockMessage = mockMessage(messageContent)
|
||||
every { mockMessage.deleteMessage() } returns mockk()
|
||||
every { mockMessage.messageAuthor.asUser() } returns messageableAuthor(replies)
|
||||
Kagebot.processMessage(mockMessage)
|
||||
verify(exactly = 1) { mockMessage.deleteMessage() }
|
||||
replies.size shouldBe 1
|
||||
embedToString(replies[0]) shouldContain messageContent
|
||||
withConfig(
|
||||
"""
|
||||
[[command]]
|
||||
trigger = "delet this"
|
||||
[command.action]
|
||||
delete = true
|
||||
""".trimIndent()
|
||||
) {
|
||||
val replies = mutableListOf<EmbedBuilder>()
|
||||
val messageContent = "delet this"
|
||||
val mockMessage = mockMessage(messageContent)
|
||||
every { mockMessage.deleteMessage() } returns mockk()
|
||||
every { mockMessage.messageAuthor.asUser() } returns Optional.of(messageableAuthor(replies))
|
||||
Kagebot.processMessage(mockMessage)
|
||||
verify(exactly = 1) { mockMessage.deleteMessage() }
|
||||
replies.size shouldBe 1
|
||||
embedToString(replies[0]) shouldContain messageContent
|
||||
}
|
||||
}
|
||||
"should refuse command without permissions" {
|
||||
val replies = mutableListOf<String>()
|
||||
val mockMessage = mockMessage("!restricted", replies = replies)
|
||||
every { mockMessage.messageAuthor.asUser() } returns messageableAuthor()
|
||||
Kagebot.processMessage(mockMessage)
|
||||
replies shouldBe mutableListOf(config.localization.permissionDenied)
|
||||
withConfig(
|
||||
"""
|
||||
[[command]]
|
||||
trigger = "!restricted"
|
||||
response = "access granted"
|
||||
[command.permissions]
|
||||
hasOneOf = [
|
||||
"testrole",
|
||||
]
|
||||
""".trimIndent()
|
||||
) {
|
||||
val replies = mutableListOf<String>()
|
||||
val mockMessage = mockMessage("!restricted", replies = replies)
|
||||
every { mockMessage.messageAuthor.asUser() } returns Optional.of(messageableAuthor())
|
||||
Kagebot.processMessage(mockMessage)
|
||||
replies shouldBe mutableListOf(config.localization.permissionDenied)
|
||||
}
|
||||
}
|
||||
"should accept restricted command for owner" {
|
||||
val calls = mutableListOf<String>()
|
||||
val mockMessage = mockMessage("!restricted", replies = calls)
|
||||
every { mockMessage.messageAuthor.isBotOwner } returns true
|
||||
Kagebot.processMessage(mockMessage)
|
||||
calls shouldBe mutableListOf("access granted")
|
||||
withConfig(
|
||||
"""
|
||||
[[command]]
|
||||
trigger = "!restricted"
|
||||
response = "access granted"
|
||||
[command.permissions]
|
||||
hasOneOf = [
|
||||
"testrole"
|
||||
]
|
||||
""".trimIndent()
|
||||
) {
|
||||
val calls = mutableListOf<String>()
|
||||
val mockMessage = mockMessage("!restricted", replies = calls)
|
||||
every { mockMessage.messageAuthor.isBotOwner } returns true
|
||||
Kagebot.processMessage(mockMessage)
|
||||
calls shouldBe mutableListOf("access granted")
|
||||
}
|
||||
}
|
||||
"should accept restricted command with permissions" {
|
||||
val calls = mutableListOf<String>()
|
||||
val mockMessage = mockMessage("!restricted", replies = calls)
|
||||
every { mockMessage.messageAuthor.asUser() } returns mockk {
|
||||
every { isPresent } returns true
|
||||
every { get().getRoles(any()) } returns listOf(
|
||||
mockk { every { id } returns 452034011393425409 }
|
||||
)
|
||||
withConfig(
|
||||
"""
|
||||
[[command]]
|
||||
trigger = "!restricted"
|
||||
response = "access granted"
|
||||
[command.permissions]
|
||||
hasOneOf = [
|
||||
"testrole"
|
||||
]
|
||||
""".trimIndent()
|
||||
) {
|
||||
val calls = mutableListOf<String>()
|
||||
val mockMessage = mockMessage("!restricted", replies = calls)
|
||||
every { mockMessage.messageAuthor.asUser() } returns Optional.of(mockk {
|
||||
every { getRoles(any()) } returns listOf(
|
||||
Globals.server.getRolesByNameIgnoreCase("testrole")[0]
|
||||
)
|
||||
})
|
||||
Kagebot.processMessage(mockMessage)
|
||||
calls shouldBe mutableListOf("access granted")
|
||||
}
|
||||
Kagebot.processMessage(mockMessage)
|
||||
calls shouldBe mutableListOf("access granted")
|
||||
}
|
||||
"should deny command to excluded roles" {
|
||||
val calls = mutableListOf<String>()
|
||||
val mockMessage = mockMessage("!almostUnrestricted", replies = calls)
|
||||
// with the banned role
|
||||
every { mockMessage.messageAuthor.asUser() } returns mockk {
|
||||
every { isPresent } returns true
|
||||
every { get().getRoles(any()) } returns listOf(
|
||||
mockk { every { id } returns 452034011393425409 }
|
||||
)
|
||||
}
|
||||
Kagebot.processMessage(mockMessage)
|
||||
withConfig(
|
||||
"""
|
||||
[[command]]
|
||||
trigger = "!almostUnrestricted"
|
||||
response = "access granted"
|
||||
[command.permissions]
|
||||
hasNoneOf = ["testrole"]
|
||||
""".trimIndent()
|
||||
) {
|
||||
val calls = mutableListOf<String>()
|
||||
val mockMessage = mockMessage("!almostUnrestricted", replies = calls)
|
||||
// with the banned role
|
||||
every { mockMessage.messageAuthor.asUser() } returns mockk {
|
||||
every { isPresent } returns true
|
||||
every { get().getRoles(any()) } returns listOf(
|
||||
Globals.server.getRolesByNameIgnoreCase("testrole")[0]
|
||||
)
|
||||
}
|
||||
Kagebot.processMessage(mockMessage)
|
||||
|
||||
// without the role
|
||||
every { mockMessage.messageAuthor.asUser() } returns mockk {
|
||||
every { isPresent } returns true
|
||||
every { get().getRoles(any()) } returns emptyList()
|
||||
// without the role
|
||||
every { mockMessage.messageAuthor.asUser() } returns mockk {
|
||||
every { isPresent } returns true
|
||||
every { get().getRoles(any()) } returns emptyList()
|
||||
}
|
||||
Kagebot.processMessage(mockMessage)
|
||||
calls shouldBe mutableListOf(config.localization.permissionDenied, "access granted")
|
||||
}
|
||||
}
|
||||
"should refuse DM only message in server channel" {
|
||||
withConfig(
|
||||
"""
|
||||
[[command]]
|
||||
trigger = "!dm"
|
||||
response = "access granted"
|
||||
[command.permissions]
|
||||
onlyDM = true
|
||||
""".trimIndent()
|
||||
) {
|
||||
val calls = mutableListOf<String>()
|
||||
Kagebot.processMessage(mockMessage("!dm", replies = calls))
|
||||
calls shouldBe listOf(config.localization.permissionDenied)
|
||||
}
|
||||
Kagebot.processMessage(mockMessage)
|
||||
calls shouldBe mutableListOf(config.localization.permissionDenied, "access granted")
|
||||
}
|
||||
/*
|
||||
* This implicitly tests that the message author is not included in anonymous complaints
|
||||
|
@ -94,10 +209,21 @@ class CommandTest : StringSpec({
|
|||
*/
|
||||
"should redirect" {
|
||||
val calls = mutableListOf<EmbedBuilder>()
|
||||
TestUtil.prepareServerConfig(calls)
|
||||
val message = "this is a message"
|
||||
Kagebot.processMessage(mockMessage("!anonRedirect $message"))
|
||||
calls.size shouldBe 1
|
||||
embedToString(calls[0]) shouldContain "\"$message\""
|
||||
TestUtil.prepareTestEnvironment(calls)
|
||||
withConfig(
|
||||
"""
|
||||
[[command]]
|
||||
trigger = "!redirect"
|
||||
response = "redirected"
|
||||
[command.action.redirect]
|
||||
target = "testchannel"
|
||||
anonymous = true
|
||||
""".trimIndent()
|
||||
) {
|
||||
val message = "this is a message"
|
||||
Kagebot.processMessage(mockMessage("!redirect $message", replyEmbeds = calls))
|
||||
calls.size shouldBe 1
|
||||
embedToString(calls[0]) shouldContain "\"$message\""
|
||||
}
|
||||
}
|
||||
})
|
|
@ -1,17 +1,13 @@
|
|||
package moe.kageru.kagebot
|
||||
|
||||
import io.kotlintest.shouldBe
|
||||
import io.kotlintest.shouldNotBe
|
||||
import io.kotlintest.specs.StringSpec
|
||||
import moe.kageru.kagebot.config.RawConfig
|
||||
|
||||
class ConfigTest : StringSpec({
|
||||
/*
|
||||
"should properly parse default config" {
|
||||
Config.config shouldNotBe null
|
||||
Config.config.commands shouldNotBe null
|
||||
}
|
||||
*/
|
||||
"should convert to raw config" {
|
||||
RawConfig.config shouldNotBe null
|
||||
TestUtil.prepareTestEnvironment()
|
||||
"should properly parse test config" {
|
||||
Globals.config shouldNotBe null
|
||||
Globals.config.commands shouldBe emptyList()
|
||||
}
|
||||
})
|
|
@ -31,7 +31,7 @@ class FeatureTest : StringSpec({
|
|||
"should send welcome fallback if DMs are disabled" {
|
||||
val dm = slot<String>()
|
||||
val sentMessages = mutableListOf<EmbedBuilder>()
|
||||
TestUtil.prepareServerConfig(sentMessages)
|
||||
TestUtil.prepareTestEnvironment(sentMessages)
|
||||
Kagebot.welcomeUser(
|
||||
mockk {
|
||||
every { user } returns mockk {
|
||||
|
|
|
@ -5,9 +5,11 @@ import io.mockk.Runs
|
|||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import moe.kageru.kagebot.config.Config
|
||||
import moe.kageru.kagebot.config.RawConfig
|
||||
import org.javacord.api.DiscordApi
|
||||
import org.javacord.api.entity.channel.ServerTextChannel
|
||||
import org.javacord.api.entity.message.embed.EmbedBuilder
|
||||
import org.javacord.api.entity.server.Server
|
||||
import org.javacord.api.entity.user.User
|
||||
import org.javacord.api.event.message.MessageCreateEvent
|
||||
import org.javacord.core.entity.message.embed.EmbedBuilderDelegateImpl
|
||||
|
@ -18,40 +20,51 @@ object TestUtil {
|
|||
content: String,
|
||||
author: Long = 1,
|
||||
replies: MutableList<String> = mutableListOf(),
|
||||
isSelf: Boolean = false
|
||||
replyEmbeds: MutableList<EmbedBuilder> = mutableListOf(),
|
||||
isBot: Boolean = false
|
||||
): MessageCreateEvent {
|
||||
val message = mockk<MessageCreateEvent>()
|
||||
every { message.messageContent } returns content
|
||||
every { message.readableMessageContent } returns content
|
||||
every { message.messageAuthor.id } returns author
|
||||
every { message.channel.sendMessage(capture(replies)) } returns mockk()
|
||||
every { message.messageAuthor.isYourself } returns isSelf
|
||||
every { message.message.canYouDelete() } returns true
|
||||
every { message.messageAuthor.isBotOwner } returns false
|
||||
return message
|
||||
return mockk {
|
||||
every { messageContent } returns content
|
||||
every { readableMessageContent } returns content
|
||||
every { messageAuthor.id } returns author
|
||||
every { channel.sendMessage(capture(replies)) } returns mockk()
|
||||
every { channel.sendMessage(capture(replyEmbeds)) } returns mockk()
|
||||
every { messageAuthor.isBotUser } returns isBot
|
||||
every { message.canYouDelete() } returns true
|
||||
every { messageAuthor.isBotOwner } returns false
|
||||
every { isPrivateMessage } returns false
|
||||
}
|
||||
}
|
||||
|
||||
fun messageableAuthor(messages: MutableList<EmbedBuilder> = mutableListOf()): Optional<User> {
|
||||
fun messageableAuthor(messages: MutableList<EmbedBuilder> = mutableListOf()): User {
|
||||
return mockk {
|
||||
every { getRoles(any()) } returns emptyList()
|
||||
every { sendMessage(capture(messages)) } returns mockk()
|
||||
}
|
||||
}
|
||||
|
||||
fun prepareTestEnvironment(sentMessages: MutableList<EmbedBuilder> = mutableListOf()) {
|
||||
val channel = mockk<Optional<ServerTextChannel>> {
|
||||
every { isPresent } returns true
|
||||
every { get() } returns mockk {
|
||||
every { getRoles(any()) } returns emptyList()
|
||||
every { sendMessage(capture(messages)) } returns mockk()
|
||||
every { sendMessage(capture(sentMessages)) } returns mockk {
|
||||
every { join() } returns mockk()
|
||||
every { isCompletedExceptionally } returns false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun prepareServerConfig(sentMessages: MutableList<EmbedBuilder> = mutableListOf()) {
|
||||
val channelMock = mockk<ServerTextChannel> {
|
||||
every { sendMessage(capture(sentMessages)) } returns mockk()
|
||||
val api = mockk<DiscordApi> {
|
||||
every { getServerById(any<String>()) } returns Optional.of(mockk {
|
||||
every { icon.ifPresent(any()) } just Runs
|
||||
every { getTextChannelById(any<String>()) } returns channel
|
||||
every { getTextChannelsByName(any()) } returns listOf(channel.get())
|
||||
every { getRolesByNameIgnoreCase("testrole") } returns listOf(mockk {
|
||||
every { id } returns 1
|
||||
})
|
||||
})
|
||||
}
|
||||
val resultMock = mockk<Optional<ServerTextChannel>>()
|
||||
every { resultMock.isPresent } returns true
|
||||
every { resultMock.get() } returns channelMock
|
||||
val server = mockk<Server>()
|
||||
every { server.icon.ifPresent(any()) } just Runs
|
||||
every { server.getTextChannelById(any<Long>()) } returns resultMock
|
||||
//Config.server = server
|
||||
Globals.api = api
|
||||
Globals.config = Config(RawConfig.read("testconfig.toml"))
|
||||
}
|
||||
|
||||
fun testMessageSuccess(content: String, result: String) {
|
||||
|
@ -63,4 +76,10 @@ object TestUtil {
|
|||
fun embedToString(embed: EmbedBuilder): String {
|
||||
return (embed.delegate as EmbedBuilderDelegateImpl).toJsonNode().toString()
|
||||
}
|
||||
|
||||
fun <R> withConfig(config: String, test: (() -> R)) {
|
||||
val rawConfig = RawConfig.readFromString(config)
|
||||
Globals.config.reloadCommands(rawConfig)
|
||||
test()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
[system]
|
||||
serverId = "356414885292277771"
|
||||
color = "#1793d0"
|
||||
|
||||
[localization]
|
||||
permissionDenied = "no permissions"
|
||||
redirectedMessage = "says"
|
||||
messageDeleted = "message dongered"
|
Loading…
Reference in New Issue
Block a user