Files
pgames-manager/backend/tests/test_tomie_format.py
T
mrleo1nidandClaude Sonnet 5.5 12ec82c7e6 refactor: move game-specific import logic into profiles; unblock Tomie import
- Add app/games: GameProfile base, registry, ReaderHooks and renpy/naninovel/
  tomie profiles. pipeline, preflight, detect and mods dispatch via the registry
- Move tomie_* converter modules to app/games/tomie and split out reader hooks,
  import, mod validation and known defects
- Tolerate the 31 authoring defects of the pinned Tomie build as report
  warnings (exact list, per-script counts); any new defect still blocks import
- Frontend: runtime registry (runtimes.ts) with lazy Tomie launcher
- Add profile/registry tests and docs/GAME_PROFILES.md; update IMPORT.md

Full media export of the original Tomie build is not yet verified.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 11:35:23 +03:00

75 lines
4.1 KiB
Python

from types import SimpleNamespace
import pytest
def test_native_translation_and_mod_edits_rebuild_the_same_vm_input(tmp_path, monkeypatch):
from app import mods
from app.config import get_settings
from app.converter.nani_package import Package, text_records
from app.games.tomie.convert import convert_package
from app.games.tomie.format import unpack_modules
from app.games.tomie.profile import PROFILE
from app.translation import apply_changes, locale_tables, text_index
monkeypatch.setenv("DATA_DIR", str(tmp_path / "data"))
get_settings.cache_clear()
package = Package(profile=PROFILE, defaults={"points": 3}, function_data={"names": ["Tomie"]})
def script(name, label, commands):
return {"name": name, "lines": [{"line": 1, "label": label, "commands": commands}]}
package.scripts = {
"StartGameSetting": script("StartGameSetting", "Start", [
{"op": "PrintText", "args": {"Text": {"template": "Points: {points}"}}},
{"op": "ExitToTitle", "args": {}}]),
"MessagePlay": script("MessagePlay", "Start", [{"op": "Return", "args": {}}]),
"AppScreen": script("AppScreen", "Start", [{"op": "Stop", "args": {}}]),
}
package.texts = text_records("Tips", "tip:Title|Description {points}", "Tips")
media = {key: {} for key in ("backgrounds", "characters", "textures", "videos", "audio", "fonts")}
monkeypatch.setattr("app.games.tomie.convert.export_media", lambda *_: ({}, media, {}))
try:
result = convert_package(tmp_path, tmp_path / "work", lambda _: None, package)
index = text_index(result.manifest)
assert {line.source for line in index.lines} == {"Points: {points}", "Title", "Description {points}"}
line = next(line for line in index.lines if line.source.startswith("Points:"))
translated = apply_changes(result.manifest, "ru", lines={line.tid: {"t": "Баллы: {points}"}})
assert locale_tables(translated, "ru")[0][line.tid]["t"] == "Баллы: {points}"
doc = mods.document(translated)
mods.validate(doc, translated)
node = next(node for module in doc["scripts"].values() for label in module["labels"]
for node in label["body"] if node.get("tid") == line.tid)
node["what"] = "Score: {points}"
updated = mods.store(doc, translated)
runtime = unpack_modules(mods.document(updated)["scripts"])
assert runtime["StartGameSetting"]["commands"][0]["args"]["Text"] == {"template": "Score: {points}"}
module = next(module for module in doc["scripts"].values() if module.get("nani", {}).get("name") == "StartGameSetting")
module["labels"][0]["body"].insert(0, {"id": "inserted", "op": "nani_command", "command": {
"op": "SetCustomVariable", "args": {"Expression": "points+=1"}}})
assert unpack_modules(doc["scripts"])["StartGameSetting"]["labels"]["Start"] == 1
mods.validate(doc, translated)
node["command"]["op"] = "NativePlugin"
with pytest.raises(ValueError, match="NativePlugin"):
mods.validate(doc, translated)
finally:
get_settings.cache_clear()
def test_video_recovery_checks_ranges_and_copies_only_declared_bytes(tmp_path):
from app.games.tomie.assets import recover_object
data = tmp_path / "data"
out = tmp_path / "out"
data.mkdir(); out.mkdir()
original = b"header-clip-trailer"
(data / "resources.resource").write_bytes(original)
tree = {"m_OriginalPath": "Assets/Video/clip.webm", "m_ExternalResources": {
"m_Source": "resources.resource", "m_Offset": 7, "m_Size": 4}}
obj = SimpleNamespace(type=SimpleNamespace(name="VideoClip"), read=lambda: SimpleNamespace(m_Name="Clip"),
read_typetree=lambda: tree)
recovered = recover_object(obj, data, out, "video")
assert recovered["path"].read_bytes() == b"clip"
assert (data / "resources.resource").read_bytes() == original
tree["m_ExternalResources"]["m_Size"] = len(original)
with pytest.raises(ValueError, match="диапазон"):
recover_object(obj, data, out, "invalid")