"""Schema contract tests: round-trip, JSON-schema export, query-term logic.""" from __future__ import annotations import json from recon_triage.schema import ( ExploitDBMatch, Host, Port, ReconReport, Service, export_json_schema, ) def test_recon_report_minimal_valid(): r = ReconReport(run_id="t1") assert r.run_id == "t1" assert r.hosts == [] assert "Authorized use only" in r.notice def test_round_trip_json(): r = ReconReport( run_id="t1", hosts=[ Host( hostname="api.example.com", ips=["1.2.3.4"], ports=[ Port( number=443, service=Service( name="http", product="Apache httpd", version="2.4.49", exploitdb_candidates=[ ExploitDBMatch(edb_id="50383", title="x", path="p") ], ), ) ], ) ], ) dumped = r.model_dump_json() restored = ReconReport.model_validate_json(dumped) assert restored.hosts[0].ports[0].service.product == "Apache httpd" assert restored.hosts[0].ports[0].service.exploitdb_candidates[0].verified is False def test_exploitdb_match_always_unverified(): m = ExploitDBMatch(edb_id="1", title="t", path="p") assert m.verified is False assert m.source == "exploit-db" def test_query_term(): assert Service(product="Apache httpd", version="2.4.49").query_term() == "Apache httpd 2.4.49" assert Service(product="nginx").query_term() == "nginx" assert Service(name="http").query_term() is None def test_export_json_schema(tmp_path): p = export_json_schema(tmp_path) assert p.exists() doc = json.loads(p.read_text()) assert "properties" in doc and "hosts" in doc["properties"] assert (tmp_path / "triage_report.schema.json").exists()