Files
Copies/tests/test_custom_remarks.py
T

86 lines
5.2 KiB
Python

from copy import deepcopy
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch
from PIL import Image, ImageDraw
from copienator import EvaluationWorkspace, ExitCode, atomic_write_json
from copienator.custom_remarks import apply_custom_remarks, set_remark, remarks_for_copy
from copienator.commands import annotating, reading_annotations as standard
from copienator.commands import reading_grouped_annotations as grouped
class CustomRemarkTests(unittest.TestCase):
def test_storage_preserves_other_students_and_feedback_is_idempotent(self):
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
set_remark(root, "01", "Ex 1", "First")
set_remark(root, "2", "Ex 1", "Other student")
set_remark(root, "1", "Ex 2", "Other label")
labels = {"Ex 1": {"result": {"feedback": [{"text": "Gemini"}]}}}
apply_custom_remarks(root, "1", labels)
apply_custom_remarks(root, "01", labels)
self.assertEqual([f["text"] for f in labels["Ex 1"]["result"]["feedback"]], ["Gemini", "First"])
set_remark(root, "01", "Ex 1", " ")
apply_custom_remarks(root, "1", labels)
self.assertEqual(labels["Ex 1"]["result"]["feedback"], [{"text": "Gemini"}])
self.assertEqual(remarks_for_copy(root, "1"), {"Ex 2": "Other label"})
self.assertEqual(remarks_for_copy(root, "02"), {"Ex 1": "Other student"})
def test_readers_render_remark_after_checkbox_deletion_and_preserve_ink(self):
for mode in ("Bnot", "BGnot"):
with self.subTest(mode=mode), tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
workspace = EvaluationWorkspace(root)
output = root / mode / "Copie01"
output.mkdir(parents=True)
answer = root / "answer.pdf"
answer.touch()
atomic_write_json(output / "bnote.json", {"images": [{"label": "Ex 1"}]})
atomic_write_json(output / "score.json", {"Ex 1": "4"})
original = {"01": {"Ex 1": {"pdf_path": answer, "coordinates": (0, 0),
"result": {"score": 4, "feedback": [{"text": "Gemini"}]}}}}
set_remark(root, "1", "Ex 1", "Teacher")
ink = Image.new("RGBA", (1500, 110), (0, 0, 0, 0))
draw = ImageDraw.Draw(ink)
draw.rectangle((100, 1, 120, 8), fill="red")
draw.rectangle((100, 30, 120, 50), fill="blue")
real_compose = annotating.compose_label_image
def compose(*args, **kwargs):
return real_compose(*args, **kwargs,
render_fn=lambda text, *a, **k: Image.new("RGB", (1500, 20), "green"))
with patch.object(annotating, "make_base_image", return_value=(Image.new("RGB", (1500, 100), "white"), 0, 0)), \
patch.object(annotating, "render_score_text", return_value=Image.new("RGB", (1500, 10), "white")), \
patch.object(annotating, "compose_label_image", side_effect=compose), \
patch.object(grouped, "get_extra_pdfs_as_images", return_value=[]):
def run(with_ink=True):
data = deepcopy(original)
actions = [{"label": "Ex 1", "type": "clear_all"}]
if mode == "Bnot":
# The tablet header was ten pixels tall.
atomic_write_json(output / "bnote.json", {"images": [
{"label": "Ex 1", "header_height": 10}]})
return standard.apply_actions_and_regenerate(workspace, data, "01", actions,
None, ["Ex 1"], update_score=True, label_notes={"Ex 1": ink} if with_ink else {})
status, _ = grouped.apply_actions_and_regenerate_grouped(workspace, data, "01",
actions, {"Ex 1": {"img": ink, "old_header_h": 10}} if with_ink else {}, ["Ex 1"], update_score=True)
return status
self.assertEqual(run(), ExitCode.SUCCESS)
self.assertTrue((output / "Concat_F.pdf").is_file())
with Image.open(output / "Ex 1.jpg") as image:
self.assertEqual(image.height, 130)
self.assertGreater(image.getpixel((110, 4))[0], 180)
self.assertGreater(image.getpixel((110, 65))[2], 180)
# Even with no handwritten ink, a personal remark includes a perfect answer.
original["01"]["Ex 1"]["result"]["feedback"] = []
self.assertEqual(run(with_ink=False), ExitCode.SUCCESS)
self.assertTrue((output / "Concat_F.pdf").is_file())
set_remark(root, "1", "Ex 1", "")
self.assertEqual(run(), ExitCode.SUCCESS)
with Image.open(output / "Ex 1.jpg") as image:
self.assertEqual(image.height, 110)
self.assertEqual(run(with_ink=False), ExitCode.SUCCESS)
self.assertFalse((output / "Concat_F.pdf").exists())