From 3ee141f0a3d6c1f8faba3a0a946d9be12ccc0a39 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 21 May 2026 10:07:35 +0000 Subject: [PATCH] test(pykotor): cover json-export ci progress and archive plaintext helper Co-authored-by: Boden --- .../PyKotor/tests/cli/test_json_commands.py | 56 +++++++++++++++++++ .../test_archive_serializer_regressions.py | 6 ++ 2 files changed, 62 insertions(+) diff --git a/Libraries/PyKotor/tests/cli/test_json_commands.py b/Libraries/PyKotor/tests/cli/test_json_commands.py index 67a02752f..9d5b321b2 100644 --- a/Libraries/PyKotor/tests/cli/test_json_commands.py +++ b/Libraries/PyKotor/tests/cli/test_json_commands.py @@ -6,6 +6,7 @@ from argparse import Namespace from pathlib import Path +from typing import TextIO, cast import pytest from loggerplus import RobustLogger @@ -27,7 +28,9 @@ from pykotor.resource.formats.tpc import TPC, TPCTextureFormat, bytes_tpc, read_tpc from pykotor.resource.type import ResourceType from pykotor.tools.resource_json import ( + _ExportProgressReporter, _serialize_mdl_face, + _supports_live_progress, export_installation_to_json_tree, iter_installation_resource_documents, serialize_file_resource_document, @@ -922,3 +925,56 @@ def fake_main(argv: list[str]) -> int: assert "--merge-module" in captured_argv assert captured_argv.count("--merge-path") == 2 assert "--merge-conflict-policy" in captured_argv + + +def test_supports_live_progress_false_when_ci_set(monkeypatch: pytest.MonkeyPatch) -> None: + """Regression: CI must disable carriage-return progress even if stderr is a TTY.""" + monkeypatch.setenv("CI", "true") + + class TtyStream: + def isatty(self) -> bool: + return True + + assert _supports_live_progress(TtyStream()) is False + + +def test_supports_live_progress_false_when_github_actions_set( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.delenv("CI", raising=False) + monkeypatch.setenv("GITHUB_ACTIONS", "yes") + + class TtyStream: + def isatty(self) -> bool: + return True + + assert _supports_live_progress(TtyStream()) is False + + +def test_export_progress_reporter_uses_logger_not_stream_when_ci_forces_non_tty( + monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, +) -> None: + """Regression: percentage milestones must reach logging (caplog/aggregators) in automation.""" + monkeypatch.setenv("CI", "true") + + class StrictTTY: + def isatty(self) -> bool: + return True + + def write(self, *_args: object, **_kwargs: object) -> None: + msg = "stream write must not be used when CI disables live progress" + raise AssertionError(msg) + + def flush(self) -> None: + msg = "stream flush must not be used when CI disables live progress" + raise AssertionError(msg) + + with caplog.at_level(logging.INFO): + progress = _ExportProgressReporter(RobustLogger(), 2, stream=cast(TextIO, StrictTTY())) + assert progress.live_updates is False + progress.update(1, "sample.txt") + progress.finish() + + combined = caplog.text + assert "50.00%" in combined and "sample.txt" in combined diff --git a/Libraries/PyKotor/tests/resource/formats/test_archive_serializer_regressions.py b/Libraries/PyKotor/tests/resource/formats/test_archive_serializer_regressions.py index de1278f6e..67b08871e 100644 --- a/Libraries/PyKotor/tests/resource/formats/test_archive_serializer_regressions.py +++ b/Libraries/PyKotor/tests/resource/formats/test_archive_serializer_regressions.py @@ -45,6 +45,12 @@ def test_resource_bytes_to_plaintext_gff_from_raw_bytes() -> None: assert payload["fields"]["SomeField"]["value"] == 42 +def test_resource_bytes_to_plaintext_returns_none_when_only_base64_embedding() -> None: + """When embedded mode cannot produce a structured/plain payload, helper returns None.""" + raw = bytes(range(256)) + assert _resource_bytes_to_plaintext(raw, ResourceType.WAV) is None + + def test_gff_json_writer_binary_field_is_base64_ascii() -> None: """Binary GFF fields must serialize to JSON-safe base64 strings.""" payload = b"\x00\xff\x01"