- Redesigned frontend with Outfit/Figtree typography, coral accent palette, noise texture, glassmorphism header, and staggered animations - Split monolithic index.html into modular JS (app, api, upload, batch, results, page-viewer, utils) and extracted CSS - Fixed worker.py to generate page images for Visual Page Inspector - Added Docker Compose stack (web, worker, redis, postgres) - Added batch upload, HTML report export, rate limiting, and Redis queue - Extended test suite with checker, remediation, worker, and DB tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
196 lines
6.6 KiB
Python
196 lines
6.6 KiB
Python
"""
|
|
Extended tests for pdf_remediation.py — covers PDFRemediator analysis and fix methods.
|
|
"""
|
|
|
|
import pytest
|
|
from pathlib import Path
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
|
|
class TestPDFRemediatorAnalysis:
|
|
def test_analyze_and_suggest_fixes(self, sample_poor_pdf):
|
|
from pdf_remediation import PDFRemediator
|
|
|
|
remediator = PDFRemediator(str(sample_poor_pdf))
|
|
suggestions = remediator.analyze_and_suggest_fixes()
|
|
|
|
assert isinstance(suggestions, dict)
|
|
# Should have at least one category
|
|
assert len(suggestions) >= 0
|
|
|
|
def test_analyze_good_pdf(self, sample_good_pdf):
|
|
from pdf_remediation import PDFRemediator
|
|
|
|
remediator = PDFRemediator(str(sample_good_pdf))
|
|
suggestions = remediator.analyze_and_suggest_fixes()
|
|
|
|
assert isinstance(suggestions, dict)
|
|
|
|
|
|
class TestPDFRemediatorApplyFixes:
|
|
def test_apply_fixes_produces_output(self, sample_poor_pdf, tmp_path):
|
|
from pdf_remediation import PDFRemediator
|
|
|
|
output_path = str(tmp_path / "fixed.pdf")
|
|
remediator = PDFRemediator(str(sample_poor_pdf))
|
|
|
|
result = remediator.apply_fixes([], output_path=output_path)
|
|
assert isinstance(result, dict)
|
|
|
|
def test_apply_fixes_with_title(self, sample_poor_pdf, tmp_path):
|
|
from pdf_remediation import PDFRemediator
|
|
|
|
output_path = str(tmp_path / "titled.pdf")
|
|
remediator = PDFRemediator(str(sample_poor_pdf))
|
|
|
|
result = remediator.apply_fixes(
|
|
["add_title"], output_path=output_path,
|
|
custom_values={"title": "Test Title"}
|
|
)
|
|
assert isinstance(result, dict)
|
|
|
|
def test_apply_fixes_default_output_path(self, sample_poor_pdf):
|
|
from pdf_remediation import PDFRemediator
|
|
|
|
remediator = PDFRemediator(str(sample_poor_pdf))
|
|
result = remediator.apply_fixes([])
|
|
assert isinstance(result, dict)
|
|
|
|
|
|
class TestPDFRemediatorFixMethods:
|
|
def test_fix_add_title(self, sample_poor_pdf):
|
|
from pdf_remediation import PDFRemediator
|
|
|
|
remediator = PDFRemediator(str(sample_poor_pdf))
|
|
# Clone pages first (required before fix methods)
|
|
for page in remediator.reader.pages:
|
|
remediator.writer.add_page(page)
|
|
|
|
if hasattr(remediator, '_fix_add_title'):
|
|
remediator._fix_add_title("Test Title")
|
|
else:
|
|
pytest.skip("_fix_add_title not available")
|
|
|
|
def test_fix_set_language(self, sample_poor_pdf):
|
|
from pdf_remediation import PDFRemediator
|
|
|
|
remediator = PDFRemediator(str(sample_poor_pdf))
|
|
for page in remediator.reader.pages:
|
|
remediator.writer.add_page(page)
|
|
|
|
if hasattr(remediator, '_fix_set_language'):
|
|
remediator._fix_set_language("en-US")
|
|
else:
|
|
pytest.skip("_fix_set_language not available")
|
|
|
|
def test_fix_mark_tagged(self, sample_poor_pdf):
|
|
from pdf_remediation import PDFRemediator
|
|
|
|
remediator = PDFRemediator(str(sample_poor_pdf))
|
|
for page in remediator.reader.pages:
|
|
remediator.writer.add_page(page)
|
|
|
|
if hasattr(remediator, '_fix_mark_tagged'):
|
|
remediator._fix_mark_tagged()
|
|
else:
|
|
pytest.skip("_fix_mark_tagged not available")
|
|
|
|
|
|
class TestVeraPDFValidatorExtended:
|
|
@patch("subprocess.run")
|
|
def test_validate_compliant(self, mock_run, sample_good_pdf):
|
|
from pdf_remediation import VeraPDFValidator
|
|
|
|
mock_run.return_value = MagicMock(
|
|
returncode=0,
|
|
stdout='{"report":{"jobs":[{"validationResult":[{"details":{"passedRules":50,"failedRules":0,"passedChecks":200,"failedChecks":0,"ruleSummaries":[]}}]}]}}',
|
|
stderr=""
|
|
)
|
|
|
|
validator = VeraPDFValidator()
|
|
result = validator.validate(str(sample_good_pdf))
|
|
|
|
assert result["compliant"] is True
|
|
assert result["passed_rules"] == 50
|
|
assert result["failed_rules"] == 0
|
|
|
|
@patch("subprocess.run")
|
|
def test_validate_non_compliant(self, mock_run, sample_poor_pdf):
|
|
from pdf_remediation import VeraPDFValidator
|
|
|
|
mock_run.return_value = MagicMock(
|
|
returncode=0,
|
|
stdout='{"report":{"jobs":[{"validationResult":[{"details":{"passedRules":30,"failedRules":5,"passedChecks":150,"failedChecks":10,"ruleSummaries":[{"ruleStatus":"FAILED","clause":"7.1","description":"Missing tag","testNumber":1,"failedChecks":2}]}}]}]}}',
|
|
stderr=""
|
|
)
|
|
|
|
validator = VeraPDFValidator()
|
|
result = validator.validate(str(sample_poor_pdf))
|
|
|
|
assert result["compliant"] is False
|
|
assert result["failed_rules"] == 5
|
|
assert len(result["errors"]) == 1
|
|
|
|
@patch("subprocess.run")
|
|
def test_validate_timeout(self, mock_run, sample_good_pdf):
|
|
import subprocess as sp
|
|
from pdf_remediation import VeraPDFValidator
|
|
|
|
mock_run.side_effect = sp.TimeoutExpired(cmd="verapdf", timeout=30)
|
|
|
|
validator = VeraPDFValidator()
|
|
result = validator.validate(str(sample_good_pdf), timeout=30)
|
|
|
|
assert "error" in result
|
|
assert "timeout" in result["error"].lower()
|
|
|
|
@patch("subprocess.run")
|
|
def test_validate_process_error(self, mock_run, sample_good_pdf):
|
|
from pdf_remediation import VeraPDFValidator
|
|
|
|
mock_run.return_value = MagicMock(
|
|
returncode=1,
|
|
stdout="",
|
|
stderr="veraPDF not found"
|
|
)
|
|
|
|
validator = VeraPDFValidator()
|
|
result = validator.validate(str(sample_good_pdf))
|
|
|
|
assert "error" in result
|
|
|
|
@patch("subprocess.run")
|
|
def test_validate_no_jobs(self, mock_run, sample_good_pdf):
|
|
from pdf_remediation import VeraPDFValidator
|
|
|
|
mock_run.return_value = MagicMock(
|
|
returncode=0,
|
|
stdout='{"report":{"jobs":[]}}',
|
|
stderr=""
|
|
)
|
|
|
|
validator = VeraPDFValidator()
|
|
result = validator.validate(str(sample_good_pdf))
|
|
|
|
assert "error" in result
|
|
|
|
|
|
class TestPDFRemediatorInit:
|
|
def test_reader_and_writer_types(self, sample_good_pdf):
|
|
from pdf_remediation import PDFRemediator
|
|
from pypdf import PdfReader, PdfWriter
|
|
|
|
remediator = PDFRemediator(str(sample_good_pdf))
|
|
assert isinstance(remediator.reader, PdfReader)
|
|
assert isinstance(remediator.writer, PdfWriter)
|
|
assert remediator.fixes_applied == []
|
|
|
|
def test_pdf_path_stored(self, sample_good_pdf):
|
|
from pdf_remediation import PDFRemediator
|
|
|
|
remediator = PDFRemediator(str(sample_good_pdf))
|
|
assert remediator.pdf_path == Path(sample_good_pdf)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|