"""Integration tests for the full documentation pipeline.""" import tempfile from pathlib import Path import pytest from click.testing import CliRunner from doc2man.cli import main from doc2man.parsers.python import parse_python_file from doc2man.parsers.go import parse_go_file from doc2man.parsers.javascript import parse_javascript_file from doc2man.generators.man import generate_man_page from doc2man.generators.markdown import generate_markdown from doc2man.generators.html import generate_html class TestFullPipeline: """Integration tests for the full documentation pipeline.""" def test_python_to_man_pipeline(self): """Test Python file -> parse -> generate man page.""" with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as f: f.write(b''' def greet(name, greeting="Hello"): """Greet a person with a custom greeting. Args: name: The name of the person to greet. greeting: The greeting word to use. Returns: The greeting string. Raises: ValueError: If name is empty. """ if not name: raise ValueError("Name cannot be empty") return f"{greeting}, {name}!" ''') f.flush() parsed = parse_python_file(Path(f.name)) assert parsed["language"] == "python" assert len(parsed["functions"]) == 1 with tempfile.NamedTemporaryFile(suffix=".1", delete=False) as out: output_path = Path(out.name) result = generate_man_page([{"file": str(f.name), "data": parsed}], output_path) assert ".TH" in result assert "NAME" in result assert "greet" in result.lower() output_path.unlink() Path(f.name).unlink() def test_python_to_markdown_pipeline(self): """Test Python file -> parse -> generate markdown.""" with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as f: f.write(b''' def calculate(a, b): """Calculate sum of two numbers. Args: a: First number. b: Second number. Returns: The sum of a and b. """ return a + b ''') f.flush() parsed = parse_python_file(Path(f.name)) with tempfile.NamedTemporaryFile(suffix=".md", delete=False) as out: output_path = Path(out.name) result = generate_markdown([{"file": str(f.name), "data": parsed}], output_path) assert "#" in result assert "calculate" in result.lower() assert "Parameters" in result output_path.unlink() Path(f.name).unlink() def test_python_to_html_pipeline(self): """Test Python file -> parse -> generate HTML.""" with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as f: f.write(b''' class Calculator: """A simple calculator class.""" def add(self, a, b): """Add two numbers. Args: a: First number. b: Second number. Returns: The sum. """ return a + b ''') f.flush() parsed = parse_python_file(Path(f.name)) with tempfile.NamedTemporaryFile(suffix=".html", delete=False) as out: output_path = Path(out.name) result = generate_html([{"file": str(f.name), "data": parsed}], output_path) assert "" in result assert "" in result assert "Calculator" in result output_path.unlink() Path(f.name).unlink() def test_go_pipeline(self): """Test Go file parsing and generation.""" with tempfile.NamedTemporaryFile(suffix=".go", delete=False) as f: f.write(b''' // Package math provides math utilities. // // This is a simple math package. package math // Add adds two integers. // // a: First integer // b: Second integer // // Returns: The sum func Add(a, b int) int { return a + b } ''') f.flush() parsed = parse_go_file(Path(f.name)) assert parsed["language"] == "go" assert len(parsed["functions"]) >= 1 Path(f.name).unlink() def test_javascript_pipeline(self): """Test JavaScript file parsing and generation.""" with tempfile.NamedTemporaryFile(suffix=".js", delete=False) as f: f.write(b''' /** * Multiplies two numbers. * * @param {number} a - First number * @param {number} b - Second number * @returns {number} The product */ function multiply(a, b) { return a * b; } ''') f.flush() parsed = parse_javascript_file(Path(f.name)) assert parsed["language"] == "javascript" assert len(parsed["functions"]) == 1 Path(f.name).unlink() def test_typescript_pipeline(self): """Test TypeScript file parsing and generation.""" with tempfile.NamedTemporaryFile(suffix=".ts", delete=False) as f: f.write(b''' /** * Divides two numbers. * * @param numerator - The numerator * @param denominator - The denominator * @returns The quotient */ function divide(numerator: number, denominator: number): number { return numerator / denominator; } ''') f.flush() parsed = parse_javascript_file(Path(f.name)) assert parsed["language"] == "javascript" assert len(parsed["functions"]) >= 1 Path(f.name).unlink() class TestCLIIntegration: """Integration tests for CLI commands.""" def test_cli_generate_command(self): """Test the full generate CLI command.""" with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as f: f.write(b''' def example(): """An example function.""" pass ''') f.flush() with tempfile.NamedTemporaryFile(suffix=".1", delete=False) as out: runner = CliRunner() result = runner.invoke(main, [ "generate", f.name, "--output", out.name, "--format", "man" ]) assert result.exit_code == 0 assert Path(out.name).exists() out_path = Path(out.name) assert out_path.stat().st_size > 0 out_path.unlink() Path(f.name).unlink() def test_cli_multiple_files(self): """Test generating from multiple files.""" with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as f1: f1.write(b''' def func1(): """First function.""" pass ''') f1.flush() with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as f2: f2.write(b''' def func2(): """Second function.""" pass ''') f2.flush() with tempfile.NamedTemporaryFile(suffix=".md", delete=False) as out: runner = CliRunner() result = runner.invoke(main, [ "generate", f1.name, f2.name, "--output", out.name, "--format", "markdown" ]) assert result.exit_code == 0 content = Path(out.name).read_text() assert "func1" in content or "func2" in content out_path = Path(out.name) out_path.unlink() Path(f1.name).unlink() Path(f2.name).unlink()