@@ -0,0 +1,83 @@
|
||||
import importlib.util
|
||||
import io
|
||||
import tempfile
|
||||
import unittest
|
||||
from contextlib import redirect_stderr, redirect_stdout
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SCRIPT_PATH = (
|
||||
Path(__file__).resolve().parents[1]
|
||||
/ "scripts"
|
||||
/ "build_index.py"
|
||||
)
|
||||
|
||||
|
||||
def load_script():
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
"tsl_codegen_function_index", SCRIPT_PATH
|
||||
)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
class FunctionIndexTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp_dir = tempfile.TemporaryDirectory()
|
||||
self.skill_dir = Path(self.temp_dir.name) / "tsl-api-reference"
|
||||
self.codegen_root = self.skill_dir / "references" / "codegen"
|
||||
self.data_dir = self.skill_dir / "data"
|
||||
leaf = self.codegen_root / "builtin" / "base" / "array.md"
|
||||
leaf.parent.mkdir(parents=True)
|
||||
leaf.write_text(
|
||||
"# Builtin - 基础 / 数组\n\n"
|
||||
"## `demo()`\n\n"
|
||||
"<!-- tags: 数组 列表 -->\n\n"
|
||||
"返回示例值。\n\n"
|
||||
"返回:integer\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
self.module = load_script()
|
||||
|
||||
def tearDown(self):
|
||||
self.temp_dir.cleanup()
|
||||
|
||||
def run_main(self, *args):
|
||||
stdout = io.StringIO()
|
||||
stderr = io.StringIO()
|
||||
with redirect_stdout(stdout), redirect_stderr(stderr):
|
||||
result = self.module.main(["--skill-dir", str(self.skill_dir), *args])
|
||||
return result, stdout.getvalue(), stderr.getvalue()
|
||||
|
||||
def test_rebuild_writes_only_tsv(self):
|
||||
result, _, _ = self.run_main()
|
||||
|
||||
self.assertEqual(0, result)
|
||||
self.assertTrue((self.data_dir / "function_index.tsv").is_file())
|
||||
self.assertEqual([], list(self.codegen_root.rglob("index.md")))
|
||||
|
||||
def test_tags_and_summary_are_stored_separately(self):
|
||||
rows = self.module.build_rows(self.codegen_root)
|
||||
row = dict(zip(self.module.HEADER, rows[0]))
|
||||
|
||||
self.assertEqual("数组 列表", row["tags"])
|
||||
self.assertEqual("返回示例值。", row["summary"])
|
||||
|
||||
def test_check_does_not_require_index_pages(self):
|
||||
self.data_dir.mkdir(parents=True)
|
||||
rows = self.module.build_rows(self.codegen_root)
|
||||
(self.data_dir / "function_index.tsv").write_text(
|
||||
self.module.render_tsv(rows),
|
||||
encoding="utf-8",
|
||||
newline="\n",
|
||||
)
|
||||
|
||||
result, stdout, _ = self.run_main("--check")
|
||||
|
||||
self.assertEqual(0, result)
|
||||
self.assertIn("matches md tree", stdout)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,85 @@
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SCRIPT = Path(__file__).parents[1] / "scripts" / "generate.py"
|
||||
|
||||
|
||||
class DocGenCliTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp_dir = tempfile.TemporaryDirectory()
|
||||
self.root = Path(self.temp_dir.name)
|
||||
self.input = self.root / "entry.json"
|
||||
self.input.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"module": "项目 / 示例",
|
||||
"path": "base/my_functions",
|
||||
"functions": [
|
||||
{
|
||||
"signature": "demo()",
|
||||
"desc": "示例函数。",
|
||||
"returns": "nil",
|
||||
}
|
||||
],
|
||||
},
|
||||
ensure_ascii=False,
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
self.temp_dir.cleanup()
|
||||
|
||||
def run_cli(self, *args):
|
||||
return subprocess.run(
|
||||
[sys.executable, str(SCRIPT), str(self.input), *args],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
cwd=self.root,
|
||||
)
|
||||
|
||||
def test_default_scope_writes_configured_path_under_project(self):
|
||||
result = self.run_cli()
|
||||
output = (
|
||||
self.root
|
||||
/ "skills"
|
||||
/ "tsl-api-reference"
|
||||
/ "references"
|
||||
/ "codegen"
|
||||
/ "project"
|
||||
/ "base"
|
||||
/ "my_functions.md"
|
||||
)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertTrue(output.is_file())
|
||||
self.assertTrue(output.read_text(encoding="utf-8").startswith("# 项目 / 示例\n"))
|
||||
|
||||
def test_custom_scope_changes_first_destination_directory(self):
|
||||
result = self.run_cli("--scope", "my-project")
|
||||
output = (
|
||||
self.root
|
||||
/ "skills"
|
||||
/ "tsl-api-reference"
|
||||
/ "references"
|
||||
/ "codegen"
|
||||
/ "my-project"
|
||||
/ "base"
|
||||
/ "my_functions.md"
|
||||
)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertTrue(output.is_file())
|
||||
|
||||
def test_output_option_is_rejected(self):
|
||||
result = self.run_cli("--output", str(self.root / "out.md"))
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("unrecognized arguments: --output", result.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,43 @@
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SCRIPT = Path(__file__).parents[1] / "scripts" / "lint.py"
|
||||
VALID_PAGE = "# 项目 / 示例\n\n## `demo()`\n\n示例函数\n\n返回:nil\n"
|
||||
|
||||
|
||||
class DocLintCliTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp_dir = tempfile.TemporaryDirectory()
|
||||
self.root = Path(self.temp_dir.name)
|
||||
self.page = self.root / "base" / "demo.md"
|
||||
self.page.parent.mkdir()
|
||||
self.page.write_text(VALID_PAGE, encoding="utf-8")
|
||||
|
||||
def tearDown(self):
|
||||
self.temp_dir.cleanup()
|
||||
|
||||
def run_cli(self, *args):
|
||||
return subprocess.run(
|
||||
[sys.executable, str(SCRIPT), *map(str, args)],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
def test_accepts_one_markdown_file(self):
|
||||
result = self.run_cli("--file", self.page)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertIn("1 files", result.stderr)
|
||||
|
||||
def test_accepts_one_directory(self):
|
||||
result = self.run_cli("--dir", self.root)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertIn("1 files", result.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,40 @@
|
||||
import importlib.util
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SCRIPT = (
|
||||
Path(__file__).resolve().parents[3]
|
||||
/ "skills"
|
||||
/ "tsl-api-reference"
|
||||
/ "scripts"
|
||||
/ "lookup.py"
|
||||
)
|
||||
|
||||
|
||||
def load_script():
|
||||
spec = importlib.util.spec_from_file_location("tsl_lookup", SCRIPT)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
class LookupTest(unittest.TestCase):
|
||||
def test_keyword_search_includes_tags_and_summary(self):
|
||||
module = load_script()
|
||||
rows = [
|
||||
{
|
||||
"name": "demo",
|
||||
"signature": "demo()",
|
||||
"module": "base",
|
||||
"tags": "数组 列表",
|
||||
"summary": "返回示例值",
|
||||
}
|
||||
]
|
||||
|
||||
self.assertEqual(rows, module.search_keyword(rows, ["数组"]))
|
||||
self.assertEqual(rows, module.search_keyword(rows, ["返回示例"]))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user