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
82 changes: 82 additions & 0 deletions Libraries/PyKotor/tests/cli/test_resource_json_progress.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""Regression tests for resource JSON export progress reporting."""

from __future__ import annotations

import io
import logging
from typing import TextIO

import pytest

from pykotor.tools.resource_json import (
_ExportProgressReporter,
_format_progress_bar,
_supports_live_progress,
)


class _FakeTTY(io.StringIO):
def isatty(self) -> bool: # noqa: D102
return True


class _FakeNonTTY(io.StringIO):
def isatty(self) -> bool: # noqa: D102
return False


@pytest.mark.parametrize("percent", [0.0, 50.0, 100.0])
def test_format_progress_bar_clamps_and_fills(percent: float) -> None:
bar = _format_progress_bar(percent)
assert len(bar) == 24
assert set(bar) <= {"#", "-"}


@pytest.mark.parametrize("stream", [_FakeTTY(), _FakeNonTTY()])
def test_supports_live_progress_disabled_when_ci_env_set(
stream: TextIO,
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setenv("CI", "true")
assert _supports_live_progress(stream) is False


@pytest.mark.parametrize("stream", [_FakeTTY(), _FakeNonTTY()])
def test_supports_live_progress_disabled_when_github_actions_set(
stream: TextIO,
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setenv("GITHUB_ACTIONS", "1")
assert _supports_live_progress(stream) is False


def test_supports_live_progress_true_for_tty_without_ci(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.delenv("CI", raising=False)
monkeypatch.delenv("GITHUB_ACTIONS", raising=False)
assert _supports_live_progress(_FakeTTY()) is True


def test_supports_live_progress_false_for_non_tty_without_ci(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.delenv("CI", raising=False)
monkeypatch.delenv("GITHUB_ACTIONS", raising=False)
assert _supports_live_progress(_FakeNonTTY()) is False


def test_export_progress_reporter_logs_to_logger_in_ci(
caplog: pytest.LogCaptureFixture,
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setenv("CI", "true")
logger = logging.getLogger("test_resource_json_progress")
reporter = _ExportProgressReporter(
logger=logger,
total_resources=2,
stream=_FakeTTY(),
)
assert reporter.live_updates is False

with caplog.at_level(logging.INFO, logger="test_resource_json_progress"):
reporter.update(1, "test.2da")
reporter.finish()

assert any("Writing test.2da" in record.message for record in caplog.records)
65 changes: 65 additions & 0 deletions Libraries/PyKotor/tests/diff_tool/test_cli_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""Regression tests for diff_tool CLI path helpers (case-aware install detection)."""

from __future__ import annotations

import sys
from pathlib import Path

import pytest

from pykotor.diff_tool.cli_utils import is_kotor_install_dir, normalize_path_arg


@pytest.mark.parametrize(
("raw", "expected"),
[
(None, None),
("", None),
(" ", None),
('"C:/Games/KOTOR"', "C:/Games/KOTOR"),
("'C:/Games/KOTOR'", "C:/Games/KOTOR"),
(
'C:\\Program Files\\Steam\\steamapps\\common\\swkotor" C:\\other',
"C:\\Program Files\\Steam\\steamapps\\common\\swkotor",
),
('C:\\Games\\KOTOR\\', "C:\\Games\\KOTOR"),
],
)
def test_normalize_path_arg_strips_quotes_and_mangled_powershell_paths(
raw: str | None,
expected: str | None,
) -> None:
assert normalize_path_arg(raw) == expected


def test_is_kotor_install_dir_false_without_chitin_key(tmp_path: Path) -> None:
install_dir = tmp_path / "kotor"
install_dir.mkdir()
assert is_kotor_install_dir(install_dir) is False


def test_is_kotor_install_dir_true_with_chitin_key(tmp_path: Path) -> None:
install_dir = tmp_path / "kotor"
install_dir.mkdir()
(install_dir / "chitin.key").write_bytes(b"key")
assert is_kotor_install_dir(install_dir) is True


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

mismatched = tmp_path / "kotor"
assert is_kotor_install_dir(mismatched) is True


def test_tslpatcher_engine_is_kotor_install_dir_matches_cli_utils(tmp_path: Path) -> None:
from pykotor.tslpatcher.diff.engine import is_kotor_install_dir as engine_is_install

install_dir = tmp_path / "install"
install_dir.mkdir()
(install_dir / "chitin.key").write_bytes(b"key")

assert engine_is_install(install_dir) == is_kotor_install_dir(install_dir)
Loading