PlanOpticon

planopticon / tests / test_output_formatter.py
Blame History Raw 276 lines
1
"""Tests for video_processor.cli.output_formatter.OutputFormatter."""
2
3
from pathlib import Path
4
5
import pytest
6
7
from video_processor.cli.output_formatter import OutputFormatter
8
9
10
@pytest.fixture()
11
def tmp_dir(tmp_path):
12
"""Return a fresh temp directory that is cleaned up automatically."""
13
return tmp_path
14
15
16
@pytest.fixture()
17
def formatter(tmp_dir):
18
"""Return an OutputFormatter pointed at a temp output directory."""
19
return OutputFormatter(tmp_dir / "output")
20
21
22
# --- Constructor ---
23
24
25
def test_constructor_creates_output_dir(tmp_dir):
26
out = tmp_dir / "new_output"
27
assert not out.exists()
28
OutputFormatter(out)
29
assert out.is_dir()
30
31
32
def test_constructor_accepts_string(tmp_dir):
33
fmt = OutputFormatter(str(tmp_dir / "str_output"))
34
assert fmt.output_dir.is_dir()
35
36
37
# --- organize_outputs ---
38
39
40
def _create_file(path: Path, content: str = "test") -> Path:
41
path.parent.mkdir(parents=True, exist_ok=True)
42
path.write_text(content)
43
return path
44
45
46
def test_organize_outputs_basic(formatter, tmp_dir):
47
md = _create_file(tmp_dir / "analysis.md", "# Title")
48
kg = _create_file(tmp_dir / "kg.json", "{}")
49
50
result = formatter.organize_outputs(
51
markdown_path=md,
52
knowledge_graph_path=kg,
53
diagrams=[],
54
)
55
56
assert "markdown" in result
57
assert "knowledge_graph" in result
58
assert Path(result["markdown"]).exists()
59
assert Path(result["knowledge_graph"]).exists()
60
assert result["diagram_images"] == []
61
assert result["frames"] == []
62
assert result["transcript"] is None
63
64
65
def test_organize_outputs_with_transcript(formatter, tmp_dir):
66
md = _create_file(tmp_dir / "analysis.md")
67
kg = _create_file(tmp_dir / "kg.json")
68
transcript = _create_file(tmp_dir / "transcript.txt", "Hello world")
69
70
result = formatter.organize_outputs(
71
markdown_path=md,
72
knowledge_graph_path=kg,
73
diagrams=[],
74
transcript_path=transcript,
75
)
76
77
assert result["transcript"] is not None
78
assert Path(result["transcript"]).exists()
79
80
81
def test_organize_outputs_with_diagrams(formatter, tmp_dir):
82
md = _create_file(tmp_dir / "analysis.md")
83
kg = _create_file(tmp_dir / "kg.json")
84
img = _create_file(tmp_dir / "diagram1.png", "fake-png")
85
86
result = formatter.organize_outputs(
87
markdown_path=md,
88
knowledge_graph_path=kg,
89
diagrams=[{"image_path": str(img)}],
90
)
91
92
assert len(result["diagram_images"]) == 1
93
assert Path(result["diagram_images"][0]).exists()
94
95
96
def test_organize_outputs_skips_missing_diagram(formatter, tmp_dir):
97
md = _create_file(tmp_dir / "analysis.md")
98
kg = _create_file(tmp_dir / "kg.json")
99
100
result = formatter.organize_outputs(
101
markdown_path=md,
102
knowledge_graph_path=kg,
103
diagrams=[{"image_path": "/nonexistent/diagram.png"}],
104
)
105
106
assert result["diagram_images"] == []
107
108
109
def test_organize_outputs_diagram_without_image_path(formatter, tmp_dir):
110
md = _create_file(tmp_dir / "analysis.md")
111
kg = _create_file(tmp_dir / "kg.json")
112
113
result = formatter.organize_outputs(
114
markdown_path=md,
115
knowledge_graph_path=kg,
116
diagrams=[{"description": "A diagram"}],
117
)
118
119
assert result["diagram_images"] == []
120
121
122
def test_organize_outputs_with_frames(formatter, tmp_dir):
123
md = _create_file(tmp_dir / "analysis.md")
124
kg = _create_file(tmp_dir / "kg.json")
125
frames_dir = tmp_dir / "frames"
126
frames_dir.mkdir()
127
for i in range(5):
128
_create_file(frames_dir / f"frame_{i:03d}.jpg", f"frame{i}")
129
130
result = formatter.organize_outputs(
131
markdown_path=md,
132
knowledge_graph_path=kg,
133
diagrams=[],
134
frames_dir=frames_dir,
135
)
136
137
assert len(result["frames"]) == 5
138
139
140
def test_organize_outputs_limits_frames_to_10(formatter, tmp_dir):
141
md = _create_file(tmp_dir / "analysis.md")
142
kg = _create_file(tmp_dir / "kg.json")
143
frames_dir = tmp_dir / "frames"
144
frames_dir.mkdir()
145
for i in range(25):
146
_create_file(frames_dir / f"frame_{i:03d}.jpg", f"frame{i}")
147
148
result = formatter.organize_outputs(
149
markdown_path=md,
150
knowledge_graph_path=kg,
151
diagrams=[],
152
frames_dir=frames_dir,
153
)
154
155
assert len(result["frames"]) <= 10
156
157
158
def test_organize_outputs_missing_frames_dir(formatter, tmp_dir):
159
md = _create_file(tmp_dir / "analysis.md")
160
kg = _create_file(tmp_dir / "kg.json")
161
162
result = formatter.organize_outputs(
163
markdown_path=md,
164
knowledge_graph_path=kg,
165
diagrams=[],
166
frames_dir=tmp_dir / "nonexistent_frames",
167
)
168
169
assert result["frames"] == []
170
171
172
# --- create_html_index ---
173
174
175
def test_create_html_index_returns_path(formatter, tmp_dir):
176
outputs = {
177
"markdown": str(formatter.output_dir / "markdown" / "analysis.md"),
178
"knowledge_graph": str(formatter.output_dir / "data" / "kg.json"),
179
"diagram_images": [],
180
"frames": [],
181
"transcript": None,
182
}
183
# Create the referenced files so relative_to works
184
for key in ("markdown", "knowledge_graph"):
185
_create_file(Path(outputs[key]))
186
187
index = formatter.create_html_index(outputs)
188
assert index.exists()
189
assert index.name == "index.html"
190
191
192
def test_create_html_index_contains_analysis_link(formatter, tmp_dir):
193
md_path = formatter.output_dir / "markdown" / "analysis.md"
194
_create_file(md_path)
195
outputs = {
196
"markdown": str(md_path),
197
"knowledge_graph": None,
198
"diagram_images": [],
199
"frames": [],
200
"transcript": None,
201
}
202
203
index = formatter.create_html_index(outputs)
204
content = index.read_text()
205
assert "Analysis Report" in content
206
assert "analysis.md" in content
207
208
209
def test_create_html_index_with_diagrams(formatter, tmp_dir):
210
img_path = formatter.output_dir / "diagrams" / "d1.png"
211
_create_file(img_path)
212
outputs = {
213
"markdown": None,
214
"knowledge_graph": None,
215
"diagram_images": [str(img_path)],
216
"frames": [],
217
"transcript": None,
218
}
219
220
index = formatter.create_html_index(outputs)
221
content = index.read_text()
222
assert "Diagrams" in content
223
assert "d1.png" in content
224
225
226
def test_create_html_index_with_frames(formatter, tmp_dir):
227
frame_path = formatter.output_dir / "frames" / "frame_001.jpg"
228
_create_file(frame_path)
229
outputs = {
230
"markdown": None,
231
"knowledge_graph": None,
232
"diagram_images": [],
233
"frames": [str(frame_path)],
234
"transcript": None,
235
}
236
237
index = formatter.create_html_index(outputs)
238
content = index.read_text()
239
assert "Key Frames" in content
240
assert "frame_001.jpg" in content
241
242
243
def test_create_html_index_with_data_files(formatter, tmp_dir):
244
kg_path = formatter.output_dir / "data" / "kg.json"
245
transcript_path = formatter.output_dir / "data" / "transcript.txt"
246
_create_file(kg_path)
247
_create_file(transcript_path)
248
outputs = {
249
"markdown": None,
250
"knowledge_graph": str(kg_path),
251
"diagram_images": [],
252
"frames": [],
253
"transcript": str(transcript_path),
254
}
255
256
index = formatter.create_html_index(outputs)
257
content = index.read_text()
258
assert "Data Files" in content
259
assert "kg.json" in content
260
assert "transcript.txt" in content
261
262
263
def test_create_html_index_empty_outputs(formatter):
264
outputs = {
265
"markdown": None,
266
"knowledge_graph": None,
267
"diagram_images": [],
268
"frames": [],
269
"transcript": None,
270
}
271
272
index = formatter.create_html_index(outputs)
273
content = index.read_text()
274
assert "PlanOpticon Analysis Results" in content
275
assert "<!DOCTYPE html>" in content
276

Keyboard Shortcuts

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