Files
UnheardCity/tests/conftest.py
Cristian Gora 1ccaa8b398 Full correctness check against the docs: safer writes, reverts and texts
Safety
- Writes are serialized (Workspace.lock): two background jobs rebuilding one
  package (a sound and its subtitle applied side by side) lost an edit.
- A store copies a bank file or package as "original" only if it matches the
  shipped catalog (Workspace.unoriginal_files: in-memory sounds, bank copies of
  voice lines, subtitles); the editor refuses to switch stores while changes
  are applied. A second store could otherwise resurrect a reverted sound.
- Mod import in the editor asks before overwriting files changed outside the
  tool (it forced silently).
- Revert all in the editor reverts texts too; the uninstaller counts text
  edits before offering to delete the store.
- ackit restore-backup: the full-backup restore decisions.md described; it
  keeps the sounds of WADs without a full copy recorded.
- build_catalog also stops when a subtitle differs from the catalog.

Languages and texts
- Game.language() returns languages without voices (JPN, RUS, ...) and
  Game.voice_archive() their INT voices; ackit text --lang JPN works.
- Menu lookups parse one cached file (find & replace: minutes -> ms).
- Subtitles decode cp1252 as Windows does: the UTF-8-in-cp1252 line
  Speech_TAPE_J_Answer_1_00 (KOR/POL/POR/RUS) is written back byte-for-byte;
  SUB_KOR/SUB_RUS rebuilt from the original game (only those rows changed).
- Mods exported while another language is loaded keep name and line.

Other fixes
- Down-mix folds extra channels in at -3 dB (a 5.1 centre voice was dropped).
- e2e_editor no longer overwrites the user's settings.json; kill_game waits
  for the game to exit before reverts.
- Recorder handles Int32/UInt8 input and split frames; package block cache
  locked; conflict messages, CLI help examples, stale docstrings and doc
  references fixed; tests no longer read this PC's game language.

Docs (decisions, user guide, README, subtitles.md, banks.md, catalog README,
REPORT, NOTES, CLAUDE.md) updated; check_docs: 102 claims match. 148 tests;
e2e_features 9/9, e2e_editor and verify PASS; game original afterwards.
2026-10-13 21:34:13 +02:00

57 lines
1.7 KiB
Python

import os
import shutil
import sys
import pytest
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, ROOT)
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
@pytest.fixture(autouse=True)
def isolated_home(tmp_path, monkeypatch):
"""User data/config/cache go to a temp folder (never touch the real settings or stores), and the language
the game is set to on this machine (Documents\\WB Games\\...\\UserEngine.ini) does not leak into tests."""
from ackit import game as G
monkeypatch.setenv("ACKIT_HOME", str(tmp_path / "home"))
real = G.Game.config_dirs
mine = os.path.normcase(os.path.join(os.path.expanduser("~"), "Documents", "WB Games"))
monkeypatch.setattr(G.Game, "config_dirs",
lambda self: [d for d in real(self) if not os.path.normcase(d).startswith(mine)])
yield
@pytest.fixture(scope="session")
def synth_template(tmp_path_factory):
import synth
d = tmp_path_factory.mktemp("synth_template")
originals = synth.make_game(str(d))
return str(d), originals
@pytest.fixture
def synth_game(synth_template, tmp_path):
"""A fresh copy of the synthetic game folder for each test -> (root, originals)."""
src, originals = synth_template
dst = str(tmp_path / "game")
shutil.copytree(src, dst)
return dst, originals
def _real_game():
from ackit.game import find_installs
try:
found = find_installs()
except Exception:
found = []
return found[0] if found else None
@pytest.fixture(scope="session")
def real_game_dir():
d = os.environ.get("ACKIT_TEST_GAME") or _real_game()
if not d:
pytest.skip("real game not installed")
return d