import contextlib import io import json import re import shlex import unittest from pathlib import Path from types import SimpleNamespace from scripts import run_offline_checks from scripts import run_training_case_package as training_cli ROOT = Path(__file__).resolve().parents[2] README = ROOT / "README.md" TRAINING_PUBLIC_DOC = ROOT / "docs" / "training_console_public_surface_v1.md" DOC_EXAMPLE = ROOT / "docs" / "examples" / "training_case_package_smoke_m6.md" FIXTURE = ROOT / "tests" / "fixtures" / "training_case_package_m6.json" FIXTURE_REF = "tests/fixtures/training_case_package_m6.json" PACKAGE_SMOKE_COMMAND = ".venv/bin/python scripts/run_training_case_package.py" OFFLINE_CHECK_COMMAND = ".venv/bin/python scripts/run_offline_checks.py" def _documented_command_parts() -> list[str]: text = DOC_EXAMPLE.read_text(encoding="utf-8") match = re.search(r"```bash\n(?P.*?)\n```", text, flags=re.DOTALL) if match is None: raise AssertionError("missing documented package smoke command") return shlex.split(re.sub(r"\\\n\s*", " ", match.group("command").strip())) class TrainingCaseDocsCliM10Tests(unittest.TestCase): def test_example_doc_uses_current_public_fixture_and_cli(self) -> None: parts = _documented_command_parts() self.assertEqual(parts[:3], [".venv/bin/python", "scripts/run_training_case_package.py", "--input"]) self.assertIn(FIXTURE_REF, parts) self.assertIn("--output", parts) def test_example_doc_publishes_current_public_smoke_wording(self) -> None: text = DOC_EXAMPLE.read_text(encoding="utf-8") for snippet in ( "import/export smoke", "public package", "public export", "public output", "one-line JSON", "input_file_not_found", "input_path_is_directory", "output_path_is_directory", "output_path_unwritable", ): self.assertIn(snippet, text) def test_training_public_doc_references_console_and_api_surface(self) -> None: text = TRAINING_PUBLIC_DOC.read_text(encoding="utf-8") for snippet in ( "The public browser entry is `/training`.", "The trading workbench stays at `/`.", "| GET | `/training/cases` |", "| GET | `/training/progress` |", "Training public error catalog:", PACKAGE_SMOKE_COMMAND, ): self.assertIn(snippet, text) def test_readme_points_to_current_offline_checks_and_training_console(self) -> None: text = README.read_text(encoding="utf-8") for snippet in ( OFFLINE_CHECK_COMMAND, "Training Console at `/training`", "training_console_js_syntax", "python3 scripts/run_api_server.py", ): self.assertIn(snippet, text) self.assertNotIn("training_case_engine_m1_m6_product_readme.md", text) def test_offline_checks_registry_includes_both_web_entries(self) -> None: commands = dict(run_offline_checks.build_check_commands(env={})) self.assertEqual(commands["dashboard_js_syntax"], ["node", "--check", "src/web/app.js"]) self.assertEqual(commands["training_console_js_syntax"], ["node", "--check", "src/web/training.js"]) def test_offline_checks_json_and_node_skip_behavior_cover_new_training_check(self) -> None: def fake_runner(command, **_kwargs): return SimpleNamespace(returncode=0, stdout="ok\n", stderr="") output = io.StringIO() with contextlib.redirect_stdout(output): exit_code = run_offline_checks.run_checks( commands=[("training_console_js_syntax", ["node", "--check", "src/web/training.js"])], runner=fake_runner, node_available=False, env={}, ) self.assertEqual(exit_code, 0) self.assertIn("Offline check skipped: training_console_js_syntax", output.getvalue()) def test_package_cli_still_emits_one_line_public_json(self) -> None: output = io.StringIO() with contextlib.redirect_stdout(output): exit_code = training_cli.main(["--input", str(FIXTURE)]) summary = json.loads(output.getvalue()) self.assertEqual(exit_code, 0) self.assertTrue(summary["passed"]) self.assertTrue(str(summary["input"]).endswith("tests\\fixtures\\training_case_package_m6.json")) self.assertIsNone(summary["output"]) if __name__ == "__main__": unittest.main()