"""迁移内部脚本的最小行为测试。""" from __future__ import annotations import importlib.util import hashlib import json import tempfile import unittest from pathlib import Path SCRIPT_ROOT = Path(__file__).parents[1] / "scripts" def load_module(name: str): """从脚本路径加载模块,避免要求项目安装为 Python 包。""" spec = importlib.util.spec_from_file_location(name, SCRIPT_ROOT / f"{name}.py") module = importlib.util.module_from_spec(spec) assert spec.loader spec.loader.exec_module(module) return module scan_sources = load_module("scan_sources") check_skill = load_module("check_skill") update_lock = load_module("update_lock") class MigrationScriptTests(unittest.TestCase): def test_scan_uses_relative_paths_and_stable_hash(self): with tempfile.TemporaryDirectory() as directory: root = Path(directory) skill = root / "group" / "demo" skill.mkdir(parents=True) (skill / "SKILL.md").write_text( "---\nname: demo\ndescription: 示例\n---\n", encoding="utf-8" ) first = scan_sources.scan_source("source-a", root) second = scan_sources.scan_source("source-a", root) self.assertEqual("group/demo", first["skills"][0]["relativePath"]) self.assertEqual(first["skills"][0]["sha256"], second["skills"][0]["sha256"]) self.assertNotIn(str(root), json.dumps(first, ensure_ascii=False)) def test_check_reports_name_mismatch_and_forbidden_term(self): with tempfile.TemporaryDirectory() as directory: root = Path(directory) / "expected" root.mkdir() (root / "SKILL.md").write_text( "---\nname: other\ndescription: 示例\n---\n内部标识", encoding="utf-8", ) result = check_skill.check_skill(root, ["内部标识"]) codes = {issue["code"] for issue in result["issues"]} self.assertIn("name-path-mismatch", codes) self.assertIn("forbidden:内部标识", codes) def test_update_lock_preserves_manual_fields(self): path_hash = hashlib.sha256("group/demo".encode("utf-8")).hexdigest() key = f"source-a:{path_hash[:16]}" lock = { "schemaVersion": 1, "sources": {}, "skills": { key: { "status": "specified", "target": "plugins/skill/skills/demo", } }, } report = { "sources": [ { "id": "source-a", "commit": "abc", "skillCount": 1, "skills": [ { "name": "demo", "relativePath": "group/demo", "sha256": "123", } ], } ] } merged = update_lock.merge(lock, report) entry = merged["skills"][key] self.assertEqual("specified", entry["status"]) self.assertEqual("plugins/skill/skills/demo", entry["target"]) self.assertEqual("123", entry["sourceSha256"]) self.assertNotIn("name", entry) if __name__ == "__main__": unittest.main()