138 lines
5.1 KiB
Python
138 lines
5.1 KiB
Python
import os
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = os.path.abspath(os.path.dirname(__file__))
|
|
sys.path.insert(0, ROOT)
|
|
|
|
from generate_handbook import generate_markdown_handbook
|
|
|
|
|
|
def write_text(path: Path, content: str) -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(content, encoding="utf-8")
|
|
|
|
|
|
class GenerateHandbookTest(unittest.TestCase):
|
|
def test_generates_markdown_without_removing_images(self):
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
root = Path(temp_dir)
|
|
src_root = root / "components"
|
|
docs_root = root / "docs" / "source" / "mxpic" / "components"
|
|
image_root = root / "docs" / "source" / "images"
|
|
|
|
write_text(
|
|
src_root / "primitives" / "pic" / "device.py",
|
|
'''
|
|
class ExistingImage:
|
|
"""A class with a matching generated picture."""
|
|
|
|
|
|
class MissingImage:
|
|
"""A class without a picture."""
|
|
|
|
|
|
class ExistingImage:
|
|
"""A duplicate class name that should be documented once."""
|
|
|
|
|
|
def public_function():
|
|
"""A public function."""
|
|
|
|
|
|
def public_function():
|
|
"""A duplicate function name that should be documented once."""
|
|
|
|
|
|
def _hidden_function():
|
|
"""A private function."""
|
|
''',
|
|
)
|
|
write_text(src_root / "basic.py", "CONSTANT = 1\n")
|
|
write_text(src_root / "primitives" / "__init__.py", "")
|
|
|
|
image_path = image_root / "pic" / "ExistingImage.png"
|
|
image_path.parent.mkdir(parents=True, exist_ok=True)
|
|
image_path.write_bytes(b"fake png")
|
|
write_text(docs_root / "old" / "stale.md", "# Stale\n")
|
|
|
|
modules = generate_markdown_handbook(
|
|
src_root=src_root,
|
|
docs_root=docs_root,
|
|
image_root=image_root,
|
|
package_root="fake.components",
|
|
)
|
|
|
|
self.assertEqual(len(modules), 2)
|
|
self.assertTrue(image_path.exists())
|
|
self.assertFalse((docs_root / "old" / "stale.md").exists())
|
|
|
|
device_page = (docs_root / "primitives" / "pic" / "device.md").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
self.assertIn("# fake.components.primitives.pic.device", device_page)
|
|
self.assertIn(".. autoclass:: fake.components.primitives.pic.device.ExistingImage", device_page)
|
|
self.assertEqual(
|
|
device_page.count(".. autoclass:: fake.components.primitives.pic.device.ExistingImage"),
|
|
1,
|
|
)
|
|
self.assertIn(".. image:: ../../../../images/pic/ExistingImage.png", device_page)
|
|
self.assertIn(".. autoclass:: fake.components.primitives.pic.device.MissingImage", device_page)
|
|
self.assertNotIn(".. image:: MissingImage.png", device_page)
|
|
self.assertIn(".. autofunction:: fake.components.primitives.pic.device.public_function", device_page)
|
|
self.assertEqual(
|
|
device_page.count(".. autofunction:: fake.components.primitives.pic.device.public_function"),
|
|
1,
|
|
)
|
|
self.assertNotIn("_hidden_function", device_page)
|
|
|
|
basic_page = (docs_root / "basic.md").read_text(encoding="utf-8")
|
|
self.assertIn(".. automodule:: fake.components.basic", basic_page)
|
|
|
|
def test_recursive_indexes_point_to_existing_generated_pages(self):
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
root = Path(temp_dir)
|
|
src_root = root / "components"
|
|
docs_root = root / "docs" / "source" / "mxpic" / "components"
|
|
|
|
write_text(src_root / "basic.py", "def make_basic():\n return None\n")
|
|
write_text(src_root / "primitives" / "pic" / "device.py", "class Device:\n pass\n")
|
|
|
|
generate_markdown_handbook(
|
|
src_root=src_root,
|
|
docs_root=docs_root,
|
|
image_root=root / "docs" / "source" / "images",
|
|
package_root="fake.components",
|
|
)
|
|
|
|
root_index = (docs_root / "index.md").read_text(encoding="utf-8")
|
|
primitives_index = (docs_root / "primitives" / "index.md").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
pic_index = (docs_root / "primitives" / "pic" / "index.md").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
|
|
self.assertIn("basic", root_index)
|
|
self.assertIn("primitives/index", root_index)
|
|
self.assertIn("pic/index", primitives_index)
|
|
self.assertIn("device", pic_index)
|
|
self.assert_toctree_entries_exist(docs_root)
|
|
|
|
def assert_toctree_entries_exist(self, docs_root: Path) -> None:
|
|
for index_path in docs_root.rglob("index.md"):
|
|
for line in index_path.read_text(encoding="utf-8").splitlines():
|
|
entry = line.strip()
|
|
if not entry or entry.startswith(("#", ":", "```")):
|
|
continue
|
|
|
|
target = index_path.parent / f"{entry}.md"
|
|
self.assertTrue(target.exists(), f"{index_path} points to missing {target}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|