OPEN SOURCE
software/tests/test_widgets_extended.py
このサイトで読み、必要なファイルを保存できます。
日常訳はAIを用いて作成された翻訳です。人間の聖書学・原語の専門家による全訳の検証は確認されていません。既存の翻訳や原語資料と照らし合わせてお読みください。
1"""Extended tests for TUI widgets to improve coverage."""23import json4from datetime import datetime5from io import StringIO6from pathlib import Path78import pytest9from rich.console import Console10from rich.text import Text1112from src.models.evaluation import (13EvaluationScore,14VerseEvaluation,15)16from src.tui.data_provider import TUIDataProvider, VerseData17from src.tui.widgets import (18ChapterQualitySummary,19DetailPanel,20EvaluationSummaryTable,21)222324@pytest.fixture25def temp_data_dir(tmp_path: Path) -> Path:26"""Create a temporary data directory with test data."""27# Create source directories28sources_dir = tmp_path / "sources"29(sources_dir / "greek").mkdir(parents=True)30(sources_dir / "english" / "kjv").mkdir(parents=True)3132# Create Greek source33greek_data = {"1:1": {"text": "Ἐν ἀρχῇ", "translit": "En archē"}}34with (sources_dir / "greek" / "john.json").open("w") as f:35json.dump(greek_data, f)3637# Create KJV source38kjv_data = {"1:1": "In the beginning was the Word"}39with (sources_dir / "english" / "kjv" / "john.json").open("w") as f:40json.dump(kjv_data, f)4142# Create output directory with translations43output_dir = tmp_path / "output" / "john"44output_dir.mkdir(parents=True)4546chapter_data = {47"book": "john",48"chapter": 1,49"verses": {50"1": {51"text": "初めに言葉があった。",52"model": "claude-sonnet-4",53"timestamp": "2026-01-13T00:00:00Z",54"glossary_terms_applied": [],55},56},57}58with (output_dir / "chapter_01.json").open("w") as f:59json.dump(chapter_data, f)6061# Create evaluation file with all score levels62eval_data = {63"book": "john",64"chapter": 1,65"evaluator_model": "claude-opus-4-5",66"evaluated_at": "2026-01-13T00:00:00Z",67"verses": {68"1": {69"scores": {70"theological_accuracy": {71"score": 95,72"confidence": 90,73"reasoning": "Excellent",74},75"source_fidelity": {76"score": 75,77"confidence": 85,78"reasoning": "Good but could improve",79},80"naturalness": {81"score": 65,82"confidence": 80,83"reasoning": "Below threshold",84},85},86"overall_score": 78.3,87"flags": ["naturalness_concern"],88"notes": "Consider improving naturalness",89"timestamp": "2026-01-13T00:00:00Z",90},91},92"aggregate": {93"scores": {94"theological_accuracy": 95.0,95"source_fidelity": 75.0,96"naturalness": 65.0,97},98"overall": 78.3,99"flagged_count": 1,100"flagged_verses": [1],101},102}103with (output_dir / "chapter_01_eval.json").open("w") as f:104json.dump(eval_data, f)105106# Create metadata directory107metadata_dir = tmp_path / "metadata"108metadata_dir.mkdir(parents=True)109110return tmp_path111112113def _render_to_string(renderable) -> str:114"""Render content to a string for testing."""115console = Console(file=StringIO(), force_terminal=True, width=120)116console.print(renderable)117return console.file.getvalue()118119120class TestDetailPanelScoreColors:121"""Tests for DetailPanel score color coding."""122123def test_render_with_excellent_score(self, temp_data_dir: Path) -> None:124"""Test rendering with excellent score (>= 90)."""125provider = TUIDataProvider(temp_data_dir)126panel = DetailPanel(provider, id="detail")127128# Create verse data with excellent score129panel.current_verse = VerseData(130book="john",131chapter=1,132verse=1,133greek_text="Ἐν ἀρχῇ",134kjv_text="In the beginning",135japanese_reference=None,136glossary_terms=[],137translation_text="初めに言葉があった。",138translation_model="claude-sonnet-4",139translation_timestamp="2026-01-13",140evaluation=VerseEvaluation(141verse_number=1,142evaluator_model="test",143timestamp=datetime.utcnow(),144scores={145"theological_accuracy": EvaluationScore(146dimension="theological_accuracy",147score=95.0,148confidence=90.0,149reasoning="Excellent",150),151},152flags=[],153notes=None,154),155)156157rendered_str = _render_to_string(panel.render())158# Should show excellent score indicator159assert "95" in rendered_str160161def test_render_with_concern_score(self, temp_data_dir: Path) -> None:162"""Test rendering with concerning score (< 70)."""163provider = TUIDataProvider(temp_data_dir)164panel = DetailPanel(provider, id="detail")165166# Create verse data with low score167panel.current_verse = VerseData(168book="john",169chapter=1,170verse=1,171greek_text="Ἐν ἀρχῇ",172kjv_text="In the beginning",173japanese_reference=None,174glossary_terms=[],175translation_text="初めに言葉があった。",176translation_model="claude-sonnet-4",177translation_timestamp="2026-01-13",178evaluation=VerseEvaluation(179verse_number=1,180evaluator_model="test",181timestamp=datetime.utcnow(),182scores={183"naturalness": EvaluationScore(184dimension="naturalness",185score=55.0,186confidence=80.0,187reasoning="Needs work",188),189},190flags=["naturalness_concern"],191notes="Needs improvement",192),193)194195rendered_str = _render_to_string(panel.render())196assert "55" in rendered_str197198def test_render_with_multiple_flags(self, temp_data_dir: Path) -> None:199"""Test rendering verse with multiple flags."""200provider = TUIDataProvider(temp_data_dir)201panel = DetailPanel(provider, id="detail")202203panel.current_verse = VerseData(204book="john",205chapter=1,206verse=1,207greek_text="Ἐν ἀρχῇ",208kjv_text="In the beginning",209japanese_reference=None,210glossary_terms=[],211translation_text="初めに言葉があった。",212translation_model="claude-sonnet-4",213translation_timestamp="2026-01-13",214evaluation=VerseEvaluation(215verse_number=1,216evaluator_model="test",217timestamp=datetime.utcnow(),218scores={219"theological_accuracy": EvaluationScore(220dimension="theological_accuracy",221score=60.0,222confidence=70.0,223reasoning="Concern",224),225"source_fidelity": EvaluationScore(226dimension="source_fidelity",227score=55.0,228confidence=65.0,229reasoning="Issue",230),231},232flags=["theological_concern", "source_fidelity_concern"],233notes="Multiple issues",234),235)236237rendered_str = _render_to_string(panel.render())238# Should contain flag indicators239assert "concern" in rendered_str.lower() or "flag" in rendered_str.lower()240241242class TestEvaluationSummaryTableScoreBars:243"""Tests for EvaluationSummaryTable visual bars."""244245def test_render_with_varied_scores(self) -> None:246"""Test rendering with various score levels."""247table = EvaluationSummaryTable(id="eval-table")248table.set_scores({249"theological_accuracy": (95.0, 90.0), # Excellent250"source_fidelity": (75.0, 85.0), # Good251"naturalness": (55.0, 80.0), # Concern252"readability": (85.0, 90.0), # Good253"glossary_consistency": (100.0, 100.0), # Perfect254"literary_quality": (65.0, 75.0), # Below threshold255})256257rendered_str = _render_to_string(table.render())258259# Should contain all dimension scores260assert "95" in rendered_str261assert "75" in rendered_str262assert "55" in rendered_str263264def test_render_with_scores_uses_bars(self) -> None:265"""Test rendering includes visual bars."""266table = EvaluationSummaryTable(id="eval-table")267table.set_scores({"theological_accuracy": (90.0, 95.0)})268269rendered_str = _render_to_string(table.render())270# Should contain bar characters271assert "█" in rendered_str or "░" in rendered_str272273274class TestChapterQualitySummary:275"""Tests for ChapterQualitySummary widget."""276277def test_render_empty(self, temp_data_dir: Path) -> None:278"""Test rendering with no chapter selected."""279provider = TUIDataProvider(temp_data_dir)280widget = ChapterQualitySummary(provider, id="quality-summary")281rendered = widget.render()282rendered_str = _render_to_string(rendered)283assert "Select a chapter" in rendered_str or "Chapter" in rendered_str284285def test_render_with_chapter_data(self, temp_data_dir: Path) -> None:286"""Test rendering with chapter selected."""287provider = TUIDataProvider(temp_data_dir)288widget = ChapterQualitySummary(provider, id="quality-summary")289widget.update_chapter("john", 1)290291rendered_str = _render_to_string(widget.render())292# Should show chapter info293assert "JOHN" in rendered_str or "john" in rendered_str.lower()294295def test_render_with_no_eval_data(self, temp_data_dir: Path) -> None:296"""Test rendering chapter with no evaluation."""297provider = TUIDataProvider(temp_data_dir)298widget = ChapterQualitySummary(provider, id="quality-summary")299# Select a chapter that doesn't have evaluation300widget.update_chapter("john", 99)301302rendered_str = _render_to_string(widget.render())303assert "No evaluation" in rendered_str or "--evaluate" in rendered_str304305306class TestDimensionNameFormatting:307"""Tests for dimension name formatting in widgets."""308309def test_format_dimension_names_table(self) -> None:310"""Test dimension name formatting in EvaluationSummaryTable."""311table = EvaluationSummaryTable(id="eval-table")312313# Test that dimension names are formatted314formatted = table._format_dimension_name("theological_accuracy")315assert "Theolog" in formatted or "theological" in formatted.lower()316317formatted = table._format_dimension_name("source_fidelity")318assert "Fidelity" in formatted or "source" in formatted.lower()319320formatted = table._format_dimension_name("glossary_consistency")321assert "Glossary" in formatted or "consistency" in formatted.lower()322323def test_format_dimension_names_panel(self, temp_data_dir: Path) -> None:324"""Test dimension name formatting in DetailPanel."""325provider = TUIDataProvider(temp_data_dir)326panel = DetailPanel(provider, id="detail")327328formatted = panel._format_dimension_name("theological_accuracy")329assert "Theolog" in formatted330331formatted = panel._format_dimension_name("unknown_dimension")332# Unknown dimensions should be title-cased333assert "Unknown" in formatted or "Dimension" in formatted334335336class TestScoreColorHelpers:337"""Tests for score color helper methods."""338339def test_get_score_color_excellent(self) -> None:340"""Test color for excellent scores."""341table = EvaluationSummaryTable(id="eval-table")342color = table._get_score_color(95.0)343assert color == "green"344345def test_get_score_color_good(self) -> None:346"""Test color for good scores."""347table = EvaluationSummaryTable(id="eval-table")348color = table._get_score_color(80.0)349assert color == "yellow"350351def test_get_score_color_concern(self) -> None:352"""Test color for concerning scores."""353table = EvaluationSummaryTable(id="eval-table")354color = table._get_score_color(65.0)355assert color == "orange1"356357def test_get_score_color_poor(self) -> None:358"""Test color for poor scores."""359table = EvaluationSummaryTable(id="eval-table")360color = table._get_score_color(50.0)361assert color == "red"362363364class TestDetailPanelHelpers:365"""Tests for DetailPanel helper methods."""366367def test_get_quality_indicator_excellent(self, temp_data_dir: Path) -> None:368"""Test indicator for excellent quality."""369provider = TUIDataProvider(temp_data_dir)370panel = DetailPanel(provider, id="detail")371indicator = panel._get_quality_indicator(95.0)372assert indicator == "●"373374def test_get_quality_indicator_good(self, temp_data_dir: Path) -> None:375"""Test indicator for good quality."""376provider = TUIDataProvider(temp_data_dir)377panel = DetailPanel(provider, id="detail")378indicator = panel._get_quality_indicator(80.0)379assert indicator == "◐"380381def test_get_quality_indicator_concern(self, temp_data_dir: Path) -> None:382"""Test indicator for concerning quality."""383provider = TUIDataProvider(temp_data_dir)384panel = DetailPanel(provider, id="detail")385indicator = panel._get_quality_indicator(65.0)386assert indicator == "○"387388def test_get_quality_indicator_poor(self, temp_data_dir: Path) -> None:389"""Test indicator for poor quality."""390provider = TUIDataProvider(temp_data_dir)391panel = DetailPanel(provider, id="detail")392indicator = panel._get_quality_indicator(50.0)393assert indicator == "✗"394395396class TestFlagFormatting:397"""Tests for flag formatting in DetailPanel."""398399def test_format_flag_theological(self, temp_data_dir: Path) -> None:400"""Test formatting theological flag."""401provider = TUIDataProvider(temp_data_dir)402panel = DetailPanel(provider, id="detail")403formatted = panel._format_flag("theological_concern")404assert "theological" in formatted or "concern" in formatted405406def test_format_flag_source(self, temp_data_dir: Path) -> None:407"""Test formatting source fidelity flag."""408provider = TUIDataProvider(temp_data_dir)409panel = DetailPanel(provider, id="detail")410formatted = panel._format_flag("source_fidelity_concern")411assert "source" in formatted or "fidelity" in formatted412413def test_format_flag_with_low(self, temp_data_dir: Path) -> None:414"""Test formatting flag with 'low' keyword."""415provider = TUIDataProvider(temp_data_dir)416panel = DetailPanel(provider, id="detail")417formatted = panel._format_flag("low_confidence")418# 'low' should be replaced with arrow419assert "↓" in formatted or "confidence" in formatted420