"""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