from __future__ import annotations import os from pathlib import Path import subprocess import sys _ROOT = Path(__file__).resolve().parents[1] def test_campaign_starts_and_contributes_its_provider_without_reporting() -> None: script = """ import importlib.abc import sys class Blocker(importlib.abc.MetaPathFinder): def find_spec(self, fullname, path=None, target=None): if fullname == 'govoplan_reporting' or fullname.startswith('govoplan_reporting.'): raise ModuleNotFoundError("Reporting is physically absent", name=fullname) return None sys.meta_path.insert(0, Blocker()) from govoplan_campaign.backend.manifest import get_manifest manifest = get_manifest() assert 'reporting' not in manifest.dependencies assert 'reporting' in manifest.optional_dependencies assert 'reporting.report_provider.campaigns' in manifest.capability_factories """ _run_probe(script) def test_reporting_starts_without_campaign_and_owns_the_global_route() -> None: script = """ import importlib.abc import sys class Blocker(importlib.abc.MetaPathFinder): def find_spec(self, fullname, path=None, target=None): if fullname == 'govoplan_campaign' or fullname.startswith('govoplan_campaign.'): raise ModuleNotFoundError("Campaign is physically absent", name=fullname) return None sys.meta_path.insert(0, Blocker()) from govoplan_reporting.backend.manifest import get_manifest manifest = get_manifest() assert 'campaigns' not in manifest.dependencies assert manifest.nav_items[0].path == '/reports' assert {item.path for item in manifest.frontend.routes} == {'/reports', '/reporting'} """ _run_probe(script) def test_reporting_with_campaign_uses_only_the_provider_contract() -> None: script = """ from govoplan_campaign.backend.manifest import get_manifest as campaign_manifest from govoplan_core.core.reporting import REPORT_PROVIDER_CAPABILITY_PREFIX from govoplan_reporting.backend.manifest import get_manifest as reporting_manifest reporting = reporting_manifest() campaign = campaign_manifest() provider_name = REPORT_PROVIDER_CAPABILITY_PREFIX + 'campaigns' assert provider_name in campaign.capability_factories assert provider_name in {item.name for item in campaign.provides_interfaces} assert 'campaigns' not in reporting.dependencies assert '/reports' not in {route.path for route in campaign.frontend.routes} provider = campaign.capability_factories[provider_name](None) assert provider.provider_id == 'campaigns' assert provider.contract_version == '1.0' """ _run_probe(script) def test_reporting_starts_without_files_or_mail_and_keeps_targets_optional() -> None: script = """ import importlib.abc import sys class Blocker(importlib.abc.MetaPathFinder): def find_spec(self, fullname, path=None, target=None): if fullname == 'govoplan_files' or fullname.startswith('govoplan_files.'): raise ModuleNotFoundError("Files is physically absent", name=fullname) if fullname == 'govoplan_mail' or fullname.startswith('govoplan_mail.'): raise ModuleNotFoundError("Mail is physically absent", name=fullname) return None sys.meta_path.insert(0, Blocker()) from govoplan_reporting.backend.contracts import ( CAPABILITY_REPORTING_PUBLICATION_FILES, CAPABILITY_REPORTING_PUBLICATION_MAIL, ) from govoplan_reporting.backend.manifest import get_manifest manifest = get_manifest() assert 'files' in manifest.optional_dependencies assert 'mail' in manifest.optional_dependencies assert CAPABILITY_REPORTING_PUBLICATION_FILES in manifest.capability_factories assert CAPABILITY_REPORTING_PUBLICATION_MAIL in manifest.capability_factories """ _run_probe(script) def _run_probe(source: str) -> None: environment = dict(os.environ) environment["PYTHONPATH"] = os.pathsep.join( ( str(_ROOT / "src"), str(_ROOT.parent / "govoplan-campaign" / "src"), str(_ROOT.parent / "govoplan-core" / "src"), environment.get("PYTHONPATH", ""), ) ) result = subprocess.run( [sys.executable, "-c", source], cwd=_ROOT, env=environment, text=True, capture_output=True, check=False, ) assert result.returncode == 0, result.stderr or result.stdout