Spaces:
Sleeping
Sleeping
| from pathlib import Path | |
| from backend import modal_api | |
| from voiceledger.parser.rules import parse_transaction as local_parse_transaction | |
| class FakeResponse: | |
| def __init__(self, payload: dict) -> None: | |
| self.payload = payload | |
| def raise_for_status(self) -> None: | |
| return None | |
| def json(self) -> dict: | |
| return self.payload | |
| def test_parse_transaction_uses_local_fallback_when_url_missing(monkeypatch) -> None: | |
| monkeypatch.delenv(modal_api.MODAL_PARSE_URL_ENV, raising=False) | |
| transaction = modal_api.parse_transaction("Amit owes 100", fallback=local_parse_transaction) | |
| assert transaction.transaction_type == "customer_credit" | |
| assert transaction.customer == "Amit" | |
| def test_parse_transaction_uses_modal_response(monkeypatch) -> None: | |
| monkeypatch.setenv(modal_api.MODAL_PARSE_URL_ENV, "https://modal.example/parse") | |
| def fake_post(*args, **kwargs) -> FakeResponse: | |
| return FakeResponse( | |
| { | |
| "transaction": { | |
| "transaction_type": "expense", | |
| "item": "rent", | |
| "quantity": None, | |
| "unit_price": None, | |
| "amount": 300, | |
| "customer": None, | |
| "payment_status": "paid", | |
| "notes": "rent 300", | |
| "confidence": 0.99, | |
| } | |
| } | |
| ) | |
| monkeypatch.setattr(modal_api.requests, "post", fake_post) | |
| transaction = modal_api.parse_transaction("rent 300", fallback=local_parse_transaction) | |
| assert transaction.transaction_type == "expense" | |
| assert transaction.item == "rent" | |
| assert transaction.amount == 300 | |
| def test_parse_transaction_result_reports_modal_source(monkeypatch) -> None: | |
| monkeypatch.setenv(modal_api.MODAL_PARSE_URL_ENV, "https://modal.example/parse") | |
| def fake_post(*args, **kwargs) -> FakeResponse: | |
| return FakeResponse( | |
| { | |
| "transaction": { | |
| "transaction_type": "sale", | |
| "item": "mangoes", | |
| "quantity": 12, | |
| "unit_price": 20, | |
| "amount": 240, | |
| "customer": None, | |
| "payment_status": "paid", | |
| "notes": "Sold 12 mangoes, 20 each", | |
| "confidence": 0.97, | |
| } | |
| } | |
| ) | |
| monkeypatch.setattr(modal_api.requests, "post", fake_post) | |
| result = modal_api.parse_transaction_result("Sold 12 mangoes, 20 each", fallback=local_parse_transaction) | |
| assert result.source == "modal" | |
| assert "NVIDIA Nemotron" in result.message | |
| assert result.fallback_reason is None | |
| assert result.transaction.amount == 240 | |
| def test_parse_transaction_falls_back_when_modal_errors(monkeypatch) -> None: | |
| monkeypatch.setenv(modal_api.MODAL_PARSE_URL_ENV, "https://modal.example/parse") | |
| def fake_post(*args, **kwargs) -> None: | |
| raise RuntimeError("network down") | |
| monkeypatch.setattr(modal_api.requests, "post", fake_post) | |
| transaction = modal_api.parse_transaction("mango 12 x 20", fallback=local_parse_transaction) | |
| assert transaction.transaction_type == "sale" | |
| assert transaction.amount == 240 | |
| def test_parse_transaction_result_reports_fallback_reason(monkeypatch) -> None: | |
| monkeypatch.setenv(modal_api.MODAL_PARSE_URL_ENV, "https://modal.example/parse") | |
| def fake_post(*args, **kwargs) -> None: | |
| raise RuntimeError("network down") | |
| monkeypatch.setattr(modal_api.requests, "post", fake_post) | |
| result = modal_api.parse_transaction_result("mango 12 x 20", fallback=local_parse_transaction) | |
| assert result.source == "local" | |
| assert "after Modal failed" in result.message | |
| assert "network down" in result.fallback_reason | |
| assert result.transaction.amount == 240 | |
| def test_parse_transaction_result_force_local_skips_modal(monkeypatch) -> None: | |
| monkeypatch.setenv(modal_api.MODAL_PARSE_URL_ENV, "https://modal.example/parse") | |
| def fake_post(*args, **kwargs) -> None: | |
| raise AssertionError("Modal should not be called in local-first mode") | |
| monkeypatch.setattr(modal_api.requests, "post", fake_post) | |
| result = modal_api.parse_transaction_result( | |
| "Amit owes 100", | |
| fallback=local_parse_transaction, | |
| force_local=True, | |
| ) | |
| assert result.source == "local" | |
| assert result.transaction.transaction_type == "customer_credit" | |
| assert "local-first mode" in result.fallback_reason | |
| def test_transcribe_audio_uses_modal_response(tmp_path: Path, monkeypatch) -> None: | |
| audio_path = tmp_path / "audio.wav" | |
| audio_path.write_bytes(b"audio") | |
| monkeypatch.setenv(modal_api.MODAL_TRANSCRIBE_URL_ENV, "https://modal.example/transcribe") | |
| def fake_post(*args, **kwargs) -> FakeResponse: | |
| return FakeResponse({"transcript": "Sold 12 mangoes"}) | |
| monkeypatch.setattr(modal_api.requests, "post", fake_post) | |
| transcript = modal_api.transcribe_audio(audio_path, fallback=lambda _: "fallback") | |
| assert transcript == "Sold 12 mangoes" | |
| def test_transcribe_audio_result_reports_modal_source(tmp_path: Path, monkeypatch) -> None: | |
| audio_path = tmp_path / "audio.wav" | |
| audio_path.write_bytes(b"audio") | |
| monkeypatch.setenv(modal_api.MODAL_TRANSCRIBE_URL_ENV, "https://modal.example/transcribe") | |
| def fake_post(*args, **kwargs) -> FakeResponse: | |
| return FakeResponse({"transcript": "Sold 12 mangoes"}) | |
| monkeypatch.setattr(modal_api.requests, "post", fake_post) | |
| result = modal_api.transcribe_audio_result(audio_path, fallback=lambda _: "fallback") | |
| assert result.source == "modal" | |
| assert result.transcript == "Sold 12 mangoes" | |
| assert result.fallback_reason is None | |
| def test_transcribe_audio_result_force_local_skips_modal(tmp_path: Path, monkeypatch) -> None: | |
| audio_path = tmp_path / "audio.wav" | |
| audio_path.write_bytes(b"audio") | |
| monkeypatch.setenv(modal_api.MODAL_TRANSCRIBE_URL_ENV, "https://modal.example/transcribe") | |
| def fake_post(*args, **kwargs) -> None: | |
| raise AssertionError("Modal should not be called in local-first mode") | |
| monkeypatch.setattr(modal_api.requests, "post", fake_post) | |
| result = modal_api.transcribe_audio_result( | |
| audio_path, | |
| fallback=lambda _: "local transcript", | |
| force_local=True, | |
| ) | |
| assert result.source == "local" | |
| assert result.transcript == "local transcript" | |
| assert "local-first mode" in result.fallback_reason | |
| def test_transcribe_audio_accepts_gradio_dict_payload(tmp_path: Path, monkeypatch) -> None: | |
| audio_path = tmp_path / "audio.wav" | |
| audio_path.write_bytes(b"audio") | |
| monkeypatch.setenv(modal_api.MODAL_TRANSCRIBE_URL_ENV, "https://modal.example/transcribe") | |
| def fake_post(*args, **kwargs) -> FakeResponse: | |
| return FakeResponse({"transcript": "Paid 500 for supplies"}) | |
| monkeypatch.setattr(modal_api.requests, "post", fake_post) | |
| transcript = modal_api.transcribe_audio({"path": str(audio_path)}, fallback=lambda _: "fallback") | |
| assert transcript == "Paid 500 for supplies" | |
| def test_transcribe_audio_falls_back_when_url_missing(tmp_path: Path, monkeypatch) -> None: | |
| audio_path = tmp_path / "audio.wav" | |
| audio_path.write_bytes(b"audio") | |
| monkeypatch.delenv(modal_api.MODAL_TRANSCRIBE_URL_ENV, raising=False) | |
| transcript = modal_api.transcribe_audio(audio_path, fallback=lambda _: "fallback transcript") | |
| assert transcript == "fallback transcript" | |
| def test_get_modal_health_reports_version(monkeypatch) -> None: | |
| monkeypatch.setenv(modal_api.MODAL_PARSE_URL_ENV, "https://modal.example/parse") | |
| def fake_get(url: str, *args, **kwargs) -> FakeResponse: | |
| if url.endswith("/health"): | |
| return FakeResponse({"status": "ok"}) | |
| if url.endswith("/version"): | |
| return FakeResponse({"version": "parse-starlette-route-v1"}) | |
| raise AssertionError(f"unexpected url: {url}") | |
| monkeypatch.setattr(modal_api.requests, "get", fake_get) | |
| health = modal_api.get_modal_health() | |
| assert health["status"] == "ok" | |
| assert health["version"] == "parse-starlette-route-v1" | |