DazedTL/tests/test_workflow_prompts.py

135 lines
6 KiB
Python

"""Regression tests for concise, interactive plugin translation prompts."""
import unittest
from pathlib import Path
from util.skills import load_clipboard_skill, load_project_setup
ROOT = Path(__file__).resolve().parents[1]
class WorkflowTranslationPromptTests(unittest.TestCase):
def _assert_interactive_in_place_prompt(self, prompt: str):
lowered = prompt.casefold()
self.assertIn("do not edit anything yet", lowered)
self.assertIn("ask one focused question", lowered)
self.assertIn("offer to translate all safe items yourself", lowered)
self.assertIn("edit approved", lowered)
self.assertIn("never paste or repost an entire", lowered)
self.assertIn("minimal unified diff", lowered)
self.assertNotIn("complete replacement", lowered)
self.assertNotIn("full translated file", lowered)
def test_mvmz_prompt_audits_enabled_plugins_before_editing(self):
prompt = load_clipboard_skill("plugin_translation.md")
self._assert_interactive_in_place_prompt(prompt)
self.assertIn("js/plugins.js", prompt)
self.assertIn("js/plugins/<PluginName>.js", prompt)
self.assertIn("which listed plugins should you translate", prompt)
def test_ace_prompt_audits_scripts_before_editing(self):
prompt = load_clipboard_skill("ace_script_translation.md")
self._assert_interactive_in_place_prompt(prompt)
self.assertIn("ace_json/scripts/*.rb", prompt)
self.assertIn("which listed scripts should you translate", prompt)
self.assertIn("Ruby interpolation (#{...})", prompt)
def test_rpgmaker_qa_prompt_scales_and_requires_approval(self):
prompt = load_clipboard_skill("rpgmaker_translation_qa.md")
lowered = prompt.casefold()
self.assertIn("mechanically check 100%", lowered)
self.assertIn("deterministic stratified sample", lowered)
self.assertIn("control-code scope and placement", lowered)
self.assertIn("enabled plugin code consumes a 108/408 comment block", lowered)
self.assertIn("do not edit during the first pass", lowered)
self.assertIn("stop and wait for approval", lowered)
self.assertIn("never modify or remove `_original`", lowered)
for placeholder in (
"{{GAME_DATA_FOLDER}}",
"{{GAME_ROOT}}",
"{{VOCAB_FILE}}",
):
self.assertIn(placeholder, prompt)
def test_rpgmaker_project_setup_recommends_408_and_layout_geometry(self):
prompt = load_project_setup("rpgmaker")
lowered = prompt.casefold()
self.assertIn("code408 : enable|skip", lowered)
self.assertIn("translate code 408 plugin/comment text", lowered)
self.assertIn("dialogue : width=", lowered)
self.assertIn("facewidth=<code-101 face width>", lowered)
self.assertIn("list/help: listwidth=", lowered)
self.assertIn("notes : notewidth=", lowered)
self.assertIn("face/portrait reservation", lowered)
self.assertIn("applicable line height", lowered)
self.assertIn("pagination/manual reflow", lowered)
wolf_prompt = load_project_setup("wolf")
self.assertNotIn("code408 : enable|skip", wolf_prompt.casefold())
def test_phase1_code408_is_user_controlled(self):
from gui.workflow_tab import PHASE1_CONFIG
self.assertFalse(PHASE1_CONFIG["CODE408"])
workflow_source = (ROOT / "gui/workflow_tab.py").read_text(encoding="utf-8")
self.assertIn("Translate code 408 plugin/comment text", workflow_source)
self.assertIn('config["CODE408"] = bool(', workflow_source)
def test_static_clipboard_prompts_live_under_data_skills(self):
expected = (
"wrap_config.md",
"plugin_translation.md",
"ace_script_translation.md",
"rpgmaker_translation_qa.md",
"image_translation.md",
"risky_codes.md",
"wolf_speakers.md",
)
for name in expected:
with self.subTest(name=name):
self.assertTrue(load_clipboard_skill(name).strip())
workflow_source = (ROOT / "gui/workflow_tab.py").read_text(encoding="utf-8")
wolf_source = (ROOT / "gui/wolf_workflow_tab.py").read_text(encoding="utf-8")
for constant in (
"_WRAP_PROMPT",
"_PLUGINS_JS_TRANSLATE_PROMPT",
"_ACE_SCRIPTS_TRANSLATE_PROMPT",
"_PLUGIN_PROMPT",
):
self.assertNotIn(constant, workflow_source)
self.assertNotIn("_WOLF_SPEAKER_PROMPT", wolf_source)
self.assertIn("QA Game Data Skill", workflow_source)
self.assertIn('load_clipboard_skill("rpgmaker_translation_qa.md")', workflow_source)
def test_wrap_prompt_accounts_for_code101_faces_and_font_changes(self):
prompt = load_clipboard_skill("wrap_config.md").casefold()
self.assertIn("facewidth", prompt)
self.assertIn("non-empty parameter 0", prompt)
self.assertIn("plugin portraits", prompt)
self.assertIn("pagination/manual reflow", prompt)
self.assertIn("rendered line count", prompt)
self.assertIn("visible-row limit", prompt)
self.assertIn("simultaneous constraints", prompt)
self.assertIn("narrower wrapping usually creates more lines", prompt)
def test_image_translation_prompt_ends_skips_with_recovery_options(self):
prompt = load_clipboard_skill("image_translation.md")
self.assertIn("### Skipped / review items", prompt)
self.assertIn("literal final section of the user-facing response", prompt)
self.assertIn("Try it anyway", prompt)
self.assertIn("Use generative AI", prompt)
self.assertIn("Provide clean source art or layers", prompt)
self.assertIn("Manual artist review", prompt)
self.assertIn("If nothing was skipped or marked for review, omit", prompt)
def test_clipboard_skill_loader_rejects_paths(self):
with self.assertRaises(ValueError):
load_clipboard_skill("../system.md")
if __name__ == "__main__":
unittest.main()