- Fixed undefined 'tool' variable in display_history function - Changed '[tool]' markup tag usage to proper Rich syntax - All tests now pass (38/38 unit tests) - Type checking passes with mypy --strict
264 lines
7.4 KiB
Python
264 lines
7.4 KiB
Python
"""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 "<!DOCTYPE html>" in result
|
|
assert "<title>" 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()
|