diff --git a/tests/test_if_session.py b/tests/test_if_session.py index c14a6b1..a105c65 100644 --- a/tests/test_if_session.py +++ b/tests/test_if_session.py @@ -350,7 +350,7 @@ async def test_do_save_sends_save_command(tmp_path): assert b"\n" in calls[1][0][0] # Result should contain confirmation - assert "Ok" in result or "ok" in result.lower() + assert "saved" in result.lower() @pytest.mark.asyncio @@ -495,7 +495,7 @@ async def test_handle_input_save_triggers_save(tmp_path): response = await session.handle_input("::save") assert response.done is False - assert "Ok" in response.output or "ok" in response.output.lower() + assert "saved" in response.output.lower() # Verify save command was sent assert mock_process.stdin.write.call_args_list[0][0][0] == b"save\n" @@ -815,3 +815,89 @@ async def test_read_response_handles_chunked_data(): assert "Welcome to Zork" in result assert "open field" in result assert not result.strip().endswith(">") + + +@pytest.mark.asyncio +async def test_do_save_auto_confirms_overwrite(tmp_path): + """_do_save() auto-confirms with 'yes' when overwrite prompt appears.""" + 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 responses: prompt, overwrite question, confirmation + responses = [ + b"Enter saved game to store: \n>", + b"Overwrite existing file?\n>", + b"Ok.\n>", + ] + response_iter = iter(responses) + + async def read_side_effect(n): + try: + return next(response_iter) + except StopIteration: + return b"" + + mock_process.stdout.read = AsyncMock(side_effect=read_side_effect) + + result = await session._do_save() + + # Should have written "save\n", filepath, "yes\n" + calls = mock_process.stdin.write.call_args_list + assert len(calls) == 3 + assert calls[0][0][0] == b"save\n" + assert str(session.save_path) in calls[1][0][0].decode() + assert calls[2][0][0] == b"yes\n" + + # Result should contain "saved" + assert "saved" in result.lower() + assert session._saved is True + + +@pytest.mark.asyncio +async def test_do_save_detects_failure(tmp_path): + """_do_save() returns error when dfrotz responds with 'Failed.'""" + 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 responses: prompt, then failure + responses = [ + b"Enter saved game to store: \n>", + b"Failed.\n>", + ] + response_iter = iter(responses) + + async def read_side_effect(n): + try: + return next(response_iter) + except StopIteration: + return b"" + + mock_process.stdout.read = AsyncMock(side_effect=read_side_effect) + + result = await session._do_save() + + # Result should contain error and failed + assert "error" in result.lower() + assert "failed" in result.lower() + # Should NOT be marked as saved + assert session._saved is False