PlanOpticon

planopticon / tests / test_exporters.py
Blame History Raw 158 lines
1
"""Tests for PDF and PPTX exporters."""
2
3
import pytest
4
5
from video_processor.exporters.pdf_export import generate_pdf
6
from video_processor.exporters.pptx_export import generate_pptx
7
8
9
def _sample_kg():
10
"""Return a sample knowledge graph dict for testing."""
11
return {
12
"nodes": [
13
{"name": "Python", "type": "technology", "descriptions": ["A programming language"]},
14
{"name": "Django", "type": "technology", "descriptions": ["A web framework"]},
15
{"name": "Alice", "type": "person", "descriptions": ["Software engineer"]},
16
{"name": "Bob", "type": "person", "descriptions": ["Product manager"]},
17
{"name": "Acme Corp", "type": "organization", "descriptions": ["A tech company"]},
18
],
19
"relationships": [
20
{"source": "Alice", "target": "Python", "type": "uses"},
21
{"source": "Alice", "target": "Bob", "type": "works_with"},
22
{"source": "Django", "target": "Python", "type": "built_on"},
23
{"source": "Alice", "target": "Acme Corp", "type": "employed_by"},
24
],
25
}
26
27
28
def _empty_kg():
29
return {"nodes": [], "relationships": []}
30
31
32
class TestPDFExport:
33
@pytest.fixture(autouse=True)
34
def _check_reportlab(self):
35
pytest.importorskip("reportlab")
36
37
def test_generate_pdf(self, tmp_path):
38
out = tmp_path / "report.pdf"
39
result = generate_pdf(_sample_kg(), out, title="Test Report")
40
assert result == out
41
assert out.exists()
42
assert out.stat().st_size > 0
43
44
def test_generate_pdf_empty_kg(self, tmp_path):
45
out = tmp_path / "empty.pdf"
46
result = generate_pdf(_empty_kg(), out)
47
assert result == out
48
assert out.exists()
49
50
def test_generate_pdf_creates_parent_dirs(self, tmp_path):
51
out = tmp_path / "sub" / "dir" / "report.pdf"
52
result = generate_pdf(_sample_kg(), out)
53
assert result == out
54
assert out.exists()
55
56
def test_generate_pdf_default_title(self, tmp_path):
57
out = tmp_path / "default.pdf"
58
generate_pdf(_sample_kg(), out)
59
assert out.exists()
60
61
def test_generate_pdf_with_diagrams_dir(self, tmp_path):
62
diag_dir = tmp_path / "diagrams"
63
diag_dir.mkdir()
64
out = tmp_path / "report.pdf"
65
# No PNGs in dir — should still work
66
result = generate_pdf(_sample_kg(), out, diagrams_dir=diag_dir)
67
assert result == out
68
69
def test_generate_pdf_no_reportlab(self, tmp_path, monkeypatch):
70
"""Verify ImportError propagates when reportlab is missing."""
71
import builtins
72
73
real_import = builtins.__import__
74
75
def mock_import(name, *args, **kwargs):
76
if name.startswith("reportlab"):
77
raise ImportError("No module named 'reportlab'")
78
return real_import(name, *args, **kwargs)
79
80
monkeypatch.setattr(builtins, "__import__", mock_import)
81
with pytest.raises(ImportError):
82
generate_pdf(_sample_kg(), tmp_path / "fail.pdf")
83
84
85
class TestPPTXExport:
86
@pytest.fixture(autouse=True)
87
def _check_pptx(self):
88
pytest.importorskip("pptx")
89
90
def test_generate_pptx(self, tmp_path):
91
out = tmp_path / "slides.pptx"
92
result = generate_pptx(_sample_kg(), out, title="Test Deck")
93
assert result == out
94
assert out.exists()
95
assert out.stat().st_size > 0
96
97
def test_generate_pptx_empty_kg(self, tmp_path):
98
out = tmp_path / "empty.pptx"
99
result = generate_pptx(_empty_kg(), out)
100
assert result == out
101
assert out.exists()
102
103
def test_generate_pptx_creates_parent_dirs(self, tmp_path):
104
out = tmp_path / "sub" / "dir" / "slides.pptx"
105
result = generate_pptx(_sample_kg(), out)
106
assert result == out
107
assert out.exists()
108
109
def test_generate_pptx_with_diagrams_dir(self, tmp_path):
110
diag_dir = tmp_path / "diagrams"
111
diag_dir.mkdir()
112
out = tmp_path / "slides.pptx"
113
result = generate_pptx(_sample_kg(), out, diagrams_dir=diag_dir)
114
assert result == out
115
116
def test_pptx_slide_count(self, tmp_path):
117
"""Verify expected number of slides are created."""
118
from pptx import Presentation
119
120
out = tmp_path / "count.pptx"
121
generate_pptx(_sample_kg(), out)
122
prs = Presentation(str(out))
123
# Title + Overview + Key Entities + Rel Types + 1 entity batch = 5
124
assert len(prs.slides) == 5
125
126
def test_pptx_many_entities_batched(self, tmp_path):
127
"""Entities are batched into multiple slides when >12."""
128
from pptx import Presentation
129
130
kg = {
131
"nodes": [
132
{"name": f"Entity{i}", "type": "concept", "descriptions": [f"desc {i}"]}
133
for i in range(25)
134
],
135
"relationships": [],
136
}
137
out = tmp_path / "many.pptx"
138
generate_pptx(kg, out)
139
prs = Presentation(str(out))
140
# Title + Overview + 3 entity batches (12 + 12 + 1) = 5
141
# No Key Entities or Rel Types slides (no relationships)
142
assert len(prs.slides) == 5
143
144
def test_generate_pptx_no_pptx(self, tmp_path, monkeypatch):
145
"""Verify ImportError propagates when python-pptx is missing."""
146
import builtins
147
148
real_import = builtins.__import__
149
150
def mock_import(name, *args, **kwargs):
151
if name.startswith("pptx"):
152
raise ImportError("No module named 'pptx'")
153
return real_import(name, *args, **kwargs)
154
155
monkeypatch.setattr(builtins, "__import__", mock_import)
156
with pytest.raises(ImportError):
157
generate_pptx(_sample_kg(), tmp_path / "fail.pptx")
158

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button