forked from retoor/devplacepy
Update
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user