SmokeScan / tests /test_pdf_generator.py
KinetoLabs's picture
Initial commit: FDAM AI Pipeline v4.0.1
88bdcff
raw
history blame
6.99 kB
"""Tests for PDF generation module."""
import pytest
import tempfile
from pathlib import Path
from pipeline.pdf_generator import PDFGenerator, PDFResult, generate_sow_pdf, SOW_CSS
class TestPDFGenerator:
"""Test PDF generator functionality."""
@pytest.fixture
def generator(self):
"""Create PDF generator instance."""
return PDFGenerator()
@pytest.fixture
def sample_markdown(self):
"""Sample markdown for testing."""
return """# Test Document
## Section One
This is a test paragraph with **bold** and *italic* text.
| Column A | Column B |
|----------|----------|
| Value 1 | Value 2 |
| Value 3 | Value 4 |
## Section Two
- Bullet point one
- Bullet point two
- Bullet point three
---
*Generated by test*
"""
def test_weasyprint_available(self, generator):
"""Test that WeasyPrint is detected as available."""
assert generator.weasyprint_available is True
def test_markdown_to_html(self, generator, sample_markdown):
"""Test markdown to HTML conversion."""
html = generator.markdown_to_html(sample_markdown)
assert "<!DOCTYPE html>" in html
assert "<html>" in html
assert "<style>" in html
# Note: markdown library adds id attribute to headers (from TOC extension)
assert "<h1" in html and "Test Document</h1>" in html
assert "<table>" in html
assert "<strong>bold</strong>" in html
def test_markdown_to_html_includes_css(self, generator, sample_markdown):
"""Test that HTML includes CSS styling."""
html = generator.markdown_to_html(sample_markdown)
# Check key CSS rules are included
assert "font-family" in html
assert "border-collapse" in html
assert "@page" in html
def test_generate_pdf_success(self, generator, sample_markdown):
"""Test successful PDF generation."""
result = generator.generate_pdf(sample_markdown)
assert isinstance(result, PDFResult)
assert result.success is True
assert result.pdf_path is not None
assert result.error_message is None
assert result.file_size_bytes > 0
# Verify file exists
pdf_path = Path(result.pdf_path)
assert pdf_path.exists()
assert pdf_path.suffix == ".pdf"
# Clean up
pdf_path.unlink()
def test_generate_pdf_with_custom_path(self, generator, sample_markdown):
"""Test PDF generation with custom output path."""
with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as f:
output_path = f.name
result = generator.generate_pdf(sample_markdown, output_path=output_path)
assert result.success is True
assert result.pdf_path == output_path
# Clean up
Path(output_path).unlink()
def test_generate_pdf_empty_content(self, generator):
"""Test PDF generation with empty content."""
result = generator.generate_pdf("")
# Should still succeed with empty content
assert result.success is True
assert result.pdf_path is not None
# Clean up
Path(result.pdf_path).unlink()
def test_generate_pdf_complex_tables(self, generator):
"""Test PDF with complex table content."""
markdown = """# Thresholds
| Metal | Non-Operational | Operational | Unit |
|-------|-----------------|-------------|------|
| Lead | 22 | 500 | µg/100cm² |
| Cadmium | 3.3 | 50 | µg/100cm² |
| Arsenic | 6.7 | 100 | µg/100cm² |
## Notes
Special characters: µ, °, ², ™
"""
result = generator.generate_pdf(markdown)
assert result.success is True
assert result.file_size_bytes > 0
# Clean up
Path(result.pdf_path).unlink()
def test_generate_html_fallback(self, generator, sample_markdown):
"""Test HTML generation as fallback."""
success, html_path, error = generator.generate_html(sample_markdown)
assert success is True
assert html_path is not None
assert error is None
# Verify file exists and contains HTML
html_path = Path(html_path)
assert html_path.exists()
content = html_path.read_text()
assert "<html>" in content
# Clean up
html_path.unlink()
def test_custom_css(self):
"""Test PDF generator with custom CSS."""
custom_css = """
body { font-family: monospace; }
h1 { color: red; }
"""
generator = PDFGenerator(custom_css=custom_css)
html = generator.markdown_to_html("# Test")
assert "font-family: monospace" in html
assert "color: red" in html
class TestGenerateSowPdf:
"""Test the convenience function."""
def test_generate_sow_pdf(self):
"""Test generate_sow_pdf convenience function."""
markdown = """# Scope of Work
## Project: Test Fire
| Field | Value |
|-------|-------|
| Client | ACME Corp |
| Date | 2024-01-15 |
## Recommendations
- Clean all surfaces
- HEPA vacuum required
"""
result = generate_sow_pdf(
markdown_content=markdown,
project_name="Test Fire",
)
assert result.success is True
assert result.pdf_path is not None
# Clean up
Path(result.pdf_path).unlink()
class TestSOWCSS:
"""Test CSS styling constants."""
def test_sow_css_exists(self):
"""Test that SOW_CSS is defined."""
assert SOW_CSS is not None
assert len(SOW_CSS) > 0
def test_sow_css_has_page_settings(self):
"""Test that CSS includes page settings."""
assert "@page" in SOW_CSS
assert "margin" in SOW_CSS
def test_sow_css_has_table_styling(self):
"""Test that CSS includes table styling."""
assert "table" in SOW_CSS
assert "border-collapse" in SOW_CSS
assert "th" in SOW_CSS
assert "td" in SOW_CSS
def test_sow_css_has_header_styling(self):
"""Test that CSS includes header styling."""
assert "h1" in SOW_CSS
assert "h2" in SOW_CSS
class TestPDFResultDataclass:
"""Test PDFResult dataclass."""
def test_pdf_result_success(self):
"""Test PDFResult with success."""
result = PDFResult(
success=True,
pdf_path="/tmp/test.pdf",
file_size_bytes=1000,
)
assert result.success is True
assert result.pdf_path == "/tmp/test.pdf"
assert result.error_message is None
assert result.file_size_bytes == 1000
def test_pdf_result_failure(self):
"""Test PDFResult with failure."""
result = PDFResult(
success=False,
pdf_path=None,
error_message="Something went wrong",
)
assert result.success is False
assert result.pdf_path is None
assert result.error_message == "Something went wrong"
assert result.file_size_bytes == 0