Pre-publication review draft
日常訳NICHIJOYAKU日本語 ↗

OPEN SOURCE

software/tests/test_output.py

Read on this site and download the files you need.

Nichijoyaku was created using AI. A complete review by human biblical-language and biblical-studies specialists has not been established. Read alongside established translations and original-language resources.

← Back to the open-source guide

software/tests/test_output.py267 linesDownload this file ↓

This is the same source included in the download. Each line number is a link you can save or share.

File verification detailsSHA-256 e4d6f551d57d13bbf829cf408823a46b43b234809ba9de05747fcca125e021d0
1"""Tests for output formatters."""23import json4import pytest5from pathlib import Path67from src.data.storage import Storage8from src.models.verse import BookMetadata, TranslationOutput, VerseReference9from src.output.formatters import OutputFormatter101112@pytest.fixture13def temp_data_dir(tmp_path: Path) -> Path:14    """Create temporary data directory with translations."""15    (tmp_path / "output" / "john").mkdir(parents=True)16    (tmp_path / "progress").mkdir(parents=True)17    return tmp_path181920@pytest.fixture21def storage_with_translations(temp_data_dir: Path) -> Storage:22    """Create storage with test translations."""23    storage = Storage(temp_data_dir)2425    # Add translations for John chapter 126    for verse_num in range(1, 6):27        ref = VerseReference(book="john", chapter=1, verse=verse_num)28        output = TranslationOutput(29            reference=ref,30            text=f"ヨハネ第1章{verse_num}節の翻訳。",31            model="test-model",32        )33        storage.save_translation(output)3435    # Add translations for John chapter 236    for verse_num in range(1, 4):37        ref = VerseReference(book="john", chapter=2, verse=verse_num)38        output = TranslationOutput(39            reference=ref,40            text=f"ヨハネ第2章{verse_num}節の翻訳。",41            model="test-model",42        )43        storage.save_translation(output)4445    return storage464748class TestOutputFormatter:49    """Tests for OutputFormatter."""5051    def test_export_chapter_json(52        self, storage_with_translations: Storage, tmp_path: Path53    ) -> None:54        """Test exporting chapter as JSON."""55        formatter = OutputFormatter(storage_with_translations)56        output_dir = tmp_path / "exports"5758        path = formatter.export_chapter_json("john", 1, output_dir)5960        assert path.exists()61        with path.open("r", encoding="utf-8") as f:62            data = json.load(f)6364        assert data["book"] == "john"65        assert data["chapter"] == 166        assert len(data["verses"]) == 56768    def test_export_chapter_text(69        self, storage_with_translations: Storage, tmp_path: Path70    ) -> None:71        """Test exporting chapter as plain text."""72        formatter = OutputFormatter(storage_with_translations)73        output_dir = tmp_path / "exports"7475        path = formatter.export_chapter_text("john", 1, output_dir)7677        assert path.exists()78        content = path.read_text(encoding="utf-8")7980        assert "John Chapter 1" in content81        assert "ヨハネ第1章1節の翻訳。" in content8283    def test_export_chapter_html(84        self, storage_with_translations: Storage, tmp_path: Path85    ) -> None:86        """Test exporting chapter as HTML."""87        formatter = OutputFormatter(storage_with_translations)88        output_dir = tmp_path / "exports"8990        path = formatter.export_chapter_html("john", 1, output_dir)9192        assert path.exists()93        content = path.read_text(encoding="utf-8")9495        assert "<!DOCTYPE html>" in content96        assert '<html lang="ja">' in content97        assert "ヨハネ第1章1節の翻訳。" in content9899    def test_export_chapter_html_with_metadata(100        self, storage_with_translations: Storage, tmp_path: Path101    ) -> None:102        """Test exporting chapter HTML with metadata."""103        formatter = OutputFormatter(storage_with_translations)104        output_dir = tmp_path / "exports"105106        metadata = BookMetadata(107            book="john",108            name_japanese="ヨハネによる福音書",109            name_english="Gospel of John",110            testament="NT",111            author="John",112            themes=[],113            description="Test",114            chapter_count=21,115            verse_count=879,116        )117118        path = formatter.export_chapter_html("john", 1, output_dir, metadata)119120        content = path.read_text(encoding="utf-8")121        assert "ヨハネによる福音書" in content122        assert "第1章" in content123124    def test_export_book_json(125        self, storage_with_translations: Storage, tmp_path: Path126    ) -> None:127        """Test exporting entire book as JSON."""128        formatter = OutputFormatter(storage_with_translations)129        output_dir = tmp_path / "exports"130131        path = formatter.export_book_json("john", output_dir)132133        assert path.exists()134        with path.open("r", encoding="utf-8") as f:135            data = json.load(f)136137        assert data["book"] == "john"138        assert "1" in data["chapters"]139        assert "2" in data["chapters"]140141    def test_export_book_text(142        self, storage_with_translations: Storage, tmp_path: Path143    ) -> None:144        """Test exporting entire book as plain text."""145        formatter = OutputFormatter(storage_with_translations)146        output_dir = tmp_path / "exports"147148        path = formatter.export_book_text("john", output_dir)149150        assert path.exists()151        content = path.read_text(encoding="utf-8")152153        assert "John" in content154        assert "Chapter 1" in content155        assert "Chapter 2" in content156157    def test_export_book_json_empty(158        self, temp_data_dir: Path, tmp_path: Path159    ) -> None:160        """Test exporting book with no translations."""161        storage = Storage(temp_data_dir)162        formatter = OutputFormatter(storage)163        output_dir = tmp_path / "exports"164165        path = formatter.export_book_json("matthew", output_dir)166167        assert path.exists()168        with path.open("r", encoding="utf-8") as f:169            data = json.load(f)170171        assert data["book"] == "matthew"172        assert data["chapters"] == {}173174    def test_export_book_text_empty(175        self, temp_data_dir: Path, tmp_path: Path176    ) -> None:177        """Test exporting empty book as text."""178        storage = Storage(temp_data_dir)179        formatter = OutputFormatter(storage)180        output_dir = tmp_path / "exports"181182        path = formatter.export_book_text("matthew", output_dir)183184        assert path.exists()185        content = path.read_text(encoding="utf-8")186        assert "Matthew" in content187188    def test_export_creates_directory(189        self, storage_with_translations: Storage, tmp_path: Path190    ) -> None:191        """Test export creates output directory if needed."""192        formatter = OutputFormatter(storage_with_translations)193        output_dir = tmp_path / "nested" / "deep" / "exports"194195        path = formatter.export_chapter_json("john", 1, output_dir)196197        assert path.exists()198        assert output_dir.exists()199200    def test_export_chapter_html_with_furigana(201        self, temp_data_dir: Path, tmp_path: Path202    ) -> None:203        """Test exporting chapter HTML includes ruby tags for furigana."""204        storage = Storage(temp_data_dir)205206        # Create translation with furigana207        ref = VerseReference(book="john", chapter=1, verse=1)208        output = TranslationOutput(209            reference=ref,210            text="神は愛です",211            text_with_furigana="神[かみ]は愛[あい]です",212            furigana_annotations=[213                {214                    "start_offset": 0,215                    "end_offset": 1,216                    "base_text": "神",217                    "reading": "かみ",218                },219                {220                    "start_offset": 2,221                    "end_offset": 3,222                    "base_text": "愛",223                    "reading": "あい",224                },225            ],226            model="test-model",227        )228        storage.save_translation(output)229230        formatter = OutputFormatter(storage)231        output_dir = tmp_path / "exports"232        path = formatter.export_chapter_html("john", 1, output_dir)233234        content = path.read_text(encoding="utf-8")235236        # Check ruby tags are present237        assert "<ruby>神<rt>かみ</rt></ruby>" in content238        assert "<ruby>愛<rt>あい</rt></ruby>" in content239240    def test_export_chapter_html_includes_ruby_css(241        self, storage_with_translations: Storage, tmp_path: Path242    ) -> None:243        """Test HTML export includes CSS for ruby styling."""244        formatter = OutputFormatter(storage_with_translations)245        output_dir = tmp_path / "exports"246247        path = formatter.export_chapter_html("john", 1, output_dir)248        content = path.read_text(encoding="utf-8")249250        assert "ruby { ruby-position: over; }" in content251        assert "rt { font-size: 0.6em; color: #666; }" in content252253    def test_export_chapter_html_fallback_without_furigana(254        self, storage_with_translations: Storage, tmp_path: Path255    ) -> None:256        """Test HTML export falls back to plain text without furigana."""257        formatter = OutputFormatter(storage_with_translations)258        output_dir = tmp_path / "exports"259260        path = formatter.export_chapter_html("john", 1, output_dir)261        content = path.read_text(encoding="utf-8")262263        # Original test translations don't have furigana, should use plain text264        assert "ヨハネ第1章1節の翻訳。" in content265        # Should not have any ruby tags for these translations266        assert "<ruby>" not in content or "ヨハネ" not in content.split("<ruby>")[0]267