# retoor import base64 import io from datetime import datetime, timezone import pytest from PIL import Image from devplacepy.db_client import get_award_usage, get_table, init_db from devplacepy.db_client import recompute_user_award_stats from devplacepy.services.jobs.award_service import AwardService from devplacepy.utils import generate_uid, make_combined_slug from tests.conftest import run_async @pytest.fixture(autouse=True) def _db(local_db, tmp_path, monkeypatch): init_db() monkeypatch.setattr("devplacepy.attachments.ATTACHMENTS_DIR", tmp_path / "attachments") yield def _png_bytes(): buf = io.BytesIO() Image.new("RGBA", (64, 64), (40, 80, 120, 255)).save(buf, format="PNG") return buf.getvalue() class _FakeResponse: def __init__(self, payload, headers=None): self._payload = payload self.headers = headers or {} def raise_for_status(self): return None def json(self): return self._payload class _FakeClient: def __init__(self, *args, **kwargs): self._png = _png_bytes() def __enter__(self): return self def __exit__(self, *args): return False def post(self, url, json=None, headers=None): encoded = base64.b64encode(self._png).decode("ascii") return _FakeResponse( {"data": [{"b64_json": encoded}]}, headers={ "X-Gateway-Cost-USD": "0.001", "X-Gateway-Prompt-Tokens": "10", "X-Gateway-Completion-Tokens": "0", "X-Gateway-Total-Tokens": "10", "X-Gateway-Upstream-Latency-Ms": "100", "X-Gateway-Total-Latency-Ms": "120", }, ) def _seed_pending(giver_uid, receiver_uid, description="Nice job"): uid = generate_uid() slug = make_combined_slug(description, uid) get_table("awards").insert( { "uid": uid, "slug": slug, "description": description, "giver_uid": giver_uid, "receiver_uid": receiver_uid, "attachment_uid_512": "", "attachment_uid_256": "", "attachment_uid_64": "", "generated_at": None, "created_at": datetime.now(timezone.utc).isoformat(), "job_uid": "", "deleted_at": None, "deleted_by": None, } ) return uid, slug def _user(prefix): uid = generate_uid() get_table("users").insert( { "uid": uid, "username": f"{prefix}_{uid[:8]}", "email": f"{uid[:8]}@t.dev", "api_key": generate_uid(), "created_at": datetime.now(timezone.utc).isoformat(), } ) return uid def _job(award_uid, giver_uid, receiver_uid, api_key): return { "uid": generate_uid(), "payload": { "award_uid": award_uid, "giver_uid": giver_uid, "receiver_uid": receiver_uid, "description": "Nice job", "api_key": api_key, }, } def test_process_finalizes_award(monkeypatch): monkeypatch.setattr("devplacepy.services.jobs.award_service.stealth.stealth_sync_client", _FakeClient) giver = _user("giver") receiver = _user("recv") api_key = get_table("users").find_one(uid=giver)["api_key"] award_uid, _ = _seed_pending(giver, receiver) run_async(AwardService().process(_job(award_uid, giver, receiver, api_key))) row = get_table("awards").find_one(uid=award_uid) assert row.get("generated_at") assert row.get("attachment_uid_512") assert row.get("attachment_uid_256") assert row.get("attachment_uid_64") recompute_user_award_stats(receiver) user = get_table("users").find_one(uid=receiver) assert user.get("award_count") == 1 def test_process_is_idempotent(monkeypatch): monkeypatch.setattr("devplacepy.services.jobs.award_service.stealth.stealth_sync_client", _FakeClient) giver = _user("giver2") receiver = _user("recv2") api_key = get_table("users").find_one(uid=giver)["api_key"] award_uid, _ = _seed_pending(giver, receiver) job = _job(award_uid, giver, receiver, api_key) svc = AwardService() run_async(svc.process(job)) first = get_table("awards").find_one(uid=award_uid) run_async(svc.process(job)) second = get_table("awards").find_one(uid=award_uid) assert first["generated_at"] == second["generated_at"] assert first["attachment_uid_512"] == second["attachment_uid_512"] def test_process_skips_soft_deleted_award(monkeypatch): monkeypatch.setattr("devplacepy.services.jobs.award_service.stealth.stealth_sync_client", _FakeClient) giver = _user("giver3") receiver = _user("recv3") api_key = get_table("users").find_one(uid=giver)["api_key"] award_uid, _ = _seed_pending(giver, receiver) get_table("awards").update( {"uid": award_uid, "deleted_at": datetime.now(timezone.utc).isoformat(), "deleted_by": giver}, ["uid"], ) result = run_async(AwardService().process(_job(award_uid, giver, receiver, api_key))) assert result.get("skipped") is True assert not get_table("awards").find_one(uid=award_uid).get("generated_at") def test_award_usage_accumulates_from_gateway_headers(monkeypatch): monkeypatch.setattr("devplacepy.services.jobs.award_service.stealth.stealth_sync_client", _FakeClient) get_table("award_usage").delete() giver = _user("giver4") receiver = _user("recv4") api_key = get_table("users").find_one(uid=giver)["api_key"] award_uid, _ = _seed_pending(giver, receiver) run_async(AwardService().process(_job(award_uid, giver, receiver, api_key))) usage = get_award_usage() assert usage["calls"] >= 1 assert usage["cost_usd"] > 0