""" Shared test helpers for the Outline Sync Web UI test suite. Import directly: from tests.helpers import make_mock_process """ from unittest.mock import AsyncMock, MagicMock class _AsyncLineIter: """Proper async iterator for mocking asyncio subprocess stdout.""" def __init__(self, lines: list[str]): self._iter = iter(lines) def __aiter__(self): return self async def __anext__(self) -> bytes: try: return (next(self._iter) + "\n").encode() except StopIteration: raise StopAsyncIteration def make_mock_process(stdout_lines: list[str], returncode: int = 0) -> MagicMock: """ Build a mock asyncio subprocess whose stdout is a proper async iterable. Usage in tests: with patch("webui.spawn_sync_subprocess") as mock_spawn: mock_spawn.return_value = make_mock_process(["Done."]) """ proc = MagicMock() proc.returncode = returncode proc.stdout = _AsyncLineIter(stdout_lines) proc.wait = AsyncMock(return_value=returncode) return proc