diff --git a/src/mudlib/if_session.py b/src/mudlib/if_session.py index aa06aa6..5c95a90 100644 --- a/src/mudlib/if_session.py +++ b/src/mudlib/if_session.py @@ -63,9 +63,14 @@ class IFSession: if text.lower() == "::help": help_text = """escape commands: ::quit - exit the game +::save - save game progress ::help - show this help""" return IFResponse(output=help_text, done=False) + if text.lower() == "::save": + confirmation = await self._do_save() + return IFResponse(output=confirmation, done=False) + # Regular game input - send to dfrotz if self.process and self.process.stdin: stripped = text.strip() diff --git a/tests/test_if_session.py b/tests/test_if_session.py index 2ff7c37..956d0f2 100644 --- a/tests/test_if_session.py +++ b/tests/test_if_session.py @@ -479,3 +479,41 @@ async def test_do_restore_sends_restore_command(tmp_path): # Result should contain game text assert "West of House" in result assert "open field" in result + + +@pytest.mark.asyncio +async def test_handle_input_save_triggers_save(tmp_path): + """handle_input('::save') triggers save and returns confirmation.""" + player = MagicMock() + player.name = "tester" + session = IFSession(player, "/path/to/zork.z5", "zork") + session._data_dir = tmp_path + + # Mock process + mock_process = MagicMock() + mock_process.stdin = MagicMock() + mock_process.stdin.write = MagicMock() + mock_process.stdin.drain = AsyncMock() + mock_process.stdout = AsyncMock() + session.process = mock_process + + # Simulate dfrotz save responses + responses = [b"Enter saved game: \n>", b"Ok.\n>"] + response_data = b"".join(responses) + + async def read_side_effect(n): + nonlocal response_data + if response_data: + byte = response_data[:1] + response_data = response_data[1:] + return byte + return b"" + + mock_process.stdout.read = AsyncMock(side_effect=read_side_effect) + + response = await session.handle_input("::save") + + assert response.done is False + assert "Ok" in response.output or "ok" in response.output.lower() + # Verify save command was sent + assert mock_process.stdin.write.call_args_list[0][0][0] == b"save\n"