"""Glyph-fragmented CVs must not silently lose every substring check. The defect these cover, found on a live application: a CV whose PDF positions each glyph separately came out of pypdf's default mode as one character per line. The text was all there, so the LLM read it and scored the candidate fine — but `linkedin.com/in/...` was spelled across forty lines, so the LinkedIn scan found nothing, and so did the skills, company and education clamps, which all ask whether a string appears in the resume. No real PDF and no pypdf call: a stub reader returns canned page text, which is the only input the function under test actually reads. """ from __future__ import annotations import pytest from app.services.pdf import extract_pdf_text, is_glyph_fragmented # The real shape of the failure, taken from the CV that exposed it. FRAGMENTED = "\n".join("LinkedIn:linkedin.com/in/mohammad-raza-digital-marketer") REPAIRED = ( "MOHAMMAD RAZA\n" "Performance Marketing Specialist\n" "Karachi, Pakistan | +923362837939\n" "LinkedIn:linkedin.com/in/mohammad-raza-digital-marketer\n" ) ORDINARY = "\n".join(f"Line {i} of an ordinary resume with real words on it." for i in range(30)) class _Page: """Minimal pypdf page: default text, and optionally a layout-mode variant.""" def __init__(self, default, layout=None, layout_raises=False): self._default = default self._layout = layout self._layout_raises = layout_raises def extract_text(self, extraction_mode="plain"): if extraction_mode == "layout": if self._layout_raises: raise ValueError("layout mode unsupported") return self._layout return self._default class _Reader: def __init__(self, *pages): self.pages = list(pages) class TestIsGlyphFragmented: def test_one_character_per_line_is_fragmented(self): assert is_glyph_fragmented(FRAGMENTED) is True def test_ordinary_text_is_not(self): assert is_glyph_fragmented(ORDINARY) is False def test_short_input_never_trips_it(self): # A two-line PDF of initials is not evidence of a broken extractor, and # treating it as such would send every tiny document through layout mode. assert is_glyph_fragmented("A\nB\nC") is False @pytest.mark.parametrize("text", ["", None]) def test_empty_is_not_fragmented(self, text): assert is_glyph_fragmented(text) is False class TestExtractPdfText: def test_ordinary_pdf_is_returned_untouched(self): # The guarantee that matters most: a CV that extracts cleanly today must # keep extracting byte-identically, never routed through layout mode. reader = _Reader(_Page(ORDINARY, layout="LAYOUT SHOULD NOT BE USED")) assert extract_pdf_text(reader) == ORDINARY def test_fragmented_pdf_falls_back_to_layout(self): reader = _Reader(_Page(FRAGMENTED, layout=REPAIRED)) out = extract_pdf_text(reader) assert out == REPAIRED assert "linkedin.com/in/mohammad-raza-digital-marketer" in out.lower() def test_layout_that_is_also_fragmented_is_rejected(self): reader = _Reader(_Page(FRAGMENTED, layout=FRAGMENTED)) assert extract_pdf_text(reader) == FRAGMENTED def test_empty_layout_is_rejected(self): # Fragmented text still scores a candidate. Empty text fails them outright. reader = _Reader(_Page(FRAGMENTED, layout=" ")) assert extract_pdf_text(reader) == FRAGMENTED def test_layout_mode_unsupported_falls_back_to_default(self): reader = _Reader(_Page(FRAGMENTED, layout_raises=True)) assert extract_pdf_text(reader) == FRAGMENTED def test_pages_are_joined(self): reader = _Reader(_Page("page one text here"), _Page("page two text here")) assert extract_pdf_text(reader) == "page one text here\npage two text here"