diff --git a/docforge/cli/commands.py b/docforge/cli/commands.py index 34585e3..6cb7975 100644 --- a/docforge/cli/commands.py +++ b/docforge/cli/commands.py @@ -2,8 +2,9 @@ import click from pathlib import Path from typing import Sequence, Optional from docforge.loaders import GriffeLoader -from docforge.cli.mkdocs import logic as mkdocs_logic -from docforge.cli.mcp import logic as mcp_logic +from docforge.cli import mkdocs_utils +from docforge.cli import mcp_utils + @click.group() def cli() -> None: @@ -13,6 +14,7 @@ def cli() -> None: """ pass + @cli.command() @click.option("--mcp", is_flag=True, help="Build MCP resources") @click.option("--mkdocs", is_flag=True, help="Build MkDocs site") @@ -21,7 +23,8 @@ def cli() -> None: # MkDocs specific @click.option("--site-name", help="MkDocs site name") @click.option("--docs-dir", type=click.Path(path_type=Path), default=Path("docs"), help="Directory for MD sources") -@click.option("--nav", "nav_file", type=click.Path(path_type=Path), default=Path("docforge.nav.yml"), help="Nav spec path") +@click.option("--nav", "nav_file", type=click.Path(path_type=Path), default=Path("docforge.nav.yml"), + help="Nav spec path") @click.option("--template", type=click.Path(path_type=Path), help="MkDocs template path") @click.option("--mkdocs-yml", type=click.Path(path_type=Path), default=Path("mkdocs.yml"), help="Output config path") # MCP specific @@ -49,25 +52,26 @@ def build( raise click.UsageError("--module is required for MkDocs build") if not site_name: site_name = module - + click.echo(f"Generating MkDocs sources in {docs_dir}...") - mkdocs_logic.generate_sources(module, project_name, docs_dir) - + mkdocs_utils.generate_sources(module, project_name, docs_dir) + click.echo(f"Generating MkDocs config {mkdocs_yml}...") - mkdocs_logic.generate_config(docs_dir, nav_file, template, mkdocs_yml, site_name) - + mkdocs_utils.generate_config(docs_dir, nav_file, template, mkdocs_yml, site_name) + click.echo("Running MkDocs build...") - mkdocs_logic.build(mkdocs_yml) + mkdocs_utils.build(mkdocs_yml) click.echo("MkDocs build completed.") if mcp: if not module: raise click.UsageError("--module is required for MCP build") - + click.echo(f"Generating MCP resources in {out_dir}...") - mcp_logic.generate_resources(module, project_name, out_dir) + mcp_utils.generate_resources(module, project_name, out_dir) click.echo("MCP build completed.") + @cli.command() @click.option("--mcp", is_flag=True, help="Serve MCP documentation") @click.option("--mkdocs", is_flag=True, help="Serve MkDocs site") @@ -88,9 +92,10 @@ def serve( raise click.UsageError("Must specify either --mcp or --mkdocs") if mkdocs: - mkdocs_logic.serve(mkdocs_yml) + mkdocs_utils.serve(mkdocs_yml) elif mcp: - mcp_logic.serve(out_dir) + mcp_utils.serve(out_dir) + @cli.command() @click.option( @@ -120,6 +125,7 @@ def tree( for obj in module.get_all_objects(): _print_object(obj, indent="│ ") + def _print_object(obj, indent: str) -> None: """ Recursive helper to print doc objects and their members to the console. diff --git a/docforge/cli/mcp/__init__.py b/docforge/cli/mcp/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/docforge/cli/mcp/logic.py b/docforge/cli/mcp_utils.py similarity index 100% rename from docforge/cli/mcp/logic.py rename to docforge/cli/mcp_utils.py diff --git a/docforge/cli/mkdocs/__init__.py b/docforge/cli/mkdocs/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/docforge/cli/mkdocs/logic.py b/docforge/cli/mkdocs_utils.py similarity index 100% rename from docforge/cli/mkdocs/logic.py rename to docforge/cli/mkdocs_utils.py diff --git a/tests/cli/test_build_mcp.py b/tests/cli/test_build_mcp.py index 61e820a..f783945 100644 --- a/tests/cli/test_build_mcp.py +++ b/tests/cli/test_build_mcp.py @@ -1,6 +1,4 @@ -import json from pathlib import Path -from click.testing import CliRunner from docforge.cli.main import cli def test_mcp_build(cli_runner): diff --git a/tests/cli/test_build_mkdocs.py b/tests/cli/test_build_mkdocs.py index c0f6bdf..a84722f 100644 --- a/tests/cli/test_build_mkdocs.py +++ b/tests/cli/test_build_mkdocs.py @@ -48,7 +48,52 @@ def test_mkdocs_build_missing_module_fails(cli_runner): assert result.exit_code != 0 assert "--module is required" in result.output -def test_mkdocs_build_missing_site_name_fails(cli_runner): - result = cli_runner.invoke(cli, ["build", "--mkdocs", "--module", "testpkg"]) - assert result.exit_code != 0 - assert "--site-name is required" in result.output +def test_mkdocs_build_without_site_name_uses_module_as_default_full_flow( + cli_runner, + mock_mkdocs_build, + mock_mkdocs_load_config, +): + # Full integration test: real generation, real config, mocked mkdocs build + with cli_runner.isolated_filesystem(): + cwd = Path.cwd() + + # Create a minimal Python package + pkg = cwd / "testpkg" + pkg.mkdir() + (pkg / "__init__.py").write_text("") + (pkg / "mod.py").write_text("def f(): ...\n") + + # Create nav spec expected by generate_config + nav_file = cwd / "docforge.nav.yml" + nav_file.write_text( + "home: testpkg/index.md\ngroups: {}\n", + encoding="utf-8", + ) + + result = cli_runner.invoke( + cli, + [ + "build", + "--mkdocs", + "--module", + "testpkg", + "--docs-dir", + "docs", + "--mkdocs-yml", + "mkdocs.yml", + ], + ) + + assert result.exit_code == 0 + assert mock_mkdocs_build() is True + + # MkDocs config must exist + mkdocs_yml = cwd / "mkdocs.yml" + assert mkdocs_yml.exists() + + # Site name must default to module name + content = mkdocs_yml.read_text() + assert "site_name: testpkg" in content + + # Docs must be generated + assert (cwd / "docs" / "testpkg" / "mod.md").exists()