"""Offline tests for caching, the query counter, and typed errors. A fake transport stands in for requests.post so nothing touches the network. """ import pytest import bls_client.client as client_mod from bls_client import BLSClient, BLSQuotaError, BLSRequestError from bls_client.cache import FileCache class FakeResp: def __init__(self, payload): self._payload = payload def raise_for_status(self): pass def json(self): return self._payload def _ok(series_id): return { "status": "REQUEST_SUCCEEDED", "Results": {"series": [{"seriesID": series_id, "data": [{"year": "2024", "period": "M01", "value": "1.0"}]}]}, } def test_query_counter_and_cache(tmp_path, monkeypatch): calls = {"n": 0} def fake_post(url, json=None, timeout=None): calls["n"] += 1 return FakeResp(_ok(json["seriesid"][0])) monkeypatch.setattr(client_mod.requests, "post", fake_post) c = BLSClient("key", cache=FileCache(cache_dir=tmp_path, ttl=86400)) c.fetch(["CES0000000001"], 2024, 2024) assert c.queries_used == 1 and calls["n"] == 1 # identical request -> served from cache, no new network call c.fetch(["CES0000000001"], 2024, 2024) assert c.queries_used == 1 and calls["n"] == 1 # different request -> one more call c.fetch(["CES0000000001"], 2023, 2024) assert c.queries_used == 2 and calls["n"] == 2 def test_no_cache_by_default(monkeypatch): def fake_post(url, json=None, timeout=None): return FakeResp(_ok(json["seriesid"][0])) monkeypatch.setattr(client_mod.requests, "post", fake_post) c = BLSClient("key") assert c.cache is None c.fetch(["CES0000000001"], 2024, 2024) c.fetch(["CES0000000001"], 2024, 2024) assert c.queries_used == 2 # no caching -> both hit the (fake) network def test_quota_error(monkeypatch): def fake_post(url, json=None, timeout=None): return FakeResp({ "status": "REQUEST_NOT_PROCESSED", "message": ["Query exceeds the threshold of 500 queries per day."], }) monkeypatch.setattr(client_mod.requests, "post", fake_post) with pytest.raises(BLSQuotaError) as exc: BLSClient("key").fetch(["CES0000000001"], 2024, 2024) assert exc.value.status == "REQUEST_NOT_PROCESSED" def test_request_error(monkeypatch): def fake_post(url, json=None, timeout=None): return FakeResp({"status": "REQUEST_FAILED", "message": ["invalid series"]}) monkeypatch.setattr(client_mod.requests, "post", fake_post) with pytest.raises(BLSRequestError): BLSClient("key").fetch(["BOGUS"], 2024, 2024)