from __future__ import annotations import importlib preflight = importlib.import_module("scripts.postgres_dev_preflight") def test_run_preflight_rejects_non_postgres_database_url(monkeypatch): monkeypatch.setenv("SCHEMA_MANAGEMENT_MODE", "migrations") results = preflight.run_preflight( database_url="sqlite:///./mvp_cc.db", base_url=None, require_rabbitmq=False, ) assert len(results) == 1 assert results[0].name == "database_url" assert results[0].ok is False def test_run_preflight_requires_migrations_mode(monkeypatch): monkeypatch.setenv("SCHEMA_MANAGEMENT_MODE", "legacy") results = preflight.run_preflight( database_url="postgresql://mvp:mvp@localhost:5432/mvpcc", base_url=None, require_rabbitmq=False, ) assert [item.name for item in results] == ["database_url", "schema_management_mode"] assert results[-1].ok is False def test_run_preflight_passes_with_http_and_rabbitmq(monkeypatch): monkeypatch.setenv("SCHEMA_MANAGEMENT_MODE", "migrations") monkeypatch.setenv("EVENT_BUS_ENABLED", "1") monkeypatch.setenv("EVENT_BUS_URL", "amqp://guest:guest@localhost:5672/") monkeypatch.setattr( preflight, "_check_tcp_endpoint", lambda name, url, default_port: preflight.CheckResult(name, True, f"{default_port} ok"), ) monkeypatch.setattr( preflight, "_check_database_connection", lambda database_url: preflight.CheckResult("database_connection", True, "SELECT 1 succeeded"), ) monkeypatch.setattr( preflight, "_check_schema_migrations", lambda database_url: preflight.CheckResult("schema_migrations", True, "applied=18/18"), ) monkeypatch.setattr( preflight, "_http_preflight_checks", lambda base_url: [ preflight.CheckResult("gateway_health", True, "status=200"), preflight.CheckResult("auth_health", True, "status=200"), ], ) results = preflight.run_preflight( database_url="postgresql://mvp:mvp@localhost:5432/mvpcc", base_url="http://127.0.0.1:8080", require_rabbitmq=False, ) assert all(item.ok for item in results) assert any(item.name == "rabbitmq_tcp" for item in results) assert any(item.name == "gateway_health" for item in results) def test_main_returns_nonzero_when_preflight_fails(monkeypatch, capsys): monkeypatch.setattr( preflight, "run_preflight", lambda **kwargs: [preflight.CheckResult("database_connection", False, "boom")], ) monkeypatch.setattr( preflight.argparse.ArgumentParser, "parse_args", lambda self: type( "Args", (), { "env_file": [], "database_url": "postgresql://mvp:mvp@localhost:5432/mvpcc", "base_url": "", "require_rabbitmq": False, "json": False, }, )(), ) exit_code = preflight.main() output = capsys.readouterr().out assert exit_code == 1 assert "[FAIL] PostgreSQL dev preflight failed" in output def test_http_preflight_uses_admin_login_token_for_read_checks(monkeypatch): monkeypatch.setenv("ALLOW_LEGACY_HEADER_AUTH", "0") monkeypatch.setenv("EVENT_BUS_ENABLED", "0") monkeypatch.setenv("ASTERISK_BRIDGE_ENABLED", "0") monkeypatch.setattr(preflight, "issue_app_token", lambda **kwargs: "ops-token") recorded_headers = {} class FakeResponse: def __init__(self, status_code, payload): self.status_code = status_code self._payload = payload def json(self): return self._payload class FakeClient: def __init__(self, *args, **kwargs): pass def __enter__(self): return self def __exit__(self, exc_type, exc, tb): return False def get(self, path, headers=None): if path == "/health": return FakeResponse(200, {"status": "ok"}) if path == "/registry": return FakeResponse(200, {"services": {name: {} for name in preflight.REQUIRED_PROXY_HEALTH_SERVICES}}) if path.startswith("/proxy/") and path.endswith("/health"): return FakeResponse(200, {"status": "ok"}) if path in { "/proxy/routing/queues", "/proxy/voice/integrations/voice/events?limit=1", "/proxy/whatsapp/integrations/whatsapp/threads", }: recorded_headers[path] = dict(headers or {}) return FakeResponse(200, []) raise AssertionError(f"Unexpected GET path: {path}") def post(self, path, json=None): if path == "/proxy/auth/auth/login": return FakeResponse(200, {"access_token": "login-token"}) raise AssertionError(f"Unexpected POST path: {path}") monkeypatch.setattr(preflight.httpx, "Client", FakeClient) results = preflight._http_preflight_checks("http://127.0.0.1:18080") assert all(item.ok for item in results) assert recorded_headers["/proxy/routing/queues"] == {"Authorization": "Bearer login-token"} assert recorded_headers["/proxy/voice/integrations/voice/events?limit=1"] == {"Authorization": "Bearer login-token"} assert recorded_headers["/proxy/whatsapp/integrations/whatsapp/threads"] == {"Authorization": "Bearer login-token"}