"""Unit tests — Spec 033 stack health probes (expect_status hardening).""" from __future__ import annotations import importlib.util import sys import unittest from pathlib import Path from unittest.mock import MagicMock, patch API_ROOT = Path(__file__).resolve().parent if not (API_ROOT / "app" / "stack_health.py").is_file(): API_ROOT = API_ROOT.parent def _load_stack_health(): path = API_ROOT / "app/stack_health.py" spec = importlib.util.spec_from_file_location("stack_health_033", path) if spec is None or spec.loader is None: raise ImportError(path) mod = importlib.util.module_from_spec(spec) sys.modules["stack_health_033"] = mod spec.loader.exec_module(mod) return mod sh = _load_stack_health() class TestNormalizeExpectStatus(unittest.TestCase): def test_single_int(self): self.assertEqual(sh._normalize_expect_status(200), (200,)) def test_single_element_tuple_with_comma(self): self.assertEqual(sh._normalize_expect_status((200,)), (200,)) def test_multi_status_tuple(self): self.assertEqual(sh._normalize_expect_status((200, 301, 302)), (200, 301, 302)) def test_list_from_yaml_contract(self): self.assertEqual(sh._normalize_expect_status([200, 403]), (200, 403)) def test_invalid_type_raises(self): with self.assertRaises(TypeError): sh._normalize_expect_status("200") # type: ignore[arg-type] class TestProbeHttpExpectStatus(unittest.TestCase): @patch("stack_health_033.httpx.Client") def test_int_expect_status_does_not_crash(self, client_cls): res = MagicMock() res.status_code = 200 client_cls.return_value.__enter__.return_value.get.return_value = res out = sh._probe_http(url="http://example.test/health", expect_status=200) self.assertTrue(out["ok"]) self.assertEqual(out["http_status"], 200) self.assertEqual(out["detail"], "HTTP 200") @patch("stack_health_033.httpx.Client") def test_default_expect_status_tuple(self, client_cls): res = MagicMock() res.status_code = 200 client_cls.return_value.__enter__.return_value.get.return_value = res out = sh._probe_http(url="http://example.test/") self.assertTrue(out["ok"]) @patch("stack_health_033.httpx.Client") def test_wrong_status_marks_check(self, client_cls): res = MagicMock() res.status_code = 503 client_cls.return_value.__enter__.return_value.get.return_value = res out = sh._probe_http(url="http://example.test/", expect_status=(200,)) self.assertFalse(out["ok"]) self.assertEqual(out["status"], "check") if __name__ == "__main__": unittest.main()