From 3db623de43b26b346ed1963a4876dc9fada428a2 Mon Sep 17 00:00:00 2001 From: Vincent Date: Sun, 20 Oct 2024 14:58:09 +0100 Subject: [PATCH] test: add test for CommandSenderWrapper --- src/endstone_test/command_executor.py | 64 +++++++++++++++---- src/endstone_test/event_listener.py | 45 +++++++++---- src/endstone_test/plugin.py | 4 +- src/endstone_test/test_helper.py | 9 ++- src/endstone_test/tests/on_load/test_block.py | 4 +- .../tests/on_load/test_plugin.py | 21 ------ .../tests/on_load/test_scoreboard.py | 24 +++++-- .../tests/on_load/test_server.py | 25 ++++++-- .../tests/on_player_join/test_command.py | 8 ++- .../tests/on_player_join/test_player.py | 4 +- .../tests/on_player_join/test_scoreboard.py | 20 ++++-- 11 files changed, 156 insertions(+), 72 deletions(-) diff --git a/src/endstone_test/command_executor.py b/src/endstone_test/command_executor.py index cb4f895..576d45e 100644 --- a/src/endstone_test/command_executor.py +++ b/src/endstone_test/command_executor.py @@ -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" ), @@ -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" ), @@ -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", @@ -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" ), @@ -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": diff --git a/src/endstone_test/event_listener.py b/src/endstone_test/event_listener.py index 27de9b5..572c02b 100644 --- a/src/endstone_test/event_listener.py +++ b/src/endstone_test/event_listener.py @@ -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 @@ -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: @@ -31,7 +30,9 @@ 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) @@ -39,15 +40,20 @@ def on_player_join(self, event: PlayerJoinEvent) -> None: @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 @@ -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): @@ -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): @@ -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): @@ -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 diff --git a/src/endstone_test/plugin.py b/src/endstone_test/plugin.py index 5a6fe24..0914ecd 100644 --- a/src/endstone_test/plugin.py +++ b/src/endstone_test/plugin.py @@ -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}") diff --git a/src/endstone_test/test_helper.py b/src/endstone_test/test_helper.py index e358e34..4fcae13 100644 --- a/src/endstone_test/test_helper.py +++ b/src/endstone_test/test_helper.py @@ -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): @@ -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)], + ) diff --git a/src/endstone_test/tests/on_load/test_block.py b/src/endstone_test/tests/on_load/test_block.py index 222dacd..fe718a0 100644 --- a/src/endstone_test/tests/on_load/test_block.py +++ b/src/endstone_test/tests/on_load/test_block.py @@ -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 diff --git a/src/endstone_test/tests/on_load/test_plugin.py b/src/endstone_test/tests/on_load/test_plugin.py index 0737c1c..8186665 100644 --- a/src/endstone_test/tests/on_load/test_plugin.py +++ b/src/endstone_test/tests/on_load/test_plugin.py @@ -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) diff --git a/src/endstone_test/tests/on_load/test_scoreboard.py b/src/endstone_test/tests/on_load/test_scoreboard.py index d94e4fd..84f9d61 100644 --- a/src/endstone_test/tests/on_load/test_scoreboard.py +++ b/src/endstone_test/tests/on_load/test_scoreboard.py @@ -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 @@ -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 @@ -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 diff --git a/src/endstone_test/tests/on_load/test_server.py b/src/endstone_test/tests/on_load/test_server.py index 043b84a..b2c35b8 100644 --- a/src/endstone_test/tests/on_load/test_server.py +++ b/src/endstone_test/tests/on_load/test_server.py @@ -2,7 +2,7 @@ from pathlib import Path import pytest -from endstone import Server, Translatable, __minecraft_version__ +from endstone import Server, __minecraft_version__ from endstone.plugin import Plugin from endstone.command import CommandSenderWrapper @@ -23,7 +23,9 @@ def test_server_level(server: Server) -> None: def test_dispatch_command(server: Server) -> None: - assert server.dispatch_command(server.command_sender, "scriptevent endstone:test Hello World!") + assert server.dispatch_command( + server.command_sender, "scriptevent endstone:test Hello World!" + ) def test_max_players(server: Server) -> None: @@ -37,11 +39,22 @@ def test_max_players(server: Server) -> None: def test_online_mode(plugin: Plugin, server: Server) -> None: properties_file = Path(plugin.data_folder, "..", "..", "server.properties") - with properties_file.open(mode='r') as file: + with properties_file.open(mode="r") as file: for line in file: - if line.startswith('online-mode='): - value = line.split('=', 1)[1].strip() - assert (value.lower() == 'true') == server.online_mode + if line.startswith("online-mode="): + value = line.split("=", 1)[1].strip() + assert (value.lower() == "true") == server.online_mode return assert False + + +def test_command_wrapper(server: Server): + messages = [] + + def on_message(message): + messages.append(server.language.translate(message, locale="zh_CN")) + + sender = CommandSenderWrapper(server.command_sender, on_message=on_message) + assert server.dispatch_command(sender, "listd") + assert "玩家在线" in "".join(messages) diff --git a/src/endstone_test/tests/on_player_join/test_command.py b/src/endstone_test/tests/on_player_join/test_command.py index 6d98043..e7b4f4e 100644 --- a/src/endstone_test/tests/on_player_join/test_command.py +++ b/src/endstone_test/tests/on_player_join/test_command.py @@ -1,4 +1,3 @@ - from endstone import Player, Server import pytest @@ -7,8 +6,13 @@ def server(player: Player) -> Server: return player.server + def test_run_command(player: Player): assert player.perform_command("test sender") + def test_run_command_as_server(player: Player, server: Server): - server.dispatch_command(server.command_sender, f'execute as "{player.name}" run scriptevent endstone:test Hello World!') + server.dispatch_command( + server.command_sender, + f'execute as "{player.name}" run scriptevent endstone:test Hello World!', + ) diff --git a/src/endstone_test/tests/on_player_join/test_player.py b/src/endstone_test/tests/on_player_join/test_player.py index 928397f..6554241 100644 --- a/src/endstone_test/tests/on_player_join/test_player.py +++ b/src/endstone_test/tests/on_player_join/test_player.py @@ -87,5 +87,7 @@ def test_player_scoreboard(player: Player, server: Server): def test_player_tags(player: Player, server: Server): server.dispatch_command(server.command_sender, f'tag "{player.name}" add test_tag') assert "test_tag" in player.scoreboard_tags - server.dispatch_command(server.command_sender, f'tag "{player.name}" remove test_tag') + server.dispatch_command( + server.command_sender, f'tag "{player.name}" remove test_tag' + ) assert "test_tag" not in player.scoreboard_tags diff --git a/src/endstone_test/tests/on_player_join/test_scoreboard.py b/src/endstone_test/tests/on_player_join/test_scoreboard.py index 8b66476..bb7b396 100644 --- a/src/endstone_test/tests/on_player_join/test_scoreboard.py +++ b/src/endstone_test/tests/on_player_join/test_scoreboard.py @@ -18,7 +18,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 @@ -28,17 +30,25 @@ 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 -def test_scoreboard_value(player: Player, server: Server, scoreboard: Scoreboard) -> None: - server.dispatch_command(server.command_sender, "scoreboard objectives add test_objective dummy") +def test_scoreboard_value( + player: Player, server: Server, scoreboard: Scoreboard +) -> None: + 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, f"scoreboard players set {player.name} test_objective 3") + server.dispatch_command( + server.command_sender, f"scoreboard players set {player.name} test_objective 3" + ) score = objective.get_score(player) assert score.is_score_set assert score.value == 3