"""Shared test helpers. Connector tests never hit the network: they replay fixtures through `extract_from_fixture`.""" from __future__ import annotations from datetime import UTC, datetime from pathlib import Path import pytest from aiatlas.sdk.connector import BaseConnector, RunContext from aiatlas.sdk.facts import Facts, Target from aiatlas.sdk.fetch import file_result FIXTURES = Path(__file__).parent / "fixtures" def fixture_path(*parts: str) -> Path: return FIXTURES.joinpath(*parts) async def extract_from_fixture(connector: BaseConnector, target: Target, path: Path, *, content_type: str = "text/html") -> Facts: """Parse a saved response and run the connector's extract() — no database, no network.""" ctx = RunContext(run_id="test", connector=connector, fetcher=None, started_at=datetime.now(UTC)) # type: ignore[arg-type] res = file_result(str(path), url=target.url, content_type=content_type) parsed = connector.parse(target, res) facts = await connector.extract(ctx, target, res, parsed) return facts or Facts() @pytest.fixture def fixtures() -> Path: return FIXTURES def claims_of(facts: Facts, entity_name: str) -> dict[str, object]: """{property: value} for one entity (from Facts.claims and EntityRef.attributes).""" out: dict[str, object] = {} for e in facts.entities: if e.name == entity_name: out.update(e.attributes) for c in facts.claims: if c.entity.name == entity_name: out[c.property] = c.value return out def entity_names(facts: Facts, entity_type: str) -> set[str]: return {e.name for e in facts.entities if e.entity_type == entity_type}