"""Shared pytest fixtures and path setup. Stubs heavy optional dependencies (``fitz``/PyMuPDF, ``bs4``/BeautifulSoup, ``openai``) so the test suite can run without the full prod requirements installed. The tests in this directory are pure unit tests over parser logic and prompt formatters — they neither parse PDFs nor make HTTP calls, so the stubs are inert placeholders that satisfy the import machinery but never get exercised. If a test ever does need real PyMuPDF or httpx integration, give it a fixture marked with ``@pytest.mark.integration`` and skip it by default. """ import sys import types from pathlib import Path # Make the `app` package importable when pytest is run from the webapp/ root. ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT)) def _stub(name: str, **attrs) -> None: if name in sys.modules: return mod = types.ModuleType(name) for k, v in attrs.items(): setattr(mod, k, v) sys.modules[name] = mod _stub("fitz") # PyMuPDF — used for PDF parsing, not in unit tests _stub("bs4", BeautifulSoup=lambda *a, **kw: None) # only needed by NRWAdapter live calls _stub("openai", OpenAI=lambda **kw: None) # only needed by embeddings live calls # pydantic_settings is a small but external dep that's not in the test # environment. Stub it with a minimal BaseSettings shim so app.config can # import without crashing — the tests don't actually read settings values. class _BaseSettingsShim: model_config: dict = {} def __init__(self, **kwargs): for k, v in kwargs.items(): setattr(self, k, v) def _settings_config_dict(**kwargs): return kwargs _stub("pydantic_settings", BaseSettings=_BaseSettingsShim, SettingsConfigDict=_settings_config_dict)