# retoor import json from devplacepy.database import get_setting, set_setting from devplacepy.services.nodes import social as social_module HN = json.dumps({"hits": [{"objectID": "9", "title": "A story", "points": 4}]}).encode() def test_guests_get_401(client): assert client.get("/nodes/social/search?q=x").status_code == 401 assert client.post("/nodes/internal/fetch", json={"url": "https://www.reddit.com/"}).status_code == 401 def test_query_is_required(client, member): assert client.get("/nodes/social/search", headers=member["headers"]).status_code == 400 def test_search_returns_hits_and_reasons(client, member, monkeypatch): async def getter(url): return HN monkeypatch.setattr(social_module, "direct_get", getter) body = client.get( "/nodes/social/search?q=sqlite&platforms=hackernews,reddit", headers=member["headers"] ).json() assert body["hits"][0]["platform"] == "hackernews" assert body["unavailable"] == {"reddit": "nodes_not_used"} assert body["platforms"] == ["hackernews", "reddit"] def test_search_has_a_daily_quota(client, member, monkeypatch): async def getter(url): return HN monkeypatch.setattr(social_module, "direct_get", getter) previous = get_setting("nodes_daily_social_user", "300") set_setting("nodes_daily_social_user", "2") try: codes = [ client.get("/nodes/social/search?q=a&platforms=hackernews", headers=member["headers"]).status_code for _ in range(3) ] finally: set_setting("nodes_daily_social_user", previous) assert codes == [200, 200, 429] def test_internal_fetch_refuses_hosts_off_the_allowlist(client, member): response = client.post( "/nodes/internal/fetch", json={"url": "https://example.com/"}, headers=member["headers"] ) assert response.status_code == 403 assert response.json()["error"]["reason"] == "host_not_allowed" def test_internal_fetch_without_donors_is_503(client, member): response = client.post( "/nodes/internal/fetch", json={"url": "https://www.reddit.com/r/python.json", "cache": False}, headers=member["headers"], ) assert response.status_code == 503 assert response.json()["error"]["reason"] in ("no_nodes", "kill_switch")