Newer
Older
navi-1 / tests / unit / api / test_health.py
"""Health endpoint contract tests (handbook 10-platform/health.md)."""

from unittest.mock import AsyncMock

import pytest
from fastapi.testclient import TestClient

import navi.api.routes.health as health_mod
from navi.config import Settings


@pytest.fixture
def health_client(monkeypatch):
    new_settings = Settings(_env_file=None, navi_persona_file="", hive_url="")
    monkeypatch.setattr(health_mod, "settings", new_settings)
    from navi.main import app

    return TestClient(app)


@pytest.fixture(autouse=True)
def _fresh_embed_cache():
    health_mod._embed_cache["checked_at"] = 0.0
    health_mod._embed_cache["result"] = None
    yield


def test_health_ok_when_all_checks_pass(health_client, monkeypatch):
    monkeypatch.setattr(
        health_mod, "_check_embed",
        AsyncMock(return_value={"ok": True, "backend": "ollama:11434", "error": None}),
    )
    resp = health_client.get("/health")
    assert resp.status_code == 200
    body = resp.json()
    assert body["status"] == "ok"
    assert body["service"] == "navi"
    assert body["checks"]["embed"]["status"] == "ok"
    assert body["checks"]["hive"]["status"] == "ok"


def test_health_degraded_when_embed_fails(health_client, monkeypatch):
    monkeypatch.setattr(
        health_mod, "_check_embed",
        AsyncMock(return_value={"ok": False, "backend": "none", "error": "connection refused"}),
    )
    body = health_client.get("/health").json()
    assert body["status"] == "degraded"
    assert body["checks"]["embed"]["status"] == "degraded"
    assert body["checks"]["embed"]["detail"] == "connection refused"


def test_health_keeps_legacy_embed_payload(health_client, monkeypatch):
    """The pre-contract top-level `embed` dict must survive for existing tooling."""
    monkeypatch.setattr(
        health_mod, "_check_embed",
        AsyncMock(return_value={"ok": True, "backend": "ollama:11434", "error": None}),
    )
    body = health_client.get("/health").json()
    assert body["embed"]["ok"] is True
    assert body["embed"]["backend"] == "ollama:11434"


def test_embed_check_is_cached(health_client, monkeypatch):
    check = AsyncMock(return_value={"ok": True, "backend": "x", "error": None})
    monkeypatch.setattr(health_mod, "_check_embed", check)

    first = health_client.get("/health").json()
    second = health_client.get("/health").json()

    assert check.await_count == 1  # second poll was served from cache
    assert first["checks"]["embed"] == second["checks"]["embed"]
    assert isinstance(first["checks"]["embed"]["ms"], int)