lightkeeper-parent 1.2.0-SNAPSHOT API

LightKeeper API

LightKeeper runs integration tests for Minecraft plugins against real Paper and Spigot servers. Tests use a typed Java API to create worlds and synthetic players, interact with plugins, capture events, and assert the resulting server state.

This overview introduces the API entry points and a typical test. For dependencies, server provisioning, and configuration, start with the LightKeeper documentation site. The package and class documentation here describes the API in detail.

Start with LightkeeperAssertions

LightkeeperAssertions is the main entry point for assertions. Statically import its assertThat method to check worlds, players, menus, captured events, and other LightKeeper objects. Follow the returned assertion types to discover the checks and navigation available for each subject.

import static nl.pim16aap2.lightkeeper.framework.assertions.LightkeeperAssertions.assertThat;

The same import also provides ordinary AssertJ assertions for strings, collections, and other Java values. See the assertions package for the full set of supported subjects.

A first test

Once Maven's prepare-server goal has provisioned a runtime and lightkeeper.runtimeManifestPath points to its manifest, LightkeeperExtension manages the server lifecycle and injects ILightkeeperFramework into test methods. The framework groups operations under server(), worlds(), bots(), and events().

import nl.pim16aap2.lightkeeper.framework.BlockPos;
import nl.pim16aap2.lightkeeper.framework.ILightkeeperFramework;
import nl.pim16aap2.lightkeeper.framework.LightkeeperExtension;
import nl.pim16aap2.lightkeeper.framework.WorldHandle;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import static nl.pim16aap2.lightkeeper.framework.assertions.LightkeeperAssertions.assertThat;

@ExtendWith(LightkeeperExtension.class)
class MyPluginIT
{
    @Test
    void world_shouldContainPlacedBlock(ILightkeeperFramework framework)
    {
        // setup
        final WorldHandle world = framework.worlds().main();

        // execute
        world.setBlockAt(new BlockPos(1, 100, 0), "minecraft:stone");

        // verify
        assertThat(world).hasBlockAt(1, 100, 0).ofType("minecraft:stone");
    }
}

Waiting for plugin effects

Assertions are eager and read-only: they check the state observed when called and never wait implicitly. Handles query live server state; snapshots and collection navigation freeze an observation. For asynchronous effects, use LightkeeperAssertions.eventually and recreate the complete assertion chain inside its callback.

For example, given a player created through framework.bots(), if your plugin's myplugin run command sends done after background work completes:

import nl.pim16aap2.lightkeeper.framework.assertions.LightkeeperAssertions;
import java.time.Duration;

import static nl.pim16aap2.lightkeeper.framework.assertions.LightkeeperAssertions.assertThat;

// inside the test: execute the command once, outside the retry callback
player.executeCommand("myplugin run");

// re-read the messages on every attempt, for up to ten seconds
LightkeeperAssertions.eventually(
    Duration.ofSeconds(10),
    () -> assertThat(player)
        .receivedMessages()
        .contains("done")
);

Explore the API

Packages
Package
Description
Public JUnit framework API for creating worlds and synthetic players and asserting game state.
AssertJ assertions for live server/plugin, world/block, entity-query, player, menu, event-capture and error state, plus frozen inventory/item, event/value, result, entity/geometry and semantic chat snapshots.
Agent protocol command types.
Runtime manifest model and cross-process constants used by provisioning, the framework, and the in-server agent.