1
0
Fork 0
Code Issues Pull requests Projects Releases 2 Packages Wiki Activity Actions Pages
DocForge2/tests/test_cli.py

109 lines
4.3 KiB
Python

from __future__ import annotations
import os
import shutil
import tempfile
import threading
import time
import unittest
from pathlib import Path
from unittest import mock
from docforge.changesets import ChangesetStore
from docforge.cli import _parser, _run
from docforge.project import Project
from docforge.viewer_manager import ViewerManager
ROOT = Path(__file__).resolve().parents[1]
FIXTURES = ROOT / "tests" / "fixtures"
class DocForgeCliTests(unittest.TestCase):
def copy_fixture(self, destination: Path) -> Path:
root = destination / "alpha"
shutil.copytree(FIXTURES / "alpha", root)
return root
def test_reindex_apply_and_visualization_commands_are_self_service(self) -> None:
with tempfile.TemporaryDirectory() as directory:
parent = Path(directory)
root = self.copy_fixture(parent)
parser = _parser()
reindexed = _run(parser.parse_args(["--project-root", str(root), "reindex"]))
self.assertTrue(reindexed["reindexed"])
synchronized = _run(parser.parse_args(["--project-root", str(root), "sync"]))
self.assertEqual("current", synchronized["synchronization"]["action"])
project = Project.open(root)
store = ChangesetStore(project, "alpha-editor")
node = next(node for node in project.load().nodes if node.node_id == "guide.workflow")
created = store.create("cli-apply")
proposed = store.propose_update(
changeset_id="cli-apply",
expected_changeset_hash=str(created["changeset_hash"]),
node_id=node.node_id,
expected_content_hash=node.content_hash,
metadata={"summary": "Applied through the CLI."},
content=None,
relationship_changes=[],
rationale="Verify the direct application command.",
)
applied = _run(
parser.parse_args(
[
"--project-root",
str(root),
"apply",
"cli-apply",
"--changeset-hash",
str(proposed["changeset_hash"]),
"--applier",
"alpha-editor",
]
)
)
self.assertTrue(applied["applied"])
state_path = parent / "viewer-manager.json"
manager = ViewerManager(state_path, check_interval_seconds=0.02)
thread = threading.Thread(target=manager.serve_forever, daemon=True)
previous = os.environ.get("DOCFORGE_VIEWER_MANAGER_STATE")
os.environ["DOCFORGE_VIEWER_MANAGER_STATE"] = str(state_path)
thread.start()
deadline = time.monotonic() + 2
while not state_path.exists() and time.monotonic() < deadline:
time.sleep(0.01)
try:
with mock.patch("docforge.cli.webbrowser.open", return_value=True) as opened:
visualized = _run(
parser.parse_args(
[
"--project-root",
str(root),
"visualize",
"--node",
"guide.workflow",
]
)
)
self.assertTrue(visualized["opened_browser"])
opened.assert_called_once()
status = _run(
parser.parse_args(["--project-root", str(root), "visualization-status"])
)
self.assertEqual("running", status["state"])
stopped = _run(
parser.parse_args(["--project-root", str(root), "visualization-stop"])
)
self.assertEqual("stopped", stopped["state"])
finally:
manager.shutdown()
thread.join(timeout=2)
if previous is None:
os.environ.pop("DOCFORGE_VIEWER_MANAGER_STATE", None)
else:
os.environ["DOCFORGE_VIEWER_MANAGER_STATE"] = previous
if __name__ == "__main__":
unittest.main()