Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,12 @@ class AdvancementManager(
loadAdvancements()
}

fun awardAdvancement(player: Player, adv: AdvancementProvider) =
fun awardAdvancement(player: Player, adv: AdvancementProvider) {
if (!enableAdvancements.value()) {
return
}
awardAdvancement(player, plugin.server.getAdvancement(adv.namespacedKey()))
}

fun awardAdvancement(player: Player, adv: SpigotAdvancement?) {
if (adv == null || !enableAdvancements.value()) {
Expand Down
127 changes: 127 additions & 0 deletions src/test/kotlin/xyz/atrius/waystones/event/DestroyEventTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package xyz.atrius.waystones.event

import io.kotest.assertions.nondeterministic.eventually
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import net.kyori.adventure.text.Component
import org.bukkit.Material
import org.bukkit.ExplosionResult
import org.bukkit.entity.TNTPrimed
import org.bukkit.event.block.BlockBreakEvent
import org.bukkit.event.block.BlockExplodeEvent
import org.bukkit.event.entity.EntityExplodeEvent
import org.bukkit.inventory.ItemStack
import xyz.atrius.waystones.repository.WaystoneInfoRepository
import xyz.atrius.waystones.test.ServerFunSpec
import java.util.concurrent.TimeUnit
import kotlin.time.Duration.Companion.seconds

class DestroyEventTest : ServerFunSpec({

test("Breaking a waystone removes it from the database") {
val world = createWorld("world")
val player = createPlayer()
val waystone = placeWaystone(world, 0, 64, 0)

val nameTag = ItemStack(Material.NAME_TAG)
nameTag.editMeta { it.displayName(Component.text("Test Waystone")) }
player.inventory.setItem(0, nameTag)
player.inventory.heldItemSlot = 0
simulateRightClick(player, waystone, nameTag)

val repository = get<WaystoneInfoRepository>()
eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS) shouldNotBe null
}

val breakEvent = BlockBreakEvent(waystone, player)
server.pluginManager.callEvent(breakEvent)

eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS) shouldBe null
}
}

test("Breaking a non-waystone block does not affect the database") {
val world = createWorld("world")
val player = createPlayer()
val stone = placeBlock(world, 0, 64, 0, Material.STONE)

val breakEvent = BlockBreakEvent(stone, player)
server.pluginManager.callEvent(breakEvent)

breakEvent.isCancelled shouldBe false
}

test("Breaking a lodestone without a database entry does not crash") {
val world = createWorld("world")
val player = createPlayer()
val waystone = placeWaystone(world, 0, 64, 0)

val breakEvent = BlockBreakEvent(waystone, player)
server.pluginManager.callEvent(breakEvent)

breakEvent.isCancelled shouldBe false
}

test("Destroying a waystone via block explosion removes it from the database") {
val world = createWorld("world")
val waystone = placeWaystone(world, 0, 64, 0)

val nameTag = ItemStack(Material.NAME_TAG)
nameTag.editMeta { it.displayName(Component.text("Explosive Waystone")) }
val player = createPlayer()
player.inventory.setItem(0, nameTag)
player.inventory.heldItemSlot = 0
simulateRightClick(player, waystone, nameTag)

val repository = get<WaystoneInfoRepository>()
eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS) shouldNotBe null
}

val explodeEvent = BlockExplodeEvent(
waystone,
waystone.state,
mutableListOf(waystone),
4f,
ExplosionResult.DESTROY,
)
server.pluginManager.callEvent(explodeEvent)

eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS) shouldBe null
}
}

test("Destroying a waystone via entity explosion removes it from the database") {
val world = createWorld("world")
val waystone = placeWaystone(world, 0, 64, 0)

val nameTag = ItemStack(Material.NAME_TAG)
nameTag.editMeta { it.displayName(Component.text("TNT Waystone")) }
val player = createPlayer()
player.inventory.setItem(0, nameTag)
player.inventory.heldItemSlot = 0
simulateRightClick(player, waystone, nameTag)

val repository = get<WaystoneInfoRepository>()
eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS) shouldNotBe null
}

val tnt = world.spawn(waystone.location, TNTPrimed::class.java)
val explodeEvent = EntityExplodeEvent(
tnt,
waystone.location,
mutableListOf(waystone),
4f,
ExplosionResult.DESTROY,
)
server.pluginManager.callEvent(explodeEvent)

eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS) shouldBe null
}
}
})
88 changes: 88 additions & 0 deletions src/test/kotlin/xyz/atrius/waystones/event/LinkEventTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package xyz.atrius.waystones.event

import io.kotest.assertions.nondeterministic.eventually
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import org.bukkit.Material
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.CompassMeta
import org.bukkit.persistence.PersistentDataType
import xyz.atrius.waystones.repository.WaystoneInfoRepository
import xyz.atrius.waystones.test.ServerFunSpec
import xyz.atrius.waystones.utility.toKey
import java.util.concurrent.TimeUnit
import kotlin.time.Duration.Companion.seconds

class LinkEventTest : ServerFunSpec({

test("Linking a compass to a waystone creates a database entry") {
val world = createWorld("world")
val player = createPlayer()
val waystone = placeWaystone(world, 100, 64, 200)

val compass = ItemStack(Material.COMPASS)
val meta = compass.itemMeta as CompassMeta
meta.persistentDataContainer.set("is_warp_key".toKey(), PersistentDataType.INTEGER, 1)
compass.itemMeta = meta
player.inventory.setItem(0, compass)
player.inventory.heldItemSlot = 0

simulateRightClick(player, waystone, compass)

val repository = get<WaystoneInfoRepository>()
eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS) shouldNotBe null
}
}

test("Linking a compass to a non-waystone block does nothing") {
val world = createWorld("world")
val player = createPlayer()
val stone = placeBlock(world, 0, 64, 0, Material.STONE)

val compass = ItemStack(Material.COMPASS)
player.inventory.setItem(0, compass)
player.inventory.heldItemSlot = 0

simulateRightClick(player, stone, compass)

val repository = get<WaystoneInfoRepository>()
eventually(1.seconds) {
repository.getWaystone(stone.location).get(5, TimeUnit.SECONDS) shouldBe null
}
}

test("Linking a non-compass item to a waystone does nothing") {
val world = createWorld("world")
val player = createPlayer()
val waystone = placeWaystone(world, 0, 64, 0)

val stick = ItemStack(Material.STICK)
player.inventory.setItem(0, stick)
player.inventory.heldItemSlot = 0

simulateRightClick(player, waystone, stick)

val repository = get<WaystoneInfoRepository>()
eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS) shouldBe null
}
}

test("Linking a compass without warp key marker does nothing") {
val world = createWorld("world")
val player = createPlayer()
val waystone = placeWaystone(world, 0, 64, 0)

val compass = ItemStack(Material.COMPASS)
player.inventory.setItem(0, compass)
player.inventory.heldItemSlot = 0

simulateRightClick(player, waystone, compass)

val repository = get<WaystoneInfoRepository>()
eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS) shouldBe null
}
}
})
132 changes: 132 additions & 0 deletions src/test/kotlin/xyz/atrius/waystones/event/NameEventTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package xyz.atrius.waystones.event

import io.kotest.assertions.nondeterministic.eventually
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import net.kyori.adventure.text.Component
import org.bukkit.Material
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import xyz.atrius.waystones.repository.WaystoneInfoRepository
import xyz.atrius.waystones.test.ServerFunSpec
import java.util.concurrent.TimeUnit
import kotlin.time.Duration.Companion.seconds

class NameEventTest : ServerFunSpec({

test("Naming a waystone with a name tag persists to the database") {
val world = createWorld("world")
val player = createPlayer()
val waystone = placeWaystone(world, 0, 64, 0)

val nameTag = ItemStack(Material.NAME_TAG)
nameTag.editMeta { meta: ItemMeta ->
meta.displayName(Component.text("My Waystone"))
}
player.inventory.setItem(0, nameTag)
player.inventory.heldItemSlot = 0

simulateRightClick(player, waystone, nameTag)

val repository = get<WaystoneInfoRepository>()
eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS)?.name shouldBe "My Waystone"
}
}

test("Renaming a waystone updates the database entry") {
val world = createWorld("world")
val player = createPlayer()
val waystone = placeWaystone(world, 0, 64, 0)

val nameTag1 = ItemStack(Material.NAME_TAG)
nameTag1.editMeta { it.displayName(Component.text("First Name")) }
player.inventory.setItem(0, nameTag1)
player.inventory.heldItemSlot = 0
simulateRightClick(player, waystone, nameTag1)

val nameTag2 = ItemStack(Material.NAME_TAG)
nameTag2.editMeta { it.displayName(Component.text("Second Name")) }
player.inventory.setItem(0, nameTag2)
player.inventory.heldItemSlot = 0
simulateRightClick(player, waystone, nameTag2)

val repository = get<WaystoneInfoRepository>()
eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS)?.name shouldBe "Second Name"
}
}

test("Using a non-name-tag item does not name the waystone") {
val world = createWorld("world")
val player = createPlayer()
val waystone = placeWaystone(world, 0, 64, 0)

val stick = ItemStack(Material.STICK)
player.inventory.setItem(0, stick)
player.inventory.heldItemSlot = 0
simulateRightClick(player, waystone, stick)

val repository = get<WaystoneInfoRepository>()
eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS)?.name shouldBe null
}
}

test("Naming a waystone with a name tag without display name does nothing") {
val world = createWorld("world")
val player = createPlayer()
val waystone = placeWaystone(world, 0, 64, 0)

val nameTag = ItemStack(Material.NAME_TAG)
player.inventory.setItem(0, nameTag)
player.inventory.heldItemSlot = 0
simulateRightClick(player, waystone, nameTag)

val repository = get<WaystoneInfoRepository>()
eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS)?.name shouldBe null
}
}

test("Naming a non-lodestone block does nothing") {
val world = createWorld("world")
val player = createPlayer()
val stone = placeBlock(world, 0, 64, 0, Material.STONE)

val nameTag = ItemStack(Material.NAME_TAG)
nameTag.editMeta { it.displayName(Component.text("My Stone")) }
player.inventory.setItem(0, nameTag)
player.inventory.heldItemSlot = 0
simulateRightClick(player, stone, nameTag)

val repository = get<WaystoneInfoRepository>()
val info = repository.getWaystone(stone.location).get(5, TimeUnit.SECONDS)
info?.name shouldBe null
}

test("Naming a waystone with the same name is ignored") {
val world = createWorld("world")
val player = createPlayer()
val waystone = placeWaystone(world, 0, 64, 0)

val nameTag1 = ItemStack(Material.NAME_TAG)
nameTag1.editMeta { it.displayName(Component.text("Same Name")) }
player.inventory.setItem(0, nameTag1)
player.inventory.heldItemSlot = 0
simulateRightClick(player, waystone, nameTag1)

val repository = get<WaystoneInfoRepository>()
eventually(1.seconds) {
repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS)?.name shouldBe "Same Name"
}

val nameTag2 = ItemStack(Material.NAME_TAG)
nameTag2.editMeta { it.displayName(Component.text("Same Name")) }
player.inventory.setItem(0, nameTag2)
player.inventory.heldItemSlot = 0
simulateRightClick(player, waystone, nameTag2)

repository.getWaystone(waystone.location).get(5, TimeUnit.SECONDS)?.name shouldBe "Same Name"
}
})
12 changes: 10 additions & 2 deletions src/test/kotlin/xyz/atrius/waystones/test/ServerFunSpec.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.bukkit.entity.Player
import org.bukkit.event.block.Action
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.inventory.ItemStack
import org.koin.core.context.stopKoin
import org.mockbukkit.mockbukkit.MockBukkit
import org.mockbukkit.mockbukkit.ServerMock
import xyz.atrius.waystones.Waystones
Expand Down Expand Up @@ -51,14 +52,21 @@ abstract class ServerFunSpec private constructor() : FunSpec() {
extensions(
object : SpecExtension {
override suspend fun intercept(spec: Spec, execute: suspend (Spec) -> Unit) {
_server = MockBukkit.mock()
_plugin = MockBukkit.load(Waystones::class.java)
_server = MockBukkit.mock(TestServerMock())

// Load plugin with custom config
val configStream = javaClass.getResourceAsStream("/test-config.yml")
?: throw IllegalStateException("test-config.yml not found")
_plugin = MockBukkit.loadWithConfig(Waystones::class.java, configStream.use {
org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(java.io.InputStreamReader(it))
})
_koin = _plugin!!.getKoinApp().koin

try {
execute(spec)
} finally {
MockBukkit.unmock()
stopKoin()
}
}
}
Expand Down
Loading
Loading