# retoor import json from devplacepy.database import set_setting from devplacepy.services.nodes import social as social_module from devplacepy.services.nodes.adapters.base import AdapterError from devplacepy.services.nodes.fabric import FabricUnavailable from devplacepy.services.nodes.social import SocialSearch from tests.conftest import run_async HN = json.dumps({"hits": [{"objectID": "1", "title": "HN story", "points": 1}]}).encode() SE = json.dumps({"items": [{"title": "SO question", "link": "https://stackoverflow.com/q/1"}]}).encode() class StubFabric: def __init__(self, error=None): self.error = error self.calls = 0 async def fetch(self, url, **kwargs): self.calls += 1 if self.error: raise self.error raise AssertionError("not expected") def search(monkeypatch, getter, platforms, fabric=None): monkeypatch.setattr(social_module, "direct_get", getter) return run_async( SocialSearch(fabric or StubFabric()).search( "sqlite", caller_kind="user", caller_id="u1", platforms=platforms ) ) def test_hits_are_merged_and_failures_reported(monkeypatch): async def getter(url): if "algolia" in url: return HN if "stackexchange" in url: return SE raise AdapterError("upstream", "HTTP 500") outcome = search(monkeypatch, getter, ["hackernews", "stackexchange", "github"]) assert {item.platform for item in outcome.hits} == {"hackernews", "stackexchange"} assert outcome.unavailable == {"github": "upstream"} def test_unknown_platform_is_dropped(monkeypatch): async def getter(url): return HN outcome = search(monkeypatch, getter, ["hackernews", "x", "instagram"]) assert [item.platform for item in outcome.hits] == ["hackernews"] assert outcome.unavailable == {} def test_reddit_is_off_unless_routing_through_nodes_is_enabled(monkeypatch): async def getter(url): return HN fabric = StubFabric() outcome = search(monkeypatch, getter, ["reddit"], fabric) assert outcome.unavailable == {"reddit": "nodes_not_used"} assert fabric.calls == 0 def test_reddit_reports_the_fabric_reason(monkeypatch): async def getter(url): return HN set_setting("nodes_social_via_nodes", "1") try: outcome = search(monkeypatch, getter, ["reddit"], StubFabric(FabricUnavailable("no_nodes"))) finally: set_setting("nodes_social_via_nodes", "0") assert outcome.unavailable == {"reddit": "no_nodes"} def test_blank_query_and_limit_cap(monkeypatch): async def getter(url): return HN monkeypatch.setattr(social_module, "direct_get", getter) empty = run_async(SocialSearch(StubFabric()).search(" ", caller_kind="user", caller_id="u")) assert empty.hits == [] assert social_module.MAX_LIMIT == 20