"""Tests for pager integration.""" from __future__ import annotations import signal import subprocess from unittest.mock import MagicMock, patch from rp.pager import MousePager, _mouse_capable_less class TestMouseCapableLess: """Tests for _mouse_capable_less().""" def test_returns_path_when_less_supports_mouse(self) -> None: with patch("rp.pager.shutil.which", return_value="/usr/bin/less"): mock_result = MagicMock() mock_result.stdout = "less 551 (POSIX regular expressions)" mock_result.stderr = "" with patch("rp.pager.subprocess.run", return_value=mock_result): assert _mouse_capable_less() == "/usr/bin/less" def test_returns_none_when_less_not_found(self) -> None: with patch("rp.pager.shutil.which", return_value=None): assert _mouse_capable_less() is None def test_returns_none_when_less_too_old(self) -> None: with patch("rp.pager.shutil.which", return_value="/usr/bin/less"): mock_result = MagicMock() mock_result.stdout = "less 444" mock_result.stderr = "" with patch("rp.pager.subprocess.run", return_value=mock_result): assert _mouse_capable_less() is None def test_returns_path_when_version_is_in_stderr(self) -> None: with patch("rp.pager.shutil.which", return_value="/usr/bin/less"): mock_result = MagicMock() mock_result.stdout = "" mock_result.stderr = "less 600" with patch("rp.pager.subprocess.run", return_value=mock_result): assert _mouse_capable_less() == "/usr/bin/less" def test_returns_none_on_timeout(self) -> None: with patch("rp.pager.shutil.which", return_value="/usr/bin/less"): with patch( "rp.pager.subprocess.run", side_effect=subprocess.TimeoutExpired(cmd="less", timeout=5), ): assert _mouse_capable_less() is None def test_returns_none_on_os_error(self) -> None: with patch("rp.pager.shutil.which", return_value="/usr/bin/less"): with patch("rp.pager.subprocess.run", side_effect=OSError("nope")): assert _mouse_capable_less() is None def test_returns_none_when_version_not_parseable(self) -> None: with patch("rp.pager.shutil.which", return_value="/usr/bin/less"): mock_result = MagicMock() mock_result.stdout = "some random output" mock_result.stderr = "" with patch("rp.pager.subprocess.run", return_value=mock_result): assert _mouse_capable_less() is None def test_boundary_version_543(self) -> None: with patch("rp.pager.shutil.which", return_value="/usr/bin/less"): mock_result = MagicMock() mock_result.stdout = "less 543" mock_result.stderr = "" with patch("rp.pager.subprocess.run", return_value=mock_result): assert _mouse_capable_less() == "/usr/bin/less" def test_boundary_version_542(self) -> None: with patch("rp.pager.shutil.which", return_value="/usr/bin/less"): mock_result = MagicMock() mock_result.stdout = "less 542" mock_result.stderr = "" with patch("rp.pager.subprocess.run", return_value=mock_result): assert _mouse_capable_less() is None class TestMousePager: """Tests for MousePager.show().""" def test_falls_back_to_system_pager_when_no_less(self) -> None: pager = MousePager() with patch("rp.pager._mouse_capable_less", return_value=None): with patch("rp.pager.SystemPager") as mock_system_pager: mock_instance = MagicMock() mock_system_pager.return_value = mock_instance pager.show("content") mock_instance.show.assert_called_once_with("content") def test_uses_less_when_available(self) -> None: pager = MousePager() mock_result = MagicMock() mock_result.returncode = 0 with patch("rp.pager._mouse_capable_less", return_value="/usr/bin/less"): with patch("rp.pager.subprocess.run", return_value=mock_result) as mock_run: pager.show("hello") mock_run.assert_called_once_with( ["/usr/bin/less", "-R", "--mouse"], input="hello", text=True, ) def test_sigint_does_not_trigger_fallback_for_negative_code(self) -> None: pager = MousePager() mock_result = MagicMock() mock_result.returncode = -signal.SIGINT with patch("rp.pager._mouse_capable_less", return_value="/usr/bin/less"): with patch("rp.pager.subprocess.run", return_value=mock_result): with patch("rp.pager.SystemPager") as mock_system_pager: pager.show("content") mock_system_pager.assert_not_called() def test_sigint_does_not_trigger_fallback_for_128_plus_code(self) -> None: pager = MousePager() mock_result = MagicMock() mock_result.returncode = 128 + signal.SIGINT with patch("rp.pager._mouse_capable_less", return_value="/usr/bin/less"): with patch("rp.pager.subprocess.run", return_value=mock_result): with patch("rp.pager.SystemPager") as mock_system_pager: pager.show("content") mock_system_pager.assert_not_called() def test_nonzero_exit_triggers_fallback(self) -> None: pager = MousePager() mock_result = MagicMock() mock_result.returncode = 1 with patch("rp.pager._mouse_capable_less", return_value="/usr/bin/less"): with patch("rp.pager.subprocess.run", return_value=mock_result): with patch("rp.pager.SystemPager") as mock_system_pager: mock_instance = MagicMock() mock_system_pager.return_value = mock_instance pager.show("content") mock_instance.show.assert_called_once_with("content") def test_oserror_triggers_fallback(self) -> None: pager = MousePager() with patch("rp.pager._mouse_capable_less", return_value="/usr/bin/less"): with patch("rp.pager.subprocess.run", side_effect=OSError("fail")): with patch("rp.pager.SystemPager") as mock_system_pager: mock_instance = MagicMock() mock_system_pager.return_value = mock_instance pager.show("content") mock_instance.show.assert_called_once_with("content")