150 lines
6.5 KiB
Python
150 lines
6.5 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
|
|
|
import pytest
|
|
from PySide6.QtCore import QBuffer, QCoreApplication, QEvent, QIODevice, QPoint, Qt
|
|
from PySide6.QtGui import QColor, QDesktopServices, QFont, QImage, QPainter
|
|
from PySide6.QtTest import QTest
|
|
from PySide6.QtWidgets import QApplication
|
|
from test_diagnosis_drawer_visual import (
|
|
ActionRepository,
|
|
_open_dialog,
|
|
_select_tab,
|
|
)
|
|
from test_diagnosis_drawer_visual import (
|
|
application as application,
|
|
)
|
|
from test_diagnosis_drawer_visual import (
|
|
immediate_async as immediate_async,
|
|
)
|
|
from test_diagnosis_media_thumbnail_visual import (
|
|
_FakeManager,
|
|
_hold_remote_load,
|
|
_png_bytes,
|
|
)
|
|
|
|
from doctor_workstation.ui.diagnosis_drawer import _RemoteImageButton
|
|
from doctor_workstation.ui.diagnosis_media import ImagePreviewDialog
|
|
from doctor_workstation.ui.theme import _register_preferred_cjk_fonts
|
|
|
|
|
|
def _synthetic_image() -> bytes:
|
|
image = QImage(1600, 1200, QImage.Format.Format_ARGB32)
|
|
image.fill(QColor("#F4E3D8"))
|
|
painter = QPainter(image)
|
|
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
|
|
painter.setPen(Qt.PenStyle.NoPen)
|
|
painter.setBrush(QColor("#C37B85"))
|
|
painter.drawEllipse(440, 160, 720, 900)
|
|
painter.setPen(QColor("#67434A"))
|
|
painter.setFont(QFont("Arial", 36))
|
|
painter.drawText(image.rect(), Qt.AlignmentFlag.AlignCenter, "SYNTHETIC TEST IMAGE")
|
|
painter.end()
|
|
buffer = QBuffer()
|
|
assert buffer.open(QIODevice.OpenModeFlag.WriteOnly)
|
|
assert image.save(buffer, "PNG")
|
|
return bytes(buffer.data())
|
|
|
|
|
|
@pytest.mark.parametrize("mode", ["edit", "readonly"])
|
|
def test_real_note_thumbnail_click_keeps_drawer_and_previews_all_eight_images(
|
|
application: QApplication, monkeypatch: pytest.MonkeyPatch, mode: str,
|
|
) -> None:
|
|
"""Exercise the wired drawer click, not just the standalone lightbox class."""
|
|
monkeypatch.setattr(_RemoteImageButton, "load_url", _hold_remote_load)
|
|
external: list[str] = []
|
|
monkeypatch.setattr(QDesktopServices, "openUrl", lambda url: external.append(url.toString()) or True)
|
|
application.setFont(QFont(_register_preferred_cjk_fonts(), 10))
|
|
payload = _synthetic_image()
|
|
|
|
def offline_request(preview: ImagePreviewDialog, target: str) -> None:
|
|
preview._invalidate_request()
|
|
preview.apply_payload(payload, preview._generation)
|
|
|
|
monkeypatch.setattr(ImagePreviewDialog, "_request", offline_request)
|
|
dialog = _open_dialog(application, (1440, 900), mode=mode, repository=ActionRepository())
|
|
urls = [f"https://media.example.invalid/tongue-{index}.jpg" for index in range(8)]
|
|
if mode == "edit":
|
|
_select_tab(dialog, "notes")
|
|
dialog._fill_notes([{"id": 7001, "note_date": "2026-09-08", "content": "合成测试图片", "tongue_images": urls}])
|
|
QCoreApplication.sendPostedEvents(None, QEvent.Type.DeferredDelete)
|
|
timeline = dialog.drawer_notes_timeline if mode == "edit" else dialog._notes_timelines[0]
|
|
application.processEvents()
|
|
thumbs = timeline.findChildren(_RemoteImageButton, "DiagnosisTongueThumb")
|
|
assert len(thumbs) == 8
|
|
for thumb in thumbs:
|
|
assert thumb._apply_payload(payload, thumb._generation)
|
|
original_parent = dialog.parentWidget()
|
|
original_generation = dialog._generation
|
|
for index in (0, 7, 3):
|
|
QTest.mouseClick(thumbs[index], Qt.MouseButton.LeftButton, pos=QPoint(24, 32))
|
|
application.processEvents()
|
|
assert external == [], "Thumbnail click must not launch the system browser"
|
|
preview = dialog._image_preview
|
|
assert isinstance(preview, ImagePreviewDialog)
|
|
assert preview.isVisible() and preview.parentWidget() is dialog
|
|
assert dialog.isVisible() and dialog.parentWidget() is original_parent
|
|
assert dialog._generation == original_generation
|
|
assert preview.current_source == urls[index]
|
|
assert preview.sources == urls
|
|
assert not preview.canvas.pixmap().isNull()
|
|
fitted_width = preview.canvas.pixmap().width()
|
|
QTest.mouseClick(preview.zoom_button, Qt.MouseButton.LeftButton)
|
|
assert preview.canvas.pixmap().width() == 1600 > fitted_width
|
|
QTest.mouseClick(preview.next_button, Qt.MouseButton.LeftButton)
|
|
assert preview.current_source == urls[(index + 1) % 8]
|
|
QTest.mouseClick(preview.previous_button, Qt.MouseButton.LeftButton)
|
|
assert preview.current_source == urls[index]
|
|
if mode == "edit" and index == 7:
|
|
output = Path(__file__).resolve().parents[2] / "artifacts/patient-render-image-fix"
|
|
output.mkdir(parents=True, exist_ok=True)
|
|
assert dialog.grab().save(str(output / "notes-eight-thumbnails.png"))
|
|
QTest.mouseClick(preview.zoom_button, Qt.MouseButton.LeftButton)
|
|
application.processEvents()
|
|
assert preview.grab().save(str(output / "notes-image-preview.png"))
|
|
if index == 3:
|
|
QTest.keyClick(preview, Qt.Key.Key_Escape)
|
|
else:
|
|
QTest.mouseClick(preview.close_button, Qt.MouseButton.LeftButton)
|
|
application.processEvents()
|
|
assert dialog.isVisible() and timeline.isVisible()
|
|
assert dialog._image_preview is None
|
|
QCoreApplication.sendPostedEvents(None, QEvent.Type.DeferredDelete)
|
|
assert external == []
|
|
QTest.mouseClick(thumbs[4], Qt.MouseButton.LeftButton, pos=QPoint(24, 32))
|
|
preview = dialog._image_preview
|
|
QTest.mouseClick(preview.external_button, Qt.MouseButton.LeftButton)
|
|
assert external == [urls[4]]
|
|
dialog.reject()
|
|
application.processEvents()
|
|
assert dialog._image_preview is None
|
|
|
|
|
|
@pytest.mark.parametrize("close_with_escape", [False, True])
|
|
def test_preview_close_cancels_pending_response(
|
|
application: QApplication, monkeypatch: pytest.MonkeyPatch, close_with_escape: bool,
|
|
) -> None:
|
|
monkeypatch.setattr(ImagePreviewDialog, "_request", lambda self, target: None)
|
|
preview = ImagePreviewDialog(["https://media.example.invalid/pending.jpg"])
|
|
manager = _FakeManager(preview)
|
|
manager.queue(_png_bytes(80, 60))
|
|
preview._manager = manager
|
|
monkeypatch.undo()
|
|
preview.reload_current()
|
|
reply = manager.replies[-1]
|
|
generation = preview._generation
|
|
preview.show()
|
|
if close_with_escape:
|
|
QTest.keyClick(preview, Qt.Key.Key_Escape)
|
|
else:
|
|
QTest.mouseClick(preview.close_button, Qt.MouseButton.LeftButton)
|
|
assert reply.aborted
|
|
assert preview._generation > generation
|
|
reply.finished.emit()
|
|
assert preview._pixmap.isNull()
|
|
application.processEvents()
|