"""UI가 실제로 만들어지고 자막이 그려지는지 확인한다 (offscreen 렌더링).""" from __future__ import annotations import os import pytest pytest.importorskip("PySide6") os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") from PySide6.QtGui import QImage, QPainter # noqa: E402 from PySide6.QtWidgets import QApplication # noqa: E402 from hearo.config import AppConfig # noqa: E402 from hearo.core.events import EngineState, EngineStatus, TranslationLine # noqa: E402 from hearo.ui.main_window import MainWindow # noqa: E402 from hearo.ui.overlay import paint_subtitle # noqa: E402 @pytest.fixture(scope="session") def qapp(): app = QApplication.instance() or QApplication([]) yield app @pytest.fixture def window(qapp, tmp_path, monkeypatch): monkeypatch.setattr("hearo.constants.user_data_dir", lambda: tmp_path) config = AppConfig() config.models.preload_on_start = False config.glossary.path = str(tmp_path / "glossary.json") win = MainWindow(config) yield win win.engine.shutdown() win.overlay.close() win.close() def test_main_window_builds_all_pages(window): assert window.stack.count() == 5 def test_navigation_switches_pages(window): for index in range(5): window._goto_page(index) assert window.stack.currentIndex() == index def test_status_updates_toggle_button(window): window._on_status(EngineStatus(EngineState.RUNNING, "듣는 중")) assert window.home_page.toggle_button.text() == "번역 정지" window._on_status(EngineStatus(EngineState.IDLE, "대기 중")) assert window.home_page.toggle_button.text() == "번역 시작" def test_final_line_reaches_overlay_and_log(window): window.config.log_transcripts = False window._on_line( TranslationLine("hello", "안녕하세요", "en", "ko", is_final=True, latency_s=1.2) ) assert window.overlay._final_text == "안녕하세요" assert window.home_page.log_list.count() == 1 def test_partial_line_is_not_logged(window): window.config.log_transcripts = False window._on_line(TranslationLine("hel", "", "en", "ko", is_final=False)) assert window.home_page.log_list.count() == 0 def test_tier_selection_updates_config(window): window.models_page._on_tier_selected(window.models_page._cards[3].tier) assert window.config.models.tier == "precision" def test_subtitle_style_edit_propagates(window): window.subtitle_page.size_spin.setValue(60) assert window.config.subtitle.font_size == 60 def test_paint_subtitle_actually_draws_pixels(qapp): """자막 글씨가 투명 이미지 위에 실제로 그려지는지 (빈 화면이면 실패). 배경 상자가 픽셀을 채워버리면 글씨 유무를 알 수 없으므로 배경은 끄고 잰다. """ st = AppConfig().subtitle st.background_opacity = 0 image = QImage(900, 200, QImage.Format.Format_ARGB32) image.fill(0) painter = QPainter(image) paint_subtitle(painter, image.rect(), st, "안녕하세요 반갑습니다", "Hello there") painter.end() non_transparent = sum( 1 for y in range(0, image.height(), 4) for x in range(0, image.width(), 4) if image.pixelColor(x, y).alpha() > 0 ) assert non_transparent > 100