Files
Copies/tests/test_gui_manual_resolution.py
T
2026-10-06 11:11:03 +02:00

134 lines
6.0 KiB
Python

import os
import tempfile
import tkinter as tk
import unittest
from pathlib import Path
from unittest.mock import call, patch
from copienator.answer_origins import save_origins
from copienator_gui.manual_resolution import ManualResolutionPanel
@unittest.skipUnless(os.environ.get("DISPLAY"), "requires a display")
class ManualResolutionPanelTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.evaluation = Path(self.temp.name)
self.root = tk.Tk()
self.addCleanup(self.root.destroy)
self.path = self.evaluation / "manual_resolutions.txt"
def panel(self):
panel = ManualResolutionPanel(self.root, lambda: self.evaluation)
panel.pack()
self.root.update()
return panel
def test_preview_editor_and_each_pdf_pair_use_shared_resolution_rules(self):
content = "### Instructions\nCopie01 Ex 1 x> |Ex 2\n\nCopie02 Ex 3 ss Ex 4|\n"
self.path.write_text(content, encoding="utf-8")
paths = []
for copy, label in (("01", "Ex 1_new"), ("01", "Ex 2_old"),
("02", "Ex 3"), ("02", "Ex 4")):
path = self.evaluation / "Copies" / f"Copie{copy}" / f"{label}.pdf"
path.parent.mkdir(parents=True, exist_ok=True)
path.touch()
paths.append(path)
copy_paths = []
for copy in ("01", "02"):
pdf = self.evaluation / "Copies" / f"Copie{copy}.pdf"
pdf.touch()
copy_paths.extend((pdf, pdf.with_suffix("")))
panel = self.panel()
self.assertEqual(panel.text.get("1.0", "end-1c"), content)
self.assertEqual(len(panel.pdf_buttons), 4)
self.assertEqual([button.cget("text") for button in panel.pdf_buttons],
["Source : Ex 1", "Cible : Ex 2",
"Source : Ex 3", "Cible : Ex 4"])
self.assertEqual([button.cget("text") for button in panel.copy_buttons],
["pdf", "dir", "pdf", "dir"])
with patch("copienator_gui.manual_resolution.open_path") as opened:
panel.editor_button.invoke()
for button in panel.pdf_buttons:
button.invoke()
for button in panel.copy_buttons:
button.invoke()
self.assertEqual(opened.call_args_list,
[call(self.path), *map(call, paths), *map(call, copy_paths)])
def test_reload_updates_the_displayed_target_and_its_pdf_action(self):
self.path.write_text("Copie01 A -> B|\n", encoding="utf-8")
copies = self.evaluation / "Copies" / "Copie01"
copies.mkdir(parents=True)
(copies / "A.pdf").touch()
(copies / "C.pdf").touch()
panel = self.panel()
self.path.write_text("Copie01 A -> C|\n", encoding="utf-8")
panel.reload_button.invoke()
self.assertEqual(panel.text.get("1.0", "end-1c"), "Copie01 A -> C|\n")
self.assertEqual(panel.pdf_buttons[1].cget("text"), "Cible : C")
with patch("copienator_gui.manual_resolution.open_path") as opened:
panel.pdf_buttons[1].invoke()
opened.assert_called_once_with(copies / "C.pdf")
def test_populated_labels_appear_under_each_relevant_conflict(self):
content = "Copie01 A -> B|\nCopie02 A -> B|\nCopie01 A -> C|"
self.path.write_text(content, encoding="utf-8")
copies = self.evaluation / "Copies" / "Copie01"
copies.mkdir(parents=True)
for label, filename in (("label2", "label2_new.pdf"),
("label1", "label1.pdf"),
("stale", "stale.pdf"),
("archived", "archived_old.pdf")):
pdf = copies / filename
pdf.write_bytes(b"answer")
save_origins(self.evaluation, "01", label, pdf, ["A"])
(copies / "stale.pdf").write_bytes(b"changed answer")
panel = self.panel()
expected = (
"Copie01 A -> B|\n# -> label1, label2\n"
"Copie02 A -> B|\n"
"Copie01 A -> C|\n# -> label1, label2"
)
self.assertEqual(panel.text.get("1.0", "end-1c"), expected)
self.assertEqual(self.path.read_text(encoding="utf-8"), content)
self.assertEqual(len(panel.pdf_buttons), 6)
self.assertIn("3 instruction(s)", panel.status.cget("text"))
(copies / "label1.pdf").unlink()
panel.reload()
self.assertEqual(panel.text.get("1.0", "end-1c"),
expected.replace("label1, label2", "label2"))
def test_reload_keeps_invalid_lines_visible_and_removes_stale_actions(self):
self.path.write_text("Copie01 A -> B|\n", encoding="utf-8")
panel = self.panel()
self.path.write_text("bad instruction\nCopie02 C sx D\n", encoding="utf-8")
panel.reload()
self.assertIn("bad instruction", panel.text.get("1.0", "end"))
self.assertIn("lignes invalides : 1", panel.status.cget("text"))
self.assertEqual(len(panel.pdf_buttons), 2)
self.assertEqual(len(panel.copy_buttons), 2)
self.path.unlink()
panel.reload()
self.assertFalse(panel.pdf_buttons)
self.assertFalse(panel.copy_buttons)
self.assertEqual(str(panel.editor_button.cget("state")), "disabled")
def test_missing_source_does_not_prevent_opening_destination(self):
self.path.write_text("Copie01 A -> B|\n", encoding="utf-8")
destination = self.evaluation / "Copies" / "Copie01" / "B.pdf"
destination.parent.mkdir(parents=True)
destination.touch()
panel = self.panel()
with patch("copienator_gui.manual_resolution.open_path") as opened, patch(
"copienator_gui.manual_resolution.messagebox.showerror"
) as error:
panel.pdf_buttons[0].invoke()
opened.assert_not_called()
panel.pdf_buttons[1].invoke()
opened.assert_called_once_with(destination)
self.assertIn("A.pdf", error.call_args.args[1])