import json from pathlib import Path from spelunkai_recording.session import RecordingSession, session_paths class FakeKeyboard: def __init__(self, keys_sequence): self._keys_sequence = keys_sequence self._i = 0 self.started = False self.stopped = False def start(self): self.started = True def stop(self): self.stopped = True def snapshot(self): keys = self._keys_sequence[min(self._i, len(self._keys_sequence) - 1)] self._i += 1 return keys class FakeVideo: def __init__(self): self.started = False self.stopped = False def start(self): self.started = True def stop(self): self.stopped = True def test_session_logs_one_row_per_frame_and_writes_manifest(tmp_path: Path): paths = session_paths(tmp_path, "test-session") keyboard = FakeKeyboard([["LEFT"], [], ["RIGHT", "KEY_Z"]]) video = FakeVideo() session = RecordingSession(paths=paths, keyboard=keyboard, video=video, fps=30, width=1280, height=720) frame_count = session.run(duration_s=0.1) assert frame_count >= 1 assert keyboard.started and keyboard.stopped assert video.started and video.stopped lines = paths.input_log.read_text(encoding="utf-8").splitlines() assert len(lines) == frame_count first_row = json.loads(lines[0]) assert first_row["frame"] == 0 assert first_row["keys"] == ["LEFT"] manifest = json.loads(paths.manifest.read_text(encoding="utf-8")) assert manifest["fps"] == 30 assert manifest["frame_count"] == frame_count assert manifest["video_file"] == paths.video.name