generated from coulomb/repo-seed
Add credentialed E2B and Modal extensions, burst routing fallback, fin-hub meter export hook, BYOK docs, and 77 tests.
50 lines
1.8 KiB
Python
50 lines
1.8 KiB
Python
"""fin-hub billing export tests."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from sandboxer.models import ActorType, Consumer, MeterRecord, SandboxState, SandboxStatus
|
|
from sandboxer.payments.billing_export import export_meter_usage
|
|
|
|
|
|
def test_export_skipped_when_url_unset() -> None:
|
|
now = datetime.now(UTC)
|
|
status = SandboxStatus(
|
|
sandbox_id="s1",
|
|
profile_id="profile.e2b-burst",
|
|
extension_id="ext.e2b",
|
|
state=SandboxState.DESTROYED,
|
|
consumer=Consumer(actor=ActorType.ADM, project="sand-boxer"),
|
|
created_at=now,
|
|
updated_at=now,
|
|
)
|
|
meter = MeterRecord(pricing_model="metered", actual_usd=0.5, duration_s=100.0)
|
|
assert export_meter_usage(status, extension_id="ext.e2b", meter=meter) is None
|
|
|
|
|
|
def test_export_posts_when_configured(monkeypatch) -> None:
|
|
monkeypatch.setenv("SANDBOXER_FIN_HUB_URL", "http://fin-hub.test")
|
|
now = datetime.now(UTC)
|
|
status = SandboxStatus(
|
|
sandbox_id="s1",
|
|
profile_id="profile.e2b-burst",
|
|
extension_id="ext.e2b",
|
|
state=SandboxState.DESTROYED,
|
|
consumer=Consumer(actor=ActorType.ADM, project="sand-boxer"),
|
|
created_at=now,
|
|
updated_at=now,
|
|
)
|
|
meter = MeterRecord(pricing_model="metered", actual_usd=0.5, duration_s=100.0)
|
|
|
|
mock_response = MagicMock()
|
|
mock_response.json.return_value = {"ok": True}
|
|
with patch("sandboxer.payments.billing_export.httpx.post", return_value=mock_response) as post:
|
|
result = export_meter_usage(status, extension_id="ext.e2b", meter=meter)
|
|
|
|
assert result == {"ok": True}
|
|
post.assert_called_once()
|
|
payload = post.call_args.kwargs["json"]
|
|
assert payload["sandbox_id"] == "s1"
|
|
assert payload["actual_usd"] == 0.5 |