bookmark/tests/test_session.py

96 lines
3.1 KiB
Python

from pathlib import Path
import numpy as np
import pytest
from bookmark.capture_strategies.manual_button import ManualButtonStrategy
from bookmark.catalogue import Catalogue
from bookmark.session import IntakeSession, IntakeState
from bookmark.sizing import MarkerRegion
def make_reference(size=100, color=200):
return np.full((size, size, 3), color, dtype=np.uint8)
def make_book_frame(size=100, ref_color=200, book_color=50, box=(20, 20, 40, 40)):
frame = np.full((size, size, 3), ref_color, dtype=np.uint8)
x, y, w, h = box
frame[y:y + h, x:x + w] = book_color
return frame
@pytest.fixture
def session(tmp_path):
catalogue = Catalogue(tmp_path / "catalogue.csv")
strategy = ManualButtonStrategy()
reference = make_reference()
markers = [
MarkerRegion(name="small_boundary", bucket="small", x=0, y=0, width=10, height=10),
MarkerRegion(name="medium_boundary", bucket="medium", x=90, y=0, width=10, height=10),
MarkerRegion(name="large_boundary", bucket="large", x=0, y=90, width=10, height=10),
]
return IntakeSession(
catalogue=catalogue,
strategy=strategy,
reference_frame=reference,
markers=markers,
captures_dir=tmp_path / "captures",
)
def test_session_starts_waiting_for_front(session):
assert session.state == IntakeState.WAITING_FRONT
def test_front_capture_advances_to_waiting_back_and_writes_catalogue_row(session):
session.strategy.trigger()
fired = session.observe_frame(make_book_frame())
assert fired is True
assert session.state == IntakeState.WAITING_BACK
assert session.current_book_id is not None
rows = session.catalogue.read_all()
assert len(rows) == 1
assert rows[0]["book_id"] == session.current_book_id
assert rows[0]["status"] == "captured"
assert Path(rows[0]["front_wide_path"]).exists()
assert Path(rows[0]["front_cropped_path"]).exists()
def test_back_capture_completes_book_and_updates_row(session):
session.strategy.trigger()
session.observe_frame(make_book_frame())
book_id = session.current_book_id
session.strategy.trigger()
fired = session.observe_frame(make_book_frame())
assert fired is True
assert session.state == IntakeState.BOOK_COMPLETE
rows = session.catalogue.read_all()
assert rows[0]["book_id"] == book_id
assert Path(rows[0]["back_wide_path"]).exists()
assert Path(rows[0]["back_cropped_path"]).exists()
def test_start_next_book_resets_state_and_assigns_new_id(session):
session.strategy.trigger()
session.observe_frame(make_book_frame())
session.strategy.trigger()
session.observe_frame(make_book_frame())
first_book_id = session.current_book_id
session.start_next_book()
assert session.state == IntakeState.WAITING_FRONT
assert session.current_book_id is None
session.strategy.trigger()
session.observe_frame(make_book_frame())
assert session.current_book_id != first_book_id
def test_start_next_book_raises_if_book_not_complete(session):
with pytest.raises(RuntimeError):
session.start_next_book()