"""Testes do parser bíblico. O parser reconstrói livro, capítulo e versículo a partir do texto extraído do PDF. O caso de referência é o PDF do projeto (Almeida Revista e Corrigida), em que o capítulo aparece como `[N]` e os versículos são numerados no início da linha. """ from __future__ import annotations import sys from pathlib import Path import pytest sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from app.bible_parser import ( # noqa: E402 BOOKS, BibleParser, parse_book_index, ) from app.extraction import PageText # noqa: E402 def make_page(number: int, text: str) -> PageText: return PageText(page=number, text=text) # --------------------------------------------------------------------------- # # Índice de livros # --------------------------------------------------------------------------- # def test_parse_book_index_reads_book_and_start_page(): text = """ INDICE ANTIGO TESTAMENTO: 5 Gênesis: 6 Êxodo: 168 Levítico: 303 NOVO TESTAMENTO: 2542 Mateus: 2543 Apocalipse: 3314 """ starts = parse_book_index(text) assert starts["Gênesis"] == 6 assert starts["Êxodo"] == 168 assert starts["Apocalipse"] == 3314 assert "ANTIGO TESTAMENTO" not in starts assert "NOVO TESTAMENTO" not in starts def test_parse_book_index_ignores_unknown_entries(): starts = parse_book_index("Gênesis: 6\nPagina solta: 12\n") assert starts == {"Gênesis": 6} # --------------------------------------------------------------------------- # # Atribuição de livro # --------------------------------------------------------------------------- # def test_book_is_assigned_by_page_range(): parser = BibleParser() starts = {"Gênesis": 6, "Êxodo": 168} assert parser.book_for_page(6, starts) == "Gênesis" assert parser.book_for_page(167, starts) == "Gênesis" assert parser.book_for_page(168, starts) == "Êxodo" assert parser.book_for_page(300, starts) == "Êxodo" def test_page_before_first_book_has_no_book(): parser = BibleParser() assert parser.book_for_page(3, {"Gênesis": 6}) is None def test_page_after_last_book_keeps_last_book(): parser = BibleParser() assert parser.book_for_page(3363, {"Gênesis": 6, "Êxodo": 168}) == "Êxodo" def test_book_falls_back_to_page_header_when_index_is_missing(): parser = BibleParser() text = "GÊNESIS\n\n[1]\n1 No princípio criou Deus os céus e a terra." chunks = parser.parse([make_page(6, text)], "biblia.pdf", {}) assert chunks, "o fallback por cabeçalho deveria produzir chunks" assert chunks[0].book == "Gênesis" assert chunks[0].chapter == 1 assert chunks[0].verse == 1 # --------------------------------------------------------------------------- # # Capítulos e versículos # --------------------------------------------------------------------------- # def test_parses_genesis_1_1(): parser = BibleParser() text = ( "GÊNESIS\n" "\n" "[1]\n" "1 No princípio criou Deus os céus e a terra.\n" "2 A terra era sem forma e vazia; e havia trevas\n" "sobre a face do abismo, mas o Espírito de Deus\n" "pairava sobre a face das águas.\n" ) chunks = parser.parse([make_page(6, text)], "biblia.pdf", {"Gênesis": 6}) assert len(chunks) == 2 first = chunks[0] assert first.book == "Gênesis" assert first.chapter == 1 assert first.verse == 1 assert first.page == 6 assert first.file == "biblia.pdf" assert first.text == "No princípio criou Deus os céus e a terra." second = chunks[1] assert second.verse == 2 assert second.text.endswith("pairava sobre a face das águas.") def test_chapter_marker_in_brackets_increments_chapter(): parser = BibleParser() text = ( "GÊNESIS\n" "[1]\n" "1 No princípio criou Deus os céus e a terra.\n" "\n" "[2]\n" "1 E disse Deus: haja luz. E houve luz.\n" ) chunks = parser.parse([make_page(6, text)], "biblia.pdf", {"Gênesis": 6}) assert {c.chapter for c in chunks} == {1, 2} chapter_two = next(c for c in chunks if c.chapter == 2) assert chapter_two.verse == 1 def test_verse_number_alone_on_a_line_joins_the_next_line(): parser = BibleParser() text = ( "GÊNESIS\n" "[1]\n" "1 No princípio criou Deus os céus e a terra.\n" "2\n" "A terra era sem forma e vazia.\n" ) chunks = parser.parse([make_page(6, text)], "biblia.pdf", {"Gênesis": 6}) assert len(chunks) == 2 assert chunks[1].verse == 2 assert chunks[1].text == "A terra era sem forma e vazia." def test_continuation_lines_are_appended_to_the_current_verse(): parser = BibleParser() text = ( "GÊNESIS\n" "[1]\n" "1 No princípio criou Deus os céus e a terra.\n" "sobre a face do abismo, mas o Espírito de Deus\n" ) chunks = parser.parse([make_page(6, text)], "biblia.pdf", {"Gênesis": 6}) assert len(chunks) == 1 assert chunks[0].text.endswith("sobre a face do abismo, mas o Espírito de Deus") def test_hyphenated_word_at_line_end_is_joined(): parser = BibleParser() text = ( "GÊNESIS\n" "[3]\n" "10 Respondeu-lhe o homem: Ouvi a tua voz no\n" "jardim e tive medo, porque estava nu; e esconde-\n" "me.\n" ) chunks = parser.parse([make_page(12, text)], "biblia.pdf", {"Gênesis": 6}) assert len(chunks) == 1 assert "escondeme" in chunks[0].text assert "esconde-\n" not in chunks[0].text def test_lexical_hyphen_is_preserved(): parser = BibleParser() text = ( "GÊNESIS\n" "[1]\n" "1 E disse Deus: haja uma separação entre águas e águas,\n" "para separar as águas.\n" ) chunks = parser.parse([make_page(6, text)], "biblia.pdf", {"Gênesis": 6}) assert chunks assert "para separar" in chunks[0].text def test_pages_outside_any_book_are_discarded(): parser = BibleParser() index_text = "Gênesis: 6\nÊxodo: 168\n" copyright_text = "L.C.C. Publicações Eletrônicas\nProibido todo uso comercial.\n" chunks = parser.parse( [make_page(3, index_text), make_page(6, "GÊNESIS\n[1]\n1 No princípio.\n"), make_page(3364, copyright_text)], "biblia.pdf", {"Gênesis": 6, "Êxodo": 168}, ) assert all(c.book == "Gênesis" for c in chunks) assert all("Publicações" not in c.text for c in chunks) def test_book_names_are_recognized_in_canonical_order(): # Esta edição da Almeida não inclui Neemias nem Ester: 64 livros. assert len(BOOKS) == 64 assert BOOKS[0] == "Gênesis" assert BOOKS[37] == "Mateus" assert BOOKS[-1] == "Apocalipse" assert "Neemias" not in BOOKS assert "Ester" not in BOOKS def test_esdras_is_followed_directly_by_job(): """O índice do PDF vai de Esdras (1407) direto para Jó (1440).""" assert BOOKS.index("Esdras") + 1 == BOOKS.index("Jó") def test_reference_is_formatted_as_book_chapter_verse(): parser = BibleParser() text = "GÊNESIS\n[1]\n1 No princípio criou Deus os céus e a terra.\n" chunks = parser.parse([make_page(6, text)], "biblia.pdf", {"Gênesis": 6}) assert chunks[0].reference == "Gênesis 1:1" @pytest.mark.parametrize( "raw,expected", [ ("Gênesis", "Gênesis"), ("Êxodo", "Êxodo"), ("Números", "Números"), ("Cântico dos Cânticos", "Cântico dos Cânticos"), ("I Coríntios", "I Coríntios"), ("II João", "II João"), ], ) def test_canonical_book_names_are_preserved(raw, expected): assert raw in BOOKS assert expected == raw