Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions Libraries/PyKotor/tests/cli/test_json_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,47 @@
from pykotor.resource.type import ResourceType
from pykotor.tools.resource_json import (
_serialize_mdl_face,
_supports_live_progress,
export_installation_to_json_tree,
iter_installation_resource_documents,
serialize_file_resource_document,
serialize_resource_payload,
)


def test_supports_live_progress_disabled_in_ci(monkeypatch: pytest.MonkeyPatch) -> None:
class _FakeTty:
def isatty(self) -> bool:
return True

monkeypatch.setenv("CI", "true")
assert _supports_live_progress(_FakeTty()) is False


def test_supports_live_progress_disabled_in_github_actions(
monkeypatch: pytest.MonkeyPatch,
) -> None:
class _FakeTty:
def isatty(self) -> bool:
return True

monkeypatch.delenv("CI", raising=False)
monkeypatch.setenv("GITHUB_ACTIONS", "true")
assert _supports_live_progress(_FakeTty()) is False


def test_supports_live_progress_enabled_for_interactive_tty(
monkeypatch: pytest.MonkeyPatch,
) -> None:
class _FakeTty:
def isatty(self) -> bool:
return True

monkeypatch.delenv("CI", raising=False)
monkeypatch.delenv("GITHUB_ACTIONS", raising=False)
assert _supports_live_progress(_FakeTty()) is True


def test_to_json_and_from_json_roundtrip_tlk(tmp_path: Path) -> None:
input_path = tmp_path / "dialog.tlk"
json_path = tmp_path / "dialog.tlk.json"
Expand Down
68 changes: 68 additions & 0 deletions Libraries/PyKotor/tests/common/test_kotor_install_detection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"""Regression tests for CaseAwarePath-based KOTOR install directory detection."""

from __future__ import annotations

import importlib
import sys
from pathlib import Path

import pytest

_INSTALL_DETECTORS = (
("pykotor.diff_tool.cli_utils", "is_kotor_install_dir"),
("pykotor.tools.patching", "is_kotor_install_dir"),
("pykotor.tslpatcher.diff.engine", "is_kotor_install_dir"),
)


@pytest.fixture(params=_INSTALL_DETECTORS, ids=[f"{module}.{name}" for module, name in _INSTALL_DETECTORS])
def is_kotor_install_dir(request):
module_name, attr_name = request.param
module = importlib.import_module(module_name)
return getattr(module, attr_name)


def test_detects_install_with_chitin_key(tmp_path: Path, is_kotor_install_dir) -> None:
install = tmp_path / "KotorInstall"
install.mkdir()
(install / "chitin.key").write_bytes(b"")

assert is_kotor_install_dir(install) is True


def test_rejects_folder_without_chitin_key(tmp_path: Path, is_kotor_install_dir) -> None:
folder = tmp_path / "not_install"
folder.mkdir()

assert not is_kotor_install_dir(folder)


def test_rejects_regular_file(tmp_path: Path, is_kotor_install_dir) -> None:
file_path = tmp_path / "file.txt"
file_path.write_text("x", encoding="utf-8")

assert not is_kotor_install_dir(file_path)


@pytest.mark.skipif(
sys.platform == "win32",
reason="Case-mismatch path semantics differ on Windows filesystems.",
)
def test_detects_case_mismatched_install_path(tmp_path: Path, is_kotor_install_dir) -> None:
install = tmp_path / "GameInstall"
install.mkdir()
(install / "chitin.key").write_bytes(b"")

assert is_kotor_install_dir(tmp_path / "gameinstall") is True


@pytest.mark.skipif(
sys.platform == "win32",
reason="Case-mismatch path semantics differ on Windows filesystems.",
)
def test_detects_case_mismatched_chitin_key(tmp_path: Path, is_kotor_install_dir) -> None:
install = tmp_path / "install"
install.mkdir()
(install / "CHITIN.KEY").write_bytes(b"")

assert is_kotor_install_dir(install) is True
15 changes: 15 additions & 0 deletions Libraries/PyKotor/tests/tslpatcher/test_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,21 @@ def tearDown(self):
if hasattr(self, "temp_dir"):
shutil.rmtree(self.temp_dir, ignore_errors=True)

@unittest.skipIf(
sys.platform == "win32",
"Case-mismatch path semantics differ on Windows filesystems.",
)
def test_from_filepath_resolves_case_mismatched_ini_path(self):
mod_dir = Path(self.temp_dir) / "ModDir"
mod_dir.mkdir()
ini_path = mod_dir / "changes.ini"
ini_path.write_text("[Settings]\nWindowCaption=CaseAware INI\n", encoding="utf-8")

reader = ConfigReader.from_filepath(Path(self.temp_dir) / "moddir" / "changes.ini")
reader.load_settings()

self.assertEqual(reader.config.window_title, "CaseAware INI")

def create_test_tlk(self, data: dict[int, dict[str, str]]) -> TLK:
tlk = TLK()
for v in data.values():
Expand Down
Loading