diff --git a/requirements.txt b/requirements.txt index f864165..ea3ed3d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,4 +16,5 @@ pytest-timeout>=2.2.0 pytest-xdist>=3.5.0 requests>=2.0 ruff>=0.8.0 +websockets>=12.0 types-requests>=2.31.0 diff --git a/steam_backlog_enforcer/tests/test_enforcer.py b/steam_backlog_enforcer/tests/test_enforcer.py index a6af9f7..1ef2dcf 100644 --- a/steam_backlog_enforcer/tests/test_enforcer.py +++ b/steam_backlog_enforcer/tests/test_enforcer.py @@ -105,9 +105,7 @@ class TestEnforceAllowedGame: "steam_backlog_enforcer.enforcer.get_running_steam_game_pids", return_value={100: 570, 200: 440}, ), - patch( - "steam_backlog_enforcer.enforcer.kill_process" - ) as mock_kill, + patch("steam_backlog_enforcer.enforcer.kill_process") as mock_kill, ): result = enforce_allowed_game(440, kill_unauthorized=True) assert result == [(100, 570)] @@ -144,9 +142,7 @@ class TestEnforceAllowedGame: "steam_backlog_enforcer.enforcer.is_protected_app", side_effect=lambda aid: aid == 1331550, ), - patch( - "steam_backlog_enforcer.enforcer.kill_process" - ) as mock_kill, + patch("steam_backlog_enforcer.enforcer.kill_process") as mock_kill, ): result = enforce_allowed_game(440, kill_unauthorized=True) assert result == [] @@ -180,9 +176,7 @@ class TestSendNotification: """Tests for send_notification.""" def test_sends(self) -> None: - with patch( - "steam_backlog_enforcer.enforcer.subprocess.run" - ) as mock_run: + with patch("steam_backlog_enforcer.enforcer.subprocess.run") as mock_run: send_notification("Title", "Body") mock_run.assert_called_once() diff --git a/steam_backlog_enforcer/tests/test_game_install.py b/steam_backlog_enforcer/tests/test_game_install.py index 33e9849..d93cad5 100644 --- a/steam_backlog_enforcer/tests/test_game_install.py +++ b/steam_backlog_enforcer/tests/test_game_install.py @@ -98,9 +98,7 @@ class TestTriggerSteamInstall: """Tests for _trigger_steam_install.""" def test_success(self) -> None: - with patch( - "steam_backlog_enforcer.game_install.subprocess.run" - ) as mock_run: + with patch("steam_backlog_enforcer.game_install.subprocess.run") as mock_run: result = _trigger_steam_install(440, "TF2") assert result is True mock_run.assert_called_once() @@ -174,15 +172,11 @@ class TestIsGameInstalled: def test_installed(self, tmp_path: Path) -> None: manifest = tmp_path / "appmanifest_440.acf" manifest.touch() - with patch( - "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path - ): + with patch("steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path): assert is_game_installed(440) is True def test_not_installed(self, tmp_path: Path) -> None: - with patch( - "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path - ): + with patch("steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path): assert is_game_installed(440) is False @@ -204,9 +198,7 @@ class TestEnsureSteamRunning: "steam_backlog_enforcer.game_install.subprocess.run", return_value=mock_result, ), - patch( - "steam_backlog_enforcer.game_install.subprocess.Popen" - ) as mock_popen, + patch("steam_backlog_enforcer.game_install.subprocess.Popen") as mock_popen, patch( "steam_backlog_enforcer.game_install.os.geteuid", return_value=1000, @@ -226,9 +218,7 @@ class TestEnsureSteamRunning: "steam_backlog_enforcer.game_install.subprocess.run", return_value=mock_result, ), - patch( - "steam_backlog_enforcer.game_install.subprocess.Popen" - ) as mock_popen, + patch("steam_backlog_enforcer.game_install.subprocess.Popen") as mock_popen, patch( "steam_backlog_enforcer.game_install.os.geteuid", return_value=0, diff --git a/steam_backlog_enforcer/tests/test_game_install_part3.py b/steam_backlog_enforcer/tests/test_game_install_part3.py index 99aacc9..6ba14bb 100644 --- a/steam_backlog_enforcer/tests/test_game_install_part3.py +++ b/steam_backlog_enforcer/tests/test_game_install_part3.py @@ -25,9 +25,7 @@ class TestInstallGame: def test_already_installed(self, tmp_path: Path) -> None: manifest = tmp_path / "appmanifest_440.acf" manifest.touch() - with patch( - "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path - ): + with patch("steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path): assert install_game(440, "TF2", "steam123") is True def test_use_steam_protocol_success(self, tmp_path: Path) -> None: @@ -36,9 +34,7 @@ class TestInstallGame: "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path, ), - patch( - "steam_backlog_enforcer.game_install._ensure_steam_running" - ), + patch("steam_backlog_enforcer.game_install._ensure_steam_running"), patch( "steam_backlog_enforcer.game_install._trigger_steam_install", return_value=True, @@ -52,9 +48,7 @@ class TestInstallGame: "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path, ), - patch( - "steam_backlog_enforcer.game_install._ensure_steam_running" - ), + patch("steam_backlog_enforcer.game_install._ensure_steam_running"), patch( "steam_backlog_enforcer.game_install._trigger_steam_install", return_value=False, @@ -73,9 +67,7 @@ class TestInstallGame: "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path, ), - patch( - "steam_backlog_enforcer.game_install._ensure_steam_running" - ), + patch("steam_backlog_enforcer.game_install._ensure_steam_running"), patch( "steam_backlog_enforcer.game_install.os.geteuid", return_value=0, @@ -88,9 +80,7 @@ class TestInstallGame: "steam_backlog_enforcer.game_install._get_uid_gid_for_user", return_value=(1001, 1001), ), - patch( - "steam_backlog_enforcer.game_install.os.chown" - ) as mock_chown, + patch("steam_backlog_enforcer.game_install.os.chown") as mock_chown, ): assert install_game(440, "TF2", "s1") is True mock_chown.assert_called_once() @@ -102,9 +92,7 @@ class TestInstallGame: "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path / "nonexistent" / "deep", ), - patch( - "steam_backlog_enforcer.game_install._ensure_steam_running" - ), + patch("steam_backlog_enforcer.game_install._ensure_steam_running"), patch( "steam_backlog_enforcer.game_install.os.geteuid", return_value=1000, @@ -118,9 +106,7 @@ class TestInstallGame: "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path, ), - patch( - "steam_backlog_enforcer.game_install._ensure_steam_running" - ), + patch("steam_backlog_enforcer.game_install._ensure_steam_running"), patch( "steam_backlog_enforcer.game_install.os.geteuid", return_value=1000, @@ -134,16 +120,12 @@ class TestInstallGame: "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path, ), - patch( - "steam_backlog_enforcer.game_install._ensure_steam_running" - ), + patch("steam_backlog_enforcer.game_install._ensure_steam_running"), patch( "steam_backlog_enforcer.game_install.os.geteuid", return_value=1000, ), - patch( - "steam_backlog_enforcer.game_install.os.chown" - ) as mock_chown, + patch("steam_backlog_enforcer.game_install.os.chown") as mock_chown, ): assert install_game(440, "TF2", "s1") is True mock_chown.assert_not_called() @@ -155,9 +137,7 @@ class TestInstallGame: "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path, ), - patch( - "steam_backlog_enforcer.game_install._ensure_steam_running" - ), + patch("steam_backlog_enforcer.game_install._ensure_steam_running"), patch( "steam_backlog_enforcer.game_install.os.geteuid", return_value=0, @@ -166,9 +146,7 @@ class TestInstallGame: "steam_backlog_enforcer.game_install._get_real_user", return_value="root", ), - patch( - "steam_backlog_enforcer.game_install.os.chown" - ) as mock_chown, + patch("steam_backlog_enforcer.game_install.os.chown") as mock_chown, ): assert install_game(440, "TF2", "s1") is True mock_chown.assert_not_called() @@ -180,34 +158,26 @@ class TestGetInstalledGames: def test_parses_manifests(self, tmp_path: Path) -> None: manifest = tmp_path / "appmanifest_440.acf" manifest.write_text('"appid"\t\t"440"\n"name"\t\t"Team Fortress 2"\n') - with patch( - "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path - ): + with patch("steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path): result = get_installed_games() assert result == [(440, "Team Fortress 2")] def test_no_name(self, tmp_path: Path) -> None: manifest = tmp_path / "appmanifest_440.acf" manifest.write_text('"appid"\t\t"440"\n') - with patch( - "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path - ): + with patch("steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path): result = get_installed_games() assert result == [(440, "Unknown (440)")] def test_empty_dir(self, tmp_path: Path) -> None: - with patch( - "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path - ): + with patch("steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path): result = get_installed_games() assert result == [] def test_no_appid_match(self, tmp_path: Path) -> None: manifest = tmp_path / "appmanifest_440.acf" manifest.write_text('"name"\t\t"NoAppId"\n') - with patch( - "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path - ): + with patch("steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path): result = get_installed_games() assert result == [] @@ -218,18 +188,14 @@ class TestReadInstallDir: def test_reads_dir(self, tmp_path: Path) -> None: manifest = tmp_path / "appmanifest_440.acf" manifest.write_text('"installdir"\t\t"Team Fortress 2"\n') - with patch( - "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path - ): + with patch("steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path): result = _read_install_dir(manifest) assert result == tmp_path / "common" / "Team Fortress 2" def test_no_match(self, tmp_path: Path) -> None: manifest = tmp_path / "appmanifest_440.acf" manifest.write_text('"appid"\t\t"440"\n') - with patch( - "steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path - ): + with patch("steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path): assert _read_install_dir(manifest) is None def test_missing_file(self, tmp_path: Path) -> None: diff --git a/steam_backlog_enforcer/tests/test_hltb.py b/steam_backlog_enforcer/tests/test_hltb.py index 53c27ae..77a12ae 100644 --- a/steam_backlog_enforcer/tests/test_hltb.py +++ b/steam_backlog_enforcer/tests/test_hltb.py @@ -32,25 +32,19 @@ class TestHltbCache: def test_load_cache_exists(self, tmp_path: Path) -> None: cache_file = tmp_path / "hltb_cache.json" cache_file.write_text(json.dumps({"440": 10.5}), encoding="utf-8") - with patch( - "steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE", cache_file - ): + with patch("steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE", cache_file): result = load_hltb_cache() assert result == {440: 10.5} def test_load_cache_missing(self, tmp_path: Path) -> None: cache_file = tmp_path / "nonexistent.json" - with patch( - "steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE", cache_file - ): + with patch("steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE", cache_file): assert load_hltb_cache() == {} def test_load_cache_corrupt(self, tmp_path: Path) -> None: cache_file = tmp_path / "hltb_cache.json" cache_file.write_text("not json", encoding="utf-8") - with patch( - "steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE", cache_file - ): + with patch("steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE", cache_file): assert load_hltb_cache() == {} def test_save_cache(self, tmp_path: Path) -> None: @@ -79,18 +73,14 @@ class TestGetHltbSearchUrl: def test_discovers_url(self) -> None: mock_info = MagicMock() mock_info.search_url = "/api/search/abc" - with patch( - "steam_backlog_enforcer._hltb_search.HTMLRequests" - ) as mock_html: + with patch("steam_backlog_enforcer._hltb_search.HTMLRequests") as mock_html: mock_html.send_website_request_getcode.return_value = mock_info mock_html.BASE_URL = "https://howlongtobeat.com" url = _get_hltb_search_url() assert url == "https://howlongtobeat.com/api/search/abc" def test_fallback_url(self) -> None: - with patch( - "steam_backlog_enforcer._hltb_search.HTMLRequests" - ) as mock_html: + with patch("steam_backlog_enforcer._hltb_search.HTMLRequests") as mock_html: mock_html.send_website_request_getcode.return_value = None url = _get_hltb_search_url() assert url == "https://howlongtobeat.com/api/finder" @@ -98,18 +88,14 @@ class TestGetHltbSearchUrl: def test_first_returns_none_second_returns_info(self) -> None: mock_info = MagicMock() mock_info.search_url = "/api/search/xyz" - with patch( - "steam_backlog_enforcer._hltb_search.HTMLRequests" - ) as mock_html: + with patch("steam_backlog_enforcer._hltb_search.HTMLRequests") as mock_html: mock_html.send_website_request_getcode.side_effect = [None, mock_info] mock_html.BASE_URL = "https://howlongtobeat.com" url = _get_hltb_search_url() assert url == "https://howlongtobeat.com/api/search/xyz" def test_exception_fallback(self) -> None: - with patch( - "steam_backlog_enforcer._hltb_search.HTMLRequests" - ) as mock_html: + with patch("steam_backlog_enforcer._hltb_search.HTMLRequests") as mock_html: mock_html.send_website_request_getcode.side_effect = RuntimeError url = _get_hltb_search_url() assert url == "https://howlongtobeat.com/api/finder" diff --git a/steam_backlog_enforcer/tests/test_hltb_detail.py b/steam_backlog_enforcer/tests/test_hltb_detail.py index 39361e1..3b9c6b8 100644 --- a/steam_backlog_enforcer/tests/test_hltb_detail.py +++ b/steam_backlog_enforcer/tests/test_hltb_detail.py @@ -454,9 +454,7 @@ class TestFetchLeisureTimes: new_callable=AsyncMock, return_value=game_data, ), - patch( - "steam_backlog_enforcer._hltb_detail.save_hltb_cache" - ) as mock_save, + patch("steam_backlog_enforcer._hltb_detail.save_hltb_cache") as mock_save, ): asyncio.run(_fetch_leisure_times(results, cache, {}, None)) mock_save.assert_called_once() diff --git a/steam_backlog_enforcer/tests/test_scanning.py b/steam_backlog_enforcer/tests/test_scanning.py index 7e8326e..f930760 100644 --- a/steam_backlog_enforcer/tests/test_scanning.py +++ b/steam_backlog_enforcer/tests/test_scanning.py @@ -322,9 +322,7 @@ class TestPickNextGame: "steam_backlog_enforcer.scanning.is_game_installed", return_value=False, ), - patch( - "steam_backlog_enforcer.scanning.install_game" - ) as mock_install, + patch("steam_backlog_enforcer.scanning.install_game") as mock_install, patch("builtins.input", return_value="1"), ): pick_next_game([g1], state, config) diff --git a/steam_backlog_enforcer/tests/test_scanning_part3.py b/steam_backlog_enforcer/tests/test_scanning_part3.py index 6e73cf1..29ef412 100644 --- a/steam_backlog_enforcer/tests/test_scanning_part3.py +++ b/steam_backlog_enforcer/tests/test_scanning_part3.py @@ -311,9 +311,7 @@ class TestPickNextGameSequential: return_value=0, ) ) - stack.enter_context( - patch("steam_backlog_enforcer.config._atomic_write") - ) + stack.enter_context(patch("steam_backlog_enforcer.config._atomic_write")) return stack def test_on_select_accepts_pick(self) -> None: diff --git a/steam_backlog_enforcer/tests/test_scanning_part4.py b/steam_backlog_enforcer/tests/test_scanning_part4.py index 0bc4b03..479130a 100644 --- a/steam_backlog_enforcer/tests/test_scanning_part4.py +++ b/steam_backlog_enforcer/tests/test_scanning_part4.py @@ -172,9 +172,7 @@ class TestConfidenceHelpers: patch( "steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence_batch", ), - patch( - "steam_backlog_enforcer._scanning_confidence._echo" - ) as mock_echo, + patch("steam_backlog_enforcer._scanning_confidence._echo") as mock_echo, ): result = _filter_hltb_confident_candidates([low]) assert result == []