pdf-quiz-generator/backend/tests/test_question_figures.py
Daniel 094bab20cd
Some checks failed
Tests / backend (push) Failing after 9s
Tests / frontend (push) Successful in 38s
Tests / e2e (push) Failing after 43s
feat: an opened explanation figure shows what the library knows
Two voices, and they belong in different places. The thumbnail in an
explanation carries what the *question* says about the figure — words an
educator chose for this question. Opening it now adds the catalogue
entry underneath: what the image was filed as, the description written
when it was filed, where it came from, and any marks an educator drew on
it, behind a switch.

It rides on explanation rows only. Those are already withheld by the
server until answers are revealed, so the record reaches somebody who
has finished the question and gets nowhere near somebody who has not —
which is the whole reason the caption came off the figure in the first
place.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqXevQJhxFrM7jJg82cgZN
2026-09-13 05:05:59 +02:00

70 lines
3.2 KiB
Python

"""What a question says about its own figures — and what it must not say.
Run: DATABASE_URL=sqlite:///:memory: PYTHONPATH=backend python -m unittest discover -s backend/tests
"""
import os
os.environ.setdefault("DATABASE_URL", "sqlite:///:memory:")
import unittest
from app.models.media import MediaAsset
from app.models.question_media import QuestionMedia
from app.services.question_figures import figure_json
class FigureCaptionTests(unittest.TestCase):
"""A caption beside a stem is read before the question is answered.
The library's description of an image is written to catalogue it — "an
X-ray of a child's pelvis and hips, showing abnormalities in the right hip
joint" is a perfectly good catalogue entry and a complete giveaway under a
stem about a limping five-year-old. Every one of the bank's 343 figures was
inheriting one; not one had a caption of its own.
"""
def setUp(self):
self.asset = MediaAsset(id=5, path="uploads/hip.png",
title="Right SCFE, AP pelvis",
caption="An X-ray of a child's pelvis and hips, "
"showing abnormalities in the right hip joint.")
def test_the_library_description_never_reaches_a_question(self):
link = QuestionMedia(id=1, question_id=9, media_id=5, role="stem",
label=None, caption=None, position=0)
figure = figure_json(link, self.asset)
self.assertIsNone(figure["caption"])
self.assertIsNone(figure["label"])
# Nor by another name: the catalogue title is a giveaway of its own,
# and nothing renders it.
self.assertNotIn("title", figure)
self.assertEqual(figure["path"], "uploads/hip.png")
def test_the_library_record_rides_only_on_an_explanation_figure(self):
"""Once the answer is in, the catalogue entry is worth having.
The server already withholds explanation figures until answers are
revealed, so hanging the library record on those rows — and only those
— puts it in front of a reader who has finished the question and
nowhere near one who has not.
"""
self.asset.source = "Teaching file"
self.asset.source_url = "https://example.org/x"
stem = QuestionMedia(id=3, question_id=9, media_id=5, role="stem", position=0)
back = QuestionMedia(id=4, question_id=9, media_id=5, role="explanation", position=0)
self.assertIsNone(figure_json(stem, self.asset)["library"])
shelf = figure_json(back, self.asset)["library"]
self.assertEqual(shelf["title"], "Right SCFE, AP pelvis")
self.assertIn("right hip joint", shelf["caption"])
self.assertEqual(shelf["source"], "Teaching file")
def test_what_the_question_itself_says_is_shown(self):
link = QuestionMedia(id=2, question_id=9, media_id=5, role="stem",
label="Figure 1", caption="AP pelvis at presentation.",
position=0)
figure = figure_json(link, self.asset)
self.assertEqual(figure["caption"], "AP pelvis at presentation.")
self.assertEqual(figure["label"], "Figure 1")
if __name__ == "__main__":
unittest.main()