feat: add offline waterbody source crosswalk

This commit is contained in:
ik
2026-09-20 19:16:46 +07:00
parent d541443a1a
commit f02cb247a3
11 changed files with 311 additions and 14 deletions
+64 -1
View File
@@ -5,7 +5,7 @@ import pytest
from rf4_research import community_cli
from rf4_research.community_cli import enforce_fetch_interval, fetch_site_key, mark_fetch
from rf4_research.community_sources import RF4DBWaterbodyDetail
from rf4_research.community_sources import RF4DBWaterbodyDetail, RF4MapWaterbodyCandidate, RF4StatWaterbodyCandidate
def test_fetch_cooldown_is_persistent_per_source(tmp_path: Path) -> None:
@@ -36,6 +36,7 @@ def test_fetch_site_key_normalizes_common_subdomains() -> None:
assert fetch_site_key("https://cdn.rf4db.com/assets/img.jpg") == "rf4db.com"
assert fetch_site_key("https://oss.rf4db.com/game/fish/pike.webp") == "rf4db.com"
assert fetch_site_key("https://www.rf4db.com/") == "rf4db.com"
assert fetch_site_key("https://en.rf4-stat.ru/locations/") == "rf4-stat.ru"
# Base domain stays the same
assert fetch_site_key("https://rf4db.com/") == "rf4db.com"
assert fetch_site_key("https://gw.rf4map.ru/public/images/fish.webp") == "rf4map.ru"
@@ -72,6 +73,68 @@ def test_reserve_only_does_not_make_http_request(
assert payload == {"reserved": True, "source": "rf4db-waterbodies", "site_key": "rf4db.com"}
def test_rf4map_waterbody_directory_is_a_manual_source(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str],
) -> None:
state_file = tmp_path / "fetch-state.json"
monkeypatch.setattr(community_cli, "fetch_html", lambda _url: "<html></html>")
monkeypatch.setitem(
community_cli.SOURCES,
"rf4map-waterbodies",
("https://rf4map.ru/lakes", lambda _html: [RF4MapWaterbodyCandidate(
source_system="rf4map-waterbodies", source_external_id="fixture",
source_url="https://rf4map.ru/lakes/fixture", name="fixture", fish_species_count=None,
)]),
)
assert community_cli.main([
"rf4map-waterbodies", "--state-file", str(state_file),
]) == 0
assert json.loads(capsys.readouterr().out)[0]["source_external_id"] == "fixture"
def test_rf4stat_location_directory_is_a_manual_source(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str],
) -> None:
state_file = tmp_path / "fetch-state.json"
monkeypatch.setattr(community_cli, "fetch_html", lambda _url: "<html></html>")
monkeypatch.setitem(
community_cli.SOURCES,
"rf4stat-locations",
("https://en.rf4-stat.ru/locations/", lambda _html: [RF4StatWaterbodyCandidate(
source_system="rf4stat-locations", source_external_id="fixture",
source_url="https://en.rf4-stat.ru/locations/location/fixture", name="fixture",
catches_count=None, fish_species_count=None, bait_count=None, spot_count=None,
)]),
)
assert community_cli.main(["rf4stat-locations", "--state-file", str(state_file)]) == 0
assert json.loads(capsys.readouterr().out)[0]["source_external_id"] == "fixture"
def test_saved_html_source_does_not_reserve_or_make_http_request(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str],
) -> None:
state_file = tmp_path / "fetch-state.json"
html_file = tmp_path / "source.html"
html_file.write_text("<html></html>", encoding="utf-8")
monkeypatch.setattr(community_cli, "fetch_html", lambda _url: (_ for _ in ()).throw(AssertionError("offline mode must not fetch")))
monkeypatch.setitem(
community_cli.SOURCES,
"rf4map-waterbodies",
("https://rf4map.ru/lakes", lambda _html: [RF4MapWaterbodyCandidate(
source_system="rf4map-waterbodies", source_external_id="fixture",
source_url="https://rf4map.ru/lakes/fixture", name="fixture", fish_species_count=None,
)]),
)
assert community_cli.main([
"rf4map-waterbodies", "--html", str(html_file), "--state-file", str(state_file),
]) == 0
assert not state_file.exists()
assert json.loads(capsys.readouterr().out)[0]["source_external_id"] == "fixture"
def test_detail_fetch_serializes_single_record(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str],
) -> None: