Skip to content

Commit

Permalink
test: add test for CommandSenderWrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
wu-vincent committed Oct 20, 2024
1 parent 3661f3e commit 3db623d
Show file tree
Hide file tree
Showing 11 changed files with 156 additions and 72 deletions.
64 changes: 50 additions & 14 deletions src/endstone_test/command_executor.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,42 @@
import json

from endstone import ColorFormat, Player
from endstone import Translatable as tr
from endstone.command import Command, CommandExecutor, CommandSender, ConsoleCommandSender
from endstone.lang import Translatable as tr
from endstone.command import (
Command,
CommandExecutor,
CommandSender,
ConsoleCommandSender,
)
from endstone.form import *


class TestCommandExecutor(CommandExecutor):
__test__ = False

def on_command(self, sender: CommandSender, command: Command, args: list[str]) -> bool:
def on_command(
self, sender: CommandSender, command: Command, args: list[str]
) -> bool:
match args:
case ["form", ("message" | "action" | "modal") as form_type]:
if not isinstance(sender, Player):
sender.send_error_message("You must execute this command as a player")
sender.send_error_message(
"You must execute this command as a player"
)
return False

if form_type == "message":
sender.send_form(
MessageForm(
title=tr("permissions.removeplayer"),
content=tr("accessibility.list.or.two", ["Player 1", "Player 2"]),
content=tr(
"accessibility.list.or.two", ["Player 1", "Player 2"]
),
button1="Yes",
button2="No",
on_submit=lambda player, selection: player.send_message(f"You've selected #{selection}"),
on_submit=lambda player, selection: player.send_message(
f"You've selected #{selection}"
),
on_close=lambda player: player.send_message(
f"You just closed a {ColorFormat.GREEN}message form"
),
Expand All @@ -33,13 +46,20 @@ def on_command(self, sender: CommandSender, command: Command, args: list[str]) -
sender.send_form(
ActionForm(
title=tr("permissions.removeplayer"),
content=tr("accessibility.list.or.two", ["Player 1", "Player 2"]),
content=tr(
"accessibility.list.or.two", ["Player 1", "Player 2"]
),
buttons=[
ActionForm.Button("Endstone", icon="https://avatars.githubusercontent.com/u/142812342"),
ActionForm.Button(
"Endstone",
icon="https://avatars.githubusercontent.com/u/142812342",
),
ActionForm.Button("Instagram"),
ActionForm.Button("Twitter"),
],
on_submit=lambda player, selection: player.send_message(f"You've selected #{selection}"),
on_submit=lambda player, selection: player.send_message(
f"You've selected #{selection}"
),
on_close=lambda player: player.send_message(
f"You just closed an {ColorFormat.GREEN}action form"
),
Expand All @@ -50,10 +70,22 @@ def on_command(self, sender: CommandSender, command: Command, args: list[str]) -
ModalForm(
title=tr("permissions.removeplayer"),
controls=[
Dropdown(label="This is a dropdown", options=["Apple", "Orange", "Banana"]),
Dropdown(
label="This is a dropdown",
options=["Apple", "Orange", "Banana"],
),
Label(text="This is a label"),
Slider(label="This is a slider", min=0, max=5, step=1, default_value=2),
StepSlider(label="This is a step slider", options=["Mild", "Hot", "Extra hot"]),
Slider(
label="This is a slider",
min=0,
max=5,
step=1,
default_value=2,
),
StepSlider(
label="This is a step slider",
options=["Mild", "Hot", "Extra hot"],
),
TextInput(
label="This is a text input",
placeholder="This is the placehoder",
Expand All @@ -63,7 +95,9 @@ def on_command(self, sender: CommandSender, command: Command, args: list[str]) -
],
submit_button="Let's GO",
icon="https://avatars.githubusercontent.com/u/142812342",
on_submit=lambda player, data: player.send_message(f"Response {json.loads(data)}"),
on_submit=lambda player, data: player.send_message(
f"Response {json.loads(data)}"
),
on_close=lambda player: player.send_message(
f"You just closed a {ColorFormat.GREEN}modal form"
),
Expand All @@ -83,7 +117,9 @@ def on_command(self, sender: CommandSender, command: Command, args: list[str]) -

case ["player", ("toast" | "title" | "kick") as test_type]:
if not isinstance(sender, Player):
sender.send_error_message("You must execute this command as a player")
sender.send_error_message(
"You must execute this command as a player"
)
return False

if test_type == "toast":
Expand Down
45 changes: 32 additions & 13 deletions src/endstone_test/event_listener.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import datetime

from babel import Locale
from endstone import ColorFormat, Server, Translatable
from endstone import ColorFormat, Server
from endstone.event import *
from endstone.plugin import Plugin
from endstone_test.test_helper import run_tests
Expand All @@ -13,7 +10,9 @@ def __init__(self, plugin: Plugin):

@event_handler
def on_player_login(self, event: PlayerLoginEvent) -> None:
self.server.broadcast_message(ColorFormat.YELLOW + f"{event.player.name} logged in.")
self.server.broadcast_message(
ColorFormat.YELLOW + f"{event.player.name} logged in."
)

@event_handler
def on_player_join(self, event: PlayerJoinEvent) -> None:
Expand All @@ -31,23 +30,30 @@ def on_player_join(self, event: PlayerJoinEvent) -> None:
self._plugin.logger.info(f"Op status: {event.player.is_op}")
self._plugin.logger.info(f"Ping: {event.player.ping}ms")
self._plugin.logger.info(f"Locale: {event.player.locale}")
self._plugin.logger.info(f"Device: {event.player.device_os} {event.player.device_id}")
self._plugin.logger.info(
f"Device: {event.player.device_os} {event.player.device_id}"
)
self._plugin.logger.info("===========================")

run_tests("on_player_join", player=event.player, plugin=self._plugin)

@event_handler
def on_player_interact(self, event: PlayerInteractEvent):
self._plugin.logger.info(
f"{event.player.name} interacts with {event.block} (face={event.block_face}) using {event.item} item")
f"{event.player.name} interacts with {event.block} (face={event.block_face}) using {event.item} item"
)

@event_handler
def on_player_interact_actor(self, event: PlayerInteractActorEvent):
self._plugin.logger.info(f"{event.player.name} interacts with actor {event.actor.name}")
self._plugin.logger.info(
f"{event.player.name} interacts with actor {event.actor.name}"
)

@event_handler
def on_player_kick(self, event: PlayerKickEvent) -> None:
self._plugin.logger.info(f"{event.player.name} has been kicked due to {event.reason}")
self._plugin.logger.info(
f"{event.player.name} has been kicked due to {event.reason}"
)
event.reason = ColorFormat.BOLD + event.reason

@event_handler
Expand All @@ -56,7 +62,9 @@ def on_player_quit(self, event: PlayerQuitEvent) -> None:

@event_handler
def on_player_teleport(self, event: PlayerTeleportEvent):
self._plugin.logger.info(f"{event.player.name} teleported from {event.from_location} to {event.to_location}")
self._plugin.logger.info(
f"{event.player.name} teleported from {event.from_location} to {event.to_location}"
)

@event_handler
def on_player_death(self, event: PlayerDeathEvent):
Expand All @@ -80,7 +88,9 @@ def on_actor_spawned(self, event: ActorSpawnEvent):

@event_handler
def on_actor_teleport(self, event: ActorTeleportEvent):
self._plugin.logger.info(f"{event.actor.name} teleported from {event.from_location} to {event.to_location}")
self._plugin.logger.info(
f"{event.actor.name} teleported from {event.from_location} to {event.to_location}"
)

@event_handler
def on_block_break(self, event: BlockBreakEvent):
Expand All @@ -89,7 +99,8 @@ def on_block_break(self, event: BlockBreakEvent):
@event_handler
def on_block_placed(self, event: BlockPlaceEvent):
self._plugin.logger.info(
f"{event.player.name} places a {event.block_placed_state} against {event.block_against} (was {event.block})")
f"{event.player.name} places a {event.block_placed_state} against {event.block_against} (was {event.block})"
)

@event_handler
def on_thunder_change(self, event: ThunderChangeEvent):
Expand All @@ -101,13 +112,21 @@ def on_weather_change(self, event: WeatherChangeEvent):

@event_handler
def on_server_command(self, event: ServerCommandEvent):
self._plugin.logger.info(f"{event.sender.name} executed command: {event.command}")
self._plugin.logger.info(
f"{event.sender.name} executed command: {event.command}"
)

@event_handler
def on_server_list_ping(self, event: ServerListPingEvent):
event.motd = ColorFormat.BOLD + event.motd
event.level_name = ColorFormat.GREEN + "Endstone Test" + ColorFormat.RESET

@event_handler
def on_script_message(self, event: ScriptMessageEvent):
self._plugin.logger.info(
f"Script message received from {event.sender}: message_id={event.message_id}, message={event.message}"
)

@property
def server(self) -> Server:
return self._plugin.server
4 changes: 3 additions & 1 deletion src/endstone_test/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,7 @@ def on_disable(self) -> None:
self.logger.info("on_disable is called!")

def run_tests(self) -> None:
ret_code = pytest.main(["-s", "--pyargs", "endstone_test.tests"], plugins=[FixtureInjection(self)])
ret_code = pytest.main(
["-s", "--pyargs", "endstone_test.tests"], plugins=[FixtureInjection(self)]
)
self.logger.info(f"Testing finished with exit code {ret_code}")
9 changes: 7 additions & 2 deletions src/endstone_test/test_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
class FixtureInjection:
def __init__(self, **kwargs):
for name, obj in kwargs.items():
setattr(self, name, pytest.fixture(scope='session')(self._create_fixture(obj)))
setattr(
self, name, pytest.fixture(scope="session")(self._create_fixture(obj))
)

@staticmethod
def _create_fixture(obj):
Expand All @@ -16,4 +18,7 @@ def fixture_func():


def run_tests(name: str, **kwargs) -> int | ExitCode:
return pytest.main(["-s", "--pyargs", f"endstone_test.tests.{name}"], plugins=[FixtureInjection(**kwargs)])
return pytest.main(
["-s", "--pyargs", f"endstone_test.tests.{name}"],
plugins=[FixtureInjection(**kwargs)],
)
4 changes: 3 additions & 1 deletion src/endstone_test/tests/on_load/test_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ def test_create_block_data_default_block_states(server: Server) -> None:


def test_create_block_data_custom_block_states(server: Server) -> None:
block_data = server.create_block_data("minecraft:standing_sign", {"ground_sign_direction": 8})
block_data = server.create_block_data(
"minecraft:standing_sign", {"ground_sign_direction": 8}
)
assert block_data.type == "minecraft:standing_sign"
assert "ground_sign_direction" in block_data.block_states
assert block_data.block_states["ground_sign_direction"] == 8
Expand Down
21 changes: 0 additions & 21 deletions src/endstone_test/tests/on_load/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,3 @@
def test_instance(plugin: Plugin):
assert plugin is not None
assert isinstance(plugin, EndstoneTest)


def test_schedule_task(plugin: Plugin) -> None:
# case study: https://github.com/EndstoneMC/endstone/issues/31
server = plugin.server
assert server.dispatch_command(server.command_sender, "save hold")

# since /save hold takes time to save, we run /save query in a delayed task to avoid blocking the thread
def save_query():
messages = []
sender = CommandSenderWrapper(server.command_sender,
on_message=lambda msg: messages.extend([msg.translate, *msg.with_]))
ready = server.dispatch_command(sender, "save query")
if not ready:
server.scheduler.run_task(plugin, save_query, delay=5)
return

assert 'commands.save-all.success' in messages
assert server.dispatch_command(server.command_sender, "save resume")

server.scheduler.run_task(plugin, save_query, delay=5)
24 changes: 18 additions & 6 deletions src/endstone_test/tests/on_load/test_scoreboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ def before_each_after_each(server: Server, scoreboard: Scoreboard):
# Before each test run
objective = scoreboard.get_objective("test_objective")
if objective is not None:
server.dispatch_command(server.command_sender, "scoreboard objectives remove test_objective")
server.dispatch_command(
server.command_sender, "scoreboard objectives remove test_objective"
)

objective = scoreboard.get_objective("test_objective")
assert objective is None
Expand All @@ -29,7 +31,9 @@ def before_each_after_each(server: Server, scoreboard: Scoreboard):
# After each test run
objective = scoreboard.get_objective("test_objective")
if objective is not None:
server.dispatch_command(server.command_sender, "scoreboard objectives remove test_objective")
server.dispatch_command(
server.command_sender, "scoreboard objectives remove test_objective"
)
objective = scoreboard.get_objective("test_objective")
assert objective is None

Expand All @@ -46,25 +50,33 @@ def test_add_objective(server: Server, scoreboard: Scoreboard) -> None:


def test_remove_objective(server: Server, scoreboard: Scoreboard) -> None:
server.dispatch_command(server.command_sender, "scoreboard objectives add test_objective dummy")
server.dispatch_command(
server.command_sender, "scoreboard objectives add test_objective dummy"
)
objective = scoreboard.get_objective("test_objective")
assert objective is not None
objective.unregister()


def test_list_objectives(server: Server, scoreboard: Scoreboard) -> None:
server.dispatch_command(server.command_sender, "scoreboard objectives add test_objective dummy")
server.dispatch_command(
server.command_sender, "scoreboard objectives add test_objective dummy"
)
objective = scoreboard.get_objective("test_objective")
assert objective is not None
assert objective in scoreboard.objectives


def test_scoreboard_value(server: Server, scoreboard: Scoreboard) -> None:
server.dispatch_command(server.command_sender, "scoreboard objectives add test_objective dummy")
server.dispatch_command(
server.command_sender, "scoreboard objectives add test_objective dummy"
)
objective = scoreboard.get_objective("test_objective")
assert objective is not None

server.dispatch_command(server.command_sender, "scoreboard players set test_player test_objective 3")
server.dispatch_command(
server.command_sender, "scoreboard players set test_player test_objective 3"
)
score = objective.get_score("test_player")
assert score.is_score_set
assert score.value == 3
Expand Down
Loading

0 comments on commit 3db623d

Please sign in to comment.