diff --git a/tests/test_app_download_settings.py b/tests/test_app_download_settings.py index f47c337..b30f44f 100644 --- a/tests/test_app_download_settings.py +++ b/tests/test_app_download_settings.py @@ -1,6 +1,7 @@ import pytest from _pytest.monkeypatch import MonkeyPatch +from collections.abc import Iterator from pathlib import Path from dzgui.api.steam import get_app_allows_downloads, get_last_updated @@ -36,7 +37,7 @@ def steam_path() -> Path: @pytest.fixture(scope="module", autouse=True) -def patch_api() -> None: +def patch_api() -> Iterator[None]: mp = MonkeyPatch() mp.setattr("dzgui.api.steam.get_app_path", mock_path) yield diff --git a/tests/test_loginusers.py b/tests/test_loginusers.py index db96c56..cfcba50 100644 --- a/tests/test_loginusers.py +++ b/tests/test_loginusers.py @@ -1,6 +1,7 @@ import pytest from pathlib import Path +from typing import TYPE_CHECKING from dzgui.api.steam import find_user_id from dzgui.const.constants import DEFAULT_STEAM_PATH @@ -8,6 +9,9 @@ from tests.fixtures import fixture_path pytestmark = pytest.mark.apitest +if TYPE_CHECKING: + from _pytest.monkeypatch import MonkeyPatch + @pytest.mark.parametrize( "fixture, expect", @@ -19,12 +23,14 @@ pytestmark = pytest.mark.apitest ("api/loginusers_beta_client_multiple_2.vdf", 0), ], ) -def test_loginusers(monkeypatch, fixture: str, expect: int) -> None: +def test_loginusers(monkeypatch: "MonkeyPatch", fixture: str, expect: int) -> None: def mock_loginusers(path: Path) -> Path: return fixture_path(fixture) monkeypatch.setattr("dzgui.api.steam.find_loginusers", mock_loginusers) uid = find_user_id(Path("")) + if uid is None: + raise ValueError() assert int(uid) == expect diff --git a/tests/test_mod_signatures.py b/tests/test_mod_signatures.py index 8aa5dd6..8de0fc7 100644 --- a/tests/test_mod_signatures.py +++ b/tests/test_mod_signatures.py @@ -11,27 +11,33 @@ import dzgui.config.query from tests.fixtures import fixture_path if TYPE_CHECKING: - from dzgui.const.enums import Preferences + from _pytest.monkeypatch import MonkeyPatch + from dzgui.const.enum import Preferences pytestmark = pytest.mark.mods + @pytest.fixture -def versions() -> str: +def versions() -> "Path": return fixture_path("dzg.versions") + @pytest.fixture def tmp() -> str: with tempfile.NamedTemporaryFile(delete=False) as f: tmp = f.name return tmp + def mock_local_ids(path: Path) -> list[int]: return [3410710885, 3739934289] + def mock_lookup(path: Path, prefs: "Preferences") -> str: return "" -def test_signatures(monkeypatch, tmp: str, versions: str) -> None: + +def test_signatures(monkeypatch: "MonkeyPatch", tmp: str, versions: str) -> None: ids = [1559212036, 1654462998] shutil.copyfile(versions, tmp) path = Path(tmp) @@ -41,12 +47,15 @@ def test_signatures(monkeypatch, tmp: str, versions: str) -> None: lines = f.readlines() assert ids not in lines -def test_signatures_with_no_ids(monkeypatch, tmp: str, versions: str) -> None: + +def test_signatures_with_no_ids( + monkeypatch: "MonkeyPatch", tmp: str, versions: str +) -> None: shutil.copyfile(versions, tmp) path = Path(tmp) monkeypatch.setattr("dzgui.api.mods.get_local_mod_ids", mock_local_ids) monkeypatch.setattr("dzgui.api.mods.lookup", mock_lookup) dzgui.api.mods.remove_stale_signatures(path, path) with open(tmp, "r") as f: - lines = f.readlines() - assert lines == ["3410710885,1752864732\n", "3739934289,1780855136\n"] + lines = [line.rstrip() for line in f.readlines()] + assert lines == ["3410710885,1752864732", "3739934289,1780855136"] diff --git a/tests/test_modmeta.py b/tests/test_modmeta.py index 8002825..f1ffa01 100644 --- a/tests/test_modmeta.py +++ b/tests/test_modmeta.py @@ -4,10 +4,13 @@ from pathlib import Path from dzgui.api.mods import tokenize from tests.fixtures import fixture_path + @pytest.mark.mods @pytest.mark.parametrize("i", range(1, 7)) def test_modmeta(i: int) -> None: fixture = fixture_path(f"cpp/mod{i}") path = Path(fixture) meta = tokenize(path) + if meta is None: + raise ValueError assert meta["name"] == "ModName" diff --git a/tests/test_paused_downloads.py b/tests/test_paused_downloads.py index 6183e93..255c4ef 100644 --- a/tests/test_paused_downloads.py +++ b/tests/test_paused_downloads.py @@ -23,11 +23,11 @@ if TYPE_CHECKING: def test_dayz_patch_pending( monkeypatch: "MonkeyPatch", file_list: list[str], expect: bool ) -> None: - def mock_get_pending_downloads(steam_path: Path, appid: int) -> None: + def mock_get_pending_downloads(steam_path: Path, appid: int) -> list[Path]: files = [Path(file) for file in file_list] return files monkeypatch.setattr( "dzgui.api.steam.get_pending_downloads", mock_get_pending_downloads ) - assert is_dayz_downloading(Path("/tmp"), Path("/tmp")) == expect + assert is_dayz_downloading(Path("/tmp"), 221100) == expect diff --git a/tests/test_pefile.py b/tests/test_pefile.py index 6d6be0a..e17a1d3 100644 --- a/tests/test_pefile.py +++ b/tests/test_pefile.py @@ -1,6 +1,7 @@ import pytest -from pathlib import Path +from pathlib import Path +from typing import TYPE_CHECKING import dzgui.api.pefile as PeFile from dzgui.api.steam import ( @@ -16,6 +17,9 @@ from dzgui.const.constants import APPID_DAYZ from tests.fixtures import fixture_path +if TYPE_CHECKING: + from _pytest.monkeypatch import MonkeyPatch + pytestmark = pytest.mark.apitest @@ -53,7 +57,9 @@ def test_invalid_pefile_path() -> None: ("malformed.vdf", VDFLoadError), ], ) -def test_not_in_library(monkeypatch, fixture, exception): +def test_not_in_library( + monkeypatch: "MonkeyPatch", fixture: str, exception: type[Exception] +) -> None: import dzgui.api.steam as steam monkeypatch.setattr(steam, "LIBRARYFOLDERS_PATH", fixture) @@ -71,7 +77,7 @@ def second_drive() -> str: return "in_library_on_second_drive.vdf" -def test_on_second_drive(monkeypatch, second_drive: str) -> None: +def test_on_second_drive(monkeypatch: "MonkeyPatch", second_drive: str) -> None: import dzgui.api.steam as steam monkeypatch.setattr(steam, "LIBRARYFOLDERS_PATH", second_drive) diff --git a/tests/test_process_detection.py b/tests/test_process_detection.py index cc89f05..f57ced3 100644 --- a/tests/test_process_detection.py +++ b/tests/test_process_detection.py @@ -1,6 +1,8 @@ import pytest import unittest + from unittest.mock import patch +from typing import Any from dzgui.const.constants import ( FLATPAK_APPID, @@ -15,7 +17,7 @@ pytestmark = pytest.mark.flatpak class TestSteamDetection(unittest.TestCase): def test_flatpak_detection_with_multiple_running_apps(self) -> None: - def flatpak_output(args, *, text: str) -> str: + def flatpak_output(args: Any, *, text: str) -> str: # Default 'flatpak ps' includes instance, PID, app and runtime columns. if args == ["flatpak", "ps", "--columns=application"]: return f"com.spotify.Client\n{FLATPAK_APPID}\n{FLATPAK_APPID}\n" diff --git a/tests/test_remote_api.py b/tests/test_remote_api.py index a340510..5e90498 100644 --- a/tests/test_remote_api.py +++ b/tests/test_remote_api.py @@ -1,6 +1,6 @@ import pytest -from typing import TYPE_CHECKING +from typing import Any, TYPE_CHECKING from dzgui.api import probe from dzgui.config.query import get_config @@ -13,7 +13,7 @@ pytestmark = pytest.mark.webtest @pytest.fixture -def config() -> dict[str, "Path"]: +def config() -> Any: paths = get_xdg_paths() xdg = parse_filepaths(paths) return get_config(xdg.config) @@ -23,6 +23,6 @@ def test_ipdb() -> None: assert probe.test_ipdb() -def test_steam(config: dict[str, "Path"]) -> None: +def test_steam(config: Any) -> None: key = config["steam_api"] assert probe.test_steam_api(key) diff --git a/tests/test_server_metadata.py b/tests/test_server_metadata.py index dc3408c..392af2a 100644 --- a/tests/test_server_metadata.py +++ b/tests/test_server_metadata.py @@ -27,6 +27,8 @@ def test_time_accel(details, key, expect) -> None: def test_gametime(details: Details | None) -> None: time_reg = r"^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]$)" + if details is None: + raise ValueError match = re.match(time_reg, details.gametime) assert match is not None diff --git a/tests/test_server_time.py b/tests/test_server_time.py index 7bb7397..8bd32b4 100644 --- a/tests/test_server_time.py +++ b/tests/test_server_time.py @@ -1,7 +1,8 @@ import pytest -from hypothesis import given, strategies as st from datetime import datetime, timedelta +from hypothesis import given, strategies as st +from typing import Any from dzgui.views.dialogs.calc import ( LocalClock, @@ -17,12 +18,12 @@ class DummyEmitter: def __init__(self) -> None: pass - def connect(self, _, __) -> None: + def connect(self, _: Any, __: Any) -> None: pass @pytest.fixture(params=[("05:00", 10.0), ("15:30", 5.0)]) -def accel_server_clock(request) -> None: +def accel_server_clock(request) -> tuple[str, ServerClock]: clock_time, expect = request.param cur_time = Time(clock_time, 5.0, 2.0) emitter = DummyEmitter() @@ -31,13 +32,18 @@ def accel_server_clock(request) -> None: return expect, server_clock -def test_accel_factor(accel_server_clock) -> None: +def test_accel_factor(accel_server_clock: tuple[str, ServerClock]) -> None: """Static test checking times at known boundaries""" expect, clock = accel_server_clock assert clock.get_accel_factor(clock.cur_time) == expect -def reference_calc(start, end, day_factor, night_factor): +def reference_calc( + start: datetime, + end: datetime, + day_factor: float, + night_factor: float, +) -> timedelta: """ Reference implementation to test validity of UI-side calculator Aggregates total seconds and applies accel factors after @@ -80,7 +86,7 @@ night_accel = st.floats( @st.composite -def time_ranges(draw): +def time_ranges(draw: st.DrawFn) -> tuple[datetime, datetime]: start_time = draw(st.times()) deltas = st.timedeltas(min_value=timedelta(0), max_value=timedelta(days=1)) duration = draw(deltas) @@ -91,7 +97,11 @@ def time_ranges(draw): @given(span=time_ranges(), day_factor=day_accel, night_factor=night_accel) -def test_time_aggregation(span, day_factor, night_factor) -> None: +def test_time_aggregation( + span: tuple[datetime, datetime], + day_factor: float, + night_factor: float, +) -> None: start, end = span strtime = start.strftime("%H:%M") diff --git a/tests/test_shortcuts.py b/tests/test_shortcuts.py index ac23e9d..d92eda1 100644 --- a/tests/test_shortcuts.py +++ b/tests/test_shortcuts.py @@ -1,10 +1,11 @@ import pytest import tempfile -from typing import TYPE_CHECKING -from pathlib import Path from _pytest.monkeypatch import MonkeyPatch +from collections.abc import Iterator +from pathlib import Path +from typing import Any, cast, TYPE_CHECKING from dzgui.api.shortcuts import Shortcuts from tests.fixtures import fixture_path @@ -15,12 +16,12 @@ if TYPE_CHECKING: pytestmark = pytest.mark.apitest -def mock_find_shortcuts(self, steam_path: Path) -> Path: +def mock_find_shortcuts(self: Shortcuts, steam_path: Path) -> Path: return Path(fixture_path("api/no_shortcuts.vdf")) @pytest.fixture(scope="module", autouse=True) -def patch_api() -> None: +def patch_api() -> Iterator[None]: mp = MonkeyPatch() mp.setattr("dzgui.api.shortcuts.Shortcuts.find_shortcuts_path", mock_find_shortcuts) yield @@ -33,64 +34,62 @@ def test_no_shortcuts(monkeypatch: "MonkeyPatch") -> None: @pytest.fixture -def dummy_app() -> dict[str, str]: +def dummy_app() -> dict[str, Any]: d = { "AppName": "TEST APP", - "StartDir": "TEST_DIR", - "Exe": "TEST_DIR/TEST_EXE.EXE", - "icon": "IMAGES_DIR/TEST_IMAGE.PNG", + "StartDir": Path("TEST_DIR"), + "Exe": Path("TEST_DIR/TEST_EXE.EXE"), + "icon": Path("IMAGES_DIR/TEST_IMAGE.PNG"), } return d -def test_wrap_exe(dummy_app: dict[str, str]) -> None: +@pytest.fixture +def shortcuts(dummy_app: dict[str, Any]) -> Shortcuts: s = Shortcuts(Path("")) - s.add_shortcut(*dummy_app.values()) - assert s.shortcuts["shortcuts"]["0"]["Exe"][0] == '"' - assert s.shortcuts["shortcuts"]["0"]["Exe"][-1] == '"' + args = cast(tuple[str, Path, Path, Path], dummy_app.values()) + s.add_shortcut(*args) + return s -def test_add_shortcut(dummy_app: dict[str, str]) -> None: - s = Shortcuts(Path("")) - s.add_shortcut(*dummy_app.values()) - new = s.shortcuts["shortcuts"] +def test_wrap_exe(shortcuts: Shortcuts) -> None: + assert shortcuts.shortcuts["shortcuts"]["0"]["Exe"][0] == '"' + assert shortcuts.shortcuts["shortcuts"]["0"]["Exe"][-1] == '"' + + +def test_add_shortcut(shortcuts: Shortcuts, dummy_app: dict[str, Any]) -> None: + new = shortcuts.shortcuts["shortcuts"] ind = str(len(new) - 1) for k, v in dummy_app.items(): if k == "Exe": v = f'"{v}"' - assert new[ind][k] == v + assert new[ind][k] == str(v) -def test_save_shortcut(dummy_app: dict[str, str]) -> None: - s = Shortcuts(Path("")) - s.add_shortcut(*dummy_app.values()) +def test_save_shortcut(shortcuts: Shortcuts) -> None: with tempfile.NamedTemporaryFile() as f: tmp = Path(f.name) - s.shortcuts_path = tmp - s.save_shortcuts() - s._load_shortcuts(tmp) - assert len(s.shortcuts["shortcuts"]) == 1 + shortcuts.shortcuts_path = tmp + shortcuts.save_shortcuts() + shortcuts._load_shortcuts(tmp) + assert len(shortcuts.shortcuts["shortcuts"]) == 1 -def test_shortcut_crc(dummy_app: dict[str, str]) -> None: - s = Shortcuts(Path("")) - s.add_shortcut(*dummy_app.values()) - for key in s.shortcuts["shortcuts"].keys(): - entry = s.shortcuts["shortcuts"][key] +def test_shortcut_crc(shortcuts: Shortcuts) -> None: + for key in shortcuts.shortcuts["shortcuts"].keys(): + entry = shortcuts.shortcuts["shortcuts"][key] name = entry["AppName"] exe = entry["Exe"] uid = name + exe - bpid = s.gen_bpid(uid) + bpid = shortcuts.gen_bpid(uid) assert entry["appid"] & 0xFFFFFFFF == bpid -def test_reverse_crc(dummy_app: dict[str, str]) -> None: - s = Shortcuts(Path("")) - s.add_shortcut(*dummy_app.values()) - for key in s.shortcuts["shortcuts"].keys(): - entry = s.shortcuts["shortcuts"][key] +def test_reverse_crc(shortcuts: Shortcuts) -> None: + for key in shortcuts.shortcuts["shortcuts"].keys(): + entry = shortcuts.shortcuts["shortcuts"][key] name = entry["AppName"] exe = entry["Exe"] uid = name + exe - bpid = s.gen_bpid(uid) - assert s.find_appname_by_unsigned_id(bpid) == name + bpid = shortcuts.gen_bpid(uid) + assert shortcuts.find_appname_by_unsigned_id(bpid) == name