grantforge-api / backend /tests /test_advisor_brief_extract.py
GrantForge Bot
Deploy sha-565ad85979610064f6d1c18ab3b6404357d61073 — source build (no GHCR)
ce8f04a
Raw
History Blame Contribute Delete
3.04 kB
"""Fixture-backed tests for regulation text → structured advisor brief."""
from __future__ import annotations
from core.grants.advisor_brief_extract import (
brief_quality_score,
build_advisor_brief_from_text,
empty_advisor_brief,
is_brief_usable,
merge_briefs,
)
# Representative regulation / instruction fragment (Polish grant style)
RICH_REGULATION = """
REGULAMIN NABORU — Ścieżka SMART 2026
§ 1. Wnioskodawca musi posiadać status MŚP oraz siedzibę na terenie Polski.
§ 2. Intensywność dofinansowania wynosi do 70% kosztów kwalifikowalnych.
§ 3. Maksymalne dofinansowanie projektu nie może przekroczyć 20 mln zł.
§ 4. Projekt musi spełniać zasadę DNSH (Do No Significant Harm) i wymogi środowiskowe.
§ 5. Wkład własny wynosi minimum 30% kosztów kwalifikowalnych.
§ 6. Wyklucza się koszty niekwalifikowalne: grzywny, odsetki karne, nabycie gruntu.
Art. 10. Wniosek musi zawierać następujące elementy:
1. Opis projektu i innowacyjności
2. Budżet i harmonogram rzeczowo-finansowy
3. Wskaźniki rezultatu
4. Analiza ryzyka
Załączniki obowiązkowe:
Załącznik 1. Oświadczenie o statusie MŚP
Załącznik 2. Formularz kosztów kwalifikowalnych
Załącznik 3. Kosztorys inwestorski
Beneficjent jest zobowiązany do przestrzegania limitu pomocy de minimis.
Poziom gotowości technologicznej TRL: 6-8.
"""
EMPTYISH = "Lorem ipsum dolor sit amet. Contact us at biuro@example.com."
def test_rich_regulation_yields_nonempty_brief():
brief = build_advisor_brief_from_text(RICH_REGULATION, source_url="https://example.gov.pl/reg.pdf")
assert brief["text_chars"] > 100
assert brief["key_rules"], "expected key_rules from §/must patterns"
assert brief["required_sections"] or brief["required_attachments"], (
"expected sections or attachments from rich regulation"
)
assert brief["attention_points"], "expected attention points (DNSH/MŚP/etc.)"
assert is_brief_usable(brief) is True
assert brief["usable"] is True
assert brief_quality_score(brief) >= 20
def test_empty_text_yields_unusable_brief():
brief = build_advisor_brief_from_text("")
assert brief["usable"] is False
assert not brief["key_rules"]
assert is_brief_usable(brief) is False
def test_noise_text_not_usable():
brief = build_advisor_brief_from_text(EMPTYISH)
# May extract little or nothing — must not pretend usable completeness
assert brief["usable"] is False or brief_quality_score(brief) < 30
def test_empty_advisor_brief_helper():
b = empty_advisor_brief(reason="no_pack")
assert b["empty_reason"] == "no_pack"
assert is_brief_usable(b) is False
def test_merge_briefs_combines_signals():
a = build_advisor_brief_from_text(RICH_REGULATION)
b = build_advisor_brief_from_text(
"§ 99. Wnioskodawca musi złożyć załącznik: Formularz RODO.\n"
"Załącznik nr 4. Pełnomocnictwo."
)
m = merge_briefs(a, b)
assert len(m["key_rules"]) >= len(a["key_rules"])
assert is_brief_usable(m)